]> git.pld-linux.org Git - packages/autofs.git/blob - autofs-4.1.3-non_block_ping.patch
- up to 4.1.4
[packages/autofs.git] / autofs-4.1.3-non_block_ping.patch
1 diff -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.094348 seconds and 3 git commands to generate.