📄 rpcb_clnt.c
字号:
task->tk_pid, __FUNCTION__); goto bailout_nofree; } rpc_peeraddr(clnt, (void *)&addr, sizeof(addr)); /* Don't ever use rpcbind v2 for AF_INET6 requests */ switch (addr.sa_family) { case AF_INET: info = rpcb_next_version; break; case AF_INET6: info = rpcb_next_version6; break; default: status = -EAFNOSUPPORT; dprintk("RPC: %5u %s: bad address family\n", task->tk_pid, __FUNCTION__); goto bailout_nofree; } if (info[xprt->bind_index].rpc_proc == NULL) { xprt->bind_index = 0; status = -EPFNOSUPPORT; dprintk("RPC: %5u %s: no more getport versions available\n", task->tk_pid, __FUNCTION__); goto bailout_nofree; } bind_version = info[xprt->bind_index].rpc_vers; dprintk("RPC: %5u %s: trying rpcbind version %u\n", task->tk_pid, __FUNCTION__, bind_version); rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0); if (IS_ERR(rpcb_clnt)) { status = PTR_ERR(rpcb_clnt); dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); goto bailout_nofree; } map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); if (!map) { status = -ENOMEM; dprintk("RPC: %5u %s: no memory available\n", task->tk_pid, __FUNCTION__); goto bailout_nofree; } map->r_prog = clnt->cl_prog; map->r_vers = clnt->cl_vers; map->r_prot = xprt->prot; map->r_port = 0; map->r_xprt = xprt_get(xprt); map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); memcpy(map->r_addr, rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR), sizeof(map->r_addr)); map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); rpc_release_client(rpcb_clnt); if (IS_ERR(child)) { status = -EIO; dprintk("RPC: %5u %s: rpc_run_task failed\n", task->tk_pid, __FUNCTION__); goto bailout; } rpc_put_task(child); task->tk_xprt->stat.bind_count++; return;bailout: kfree(map); xprt_put(xprt);bailout_nofree: rpcb_wake_rpcbind_waiters(xprt, status);bailout_nowake: task->tk_status = status;}EXPORT_SYMBOL_GPL(rpcb_getport_async);/* * Rpcbind child task calls this callback via tk_exit. */static void rpcb_getport_done(struct rpc_task *child, void *data){ struct rpcbind_args *map = data; struct rpc_xprt *xprt = map->r_xprt; int status = child->tk_status; /* Garbage reply: retry with a lesser rpcbind version */ if (status == -EIO) status = -EPROTONOSUPPORT; /* rpcbind server doesn't support this rpcbind protocol version */ if (status == -EPROTONOSUPPORT) xprt->bind_index++; if (status < 0) { /* rpcbind server not available on remote host? */ xprt->ops->set_port(xprt, 0); } else if (map->r_port == 0) { /* Requested RPC service wasn't registered on remote host */ xprt->ops->set_port(xprt, 0); status = -EACCES; } else { /* Succeeded */ xprt->ops->set_port(xprt, map->r_port); xprt_set_bound(xprt); status = 0; } dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n", child->tk_pid, status, map->r_port); rpcb_wake_rpcbind_waiters(xprt, status);}static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p, struct rpcbind_args *rpcb){ dprintk("RPC: rpcb_encode_mapping(%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_decode_getport(struct rpc_rqst *req, __be32 *p, unsigned short *portp){ *portp = (unsigned short) ntohl(*p++); dprintk("RPC: rpcb_decode_getport result %u\n", *portp); return 0;}static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, unsigned int *boolp){ *boolp = (unsigned int) ntohl(*p++); dprintk("RPC: rpcb_decode_set result %u\n", *boolp); return 0;}static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p, struct rpcbind_args *rpcb){ dprintk("RPC: rpcb_encode_getaddr(%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 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++); /* * Simple sanity check. The smallest possible universal * address is an IPv4 address string containing 11 bytes. */ if (addr_len < 11 || addr_len > RPCB_MAXADDRLEN) 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;}#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(RPCB_MAXADDRLEN))#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, \ .p_encode = (kxdrproc_t) rpcb_encode_##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(GETADDR, mapping, getport),};static struct rpc_procinfo rpcb_procedures3[] = { PROC(SET, mapping, set), PROC(UNSET, mapping, set), PROC(GETADDR, getaddr, getaddr),};static struct rpc_procinfo rpcb_procedures4[] = { PROC(SET, mapping, set), PROC(UNSET, mapping, set), PROC(GETVERSADDR, getaddr, getaddr),};static struct rpcb_info rpcb_next_version[] = {#ifdef CONFIG_SUNRPC_BIND34 { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] }, { 3, &rpcb_procedures3[RPCBPROC_GETADDR] },#endif { 2, &rpcb_procedures2[RPCBPROC_GETPORT] }, { 0, NULL },};static struct rpcb_info rpcb_next_version6[] = {#ifdef CONFIG_SUNRPC_BIND34 { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] }, { 3, &rpcb_procedures3[RPCBPROC_GETADDR] },#endif { 0, NULL },};static struct rpc_version rpcb_version2 = { .number = 2, .nrprocs = RPCB_HIGHPROC_2, .procs = rpcb_procedures2};static struct rpc_version rpcb_version3 = { .number = 3, .nrprocs = RPCB_HIGHPROC_3, .procs = rpcb_procedures3};static struct rpc_version rpcb_version4 = { .number = 4, .nrprocs = RPCB_HIGHPROC_4, .procs = rpcb_procedures4};static struct rpc_version *rpcb_version[] = { NULL, NULL, &rpcb_version2, &rpcb_version3, &rpcb_version4};static struct rpc_stat rpcb_stats;static struct rpc_program rpcb_program = { .name = "rpcbind", .number = RPCBIND_PROGRAM, .nrvers = ARRAY_SIZE(rpcb_version), .version = rpcb_version, .stats = &rpcb_stats,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -