knfsd: nfsd: set rq_client to ip-address-determined-domain
[safe/jmp/linux-2.6] / fs / nfsd / export.c
index d4accdc..ac225a7 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/nfsd/nfsfh.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/lockd/bind.h>
+#include <linux/sunrpc/msg_prot.h>
+#include <linux/sunrpc/gss_api.h>
 
 #define NFSDDBG_FACILITY       NFSDDBG_EXPORT
 
@@ -452,8 +454,48 @@ out_free_all:
        return err;
 }
 
+static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
+{
+       int listsize, err;
+       struct exp_flavor_info *f;
+
+       err = get_int(mesg, &listsize);
+       if (err)
+               return err;
+       if (listsize < 0 || listsize > MAX_SECINFO_LIST)
+               return -EINVAL;
+
+       for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
+               err = get_int(mesg, &f->pseudoflavor);
+               if (err)
+                       return err;
+               /*
+                * Just a quick sanity check; we could also try to check
+                * whether this pseudoflavor is supported, but at worst
+                * an unsupported pseudoflavor on the export would just
+                * be a pseudoflavor that won't match the flavor of any
+                * authenticated request.  The administrator will
+                * probably discover the problem when someone fails to
+                * authenticate.
+                */
+               if (f->pseudoflavor < 0)
+                       return -EINVAL;
+               err = get_int(mesg, &f->flags);
+               if (err)
+                       return err;
+               /* Only some flags are allowed to differ between flavors: */
+               if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags))
+                       return -EINVAL;
+       }
+       exp->ex_nflavors = listsize;
+       return 0;
+}
+
 #else /* CONFIG_NFSD_V4 */
-static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; }
+static inline int
+fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;}
+static inline int
+secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
 #endif
 
 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
@@ -477,6 +519,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
 
        exp.ex_uuid = NULL;
 
+       /* secinfo */
+       exp.ex_nflavors = 0;
+
        if (mesg[mlen-1] != '\n')
                return -EINVAL;
        mesg[mlen-1] = 0;
@@ -554,7 +599,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
                                        if (exp.ex_uuid == NULL)
                                                err = -ENOMEM;
                                }
-                       } else
+                       } else if (strcmp(buf, "secinfo") == 0)
+                               err = secinfo_parse(&mesg, buf, &exp);
+                       else
                                /* quietly ignore unknown words and anything
                                 * following. Newer user-space can try to set
                                 * new values, then see what the result was.
@@ -655,6 +702,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
 {
        struct svc_export *new = container_of(cnew, struct svc_export, h);
        struct svc_export *item = container_of(citem, struct svc_export, h);
+       int i;
 
        new->ex_flags = item->ex_flags;
        new->ex_anon_uid = item->ex_anon_uid;
@@ -670,6 +718,10 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
        item->ex_fslocs.locations_count = 0;
        new->ex_fslocs.migrated = item->ex_fslocs.migrated;
        item->ex_fslocs.migrated = 0;
+       new->ex_nflavors = item->ex_nflavors;
+       for (i = 0; i < MAX_SECINFO_LIST; i++) {
+               new->ex_flavors[i] = item->ex_flavors[i];
+       }
 }
 
 static struct cache_head *svc_export_alloc(void)
@@ -1176,6 +1228,39 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
        return exp;
 }
 
+/*
+ * Called from functions that handle requests; functions that do work on
+ * behalf of mountd are passed a single client name to use, and should
+ * use exp_get_by_name() or exp_find().
+ */
+struct svc_export *
+rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+               struct dentry *dentry)
+{
+       struct auth_domain *clp;
+
+       clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+       return exp_get_by_name(clp, mnt, dentry, &rqstp->rq_chandle);
+}
+
+struct svc_export *
+rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
+{
+       struct auth_domain *clp;
+
+       clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+       return exp_find(clp, fsid_type, fsidv, &rqstp->rq_chandle);
+}
+
+struct svc_export *
+rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
+               struct dentry *dentry)
+{
+       struct auth_domain *clp;
+
+       clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+       return exp_parent(rqstp->rq_client, mnt, dentry, &rqstp->rq_chandle);
+}
 
 /*
  * Called when we need the filehandle for the root of the pseudofs,
@@ -1183,8 +1268,7 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
  * export point with fsid==0
  */
 __be32
-exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
-              struct cache_req *creq)
+exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
 {
        struct svc_export *exp;
        __be32 rv;
@@ -1192,7 +1276,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
 
        mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
 
-       exp = exp_find(clp, FSID_NUM, fsidv, creq);
+       exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
        if (PTR_ERR(exp) == -ENOENT)
                return nfserr_perm;
        if (IS_ERR(exp))