X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fexport%2Fclient.c;h=6d5d3063317502d0a958493795b046df23a4f5ab;hp=a7f9d020c390a3e6f25643e32ce6cb959281b2da;hb=c69020c28de49ab71da0389199c45d104f170656;hpb=1369ddc35e940c56aafdb73174b6fe7acc631d8f diff --git a/support/export/client.c b/support/export/client.c index a7f9d02..6d5d306 100644 --- a/support/export/client.c +++ b/support/export/client.c @@ -32,8 +32,12 @@ static int client_checkaddr(nfs_client *clp, struct in_addr addr); nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; +/* if canonical is set, then we *know* this is already a canonical name + * so hostname lookup is avoided. + * This is used when reading /proc/fs/nfs/exports + */ nfs_client * -client_lookup(char *hname) +client_lookup(char *hname, int canonical) { nfs_client *clp = NULL; int htype; @@ -41,13 +45,32 @@ client_lookup(char *hname) htype = client_gettype(hname); - if (htype == MCL_FQDN) { + if (htype == MCL_FQDN && !canonical) { + struct hostent *hp2; hp = gethostbyname(hname); if (hp == NULL || hp->h_addrtype != AF_INET) { xlog(L_ERROR, "%s has non-inet addr", hname); return NULL; } - hp = hostent_dup (hp); + /* make sure we have canonical name */ + hp2 = hostent_dup(hp); + hp = gethostbyaddr(hp2->h_addr, hp2->h_length, + hp2->h_addrtype); + if (hp) { + hp = hostent_dup(hp); + /* but now we might not have all addresses... */ + if (hp2->h_addr_list[1]) { + struct hostent *hp3 = + gethostbyname(hp->h_name); + if (hp3) { + free(hp); + hp = hostent_dup(hp3); + } + } + free(hp2); + } else + hp = hp2; + hname = (char *) hp->h_name; for (clp = clientlist[htype]; clp; clp = clp->m_next) { @@ -56,7 +79,7 @@ client_lookup(char *hname) } } else { for (clp = clientlist[htype]; clp; clp = clp->m_next) { - if (strcmp(hname, clp->m_hostname)==0) + if (strcasecmp(hname, clp->m_hostname)==0) break; } } @@ -118,7 +141,20 @@ client_init(nfs_client *clp, const char *hname, struct hostent *hp) *cp = '\0'; clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname); - clp->m_addrlist[1].s_addr = inet_addr(cp+1); + if (strchr(cp + 1, '.')) { + clp->m_addrlist[1].s_addr = inet_addr(cp+1); + } + else { + int netmask = atoi(cp + 1); + if (0 < netmask && netmask <= 32) { + clp->m_addrlist[1].s_addr = + htonl ((uint32_t) ~0 << (32 - netmask)); + } + else { + xlog(L_FATAL, "invalid netmask `%s' for %s", + cp + 1, clp->m_hostname); + } + } *cp = '/'; clp->m_naddr = 0; } else if (!hp) { @@ -226,12 +262,23 @@ client_check(nfs_client *clp, struct hostent *hp) { char *dot; int match; + struct hostent *nhp = NULL; + struct sockaddr_in addr; /* First, try to match the hostname without * splitting off the domain */ if (innetgr(cname+1, hname, NULL, NULL)) return 1; + /* If hname is ip address convert to FQDN */ + if (inet_aton(hname, &addr.sin_addr) && + (nhp = gethostbyaddr((const char *)&(addr.sin_addr), + sizeof(addr.sin_addr), AF_INET))) { + hname = (char *)nhp->h_name; + if (innetgr(cname+1, hname, NULL, NULL)) + return 1; + } + /* Okay, strip off the domain (if we have one) */ if ((dot = strchr(hname, '.')) == NULL) return 0; @@ -278,7 +325,7 @@ client_gettype(char *ident) { char *sp; - if (ident[0] == '\0') + if (ident[0] == '\0' || strcmp(ident, "*")==0) return MCL_ANONYMOUS; if (ident[0] == '@') { #ifndef HAVE_INNETGR