2 * Provide a variety of APIs that query an rpcbind daemon to
3 * discover RPC service ports and allowed protocol version
6 * Copyright (C) 2008 Oracle Corporation. All rights reserved.
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.
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.
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., 59 Temple Place - Suite 330,
21 * Boston, MA 021110-1307, USA.
29 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
38 #include <arpa/inet.h>
41 #include <rpc/pmap_prot.h>
44 #include <netconfig.h>
45 #include <rpc/rpcb_prot.h>
51 * Try a local socket first to access the local rpcbind daemon
53 * Rpcbind's local socket service does not seem to be working.
54 * Disable this logic for now.
58 #else /* !HAVE_LIBTIRPC */
60 #endif /* !HAVE_LIBTIRPC */
63 static const rpcvers_t default_rpcb_version = RPCBVERS_4;
64 #else /* !HAVE_LIBTIRPC */
65 static const rpcvers_t default_rpcb_version = PMAPVERS;
66 #endif /* !HAVE_LIBTIRPC */
69 * Historical: Map TCP connect timeouts to timeout
70 * error code used by UDP.
73 nfs_gp_map_tcp_errorcodes(const unsigned short protocol)
75 if (protocol != IPPROTO_TCP)
78 switch (rpc_createerr.cf_error.re_errno) {
80 rpc_createerr.cf_stat = RPC_TIMEDOUT;
83 rpc_createerr.cf_stat = RPC_CANTRECV;
89 * There's no easy way to tell how the local system's networking
90 * and rpcbind is configured (ie. whether we want to use IPv6 or
91 * IPv4 loopback to contact RPC services on the local host). We
92 * punt and simply try to look up "localhost".
94 * Returns TRUE on success.
96 static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
98 struct addrinfo *gai_results;
101 if (getaddrinfo("localhost", NULL, NULL, &gai_results))
104 if (*salen >= gai_results->ai_addrlen) {
105 memcpy(sap, gai_results->ai_addr,
106 gai_results->ai_addrlen);
107 *salen = gai_results->ai_addrlen;
111 freeaddrinfo(gai_results);
116 * Look up a network service in /etc/services and return the
117 * network-order port number of that service.
119 static in_port_t nfs_gp_getservbyname(const char *service,
120 const unsigned short protocol)
122 const struct addrinfo gai_hint = {
123 .ai_family = AF_INET,
124 .ai_protocol = protocol,
125 .ai_flags = AI_PASSIVE,
127 struct addrinfo *gai_results;
128 const struct sockaddr_in *sin;
131 if (getaddrinfo(NULL, service, &gai_hint, &gai_results) != 0)
134 sin = (const struct sockaddr_in *)gai_results->ai_addr;
135 port = sin->sin_port;
137 freeaddrinfo(gai_results);
142 * Discover the port number that should be used to contact an
143 * rpcbind service. This will detect if the port has a local
144 * value that may have been set in /etc/services.
146 * Returns network byte-order port number of rpcbind service
149 static in_port_t nfs_gp_get_rpcb_port(const unsigned short protocol)
151 static const char *rpcb_netnametbl[] = {
159 for (i = 0; rpcb_netnametbl[i] != NULL; i++) {
162 port = nfs_gp_getservbyname(rpcb_netnametbl[i], protocol);
167 return (in_port_t)htons((uint16_t)PMAPPORT);
171 * Set up an RPC client for communicating with an rpcbind daemon at
172 * @sap over @transport with protocol version @version.
174 * Returns a pointer to a prepared RPC client if successful, and
175 * @timeout is initialized; caller must destroy a non-NULL returned RPC
176 * client. Otherwise returns NULL, and rpc_createerr.cf_stat is set to
179 static CLIENT *nfs_gp_get_rpcbclient(struct sockaddr *sap,
180 const socklen_t salen,
181 const unsigned short transport,
182 const rpcvers_t version,
183 struct timeval *timeout)
185 static const char *rpcb_pgmtbl[] = {
192 rpcprog_t rpcb_prog = nfs_getrpcbyname(RPCBPROG, rpcb_pgmtbl);
195 nfs_set_port(sap, ntohs(nfs_gp_get_rpcb_port(transport)));
196 clnt = nfs_get_rpcclient(sap, salen, transport, rpcb_prog,
198 nfs_gp_map_tcp_errorcodes(transport);
203 * nfs_get_proto - Convert a netid to an address family and protocol number
204 * @netid: C string containing a netid
205 * @family: OUT: address family
206 * @protocol: OUT: protocol number
208 * Returns 1 and fills in @protocol if the netid was recognized;
209 * otherwise zero is returned.
213 nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol)
215 struct netconfig *nconf;
216 struct protoent *proto;
218 nconf = getnetconfigent(netid);
222 proto = getprotobyname(nconf->nc_proto);
224 freenetconfigent(nconf);
229 if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
231 if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
233 freenetconfigent(nconf);
235 *protocol = (unsigned long)proto->p_proto;
238 #else /* !HAVE_LIBTIRPC */
240 nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol)
242 struct protoent *proto;
244 proto = getprotobyname(netid);
249 *protocol = (unsigned long)proto->p_proto;
252 #endif /* !HAVE_LIBTIRPC */
255 * nfs_get_netid - Convert a protocol family and protocol name to a netid
256 * @family: protocol family
257 * @protocol: protocol number
259 * One of the arguments passed when querying remote rpcbind services
260 * via rpcbind v3 or v4 is a netid string. This replaces the pm_prot
261 * field used in legacy PMAP_GETPORT calls.
263 * RFC 1833 says netids are not standard but rather defined on the local
264 * host. There are, however, standard definitions for nc_protofmly and
265 * nc_proto that can be used to derive a netid string on the local host,
266 * based on the contents of /etc/netconfig.
268 * Walk through the local netconfig database and grab the netid of the
269 * first entry that matches @family and @protocol and whose netid string
270 * fits in the provided buffer.
272 * Returns a '\0'-terminated string if successful. Caller must
273 * free the returned string. Otherwise NULL is returned, and
274 * rpc_createerr.cf_stat is set to reflect the error.
277 char *nfs_get_netid(const sa_family_t family, const unsigned long protocol)
279 char *nc_protofmly, *nc_proto, *nc_netid;
280 struct netconfig *nconf;
281 struct protoent *proto;
287 nc_protofmly = NC_INET;
290 nc_protofmly = NC_INET6;
296 proto = getprotobynumber(protocol);
299 nc_proto = proto->p_name;
301 handle = setnetconfig();
302 while ((nconf = getnetconfig(handle)) != NULL) {
304 if (nconf->nc_protofmly != NULL &&
305 strcmp(nconf->nc_protofmly, nc_protofmly) != 0)
307 if (nconf->nc_proto != NULL &&
308 strcmp(nconf->nc_proto, nc_proto) != 0)
311 nc_netid = strdup(nconf->nc_netid);
312 endnetconfig(handle);
314 if (nc_netid == NULL)
315 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
318 endnetconfig(handle);
321 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
324 #else /* !HAVE_LIBTIRPC */
325 char *nfs_get_netid(const sa_family_t family, const unsigned long protocol)
327 struct protoent *proto;
330 if (family != AF_INET)
332 proto = getprotobynumber((int)protocol);
336 netid = strdup(proto->p_name);
338 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
342 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
345 #endif /* !HAVE_LIBTIRPC */
348 * Extract a port number from a universal address, and terminate the
349 * string in @addrstr just after the address part.
351 * Returns -1 if unsuccesful; otherwise a decoded port number (possibly 0)
354 static int nfs_gp_universal_porthelper(char *addrstr)
357 unsigned long portlo, porthi;
360 p = strrchr(addrstr, '.');
363 portlo = strtoul(p + 1, &endptr, 10);
364 if (*endptr != '\0' || portlo > 255)
368 p = strrchr(addrstr, '.');
371 porthi = strtoul(p + 1, &endptr, 10);
372 if (*endptr != '\0' || porthi > 255)
375 port = (porthi << 8) | portlo;
382 * nfs_universal2port - extract port number from a "universal address"
383 * @uaddr: '\0'-terminated C string containing a universal address
385 * Universal addresses (defined in RFC 1833) are used when calling an
386 * rpcbind daemon via protocol versions 3 or 4..
388 * Returns -1 if unsuccesful; otherwise a decoded port number (possibly 0)
391 int nfs_universal2port(const char *uaddr)
396 addrstr = strdup(uaddr);
397 if (addrstr != NULL) {
398 port = nfs_gp_universal_porthelper(addrstr);
405 * nfs_sockaddr2universal - convert a sockaddr to a "universal address"
406 * @sap: pointer to a socket address
408 * Universal addresses (defined in RFC 1833) are used when calling an
409 * rpcbind daemon via protocol versions 3 or 4..
411 * Returns a '\0'-terminated string if successful; caller must free
412 * the returned string. Otherwise NULL is returned and
413 * rpc_createerr.cf_stat is set to reflect the error.
415 * inet_ntop(3) is used here, since getnameinfo(3) is not available
416 * in some earlier glibc releases, and we don't require support for
417 * scope IDs for universal addresses.
419 char *nfs_sockaddr2universal(const struct sockaddr *sap)
421 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
422 const struct sockaddr_un *sun = (const struct sockaddr_un *)sap;
423 const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
424 char buf[INET6_ADDRSTRLEN + 8 /* for port information */];
430 switch (sap->sa_family) {
432 return strndup(sun->sun_path, sizeof(sun->sun_path));
434 if (inet_ntop(AF_INET, (const void *)&sin->sin_addr.s_addr,
435 buf, (socklen_t)sizeof(buf)) == NULL)
437 port = ntohs(sin->sin_port);
440 if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
441 buf, (socklen_t)sizeof(buf)) == NULL)
443 port = ntohs(sin6->sin6_port);
449 count = sizeof(buf) - strlen(buf);
450 len = snprintf(buf + strlen(buf), count, ".%u.%u",
451 (unsigned)(port >> 8), (unsigned)(port & 0xff));
452 /* before glibc 2.0.6, snprintf(3) could return -1 */
453 if (len < 0 || (size_t)len > count)
456 result = strdup(buf);
461 rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
466 * Send a NULL request to the indicated RPC service.
468 * Returns 1 if the service responded; otherwise 0;
470 static int nfs_gp_ping(CLIENT *client, struct timeval timeout)
472 enum clnt_stat status;
474 status = CLNT_CALL(client, NULLPROC,
475 (xdrproc_t)xdr_void, NULL,
476 (xdrproc_t)xdr_void, NULL,
479 if (status != RPC_SUCCESS) {
480 rpc_createerr.cf_stat = status;
481 CLNT_GETERR(client, &rpc_createerr.cf_error);
483 return (int)(status == RPC_SUCCESS);
489 * Initialize the rpcb argument for a GETADDR request.
491 * Returns 1 if successful, and caller must free strings pointed
492 * to by r_netid and r_addr; otherwise 0.
494 static int nfs_gp_init_rpcb_parms(const struct sockaddr *sap,
495 const rpcprog_t program,
496 const rpcvers_t version,
497 const unsigned short protocol,
502 netid = nfs_get_netid(sap->sa_family, protocol);
506 addr = nfs_sockaddr2universal(sap);
512 memset(parms, 0, sizeof(*parms));
513 parms->r_prog = program;
514 parms->r_vers = version;
515 parms->r_netid = netid;
516 parms->r_addr = addr;
522 static void nfs_gp_free_rpcb_parms(struct rpcb *parms)
524 free(parms->r_netid);
529 * Try rpcbind GETADDR via version 4. If that fails, try same
530 * request via version 3.
532 * Returns non-zero port number on success; otherwise returns
533 * zero. rpccreateerr is set to reflect the nature of the error.
535 static unsigned short nfs_gp_rpcb_getaddr(CLIENT *client,
537 struct timeval timeout)
539 rpcvers_t rpcb_version;
540 struct rpc_err rpcerr;
543 for (rpcb_version = RPCBVERS_4;
544 rpcb_version >= RPCBVERS_3;
546 enum clnt_stat status;
549 CLNT_CONTROL(client, CLSET_VERS, (void *)&rpcb_version);
550 status = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
551 (xdrproc_t)xdr_rpcb, (void *)parms,
552 (xdrproc_t)xdr_wrapstring, (void *)&uaddr,
557 if ((uaddr == NULL) || (uaddr[0] == '\0')) {
558 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
562 port = nfs_universal2port(uaddr);
563 xdr_free((xdrproc_t)xdr_wrapstring, (char *)&uaddr);
565 rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
568 return (unsigned short)port;
569 case RPC_PROGVERSMISMATCH:
570 clnt_geterr(client, &rpcerr);
571 if (rpcerr.re_vers.low > RPCBVERS4)
574 case RPC_PROCUNAVAIL:
575 case RPC_PROGUNAVAIL:
578 /* Most likely RPC_TIMEDOUT or RPC_CANTRECV */
579 rpc_createerr.cf_stat = status;
580 clnt_geterr(client, &rpc_createerr.cf_error);
587 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
588 clnt_geterr(client, &rpc_createerr.cf_error);
593 #endif /* HAVE_LIBTIRPC */
596 * Try GETPORT request via rpcbind version 2.
598 * Returns non-zero port number on success; otherwise returns
599 * zero. rpccreateerr is set to reflect the nature of the error.
601 static unsigned long nfs_gp_pmap_getport(CLIENT *client,
603 struct timeval timeout)
605 enum clnt_stat status;
608 status = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
609 (xdrproc_t)xdr_pmap, (void *)parms,
610 (xdrproc_t)xdr_u_long, (void *)&port,
613 if (status != RPC_SUCCESS) {
614 rpc_createerr.cf_stat = status;
615 CLNT_GETERR(client, &rpc_createerr.cf_error);
617 } else if (port == 0)
618 rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
625 static unsigned short nfs_gp_getport_rpcb(CLIENT *client,
626 const struct sockaddr *sap,
627 const rpcprog_t program,
628 const rpcvers_t version,
629 const unsigned short protocol,
630 struct timeval timeout)
632 unsigned short port = 0;
635 if (nfs_gp_init_rpcb_parms(sap, program, version,
636 protocol, &parms) != 0) {
637 port = nfs_gp_rpcb_getaddr(client, &parms, timeout);
638 nfs_gp_free_rpcb_parms(&parms);
644 #endif /* HAVE_LIBTIRPC */
646 static unsigned long nfs_gp_getport_pmap(CLIENT *client,
647 const rpcprog_t program,
648 const rpcvers_t version,
649 const unsigned short protocol,
650 struct timeval timeout)
652 struct pmap parms = {
657 rpcvers_t pmap_version = PMAPVERS;
659 CLNT_CONTROL(client, CLSET_VERS, (void *)&pmap_version);
660 return nfs_gp_pmap_getport(client, &parms, timeout);
664 * Try an AF_INET6 request via rpcbind v4/v3; try an AF_INET
665 * request via rpcbind v2.
667 * Returns non-zero port number on success; otherwise returns
668 * zero. rpccreateerr is set to reflect the nature of the error.
670 static unsigned short nfs_gp_getport(CLIENT *client,
671 const struct sockaddr *sap,
672 const rpcprog_t program,
673 const rpcvers_t version,
674 const unsigned short protocol,
675 struct timeval timeout)
677 switch (sap->sa_family) {
680 return nfs_gp_getport_rpcb(client, sap, program,
681 version, protocol, timeout);
682 #endif /* HAVE_LIBTIRPC */
684 return nfs_gp_getport_pmap(client, program, version,
688 rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
693 * nfs_rpc_ping - Determine if RPC service is responding to requests
694 * @sap: pointer to address of server to query (port is already filled in)
695 * @salen: length of server address
696 * @program: requested RPC program number
697 * @version: requested RPC version number
698 * @protocol: requested IPPROTO_ value of transport protocol
699 * @timeout: pointer to request timeout (NULL means use default timeout)
701 * Returns 1 if the remote service responded without an error; otherwise
704 int nfs_rpc_ping(const struct sockaddr *sap, const socklen_t salen,
705 const rpcprog_t program, const rpcvers_t version,
706 const unsigned short protocol, const struct timeval *timeout)
708 struct sockaddr_storage address;
709 struct sockaddr *saddr = (struct sockaddr *)&address;
711 struct timeval tout = { -1, 0 };
717 nfs_clear_rpc_createerr();
719 memcpy(saddr, sap, (size_t)salen);
720 client = nfs_get_rpcclient(saddr, salen, protocol,
721 program, version, &tout);
722 if (client != NULL) {
723 result = nfs_gp_ping(client, tout);
724 nfs_gp_map_tcp_errorcodes(protocol);
725 CLNT_DESTROY(client);
732 * nfs_getport - query server's rpcbind to get port number for an RPC service
733 * @sap: pointer to address of server to query
734 * @salen: length of server's address
735 * @program: requested RPC program number
736 * @version: requested RPC version number
737 * @protocol: IPPROTO_ value of requested transport protocol
739 * Uses any acceptable rpcbind version to discover the port number for the
740 * RPC service described by the given [program, version, transport] tuple.
741 * Uses a quick timeout and an ephemeral source port. Supports AF_INET and
742 * AF_INET6 server addresses.
744 * Returns a positive integer representing the port number of the RPC
745 * service advertised by the server (in host byte order), or zero if the
746 * service is not advertised or there was some problem querying the server's
747 * rpcbind daemon. rpccreateerr is set to reflect the underlying cause of
750 * There are a variety of ways to choose which transport and rpcbind versions
751 * to use. We chose to conserve local resources and try to avoid incurring
755 * To provide rudimentary support for traversing firewalls, query the remote
756 * using the same transport as the requested service. This provides some
757 * guarantee that the requested transport is available between this client
758 * and the server, and if the caller specifically requests TCP, for example,
759 * this may be becuase a firewall is in place that blocks UDP traffic. We
760 * could try both, but that could involve a lengthy timeout in several cases,
761 * and would often consume an extra ephemeral port.
764 * To avoid using up too many ephemeral ports, AF_INET queries use tried-and-
765 * true rpcbindv2, and don't try the newer versions; and AF_INET6 queries use
766 * rpcbindv4, then rpcbindv3 on the same socket. The newer rpcbind protocol
767 * versions can adequately detect if a remote RPC service does not support
768 * AF_INET6 at all. The rpcbind socket is re-used in an attempt to keep the
769 * overall number of consumed ephemeral ports low.
771 unsigned short nfs_getport(const struct sockaddr *sap,
772 const socklen_t salen,
773 const rpcprog_t program,
774 const rpcvers_t version,
775 const unsigned short protocol)
777 struct sockaddr_storage address;
778 struct sockaddr *saddr = (struct sockaddr *)&address;
779 struct timeval timeout = { -1, 0 };
780 unsigned short port = 0;
783 nfs_clear_rpc_createerr();
785 memcpy(saddr, sap, (size_t)salen);
786 client = nfs_gp_get_rpcbclient(saddr, salen, protocol,
787 default_rpcb_version, &timeout);
788 if (client != NULL) {
789 port = nfs_gp_getport(client, saddr, program,
790 version, protocol, timeout);
791 CLNT_DESTROY(client);
798 * nfs_getport_ping - query server's rpcbind and do RPC ping to verify result
799 * @sap: IN: pointer to address of server to query;
800 * OUT: pointer to updated address
801 * @salen: length of server's address
802 * @program: requested RPC program number
803 * @version: requested RPC version number
804 * @protocol: IPPROTO_ value of requested transport protocol
806 * Uses any acceptable rpcbind version to discover the port number for the
807 * RPC service described by the given [program, version, transport] tuple.
808 * Uses a quick timeout and an ephemeral source port. Supports AF_INET and
809 * AF_INET6 server addresses.
811 * Returns a 1 and sets the port number in the passed-in server address
812 * if both the query and the ping were successful; otherwise zero.
813 * rpccreateerr is set to reflect the underlying cause of the error.
815 int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen,
816 const rpcprog_t program, const rpcvers_t version,
817 const unsigned short protocol)
819 struct timeval timeout = { -1, 0 };
820 unsigned short port = 0;
824 nfs_clear_rpc_createerr();
826 client = nfs_gp_get_rpcbclient(sap, salen, protocol,
827 default_rpcb_version, &timeout);
828 if (client != NULL) {
829 port = nfs_gp_getport(client, sap, program,
830 version, protocol, timeout);
831 CLNT_DESTROY(client);
836 struct sockaddr_storage address;
837 struct sockaddr *saddr = (struct sockaddr *)&address;
839 memcpy(saddr, sap, (size_t)salen);
840 nfs_set_port(saddr, port);
842 nfs_clear_rpc_createerr();
844 client = nfs_get_rpcclient(saddr, salen, protocol,
845 program, version, &timeout);
846 if (client != NULL) {
847 result = nfs_gp_ping(client, timeout);
848 nfs_gp_map_tcp_errorcodes(protocol);
849 CLNT_DESTROY(client);
854 nfs_set_port(sap, port);
860 * nfs_getlocalport - query local rpcbind to get port number for an RPC service
861 * @program: requested RPC program number
862 * @version: requested RPC version number
863 * @protocol: IPPROTO_ value of requested transport protocol
865 * Uses any acceptable rpcbind version to discover the port number for the
866 * RPC service described by the given [program, version, transport] tuple.
867 * Uses a quick timeout and an ephemeral source port. Supports AF_INET and
868 * AF_INET6 local addresses.
870 * Returns a positive integer representing the port number of the RPC
871 * service advertised by the server (in host byte order), or zero if the
872 * service is not advertised or there was some problem querying the server's
873 * rpcbind daemon. rpccreateerr is set to reflect the underlying cause of
876 * Try an AF_LOCAL connection first. The rpcbind daemon implementation should
877 * listen on AF_LOCAL.
879 * If that doesn't work (for example, if portmapper is running, or rpcbind
880 * isn't listening on /var/run/rpcbind.sock), send a query via UDP to localhost
881 * (UDP doesn't leave a socket in TIME_WAIT, and the timeout is a relatively
884 unsigned short nfs_getlocalport(const rpcprot_t program,
885 const rpcvers_t version,
886 const unsigned short protocol)
888 struct sockaddr_storage address;
889 struct sockaddr *lb_addr = (struct sockaddr *)&address;
890 socklen_t lb_len = sizeof(*lb_addr);
891 unsigned short port = 0;
894 const struct sockaddr_un sun = {
895 .sun_family = AF_LOCAL,
896 .sun_path = _PATH_RPCBINDSOCK,
898 const struct sockaddr *sap = (struct sockaddr *)&sun;
899 const socklen_t salen = SUN_LEN(&sun);
901 struct timeval timeout = { -1, 0 };
903 nfs_clear_rpc_createerr();
905 client = nfs_gp_get_rpcbclient(sap, salen, 0, RPCBVERS_4, &timeout);
906 if (client != NULL) {
909 if (nfs_gp_init_rpcb_parms(sap, program, version,
910 protocol, &parms) != 0) {
911 port = nfs_gp_rpcb_getaddr(client, &parms, timeout);
912 nfs_gp_free_rpcb_parms(&parms);
914 CLNT_DESTROY(client);
916 #endif /* NFS_GP_LOCAL */
919 nfs_clear_rpc_createerr();
921 if (nfs_gp_loopback_address(lb_addr, &lb_len)) {
922 port = nfs_getport(lb_addr, lb_len,
923 program, version, protocol);
925 rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
932 * nfs_rpcb_getaddr - query rpcbind via rpcbind versions 4 and 3
933 * @sap: pointer to address of server to query
934 * @salen: length of server address
935 * @transport: transport protocol to use for the query
936 * @addr: pointer to r_addr address
937 * @program: requested RPC program number
938 * @version: requested RPC version number
939 * @protocol: requested IPPROTO_ value of transport protocol
940 * @timeout: pointer to request timeout (NULL means use default timeout)
942 * Returns a positive integer representing the port number of the RPC
943 * service advertised by the server (in host byte order), or zero if the
944 * service is not advertised or there was some problem querying the
945 * server's rpcbind daemon. rpccreateerr is set to reflect the
946 * underlying cause of the error.
948 * This function provides similar functionality to nfs_pmap_getport(),
949 * but performs the rpcbind lookup via rpcbind version 4. If the server
950 * doesn't support rpcbind version 4, it will retry with version 3.
951 * The GETADDR procedure is exactly the same in these two versions of
952 * the rpcbind protocol, so the socket, RPC client, and arguments are
953 * re-used when retrying, saving ephemeral port space.
955 * These RPC procedures take a universal address as an argument, so the
956 * query will fail if the remote rpcbind daemon doesn't find an entry
957 * with a matching address. A matching address includes an ANYADDR
958 * address of the same address family. In this way an RPC server can
959 * advertise via rpcbind that it does not support AF_INET6.
963 unsigned short nfs_rpcb_getaddr(const struct sockaddr *sap,
964 const socklen_t salen,
965 const unsigned short transport,
966 const struct sockaddr *addr,
967 const rpcprog_t program,
968 const rpcvers_t version,
969 const unsigned short protocol,
970 const struct timeval *timeout)
972 struct sockaddr_storage address;
973 struct sockaddr *saddr = (struct sockaddr *)&address;
976 struct timeval tout = { -1, 0 };
977 unsigned short port = 0;
982 nfs_clear_rpc_createerr();
984 memcpy(saddr, sap, (size_t)salen);
985 client = nfs_gp_get_rpcbclient(saddr, salen, transport,
987 if (client != NULL) {
988 if (nfs_gp_init_rpcb_parms(addr, program, version,
989 protocol, &parms) != 0) {
990 port = nfs_gp_rpcb_getaddr(client, &parms, tout);
991 nfs_gp_free_rpcb_parms(&parms);
993 CLNT_DESTROY(client);
999 #else /* !HAVE_LIBTIRPC */
1001 unsigned short nfs_rpcb_getaddr(__attribute__((unused)) const struct sockaddr *sap,
1002 __attribute__((unused)) const socklen_t salen,
1003 __attribute__((unused)) const unsigned short transport,
1004 __attribute__((unused)) const struct sockaddr *addr,
1005 __attribute__((unused)) const rpcprog_t program,
1006 __attribute__((unused)) const rpcvers_t version,
1007 __attribute__((unused)) const unsigned short protocol,
1008 __attribute__((unused)) const struct timeval *timeout)
1010 nfs_clear_rpc_createerr();
1012 rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
1016 #endif /* !HAVE_LIBTIRPC */
1019 * nfs_pmap_getport - query rpcbind via the portmap protocol (rpcbindv2)
1020 * @sin: pointer to AF_INET address of server to query
1021 * @transport: transport protocol to use for the query
1022 * @program: requested RPC program number
1023 * @version: requested RPC version number
1024 * @protocol: requested IPPROTO_ value of transport protocol
1025 * @timeout: pointer to request timeout (NULL means use default timeout)
1027 * Returns a positive integer representing the port number of the RPC service
1028 * advertised by the server (in host byte order), or zero if the service is
1029 * not advertised or there was some problem querying the server's rpcbind
1030 * daemon. rpccreateerr is set to reflect the underlying cause of the error.
1032 * nfs_pmap_getport() is very similar to pmap_getport(), except that:
1034 * 1. This version always tries to use an ephemeral port, since reserved
1035 * ports are not needed for GETPORT queries. This conserves the very
1036 * limited reserved port space, helping reduce failed socket binds
1037 * during mount storms.
1039 * 2. This version times out quickly by default. It time-limits the
1040 * connect process as well as the actual RPC call, and even allows the
1041 * caller to specify the timeout.
1043 * 3. This version shares code with the rpcbindv3 and rpcbindv4 query
1044 * functions. It can use a TI-RPC generated CLIENT.
1046 unsigned long nfs_pmap_getport(const struct sockaddr_in *sin,
1047 const unsigned short transport,
1048 const unsigned long program,
1049 const unsigned long version,
1050 const unsigned long protocol,
1051 const struct timeval *timeout)
1053 struct sockaddr_in address;
1054 struct sockaddr *saddr = (struct sockaddr *)&address;
1056 struct pmap parms = {
1059 .pm_prot = protocol,
1061 struct timeval tout = { -1, 0 };
1062 unsigned long port = 0;
1064 if (timeout != NULL)
1067 nfs_clear_rpc_createerr();
1069 memcpy(saddr, sin, sizeof(address));
1070 client = nfs_gp_get_rpcbclient(saddr, (socklen_t)sizeof(*sin),
1071 transport, PMAPVERS, &tout);
1072 if (client != NULL) {
1073 port = nfs_gp_pmap_getport(client, &parms, tout);
1074 CLNT_DESTROY(client);