X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fexport%2Fclient.c;h=57176d880077a53e40b0e27532643ecd7b4e2620;hp=6d5d3063317502d0a958493795b046df23a4f5ab;hb=54669c988cc7609a4aab1021604244424ebb795a;hpb=c69020c28de49ab71da0389199c45d104f170656 diff --git a/support/export/client.c b/support/export/client.c index 6d5d306..57176d8 100644 --- a/support/export/client.c +++ b/support/export/client.c @@ -138,7 +138,9 @@ client_init(nfs_client *clp, const char *hname, struct hostent *hp) if (clp->m_type == MCL_SUBNETWORK) { char *cp = strchr(clp->m_hostname, '/'); + static char slash32[] = "/32"; + if(!cp) cp = slash32; *cp = '\0'; clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname); if (strchr(cp + 1, '.')) { @@ -229,6 +231,104 @@ client_find(struct hostent *hp) return NULL; } +/* + * Find client name given an IP address + * This is found by gathering all known names that match that IP address, + * sorting them and joining them with '+' + * + */ +static char *add_name(char *old, char *add); + +char * +client_compose(struct in_addr addr) +{ + struct hostent *he = NULL; + char *name = NULL; + int i; + + if (clientlist[MCL_WILDCARD] || clientlist[MCL_NETGROUP]) + he = get_reliable_hostbyaddr((const char*)&addr, sizeof(addr), AF_INET); + if (he == NULL) + he = get_hostent((const char*)&addr, sizeof(addr), AF_INET); + + for (i = 0 ; i < MCL_MAXTYPES; i++) { + nfs_client *clp; + for (clp = clientlist[i]; clp ; clp = clp->m_next) { + if (!client_check(clp, he)) + continue; + name = add_name(name, clp->m_hostname); + } + } + return name; +} + +int +client_member(char *client, char *name) +{ + /* check if "client" (a ',' separated list of names) + * contains 'name' as a member + */ + int l = strlen(name); + while (*client) { + if (strncmp(client, name, l) == 0 && + (client[l] == ',' || client[l] == '\0')) + return 1; + client = strchr(client, ','); + if (client == NULL) + return 0; + client++; + } + return 0; +} + + +int +name_cmp(char *a, char *b) +{ + /* compare strings a and b, but only upto ',' in a */ + while (*a && *b && *a != ',' && *a == *b) + a++, b++; + if (!*b && (!*a || !a == ',') ) + return 0; + if (!*b) return 1; + if (!*a || *a == ',') return -1; + return *a - *b; +} + +static char * +add_name(char *old, char *add) +{ + int len = strlen(add)+2; + char *new; + char *cp; + if (old) len += strlen(old); + + new = malloc(len); + if (!new) { + free(old); + return NULL; + } + cp = old; + while (cp && *cp && name_cmp(cp, add) < 0) { + /* step cp forward over a name */ + char *e = strchr(cp, ','); + if (e) + cp = e+1; + else + cp = cp + strlen(cp); + } + strncpy(new, old, cp-old); + new[cp-old] = 0; + if (cp != old && !*cp) + strcat(new, ","); + strcat(new, add); + if (cp && *cp) { + strcat(new, ","); + strcat(new, cp); + } + return new; +} + /* * Match a host (given its hostent record) to a client record. This * is usually called from mountd. @@ -294,6 +394,8 @@ client_check(nfs_client *clp, struct hostent *hp) #endif case MCL_ANONYMOUS: return 1; + case MCL_GSS: + return 0; default: xlog(L_FATAL, "internal: bad client type %d", clp->m_type); } @@ -327,6 +429,8 @@ client_gettype(char *ident) if (ident[0] == '\0' || strcmp(ident, "*")==0) return MCL_ANONYMOUS; + if (strncmp(ident, "gss/", 4) == 0) + return MCL_GSS; if (ident[0] == '@') { #ifndef HAVE_INNETGR xlog(L_WARNING, "netgroup support not compiled in"); @@ -341,5 +445,12 @@ client_gettype(char *ident) if (*sp == '\\' && sp[1]) sp++; } - return MCL_FQDN; + /* check for N.N.N.N */ + sp = ident; + if(!isdigit(*sp) || strtoul(sp, &sp, 10) > 255 || *sp != '.') return MCL_FQDN; + sp++; if(!isdigit(*sp) || strtoul(sp, &sp, 10) > 255 || *sp != '.') return MCL_FQDN; + sp++; if(!isdigit(*sp) || strtoul(sp, &sp, 10) > 255 || *sp != '.') return MCL_FQDN; + sp++; if(!isdigit(*sp) || strtoul(sp, &sp, 10) > 255 || *sp != '\0') return MCL_FQDN; + /* we lie here a bit. but technically N.N.N.N == N.N.N.N/32 :) */ + return MCL_SUBNETWORK; }