[PATCH] knfsd: SUNRPC: Provide room in svc_rqst for larger addresses
authorChuck Lever <chuck.lever@oracle.com>
Mon, 12 Feb 2007 08:53:34 +0000 (00:53 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 12 Feb 2007 17:48:36 +0000 (09:48 -0800)
Expand the rq_addr field to allow it to contain larger addresses.

Specifically, we replace a 'sockaddr_in' with a 'sockaddr_storage', then
everywhere the 'sockaddr_in' was referenced, we use instead an accessor
function (svc_addr_in) which safely casts the _storage to _in.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon@ext.bull.net>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/lockd/host.c
fs/lockd/svc4proc.c
fs/lockd/svcproc.c
fs/nfs/callback.c
fs/nfs/callback_xdr.c
fs/nfsd/nfs4state.c
fs/nfsd/nfscache.c
include/linux/sunrpc/svc.h
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c

index 3d4610c2a2665f9ce7236988f6bd40c52d3623bd..22d40320897362823803b0e3a0059d086f9cc1ab 100644 (file)
@@ -192,7 +192,7 @@ struct nlm_host *
 nlmsvc_lookup_host(struct svc_rqst *rqstp,
                        const char *hostname, int hostname_len)
 {
-       return nlm_lookup_host(1, &rqstp->rq_addr,
+       return nlm_lookup_host(1, svc_addr_in(rqstp),
                               rqstp->rq_prot, rqstp->rq_vers,
                               hostname, hostname_len);
 }
index 9b591bc18341665a94cbaf89795e2e76d48cf572..47a66aa5d55b479c52a4ec5ce59f6bbb8c84df85 100644 (file)
@@ -224,7 +224,7 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        dprintk("lockd: GRANTED       called\n");
-       resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+       resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
        dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
        return rpc_success;
 }
@@ -421,7 +421,9 @@ static __be32
 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
                                              void              *resp)
 {
-       struct sockaddr_in      saddr = rqstp->rq_addr;
+       struct sockaddr_in      saddr;
+
+       memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
 
        dprintk("lockd: SM_NOTIFY     called\n");
        if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
index f590304d93bf25c046a519e911a4859977f82225..31cb48425733033529d4a7e7ba63014773b1226b 100644 (file)
@@ -253,7 +253,7 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        dprintk("lockd: GRANTED       called\n");
-       resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+       resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
        dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
        return rpc_success;
 }
