X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmountd%2Fcache.c;h=1176c624e1a75960d1738633daf4d3376e7643bc;hp=e4e2f228f848a458a9d6e30a3c6e02ef8b43bec1;hb=94ce1eb94babb4c587b2826452fb053cba745098;hpb=bc0a6ab03089fc1ea4fea26ed9635c2cc918b01b diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index e4e2f22..1176c62 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -125,7 +125,7 @@ void auth_unix_gid(FILE *f) * reply is * uid expiry count list of group ids */ - int uid; + uid_t uid; struct passwd *pw; gid_t glist[100], *groups = glist; int ngroups = 100; @@ -136,7 +136,7 @@ void auth_unix_gid(FILE *f) return; cp = lbuf; - if (qword_get_int(&cp, &uid) != 0) + if (qword_get_uint(&cp, &uid) != 0) return; pw = getpwuid(uid); @@ -153,14 +153,14 @@ void auth_unix_gid(FILE *f) groups, &ngroups); } } - qword_printint(f, uid); - qword_printint(f, time(0)+30*60); + qword_printuint(f, uid); + qword_printuint(f, time(0)+30*60); if (rv >= 0) { - qword_printint(f, ngroups); + qword_printuint(f, ngroups); for (i=0; im_export.e_flags & NFSEXP_CROSSMOUNT) { static nfs_export *prev = NULL; @@ -461,10 +506,14 @@ void nfsd_fh(FILE *f) continue; check_uuid: if (exp->m_export.e_uuid) - get_uuid(NULL, exp->m_export.e_uuid, + get_uuid(exp->m_export.e_uuid, uuidlen, u); - else if (get_uuid(path, NULL, uuidlen, u) == 0) - continue; + else + for (type = 0; + uuid_by_path(path, type, uuidlen, u); + type++) + if (memcmp(u, fhuuid, uuidlen) != 0) + break; if (memcmp(u, fhuuid, uuidlen) != 0) continue; @@ -600,13 +649,13 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex write_secinfo(f, exp, flag_mask); if (exp->e_uuid == NULL || different_fs) { char u[16]; - if (get_uuid(path, NULL, 16, u)) { + if (uuid_by_path(path, 0, 16, u)) { qword_print(f, "uuid"); qword_printhex(f, u, 16); } } else { char u[16]; - get_uuid(NULL, exp->e_uuid, 16, u); + get_uuid(exp->e_uuid, 16, u); qword_print(f, "uuid"); qword_printhex(f, u, 16); } @@ -614,73 +663,54 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex return qword_eol(f); } -void nfsd_export(FILE *f) +static int is_subdirectory(char *child, char *parent) { - /* requests are: - * domain path - * determine export options and return: - * domain path expiry flags anonuid anongid fsid - */ + int l = strlen(parent); - char *cp; - int i; - char *dom, *path; - nfs_export *exp, *found = NULL; - int found_type = 0; - struct in_addr addr; - struct hostent *he = NULL; - - - if (readline(fileno(f), &lbuf, &lbuflen) != 1) - return; - - xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf); + return strcmp(child, parent) == 0 + || (strncmp(child, parent, l) == 0 && child[l] == '/'); +} - cp = lbuf; - dom = malloc(strlen(cp)); - path = malloc(strlen(cp)); +static int path_matches(nfs_export *exp, char *path) +{ + if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) + return is_subdirectory(path, exp->m_export.e_path); + return strcmp(path, exp->m_export.e_path) == 0; +} - if (!dom || !path) - goto out; +static int client_matches(nfs_export *exp, char *dom, struct hostent *he) +{ + if (use_ipaddr) + return client_check(exp->m_client, he); + return client_member(dom, exp->m_client->m_hostname); +} - if (qword_get(&cp, dom, strlen(lbuf)) <= 0) - goto out; - if (qword_get(&cp, path, strlen(lbuf)) <= 0) - goto out; +static int export_matches(nfs_export *exp, char *dom, char *path, struct hostent *he) +{ + return path_matches(exp, path) && client_matches(exp, dom, he); +} - auth_reload(); +static nfs_export *lookup_export(char *dom, char *path, struct hostent *he) +{ + nfs_export *exp; + nfs_export *found = NULL; + int found_type = 0; + int i; - /* now find flags for this export point in this domain */ for (i=0 ; i < MCL_MAXTYPES; i++) { for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { - if (!use_ipaddr && !client_member(dom, exp->m_client->m_hostname)) - continue; - if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) { - /* if path is a mountpoint below e_path, then OK */ - int l = strlen(exp->m_export.e_path); - if (strcmp(path, exp->m_export.e_path) == 0 || - (strncmp(path, exp->m_export.e_path, l) == 0 && - path[l] == '/' && - is_mountpoint(path))) - /* ok */; - else - continue; - } else if (strcmp(path, exp->m_export.e_path) != 0) + if (!export_matches(exp, dom, path, he)) continue; - if (use_ipaddr) { - if (he == NULL) { - if (!inet_aton(dom, &addr)) - goto out; - he = client_resolve(addr); - } - if (!client_check(exp->m_client, he)) - continue; - } if (!found) { found = exp; found_type = i; continue; } + + /* Always prefer non-V4ROOT mounts */ + if (found->m_export.e_flags & NFSEXP_V4ROOT) + continue; + /* If one is a CROSSMOUNT, then prefer the longest path */ if (((found->m_export.e_flags & NFSEXP_CROSSMOUNT) || (exp->m_export.e_flags & NFSEXP_CROSSMOUNT)) && @@ -703,6 +733,50 @@ void nfsd_export(FILE *f) } } } + return found; +} + +void nfsd_export(FILE *f) +{ + /* requests are: + * domain path + * determine export options and return: + * domain path expiry flags anonuid anongid fsid + */ + + char *cp; + char *dom, *path; + nfs_export *found = NULL; + struct in_addr addr; + struct hostent *he = NULL; + + + if (readline(fileno(f), &lbuf, &lbuflen) != 1) + return; + + xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf); + + cp = lbuf; + dom = malloc(strlen(cp)); + path = malloc(strlen(cp)); + + if (!dom || !path) + goto out; + + if (qword_get(&cp, dom, strlen(lbuf)) <= 0) + goto out; + if (qword_get(&cp, path, strlen(lbuf)) <= 0) + goto out; + + auth_reload(); + + if (use_ipaddr) { + if (!inet_aton(dom, &addr)) + goto out; + he = client_resolve(addr); + } + + found = lookup_export(dom, path, he); if (found) { if (dump_to_cache(f, dom, path, &found->m_export) < 0) { @@ -838,6 +912,7 @@ int cache_export_ent(char *domain, struct exportent *exp, char *path) int cache_export(nfs_export *exp, char *path) { + char buf[INET_ADDRSTRLEN]; int err; FILE *f; @@ -845,8 +920,10 @@ int cache_export(nfs_export *exp, char *path) if (!f) return -1; + qword_print(f, "nfsd"); - qword_print(f, inet_ntoa(exp->m_client->m_addrlist[0])); + qword_print(f, + host_ntop(get_addrlist(exp->m_client, 0), buf, sizeof(buf))); qword_printint(f, time(0)+30*60); qword_print(f, exp->m_client->m_hostname); err = qword_eol(f);