rpc: pass target name down to rpc level on callbacks
authorOlga Kornievskaia <aglo@citi.umich.edu>
Tue, 23 Dec 2008 21:17:40 +0000 (16:17 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 23 Dec 2008 21:17:40 +0000 (16:17 -0500)
The rpc client needs to know the principal that the setclientid was done
as, so it can tell gssd who to authenticate to.

Signed-off-by: Olga Kornievskaia <aglo@citi.umich.edu>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfsd/nfs4callback.c
include/linux/sunrpc/clnt.h
net/sunrpc/clnt.c

index 094747a..3ca1417 100644 (file)
@@ -384,6 +384,7 @@ static int do_probe_callback(void *data)
                .version        = nfs_cb_version[1]->number,
                .authflavor     = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
                .flags          = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
+               .client_name    = clp->cl_principal,
        };
        struct rpc_message msg = {
                .rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
@@ -392,6 +393,11 @@ static int do_probe_callback(void *data)
        struct rpc_clnt *client;
        int status;
 
+       if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) {
+               status = nfserr_cb_path_down;
+               goto out_err;
+       }
+
        /* Initialize address */
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
index 6f0ee1b..c39a210 100644 (file)
@@ -58,6 +58,7 @@ struct rpc_clnt {
        struct rpc_timeout      cl_timeout_default;
        struct rpc_program *    cl_program;
        char                    cl_inline_name[32];
+       char                    *cl_principal;  /* target to authenticate to */
 };
 
 /*
@@ -108,6 +109,7 @@ struct rpc_create_args {
        u32                     version;
        rpc_authflavor_t        authflavor;
        unsigned long           flags;
+       char                    *client_name;
 };
 
 /* Values for "flags" field */
index 4895c34..347f2a2 100644 (file)
@@ -197,6 +197,12 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
 
        clnt->cl_rtt = &clnt->cl_rtt_default;
        rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval);
+       clnt->cl_principal = NULL;
+       if (args->client_name) {
+               clnt->cl_principal = kstrdup(args->client_name, GFP_KERNEL);
+               if (!clnt->cl_principal)
+                       goto out_no_principal;
+       }
 
        kref_init(&clnt->cl_kref);
 
@@ -226,6 +232,8 @@ out_no_auth:
                rpc_put_mount();
        }
 out_no_path:
+       kfree(clnt->cl_principal);
+out_no_principal:
        rpc_free_iostats(clnt->cl_metrics);
 out_no_stats:
        if (clnt->cl_server != clnt->cl_inline_name)
@@ -354,6 +362,11 @@ rpc_clone_client(struct rpc_clnt *clnt)
        new->cl_metrics = rpc_alloc_iostats(clnt);
        if (new->cl_metrics == NULL)
                goto out_no_stats;
+       if (clnt->cl_principal) {
+               new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL);
+               if (new->cl_principal == NULL)
+                       goto out_no_principal;
+       }
        kref_init(&new->cl_kref);
        err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
        if (err != 0)
@@ -366,6 +379,8 @@ rpc_clone_client(struct rpc_clnt *clnt)
        rpciod_up();
        return new;
 out_no_path:
+       kfree(new->cl_principal);
+out_no_principal:
        rpc_free_iostats(new->cl_metrics);
 out_no_stats:
        kfree(new);
@@ -417,6 +432,7 @@ rpc_free_client(struct kref *kref)
 out_free:
        rpc_unregister_client(clnt);
        rpc_free_iostats(clnt->cl_metrics);
+       kfree(clnt->cl_principal);
        clnt->cl_metrics = NULL;
        xprt_put(clnt->cl_xprt);
        rpciod_down();