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