From: J. Bruce Fields Date: Thu, 3 May 2012 19:06:21 +0000 (-0400) Subject: mountd: prepend '$' to make use_ipaddr clients self-describing X-Git-Tag: nfs-utils-1-2-6-rc7~1 X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=c2544b77566690ebec32a2d47c9249548b1a0941;p=nfs-utils.git mountd: prepend '$' to make use_ipaddr clients self-describing From: "J. Bruce Fields" Mountd is responsible for filling three interrelated kernel caches: - auth_unix_ip maps an incoming ip addresses to a "domain". - nfsd_fh maps (domain, filehandle-fragment) pairs to paths. - nfsd_export maps (domain, path) pairs to export options. Note that each export is assocated with a "client" string--the part before the parentheses in an /etc/export line--which may be a domain name, a netgroup, etc. The "domain" string in the above three caches may be either: - in the !use_ipaddr case, a comma-separated list of client strings. - in the use_ipaddr case, an ip address. In the former case, mountd does the hard work of matching an ip address to the clients when doing the auth_unix_ip mapping. In the latter case, it delays that until the nfsd_fh or nfsd_export upcall. We're currently depending on being able to flush the kernel caches completely when switching between the use_ipaddr and !use_ipaddr cases. However, the kernel's cache-flushing doesn't really provide reliable guarantees on return; it's still possible we could see nfsd_fh or nfsd_export upcalls with the old domain-type after flushing. So, instead, make the two domain types self-describing by prepending a "$" in the use_ipaddr case. Reviewed-by: NeilBrown Signed-off-by: J. Bruce Fields Signed-off-by: Steve Dickson --- diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c index 688bf78..508040a 100644 --- a/utils/mountd/auth.c +++ b/utils/mountd/auth.c @@ -112,15 +112,23 @@ auth_reload() return counter; } +static char *get_client_ipaddr_name(const struct sockaddr *caller) +{ + char buf[INET6_ADDRSTRLEN + 1]; + + buf[0] = '$'; + host_ntop(caller, buf + 1, sizeof(buf) - 1); + return strdup(buf); +} + static char * get_client_hostname(const struct sockaddr *caller, struct addrinfo *ai, enum auth_error *error) { - char buf[INET6_ADDRSTRLEN]; char *n; if (use_ipaddr) - return strdup(host_ntop(caller, buf, sizeof(buf))); + return get_client_ipaddr_name(caller); n = client_compose(ai); *error = unknown_host; if (!n) @@ -143,7 +151,7 @@ bool namelist_client_matches(nfs_export *exp, char *dom) bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai) { - if (use_ipaddr) + if (is_ipaddr_client(dom)) return ipaddr_client_matches(exp, ai); return namelist_client_matches(exp, dom); } diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index be5198e..1ae96fe 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -500,6 +500,8 @@ struct addrinfo *lookup_client_addr(char *dom) struct addrinfo *ret; struct addrinfo *tmp; + dom++; /* skip initial "$" */ + tmp = host_pton(dom); if (tmp == NULL) return NULL; @@ -551,7 +553,7 @@ static void nfsd_fh(FILE *f) auth_reload(); - if (use_ipaddr) { + if (is_ipaddr_client(dom)) { ai = lookup_client_addr(dom); if (!ai) goto out; @@ -587,7 +589,8 @@ static void nfsd_fh(FILE *f) next_exp = exp->m_next; } - if (!use_ipaddr && !namelist_client_matches(exp, dom)) + if (!is_ipaddr_client(dom) + && !namelist_client_matches(exp, dom)) continue; if (exp->m_export.e_mountpoint && !is_mountpoint(exp->m_export.e_mountpoint[0]? @@ -597,7 +600,8 @@ static void nfsd_fh(FILE *f) if (!match_fsid(&parsed, exp, path)) continue; - if (use_ipaddr && !ipaddr_client_matches(exp, ai)) + if (is_ipaddr_client(dom) + && !ipaddr_client_matches(exp, ai)) continue; if (!found || subexport(&exp->m_export, found)) { found = &exp->m_export; @@ -1071,7 +1075,7 @@ static void nfsd_export(FILE *f) auth_reload(); - if (use_ipaddr) { + if (is_ipaddr_client(dom)) { ai = lookup_client_addr(dom); if (!ai) goto out; diff --git a/utils/mountd/mountd.h b/utils/mountd/mountd.h index c969a27..6d358a7 100644 --- a/utils/mountd/mountd.h +++ b/utils/mountd/mountd.h @@ -60,4 +60,9 @@ bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai); bool namelist_client_matches(nfs_export *exp, char *dom); bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai); +static inline bool is_ipaddr_client(char *dom) +{ + return dom[0] == '$'; +} + #endif /* MOUNTD_H */