libtirpc really does a terrible job of protocol fallback. When trying to connect to rpcbind/portmap, it iterates over the protocols listed in /etc/netconfig (nice choice of name, oh yeah) and tries to create a socket for each in turn. Then it selects the last protocol for which that succeeded (yes, the last, not the first).
Only then does it try to connect. So there is no fallback at all for connection. I'm attaching a patch to fix connection fallback, but unfortunately it is not sufficient to make svc_reg() with portmap. Ben. -- Ben Hutchings Once a job is fouled up, anything done to improve it makes it worse.
--- libtirpc-0.2.1.orig/src/rpcb_clnt.c +++ libtirpc-0.2.1/src/rpcb_clnt.c @@ -459,17 +459,21 @@ /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */ mutex_lock(&loopnconf_lock); - if (loopnconf == NULL) { + if (loopnconf != NULL) { + mutex_unlock(&loopnconf_lock); + client = getclnthandle(hostname, loopnconf, NULL); + } else { struct netconfig *nconf, *tmpnconf = NULL; void *nc_handle; int fd; + mutex_unlock(&loopnconf_lock); + nc_handle = setnetconfig(); if (nc_handle == NULL) { /* fails to open netconfig file */ syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; - mutex_unlock(&loopnconf_lock); return (NULL); } while ((nconf = getnetconfig(nc_handle)) != NULL) { @@ -489,24 +493,31 @@ if (fd < 0) continue; close(fd); - tmpnconf = nconf; if (!strcmp(nconf->nc_protofmly, NC_INET)) hostname = IN4_LOCALHOST_STRING; else hostname = IN6_LOCALHOST_STRING; + client = getclnthandle(hostname, nconf, NULL); + if (client == NULL) + continue; + tmpnconf = getnetconfigent(nconf->nc_netid); + break; } } + endnetconfig(nc_handle); if (tmpnconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; - mutex_unlock(&loopnconf_lock); return (NULL); } - loopnconf = getnetconfigent(tmpnconf->nc_netid); - /* loopnconf is never freed */ - endnetconfig(nc_handle); + mutex_lock(&loopnconf_lock); + if (loopnconf == NULL) + /* loopnconf is never freed */ + loopnconf = tmpnconf; + else + /* free the duplicate */ + freenetconfigent(tmpnconf); + mutex_unlock(&loopnconf_lock); } - mutex_unlock(&loopnconf_lock); - client = getclnthandle(hostname, loopnconf, NULL); return (client); }
signature.asc
Description: This is a digitally signed message part