]> git.decadent.org.uk Git - nfs-utils.git/blob - support/nfs/getport.c
Merge branch 'sid'
[nfs-utils.git] / support / nfs / getport.c
1 /*
2  * Provide a variety of APIs that query an rpcbind daemon to
3  * discover RPC service ports and allowed protocol version
4  * numbers.
5  *
6  * Copyright (C) 2008 Oracle Corporation.  All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the
20  * Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <sys/types.h>
30 #include <sys/time.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <errno.h>
34
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <netdb.h>
38 #include <arpa/inet.h>
39
40 #include <rpc/rpc.h>
41 #include <rpc/pmap_prot.h>
42
43 #ifdef HAVE_LIBTIRPC
44 #include <netconfig.h>
45 #include <rpc/rpcb_prot.h>
46 #endif
47
48 #include "sockaddr.h"
49 #include "nfsrpc.h"
50
51 /*
52  * Try a local socket first to access the local rpcbind daemon
53  *
54  * Rpcbind's local socket service does not seem to be working.
55  * Disable this logic for now.
56  */
57 #ifdef HAVE_LIBTIRPC
58 #undef NFS_GP_LOCAL
59 #else   /* !HAVE_LIBTIRPC */
60 #undef NFS_GP_LOCAL
61 #endif  /* !HAVE_LIBTIRPC */
62
63 #ifdef HAVE_LIBTIRPC
64 static const rpcvers_t default_rpcb_version = RPCBVERS_4;
65 #else   /* !HAVE_LIBTIRPC */
66 static const rpcvers_t default_rpcb_version = PMAPVERS;
67 #endif  /* !HAVE_LIBTIRPC */
68
69 /*
70  * Historical: Map TCP connect timeouts to timeout
71  * error code used by UDP.
72  */
73 static void
74 nfs_gp_map_tcp_errorcodes(const unsigned short protocol)
75 {
76         if (protocol != IPPROTO_TCP)
77                 return;
78
79         switch (rpc_createerr.cf_error.re_errno) {
80         case ETIMEDOUT:
81                 rpc_createerr.cf_stat = RPC_TIMEDOUT;
82                 break;
83         case ECONNREFUSED:
84                 rpc_createerr.cf_stat = RPC_CANTRECV;
85                 break;
86         }
87 }
88
89 /*
90  * There's no easy way to tell how the local system's networking
91  * and rpcbind is configured (ie. whether we want to use IPv6 or
92  * IPv4 loopback to contact RPC services on the local host).  We
93  * punt and simply try to look up "localhost".
94  *
95  * Returns TRUE on success.
96  */
97 static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
98 {
99         struct addrinfo *gai_results;
100         int ret = 0;
101
102         if (getaddrinfo("localhost", NULL, NULL, &gai_results))
103                 return 0;
104
105         if (*salen >= gai_results->ai_addrlen) {
106                 memcpy(sap, gai_results->ai_addr,
107                                 gai_results->ai_addrlen);
108                 *salen = gai_results->ai_addrlen;
109                 ret = 1;
110         }
111
112         freeaddrinfo(gai_results);
113         return ret;
114 }
115
116 /*
117  * Look up a network service in /etc/services and return the
118  * network-order port number of that service.
119  */
120 static in_port_t nfs_gp_getservbyname(const char *service,
121                                       const unsigned short protocol)
122 {
123         const struct addrinfo gai_hint = {
124                 .ai_family      = AF_INET,
125                 .ai_protocol    = protocol,
126                 .ai_flags       = AI_PASSIVE,
127         };
128         struct addrinfo *gai_results;
129         const struct sockaddr_in *sin;
130         in_port_t port;
131
132         if (getaddrinfo(NULL, service, &gai_hint, &gai_results) != 0)
133                 return 0;
134
135         sin = (const struct sockaddr_in *)gai_results->ai_addr;
136         port = sin->sin_port;
137         
138         freeaddrinfo(gai_results);
139         return port;
140 }
141
142 /*
143  * Discover the port number that should be used to contact an
144  * rpcbind service.  This will detect if the port has a local
145  * value that may have been set in /etc/services.
146  *
147  * Returns network byte-order port number of rpcbind service
148  * on this system.
149  */
150 static in_port_t nfs_gp_get_rpcb_port(const unsigned short protocol)
151 {
152         static const char *rpcb_netnametbl[] = {
153                 "rpcbind",
154                 "portmapper",
155                 "sunrpc",
156                 NULL,
157         };
158         unsigned int i;
159
160         for (i = 0; rpcb_netnametbl[i] != NULL; i++) {
161                 in_port_t port;
162
163                 port = nfs_gp_getservbyname(rpcb_netnametbl[i], protocol);
164                 if (port != 0)
165                         return port;
166         }
167
168         return (in_port_t)htons((uint16_t)PMAPPORT);
169 }
170
171 /*
172  * Set up an RPC client for communicating with an rpcbind daemon at
173  * @sap over @transport with protocol version @version.
174  *
175  * Returns a pointer to a prepared RPC client if successful, and
176  * @timeout is initialized; caller must destroy a non-NULL returned RPC
177  * client.  Otherwise returns NULL, and rpc_createerr.cf_stat is set to
178  * reflect the error.
179  */
180 static CLIENT *nfs_gp_get_rpcbclient(struct sockaddr *sap,
181                                      const socklen_t salen,
182                                      const unsigned short transport,
183                                      const rpcvers_t version,
184                                      struct timeval *timeout)
185 {
186         static const char *rpcb_pgmtbl[] = {
187                 "rpcbind",
188                 "portmap",
189                 "portmapper",
190                 "sunrpc",
191                 NULL,
192         };
193         rpcprog_t rpcb_prog = nfs_getrpcbyname(RPCBPROG, rpcb_pgmtbl);
194         CLIENT *clnt;
195
196         nfs_set_port(sap, ntohs(nfs_gp_get_rpcb_port(transport)));
197         clnt = nfs_get_rpcclient(sap, salen, transport, rpcb_prog,
198                                                         version, timeout);
199         nfs_gp_map_tcp_errorcodes(transport);
200         return clnt;
201 }
202
203 /**
204  * nfs_get_proto - Convert a netid to an address family and protocol number
205  * @netid: C string containing a netid
206  * @family: OUT: address family
207  * @protocol: OUT: protocol number
208  *
209  * Returns 1 and fills in @protocol if the netid was recognized;
210  * otherwise zero is returned.
211  */
212 #ifdef HAVE_LIBTIRPC
213 int
214 nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol)
215 {
216         struct netconfig *nconf;
217         struct protoent *proto;
218
219         /*
220          * IANA does not define a protocol number for rdma netids,
221          * since "rdma" is not an IP protocol.
222          */
223         if (strcmp(netid, "rdma") == 0) {
224                 *family = AF_INET;
225                 *protocol = NFSPROTO_RDMA;
226                 return 1;
227         }
228         if (strcmp(netid, "rdma6") == 0) {
229                 *family = AF_INET6;
230                 *protocol = NFSPROTO_RDMA;
231                 return 1;
232         }
233
234         nconf = getnetconfigent(netid);
235         if (nconf == NULL)
236                 return 0;
237
238         proto = getprotobyname(nconf->nc_proto);
239         if (proto == NULL) {
240                 freenetconfigent(nconf);
241                 return 0;
242         }
243
244         *family = AF_UNSPEC;
245         if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
246                 *family = AF_INET;
247         if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
248                 *family = AF_INET6;
249         freenetconfigent(nconf);
250
251         *protocol = (unsigned long)proto->p_proto;
252         return 1;
253 }
254 #else   /* !HAVE_LIBTIRPC */
255 int
256 nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol)
257 {
258         struct protoent *proto;
259
260         /*
261          * IANA does not define a protocol number for rdma netids,
262          * since "rdma" is not an IP protocol.
263          */
264         if (strcmp(netid, "rdma") == 0) {
265                 *family = AF_INET;
266                 *protocol = NFSPROTO_RDMA;
267                 return 1;
268         }
269
270         proto = getprotobyname(netid);
271         if (proto == NULL)
272                 return 0;
273
274         *family = AF_INET;
275         *protocol = (unsigned long)proto->p_proto;
276         return 1;
277 }
278 #endif /* !HAVE_LIBTIRPC */
279
280 /**
281  * nfs_get_netid - Convert a protocol family and protocol name to a netid
282  * @family: protocol family
283  * @protocol: protocol number
284  *
285  * One of the arguments passed when querying remote rpcbind services
286  * via rpcbind v3 or v4 is a netid string.  This replaces the pm_prot
287  * field used in legacy PMAP_GETPORT calls.
288  *
289  * RFC 1833 says netids are not standard but rather defined on the local
290  * host.  There are, however, standard definitions for nc_protofmly and
291  * nc_proto that can be used to derive a netid string on the local host,
292  * based on the contents of /etc/netconfig.
293  *
294  * Walk through the local netconfig database and grab the netid of the
295  * first entry that matches @family and @protocol and whose netid string
296  * fits in the provided buffer.
297  *
298  * Returns a '\0'-terminated string if successful.  Caller must
299  * free the returned string.  Otherwise NULL is returned, and
300  * rpc_createerr.cf_stat is set to reflect the error.
301  */
302 #ifdef HAVE_LIBTIRPC
303 char *nfs_get_netid(const sa_family_t family, const unsigned long protocol)
304 {
305         char *nc_protofmly, *nc_proto, *nc_netid;
306         struct netconfig *nconf;
307         struct protoent *proto;
308         void *handle;
309
310         switch (family) {
311         case AF_LOCAL:
312         case AF_INET:
313                 nc_protofmly = NC_INET;
314                 break;
315         case AF_INET6:
316                 nc_protofmly = NC_INET6;
317                 break;
318         default:
319                 goto out;
320         }
321
322         proto = getprotobynumber(protocol);
323         if (proto == NULL)
324                 goto out;
325         nc_proto = proto->p_name;
326
327         handle = setnetconfig();
328         while ((nconf = getnetconfig(handle)) != NULL) {
329
330                 if (nconf->nc_protofmly != NULL &&
331                     strcmp(nconf->nc_protofmly, nc_protofmly) != 0)
332                         continue;
333                 if (nconf->nc_proto != NULL &&
334                     strcmp(nconf->nc_proto, nc_proto) != 0)
335                         continue;
336
337                 nc_netid = strdup(nconf->nc_netid);
338                 endnetconfig(handle);
339
340                 if (nc_netid == NULL)
341                         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
342                 return nc_netid;
343         }
344         endnetconfig(handle);
345
346 out:
347         rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
348         return NULL;
349 }
350 #else   /* !HAVE_LIBTIRPC */
351 char *nfs_get_netid(const sa_family_t family, const unsigned long protocol)
352 {
353         struct protoent *proto;
354         char *netid;
355
356         if (family != AF_INET)
357                 goto out;
358         proto = getprotobynumber((int)protocol);
359         if (proto == NULL)
360                 goto out;
361
362         netid = strdup(proto->p_name);
363         if (netid == NULL)
364                 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
365         return netid;
366
367 out:
368         rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
369         return NULL;
370 }
371 #endif  /* !HAVE_LIBTIRPC */
372
373 /*
374  * Extract a port number from a universal address, and terminate the
375  * string in @addrstr just after the address part.
376  *
377  * Returns -1 if unsuccesful; otherwise a decoded port number (possibly 0)
378  * is returned.
379  */
380 static int nfs_gp_universal_porthelper(char *addrstr)
381 {
382         char *p, *endptr;
383         unsigned long portlo, porthi;
384         int port = -1;
385
386         p = strrchr(addrstr, '.');
387         if (p == NULL)
388                 goto out;
389         portlo = strtoul(p + 1, &endptr, 10);
390         if (*endptr != '\0' || portlo > 255)
391                 goto out;
392         *p = '\0';
393
394         p = strrchr(addrstr, '.');
395         if (p == NULL)
396                 goto out;
397         porthi = strtoul(p + 1, &endptr, 10);
398         if (*endptr != '\0' || porthi > 255)
399                 goto out;
400         *p = '\0';
401         port = (porthi << 8) | portlo;
402
403 out:
404         return port;
405 }
406
407 /**
408  * nfs_universal2port - extract port number from a "universal address"
409  * @uaddr: '\0'-terminated C string containing a universal address
410  *
411  * Universal addresses (defined in RFC 1833) are used when calling an
412  * rpcbind daemon via protocol versions 3 or 4..
413  *
414  * Returns -1 if unsuccesful; otherwise a decoded port number (possibly 0)
415  * is returned.
416  */
417 int nfs_universal2port(const char *uaddr)
418 {
419         char *addrstr;
420         int port = -1;
421
422         addrstr = strdup(uaddr);
423         if (addrstr != NULL) {
424                 port = nfs_gp_universal_porthelper(addrstr);
425                 free(addrstr);
426         }
427         return port;
428 }
429
430 /**
431  * nfs_sockaddr2universal - convert a sockaddr to a "universal address"
432  * @sap: pointer to a socket address
433  *
434  * Universal addresses (defined in RFC 1833) are used when calling an
435  * rpcbind daemon via protocol versions 3 or 4..
436  *
437  * Returns a '\0'-terminated string if successful; caller must free
438  * the returned string.  Otherwise NULL is returned and
439  * rpc_createerr.cf_stat is set to reflect the error.
440  *
441  * inet_ntop(3) is used here, since getnameinfo(3) is not available
442  * in some earlier glibc releases, and we don't require support for
443  * scope IDs for universal addresses.
444  */
445 char *nfs_sockaddr2universal(const struct sockaddr *sap)
446 {
447         const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
448         const struct sockaddr_un *sun = (const struct sockaddr_un *)sap;
449         const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
450         char buf[INET6_ADDRSTRLEN + 8 /* for port information */];
451         uint16_t port;
452         size_t count;
453         char *result;
454         int len;
455
456         switch (sap->sa_family) {
457         case AF_LOCAL:
458                 return strndup(sun->sun_path, sizeof(sun->sun_path));
459         case AF_INET:
460                 if (inet_ntop(AF_INET, (const void *)&sin->sin_addr.s_addr,
461                                         buf, (socklen_t)sizeof(buf)) == NULL)
462                         goto out_err;
463                 port = ntohs(sin->sin_port);
464                 break;
465         case AF_INET6:
466                 if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
467                                         buf, (socklen_t)sizeof(buf)) == NULL)
468                         goto out_err;
469                 port = ntohs(sin6->sin6_port);
470                 break;
471         default:
472                 goto out_err;
473         }
474
475         count = sizeof(buf) - strlen(buf);
476         len = snprintf(buf + strlen(buf), count, ".%u.%u",
477                         (unsigned)(port >> 8), (unsigned)(port & 0xff));
478         /* before glibc 2.0.6, snprintf(3) could return -1 */
479         if (len < 0 || (size_t)len > count)
480                 goto out_err;
481
482         result = strdup(buf);
483         if (result != NULL)
484                 return result;
485
486 out_err:
487         rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
488         return NULL;
489 }
490
491 /*
492  * Send a NULL request to the indicated RPC service.
493  *
494  * Returns 1 if the service responded; otherwise 0;
495  */
496 static int nfs_gp_ping(CLIENT *client, struct timeval timeout)
497 {
498         enum clnt_stat status;
499
500         status = CLNT_CALL(client, NULLPROC,
501                            (xdrproc_t)xdr_void, NULL,
502                            (xdrproc_t)xdr_void, NULL,
503                            timeout);
504
505         if (status != RPC_SUCCESS) {
506                 rpc_createerr.cf_stat = status;
507                 CLNT_GETERR(client, &rpc_createerr.cf_error);
508         }
509         return (int)(status == RPC_SUCCESS);
510 }
511
512 #ifdef HAVE_LIBTIRPC
513
514 /*
515  * Initialize the rpcb argument for a GETADDR request.
516  *
517  * Returns 1 if successful, and caller must free strings pointed
518  * to by r_netid and r_addr; otherwise 0.
519  */
520 static int nfs_gp_init_rpcb_parms(const struct sockaddr *sap,
521                                   const rpcprog_t program,
522                                   const rpcvers_t version,
523                                   const unsigned short protocol,
524                                   struct rpcb *parms)
525 {
526         char *netid, *addr;
527
528         netid = nfs_get_netid(sap->sa_family, protocol);
529         if (netid == NULL)
530                 return 0;
531
532         addr = nfs_sockaddr2universal(sap);
533         if (addr == NULL) {
534                 free(netid);
535                 return 0;
536         }
537
538         memset(parms, 0, sizeof(*parms));
539         parms->r_prog   = program;
540         parms->r_vers   = version;
541         parms->r_netid  = netid;
542         parms->r_addr   = addr;
543         parms->r_owner  = "";
544
545         return 1;
546 }
547
548 static void nfs_gp_free_rpcb_parms(struct rpcb *parms)
549 {
550         free(parms->r_netid);
551         free(parms->r_addr);
552 }
553
554 /*
555  * Try rpcbind GETADDR via version 4.  If that fails, try same
556  * request via version 3.
557  *
558  * Returns non-zero port number on success; otherwise returns
559  * zero.  rpccreateerr is set to reflect the nature of the error.
560  */
561 static unsigned short nfs_gp_rpcb_getaddr(CLIENT *client,
562                                           struct rpcb *parms,
563                                           struct timeval timeout)
564 {
565         rpcvers_t rpcb_version;
566         struct rpc_err rpcerr;
567         int port = 0;
568
569         for (rpcb_version = RPCBVERS_4;
570              rpcb_version >= RPCBVERS_3;
571              rpcb_version--) {
572                 enum clnt_stat status;
573                 char *uaddr = NULL;
574
575                 CLNT_CONTROL(client, CLSET_VERS, (void *)&rpcb_version);
576                 status = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
577                                    (xdrproc_t)xdr_rpcb, (void *)parms,
578                                    (xdrproc_t)xdr_wrapstring, (void *)&uaddr,
579                                    timeout);
580
581                 switch (status) {
582                 case RPC_SUCCESS:
583                         if ((uaddr == NULL) || (uaddr[0] == '\0')) {
584                                 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
585                                 return 0;
586                         }
587
588                         port = nfs_universal2port(uaddr);
589                         xdr_free((xdrproc_t)xdr_wrapstring, (char *)&uaddr);
590                         if (port == -1) {
591                                 rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
592                                 return 0;
593                         }
594                         return (unsigned short)port;
595                 case RPC_PROGVERSMISMATCH:
596                         clnt_geterr(client, &rpcerr);
597                         if (rpcerr.re_vers.low > RPCBVERS4)
598                                 return 0;
599                         continue;
600                 case RPC_PROCUNAVAIL:
601                 case RPC_PROGUNAVAIL:
602                         continue;
603                 default:
604                         /* Most likely RPC_TIMEDOUT or RPC_CANTRECV */
605                         rpc_createerr.cf_stat = status;
606                         clnt_geterr(client, &rpc_createerr.cf_error);
607                         return 0;
608                 }
609
610         }
611
612         if (port == 0) {
613                 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
614                 clnt_geterr(client, &rpc_createerr.cf_error);
615         }
616         return port;
617 }
618
619 #endif  /* HAVE_LIBTIRPC */
620
621 /*
622  * Try GETPORT request via rpcbind version 2.
623  *
624  * Returns non-zero port number on success; otherwise returns
625  * zero.  rpccreateerr is set to reflect the nature of the error.
626  */
627 static unsigned long nfs_gp_pmap_getport(CLIENT *client,
628                                          struct pmap *parms,
629                                          struct timeval timeout)
630 {
631         enum clnt_stat status;
632         unsigned long port;
633
634         status = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
635                            (xdrproc_t)xdr_pmap, (void *)parms,
636                            (xdrproc_t)xdr_u_long, (void *)&port,
637                            timeout);
638
639         if (status != RPC_SUCCESS) {
640                 rpc_createerr.cf_stat = status;
641                 CLNT_GETERR(client, &rpc_createerr.cf_error);
642                 port = 0;
643         } else if (port == 0)
644                 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
645
646         return port;
647 }
648
649 #ifdef HAVE_LIBTIRPC
650
651 static unsigned short nfs_gp_getport_rpcb(CLIENT *client,
652                                           const struct sockaddr *sap,
653                                           const rpcprog_t program,
654                                           const rpcvers_t version,
655                                           const unsigned short protocol,
656                                           struct timeval timeout)
657 {
658         unsigned short port = 0;
659         struct rpcb parms;
660
661         if (nfs_gp_init_rpcb_parms(sap, program, version,
662                                         protocol, &parms) != 0) {
663                 port = nfs_gp_rpcb_getaddr(client, &parms, timeout);
664                 nfs_gp_free_rpcb_parms(&parms);
665         }
666
667         return port;
668 }
669
670 #endif  /* HAVE_LIBTIRPC */
671
672 static unsigned long nfs_gp_getport_pmap(CLIENT *client,
673                                          const rpcprog_t program,
674                                          const rpcvers_t version,
675                                          const unsigned short protocol,
676                                          struct timeval timeout)
677 {
678         struct pmap parms = {
679                 .pm_prog        = program,
680                 .pm_vers        = version,
681                 .pm_prot        = protocol,
682         };
683         rpcvers_t pmap_version = PMAPVERS;
684
685         CLNT_CONTROL(client, CLSET_VERS, (void *)&pmap_version);
686         return nfs_gp_pmap_getport(client, &parms, timeout);
687 }
688
689 /*
690  * Try an AF_INET6 request via rpcbind v4/v3; try an AF_INET
691  * request via rpcbind v2.
692  *
693  * Returns non-zero port number on success; otherwise returns
694  * zero.  rpccreateerr is set to reflect the nature of the error.
695  */
696 static unsigned short nfs_gp_getport(CLIENT *client,
697                                      const struct sockaddr *sap,
698                                      const rpcprog_t program,
699                                      const rpcvers_t version,
700                                      const unsigned short protocol,
701                                      struct timeval timeout)
702 {
703         switch (sap->sa_family) {
704 #ifdef HAVE_LIBTIRPC
705         case AF_INET6:
706                 return nfs_gp_getport_rpcb(client, sap, program,
707                                                 version, protocol, timeout);
708 #endif  /* HAVE_LIBTIRPC */
709         case AF_INET:
710                 return nfs_gp_getport_pmap(client, program, version,
711                                                         protocol, timeout);
712         }
713
714         rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
715         return 0;
716 }
717
718 /**
719  * nfs_rpc_ping - Determine if RPC service is responding to requests
720  * @sap: pointer to address of server to query (port is already filled in)
721  * @salen: length of server address
722  * @program: requested RPC program number
723  * @version: requested RPC version number
724  * @protocol: requested IPPROTO_ value of transport protocol
725  * @timeout: pointer to request timeout (NULL means use default timeout)
726  *
727  * Returns 1 if the remote service responded without an error; otherwise
728  * zero.
729  */
730 int nfs_rpc_ping(const struct sockaddr *sap, const socklen_t salen,
731                  const rpcprog_t program, const rpcvers_t version,
732                  const unsigned short protocol, const struct timeval *timeout)
733 {
734         union nfs_sockaddr address;
735         struct sockaddr *saddr = &address.sa;
736         CLIENT *client;
737         struct timeval tout = { -1, 0 };
738         int result = 0;
739
740         if (timeout != NULL)
741                 tout = *timeout;
742
743         nfs_clear_rpc_createerr();
744
745         memcpy(saddr, sap, (size_t)salen);
746         client = nfs_get_rpcclient(saddr, salen, protocol,
747                                                 program, version, &tout);
748         if (client != NULL) {
749                 result = nfs_gp_ping(client, tout);
750                 nfs_gp_map_tcp_errorcodes(protocol);
751                 CLNT_DESTROY(client);
752         }
753
754         return result;
755 }
756
757 /**
758  * nfs_getport - query server's rpcbind to get port number for an RPC service
759  * @sap: pointer to address of server to query
760  * @salen: length of server's address
761  * @program: requested RPC program number
762  * @version: requested RPC version number
763  * @protocol: IPPROTO_ value of requested transport protocol
764  *
765  * Uses any acceptable rpcbind version to discover the port number for the
766  * RPC service described by the given [program, version, transport] tuple.
767  * Uses a quick timeout and an ephemeral source port.  Supports AF_INET and
768  * AF_INET6 server addresses.
769  *
770  * Returns a positive integer representing the port number of the RPC
771  * service advertised by the server (in host byte order), or zero if the
772  * service is not advertised or there was some problem querying the server's
773  * rpcbind daemon.  rpccreateerr is set to reflect the underlying cause of
774  * the error.
775  *
776  * There are a variety of ways to choose which transport and rpcbind versions
777  * to use.  We chose to conserve local resources and try to avoid incurring
778  * timeouts.
779  *
780  * Transport
781  * To provide rudimentary support for traversing firewalls, query the remote
782  * using the same transport as the requested service.  This provides some
783  * guarantee that the requested transport is available between this client
784  * and the server, and if the caller specifically requests TCP, for example,
785  * this may be becuase a firewall is in place that blocks UDP traffic.  We
786  * could try both, but that could involve a lengthy timeout in several cases,
787  * and would often consume an extra ephemeral port.
788  *
789  * Rpcbind version
790  * To avoid using up too many ephemeral ports, AF_INET queries use tried-and-
791  * true rpcbindv2, and don't try the newer versions; and AF_INET6 queries use
792  * rpcbindv4, then rpcbindv3 on the same socket.  The newer rpcbind protocol
793  * versions can adequately detect if a remote RPC service does not support
794  * AF_INET6 at all.  The rpcbind socket is re-used in an attempt to keep the
795  * overall number of consumed ephemeral ports low.
796  */
797 unsigned short nfs_getport(const struct sockaddr *sap,
798                            const socklen_t salen,
799                            const rpcprog_t program,
800                            const rpcvers_t version,
801                            const unsigned short protocol)
802 {
803         union nfs_sockaddr address;
804         struct sockaddr *saddr = &address.sa;
805         struct timeval timeout = { -1, 0 };
806         unsigned short port = 0;
807         CLIENT *client;
808
809         nfs_clear_rpc_createerr();
810
811         memcpy(saddr, sap, (size_t)salen);
812         client = nfs_gp_get_rpcbclient(saddr, salen, protocol,
813                                                 default_rpcb_version, &timeout);
814         if (client != NULL) {
815                 port = nfs_gp_getport(client, saddr, program,
816                                         version, protocol, timeout);
817                 CLNT_DESTROY(client);
818         }
819
820         return port;
821 }
822
823 /**
824  * nfs_getport_ping - query server's rpcbind and do RPC ping to verify result
825  * @sap: IN: pointer to address of server to query;
826  *       OUT: pointer to updated address
827  * @salen: length of server's address
828  * @program: requested RPC program number
829  * @version: requested RPC version number
830  * @protocol: IPPROTO_ value of requested transport protocol
831  *
832  * Uses any acceptable rpcbind version to discover the port number for the
833  * RPC service described by the given [program, version, transport] tuple.
834  * Uses a quick timeout and an ephemeral source port.  Supports AF_INET and
835  * AF_INET6 server addresses.
836  *
837  * Returns a 1 and sets the port number in the passed-in server address
838  * if both the query and the ping were successful; otherwise zero.
839  * rpccreateerr is set to reflect the underlying cause of the error.
840  */
841 int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen,
842                      const rpcprog_t program, const rpcvers_t version,
843                      const unsigned short protocol)
844 {
845         struct timeval timeout = { -1, 0 };
846         unsigned short port = 0;
847         CLIENT *client;
848         int result = 0;
849         
850         nfs_clear_rpc_createerr();
851
852         client = nfs_gp_get_rpcbclient(sap, salen, protocol,
853                                                 default_rpcb_version, &timeout);
854         if (client != NULL) {
855                 port = nfs_gp_getport(client, sap, program,
856                                         version, protocol, timeout);
857                 CLNT_DESTROY(client);
858                 client = NULL;
859         }
860
861         if (port != 0) {
862                 union nfs_sockaddr address;
863                 struct sockaddr *saddr = &address.sa;
864
865                 memcpy(saddr, sap, (size_t)salen);
866                 nfs_set_port(saddr, port);
867
868                 nfs_clear_rpc_createerr();
869
870                 client = nfs_get_rpcclient(saddr, salen, protocol,
871                                                 program, version, &timeout);
872                 if (client != NULL) {
873                         result = nfs_gp_ping(client, timeout);
874                         nfs_gp_map_tcp_errorcodes(protocol);
875                         CLNT_DESTROY(client);
876                 }
877         }
878
879         if (result)
880                 nfs_set_port(sap, port);
881
882         return result;
883 }
884
885 /**
886  * nfs_getlocalport - query local rpcbind to get port number for an RPC service
887  * @program: requested RPC program number
888  * @version: requested RPC version number
889  * @protocol: IPPROTO_ value of requested transport protocol
890  *
891  * Uses any acceptable rpcbind version to discover the port number for the
892  * RPC service described by the given [program, version, transport] tuple.
893  * Uses a quick timeout and an ephemeral source port.  Supports AF_INET and
894  * AF_INET6 local addresses.
895  *
896  * Returns a positive integer representing the port number of the RPC
897  * service advertised by the server (in host byte order), or zero if the
898  * service is not advertised or there was some problem querying the server's
899  * rpcbind daemon.  rpccreateerr is set to reflect the underlying cause of
900  * the error.
901  *
902  * Try an AF_LOCAL connection first.  The rpcbind daemon implementation should
903  * listen on AF_LOCAL.
904  *
905  * If that doesn't work (for example, if portmapper is running, or rpcbind
906  * isn't listening on /var/run/rpcbind.sock), send a query via UDP to localhost
907  * (UDP doesn't leave a socket in TIME_WAIT, and the timeout is a relatively
908  * short 3 seconds).
909  */
910 unsigned short nfs_getlocalport(const rpcprot_t program,
911                                 const rpcvers_t version,
912                                 const unsigned short protocol)
913 {
914         union nfs_sockaddr address;
915         struct sockaddr *lb_addr = &address.sa;
916         socklen_t lb_len = sizeof(*lb_addr);
917         unsigned short port = 0;
918
919 #ifdef NFS_GP_LOCAL
920         const struct sockaddr_un sun = {
921                 .sun_family     = AF_LOCAL,
922                 .sun_path       = _PATH_RPCBINDSOCK,
923         };
924         const struct sockaddr *sap = (struct sockaddr *)&sun;
925         const socklen_t salen = SUN_LEN(&sun);
926         CLIENT *client;
927         struct timeval timeout = { -1, 0 };
928
929         nfs_clear_rpc_createerr();
930
931         client = nfs_gp_get_rpcbclient(sap, salen, 0, RPCBVERS_4, &timeout);
932         if (client != NULL) {
933                 struct rpcb parms;
934
935                 if (nfs_gp_init_rpcb_parms(sap, program, version,
936                                                 protocol, &parms) != 0) {
937                         port = nfs_gp_rpcb_getaddr(client, &parms, timeout);
938                         nfs_gp_free_rpcb_parms(&parms);
939                 }
940                 CLNT_DESTROY(client);
941         }
942 #endif  /* NFS_GP_LOCAL */
943
944         if (port == 0) {
945                 nfs_clear_rpc_createerr();
946
947                 if (nfs_gp_loopback_address(lb_addr, &lb_len)) {
948                         port = nfs_getport(lb_addr, lb_len,
949                                                 program, version, protocol);
950                 } else
951                         rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
952         }
953
954         return port;
955 }
956
957 /**
958  * nfs_rpcb_getaddr - query rpcbind via rpcbind versions 4 and 3
959  * @sap: pointer to address of server to query
960  * @salen: length of server address
961  * @transport: transport protocol to use for the query
962  * @addr: pointer to r_addr address
963  * @program: requested RPC program number
964  * @version: requested RPC version number
965  * @protocol: requested IPPROTO_ value of transport protocol
966  * @timeout: pointer to request timeout (NULL means use default timeout)
967  *
968  * Returns a positive integer representing the port number of the RPC
969  * service advertised by the server (in host byte order), or zero if the
970  * service is not advertised or there was some problem querying the
971  * server's rpcbind daemon.  rpccreateerr is set to reflect the
972  * underlying cause of the error.
973  *
974  * This function provides similar functionality to nfs_pmap_getport(),
975  * but performs the rpcbind lookup via rpcbind version 4.  If the server
976  * doesn't support rpcbind version 4, it will retry with version 3.
977  * The GETADDR procedure is exactly the same in these two versions of
978  * the rpcbind protocol, so the socket, RPC client, and arguments are
979  * re-used when retrying, saving ephemeral port space.
980  *
981  * These RPC procedures take a universal address as an argument, so the
982  * query will fail if the remote rpcbind daemon doesn't find an entry
983  * with a matching address.  A matching address includes an ANYADDR
984  * address of the same address family.  In this way an RPC server can
985  * advertise via rpcbind that it does not support AF_INET6.
986  */
987 #ifdef HAVE_LIBTIRPC
988
989 unsigned short nfs_rpcb_getaddr(const struct sockaddr *sap,
990                                 const socklen_t salen,
991                                 const unsigned short transport,
992                                 const struct sockaddr *addr,
993                                 const rpcprog_t program,
994                                 const rpcvers_t version,
995                                 const unsigned short protocol,
996                                 const struct timeval *timeout)
997 {
998         union nfs_sockaddr address;
999         struct sockaddr *saddr = &address.sa;
1000         CLIENT *client;
1001         struct rpcb parms;
1002         struct timeval tout = { -1, 0 };
1003         unsigned short port = 0;
1004
1005         if (timeout != NULL)
1006                 tout = *timeout;
1007
1008         nfs_clear_rpc_createerr();
1009
1010         memcpy(saddr, sap, (size_t)salen);
1011         client = nfs_gp_get_rpcbclient(saddr, salen, transport,
1012                                                         RPCBVERS_4, &tout);
1013         if (client != NULL) {
1014                 if (nfs_gp_init_rpcb_parms(addr, program, version,
1015                                                 protocol, &parms) != 0) {
1016                         port = nfs_gp_rpcb_getaddr(client, &parms, tout);
1017                         nfs_gp_free_rpcb_parms(&parms);
1018                 }
1019                 CLNT_DESTROY(client);
1020         }
1021
1022         return port;
1023 }
1024
1025 #else   /* !HAVE_LIBTIRPC */
1026
1027 unsigned short nfs_rpcb_getaddr(__attribute__((unused)) const struct sockaddr *sap,
1028                                 __attribute__((unused)) const socklen_t salen,
1029                                 __attribute__((unused)) const unsigned short transport,
1030                                 __attribute__((unused)) const struct sockaddr *addr,
1031                                 __attribute__((unused)) const rpcprog_t program,
1032                                 __attribute__((unused)) const rpcvers_t version,
1033                                 __attribute__((unused)) const unsigned short protocol,
1034                                 __attribute__((unused)) const struct timeval *timeout)
1035 {
1036         nfs_clear_rpc_createerr();
1037
1038         rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
1039         return 0;
1040 }
1041
1042 #endif  /* !HAVE_LIBTIRPC */
1043
1044 /**
1045  * nfs_pmap_getport - query rpcbind via the portmap protocol (rpcbindv2)
1046  * @sin: pointer to AF_INET address of server to query
1047  * @transport: transport protocol to use for the query
1048  * @program: requested RPC program number
1049  * @version: requested RPC version number
1050  * @protocol: requested IPPROTO_ value of transport protocol
1051  * @timeout: pointer to request timeout (NULL means use default timeout)
1052  *
1053  * Returns a positive integer representing the port number of the RPC service
1054  * advertised by the server (in host byte order), or zero if the service is
1055  * not advertised or there was some problem querying the server's rpcbind
1056  * daemon.  rpccreateerr is set to reflect the underlying cause of the error.
1057  *
1058  * nfs_pmap_getport() is very similar to pmap_getport(), except that:
1059  *
1060  *  1.  This version always tries to use an ephemeral port, since reserved
1061  *      ports are not needed for GETPORT queries.  This conserves the very
1062  *      limited reserved port space, helping reduce failed socket binds
1063  *      during mount storms.
1064  *
1065  *  2.  This version times out quickly by default.  It time-limits the
1066  *      connect process as well as the actual RPC call, and even allows the
1067  *      caller to specify the timeout.
1068  *
1069  *  3.  This version shares code with the rpcbindv3 and rpcbindv4 query
1070  *      functions.  It can use a TI-RPC generated CLIENT.
1071  */
1072 unsigned long nfs_pmap_getport(const struct sockaddr_in *sin,
1073                                const unsigned short transport,
1074                                const unsigned long program,
1075                                const unsigned long version,
1076                                const unsigned long protocol,
1077                                const struct timeval *timeout)
1078 {
1079         struct sockaddr_in address;
1080         struct sockaddr *saddr = (struct sockaddr *)&address;
1081         CLIENT *client;
1082         struct pmap parms = {
1083                 .pm_prog        = program,
1084                 .pm_vers        = version,
1085                 .pm_prot        = protocol,
1086         };
1087         struct timeval tout = { -1, 0 };
1088         unsigned long port = 0;
1089
1090         if (timeout != NULL)
1091                 tout = *timeout;
1092
1093         nfs_clear_rpc_createerr();
1094
1095         memcpy(saddr, sin, sizeof(address));
1096         client = nfs_gp_get_rpcbclient(saddr, (socklen_t)sizeof(*sin),
1097                                         transport, PMAPVERS, &tout);
1098         if (client != NULL) {
1099                 port = nfs_gp_pmap_getport(client, &parms, tout);
1100                 CLNT_DESTROY(client);
1101         }
1102
1103         return port;
1104 }