]> git.pld-linux.org Git - packages/autofs.git/blame - autofs-4.1.3-non_block_ping.patch
- up to 4.1.4
[packages/autofs.git] / autofs-4.1.3-non_block_ping.patch
CommitLineData
e3a22658 1diff -Nur autofs-4.1.3.orig/lib/rpc_subs.c autofs-4.1.3/lib/rpc_subs.c
2--- autofs-4.1.3.orig/lib/rpc_subs.c 2004-06-14 21:55:29.000000000 +0800
3+++ autofs-4.1.3/lib/rpc_subs.c 2004-06-14 21:54:35.000000000 +0800
4@@ -1,38 +1,284 @@
5+/* ----------------------------------------------------------------------- *
6+ *
7+ * rpc_subs.c - routines for rpc discovery
8+ *
9+ * Copyright 2004 Ian Kent <raven@themaw.net> - All Rights Reserved
10+ * Copyright 2004 Jeff Moyer <jmoyer@redaht.com> - All Rights Reserved
11+ *
12+ * This program is free software; you can redistribute it and/or modify
13+ * it under the terms of the GNU General Public License as published by
14+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
15+ * USA; either version 2 of the License, or (at your option) any later
16+ * version; incorporated herein by reference.
17+ *
18+ * ----------------------------------------------------------------------- */
19+
20 #include <rpc/rpc.h>
21+#include <rpc/pmap_prot.h>
22 #include <nfs/nfs.h>
23 #include <linux/nfs2.h>
24 #include <linux/nfs3.h>
25 #include <rpc/xdr.h>
26-
27+
28+#include <unistd.h>
29+#include <sys/socket.h>
30+#include <netdb.h>
31+#include <netinet/in.h>
32+#include <sys/fcntl.h>
33+#include <errno.h>
34+
35 #include "automount.h"
36
37+#define PMAP_TOUT_UDP 2
38+#define PMAP_TOUT_TCP 3
39+
40+struct conn_info {
41+ const char *host;
42+ unsigned short port;
43+ unsigned long program;
44+ unsigned long version;
45+ struct protoent *proto;
46+ unsigned int send_sz;
47+ unsigned int recv_sz;
48+ struct timeval timeout;
49+};
50+
51+/*
52+ * Create a UDP RPC client
53+ */
54+static CLIENT* create_udp_client(struct conn_info *info)
55+{
56+ int fd = -1;
57+ CLIENT *client;
58+ struct sockaddr_in addr;
59+ struct hostent *hp;
60+
61+ if (info->proto->p_proto != IPPROTO_UDP)
62+ return NULL;
63+
64+ memset(&addr, 0, sizeof(addr));
65+
66+ hp = gethostbyname(info->host);
67+ if (!hp)
68+ return NULL;
69+
70+ addr.sin_family = AF_INET;
71+ addr.sin_port = htons(info->port);
72+ memcpy(&addr.sin_addr.s_addr, hp->h_addr, hp->h_length);
73+
74+ client = clntudp_bufcreate(&addr,
75+ info->program, info->version,
76+ info->timeout, &fd,
77+ info->send_sz, info->recv_sz);
78+
79+ return client;
80+}
81+
82+/*
83+ * Perform a non-blocking connect on the socket fd.
84+ *
85+ * tout contains the timeout. It will be modified to contain the time
86+ * remaining (i.e. time provided - time elasped).
87+ */
88+static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
89+{
90+ int flags, ret, len;
91+ fd_set wset, rset;
92+
93+ flags = fcntl(fd, F_GETFL, 0);
94+ if (flags < 0)
95+ return -1;
96+
97+ ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
98+ if (ret < 0)
99+ return -1;
100+
101+ /*
102+ * From here on subsequent sys calls could change errno so
103+ * we set ret = -errno to capture it in case we decide to
104+ * use it later.
105+ */
106+ ret = connect(fd, (struct sockaddr *)addr, sizeof(struct sockaddr));
107+ if (ret < 0 && errno != EINPROGRESS) {
108+ ret = -errno;
109+ goto done;
110+ }
111+
112+ if (ret == 0)
113+ goto done;
114+
115+ /* now wait */
116+ FD_ZERO(&rset);
117+ FD_SET(fd, &rset);
118+ wset = rset;
119+
120+ ret = select(fd + 1, &rset, &wset, NULL, tout);
121+ if (ret <= 0) {
122+ if (ret == 0)
123+ ret = -ETIMEDOUT;
124+ else
125+ ret = -errno;
126+ goto done;
127+ }
128+
129+ if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
130+ int stat;
131+
132+ len = sizeof(ret);
133+ stat = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
134+ if (stat < 0) {
135+ ret = -errno;
136+ goto done;
137+ }
138+
139+ /* Oops - something wrong with connect */
140+ if (ret)
141+ ret = -ret;
142+ }
143+
144+done:
145+ fcntl(fd, F_SETFL, flags);
146+ return ret;
147+}
148+
149+/*
150+ * Create a TCP RPC client using non-blocking connect
151+ */
152+static CLIENT* create_tcp_client(struct conn_info *info)
153+{
154+ int fd;
155+ CLIENT *client;
156+ struct sockaddr_in addr;
157+ struct hostent *hp;
158+ int ret;
159+
160+ if (info->proto->p_proto != IPPROTO_TCP)
161+ return NULL;
162+
163+ memset(&addr, 0, sizeof(addr));
164+
165+ hp = gethostbyname(info->host);
166+ if (!hp)
167+ return NULL;
168+
169+ addr.sin_family = AF_INET;
170+ addr.sin_port = htons(info->port);
171+ memcpy(&addr.sin_addr.s_addr, hp->h_addr, hp->h_length);
172+
173+ fd = socket(PF_INET, SOCK_STREAM, info->proto->p_proto);
174+ if (fd < 0)
175+ return NULL;
176+
177+ ret = connect_nb(fd, &addr, &info->timeout);
178+ if (ret < 0)
179+ goto out_close;
180+
181+ client = clnttcp_create(&addr,
182+ info->program, info->version, &fd,
183+ info->send_sz, info->recv_sz);
184+ if (!client)
185+ goto out_close;
186+
187+ return client;
188+
189+out_close:
190+ close(fd);
191+ return NULL;
192+}
193+
194+static unsigned short portmap_getport(struct conn_info *info)
195+{
196+ struct conn_info pmap_info;
197+ unsigned short port = 0;
198+ CLIENT *client;
199+ enum clnt_stat stat;
200+ struct pmap parms;
201+
202+ pmap_info.host = info->host;
203+ pmap_info.port = PMAPPORT;
204+ pmap_info.program = PMAPPROG;
205+ pmap_info.version = PMAPVERS;
206+ pmap_info.proto = info->proto;
207+ pmap_info.send_sz = RPCSMALLMSGSIZE;
208+ pmap_info.recv_sz = RPCSMALLMSGSIZE;
209+ pmap_info.timeout.tv_sec = PMAP_TOUT_UDP;
210+ pmap_info.timeout.tv_usec = 0;
211+
212+ if (info->proto->p_proto == IPPROTO_TCP) {
213+ pmap_info.timeout.tv_sec = PMAP_TOUT_TCP;
214+ client = create_tcp_client(&pmap_info);
215+ } else
216+ client = create_udp_client(&pmap_info);
217+
218+ if (!client)
219+ return 0;
220+
221+ parms.pm_prog = info->program;
222+ parms.pm_vers = info->version;
223+ parms.pm_prot = info->proto->p_proto;
224+ parms.pm_port = 0;
225+
226+ stat = clnt_call(client, PMAPPROC_GETPORT,
227+ (xdrproc_t) xdr_pmap, (caddr_t) &parms,
228+ (xdrproc_t) xdr_u_short, (caddr_t) &port,
229+ pmap_info.timeout);
230+
231+ clnt_destroy(client);
232+
233+ if (stat != RPC_SUCCESS)
234+ return 0;
235+
236+ return port;
237+}
238+
239 static int rpc_ping_proto(const char *host,
240- unsigned long nfs_version, const char *proto,
241+ unsigned long nfs_version,
242+ const char *proto,
243 long seconds, long micros)
244 {
245+ struct conn_info info;
246 CLIENT *client;
247- struct timeval tout;
248 enum clnt_stat stat;
249+ struct protoent *prot;
250+
251+ prot = getprotobyname(proto);
252+ if (!prot)
253+ return 1;
254+
255+ info.host = host;
256+ info.program = NFS_PROGRAM;
257+ info.version = nfs_version;
258+ info.proto = prot;
259+ info.send_sz = 0;
260+ info.recv_sz = 0;
261+ info.timeout.tv_sec = seconds;
262+ info.timeout.tv_usec = micros;
263
264- client = clnt_create(host, NFS_PROGRAM, nfs_version, proto);
265- if (client == NULL) {
266+ info.port = portmap_getport(&info);
267+ if (!info.port)
268 return 0;
269- }
270
271- tout.tv_sec = seconds;
272- tout.tv_usec = micros;
273+ if (prot->p_proto == IPPROTO_UDP) {
274+ info.send_sz = UDPMSGSIZE;
275+ info.recv_sz = UDPMSGSIZE;
276+ client = create_udp_client(&info);
277+ } else
278+ client = create_tcp_client(&info);
279+
280+ if (!client)
281+ return 0;
282
283- clnt_control(client, CLSET_TIMEOUT, (char *)&tout);
284- clnt_control(client, CLSET_RETRY_TIMEOUT, (char *)&tout);
285+ clnt_control(client, CLSET_TIMEOUT, (char *) &info.timeout);
286+ clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) &info.timeout);
287
288 stat = clnt_call(client, NFSPROC_NULL,
289- (xdrproc_t)xdr_void, 0, (xdrproc_t)xdr_void, 0, tout);
290+ (xdrproc_t) xdr_void, 0, (xdrproc_t) xdr_void, 0,
291+ info.timeout);
292
293 clnt_destroy(client);
294
295- if (stat != RPC_SUCCESS) {
296+ if (stat != RPC_SUCCESS)
297 return 0;
298- }
299
300 return 1;
301 }
302@@ -108,10 +354,39 @@
303
304 taken = elapsed(start, end);
305
306- if (result != NULL) {
307+ if (result != NULL)
308 *result = taken;
309- }
310
311 return status;
312 }
313
314+#if 0
315+#include <stdio.h>
316+
317+int main(int argc, char **argv)
318+{
319+ int ret;
320+ double res = 0.0;
321+
322+ ret = rpc_ping("budgie", 10, 0);
323+ printf("ret = %d\n", ret);
324+
325+ res = 0.0;
326+ ret = rpc_time("raven", NFS2_VERSION, RPC_PING_TCP, 10, 0, &res);
327+ printf("v2 tcp ret = %d, res = %f\n", ret, res);
328+
329+ res = 0.0;
330+ ret = rpc_time("raven", NFS3_VERSION, RPC_PING_TCP, 10, 0, &res);
331+ printf("v3 tcp ret = %d, res = %f\n", ret, res);
332+
333+ res = 0.0;
334+ ret = rpc_time("raven", NFS2_VERSION, RPC_PING_UDP, 10, 0, &res);
335+ printf("v2 udp ret = %d, res = %f\n", ret, res);
336+
337+ res = 0.0;
338+ ret = rpc_time("raven", NFS3_VERSION, RPC_PING_UDP, 10, 0, &res);
339+ printf("v3 udp ret = %d, res = %f\n", ret, res);
340+
341+ exit(0);
342+}
343+#endif
This page took 0.092653 seconds and 4 git commands to generate.