]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/mount/network.c
When following a list of mount versions to probe -
[nfs-utils.git] / utils / mount / network.c
1 /*
2  * network.c -- Provide common network functions for NFS mount/umount
3  *
4  * Copyright (C) 2007 Oracle.  All rights reserved.
5  * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public
18  * License along with this program; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 021110-1307, USA.
21  *
22  */
23
24 #include <ctype.h>
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <netdb.h>
31 #include <time.h>
32 #include <rpc/rpc.h>
33 #include <rpc/pmap_prot.h>
34 #include <rpc/pmap_clnt.h>
35 #include <sys/socket.h>
36
37 #include "xcommon.h"
38 #include "mount.h"
39 #include "nls.h"
40 #include "nfs_mount.h"
41 #include "mount_constants.h"
42 #include "network.h"
43
44 #ifdef HAVE_RPCSVC_NFS_PROT_H
45 #include <rpcsvc/nfs_prot.h>
46 #else
47 #include <linux/nfs.h>
48 #define nfsstat nfs_stat
49 #endif
50
51 #ifndef NFS_PORT
52 #define NFS_PORT 2049
53 #endif
54
55 #define PMAP_TIMEOUT    (10)
56 #define CONNECT_TIMEOUT (20)
57 #define MOUNT_TIMEOUT   (30)
58
59 #if SIZEOF_SOCKLEN_T - 0 == 0
60 #define socklen_t unsigned int
61 #endif
62
63 extern int nfs_mount_data_version;
64 extern char *progname;
65 extern int verbose;
66
67 static const unsigned long nfs_to_mnt[] = {
68         0,
69         0,
70         1,
71         3,
72 };
73
74 static const unsigned long mnt_to_nfs[] = {
75         0,
76         2,
77         2,
78         3,
79 };
80
81 /*
82  * Map an NFS version into the corresponding Mountd version
83  */
84 unsigned long nfsvers_to_mnt(const unsigned long vers)
85 {
86         if (vers <= 3)
87                 return nfs_to_mnt[vers];
88         return 0;
89 }
90
91 /*
92  * Map a Mountd version into the corresponding NFS version
93  */
94 static unsigned long mntvers_to_nfs(const unsigned long vers)
95 {
96         if (vers <= 3)
97                 return mnt_to_nfs[vers];
98         return 0;
99 }
100
101 static const unsigned int probe_udp_only[] = {
102         IPPROTO_UDP,
103         0,
104 };
105
106 static const unsigned int probe_udp_first[] = {
107         IPPROTO_UDP,
108         IPPROTO_TCP,
109         0,
110 };
111
112 static const unsigned int probe_tcp_first[] = {
113         IPPROTO_TCP,
114         IPPROTO_UDP,
115         0,
116 };
117
118 static const unsigned long probe_nfs2_only[] = {
119         2,
120         0,
121 };
122
123 static const unsigned long probe_nfs3_first[] = {
124         3,
125         2,
126         0,
127 };
128
129 static const unsigned long probe_mnt1_first[] = {
130         1,
131         2,
132         0,
133 };
134
135 static const unsigned long probe_mnt3_first[] = {
136         3,
137         1,
138         2,
139         0,
140 };
141
142 /**
143  * nfs_gethostbyname - resolve a hostname to an IPv4 address
144  * @hostname: pointer to a C string containing a DNS hostname
145  * @saddr: returns an IPv4 address 
146  *
147  * Returns 1 if successful, otherwise zero.
148  */
149 int nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr)
150 {
151         struct hostent *hp;
152
153         saddr->sin_family = AF_INET;
154         if (!inet_aton(hostname, &saddr->sin_addr)) {
155                 if ((hp = gethostbyname(hostname)) == NULL) {
156                         nfs_error(_("%s: can't get address for %s\n"),
157                                         progname, hostname);
158                         return 0;
159                 } else {
160                         if (hp->h_length > sizeof(*saddr)) {
161                                 nfs_error(_("%s: got bad hp->h_length\n"),
162                                                 progname);
163                                 hp->h_length = sizeof(*saddr);
164                         }
165                         memcpy(&saddr->sin_addr, hp->h_addr, hp->h_length);
166                 }
167         }
168         return 1;
169 }
170
171 /*
172  * Attempt to connect a socket, but time out after "timeout" seconds.
173  *
174  * On error return, caller closes the socket.
175  */
176 static int connect_to(int fd, struct sockaddr *addr,
177                         socklen_t addrlen, int timeout)
178 {
179         int ret, saved;
180         fd_set rset, wset;
181         struct timeval tv = {
182                 .tv_sec = timeout,
183         };
184
185         saved = fcntl(fd, F_GETFL, 0);
186         fcntl(fd, F_SETFL, saved | O_NONBLOCK);
187
188         ret = connect(fd, addr, addrlen);
189         if (ret < 0 && errno != EINPROGRESS)
190                 return -1;
191         if (ret == 0)
192                 goto out;
193
194         FD_ZERO(&rset);
195         FD_SET(fd, &rset);
196         wset = rset;
197         ret = select(fd + 1, &rset, &wset, NULL, &tv);
198         if (ret == 0) {
199                 errno = ETIMEDOUT;
200                 return -1;
201         }
202         if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
203                 int error;
204                 socklen_t len = sizeof(error);
205                 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
206                         return -1;
207                 if (error) {
208                         errno = error;
209                         return -1;
210                 }
211         } else
212                 return -1;
213
214 out:
215         fcntl(fd, F_SETFL, saved);
216         return 0;
217 }
218
219 /*
220  * Create a socket that is locally bound to a reserved or non-reserved port.
221  *
222  * The caller should check rpc_createerr to determine the cause of any error.
223  */
224 static int get_socket(struct sockaddr_in *saddr, unsigned int p_prot,
225                         unsigned int timeout, int resvp, int conn)
226 {
227         int so, cc, type;
228         struct sockaddr_in laddr;
229         socklen_t namelen = sizeof(laddr);
230
231         type = (p_prot == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM);
232         if ((so = socket (AF_INET, type, p_prot)) < 0)
233                 goto err_socket;
234
235         laddr.sin_family = AF_INET;
236         laddr.sin_port = 0;
237         laddr.sin_addr.s_addr = htonl(INADDR_ANY);
238         if (resvp) {
239                 if (bindresvport(so, &laddr) < 0)
240                         goto err_bindresvport;
241         } else {
242                 cc = bind(so, (struct sockaddr *)&laddr, namelen);
243                 if (cc < 0)
244                         goto err_bind;
245         }
246         if (type == SOCK_STREAM || (conn && type == SOCK_DGRAM)) {
247                 cc = connect_to(so, (struct sockaddr *)saddr, namelen,
248                                 timeout);
249                 if (cc < 0)
250                         goto err_connect;
251         }
252         return so;
253
254 err_socket:
255         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
256         rpc_createerr.cf_error.re_errno = errno;
257         if (verbose) {
258                 nfs_error(_("%s: Unable to create %s socket: errno %d (%s)\n"),
259                         progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
260                         errno, strerror(errno));
261         }
262         return RPC_ANYSOCK;
263
264 err_bindresvport:
265         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
266         rpc_createerr.cf_error.re_errno = errno;
267         if (verbose) {
268                 nfs_error(_("%s: Unable to bindresvport %s socket: errno %d"
269                                 " (%s)\n"),
270                         progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
271                         errno, strerror(errno));
272         }
273         close(so);
274         return RPC_ANYSOCK;
275
276 err_bind:
277         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
278         rpc_createerr.cf_error.re_errno = errno;
279         if (verbose) {
280                 nfs_error(_("%s: Unable to bind to %s socket: errno %d (%s)\n"),
281                         progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
282                         errno, strerror(errno));
283         }
284         close(so);
285         return RPC_ANYSOCK;
286
287 err_connect:
288         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
289         rpc_createerr.cf_error.re_errno = errno;
290         if (verbose) {
291                 nfs_error(_("%s: Unable to connect to %s:%d, errno %d (%s)\n"),
292                         progname, inet_ntoa(saddr->sin_addr),
293                         ntohs(saddr->sin_port), errno, strerror(errno));
294         }
295         close(so);
296         return RPC_ANYSOCK;
297 }
298
299 /*
300  * getport() is very similar to pmap_getport() with the exception that
301  * this version tries to use an ephemeral port, since reserved ports are
302  * not needed for GETPORT queries.  This conserves the very limited
303  * reserved port space, which helps reduce failed socket binds
304  * during mount storms.
305  *
306  * A side effect of calling this function is that rpccreateerr is set.
307  */
308 static unsigned short getport(struct sockaddr_in *saddr,
309                                 unsigned long program,
310                                 unsigned long version,
311                                 unsigned int proto)
312 {
313         struct sockaddr_in bind_saddr;
314         unsigned short port = 0;
315         int socket;
316         CLIENT *clnt = NULL;
317         enum clnt_stat stat;
318  
319         bind_saddr = *saddr;
320         bind_saddr.sin_port = htons(PMAPPORT);
321
322         socket = get_socket(&bind_saddr, proto, PMAP_TIMEOUT, FALSE, FALSE);
323         if (socket == RPC_ANYSOCK) {
324                 if (proto == IPPROTO_TCP &&
325                     rpc_createerr.cf_error.re_errno == ETIMEDOUT)
326                         rpc_createerr.cf_stat = RPC_TIMEDOUT;
327                 return 0;
328         }
329
330         switch (proto) {
331         case IPPROTO_UDP:
332                 clnt = clntudp_bufcreate(&bind_saddr,
333                                          PMAPPROG, PMAPVERS,
334                                          RETRY_TIMEOUT, &socket,
335                                          RPCSMALLMSGSIZE,
336                                          RPCSMALLMSGSIZE);
337                 break;
338         case IPPROTO_TCP:
339                 clnt = clnttcp_create(&bind_saddr,
340                                       PMAPPROG, PMAPVERS,
341                                       &socket,
342                                       RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
343                 break;
344         }
345         if (clnt != NULL) {
346                 struct pmap parms = {
347                         .pm_prog        = program,
348                         .pm_vers        = version,
349                         .pm_prot        = proto,
350                 };
351
352                 stat = clnt_call(clnt, PMAPPROC_GETPORT,
353                                  (xdrproc_t)xdr_pmap, (caddr_t)&parms,
354                                  (xdrproc_t)xdr_u_short, (caddr_t)&port,
355                                  TIMEOUT);
356                 if (stat) {
357                         clnt_geterr(clnt, &rpc_createerr.cf_error);
358                         rpc_createerr.cf_stat = stat;
359                 }
360                 clnt_destroy(clnt);
361                 if (stat != RPC_SUCCESS)
362                         port = 0;
363                 else if (port == 0)
364                         rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
365         }
366         close(socket);
367
368         return port;
369 }
370
371 /*
372  * Use the portmapper to discover whether or not the service we want is
373  * available. The lists 'versions' and 'protos' define ordered sequences
374  * of service versions and udp/tcp protocols to probe for.
375  */
376 static int probe_port(clnt_addr_t *server, const unsigned long *versions,
377                         const unsigned int *protos)
378 {
379         struct sockaddr_in *saddr = &server->saddr;
380         struct pmap *pmap = &server->pmap;
381         const unsigned long prog = pmap->pm_prog, *p_vers;
382         const unsigned int prot = (u_int)pmap->pm_prot, *p_prot;
383         const u_short port = (u_short) pmap->pm_port;
384         unsigned long vers = pmap->pm_vers;
385         unsigned short p_port;
386
387         p_prot = prot ? &prot : protos;
388         p_vers = vers ? &vers : versions;
389         rpc_createerr.cf_stat = 0;
390         for (;;) {
391                 p_port = getport(saddr, prog, *p_vers, *p_prot);
392                 if (p_port) {
393                         if (!port || port == p_port) {
394                                 saddr->sin_port = htons(p_port);
395                                 if (verbose) {
396                                         printf(_("%s: trying %s prog %ld vers "
397                                                 "%ld prot %s port %d\n"),
398                                                 progname,
399                                                 inet_ntoa(saddr->sin_addr),
400                                                 prog, *p_vers,
401                                                 *p_prot == IPPROTO_UDP ?
402                                                         _("UDP") : _("TCP"),
403                                                 p_port);
404                                 }
405                                 if (clnt_ping(saddr, prog, *p_vers, *p_prot, NULL))
406                                         goto out_ok;
407                                 if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
408                                         goto out_bad;
409                         }
410                 }
411                 if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED &&
412                     rpc_createerr.cf_stat != RPC_PROGVERSMISMATCH)
413                         goto out_bad;
414
415                 if (!prot) {
416                         if (*++p_prot)
417                                 continue;
418                         p_prot = protos;
419                 }
420                 if (vers || !*++p_vers)
421                         break;
422         }
423
424 out_bad:
425         return 0;
426
427 out_ok:
428         if (!vers)
429                 pmap->pm_vers = *p_vers;
430         if (!prot)
431                 pmap->pm_prot = *p_prot;
432         if (!port)
433                 pmap->pm_port = p_port;
434         rpc_createerr.cf_stat = 0;
435         return 1;
436 }
437
438 static int probe_nfsport(clnt_addr_t *nfs_server)
439 {
440         struct pmap *pmap = &nfs_server->pmap;
441
442         if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
443                 return 1;
444
445         if (nfs_mount_data_version >= 4)
446                 return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first);
447         else
448                 return probe_port(nfs_server, probe_nfs2_only, probe_udp_only);
449 }
450
451 static int probe_mntport(clnt_addr_t *mnt_server)
452 {
453         struct pmap *pmap = &mnt_server->pmap;
454
455         if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
456                 return 1;
457
458         if (nfs_mount_data_version >= 4)
459                 return probe_port(mnt_server, probe_mnt3_first, probe_udp_first);
460         else
461                 return probe_port(mnt_server, probe_mnt1_first, probe_udp_only);
462 }
463
464 /**
465  * probe_bothports - discover the RPC endpoints of mountd and NFS server
466  * @mnt_server: pointer to address and pmap argument for mountd results
467  * @nfs_server: pointer to address and pmap argument for NFS server
468  *
469  * Returns 1 if successful, otherwise zero if some error occurred.
470  * Note that the arguments are both input and output arguments.
471  *
472  * A side effect of calling this function is that rpccreateerr is set.
473  */
474 int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
475 {
476         struct pmap *nfs_pmap = &nfs_server->pmap;
477         struct pmap *mnt_pmap = &mnt_server->pmap;
478         struct pmap save_nfs, save_mnt;
479         int res;
480         const unsigned long *probe_vers;
481
482         if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
483                 nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
484         else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
485                 mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
486         if (nfs_pmap->pm_vers)
487                 goto version_fixed;
488
489         memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
490         memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
491         probe_vers = (nfs_mount_data_version >= 4) ?
492                         probe_mnt3_first : probe_mnt1_first;
493
494         for (; *probe_vers; probe_vers++) {
495                 nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
496                 if ((res = probe_nfsport(nfs_server) != 0)) {
497                         mnt_pmap->pm_vers = *probe_vers;
498                         if ((res = probe_mntport(mnt_server)) != 0)
499                                 return 1;
500                         memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
501                 }
502                 switch (rpc_createerr.cf_stat) {
503                 case RPC_PROGVERSMISMATCH:
504                 case RPC_PROGNOTREGISTERED:
505                         break;
506                 default:
507                         goto out_bad;
508                 }
509                 memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
510         }
511
512 out_bad:
513         return 0;
514
515 version_fixed:
516         if (!probe_nfsport(nfs_server))
517                 goto out_bad;
518         return probe_mntport(mnt_server);
519 }
520
521 static int probe_statd(void)
522 {
523         struct sockaddr_in addr;
524         unsigned short port;
525
526         memset(&addr, 0, sizeof(addr));
527         addr.sin_family = AF_INET;
528         addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
529         port = getport(&addr, 100024, 1, IPPROTO_UDP);
530
531         if (port == 0)
532                 return 0;
533         addr.sin_port = htons(port);
534
535         if (clnt_ping(&addr, 100024, 1, IPPROTO_UDP, NULL) <= 0)
536                 return 0;
537
538         return 1;
539 }
540
541 /**
542  * start_statd - attempt to start rpc.statd
543  *
544  * Returns 1 if statd is running; otherwise zero.
545  */
546 int start_statd(void)
547 {
548 #ifdef START_STATD
549         struct stat stb;
550 #endif
551
552         if (probe_statd())
553                 return 1;
554
555 #ifdef START_STATD
556         if (stat(START_STATD, &stb) == 0) {
557                 if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
558                         system(START_STATD);
559                         if (probe_statd())
560                                 return 1;
561                 }
562         }
563 #endif
564
565         return 0;
566 }
567
568 /**
569  * nfs_call_umount - ask the server to remove a share from it's rmtab
570  * @mnt_server: address of RPC MNT program server
571  * @argp: directory path of share to "unmount"
572  *
573  * Returns one if the unmount call succeeded; zero if the unmount
574  * failed for any reason.
575  *
576  * Note that a side effect of calling this function is that rpccreateerr
577  * is set.
578  */
579 int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
580 {
581         CLIENT *clnt;
582         enum clnt_stat res = 0;
583         int msock;
584
585         if (!probe_mntport(mnt_server))
586                 return 0;
587         clnt = mnt_openclnt(mnt_server, &msock);
588         if (!clnt)
589                 return 0;
590         res = clnt_call(clnt, MOUNTPROC_UMNT,
591                         (xdrproc_t)xdr_dirpath, (caddr_t)argp,
592                         (xdrproc_t)xdr_void, NULL,
593                         TIMEOUT);
594         mnt_closeclnt(clnt, msock);
595
596         if (res == RPC_SUCCESS)
597                 return 1;
598         return 0;
599 }
600
601 /**
602  * mnt_openclnt - get a handle for a remote mountd service
603  * @mnt_server: address and pmap arguments of mountd service
604  * @msock: returns a file descriptor of the underlying transport socket
605  *
606  * Returns an active handle for the remote's mountd service
607  */
608 CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock)
609 {
610         struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
611         struct pmap *mnt_pmap = &mnt_server->pmap;
612         CLIENT *clnt = NULL;
613
614         mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
615         *msock = get_socket(mnt_saddr, mnt_pmap->pm_prot, MOUNT_TIMEOUT,
616                                 TRUE, FALSE);
617         if (*msock == RPC_ANYSOCK) {
618                 if (rpc_createerr.cf_error.re_errno == EADDRINUSE)
619                         /*
620                          * Probably in-use by a TIME_WAIT connection,
621                          * It is worth waiting a while and trying again.
622                          */
623                         rpc_createerr.cf_stat = RPC_TIMEDOUT;
624                 return NULL;
625         }
626
627         switch (mnt_pmap->pm_prot) {
628         case IPPROTO_UDP:
629                 clnt = clntudp_bufcreate(mnt_saddr,
630                                          mnt_pmap->pm_prog, mnt_pmap->pm_vers,
631                                          RETRY_TIMEOUT, msock,
632                                          MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
633                 break;
634         case IPPROTO_TCP:
635                 clnt = clnttcp_create(mnt_saddr,
636                                       mnt_pmap->pm_prog, mnt_pmap->pm_vers,
637                                       msock,
638                                       MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
639                 break;
640         }
641         if (clnt) {
642                 /* try to mount hostname:dirname */
643                 clnt->cl_auth = authunix_create_default();
644                 return clnt;
645         }
646         return NULL;
647 }
648
649 /**
650  * mnt_closeclnt - terminate a handle for a remote mountd service
651  * @clnt: pointer to an active handle for a remote mountd service
652  * @msock: file descriptor of the underlying transport socket
653  *
654  */
655 void mnt_closeclnt(CLIENT *clnt, int msock)
656 {
657         auth_destroy(clnt->cl_auth);
658         clnt_destroy(clnt);
659         close(msock);
660 }
661
662 /**
663  * clnt_ping - send an RPC ping to the remote RPC service endpoint
664  * @saddr: server's address
665  * @prog: target RPC program number
666  * @vers: target RPC version number
667  * @prot: target RPC protocol
668  * @caddr: filled in with our network address
669  *
670  * Sigh... getport() doesn't actually check the version number.
671  * In order to make sure that the server actually supports the service
672  * we're requesting, we open and RPC client, and fire off a NULL
673  * RPC call.
674  *
675  * caddr is the network address that the server will use to call us back.
676  * On multi-homed clients, this address depends on which NIC we use to
677  * route requests to the server.
678  *
679  * Returns one if successful, otherwise zero.
680  */
681 int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
682                 const unsigned long vers, const unsigned int prot,
683                 struct sockaddr_in *caddr)
684 {
685         CLIENT *clnt = NULL;
686         int sock, stat;
687         static char clnt_res;
688         struct sockaddr dissolve;
689
690         rpc_createerr.cf_stat = stat = 0;
691         sock = get_socket(saddr, prot, CONNECT_TIMEOUT, FALSE, TRUE);
692         if (sock == RPC_ANYSOCK) {
693                 if (rpc_createerr.cf_error.re_errno == ETIMEDOUT) {
694                         /*
695                          * TCP timeout. Bubble up the error to see 
696                          * how it should be handled.
697                          */
698                         rpc_createerr.cf_stat = RPC_TIMEDOUT;
699                 }
700                 return 0;
701         }
702
703         if (caddr) {
704                 /* Get the address of our end of this connection */
705                 socklen_t len = sizeof(*caddr);
706                 if (getsockname(sock, caddr, &len) != 0)
707                         caddr->sin_family = 0;
708         }
709
710         switch(prot) {
711         case IPPROTO_UDP:
712                 /* The socket is connected (so we could getsockname successfully),
713                  * but some servers on multi-homed hosts reply from
714                  * the wrong address, so if we stay connected, we lose the reply.
715                  */
716                 dissolve.sa_family = AF_UNSPEC;
717                 connect(sock, &dissolve, sizeof(dissolve));
718
719                 clnt = clntudp_bufcreate(saddr, prog, vers,
720                                          RETRY_TIMEOUT, &sock,
721                                          RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
722                 break;
723         case IPPROTO_TCP:
724                 clnt = clnttcp_create(saddr, prog, vers, &sock,
725                                       RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
726                 break;
727         }
728         if (!clnt) {
729                 close(sock);
730                 return 0;
731         }
732         memset(&clnt_res, 0, sizeof(clnt_res));
733         stat = clnt_call(clnt, NULLPROC,
734                          (xdrproc_t)xdr_void, (caddr_t)NULL,
735                          (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
736                          TIMEOUT);
737         if (stat) {
738                 clnt_geterr(clnt, &rpc_createerr.cf_error);
739                 rpc_createerr.cf_stat = stat;
740         }
741         clnt_destroy(clnt);
742         close(sock);
743
744         if (stat == RPC_SUCCESS)
745                 return 1;
746         else
747                 return 0;
748 }
749
750 /**
751  * get_client_address - acquire our local network address
752  * @saddr: server's address
753  * @caddr: filled in with our network address
754  *
755  * Discover a network address that the server will use to call us back.
756  * On multi-homed clients, this address depends on which NIC we use to
757  * route requests to the server.
758  *
759  * Use a connected datagram socket so as not to leave a socket in TIME_WAIT.
760  *
761  * Returns one if successful, otherwise zero.
762  */
763 int get_client_address(struct sockaddr_in *saddr, struct sockaddr_in *caddr)
764 {
765         socklen_t len = sizeof(*caddr);
766         int socket, err;
767
768         socket = get_socket(saddr, IPPROTO_UDP, CONNECT_TIMEOUT, FALSE, TRUE);
769         if (socket == RPC_ANYSOCK)
770                 return 0;
771
772         err = getsockname(socket, caddr, &len);
773         close(socket);
774
775         if (err && verbose) {
776                 nfs_error(_("%s: getsockname failed: %s"),
777                                 progname, strerror(errno));
778                 return 0;
779         }
780         return 1;
781 }