From 0b10bf5e14d856d1d27a2117d07af2bebee81b75 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever@oracle.com> Date: Sun, 9 Aug 2009 15:09:33 -0400 Subject: SUNRPC: Move XDR data type size macros Clean up: To make subsequent patches cleaner, move the XDR data type size macros to the top of the file (similar to nfs4xdr.c) first. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- net/sunrpc/rpcb_clnt.c | 56 ++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'net/sunrpc/rpcb_clnt.c') diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index beee6da33035..ad1d7315c498 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -75,6 +75,37 @@ enum { #define RPCB_OWNER_STRING "0" #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) +/* + * XDR data type sizes + */ +#define RPCB_program_sz (1) +#define RPCB_version_sz (1) +#define RPCB_protocol_sz (1) +#define RPCB_port_sz (1) +#define RPCB_boolean_sz (1) + +#define RPCB_netid_sz (1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) +#define RPCB_addr_sz (1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) +#define RPCB_ownerstring_sz (1 + XDR_QUADLEN(RPCB_MAXOWNERLEN)) + +/* + * XDR argument and result sizes + */ +#define RPCB_mappingargs_sz (RPCB_program_sz + RPCB_version_sz + \ + RPCB_protocol_sz + RPCB_port_sz) +#define RPCB_getaddrargs_sz (RPCB_program_sz + RPCB_version_sz + \ + RPCB_netid_sz + RPCB_addr_sz + \ + RPCB_ownerstring_sz) + +#define RPCB_getportres_sz RPCB_port_sz +#define RPCB_setres_sz RPCB_boolean_sz + +/* + * Note that RFC 1833 does not put any size restrictions on the + * address string returned by the remote rpcbind database. + */ +#define RPCB_getaddrres_sz RPCB_addr_sz + static void rpcb_getport_done(struct rpc_task *, void *); static void rpcb_map_release(void *data); static struct rpc_program rpcb_program; @@ -768,31 +799,6 @@ out_err: return -EIO; } -#define RPCB_program_sz (1u) -#define RPCB_version_sz (1u) -#define RPCB_protocol_sz (1u) -#define RPCB_port_sz (1u) -#define RPCB_boolean_sz (1u) - -#define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) -#define RPCB_addr_sz (1+XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) -#define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) - -#define RPCB_mappingargs_sz RPCB_program_sz+RPCB_version_sz+ \ - RPCB_protocol_sz+RPCB_port_sz -#define RPCB_getaddrargs_sz RPCB_program_sz+RPCB_version_sz+ \ - RPCB_netid_sz+RPCB_addr_sz+ \ - RPCB_ownerstring_sz - -#define RPCB_setres_sz RPCB_boolean_sz -#define RPCB_getportres_sz RPCB_port_sz - -/* - * Note that RFC 1833 does not put any size restrictions on the - * address string returned by the remote rpcbind database. - */ -#define RPCB_getaddrres_sz RPCB_addr_sz - #define PROC(proc, argtype, restype) \ [RPCBPROC_##proc] = { \ .p_proc = RPCBPROC_##proc, \ -- cgit v1.2.3-70-g09d2 From ba809130bc260fce04141aca01ef9e068d32af2a Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever@oracle.com> Date: Sun, 9 Aug 2009 15:09:35 -0400 Subject: SUNRPC: Remove duplicate universal address generation RPC universal address generation is currently done in several places: rpcb_clnt.c, nfs4proc.c xprtsock.c, and xprtrdma.c. Remove the redundant cases that convert a socket address to a universal address. The nfs4proc.c case takes a pre-formatted presentation address string, not a socket address, so we'll leave that one. Because the new uaddr constructor uses the recently introduced rpc_ntop(), it now supports proper "::" shorthanding for IPv6 addresses. This allows the kernel to register properly formed universal addresses with the local rpcbind service, in _all_ cases. The kernel can now also send properly formed universal addresses in RPCB_GETADDR requests, and support link-local properly when encoding and decoding IPv6 addresses. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- include/linux/sunrpc/xprt.h | 1 - net/sunrpc/rpcb_clnt.c | 48 +++++++++++++++++++++++++---------------- net/sunrpc/xprtrdma/transport.c | 8 ------- net/sunrpc/xprtsock.c | 18 ---------------- 4 files changed, 29 insertions(+), 46 deletions(-) (limited to 'net/sunrpc/rpcb_clnt.c') diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 1175d58efc2e..65fad9534d93 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -41,7 +41,6 @@ enum rpc_display_format_t { RPC_DISPLAY_ALL, RPC_DISPLAY_HEX_ADDR, RPC_DISPLAY_HEX_PORT, - RPC_DISPLAY_UNIVERSAL_ADDR, RPC_DISPLAY_NETID, RPC_DISPLAY_MAX, }; diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index ad1d7315c498..1fb1c070c19d 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -153,6 +153,7 @@ static void rpcb_map_release(void *data) rpcb_wake_rpcbind_waiters(map->r_xprt, map->r_status); xprt_put(map->r_xprt); + kfree(map->r_addr); kfree(map); } @@ -299,12 +300,9 @@ static int rpcb_register_inet4(const struct sockaddr *sap, const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; struct rpcbind_args *map = msg->rpc_argp; unsigned short port = ntohs(sin->sin_port); - char buf[32]; + int result; - /* Construct AF_INET universal address */ - snprintf(buf, sizeof(buf), "%pI4.%u.%u", - &sin->sin_addr.s_addr, port >> 8, port & 0xff); - map->r_addr = buf; + map->r_addr = rpc_sockaddr2uaddr(sap); dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " "local rpcbind\n", (port ? "" : "un"), @@ -315,7 +313,9 @@ static int rpcb_register_inet4(const struct sockaddr *sap, if (port) msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; - return rpcb_register_call(RPCBVERS_4, msg); + result = rpcb_register_call(RPCBVERS_4, msg); + kfree(map->r_addr); + return result; } /* @@ -327,16 +327,9 @@ static int rpcb_register_inet6(const struct sockaddr *sap, const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; struct rpcbind_args *map = msg->rpc_argp; unsigned short port = ntohs(sin6->sin6_port); - char buf[64]; + int result; - /* Construct AF_INET6 universal address */ - if (ipv6_addr_any(&sin6->sin6_addr)) - snprintf(buf, sizeof(buf), "::.%u.%u", - port >> 8, port & 0xff); - else - snprintf(buf, sizeof(buf), "%pI6.%u.%u", - &sin6->sin6_addr, port >> 8, port & 0xff); - map->r_addr = buf; + map->r_addr = rpc_sockaddr2uaddr(sap); dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " "local rpcbind\n", (port ? "" : "un"), @@ -347,7 +340,9 @@ static int rpcb_register_inet6(const struct sockaddr *sap, if (port) msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; - return rpcb_register_call(RPCBVERS_4, msg); + result = rpcb_register_call(RPCBVERS_4, msg); + kfree(map->r_addr); + return result; } static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) @@ -570,6 +565,7 @@ void rpcb_getport_async(struct rpc_task *task) goto bailout_nofree; } + /* Parent transport's destination address */ salen = rpc_peeraddr(clnt, sap, sizeof(addr)); /* Don't ever use rpcbind v2 for AF_INET6 requests */ @@ -620,11 +616,22 @@ void rpcb_getport_async(struct rpc_task *task) map->r_prot = xprt->prot; map->r_port = 0; map->r_xprt = xprt_get(xprt); - map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); - map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR); - map->r_owner = ""; map->r_status = -EIO; + switch (bind_version) { + case RPCBVERS_4: + case RPCBVERS_3: + map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); + map->r_addr = rpc_sockaddr2uaddr(sap); + map->r_owner = ""; + break; + case RPCBVERS_2: + map->r_addr = NULL; + break; + default: + BUG(); + } + child = rpcb_call_async(rpcb_clnt, map, proc); rpc_release_client(rpcb_clnt); if (IS_ERR(child)) { @@ -722,6 +729,9 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p, struct rpcbind_args *rpcb) { + if (rpcb->r_addr == NULL) + return -EIO; + dprintk("RPC: encoding rpcb request (%u, %u, %s)\n", rpcb->r_prog, rpcb->r_vers, rpcb->r_addr); *p++ = htonl(rpcb->r_prog); diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 1dd6123070e9..537c210a8b92 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -202,14 +202,6 @@ xprt_rdma_format_addresses(struct rpc_xprt *xprt) snprintf(buf, 8, "%4hx", ntohs(addr->sin_port)); xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; - buf = kzalloc(30, GFP_KERNEL); - if (buf) - snprintf(buf, 30, "%pI4.%u.%u", - &addr->sin_addr.s_addr, - ntohs(addr->sin_port) >> 8, - ntohs(addr->sin_port) & 0xff); - xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; - /* netid */ xprt->address_strings[RPC_DISPLAY_NETID] = "rdma"; } diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 83c73c4d017a..a42c2adda59f 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -341,15 +341,6 @@ static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt, } xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; - buf = kzalloc(30, GFP_KERNEL); - if (buf) { - snprintf(buf, 30, "%pI4.%u.%u", - &addr->sin_addr.s_addr, - ntohs(addr->sin_port) >> 8, - ntohs(addr->sin_port) & 0xff); - } - xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; - xprt->address_strings[RPC_DISPLAY_NETID] = netid; } @@ -397,15 +388,6 @@ static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt, } xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; - buf = kzalloc(50, GFP_KERNEL); - if (buf) { - snprintf(buf, 50, "%pI6.%u.%u", - &addr->sin6_addr, - ntohs(addr->sin6_port) >> 8, - ntohs(addr->sin6_port) & 0xff); - } - xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; - xprt->address_strings[RPC_DISPLAY_NETID] = netid; } -- cgit v1.2.3-70-g09d2 From 6f2c2db7a46243bd86e3d7ff5f9ff982f26a9fe8 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever@oracle.com> Date: Sun, 9 Aug 2009 15:09:40 -0400 Subject: SUNRPC: Introduce new xdr_stream-based encoders to rpcb_clnt.c Replace the open-coded encode logic for rpcbind arguments with an xdr_stream-based implementation, similar to what NFSv4 uses, to better protect against buffer overflows. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- net/sunrpc/rpcb_clnt.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) (limited to 'net/sunrpc/rpcb_clnt.c') diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 1fb1c070c19d..823d20dbad09 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -708,6 +708,30 @@ static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p, return 0; } +static int rpcb_enc_mapping(struct rpc_rqst *req, __be32 *p, + const struct rpcbind_args *rpcb) +{ + struct rpc_task *task = req->rq_task; + struct xdr_stream xdr; + + dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", + task->tk_pid, task->tk_msg.rpc_proc->p_name, + rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); + + xdr_init_encode(&xdr, &req->rq_snd_buf, p); + + p = xdr_reserve_space(&xdr, sizeof(__be32) * RPCB_mappingargs_sz); + if (unlikely(p == NULL)) + return -EIO; + + *p++ = htonl(rpcb->r_prog); + *p++ = htonl(rpcb->r_vers); + *p++ = htonl(rpcb->r_prot); + *p = htonl(rpcb->r_port); + + return 0; +} + static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p, unsigned short *portp) { @@ -746,6 +770,56 @@ static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p, return 0; } +static int encode_rpcb_string(struct xdr_stream *xdr, const char *string, + const u32 maxstrlen) +{ + u32 len; + __be32 *p; + + if (unlikely(string == NULL)) + return -EIO; + len = strlen(string); + if (unlikely(len > maxstrlen)) + return -EIO; + + p = xdr_reserve_space(xdr, sizeof(__be32) + len); + if (unlikely(p == NULL)) + return -EIO; + xdr_encode_opaque(p, string, len); + + return 0; +} + +static int rpcb_enc_getaddr(struct rpc_rqst *req, __be32 *p, + const struct rpcbind_args *rpcb) +{ + struct rpc_task *task = req->rq_task; + struct xdr_stream xdr; + + dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", + task->tk_pid, task->tk_msg.rpc_proc->p_name, + rpcb->r_prog, rpcb->r_vers, + rpcb->r_netid, rpcb->r_addr); + + xdr_init_encode(&xdr, &req->rq_snd_buf, p); + + p = xdr_reserve_space(&xdr, + sizeof(__be32) * (RPCB_program_sz + RPCB_version_sz)); + if (unlikely(p == NULL)) + return -EIO; + *p++ = htonl(rpcb->r_prog); + *p = htonl(rpcb->r_vers); + + if (encode_rpcb_string(&xdr, rpcb->r_netid, RPCBIND_MAXNETIDLEN)) + return -EIO; + if (encode_rpcb_string(&xdr, rpcb->r_addr, RPCBIND_MAXUADDRLEN)) + return -EIO; + if (encode_rpcb_string(&xdr, rpcb->r_owner, RPCB_MAXOWNERLEN)) + return -EIO; + + return 0; +} + static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, unsigned short *portp) { @@ -812,7 +886,7 @@ out_err: #define PROC(proc, argtype, restype) \ [RPCBPROC_##proc] = { \ .p_proc = RPCBPROC_##proc, \ - .p_encode = (kxdrproc_t) rpcb_encode_##argtype, \ + .p_encode = (kxdrproc_t) rpcb_enc_##argtype, \ .p_decode = (kxdrproc_t) rpcb_decode_##restype, \ .p_arglen = RPCB_##argtype##args_sz, \ .p_replen = RPCB_##restype##res_sz, \ -- cgit v1.2.3-70-g09d2 From 0d36c4f7574d5a33bedd8f0e3c793490d45d83c6 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever@oracle.com> Date: Sun, 9 Aug 2009 15:09:41 -0400 Subject: SUNRPC: Clean up: Remove unused XDR encoder functions from rpcb_clnt.c Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- net/sunrpc/rpcb_clnt.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) (limited to 'net/sunrpc/rpcb_clnt.c') diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 823d20dbad09..e0d7b31e54a7 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -694,20 +694,6 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) * XDR functions for rpcbind */ -static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p, - struct rpcbind_args *rpcb) -{ - dprintk("RPC: encoding rpcb request (%u, %u, %d, %u)\n", - rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); - *p++ = htonl(rpcb->r_prog); - *p++ = htonl(rpcb->r_vers); - *p++ = htonl(rpcb->r_prot); - *p++ = htonl(rpcb->r_port); - - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - return 0; -} - static int rpcb_enc_mapping(struct rpc_rqst *req, __be32 *p, const struct rpcbind_args *rpcb) { @@ -750,26 +736,6 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, return 0; } -static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p, - struct rpcbind_args *rpcb) -{ - if (rpcb->r_addr == NULL) - return -EIO; - - dprintk("RPC: encoding rpcb request (%u, %u, %s)\n", - rpcb->r_prog, rpcb->r_vers, rpcb->r_addr); - *p++ = htonl(rpcb->r_prog); - *p++ = htonl(rpcb->r_vers); - - p = xdr_encode_string(p, rpcb->r_netid); - p = xdr_encode_string(p, rpcb->r_addr); - p = xdr_encode_string(p, rpcb->r_owner); - - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - - return 0; -} - static int encode_rpcb_string(struct xdr_stream *xdr, const char *string, const u32 maxstrlen) { -- cgit v1.2.3-70-g09d2 From 7ed0ff983c8ad30bf4e2b9fdbb299a3e3ec08d08 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever@oracle.com> Date: Sun, 9 Aug 2009 15:09:42 -0400 Subject: SUNRPC: Introduce xdr_stream-based decoders for RPCB_UNSET Replace the open-coded decode logic for rpcbind UNSET results with an xdr_stream-based implementation, similar to what NFSv4 uses, to protect against buffer overflows. The new function is unused for the moment. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- net/sunrpc/rpcb_clnt.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'net/sunrpc/rpcb_clnt.c') diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index e0d7b31e54a7..fe183af5cc72 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -736,6 +736,28 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, return 0; } +static int rpcb_dec_set(struct rpc_rqst *req, __be32 *p, + unsigned int *boolp) +{ + struct rpc_task *task = req->rq_task; + struct xdr_stream xdr; + + xdr_init_decode(&xdr, &req->rq_rcv_buf, p); + + p = xdr_inline_decode(&xdr, sizeof(__be32)); + if (unlikely(p == NULL)) + return -EIO; + + *boolp = 0; + if (*p) + *boolp = 1; + + dprintk("RPC: %5u RPCB_%s call %s\n", + task->tk_pid, task->tk_msg.rpc_proc->p_name, + (*boolp ? "succeeded" : "failed")); + return 0; +} + static int encode_rpcb_string(struct xdr_stream *xdr, const char *string, const u32 maxstrlen) { -- cgit v1.2.3-70-g09d2 From c0c077df009f2f329875051ac5283df235288689 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever@oracle.com> Date: Sun, 9 Aug 2009 15:09:43 -0400 Subject: SUNRPC: Introduce new xdr_stream-based decoders to rpcb_clnt.c Replace the open-coded decode logic for PMAP_GETPORT/RPCB_GETADDR with an xdr_stream-based implementation, similar to what NFSv4 uses, to protect against buffer overflows. The new implementation also checks that the incoming port number is reasonable. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- net/sunrpc/rpcb_clnt.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 3 deletions(-) (limited to 'net/sunrpc/rpcb_clnt.c') diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index fe183af5cc72..88de754e3b02 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -454,7 +454,7 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot) struct rpc_message msg = { .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], .rpc_argp = &map, - .rpc_resp = &map.r_port, + .rpc_resp = &map, }; struct rpc_clnt *rpcb_clnt; int status; @@ -484,7 +484,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi struct rpc_message msg = { .rpc_proc = proc, .rpc_argp = map, - .rpc_resp = &map->r_port, + .rpc_resp = map, }; struct rpc_task_setup task_setup_data = { .rpc_client = rpcb_clnt, @@ -727,6 +727,31 @@ static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p, return 0; } +static int rpcb_dec_getport(struct rpc_rqst *req, __be32 *p, + struct rpcbind_args *rpcb) +{ + struct rpc_task *task = req->rq_task; + struct xdr_stream xdr; + unsigned long port; + + xdr_init_decode(&xdr, &req->rq_rcv_buf, p); + + rpcb->r_port = 0; + + p = xdr_inline_decode(&xdr, sizeof(__be32)); + if (unlikely(p == NULL)) + return -EIO; + + port = ntohl(*p); + dprintk("RPC: %5u PMAP_%s result: %lu\n", task->tk_pid, + task->tk_msg.rpc_proc->p_name, port); + if (unlikely(port > USHORT_MAX)) + return -EIO; + + rpcb->r_port = port; + return 0; +} + static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, unsigned int *boolp) { @@ -871,11 +896,60 @@ out_err: return -EIO; } +static int rpcb_dec_getaddr(struct rpc_rqst *req, __be32 *p, + struct rpcbind_args *rpcb) +{ + struct sockaddr_storage address; + struct sockaddr *sap = (struct sockaddr *)&address; + struct rpc_task *task = req->rq_task; + struct xdr_stream xdr; + u32 len; + + rpcb->r_port = 0; + + xdr_init_decode(&xdr, &req->rq_rcv_buf, p); + + p = xdr_inline_decode(&xdr, sizeof(__be32)); + if (unlikely(p == NULL)) + goto out_fail; + len = ntohl(*p); + + /* + * If the returned universal address is a null string, + * the requested RPC service was not registered. + */ + if (len == 0) { + dprintk("RPC: %5u RPCB reply: program not registered\n", + task->tk_pid); + return 0; + } + + if (unlikely(len > RPCBIND_MAXUADDRLEN)) + goto out_fail; + + p = xdr_inline_decode(&xdr, len); + if (unlikely(p == NULL)) + goto out_fail; + dprintk("RPC: %5u RPCB_%s reply: %s\n", task->tk_pid, + task->tk_msg.rpc_proc->p_name, (char *)p); + + if (rpc_uaddr2sockaddr((char *)p, len, sap, sizeof(address)) == 0) + goto out_fail; + rpcb->r_port = rpc_get_port(sap); + + return 0; + +out_fail: + dprintk("RPC: %5u malformed RPCB_%s reply\n", + task->tk_pid, task->tk_msg.rpc_proc->p_name); + return -EIO; +} + #define PROC(proc, argtype, restype) \ [RPCBPROC_##proc] = { \ .p_proc = RPCBPROC_##proc, \ .p_encode = (kxdrproc_t) rpcb_enc_##argtype, \ - .p_decode = (kxdrproc_t) rpcb_decode_##restype, \ + .p_decode = (kxdrproc_t) rpcb_dec_##restype, \ .p_arglen = RPCB_##argtype##args_sz, \ .p_replen = RPCB_##restype##res_sz, \ .p_statidx = RPCBPROC_##proc, \ -- cgit v1.2.3-70-g09d2 From 0e47f0d665efcf1b45f293422d21d8383f07d122 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever@oracle.com> Date: Sun, 9 Aug 2009 15:09:43 -0400 Subject: SUNRPC: Clean up: Remove unused XDR decoder functions from rpcb_clnt.c Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- net/sunrpc/rpcb_clnt.c | 81 -------------------------------------------------- 1 file changed, 81 deletions(-) (limited to 'net/sunrpc/rpcb_clnt.c') diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 88de754e3b02..c4b716cacf21 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -718,15 +718,6 @@ static int rpcb_enc_mapping(struct rpc_rqst *req, __be32 *p, return 0; } -static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p, - unsigned short *portp) -{ - *portp = (unsigned short) ntohl(*p++); - dprintk("RPC: rpcb getport result: %u\n", - *portp); - return 0; -} - static int rpcb_dec_getport(struct rpc_rqst *req, __be32 *p, struct rpcbind_args *rpcb) { @@ -752,15 +743,6 @@ static int rpcb_dec_getport(struct rpc_rqst *req, __be32 *p, return 0; } -static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, - unsigned int *boolp) -{ - *boolp = (unsigned int) ntohl(*p++); - dprintk("RPC: rpcb set/unset call %s\n", - (*boolp ? "succeeded" : "failed")); - return 0; -} - static int rpcb_dec_set(struct rpc_rqst *req, __be32 *p, unsigned int *boolp) { @@ -833,69 +815,6 @@ static int rpcb_enc_getaddr(struct rpc_rqst *req, __be32 *p, return 0; } -static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, - unsigned short *portp) -{ - char *addr; - u32 addr_len; - int c, i, f, first, val; - - *portp = 0; - addr_len = ntohl(*p++); - - if (addr_len == 0) { - dprintk("RPC: rpcb_decode_getaddr: " - "service is not registered\n"); - return 0; - } - - /* - * Simple sanity check. - */ - if (addr_len > RPCBIND_MAXUADDRLEN) - goto out_err; - - /* - * Start at the end and walk backwards until the first dot - * is encountered. When the second dot is found, we have - * both parts of the port number. - */ - addr = (char *)p; - val = 0; - first = 1; - f = 1; - for (i = addr_len - 1; i > 0; i--) { - c = addr[i]; - if (c >= '0' && c <= '9') { - val += (c - '0') * f; - f *= 10; - } else if (c == '.') { - if (first) { - *portp = val; - val = first = 0; - f = 1; - } else { - *portp |= (val << 8); - break; - } - } - } - - /* - * Simple sanity check. If we never saw a dot in the reply, - * then this was probably just garbage. - */ - if (first) - goto out_err; - - dprintk("RPC: rpcb_decode_getaddr port=%u\n", *portp); - return 0; - -out_err: - dprintk("RPC: rpcbind server returned malformed reply\n"); - return -EIO; -} - static int rpcb_dec_getaddr(struct rpc_rqst *req, __be32 *p, struct rpcbind_args *rpcb) { -- cgit v1.2.3-70-g09d2 From f8b761eff1e49fde43dd940ac32b38cf7cee2a95 Mon Sep 17 00:00:00 2001 From: Chuck Lever <chuck.lever@oracle.com> Date: Sun, 9 Aug 2009 15:09:44 -0400 Subject: SUNRPC: Eliminate PROC macro from rpcb_clnt Clean up: Replace PROC macro with open coded C99 structure initializers to improve readability. The rpcbind v4 GETVERSADDR procedure is never sent by the current implementation, so it is not copied to the new structures. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> --- net/sunrpc/rpcb_clnt.c | 113 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 22 deletions(-) (limited to 'net/sunrpc/rpcb_clnt.c') diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index c4b716cacf21..830faf4d9997 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -864,39 +864,108 @@ out_fail: return -EIO; } -#define PROC(proc, argtype, restype) \ - [RPCBPROC_##proc] = { \ - .p_proc = RPCBPROC_##proc, \ - .p_encode = (kxdrproc_t) rpcb_enc_##argtype, \ - .p_decode = (kxdrproc_t) rpcb_dec_##restype, \ - .p_arglen = RPCB_##argtype##args_sz, \ - .p_replen = RPCB_##restype##res_sz, \ - .p_statidx = RPCBPROC_##proc, \ - .p_timer = 0, \ - .p_name = #proc, \ - } - /* * Not all rpcbind procedures described in RFC 1833 are implemented * since the Linux kernel RPC code requires only these. */ + static struct rpc_procinfo rpcb_procedures2[] = { - PROC(SET, mapping, set), - PROC(UNSET, mapping, set), - PROC(GETPORT, mapping, getport), + [RPCBPROC_SET] = { + .p_proc = RPCBPROC_SET, + .p_encode = (kxdrproc_t)rpcb_enc_mapping, + .p_decode = (kxdrproc_t)rpcb_dec_set, + .p_arglen = RPCB_mappingargs_sz, + .p_replen = RPCB_setres_sz, + .p_statidx = RPCBPROC_SET, + .p_timer = 0, + .p_name = "SET", + }, + [RPCBPROC_UNSET] = { + .p_proc = RPCBPROC_UNSET, + .p_encode = (kxdrproc_t)rpcb_enc_mapping, + .p_decode = (kxdrproc_t)rpcb_dec_set, + .p_arglen = RPCB_mappingargs_sz, + .p_replen = RPCB_setres_sz, + .p_statidx = RPCBPROC_UNSET, + .p_timer = 0, + .p_name = "UNSET", + }, + [RPCBPROC_GETPORT] = { + .p_proc = RPCBPROC_GETPORT, + .p_encode = (kxdrproc_t)rpcb_enc_mapping, + .p_decode = (kxdrproc_t)rpcb_dec_getport, + .p_arglen = RPCB_mappingargs_sz, + .p_replen = RPCB_getportres_sz, + .p_statidx = RPCBPROC_GETPORT, + .p_timer = 0, + .p_name = "GETPORT", + }, }; static struct rpc_procinfo rpcb_procedures3[] = { - PROC(SET, getaddr, set), - PROC(UNSET, getaddr, set), - PROC(GETADDR, getaddr, getaddr), + [RPCBPROC_SET] = { + .p_proc = RPCBPROC_SET, + .p_encode = (kxdrproc_t)rpcb_enc_getaddr, + .p_decode = (kxdrproc_t)rpcb_dec_set, + .p_arglen = RPCB_getaddrargs_sz, + .p_replen = RPCB_setres_sz, + .p_statidx = RPCBPROC_SET, + .p_timer = 0, + .p_name = "SET", + }, + [RPCBPROC_UNSET] = { + .p_proc = RPCBPROC_UNSET, + .p_encode = (kxdrproc_t)rpcb_enc_getaddr, + .p_decode = (kxdrproc_t)rpcb_dec_set, + .p_arglen = RPCB_getaddrargs_sz, + .p_replen = RPCB_setres_sz, + .p_statidx = RPCBPROC_UNSET, + .p_timer = 0, + .p_name = "UNSET", + }, + [RPCBPROC_GETADDR] = { + .p_proc = RPCBPROC_GETADDR, + .p_encode = (kxdrproc_t)rpcb_enc_getaddr, + .p_decode = (kxdrproc_t)rpcb_dec_getaddr, + .p_arglen = RPCB_getaddrargs_sz, + .p_replen = RPCB_getaddrres_sz, + .p_statidx = RPCBPROC_GETADDR, + .p_timer = 0, + .p_name = "GETADDR", + }, }; static struct rpc_procinfo rpcb_procedures4[] = { - PROC(SET, getaddr, set), - PROC(UNSET, getaddr, set), - PROC(GETADDR, getaddr, getaddr), - PROC(GETVERSADDR, getaddr, getaddr), + [RPCBPROC_SET] = { + .p_proc = RPCBPROC_SET, + .p_encode = (kxdrproc_t)rpcb_enc_getaddr, + .p_decode = (kxdrproc_t)rpcb_dec_set, + .p_arglen = RPCB_getaddrargs_sz, + .p_replen = RPCB_setres_sz, + .p_statidx = RPCBPROC_SET, + .p_timer = 0, + .p_name = "SET", + }, + [RPCBPROC_UNSET] = { + .p_proc = RPCBPROC_UNSET, + .p_encode = (kxdrproc_t)rpcb_enc_getaddr, + .p_decode = (kxdrproc_t)rpcb_dec_set, + .p_arglen = RPCB_getaddrargs_sz, + .p_replen = RPCB_setres_sz, + .p_statidx = RPCBPROC_UNSET, + .p_timer = 0, + .p_name = "UNSET", + }, + [RPCBPROC_GETADDR] = { + .p_proc = RPCBPROC_GETADDR, + .p_encode = (kxdrproc_t)rpcb_enc_getaddr, + .p_decode = (kxdrproc_t)rpcb_dec_getaddr, + .p_arglen = RPCB_getaddrargs_sz, + .p_replen = RPCB_getaddrres_sz, + .p_statidx = RPCBPROC_GETADDR, + .p_timer = 0, + .p_name = "GETADDR", + }, }; static struct rpcb_info rpcb_next_version[] = { -- cgit v1.2.3-70-g09d2