X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fnfs%2Fgetport.c;h=4bdf556e092fc5e3e33dea26b87bf1a0b3dab128;hp=056d3c71cfc88bbddc50c13d9814d557cc41f800;hb=9350a97a266ada8d8b3282cf4248e3b9ffdc0058;hpb=df5e6316f040f49065d2821c05d4673994d48d4c diff --git a/support/nfs/getport.c b/support/nfs/getport.c index 056d3c7..4bdf556 100644 --- a/support/nfs/getport.c +++ b/support/nfs/getport.c @@ -65,6 +65,26 @@ static const rpcvers_t default_rpcb_version = RPCBVERS_4; static const rpcvers_t default_rpcb_version = PMAPVERS; #endif /* !HAVE_LIBTIRPC */ +/* + * Historical: Map TCP connect timeouts to timeout + * error code used by UDP. + */ +static void +nfs_gp_map_tcp_errorcodes(const unsigned short protocol) +{ + if (protocol != IPPROTO_TCP) + return; + + switch (rpc_createerr.cf_error.re_errno) { + case ETIMEDOUT: + rpc_createerr.cf_stat = RPC_TIMEDOUT; + break; + case ECONNREFUSED: + rpc_createerr.cf_stat = RPC_CANTRECV; + break; + } +} + /* * There's no easy way to tell how the local system's networking * and rpcbind is configured (ie. whether we want to use IPv6 or @@ -92,24 +112,6 @@ static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen) return ret; } -/* - * Plant port number in @sap. @port is already in network byte order. - */ -static void nfs_gp_set_port(struct sockaddr *sap, const in_port_t port) -{ - struct sockaddr_in *sin = (struct sockaddr_in *)sap; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; - - switch (sap->sa_family) { - case AF_INET: - sin->sin_port = port; - break; - case AF_INET6: - sin6->sin6_port = port; - break; - } -} - /* * Look up a network service in /etc/services and return the * network-order port number of that service. @@ -188,10 +190,13 @@ static CLIENT *nfs_gp_get_rpcbclient(struct sockaddr *sap, NULL, }; rpcprog_t rpcb_prog = nfs_getrpcbyname(RPCBPROG, rpcb_pgmtbl); + CLIENT *clnt; - nfs_gp_set_port(sap, nfs_gp_get_rpcb_port(transport)); - return nfs_get_rpcclient(sap, salen, transport, rpcb_prog, - version, timeout); + nfs_set_port(sap, ntohs(nfs_gp_get_rpcb_port(transport))); + clnt = nfs_get_rpcclient(sap, salen, transport, rpcb_prog, + version, timeout); + nfs_gp_map_tcp_errorcodes(transport); + return clnt; } /* @@ -321,7 +326,6 @@ int nfs_universal2port(const char *uaddr) /** * nfs_sockaddr2universal - convert a sockaddr to a "universal address" * @sap: pointer to a socket address - * @salen: length of socket address * * Universal addresses (defined in RFC 1833) are used when calling an * rpcbind daemon via protocol versions 3 or 4.. @@ -334,8 +338,7 @@ int nfs_universal2port(const char *uaddr) * in some earlier glibc releases, and we don't require support for * scope IDs for universal addresses. */ -char *nfs_sockaddr2universal(const struct sockaddr *sap, - const socklen_t salen) +char *nfs_sockaddr2universal(const struct sockaddr *sap) { const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; const struct sockaddr_un *sun = (const struct sockaddr_un *)sap; @@ -395,6 +398,10 @@ static int nfs_gp_ping(CLIENT *client, struct timeval timeout) (xdrproc_t)xdr_void, NULL, timeout); + if (status != RPC_SUCCESS) { + rpc_createerr.cf_stat = status; + CLNT_GETERR(client, &rpc_createerr.cf_error); + } return (int)(status == RPC_SUCCESS); } @@ -407,7 +414,6 @@ static int nfs_gp_ping(CLIENT *client, struct timeval timeout) * to by r_netid and r_addr; otherwise 0. */ static int nfs_gp_init_rpcb_parms(const struct sockaddr *sap, - const socklen_t salen, const rpcprog_t program, const rpcvers_t version, const unsigned short protocol, @@ -419,7 +425,7 @@ static int nfs_gp_init_rpcb_parms(const struct sockaddr *sap, if (netid == NULL) return 0; - addr = nfs_sockaddr2universal(sap, salen); + addr = nfs_sockaddr2universal(sap); if (addr == NULL) { free(netid); return 0; @@ -472,7 +478,7 @@ static unsigned short nfs_gp_rpcb_getaddr(CLIENT *client, case RPC_SUCCESS: if ((uaddr == NULL) || (uaddr[0] == '\0')) { rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; - continue; + return 0; } port = nfs_universal2port(uaddr); @@ -528,7 +534,7 @@ static unsigned long nfs_gp_pmap_getport(CLIENT *client, if (status != RPC_SUCCESS) { rpc_createerr.cf_stat = status; - clnt_geterr(client, &rpc_createerr.cf_error); + CLNT_GETERR(client, &rpc_createerr.cf_error); port = 0; } else if (port == 0) rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; @@ -540,7 +546,6 @@ static unsigned long nfs_gp_pmap_getport(CLIENT *client, static unsigned short nfs_gp_getport_rpcb(CLIENT *client, const struct sockaddr *sap, - const socklen_t salen, const rpcprog_t program, const rpcvers_t version, const unsigned short protocol, @@ -549,8 +554,8 @@ static unsigned short nfs_gp_getport_rpcb(CLIENT *client, unsigned short port = 0; struct rpcb parms; - if (nfs_gp_init_rpcb_parms(sap, salen, program, - version, protocol, &parms) != 0) { + if (nfs_gp_init_rpcb_parms(sap, program, version, + protocol, &parms) != 0) { port = nfs_gp_rpcb_getaddr(client, &parms, timeout); nfs_gp_free_rpcb_parms(&parms); } @@ -586,7 +591,6 @@ static unsigned long nfs_gp_getport_pmap(CLIENT *client, */ static unsigned short nfs_gp_getport(CLIENT *client, const struct sockaddr *sap, - const socklen_t salen, const rpcprog_t program, const rpcvers_t version, const unsigned short protocol, @@ -595,7 +599,7 @@ static unsigned short nfs_gp_getport(CLIENT *client, switch (sap->sa_family) { #ifdef HAVE_LIBTIRPC case AF_INET6: - return nfs_gp_getport_rpcb(client, sap, salen, program, + return nfs_gp_getport_rpcb(client, sap, program, version, protocol, timeout); #endif /* HAVE_LIBTIRPC */ case AF_INET: @@ -632,11 +636,14 @@ int nfs_rpc_ping(const struct sockaddr *sap, const socklen_t salen, if (timeout != NULL) tout = *timeout; + nfs_clear_rpc_createerr(); + memcpy(saddr, sap, (size_t)salen); client = nfs_get_rpcclient(saddr, salen, protocol, program, version, &tout); if (client != NULL) { result = nfs_gp_ping(client, tout); + nfs_gp_map_tcp_errorcodes(protocol); CLNT_DESTROY(client); } @@ -695,11 +702,13 @@ unsigned short nfs_getport(const struct sockaddr *sap, unsigned short port = 0; CLIENT *client; + nfs_clear_rpc_createerr(); + memcpy(saddr, sap, (size_t)salen); client = nfs_gp_get_rpcbclient(saddr, salen, protocol, default_rpcb_version, &timeout); if (client != NULL) { - port = nfs_gp_getport(client, saddr, salen, program, + port = nfs_gp_getport(client, saddr, program, version, protocol, timeout); CLNT_DESTROY(client); } @@ -734,10 +743,12 @@ int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen, CLIENT *client; int result = 0; + nfs_clear_rpc_createerr(); + client = nfs_gp_get_rpcbclient(sap, salen, protocol, default_rpcb_version, &timeout); if (client != NULL) { - port = nfs_gp_getport(client, sap, salen, program, + port = nfs_gp_getport(client, sap, program, version, protocol, timeout); CLNT_DESTROY(client); client = NULL; @@ -748,18 +759,21 @@ int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen, struct sockaddr *saddr = (struct sockaddr *)&address; memcpy(saddr, sap, (size_t)salen); - nfs_gp_set_port(saddr, htons(port)); + nfs_set_port(saddr, port); + + nfs_clear_rpc_createerr(); client = nfs_get_rpcclient(saddr, salen, protocol, program, version, &timeout); if (client != NULL) { result = nfs_gp_ping(client, timeout); + nfs_gp_map_tcp_errorcodes(protocol); CLNT_DESTROY(client); } } if (result) - nfs_gp_set_port(sap, htons(port)); + nfs_set_port(sap, port); return result; } @@ -808,11 +822,13 @@ unsigned short nfs_getlocalport(const rpcprot_t program, CLIENT *client; struct timeval timeout = { -1, 0 }; + nfs_clear_rpc_createerr(); + client = nfs_gp_get_rpcbclient(sap, salen, 0, RPCBVERS_4, &timeout); if (client != NULL) { struct rpcb parms; - if (nfs_gp_init_rpcb_parms(sap, salen, program, version, + if (nfs_gp_init_rpcb_parms(sap, program, version, protocol, &parms) != 0) { port = nfs_gp_rpcb_getaddr(client, &parms, timeout); nfs_gp_free_rpcb_parms(&parms); @@ -822,6 +838,8 @@ unsigned short nfs_getlocalport(const rpcprot_t program, #endif /* NFS_GP_LOCAL */ if (port == 0) { + nfs_clear_rpc_createerr(); + if (nfs_gp_loopback_address(lb_addr, &lb_len)) { port = nfs_getport(lb_addr, lb_len, program, version, protocol); @@ -838,7 +856,6 @@ unsigned short nfs_getlocalport(const rpcprot_t program, * @salen: length of server address * @transport: transport protocol to use for the query * @addr: pointer to r_addr address - * @addrlen: length of address * @program: requested RPC program number * @version: requested RPC version number * @protocol: requested IPPROTO_ value of transport protocol @@ -869,7 +886,6 @@ unsigned short nfs_rpcb_getaddr(const struct sockaddr *sap, const socklen_t salen, const unsigned short transport, const struct sockaddr *addr, - const socklen_t addrlen, const rpcprog_t program, const rpcvers_t version, const unsigned short protocol, @@ -885,11 +901,13 @@ unsigned short nfs_rpcb_getaddr(const struct sockaddr *sap, if (timeout != NULL) tout = *timeout; + nfs_clear_rpc_createerr(); + memcpy(saddr, sap, (size_t)salen); client = nfs_gp_get_rpcbclient(saddr, salen, transport, RPCBVERS_4, &tout); if (client != NULL) { - if (nfs_gp_init_rpcb_parms(addr, addrlen, program, version, + if (nfs_gp_init_rpcb_parms(addr, program, version, protocol, &parms) != 0) { port = nfs_gp_rpcb_getaddr(client, &parms, tout); nfs_gp_free_rpcb_parms(&parms); @@ -902,16 +920,17 @@ unsigned short nfs_rpcb_getaddr(const struct sockaddr *sap, #else /* !HAVE_LIBTIRPC */ -unsigned short nfs_rpcb_getaddr(const struct sockaddr *sap, - const socklen_t salen, - const unsigned short transport, - const struct sockaddr *addr, - const socklen_t addrlen, - const rpcprog_t program, - const rpcvers_t version, - const unsigned short protocol, - const struct timeval *timeout) +unsigned short nfs_rpcb_getaddr(__attribute__((unused)) const struct sockaddr *sap, + __attribute__((unused)) const socklen_t salen, + __attribute__((unused)) const unsigned short transport, + __attribute__((unused)) const struct sockaddr *addr, + __attribute__((unused)) const rpcprog_t program, + __attribute__((unused)) const rpcvers_t version, + __attribute__((unused)) const unsigned short protocol, + __attribute__((unused)) const struct timeval *timeout) { + nfs_clear_rpc_createerr(); + rpc_createerr.cf_stat = RPC_UNKNOWNADDR; return 0; } @@ -967,6 +986,8 @@ unsigned long nfs_pmap_getport(const struct sockaddr_in *sin, if (timeout != NULL) tout = *timeout; + nfs_clear_rpc_createerr(); + memcpy(saddr, sin, sizeof(address)); client = nfs_gp_get_rpcbclient(saddr, (socklen_t)sizeof(*sin), transport, PMAPVERS, &tout);