@@ -452,7 +452,9 @@ static __be32
 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
                                              void              *resp)
 {
-       struct sockaddr_in      saddr = rqstp->rq_addr;
+       struct sockaddr_in      saddr;
+
+       memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
 
        dprintk("lockd: SM_NOTIFY     called\n");
        if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
index 8c790af85984a8a8e11dcc3835eebde80aa85001..75f309c8741a066ff8c7b8443452a4b8d98b8740 100644 (file)
@@ -166,7 +166,7 @@ void nfs_callback_down(void)
 
 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
 {
-       struct sockaddr_in *addr = &rqstp->rq_addr;
+       struct sockaddr_in *addr = svc_addr_in(rqstp);
        struct nfs_client *clp;
        char buf[RPC_MAX_ADDRBUFLEN];
 
index f8ea1f51f59094ad69ac7ec684884f5a05df7312..849a2029975da9ddc1fac7f1da14fb52561c1106 100644 (file)
@@ -176,7 +176,7 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr
        status = decode_fh(xdr, &args->fh);
        if (unlikely(status != 0))
                goto out;
-       args->addr = &rqstp->rq_addr;
+       args->addr = svc_addr_in(rqstp);
        status = decode_bitmap(xdr, args->bitmap);
 out:
        dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
@@ -188,7 +188,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        __be32 *p;
        __be32 status;
 
-       args->addr = &rqstp->rq_addr;
+       args->addr = svc_addr_in(rqstp);
        status = decode_stateid(xdr, &args->stateid);
        if (unlikely(status != 0))
                goto out;
index 9de89df961f42afe3ddd4c79dcc61a9b8aa634b9..9e4067999209e4bd847f334ab121f1b2bd4deef5 100644 (file)
@@ -714,7 +714,7 @@ __be32
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                  struct nfsd4_setclientid *setclid)
 {
-       __be32                  ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+       struct sockaddr_in      *sin = svc_addr_in(rqstp);
        struct xdr_netobj       clname = { 
                .len = setclid->se_namelen,
                .data = setclid->se_name,
@@ -749,7 +749,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                 */
                status = nfserr_clid_inuse;
                if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
-                               || conf->cl_addr != ip_addr) {
+                               || conf->cl_addr != sin->sin_addr.s_addr) {
                        printk("NFSD: setclientid: string in use by client"
                        "(clientid %08x/%08x)\n",
                        conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
@@ -769,7 +769,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                if (new == NULL)
                        goto out;
                copy_verf(new, &clverifier);
-               new->cl_addr = ip_addr;
+               new->cl_addr = sin->sin_addr.s_addr;
                copy_cred(&new->cl_cred,&rqstp->rq_cred);
                gen_clid(new);
                gen_confirm(new);
@@ -801,7 +801,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                if (new == NULL)
                        goto out;
                copy_verf(new,&conf->cl_verifier);
-               new->cl_addr = ip_addr;
+               new->cl_addr = sin->sin_addr.s_addr;
                copy_cred(&new->cl_cred,&rqstp->rq_cred);
                copy_clid(new, conf);
                gen_confirm(new);
@@ -820,7 +820,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                if (new == NULL)
                        goto out;
                copy_verf(new,&clverifier);
-               new->cl_addr = ip_addr;
+               new->cl_addr = sin->sin_addr.s_addr;
                copy_cred(&new->cl_cred,&rqstp->rq_cred);
                gen_clid(new);
                gen_confirm(new);
@@ -847,7 +847,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                if (new == NULL)
                        goto out;
                copy_verf(new,&clverifier);
-               new->cl_addr = ip_addr;
+               new->cl_addr = sin->sin_addr.s_addr;
                copy_cred(&new->cl_cred,&rqstp->rq_cred);
                gen_clid(new);
                gen_confirm(new);
@@ -881,7 +881,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                         struct nfsd4_compound_state *cstate,
                         struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
-       __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+       struct sockaddr_in *sin = svc_addr_in(rqstp);
        struct nfs4_client *conf, *unconf;
        nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
        clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -900,9 +900,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
        unconf = find_unconfirmed_client(clid);
 
        status = nfserr_clid_inuse;
-       if (conf && conf->cl_addr != ip_addr)
+       if (conf && conf->cl_addr != sin->sin_addr.s_addr)
                goto out;
-       if (unconf && unconf->cl_addr != ip_addr)
+       if (unconf && unconf->cl_addr != sin->sin_addr.s_addr)
                goto out;
 
        if ((conf && unconf) && 
index f90d70475854f5b85f2f20a5bc61a1821a6cae37..578f2c9d56bec09899d4dc1c0ca135320e7c6bf9 100644 (file)
@@ -185,7 +185,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
        rp->c_state = RC_INPROG;
        rp->c_xid = xid;
        rp->c_proc = proc;
-       rp->c_addr = rqstp->rq_addr;
+       memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr));
        rp->c_prot = proto;
        rp->c_vers = vers;
        rp->c_timestamp = jiffies;
index 52db9c8985c59a4778601f741e3f074ea05013cb..96c1b6ae7d96db95bfc5299f70545cec3c5fd571 100644 (file)
@@ -200,8 +200,8 @@ struct svc_rqst {
        struct list_head        rq_list;        /* idle list */
        struct list_head        rq_all;         /* all threads list */
        struct svc_sock *       rq_sock;        /* socket */
-       struct sockaddr_in      rq_addr;        /* peer address */
-       int                     rq_addrlen;
+       struct sockaddr_storage rq_addr;        /* peer address */
+       size_t                  rq_addrlen;
 
        struct svc_serv *       rq_server;      /* RPC service definition */
        struct svc_pool *       rq_pool;        /* thread pool */
@@ -255,6 +255,19 @@ struct svc_rqst {
        struct task_struct      *rq_task;       /* service thread */
 };
 
+/*
+ * Rigorous type checking on sockaddr type conversions
+ */
+static inline struct sockaddr_in *svc_addr_in(struct svc_rqst *rqst)
+{
+       return (struct sockaddr_in *) &rqst->rq_addr;
+}
+
+static inline struct sockaddr *svc_addr(struct svc_rqst *rqst)
+{
+       return (struct sockaddr *) &rqst->rq_addr;
+}
+
 /*
  * Check buffer bounds after decoding arguments
  */
index 987244f95909e9d89477d49b080a9b01d4a7f649..4b775dbf580d819f852afa62be6e4901b93452b4 100644 (file)
@@ -421,6 +421,7 @@ svcauth_unix_info_release(void *info)
 static int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
+       struct sockaddr_in *sin = svc_addr_in(rqstp);
        struct ip_map *ipm;
 
        rqstp->rq_client = NULL;
@@ -430,7 +431,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
        ipm = ip_map_cached_get(rqstp);
        if (ipm == NULL)
                ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
-                                   rqstp->rq_addr.sin_addr);
+                                   sin->sin_addr);
 
        if (ipm == NULL)
                return SVC_DENIED;
index 6680e0f0560de88caf9992bcddd5e1ea6ac89edf..b11669670baa406614f458633cf1daeac1f5c8b9 100644 (file)
@@ -153,7 +153,7 @@ static char *__svc_print_addr(struct sockaddr *addr, char *buf, size_t len)
  */
 char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len)
 {
-       return __svc_print_addr((struct sockaddr *) &rqstp->rq_addr, buf, len);
+       return __svc_print_addr(svc_addr(rqstp), buf, len);
 }
 EXPORT_SYMBOL_GPL(svc_print_addr);
 
@@ -473,7 +473,7 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
                /* set the source and destination */
                struct msghdr   msg;
                msg.msg_name    = &rqstp->rq_addr;
-               msg.msg_namelen = sizeof(rqstp->rq_addr);
+               msg.msg_namelen = rqstp->rq_addrlen;
                msg.msg_iov     = NULL;
                msg.msg_iovlen  = 0;
                msg.msg_flags   = MSG_MORE;
@@ -696,6 +696,7 @@ svc_write_space(struct sock *sk)
 static int
 svc_udp_recvfrom(struct svc_rqst *rqstp)
 {
+       struct sockaddr_in *sin = svc_addr_in(rqstp);
        struct svc_sock *svsk = rqstp->rq_sock;
        struct svc_serv *serv = svsk->sk_server;
        struct sk_buff  *skb;
@@ -756,9 +757,12 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
        rqstp->rq_prot        = IPPROTO_UDP;
 
        /* Get sender address */
-       rqstp->rq_addr.sin_family = AF_INET;
-       rqstp->rq_addr.sin_port = skb->h.uh->source;
-       rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
+       sin->sin_family = AF_INET;
+       sin->sin_port = skb->h.uh->source;
+       sin->sin_addr.s_addr = skb->nh.iph->saddr;
+       rqstp->rq_addrlen = sizeof(struct sockaddr_in);
+
+       /* Remember which interface received this request */
        rqstp->rq_daddr = skb->nh.iph->daddr;
 
        if (skb_is_nonlinear(skb)) {
@@ -1298,7 +1302,8 @@ svc_sock_update_bufs(struct svc_serv *serv)
 int
 svc_recv(struct svc_rqst *rqstp, long timeout)
 {
-       struct svc_sock         *svsk =NULL;
+       struct svc_sock         *svsk = NULL;
+       struct sockaddr_in      *sin = svc_addr_in(rqstp);
        struct svc_serv         *serv = rqstp->rq_server;
        struct svc_pool         *pool = rqstp->rq_pool;
        int                     len, i;
@@ -1395,7 +1400,7 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
        svsk->sk_lastrecv = get_seconds();
        clear_bit(SK_OLD, &svsk->sk_flags);
 
-       rqstp->rq_secure  = ntohs(rqstp->rq_addr.sin_port) < 1024;
+       rqstp->rq_secure = ntohs(sin->sin_port) < PROT_SOCK;
        rqstp->rq_chandle.defer = svc_defer;
 
        if (serv->sv_stats)