From 482fb94e1b0c2efe8258334aa2a68d4f4a91de9c Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 12 Feb 2007 00:53:29 -0800 Subject: [PATCH] knfsd: SUNRPC: allow creating an RPC service without registering with portmapper Sometimes we need to create an RPC service but not register it with the local portmapper. NFSv4 delegation callback, for example. Change the svc_makesock() API to allow optionally creating temporary or permanent sockets, optionally registering with the local portmapper, and make it return the ephemeral port of the new socket. Signed-off-by: Chuck Lever Cc: Aurelien Charbon Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/lockd/svc.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 8ca18085e68d..2c3d5ac4a3b6 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -223,23 +223,29 @@ static int find_socket(struct svc_serv *serv, int proto) return found; } +/* + * Make any sockets that are needed but not present. + * If nlm_udpport or nlm_tcpport were set as module + * options, make those sockets unconditionally + */ static int make_socks(struct svc_serv *serv, int proto) { - /* Make any sockets that are needed but not present. - * If nlm_udpport or nlm_tcpport were set as module - * options, make those sockets unconditionally - */ - static int warned; + static int warned; int err = 0; + if (proto == IPPROTO_UDP || nlm_udpport) if (!find_socket(serv, IPPROTO_UDP)) - err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport); - if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport)) + err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport, + SVC_SOCK_DEFAULTS); + if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) if (!find_socket(serv, IPPROTO_TCP)) - err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport); - if (!err) + err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport, + SVC_SOCK_DEFAULTS); + + if (err >= 0) { warned = 0; - else if (warned++ == 0) + err = 0; + } else if (warned++ == 0) printk(KERN_WARNING "lockd_up: makesock failed, error=%d\n", err); return err; -- cgit v1.2.3 From ad06e4bd62351bc569cca0f25d68c58dbd298146 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 12 Feb 2007 00:53:32 -0800 Subject: [PATCH] knfsd: SUNRPC: Add a function to format the address in an svc_rqst for printing There are loads of places where the RPC server assumes that the rq_addr fields contains an IPv4 address. Top among these are error and debugging messages that display the server's IP address. Let's refactor the address printing into a separate function that's smart enough to figure out the difference between IPv4 and IPv6 addresses. Signed-off-by: Chuck Lever Cc: Aurelien Charbon Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/lockd/svc.c | 6 ++-- fs/lockd/svc4proc.c | 7 ++--- fs/lockd/svcproc.c | 7 ++--- fs/nfs/callback.c | 12 ++++++-- fs/nfsd/nfsfh.c | 7 +++-- fs/nfsd/nfsproc.c | 7 +++-- include/linux/sunrpc/svc.h | 3 ++ net/sunrpc/svcsock.c | 76 ++++++++++++++++++++++++++++++++++------------ 8 files changed, 86 insertions(+), 39 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 2c3d5ac4a3b6..80fcacc1acf9 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -141,6 +141,7 @@ lockd(struct svc_rqst *rqstp) */ while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) { long timeout = MAX_SCHEDULE_TIMEOUT; + char buf[RPC_MAX_ADDRBUFLEN]; if (signalled()) { flush_signals(current); @@ -175,11 +176,10 @@ lockd(struct svc_rqst *rqstp) break; } - dprintk("lockd: request from %08x\n", - (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr)); + dprintk("lockd: request from %s\n", + svc_print_addr(rqstp, buf, sizeof(buf))); svc_process(rqstp); - } flush_signals(current); diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index f67146a8199a..9b591bc18341 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -426,10 +426,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, dprintk("lockd: SM_NOTIFY called\n"); if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) || ntohs(saddr.sin_port) >= 1024) { - printk(KERN_WARNING - "lockd: rejected NSM callback from %08x:%d\n", - ntohl(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port)); + char buf[RPC_MAX_ADDRBUFLEN]; + printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", + svc_print_addr(rqstp, buf, sizeof(buf))); return rpc_system_err; } diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 3707c3a23e93..f590304d93bf 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -457,10 +457,9 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, dprintk("lockd: SM_NOTIFY called\n"); if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) || ntohs(saddr.sin_port) >= 1024) { - printk(KERN_WARNING - "lockd: rejected NSM callback from %08x:%d\n", - ntohl(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port)); + char buf[RPC_MAX_ADDRBUFLEN]; + printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", + svc_print_addr(rqstp, buf, sizeof(buf))); return rpc_system_err; } diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index a070109fa6c7..8c790af85984 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -71,6 +71,8 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) complete(&nfs_callback_info.started); for(;;) { + char buf[RPC_MAX_ADDRBUFLEN]; + if (signalled()) { if (nfs_callback_info.users == 0) break; @@ -88,8 +90,8 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) __FUNCTION__, -err); break; } - dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__, - NIPQUAD(rqstp->rq_addr.sin_addr.s_addr)); + dprintk("%s: request from %s\n", __FUNCTION__, + svc_print_addr(rqstp, buf, sizeof(buf))); svc_process(rqstp); } @@ -166,13 +168,17 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp) { struct sockaddr_in *addr = &rqstp->rq_addr; struct nfs_client *clp; + char buf[RPC_MAX_ADDRBUFLEN]; /* Don't talk to strangers */ clp = nfs_find_client(addr, 4); if (clp == NULL) return SVC_DROP; - dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr)); + + dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__, + svc_print_addr(rqstp, buf, sizeof(buf))); nfs_put_client(clp); + switch (rqstp->rq_authop->flavour) { case RPC_AUTH_NULL: if (rqstp->rq_proc != CB_NULL) diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index c59d6fbb7a6b..a0b4282cb284 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -180,10 +181,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) /* Check if the request originated from a secure port. */ error = nfserr_perm; if (!rqstp->rq_secure && EX_SECURE(exp)) { + char buf[RPC_MAX_ADDRBUFLEN]; printk(KERN_WARNING - "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n", - NIPQUAD(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port)); + "nfsd: request from insecure port %s!\n", + svc_print_addr(rqstp, buf, sizeof(buf))); goto out; } diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index ec983b777680..5cc2eec981b8 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -147,10 +148,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, */ if (NFSSVC_MAXBLKSIZE_V2 < argp->count) { + char buf[RPC_MAX_ADDRBUFLEN]; printk(KERN_NOTICE - "oversized read request from %u.%u.%u.%u:%d (%d bytes)\n", - NIPQUAD(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port), + "oversized read request from %s (%d bytes)\n", + svc_print_addr(rqstp, buf, sizeof(buf)), argp->count); argp->count = NFSSVC_MAXBLKSIZE_V2; } diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 64f3d60c72af..1178689b9156 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -368,5 +368,8 @@ int svc_register(struct svc_serv *, int, unsigned short); void svc_wake_up(struct svc_serv *); void svc_reserve(struct svc_rqst *rqstp, int space); struct svc_pool * svc_pool_for_cpu(struct svc_serv *serv, int cpu); +char * svc_print_addr(struct svc_rqst *, char *, size_t); + +#define RPC_MAX_ADDRBUFLEN (63U) #endif /* SUNRPC_SVC_H */ diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index a98be09768a0..08de328ce433 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -121,6 +122,41 @@ static inline void svc_reclassify_socket(struct socket *sock) } #endif +static char *__svc_print_addr(struct sockaddr *addr, char *buf, size_t len) +{ + switch (addr->sa_family) { + case AF_INET: + snprintf(buf, len, "%u.%u.%u.%u, port=%u", + NIPQUAD(((struct sockaddr_in *) addr)->sin_addr), + htons(((struct sockaddr_in *) addr)->sin_port)); + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x, port=%u", + NIP6(((struct sockaddr_in6 *) addr)->sin6_addr), + htons(((struct sockaddr_in6 *) addr)->sin6_port)); + break; +#endif + default: + snprintf(buf, len, "unknown address type: %d", addr->sa_family); + break; + } + return buf; +} + +/** + * svc_print_addr - Format rq_addr field for printing + * @rqstp: svc_rqst struct containing address to print + * @buf: target buffer for formatted address + * @len: length of target buffer + * + */ +char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len) +{ + return __svc_print_addr((struct sockaddr *) &rqstp->rq_addr, buf, len); +} +EXPORT_SYMBOL_GPL(svc_print_addr); + /* * Queue up an idle server thread. Must have pool->sp_lock held. * Note: this is really a stack rather than a queue, so that we only @@ -429,6 +465,7 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) size_t base = xdr->page_base; unsigned int pglen = xdr->page_len; unsigned int flags = MSG_MORE; + char buf[RPC_MAX_ADDRBUFLEN]; slen = xdr->len; @@ -491,9 +528,9 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) len += result; } out: - dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %x)\n", - rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, xdr->len, len, - rqstp->rq_addr.sin_addr.s_addr); + dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s)\n", + rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, + xdr->len, len, svc_print_addr(rqstp, buf, sizeof(buf))); return len; } @@ -878,6 +915,7 @@ svc_tcp_accept(struct svc_sock *svsk) struct socket *newsock; struct svc_sock *newsvsk; int err, slen; + char buf[RPC_MAX_ADDRBUFLEN]; dprintk("svc: tcp_accept %p sock %p\n", svsk, sock); if (!sock) @@ -908,18 +946,19 @@ svc_tcp_accept(struct svc_sock *svsk) } /* Ideally, we would want to reject connections from unauthorized - * hosts here, but when we get encription, the IP of the host won't - * tell us anything. For now just warn about unpriv connections. + * hosts here, but when we get encryption, the IP of the host won't + * tell us anything. For now just warn about unpriv connections. */ if (ntohs(sin.sin_port) >= 1024) { dprintk(KERN_WARNING - "%s: connect from unprivileged port: %u.%u.%u.%u:%d\n", + "%s: connect from unprivileged port: %s\n", serv->sv_name, - NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); + __svc_print_addr((struct sockaddr *) &sin, buf, + sizeof(buf))); } - - dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name, - NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); + dprintk("%s: connect from %s\n", serv->sv_name, + __svc_print_addr((struct sockaddr *) &sin, buf, + sizeof(buf))); /* make sure that a write doesn't block forever when * low on memory @@ -955,11 +994,9 @@ svc_tcp_accept(struct svc_sock *svsk) "sockets, consider increasing the " "number of nfsd threads\n", serv->sv_name); - printk(KERN_NOTICE "%s: last TCP connect from " - "%u.%u.%u.%u:%d\n", - serv->sv_name, - NIPQUAD(sin.sin_addr.s_addr), - ntohs(sin.sin_port)); + printk(KERN_NOTICE + "%s: last TCP connect from %s\n", + serv->sv_name, buf); } /* * Always select the oldest socket. It's not fair, @@ -1587,11 +1624,12 @@ static int svc_create_socket(struct svc_serv *serv, int protocol, struct socket *sock; int error; int type; + char buf[RPC_MAX_ADDRBUFLEN]; - dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n", - serv->sv_program->pg_name, protocol, - NIPQUAD(sin->sin_addr.s_addr), - ntohs(sin->sin_port)); + dprintk("svc: svc_create_socket(%s, %d, %s)\n", + serv->sv_program->pg_name, protocol, + __svc_print_addr((struct sockaddr *) sin, buf, + sizeof(buf))); if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) { printk(KERN_WARNING "svc: only UDP and TCP " -- cgit v1.2.3 From 27459f0940e16c68e080f5fc7e85aa9eb3f74528 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 12 Feb 2007 00:53:34 -0800 Subject: [PATCH] knfsd: SUNRPC: Provide room in svc_rqst for larger addresses 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 Cc: Aurelien Charbon Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/lockd/host.c | 2 +- fs/lockd/svc4proc.c | 6 ++++-- fs/lockd/svcproc.c | 6 ++++-- fs/nfs/callback.c | 2 +- fs/nfs/callback_xdr.c | 4 ++-- fs/nfsd/nfs4state.c | 18 +++++++++--------- fs/nfsd/nfscache.c | 2 +- include/linux/sunrpc/svc.h | 17 +++++++++++++++-- net/sunrpc/svcauth_unix.c | 3 ++- net/sunrpc/svcsock.c | 19 ++++++++++++------- 10 files changed, 51 insertions(+), 28 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 3d4610c2a266..22d403208973 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -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); } diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 9b591bc18341..47a66aa5d55b 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -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) diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index f590304d93bf..31cb48425733 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -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) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 8c790af85984..75f309c8741a 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -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]; diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index f8ea1f51f590..849a2029975d 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -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; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9de89df961f4..9e4067999209 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -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) && diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index f90d70475854..578f2c9d56be 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -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; diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 52db9c8985c5..96c1b6ae7d96 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -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 */ diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 987244f95909..4b775dbf580d 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -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; diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 6680e0f0560d..b11669670baa 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -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) -- cgit v1.2.3