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
5 +/* ----------------------------------------------------------------------- *
7 + * rpc_subs.c - routines for rpc discovery
9 + * Copyright 2004 Ian Kent <raven@themaw.net> - All Rights Reserved
10 + * Copyright 2004 Jeff Moyer <jmoyer@redaht.com> - All Rights Reserved
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.
18 + * ----------------------------------------------------------------------- */
21 +#include <rpc/pmap_prot.h>
23 #include <linux/nfs2.h>
24 #include <linux/nfs3.h>
29 +#include <sys/socket.h>
31 +#include <netinet/in.h>
32 +#include <sys/fcntl.h>
35 #include "automount.h"
37 +#define PMAP_TOUT_UDP 2
38 +#define PMAP_TOUT_TCP 3
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;
52 + * Create a UDP RPC client
54 +static CLIENT* create_udp_client(struct conn_info *info)
58 + struct sockaddr_in addr;
61 + if (info->proto->p_proto != IPPROTO_UDP)
64 + memset(&addr, 0, sizeof(addr));
66 + hp = gethostbyname(info->host);
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);
74 + client = clntudp_bufcreate(&addr,
75 + info->program, info->version,
77 + info->send_sz, info->recv_sz);
83 + * Perform a non-blocking connect on the socket fd.
85 + * tout contains the timeout. It will be modified to contain the time
86 + * remaining (i.e. time provided - time elasped).
88 +static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
90 + int flags, ret, len;
93 + flags = fcntl(fd, F_GETFL, 0);
97 + ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
102 + * From here on subsequent sys calls could change errno so
103 + * we set ret = -errno to capture it in case we decide to
106 + ret = connect(fd, (struct sockaddr *)addr, sizeof(struct sockaddr));
107 + if (ret < 0 && errno != EINPROGRESS) {
120 + ret = select(fd + 1, &rset, &wset, NULL, tout);
129 + if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
133 + stat = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
139 + /* Oops - something wrong with connect */
145 + fcntl(fd, F_SETFL, flags);
150 + * Create a TCP RPC client using non-blocking connect
152 +static CLIENT* create_tcp_client(struct conn_info *info)
156 + struct sockaddr_in addr;
157 + struct hostent *hp;
160 + if (info->proto->p_proto != IPPROTO_TCP)
163 + memset(&addr, 0, sizeof(addr));
165 + hp = gethostbyname(info->host);
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);
173 + fd = socket(PF_INET, SOCK_STREAM, info->proto->p_proto);
177 + ret = connect_nb(fd, &addr, &info->timeout);
181 + client = clnttcp_create(&addr,
182 + info->program, info->version, &fd,
183 + info->send_sz, info->recv_sz);
194 +static unsigned short portmap_getport(struct conn_info *info)
196 + struct conn_info pmap_info;
197 + unsigned short port = 0;
199 + enum clnt_stat stat;
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;
212 + if (info->proto->p_proto == IPPROTO_TCP) {
213 + pmap_info.timeout.tv_sec = PMAP_TOUT_TCP;
214 + client = create_tcp_client(&pmap_info);
216 + client = create_udp_client(&pmap_info);
221 + parms.pm_prog = info->program;
222 + parms.pm_vers = info->version;
223 + parms.pm_prot = info->proto->p_proto;
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);
231 + clnt_destroy(client);
233 + if (stat != RPC_SUCCESS)
239 static int rpc_ping_proto(const char *host,
240 - unsigned long nfs_version, const char *proto,
241 + unsigned long nfs_version,
243 long seconds, long micros)
245 + struct conn_info info;
247 - struct timeval tout;
249 + struct protoent *prot;
251 + prot = getprotobyname(proto);
256 + info.program = NFS_PROGRAM;
257 + info.version = nfs_version;
261 + info.timeout.tv_sec = seconds;
262 + info.timeout.tv_usec = micros;
264 - client = clnt_create(host, NFS_PROGRAM, nfs_version, proto);
265 - if (client == NULL) {
266 + info.port = portmap_getport(&info);
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);
278 + client = create_tcp_client(&info);
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);
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,
293 clnt_destroy(client);
295 - if (stat != RPC_SUCCESS) {
296 + if (stat != RPC_SUCCESS)
302 @@ -108,10 +354,39 @@
304 taken = elapsed(start, end);
306 - if (result != NULL) {
307 + if (result != NULL)
317 +int main(int argc, char **argv)
322 + ret = rpc_ping("budgie", 10, 0);
323 + printf("ret = %d\n", ret);
326 + ret = rpc_time("raven", NFS2_VERSION, RPC_PING_TCP, 10, 0, &res);
327 + printf("v2 tcp ret = %d, res = %f\n", ret, res);
330 + ret = rpc_time("raven", NFS3_VERSION, RPC_PING_TCP, 10, 0, &res);
331 + printf("v3 tcp ret = %d, res = %f\n", ret, res);
334 + ret = rpc_time("raven", NFS2_VERSION, RPC_PING_UDP, 10, 0, &res);
335 + printf("v2 udp ret = %d, res = %f\n", ret, res);
338 + ret = rpc_time("raven", NFS3_VERSION, RPC_PING_UDP, 10, 0, &res);
339 + printf("v3 udp ret = %d, res = %f\n", ret, res);