]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/mount/network.c
Merge branch 'master' of git://linux-nfs.org/nfs-utils
[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 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <ctype.h>
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <netdb.h>
35 #include <time.h>
36
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/wait.h>
40 #include <netinet/in.h>
41 #include <rpc/rpc.h>
42 #include <rpc/pmap_prot.h>
43 #include <rpc/pmap_clnt.h>
44
45 #include "xcommon.h"
46 #include "mount.h"
47 #include "nls.h"
48 #include "nfs_mount.h"
49 #include "mount_constants.h"
50 #include "nfsrpc.h"
51 #include "network.h"
52
53 #define PMAP_TIMEOUT    (10)
54 #define CONNECT_TIMEOUT (20)
55 #define MOUNT_TIMEOUT   (30)
56
57 #if SIZEOF_SOCKLEN_T - 0 == 0
58 #define socklen_t unsigned int
59 #endif
60
61 extern int nfs_mount_data_version;
62 extern char *progname;
63 extern int verbose;
64
65 static const char *nfs_ns_pgmtbl[] = {
66         "status",
67         NULL,
68 };
69
70 static const unsigned long nfs_to_mnt[] = {
71         0,
72         0,
73         1,
74         3,
75 };
76
77 static const unsigned long mnt_to_nfs[] = {
78         0,
79         2,
80         2,
81         3,
82 };
83
84 /*
85  * Map an NFS version into the corresponding Mountd version
86  */
87 unsigned long nfsvers_to_mnt(const unsigned long vers)
88 {
89         if (vers <= 3)
90                 return nfs_to_mnt[vers];
91         return 0;
92 }
93
94 /*
95  * Map a Mountd version into the corresponding NFS version
96  */
97 static unsigned long mntvers_to_nfs(const unsigned long vers)
98 {
99         if (vers <= 3)
100                 return mnt_to_nfs[vers];
101         return 0;
102 }
103
104 static const unsigned int probe_udp_only[] = {
105         IPPROTO_UDP,
106         0,
107 };
108
109 static const unsigned int probe_udp_first[] = {
110         IPPROTO_UDP,
111         IPPROTO_TCP,
112         0,
113 };
114
115 static const unsigned int probe_tcp_first[] = {
116         IPPROTO_TCP,
117         IPPROTO_UDP,
118         0,
119 };
120
121 static const unsigned long probe_nfs2_only[] = {
122         2,
123         0,
124 };
125
126 static const unsigned long probe_nfs3_first[] = {
127         3,
128         2,
129         0,
130 };
131
132 static const unsigned long probe_mnt1_first[] = {
133         1,
134         2,
135         0,
136 };
137
138 static const unsigned long probe_mnt3_first[] = {
139         3,
140         1,
141         2,
142         0,
143 };
144
145 static void nfs_set_port(struct sockaddr *sap, const unsigned short port)
146 {
147         switch (sap->sa_family) {
148         case AF_INET:
149                 ((struct sockaddr_in *)sap)->sin_port = htons(port);
150                 break;
151         case AF_INET6:
152                 ((struct sockaddr_in6 *)sap)->sin6_port = htons(port);
153                 break;
154         default:
155                 nfs_error(_("%s: unrecognized address family in %s"),
156                         progname, __func__);
157         }
158 }
159
160 #ifdef HAVE_DECL_AI_ADDRCONFIG
161 /**
162  * nfs_name_to_address - resolve hostname to an IPv4 or IPv6 socket address
163  * @hostname: pointer to C string containing DNS hostname to resolve
164  * @af_hint: hint to restrict resolution to one address family
165  * @sap: pointer to buffer to fill with socket address
166  * @len: IN: size of buffer to fill; OUT: size of socket address
167  *
168  * Returns 1 and places a socket address at @sap if successful;
169  * otherwise zero.
170  */
171 int nfs_name_to_address(const char *hostname,
172                         const sa_family_t af_hint,
173                         struct sockaddr *sap, socklen_t *salen)
174 {
175         struct addrinfo *gai_results;
176         struct addrinfo gai_hint = {
177                 .ai_family      = af_hint,
178                 .ai_flags       = AI_ADDRCONFIG,
179         };
180         socklen_t len = *salen;
181         int error, ret = 0;
182
183         if (af_hint == AF_INET6)
184                 gai_hint.ai_flags |= AI_V4MAPPED|AI_ALL;
185
186         *salen = 0;
187
188         error = getaddrinfo(hostname, NULL, &gai_hint, &gai_results);
189         if (error) {
190                 nfs_error(_("%s: DNS resolution failed for %s: %s"),
191                         progname, hostname, (error == EAI_SYSTEM ?
192                                 strerror(errno) : gai_strerror(error)));
193                 return ret;
194         }
195
196         switch (gai_results->ai_addr->sa_family) {
197         case AF_INET:
198         case AF_INET6:
199                 if (len >= gai_results->ai_addrlen) {
200                         *salen = gai_results->ai_addrlen;
201                         memcpy(sap, gai_results->ai_addr, *salen);
202                         ret = 1;
203                 }
204                 break;
205         default:
206                 /* things are really broken if we get here, so warn */
207                 nfs_error(_("%s: unrecognized DNS resolution results for %s"),
208                                 progname, hostname);
209                 break;
210         }
211
212         freeaddrinfo(gai_results);
213         return ret;
214 }
215 #else   /* HAVE_DECL_AI_ADDRCONFIG */
216 /**
217  * nfs_name_to_address - resolve hostname to an IPv4 socket address
218  * @hostname: pointer to C string containing DNS hostname to resolve
219  * @af_hint: hint to restrict resolution to one address family
220  * @sap: pointer to buffer to fill with socket address
221  * @len: IN: size of buffer to fill; OUT: size of socket address
222  *
223  * Returns 1 and places a socket address at @sap if successful;
224  * otherwise zero.
225  *
226  * Some older getaddrinfo(3) implementations don't support
227  * AI_ADDRCONFIG or AI_V4MAPPED properly.  For those cases, a DNS
228  * resolver based on the traditional gethostbyname(3) is provided.
229  */
230 int nfs_name_to_address(const char *hostname,
231                         const sa_family_t af_hint,
232                         struct sockaddr *sap, socklen_t *salen)
233 {
234         struct sockaddr_in *sin = (struct sockaddr_in *)sap;
235         socklen_t len = *salen;
236         struct hostent *hp;
237
238         *salen = 0;
239
240         if (af_hint != AF_INET) {
241                 nfs_error(_("%s: address family not supported by DNS resolver\n"),
242                                 progname, hostname);
243                 return 0;
244         }
245
246         sin->sin_family = AF_INET;
247         if (inet_aton(hostname, &sin->sin_addr)) {
248                 *salen = sizeof(*sin);
249                 return 1;
250         }
251
252         hp = gethostbyname(hostname);
253         if (hp == NULL) {
254                 nfs_error(_("%s: DNS resolution failed for %s: %s"),
255                                 progname, hostname, hstrerror(h_errno));
256                 return 0;
257         }
258
259         if (hp->h_length > len) {
260                 nfs_error(_("%s: DNS resolution results too long for buffer\n"),
261                                 progname);
262                 return 0;
263         }
264
265         memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
266         *salen = hp->h_length;
267         return 1;
268 }
269 #endif  /* HAVE_DECL_AI_ADDRCONFIG */
270
271 /**
272  * nfs_gethostbyname - resolve a hostname to an IPv4 address
273  * @hostname: pointer to a C string containing a DNS hostname
274  * @sin: returns an IPv4 address 
275  *
276  * Returns 1 if successful, otherwise zero.
277  */
278 int nfs_gethostbyname(const char *hostname, struct sockaddr_in *sin)
279 {
280         socklen_t len = sizeof(*sin);
281
282         return nfs_name_to_address(hostname, AF_INET,
283                                         (struct sockaddr *)sin, &len);
284 }
285
286 /**
287  * nfs_string_to_sockaddr - convert string address to sockaddr
288  * @address:    pointer to presentation format address to convert
289  * @addrlen:    length of presentation address
290  * @sap:        pointer to socket address buffer to fill in
291  * @salen:      IN: length of address buffer
292  *              OUT: length of converted socket address
293  *
294  * Convert a presentation format address string to a socket address.
295  * Similar to nfs_name_to_address(), but the DNS query is squelched,
296  * and won't make any noise if the getaddrinfo() call fails.
297  *
298  * Returns 1 and fills in @sap and @salen if successful; otherwise zero.
299  *
300  * See RFC 4038 section 5.1 or RFC 3513 section 2.2 for more details
301  * on presenting IPv6 addresses as text strings.
302  */
303 int nfs_string_to_sockaddr(const char *address, const size_t addrlen,
304                            struct sockaddr *sap, socklen_t *salen)
305 {
306         struct addrinfo *gai_results;
307         struct addrinfo gai_hint = {
308                 .ai_flags       = AI_NUMERICHOST,
309         };
310         socklen_t len = *salen;
311         int ret = 0;
312
313         *salen = 0;
314
315         if (getaddrinfo(address, NULL, &gai_hint, &gai_results) == 0) {
316                 switch (gai_results->ai_addr->sa_family) {
317                 case AF_INET:
318                 case AF_INET6:
319                         if (len >= gai_results->ai_addrlen) {
320                                 *salen = gai_results->ai_addrlen;
321                                 memcpy(sap, gai_results->ai_addr, *salen);
322                                 ret = 1;
323                         }
324                         break;
325                 }
326                 freeaddrinfo(gai_results);
327         }
328
329         return ret;
330 }
331
332 /**
333  * nfs_present_sockaddr - convert sockaddr to string
334  * @sap: pointer to socket address to convert
335  * @salen: length of socket address
336  * @buf: pointer to buffer to fill in
337  * @buflen: length of buffer
338  *
339  * Convert the passed-in sockaddr-style address to presentation format.
340  * The presentation format address is placed in @buf and is
341  * '\0'-terminated.
342  *
343  * Returns 1 if successful; otherwise zero.
344  *
345  * See RFC 4038 section 5.1 or RFC 3513 section 2.2 for more details
346  * on presenting IPv6 addresses as text strings.
347  */
348 int nfs_present_sockaddr(const struct sockaddr *sap, const socklen_t salen,
349                          char *buf, const size_t buflen)
350 {
351 #ifdef HAVE_GETNAMEINFO
352         int result;
353
354         result = getnameinfo(sap, salen, buf, buflen,
355                                         NULL, 0, NI_NUMERICHOST);
356         if (!result)
357                 return 1;
358
359         nfs_error(_("%s: invalid server address: %s"), progname,
360                         gai_strerror(result));
361         return 0;
362 #else   /* HAVE_GETNAMEINFO */
363         char *addr;
364
365         if (sap->sa_family == AF_INET) {
366                 addr = inet_ntoa(((struct sockaddr_in *)sap)->sin_addr);
367                 if (addr && strlen(addr) < buflen) {
368                         strcpy(buf, addr);
369                         return 1;
370                 }
371         }
372
373         nfs_error(_("%s: invalid server address"), progname);
374         return 0;
375 #endif  /* HAVE_GETNAMEINFO */
376 }
377
378 /*
379  * Attempt to connect a socket, but time out after "timeout" seconds.
380  *
381  * On error return, caller closes the socket.
382  */
383 static int connect_to(int fd, struct sockaddr *addr,
384                         socklen_t addrlen, int timeout)
385 {
386         int ret, saved;
387         fd_set rset, wset;
388         struct timeval tv = {
389                 .tv_sec = timeout,
390         };
391
392         saved = fcntl(fd, F_GETFL, 0);
393         fcntl(fd, F_SETFL, saved | O_NONBLOCK);
394
395         ret = connect(fd, addr, addrlen);
396         if (ret < 0 && errno != EINPROGRESS)
397                 return -1;
398         if (ret == 0)
399                 goto out;
400
401         FD_ZERO(&rset);
402         FD_SET(fd, &rset);
403         wset = rset;
404         ret = select(fd + 1, &rset, &wset, NULL, &tv);
405         if (ret == 0) {
406                 errno = ETIMEDOUT;
407                 return -1;
408         }
409         if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
410                 int error;
411                 socklen_t len = sizeof(error);
412                 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
413                         return -1;
414                 if (error) {
415                         errno = error;
416                         return -1;
417                 }
418         } else
419                 return -1;
420
421 out:
422         fcntl(fd, F_SETFL, saved);
423         return 0;
424 }
425
426 /*
427  * Create a socket that is locally bound to a reserved or non-reserved port.
428  *
429  * The caller should check rpc_createerr to determine the cause of any error.
430  */
431 static int get_socket(struct sockaddr_in *saddr, unsigned int p_prot,
432                         unsigned int timeout, int resvp, int conn)
433 {
434         int so, cc, type;
435         struct sockaddr_in laddr;
436         socklen_t namelen = sizeof(laddr);
437
438         type = (p_prot == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM);
439         if ((so = socket (AF_INET, type, p_prot)) < 0)
440                 goto err_socket;
441
442         laddr.sin_family = AF_INET;
443         laddr.sin_port = 0;
444         laddr.sin_addr.s_addr = htonl(INADDR_ANY);
445         if (resvp) {
446                 if (bindresvport(so, &laddr) < 0)
447                         goto err_bindresvport;
448         } else {
449                 cc = bind(so, (struct sockaddr *)&laddr, namelen);
450                 if (cc < 0)
451                         goto err_bind;
452         }
453         if (type == SOCK_STREAM || (conn && type == SOCK_DGRAM)) {
454                 cc = connect_to(so, (struct sockaddr *)saddr, namelen,
455                                 timeout);
456                 if (cc < 0)
457                         goto err_connect;
458         }
459         return so;
460
461 err_socket:
462         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
463         rpc_createerr.cf_error.re_errno = errno;
464         if (verbose) {
465                 nfs_error(_("%s: Unable to create %s socket: errno %d (%s)\n"),
466                         progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
467                         errno, strerror(errno));
468         }
469         return RPC_ANYSOCK;
470
471 err_bindresvport:
472         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
473         rpc_createerr.cf_error.re_errno = errno;
474         if (verbose) {
475                 nfs_error(_("%s: Unable to bindresvport %s socket: errno %d"
476                                 " (%s)\n"),
477                         progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
478                         errno, strerror(errno));
479         }
480         close(so);
481         return RPC_ANYSOCK;
482
483 err_bind:
484         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
485         rpc_createerr.cf_error.re_errno = errno;
486         if (verbose) {
487                 nfs_error(_("%s: Unable to bind to %s socket: errno %d (%s)\n"),
488                         progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
489                         errno, strerror(errno));
490         }
491         close(so);
492         return RPC_ANYSOCK;
493
494 err_connect:
495         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
496         rpc_createerr.cf_error.re_errno = errno;
497         if (verbose) {
498                 nfs_error(_("%s: Unable to connect to %s:%d, errno %d (%s)\n"),
499                         progname, inet_ntoa(saddr->sin_addr),
500                         ntohs(saddr->sin_port), errno, strerror(errno));
501         }
502         close(so);
503         return RPC_ANYSOCK;
504 }
505
506 static void nfs_pp_debug(const struct sockaddr *sap, const socklen_t salen,
507                          const rpcprog_t program, const rpcvers_t version,
508                          const unsigned short protocol,
509                          const unsigned short port)
510 {
511         char buf[NI_MAXHOST];
512
513         if (!verbose)
514                 return;
515
516         if (nfs_present_sockaddr(sap, salen, buf, sizeof(buf)) == 0) {
517                 buf[0] = '\0';
518                 strcat(buf, "unknown host");
519         }
520
521         fprintf(stderr, _("%s: trying %s prog %ld vers %ld prot %s port %d\n"),
522                         progname, buf, program, version,
523                         (protocol == IPPROTO_UDP ? _("UDP") : _("TCP")),
524                         port);
525 }
526
527 /*
528  * Use the portmapper to discover whether or not the service we want is
529  * available. The lists 'versions' and 'protos' define ordered sequences
530  * of service versions and udp/tcp protocols to probe for.
531  *
532  * Returns 1 if the requested service port is unambiguous and pingable;
533  * @pmap is filled in with the version, port, and transport protocol used
534  * during the successful ping.  Note that if a port is already specified
535  * in @pmap and it matches the rpcbind query result, nfs_probe_port() does
536  * not perform an RPC ping.
537  * 
538  * If an error occurs or the requested service isn't available, zero is
539  * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
540  */
541 static int nfs_probe_port(const struct sockaddr *sap, const socklen_t salen,
542                           struct pmap *pmap, const unsigned long *versions,
543                           const unsigned int *protos)
544 {
545         struct sockaddr_storage address;
546         struct sockaddr *saddr = (struct sockaddr *)&address;
547         const unsigned long prog = pmap->pm_prog, *p_vers;
548         const unsigned int prot = (u_int)pmap->pm_prot, *p_prot;
549         const u_short port = (u_short) pmap->pm_port;
550         unsigned long vers = pmap->pm_vers;
551         unsigned short p_port;
552
553         memcpy(saddr, sap, salen);
554         p_prot = prot ? &prot : protos;
555         p_vers = vers ? &vers : versions;
556         rpc_createerr.cf_stat = 0;
557
558         for (;;) {
559                 p_port = nfs_getport(saddr, salen, prog, *p_vers, *p_prot);
560                 if (p_port) {
561                         if (!port || port == p_port) {
562                                 nfs_set_port(saddr, p_port);
563                                 nfs_pp_debug(saddr, salen, prog, *p_vers,
564                                                 *p_prot, p_port);
565                                 if (nfs_rpc_ping(saddr, salen, prog,
566                                                         *p_vers, *p_prot, NULL))
567                                         goto out_ok;
568                         }
569                 }
570                 if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED &&
571                     rpc_createerr.cf_stat != RPC_TIMEDOUT &&
572                     rpc_createerr.cf_stat != RPC_CANTRECV &&
573                     rpc_createerr.cf_stat != RPC_PROGVERSMISMATCH)
574                         goto out_bad;
575
576                 if (!prot) {
577                         if (*++p_prot)
578                                 continue;
579                         p_prot = protos;
580                 }
581                 if (rpc_createerr.cf_stat == RPC_TIMEDOUT ||
582                     rpc_createerr.cf_stat == RPC_CANTRECV)
583                         goto out_bad;
584
585                 if (vers || !*++p_vers)
586                         break;
587         }
588
589 out_bad:
590         return 0;
591
592 out_ok:
593         if (!vers)
594                 pmap->pm_vers = *p_vers;
595         if (!prot)
596                 pmap->pm_prot = *p_prot;
597         if (!port)
598                 pmap->pm_port = p_port;
599         rpc_createerr.cf_stat = 0;
600         return 1;
601 }
602
603 /*
604  * Probe a server's NFS service to determine which versions and
605  * transport protocols are supported.
606  *
607  * Returns 1 if the requested service port is unambiguous and pingable;
608  * @pmap is filled in with the version, port, and transport protocol used
609  * during the successful ping.  If all three are already specified, simply
610  * return success without an rpcbind query or RPC ping (we may be trying
611  * to mount an NFS service that is not advertised via rpcbind).
612  *
613  * If an error occurs or the requested service isn't available, zero is
614  * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
615  */
616 static int nfs_probe_nfsport(const struct sockaddr *sap, const socklen_t salen,
617                                 struct pmap *pmap)
618 {
619         if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
620                 return 1;
621
622         if (nfs_mount_data_version >= 4)
623                 return nfs_probe_port(sap, salen, pmap,
624                                         probe_nfs3_first, probe_tcp_first);
625         else
626                 return nfs_probe_port(sap, salen, pmap,
627                                         probe_nfs2_only, probe_udp_only);
628 }
629
630 /*
631  * Probe a server's mountd service to determine which versions and
632  * transport protocols are supported.
633  *
634  * Returns 1 if the requested service port is unambiguous and pingable;
635  * @pmap is filled in with the version, port, and transport protocol used
636  * during the successful ping.  If all three are already specified, simply
637  * return success without an rpcbind query or RPC ping (we may be trying
638  * to mount an NFS service that is not advertised via rpcbind).
639  * 
640  * If an error occurs or the requested service isn't available, zero is
641  * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
642  */
643 static int nfs_probe_mntport(const struct sockaddr *sap, const socklen_t salen,
644                                 struct pmap *pmap)
645 {
646         if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
647                 return 1;
648
649         if (nfs_mount_data_version >= 4)
650                 return nfs_probe_port(sap, salen, pmap,
651                                         probe_mnt3_first, probe_udp_first);
652         else
653                 return nfs_probe_port(sap, salen, pmap,
654                                         probe_mnt1_first, probe_udp_only);
655 }
656
657 /*
658  * Probe a server's mountd service to determine which versions and
659  * transport protocols are supported.  Invoked when the protocol
660  * version is already known for both the NFS and mountd service.
661  *
662  * Returns 1 and fills in both @pmap structs if the requested service
663  * ports are unambiguous and pingable.  Otherwise zero is returned;
664  * rpccreateerr.cf_stat is set to reflect the nature of the error.
665  */
666 static int nfs_probe_version_fixed(const struct sockaddr *mnt_saddr,
667                         const socklen_t mnt_salen,
668                         struct pmap *mnt_pmap,
669                         const struct sockaddr *nfs_saddr,
670                         const socklen_t nfs_salen,
671                         struct pmap *nfs_pmap)
672 {
673         if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap))
674                 return 0;
675         return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
676 }
677
678 /**
679  * nfs_probe_bothports - discover the RPC endpoints of mountd and NFS server
680  * @mnt_saddr:  pointer to socket address of mountd server
681  * @mnt_salen:  length of mountd server's address
682  * @mnt_pmap:   IN: partially filled-in mountd RPC service tuple;
683  *              OUT: fully filled-in mountd RPC service tuple
684  * @nfs_saddr:  pointer to socket address of NFS server
685  * @nfs_salen:  length of NFS server's address
686  * @nfs_pmap:   IN: partially filled-in NFS RPC service tuple;
687  *              OUT: fully filled-in NFS RPC service tuple
688  *
689  * Returns 1 and fills in both @pmap structs if the requested service
690  * ports are unambiguous and pingable.  Otherwise zero is returned;
691  * rpccreateerr.cf_stat is set to reflect the nature of the error.
692  */
693 int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
694                         const socklen_t mnt_salen,
695                         struct pmap *mnt_pmap,
696                         const struct sockaddr *nfs_saddr,
697                         const socklen_t nfs_salen,
698                         struct pmap *nfs_pmap)
699 {
700         struct pmap save_nfs, save_mnt;
701         const unsigned long *probe_vers;
702
703         if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
704                 nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
705         else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
706                 mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
707
708         if (nfs_pmap->pm_vers)
709                 return nfs_probe_version_fixed(mnt_saddr, mnt_salen, mnt_pmap,
710                                                nfs_saddr, nfs_salen, nfs_pmap);
711
712         memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
713         memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
714         probe_vers = (nfs_mount_data_version >= 4) ?
715                         probe_mnt3_first : probe_mnt1_first;
716
717         for (; *probe_vers; probe_vers++) {
718                 nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
719                 if (nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap) != 0) {
720                         mnt_pmap->pm_vers = *probe_vers;
721                         if (nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap) != 0)
722                                 return 1;
723                         memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
724                 }
725                 switch (rpc_createerr.cf_stat) {
726                 case RPC_PROGVERSMISMATCH:
727                 case RPC_PROGNOTREGISTERED:
728                         break;
729                 default:
730                         return 0;
731                 }
732                 memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
733         }
734
735         return 0;
736 }
737
738 /**
739  * probe_bothports - discover the RPC endpoints of mountd and NFS server
740  * @mnt_server: pointer to address and pmap argument for mountd results
741  * @nfs_server: pointer to address and pmap argument for NFS server
742  *
743  * This is the legacy API that takes "clnt_addr_t" for both servers,
744  * but supports only AF_INET addresses.
745  *
746  * Returns 1 and fills in the pmap field in both clnt_addr_t structs
747  * if the requested service ports are unambiguous and pingable.
748  * Otherwise zero is returned; rpccreateerr.cf_stat is set to reflect
749  * the nature of the error.
750  */
751 int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
752 {
753         return nfs_probe_bothports((struct sockaddr *)&mnt_server->saddr,
754                                         sizeof(mnt_server->saddr),
755                                         &mnt_server->pmap,
756                                         (struct sockaddr *)&nfs_server->saddr,
757                                         sizeof(nfs_server->saddr),
758                                         &nfs_server->pmap);
759 }
760
761 static int nfs_probe_statd(void)
762 {
763         struct sockaddr_in addr = {
764                 .sin_family             = AF_INET,
765                 .sin_addr.s_addr        = htonl(INADDR_LOOPBACK),
766         };
767         rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl);
768
769         return nfs_getport_ping((struct sockaddr *)&addr, sizeof(addr),
770                                 program, (rpcvers_t)1, IPPROTO_UDP);
771 }
772
773 /**
774  * start_statd - attempt to start rpc.statd
775  *
776  * Returns 1 if statd is running; otherwise zero.
777  */
778 int start_statd(void)
779 {
780 #ifdef START_STATD
781         struct stat stb;
782 #endif
783
784         if (nfs_probe_statd())
785                 return 1;
786
787 #ifdef START_STATD
788         if (stat(START_STATD, &stb) == 0) {
789                 if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
790                         pid_t pid = fork();
791                         switch (pid) {
792                         case 0: /* child */
793                                 execl(START_STATD, START_STATD, NULL);
794                                 exit(1);
795                         case -1: /* error */
796                                 nfs_error(_("fork failed: %s"),
797                                                         strerror(errno));
798                                 break;
799                         default: /* parent */
800                                 waitpid(pid, NULL,0);
801                                 break;
802                         }
803                         if (nfs_probe_statd())
804                                 return 1;
805                 }
806         }
807 #endif
808
809         return 0;
810 }
811
812 /**
813  * nfs_call_umount - ask the server to remove a share from it's rmtab
814  * @mnt_server: address of RPC MNT program server
815  * @argp: directory path of share to "unmount"
816  *
817  * Returns one if the unmount call succeeded; zero if the unmount
818  * failed for any reason.
819  *
820  * Note that a side effect of calling this function is that rpccreateerr
821  * is set.
822  */
823 int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
824 {
825         struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
826         socklen_t salen = sizeof(mnt_server->saddr);
827         struct pmap *pmap = &mnt_server->pmap;
828         CLIENT *clnt;
829         enum clnt_stat res = 0;
830         int msock;
831
832         if (!nfs_probe_mntport(sap, salen, pmap))
833                 return 0;
834         clnt = mnt_openclnt(mnt_server, &msock);
835         if (!clnt)
836                 return 0;
837         res = clnt_call(clnt, MOUNTPROC_UMNT,
838                         (xdrproc_t)xdr_dirpath, (caddr_t)argp,
839                         (xdrproc_t)xdr_void, NULL,
840                         TIMEOUT);
841         mnt_closeclnt(clnt, msock);
842
843         if (res == RPC_SUCCESS)
844                 return 1;
845         return 0;
846 }
847
848 /**
849  * mnt_openclnt - get a handle for a remote mountd service
850  * @mnt_server: address and pmap arguments of mountd service
851  * @msock: returns a file descriptor of the underlying transport socket
852  *
853  * Returns an active handle for the remote's mountd service
854  */
855 CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock)
856 {
857         struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
858         struct pmap *mnt_pmap = &mnt_server->pmap;
859         CLIENT *clnt = NULL;
860
861         mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
862         *msock = get_socket(mnt_saddr, mnt_pmap->pm_prot, MOUNT_TIMEOUT,
863                                 TRUE, FALSE);
864         if (*msock == RPC_ANYSOCK) {
865                 if (rpc_createerr.cf_error.re_errno == EADDRINUSE)
866                         /*
867                          * Probably in-use by a TIME_WAIT connection,
868                          * It is worth waiting a while and trying again.
869                          */
870                         rpc_createerr.cf_stat = RPC_TIMEDOUT;
871                 return NULL;
872         }
873
874         switch (mnt_pmap->pm_prot) {
875         case IPPROTO_UDP:
876                 clnt = clntudp_bufcreate(mnt_saddr,
877                                          mnt_pmap->pm_prog, mnt_pmap->pm_vers,
878                                          RETRY_TIMEOUT, msock,
879                                          MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
880                 break;
881         case IPPROTO_TCP:
882                 clnt = clnttcp_create(mnt_saddr,
883                                       mnt_pmap->pm_prog, mnt_pmap->pm_vers,
884                                       msock,
885                                       MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
886                 break;
887         }
888         if (clnt) {
889                 /* try to mount hostname:dirname */
890                 clnt->cl_auth = authunix_create_default();
891                 return clnt;
892         }
893         return NULL;
894 }
895
896 /**
897  * mnt_closeclnt - terminate a handle for a remote mountd service
898  * @clnt: pointer to an active handle for a remote mountd service
899  * @msock: file descriptor of the underlying transport socket
900  *
901  */
902 void mnt_closeclnt(CLIENT *clnt, int msock)
903 {
904         auth_destroy(clnt->cl_auth);
905         clnt_destroy(clnt);
906         close(msock);
907 }
908
909 /**
910  * clnt_ping - send an RPC ping to the remote RPC service endpoint
911  * @saddr: server's address
912  * @prog: target RPC program number
913  * @vers: target RPC version number
914  * @prot: target RPC protocol
915  * @caddr: filled in with our network address
916  *
917  * Sigh... GETPORT queries don't actually check the version number.
918  * In order to make sure that the server actually supports the service
919  * we're requesting, we open an RPC client, and fire off a NULL
920  * RPC call.
921  *
922  * caddr is the network address that the server will use to call us back.
923  * On multi-homed clients, this address depends on which NIC we use to
924  * route requests to the server.
925  *
926  * Returns one if successful, otherwise zero.
927  */
928 int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
929                 const unsigned long vers, const unsigned int prot,
930                 struct sockaddr_in *caddr)
931 {
932         CLIENT *clnt = NULL;
933         int sock, stat;
934         static char clnt_res;
935         struct sockaddr dissolve;
936
937         rpc_createerr.cf_stat = stat = 0;
938         sock = get_socket(saddr, prot, CONNECT_TIMEOUT, FALSE, TRUE);
939         if (sock == RPC_ANYSOCK) {
940                 if (rpc_createerr.cf_error.re_errno == ETIMEDOUT) {
941                         /*
942                          * TCP timeout. Bubble up the error to see 
943                          * how it should be handled.
944                          */
945                         rpc_createerr.cf_stat = RPC_TIMEDOUT;
946                 }
947                 return 0;
948         }
949
950         if (caddr) {
951                 /* Get the address of our end of this connection */
952                 socklen_t len = sizeof(*caddr);
953                 if (getsockname(sock, caddr, &len) != 0)
954                         caddr->sin_family = 0;
955         }
956
957         switch(prot) {
958         case IPPROTO_UDP:
959                 /* The socket is connected (so we could getsockname successfully),
960                  * but some servers on multi-homed hosts reply from
961                  * the wrong address, so if we stay connected, we lose the reply.
962                  */
963                 dissolve.sa_family = AF_UNSPEC;
964                 connect(sock, &dissolve, sizeof(dissolve));
965
966                 clnt = clntudp_bufcreate(saddr, prog, vers,
967                                          RETRY_TIMEOUT, &sock,
968                                          RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
969                 break;
970         case IPPROTO_TCP:
971                 clnt = clnttcp_create(saddr, prog, vers, &sock,
972                                       RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
973                 break;
974         }
975         if (!clnt) {
976                 close(sock);
977                 return 0;
978         }
979         memset(&clnt_res, 0, sizeof(clnt_res));
980         stat = clnt_call(clnt, NULLPROC,
981                          (xdrproc_t)xdr_void, (caddr_t)NULL,
982                          (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
983                          TIMEOUT);
984         if (stat) {
985                 clnt_geterr(clnt, &rpc_createerr.cf_error);
986                 rpc_createerr.cf_stat = stat;
987         }
988         clnt_destroy(clnt);
989         close(sock);
990
991         if (stat == RPC_SUCCESS)
992                 return 1;
993         else
994                 return 0;
995 }
996
997 /*
998  * Try a getsockname() on a connected datagram socket.
999  *
1000  * Returns 1 and fills in @buf if successful; otherwise, zero.
1001  *
1002  * A connected datagram socket prevents leaving a socket in TIME_WAIT.
1003  * This conserves the ephemeral port number space, helping reduce failed
1004  * socket binds during mount storms.
1005  */
1006 static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
1007                            struct sockaddr *buf, socklen_t *buflen)
1008 {
1009         struct sockaddr_in sin = {
1010                 .sin_family             = AF_INET,
1011                 .sin_addr.s_addr        = htonl(INADDR_ANY),
1012         };
1013         struct sockaddr_in6 sin6 = {
1014                 .sin6_family            = AF_INET6,
1015                 .sin6_addr              = IN6ADDR_ANY_INIT,
1016         };
1017         int sock;
1018
1019         sock = socket(sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
1020         if (sock < 0)
1021                 return 0;
1022
1023         switch (sap->sa_family) {
1024         case AF_INET:
1025                 if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
1026                         close(sock);
1027                         return 0;
1028                 }
1029                 break;
1030         case AF_INET6:
1031                 if (bind(sock, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
1032                         close(sock);
1033                         return 0;
1034                 }
1035                 break;
1036         default:
1037                 errno = EAFNOSUPPORT;
1038                 return 0;
1039         }
1040
1041         if (connect(sock, sap, salen) < 0) {
1042                 close(sock);
1043                 return 0;
1044         }
1045
1046         return !getsockname(sock, buf, buflen);
1047 }
1048
1049 /*
1050  * Try to generate an address that prevents the server from calling us.
1051  *
1052  * Returns 1 and fills in @buf if successful; otherwise, zero.
1053  */
1054 static int nfs_ca_gai(const struct sockaddr *sap, const socklen_t salen,
1055                       struct sockaddr *buf, socklen_t *buflen)
1056 {
1057         struct addrinfo *gai_results;
1058         struct addrinfo gai_hint = {
1059                 .ai_family      = sap->sa_family,
1060                 .ai_flags       = AI_PASSIVE,   /* ANYADDR */
1061         };
1062
1063         if (getaddrinfo(NULL, "", &gai_hint, &gai_results))
1064                 return 0;
1065
1066         *buflen = gai_results->ai_addrlen;
1067         memcpy(buf, gai_results->ai_addr, *buflen);
1068
1069         freeaddrinfo(gai_results);
1070
1071         return 1;
1072 }
1073
1074 /**
1075  * nfs_callback_address - acquire our local network address
1076  * @sap: pointer to address of remote
1077  * @sap_len: length of address
1078  * @buf: pointer to buffer to be filled in with local network address
1079  * @buflen: IN: length of buffer to fill in; OUT: length of filled-in address
1080  *
1081  * Discover a network address that an NFSv4 server can use to call us back.
1082  * On multi-homed clients, this address depends on which NIC we use to
1083  * route requests to the server.
1084  *
1085  * Returns 1 and fills in @buf if an unambiguous local address is
1086  * available; returns 1 and fills in an appropriate ANYADDR address
1087  * if a local address isn't available; otherwise, returns zero.
1088  */
1089 int nfs_callback_address(const struct sockaddr *sap, const socklen_t salen,
1090                          struct sockaddr *buf, socklen_t *buflen)
1091 {
1092         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf;
1093
1094         if (nfs_ca_sockname(sap, salen, buf, buflen) == 0)
1095                 if (nfs_ca_gai(sap, salen, buf, buflen) == 0)
1096                         goto out_failed;
1097
1098         /*
1099          * The server can't use an interface ID that was generated
1100          * here on the client, so always clear sin6_scope_id.
1101          */
1102         if (sin6->sin6_family == AF_INET6)
1103                 sin6->sin6_scope_id = 0;
1104
1105         return 1;
1106
1107 out_failed:
1108         *buflen = 0;
1109         if (verbose)
1110                 nfs_error(_("%s: failed to construct callback address"));
1111         return 0;
1112
1113 }