diff --git a/CHANGELOG b/CHANGELOG index 01822f0..2ffef53 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -41,6 +41,8 @@ - fix parsing of bad mount mount point in master map. - fix use after free memory access in cache.c and lookup_yp.c. - eliminate use of pthread_kill to detect task completion. +- alter nfs4 host probing to not use portmap lookup and add options + check for "port=" parameter. 1/9/2006 autofs-5.0.1 rc2 ------------------------- diff --git a/include/replicated.h b/include/replicated.h index 00cf641..970cd31 100644 --- a/include/replicated.h +++ b/include/replicated.h @@ -62,7 +62,7 @@ struct host { void free_host_list(struct host **); int parse_location(struct host **, const char *); -int prune_host_list(struct host **, unsigned int); +int prune_host_list(struct host **, unsigned int, const char *); void dump_host_list(struct host *); #endif diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c index 94c8e8b..e859284 100644 --- a/modules/mount_nfs.c +++ b/modules/mount_nfs.c @@ -134,7 +134,7 @@ int mount_mount(struct autofs_point *ap, warn(ap->logopt, MODPREFIX "no hosts available"); return 1; } - prune_host_list(&hosts, vers); + prune_host_list(&hosts, vers, nfsoptions); if (!hosts) { warn(ap->logopt, MODPREFIX "no hosts available"); diff --git a/modules/replicated.c b/modules/replicated.c index 9b9a44b..5aaaba1 100644 --- a/modules/replicated.c +++ b/modules/replicated.c @@ -329,10 +329,42 @@ void free_host_list(struct host **list) *list = NULL; } +static unsigned short get_port_option(const char *options) +{ + const char *start; + long port = 0; + + if (!options) + return NFS_PORT; + + start = strstr(options, "port="); + if (!start) + port = NFS_PORT; + else { + char optport[30], *opteq, *end; + int len; + + end = strchr(start, ','); + len = end ? end - start : strlen(start); + strncpy(optport, start, len); + optport[len] = '\0'; + opteq = strchr(optport, '='); + if (opteq) + port = atoi(opteq + 1); + } + + if (port < 0) + port = 0; + + return (unsigned short) port; +} + static unsigned int get_nfs_info(struct host *host, struct conn_info *pm_info, struct conn_info *rpc_info, - const char *proto, unsigned int version) + const char *proto, unsigned int version, + const char *options) { + char *have_port_opt = options ? strstr(options, "port=") : NULL; struct pmap parms; struct timeval start, end; struct timezone tz; @@ -349,19 +381,10 @@ static unsigned int get_nfs_info(struct if (!rpc_info->proto) return 0; - status = rpc_portmap_getclient(pm_info, - host->name, proto, RPC_CLOSE_DEFAULT); - if (!status) - return 0; - - parms.pm_prot = rpc_info->proto->p_proto; - if (!(version & NFS4_REQUESTED)) goto v3_ver; - parms.pm_vers = NFS4_VERSION; - rpc_info->port = rpc_portmap_getport(pm_info, &parms); - if (!rpc_info->port) + if (!(rpc_info->port = get_port_option(options))) goto v3_ver; if (rpc_info->proto->p_proto == IPPROTO_UDP) @@ -380,13 +403,26 @@ static unsigned int get_nfs_info(struct } v3_ver: + if (!have_port_opt) { + status = rpc_portmap_getclient(pm_info, + host->name, proto, RPC_CLOSE_DEFAULT); + if (!status) + goto done_ver; + } + if (!(version & NFS3_REQUESTED)) goto v2_ver; - parms.pm_vers = NFS3_VERSION; - rpc_info->port = rpc_portmap_getport(pm_info, &parms); - if (!rpc_info->port) - goto v2_ver; + if (have_port_opt) { + if (!(rpc_info->port = get_port_option(options))) + goto done_ver; + } else { + parms.pm_prot = rpc_info->proto->p_proto; + parms.pm_vers = NFS3_VERSION; + rpc_info->port = rpc_portmap_getport(pm_info, &parms); + if (!rpc_info->port) + goto v2_ver; + } if (rpc_info->proto->p_proto == IPPROTO_UDP) status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS3_VERSION); @@ -407,10 +443,16 @@ v2_ver: if (!(version & NFS2_REQUESTED)) goto done_ver; - parms.pm_vers = NFS2_VERSION; - rpc_info->port = rpc_portmap_getport(pm_info, &parms); - if (!rpc_info->port) - goto done_ver; + if (have_port_opt) { + if (!(rpc_info->port = get_port_option(options))) + goto done_ver; + } else { + parms.pm_prot = rpc_info->proto->p_proto; + parms.pm_vers = NFS2_VERSION; + rpc_info->port = rpc_portmap_getport(pm_info, &parms); + if (!rpc_info->port) + goto done_ver; + } if (rpc_info->proto->p_proto == IPPROTO_UDP) status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS2_VERSION); @@ -451,7 +493,7 @@ done_ver: return supported; } -static int get_vers_and_cost(struct host *host, unsigned int version) +static int get_vers_and_cost(struct host *host, unsigned int version, const char *options) { struct conn_info pm_info, rpc_info; time_t timeout = RPC_TIMEOUT; @@ -475,7 +517,7 @@ static int get_vers_and_cost(struct host vers &= version; if (version & UDP_REQUESTED) { - supported = get_nfs_info(host, &pm_info, &rpc_info, "udp", vers); + supported = get_nfs_info(host, &pm_info, &rpc_info, "udp", vers, options); if (supported) { ret = 1; host->version |= (supported << 8); @@ -483,7 +525,7 @@ static int get_vers_and_cost(struct host } if (version & TCP_REQUESTED) { - supported = get_nfs_info(host, &pm_info, &rpc_info, "tcp", vers); + supported = get_nfs_info(host, &pm_info, &rpc_info, "tcp", vers, options); if (supported) { ret = 1; host->version |= supported; @@ -493,8 +535,9 @@ static int get_vers_and_cost(struct host return ret; } -static int get_supported_ver_and_cost(struct host *host, unsigned int version) +static int get_supported_ver_and_cost(struct host *host, unsigned int version, const char *options) { + char *have_port_opt = options ? strstr(options, "port=") : NULL; struct conn_info pm_info, rpc_info; struct pmap parms; const char *proto; @@ -534,18 +577,23 @@ static int get_supported_ver_and_cost(st if (!rpc_info.proto) return 0; - status = rpc_portmap_getclient(&pm_info, - host->name, proto, RPC_CLOSE_DEFAULT); - if (!status) - return 0; - - parms.pm_prot = rpc_info.proto->p_proto; - status = 0; + parms.pm_vers = vers; - rpc_info.port = rpc_portmap_getport(&pm_info, &parms); - if (!rpc_info.port) - goto done; + if (have_port_opt || (vers & NFS4_VERSION)) { + if (!(rpc_info.port = get_port_option(options))) + return 0; + } else { + int ret = rpc_portmap_getclient(&pm_info, + host->name, proto, RPC_CLOSE_DEFAULT); + if (!ret) + return 0; + + parms.pm_prot = rpc_info.proto->p_proto; + rpc_info.port = rpc_portmap_getport(&pm_info, &parms); + if (!rpc_info.port) + goto done; + } if (rpc_info.proto->p_proto == IPPROTO_UDP) status = rpc_udp_getclient(&rpc_info, NFS_PROGRAM, parms.pm_vers); @@ -581,7 +629,7 @@ done: return 0; } -int prune_host_list(struct host **list, unsigned int vers) +int prune_host_list(struct host **list, unsigned int vers, const char *options) { struct host *this, *last, *first; struct host *new = NULL; @@ -604,7 +652,7 @@ int prune_host_list(struct host **list, struct host *next = this->next; if (this->name) { - status = get_vers_and_cost(this, vers); + status = get_vers_and_cost(this, vers, options); if (!status) { if (this == first) { first = next; @@ -695,7 +743,7 @@ int prune_host_list(struct host **list, if (!this->name) add_host(&new, this); else { - status = get_supported_ver_and_cost(this, selected_version); + status = get_supported_ver_and_cost(this, selected_version, options); if (status) { this->version = selected_version; remove_host(list, this);