From 626010056efb7baa76b08b5e6572720e02e425b4 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 11 Dec 2009 10:34:42 -0500 Subject: [PATCH] libnfs.a: Provide shared helpers for managing netids Introduce a couple of shared functions that can convert netids to protocol numbers and families, and back. Signed-off-by: Chuck Lever Signed-off-by: Steve Dickson --- support/include/nfsrpc.h | 12 ++++++ support/nfs/getport.c | 92 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 7 deletions(-) diff --git a/support/include/nfsrpc.h b/support/include/nfsrpc.h index dff6af7..d6d4a1c 100644 --- a/support/include/nfsrpc.h +++ b/support/include/nfsrpc.h @@ -89,6 +89,18 @@ extern CLIENT *nfs_get_priv_rpcclient( const struct sockaddr *, const rpcprog_t, const rpcvers_t, struct timeval *); +/* + * Convert a netid to a protocol number and protocol family + */ +extern int nfs_get_proto(const char *netid, sa_family_t *family, + unsigned long *protocol); + +/* + * Convert a protocol family and protocol name to a netid + */ +extern char *nfs_get_netid(const sa_family_t family, + const unsigned long protocol); + /* * Convert a socket address to a universal address */ diff --git a/support/nfs/getport.c b/support/nfs/getport.c index 4bdf556..7e0f798 100644 --- a/support/nfs/getport.c +++ b/support/nfs/getport.c @@ -199,7 +199,63 @@ static CLIENT *nfs_gp_get_rpcbclient(struct sockaddr *sap, return clnt; } -/* +/** + * nfs_get_proto - Convert a netid to an address family and protocol number + * @netid: C string containing a netid + * @family: OUT: address family + * @protocol: OUT: protocol number + * + * Returns 1 and fills in @protocol if the netid was recognized; + * otherwise zero is returned. + */ +#ifdef HAVE_LIBTIRPC +int +nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol) +{ + struct netconfig *nconf; + struct protoent *proto; + + nconf = getnetconfigent(netid); + if (nconf == NULL) + return 0; + + proto = getprotobyname(nconf->nc_proto); + if (proto == NULL) { + freenetconfigent(nconf); + return 0; + } + + *family = AF_UNSPEC; + if (strcmp(nconf->nc_protofmly, NC_INET) == 0) + *family = AF_INET; + if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) + *family = AF_INET6; + freenetconfigent(nconf); + + *protocol = (unsigned long)proto->p_proto; + return 1; +} +#else /* !HAVE_LIBTIRPC */ +int +nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol) +{ + struct protoent *proto; + + proto = getprotobyname(netid); + if (proto == NULL) + return 0; + + *family = AF_INET; + *protocol = (unsigned long)proto->p_proto; + return 1; +} +#endif /* !HAVE_LIBTIRPC */ + +/** + * nfs_get_netid - Convert a protocol family and protocol name to a netid + * @family: protocol family + * @protocol: protocol number + * * One of the arguments passed when querying remote rpcbind services * via rpcbind v3 or v4 is a netid string. This replaces the pm_prot * field used in legacy PMAP_GETPORT calls. @@ -213,13 +269,12 @@ static CLIENT *nfs_gp_get_rpcbclient(struct sockaddr *sap, * first entry that matches @family and @protocol and whose netid string * fits in the provided buffer. * - * Returns a '\0'-terminated string if successful; otherwise NULL. + * Returns a '\0'-terminated string if successful. Caller must + * free the returned string. Otherwise NULL is returned, and * rpc_createerr.cf_stat is set to reflect the error. */ #ifdef HAVE_LIBTIRPC - -static char *nfs_gp_get_netid(const sa_family_t family, - const unsigned short protocol) +char *nfs_get_netid(const sa_family_t family, const unsigned long protocol) { char *nc_protofmly, *nc_proto, *nc_netid; struct netconfig *nconf; @@ -255,6 +310,9 @@ static char *nfs_gp_get_netid(const sa_family_t family, nc_netid = strdup(nconf->nc_netid); endnetconfig(handle); + + if (nc_netid == NULL) + rpc_createerr.cf_stat = RPC_SYSTEMERROR; return nc_netid; } endnetconfig(handle); @@ -263,8 +321,28 @@ out: rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return NULL; } +#else /* !HAVE_LIBTIRPC */ +char *nfs_get_netid(const sa_family_t family, const unsigned long protocol) +{ + struct protoent *proto; + char *netid; -#endif /* HAVE_LIBTIRPC */ + if (family != AF_INET) + goto out; + proto = getprotobynumber((int)protocol); + if (proto == NULL) + goto out; + + netid = strdup(proto->p_name); + if (netid == NULL) + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + return netid; + +out: + rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; + return NULL; +} +#endif /* !HAVE_LIBTIRPC */ /* * Extract a port number from a universal address, and terminate the @@ -421,7 +499,7 @@ static int nfs_gp_init_rpcb_parms(const struct sockaddr *sap, { char *netid, *addr; - netid = nfs_gp_get_netid(sap->sa_family, protocol); + netid = nfs_get_netid(sap->sa_family, protocol); if (netid == NULL) return 0; -- 2.39.5