Documentation/memory.txt: remove some very outdated recommendations
[safe/jmp/linux-2.6] / net / sunrpc / rpcb_clnt.c
index 823d20d..830faf4 100644 (file)
@@ -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,
@@ -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)
 {
@@ -732,41 +718,50 @@ 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)
+static int rpcb_dec_getport(struct rpc_rqst *req, __be32 *p,
+                           struct rpcbind_args *rpcb)
 {
-       *portp = (unsigned short) ntohl(*p++);
-       dprintk("RPC:       rpcb getport result: %u\n",
-                       *portp);
-       return 0;
-}
+       struct rpc_task *task = req->rq_task;
+       struct xdr_stream xdr;
+       unsigned long port;
 
-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"));
+       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_encode_getaddr(struct rpc_rqst *req, __be32 *p,
-                              struct rpcbind_args *rpcb)
+static int rpcb_dec_set(struct rpc_rqst *req, __be32 *p,
+                       unsigned int *boolp)
 {
-       if (rpcb->r_addr == NULL)
-               return -EIO;
+       struct rpc_task *task = req->rq_task;
+       struct xdr_stream xdr;
 
-       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);
+       xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
 
-       p = xdr_encode_string(p, rpcb->r_netid);
-       p = xdr_encode_string(p, rpcb->r_addr);
-       p = xdr_encode_string(p, rpcb->r_owner);
+       p = xdr_inline_decode(&xdr, sizeof(__be32));
+       if (unlikely(p == NULL))
+               return -EIO;
 
-       req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+       *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;
 }
 
@@ -820,102 +815,157 @@ 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)
+static int rpcb_dec_getaddr(struct rpc_rqst *req, __be32 *p,
+                           struct rpcbind_args *rpcb)
 {
-       char *addr;
-       u32 addr_len;
-       int c, i, f, first, val;
+       struct sockaddr_storage address;
+       struct sockaddr *sap = (struct sockaddr *)&address;
+       struct rpc_task *task = req->rq_task;
+       struct xdr_stream xdr;
+       u32 len;
 
-       *portp = 0;
-       addr_len = ntohl(*p++);
+       rpcb->r_port = 0;
 
-       if (addr_len == 0) {
-               dprintk("RPC:       rpcb_decode_getaddr: "
-                                       "service is not registered\n");
-               return 0;
-       }
+       xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
 
-       /*
-        * Simple sanity check.
-        */
-       if (addr_len > RPCBIND_MAXUADDRLEN)
-               goto out_err;
+       p = xdr_inline_decode(&xdr, sizeof(__be32));
+       if (unlikely(p == NULL))
+               goto out_fail;
+       len = ntohl(*p);
 
        /*
-        * 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.
+        * If the returned universal address is a null string,
+        * the requested RPC service was not registered.
         */
-       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;
-                       }
-               }
+       if (len == 0) {
+               dprintk("RPC: %5u RPCB reply: program not registered\n",
+                               task->tk_pid);
+               return 0;
        }
 
-       /*
-        * Simple sanity check.  If we never saw a dot in the reply,
-        * then this was probably just garbage.
-        */
-       if (first)
-               goto out_err;
+       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);
 
-       dprintk("RPC:       rpcb_decode_getaddr port=%u\n", *portp);
        return 0;
 
-out_err:
-       dprintk("RPC:       rpcbind server returned malformed reply\n");
+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_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[] = {