X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fexport%2Fclient.c;h=03f791721774b5937642cf83d150a8c8442636f4;hp=a7f9d020c390a3e6f25643e32ce6cb959281b2da;hb=0bd51f4c931eb68c355140c721763be64213a3ca;hpb=1369ddc35e940c56aafdb73174b6fe7acc631d8f diff --git a/support/export/client.c b/support/export/client.c index a7f9d02..03f7917 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,23 @@ 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) { + free(hp2); + hp = hostent_dup(hp); + } else + hp = hp2; + hname = (char *) hp->h_name; for (clp = clientlist[htype]; clp; clp = clp->m_next) { @@ -56,7 +70,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 +132,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 +253,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 +316,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