⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpcb_clnt.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			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 + -