mount.nfs: Provide comments for public network functions
[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                         goto out_bad;
413
414                 if (!prot) {
415                         if (*++p_prot)
416                                 continue;
417                         p_prot = protos;
418                 }
419                 if (vers == pmap->pm_vers) {
420                         p_vers = versions;
421                         vers = 0;
422                 }
423                 if (vers || !*++p_vers)
424                         break;
425         }
426
427 out_bad:
428         return 0;
429
430 out_ok:
431         if (!vers)
432                 pmap->pm_vers = *p_vers;
433         if (!prot)
434                 pmap->pm_prot = *p_prot;
435         if (!port)
436                 pmap->pm_port = p_port;
437         rpc_createerr.cf_stat = 0;
438         return 1;
439 }
440
441 static int probe_nfsport(clnt_addr_t *nfs_server)
442 {
443         struct pmap *pmap = &nfs_server->pmap;
444
445         if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
446                 return 1;
447
448         if (nfs_mount_data_version >= 4)
449                 return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first);
450         else
451                 return probe_port(nfs_server, probe_nfs2_only, probe_udp_only);
452 }
453
454 static int probe_mntport(clnt_addr_t *mnt_server)
455 {
456         struct pmap *pmap = &mnt_server->pmap;
457
458         if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
459                 return 1;
460
461         if (nfs_mount_data_version >= 4)
462                 return probe_port(mnt_server, probe_mnt3_first, probe_udp_first);
463         else
464                 return probe_port(mnt_server, probe_mnt1_first, probe_udp_only);
465 }
466
467 /**
468  * probe_bothports - discover the RPC endpoints of mountd and NFS server
469  * @mnt_server: pointer to address and pmap argument for mountd results
470  * @nfs_server: pointer to address and pmap argument for NFS server
471  *
472  * Returns 1 if successful, otherwise zero if some error occurred.
473  * Note that the arguments are both input and output arguments.
474  *
475  * A side effect of calling this function is that rpccreateerr is set.
476  */
477 int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
478 {
479         struct pmap *nfs_pmap = &nfs_server->pmap;
480         struct pmap *mnt_pmap = &mnt_server->pmap;
481         struct pmap save_nfs, save_mnt;
482         int res;
483         const unsigned long *probe_vers;
484
485         if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
486                 nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
487         else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
488                 mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
489         if (nfs_pmap->pm_vers)
490                 goto version_fixed;
491
492         memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
493         memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
494         probe_vers = (nfs_mount_data_version >= 4) ?
495                         probe_mnt3_first : probe_mnt1_first;
496
497         for (; *probe_vers; probe_vers++) {
498                 nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
499                 if ((res = probe_nfsport(nfs_server) != 0)) {
500                         mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
501                         if ((res = probe_mntport(mnt_server)) != 0)
502                                 return 1;
503                         memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
504                 }
505                 switch (rpc_createerr.cf_stat) {
506                 case RPC_PROGVERSMISMATCH:
507                 case RPC_PROGNOTREGISTERED:
508                         break;
509                 default:
510                         goto out_bad;
511                 }
512                 memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
513         }
514
515 out_bad:
516         return 0;
517
518 version_fixed:
519         if (!probe_nfsport(nfs_server))
520                 goto out_bad;
521         return probe_mntport(mnt_server);
522 }
523
524 static int probe_statd(void)
525 {
526         struct sockaddr_in addr;
527         unsigned short port;
528
529         memset(&addr, 0, sizeof(addr));
530         addr.sin_family = AF_INET;
531         addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
532         port = getport(&addr, 100024, 1, IPPROTO_UDP);
533
534         if (port == 0)
535                 return 0;
536         addr.sin_port = htons(port);
537
538         if (clnt_ping(&addr, 100024, 1, IPPROTO_UDP, NULL) <= 0)
539                 return 0;
540
541         return 1;
542 }
543
544 /**
545  * start_statd - attempt to start rpc.statd
546  *
547  * Returns 1 if statd is running; otherwise zero.
548  */
549 int start_statd(void)
550 {
551 #ifdef START_STATD
552         struct stat stb;
553 #endif
554
555         if (probe_statd())
556                 return 1;
557
558 #ifdef START_STATD
559         if (stat(START_STATD, &stb) == 0) {
560                 if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
561                         system(START_STATD);
562                         if (probe_statd())
563                                 return 1;
564                 }
565         }
566 #endif
567
568         return 0;
569 }
570
571 /**
572  * nfs_call_umount - ask the server to remove a share from it's rmtab
573  * @mnt_server: address of RPC MNT program server
574  * @argp: directory path of share to "unmount"
575  *
576  * Returns one if the unmount call succeeded; zero if the unmount
577  * failed for any reason.
578  *
579  * Note that a side effect of calling this function is that rpccreateerr
580  * is set.
581  */
582 int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
583 {
584         CLIENT *clnt;
585         enum clnt_stat res = 0;
586         int msock;
587
588         switch (mnt_server->pmap.pm_vers) {
589         case 3:
590         case 2:
591         case 1:
592                 if (!probe_mntport(mnt_server))
593                         return 0;
594                 clnt = mnt_openclnt(mnt_server, &msock);
595                 if (!clnt)
596                         return 0;
597                 res = clnt_call(clnt, MOUNTPROC_UMNT,
598                                 (xdrproc_t)xdr_dirpath, (caddr_t)argp,
599                                 (xdrproc_t)xdr_void, NULL,
600                                 TIMEOUT);
601                 mnt_closeclnt(clnt, msock);
602                 if (res == RPC_SUCCESS)
603                         return 1;
604                 break;
605         default:
606                 res = RPC_SUCCESS;
607                 break;
608         }
609
610         if (res == RPC_SUCCESS)
611                 return 1;
612         return 0;
613 }
614
615 /**
616  * mnt_openclnt - get a handle for a remote mountd service
617  * @mnt_server: address and pmap arguments of mountd service
618  * @msock: returns a file descriptor of the underlying transport socket
619  *
620  * Returns an active handle for the remote's mountd service
621  */
622 CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock)
623 {
624         struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
625         struct pmap *mnt_pmap = &mnt_server->pmap;
626         CLIENT *clnt = NULL;
627
628         mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
629         *msock = get_socket(mnt_saddr, mnt_pmap->pm_prot, MOUNT_TIMEOUT,
630                                 TRUE, FALSE);
631         if (*msock == RPC_ANYSOCK) {
632                 if (rpc_createerr.cf_error.re_errno == EADDRINUSE)
633                         /*
634                          * Probably in-use by a TIME_WAIT connection,
635                          * It is worth waiting a while and trying again.
636                          */
637                         rpc_createerr.cf_stat = RPC_TIMEDOUT;
638                 return NULL;
639         }
640
641         switch (mnt_pmap->pm_prot) {
642         case IPPROTO_UDP:
643                 clnt = clntudp_bufcreate(mnt_saddr,
644                                          mnt_pmap->pm_prog, mnt_pmap->pm_vers,
645                                          RETRY_TIMEOUT, msock,
646                                          MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
647                 break;
648         case IPPROTO_TCP:
649                 clnt = clnttcp_create(mnt_saddr,
650                                       mnt_pmap->pm_prog, mnt_pmap->pm_vers,
651                                       msock,
652                                       MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
653                 break;
654         }
655         if (clnt) {
656                 /* try to mount hostname:dirname */
657                 clnt->cl_auth = authunix_create_default();
658                 return clnt;
659         }
660         return NULL;
661 }
662
663 /**
664  * mnt_closeclnt - terminate a handle for a remote mountd service
665  * @clnt: pointer to an active handle for a remote mountd service
666  * @msock: file descriptor of the underlying transport socket
667  *
668  */
669 void mnt_closeclnt(CLIENT *clnt, int msock)
670 {
671         auth_destroy(clnt->cl_auth);
672         clnt_destroy(clnt);
673         close(msock);
674 }
675
676 /**
677  * clnt_ping - send an RPC ping to the remote RPC service endpoint
678  * @saddr: server's address
679  * @prog: target RPC program number
680  * @vers: target RPC version number
681  * @prot: target RPC protocol
682  * @caddr: filled in with our network address
683  *
684  * Sigh... getport() doesn't actually check the version number.
685  * In order to make sure that the server actually supports the service
686  * we're requesting, we open and RPC client, and fire off a NULL
687  * RPC call.
688  *
689  * caddr is the network address that the server will use to call us back.
690  * On multi-homed clients, this address depends on which NIC we use to
691  * route requests to the server.
692  *
693  * Returns one if successful, otherwise zero.
694  */
695 int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
696                 const unsigned long vers, const unsigned int prot,
697                 struct sockaddr_in *caddr)
698 {
699         CLIENT *clnt = NULL;
700         int sock, stat;
701         static char clnt_res;
702         struct sockaddr dissolve;
703
704         rpc_createerr.cf_stat = stat = 0;
705         sock = get_socket(saddr, prot, CONNECT_TIMEOUT, FALSE, TRUE);
706         if (sock == RPC_ANYSOCK) {
707                 if (rpc_createerr.cf_error.re_errno == ETIMEDOUT) {
708                         /*
709                          * TCP timeout. Bubble up the error to see 
710                          * how it should be handled.
711                          */
712                         rpc_createerr.cf_stat = RPC_TIMEDOUT;
713                 }
714                 return 0;
715         }
716
717         if (caddr) {
718                 /* Get the address of our end of this connection */
719                 socklen_t len = sizeof(*caddr);
720                 if (getsockname(sock, caddr, &len) != 0)
721                         caddr->sin_family = 0;
722         }
723
724         switch(prot) {
725         case IPPROTO_UDP:
726                 /* The socket is connected (so we could getsockname successfully),
727                  * but some servers on multi-homed hosts reply from
728                  * the wrong address, so if we stay connected, we lose the reply.
729                  */
730                 dissolve.sa_family = AF_UNSPEC;
731                 connect(sock, &dissolve, sizeof(dissolve));
732
733                 clnt = clntudp_bufcreate(saddr, prog, vers,
734                                          RETRY_TIMEOUT, &sock,
735                                          RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
736                 break;
737         case IPPROTO_TCP:
738                 clnt = clnttcp_create(saddr, prog, vers, &sock,
739                                       RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
740                 break;
741         }
742         if (!clnt) {
743                 close(sock);
744                 return 0;
745         }
746         memset(&clnt_res, 0, sizeof(clnt_res));
747         stat = clnt_call(clnt, NULLPROC,
748                          (xdrproc_t)xdr_void, (caddr_t)NULL,
749                          (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
750                          TIMEOUT);
751         if (stat) {
752                 clnt_geterr(clnt, &rpc_createerr.cf_error);
753                 rpc_createerr.cf_stat = stat;
754         }
755         clnt_destroy(clnt);
756         close(sock);
757
758         if (stat == RPC_SUCCESS)
759                 return 1;
760         else
761                 return 0;
762 }
763
764 /**
765  * get_client_address - acquire our local network address
766  * @saddr: server's address
767  * @caddr: filled in with our network address
768  *
769  * Discover a network address that the server will use to call us back.
770  * On multi-homed clients, this address depends on which NIC we use to
771  * route requests to the server.
772  *
773  * Use a connected datagram socket so as not to leave a socket in TIME_WAIT.
774  *
775  * Returns one if successful, otherwise zero.
776  */
777 int get_client_address(struct sockaddr_in *saddr, struct sockaddr_in *caddr)
778 {
779         socklen_t len = sizeof(*caddr);
780         int socket, err;
781
782         socket = get_socket(saddr, IPPROTO_UDP, CONNECT_TIMEOUT, FALSE, TRUE);
783         if (socket == RPC_ANYSOCK)
784                 return 0;
785
786         err = getsockname(socket, caddr, &len);
787         close(socket);
788
789         if (err && verbose) {
790                 nfs_error(_("%s: getsockname failed: %s"),
791                                 progname, strerror(errno));
792                 return 0;
793         }
794         return 1;
795 }