xref: /freebsd-src/sys/rpc/svc_generic.c (revision ebb36fcaae4dfd3720e43f8e6a9613e5d84227e0)
1dfdcada3SDoug Rabson /*	$NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $	*/
2dfdcada3SDoug Rabson 
32e322d37SHiroki Sato /*-
451369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
551369649SPedro F. Giffuni  *
62e322d37SHiroki Sato  * Copyright (c) 2009, Sun Microsystems, Inc.
72e322d37SHiroki Sato  * All rights reserved.
8dfdcada3SDoug Rabson  *
92e322d37SHiroki Sato  * Redistribution and use in source and binary forms, with or without
102e322d37SHiroki Sato  * modification, are permitted provided that the following conditions are met:
112e322d37SHiroki Sato  * - Redistributions of source code must retain the above copyright notice,
122e322d37SHiroki Sato  *   this list of conditions and the following disclaimer.
132e322d37SHiroki Sato  * - Redistributions in binary form must reproduce the above copyright notice,
142e322d37SHiroki Sato  *   this list of conditions and the following disclaimer in the documentation
152e322d37SHiroki Sato  *   and/or other materials provided with the distribution.
162e322d37SHiroki Sato  * - Neither the name of Sun Microsystems, Inc. nor the names of its
172e322d37SHiroki Sato  *   contributors may be used to endorse or promote products derived
182e322d37SHiroki Sato  *   from this software without specific prior written permission.
19dfdcada3SDoug Rabson  *
202e322d37SHiroki Sato  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
212e322d37SHiroki Sato  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
222e322d37SHiroki Sato  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
232e322d37SHiroki Sato  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
242e322d37SHiroki Sato  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
252e322d37SHiroki Sato  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
262e322d37SHiroki Sato  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
272e322d37SHiroki Sato  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
282e322d37SHiroki Sato  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
292e322d37SHiroki Sato  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
302e322d37SHiroki Sato  * POSSIBILITY OF SUCH DAMAGE.
31dfdcada3SDoug Rabson  */
32dfdcada3SDoug Rabson 
33dfdcada3SDoug Rabson /*
34dfdcada3SDoug Rabson  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
35dfdcada3SDoug Rabson  */
36dfdcada3SDoug Rabson 
37dfdcada3SDoug Rabson /*
38dfdcada3SDoug Rabson  * svc_generic.c, Server side for RPC.
39dfdcada3SDoug Rabson  *
40dfdcada3SDoug Rabson  */
41dfdcada3SDoug Rabson 
42dfdcada3SDoug Rabson #include "opt_inet6.h"
43dfdcada3SDoug Rabson 
44dfdcada3SDoug Rabson #include <sys/param.h>
45dfdcada3SDoug Rabson #include <sys/lock.h>
46dfdcada3SDoug Rabson #include <sys/kernel.h>
47dfdcada3SDoug Rabson #include <sys/malloc.h>
48dfdcada3SDoug Rabson #include <sys/mutex.h>
49dfdcada3SDoug Rabson #include <sys/protosw.h>
50dfdcada3SDoug Rabson #include <sys/queue.h>
51dfdcada3SDoug Rabson #include <sys/socket.h>
52dfdcada3SDoug Rabson #include <sys/socketvar.h>
53dfdcada3SDoug Rabson #include <sys/systm.h>
54dfdcada3SDoug Rabson #include <sys/sx.h>
55dfdcada3SDoug Rabson #include <sys/ucred.h>
56dfdcada3SDoug Rabson 
570348c661SMarko Zec #include <net/vnet.h>
580348c661SMarko Zec 
59dfdcada3SDoug Rabson #include <rpc/rpc.h>
60dfdcada3SDoug Rabson #include <rpc/rpcb_clnt.h>
61dfdcada3SDoug Rabson #include <rpc/nettype.h>
62dfdcada3SDoug Rabson 
63ee31b83aSDoug Rabson #include <rpc/rpc_com.h>
64dfdcada3SDoug Rabson 
65dfdcada3SDoug Rabson extern int __svc_vc_setflag(SVCXPRT *, int);
66dfdcada3SDoug Rabson 
67dfdcada3SDoug Rabson /*
68dfdcada3SDoug Rabson  * The high level interface to svc_tli_create().
69dfdcada3SDoug Rabson  * It tries to create a server for "nconf" and registers the service
70dfdcada3SDoug Rabson  * with the rpcbind. It calls svc_tli_create();
71dfdcada3SDoug Rabson  */
72dfdcada3SDoug Rabson SVCXPRT *
73dfdcada3SDoug Rabson svc_tp_create(
74dfdcada3SDoug Rabson 	SVCPOOL *pool,
75dfdcada3SDoug Rabson 	void (*dispatch)(struct svc_req *, SVCXPRT *),
76dfdcada3SDoug Rabson 	rpcprog_t prognum,		/* Program number */
77dfdcada3SDoug Rabson 	rpcvers_t versnum,		/* Version number */
78dfdcada3SDoug Rabson 	const char *uaddr,		/* Address (or null for default) */
79dfdcada3SDoug Rabson 	const struct netconfig *nconf) /* Netconfig structure for the network */
80dfdcada3SDoug Rabson {
81dfdcada3SDoug Rabson 	struct netconfig nconfcopy;
82dfdcada3SDoug Rabson 	struct netbuf *taddr;
83dfdcada3SDoug Rabson 	struct t_bind bind;
84dfdcada3SDoug Rabson 	SVCXPRT *xprt;
85dfdcada3SDoug Rabson 
86dfdcada3SDoug Rabson 	if (nconf == NULL) {
87dfdcada3SDoug Rabson 		printf(
88dfdcada3SDoug Rabson 	"svc_tp_create: invalid netconfig structure for prog %u vers %u\n",
89dfdcada3SDoug Rabson 				(unsigned)prognum, (unsigned)versnum);
90dfdcada3SDoug Rabson 		return (NULL);
91dfdcada3SDoug Rabson 	}
92dfdcada3SDoug Rabson 	if (uaddr) {
93dfdcada3SDoug Rabson 		taddr = uaddr2taddr(nconf, uaddr);
94dfdcada3SDoug Rabson 		bind.addr = *taddr;
95dfdcada3SDoug Rabson 		free(taddr, M_RPC);
9680867e61SAlexander Motin 		bind.qlen = -1;
97*d052fcbdSGleb Smirnoff 		xprt = svc_tli_create(pool, nconf, &bind, 0, 0);
98dfdcada3SDoug Rabson 		free(bind.addr.buf, M_RPC);
99dfdcada3SDoug Rabson 	} else {
100*d052fcbdSGleb Smirnoff 		xprt = svc_tli_create(pool, nconf, NULL, 0, 0);
101dfdcada3SDoug Rabson 	}
102dfdcada3SDoug Rabson 	if (xprt == NULL) {
103dfdcada3SDoug Rabson 		return (NULL);
104dfdcada3SDoug Rabson 	}
105dfdcada3SDoug Rabson 	/*LINTED const castaway*/
106dfdcada3SDoug Rabson 	nconfcopy = *nconf;
107dfdcada3SDoug Rabson 	(void) rpcb_unset(prognum, versnum, &nconfcopy);
108dfdcada3SDoug Rabson 	if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {
109dfdcada3SDoug Rabson 		printf(
110dfdcada3SDoug Rabson 		"svc_tp_create: Could not register prog %u vers %u on %s\n",
111dfdcada3SDoug Rabson 				(unsigned)prognum, (unsigned)versnum,
112dfdcada3SDoug Rabson 				nconf->nc_netid);
113a9148abdSDoug Rabson 		xprt_unregister(xprt);
1146b97c9f0SRick Macklem 		SVC_RELEASE(xprt);
115dfdcada3SDoug Rabson 		return (NULL);
116dfdcada3SDoug Rabson 	}
117dfdcada3SDoug Rabson 	return (xprt);
118dfdcada3SDoug Rabson }
119dfdcada3SDoug Rabson 
120dfdcada3SDoug Rabson /*
121dfdcada3SDoug Rabson  * If so is NULL, then it opens a socket for the given transport
122dfdcada3SDoug Rabson  * provider (nconf cannot be NULL then). If the t_state is T_UNBND and
123dfdcada3SDoug Rabson  * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
124dfdcada3SDoug Rabson  * NULL bindadr and Connection oriented transports, the value of qlen
125dfdcada3SDoug Rabson  * is set to 8.
126dfdcada3SDoug Rabson  *
127dfdcada3SDoug Rabson  * If sendsz or recvsz are zero, their default values are chosen.
128dfdcada3SDoug Rabson  */
129dfdcada3SDoug Rabson SVCXPRT *
130dfdcada3SDoug Rabson svc_tli_create(
131dfdcada3SDoug Rabson 	SVCPOOL *pool,
132dfdcada3SDoug Rabson 	const struct netconfig *nconf,	/* Netconfig struct for nettoken */
133dfdcada3SDoug Rabson 	const struct t_bind *bindaddr,	/* Local bind address */
134dfdcada3SDoug Rabson 	size_t sendsz,			/* Max sendsize */
135dfdcada3SDoug Rabson 	size_t recvsz)			/* Max recvsize */
136dfdcada3SDoug Rabson {
137*d052fcbdSGleb Smirnoff 	struct socket *so;
138dfdcada3SDoug Rabson 	SVCXPRT *xprt = NULL;		/* service handle */
139dfdcada3SDoug Rabson 	struct __rpc_sockinfo si;
140dfdcada3SDoug Rabson 	struct sockaddr_storage ss;
141dfdcada3SDoug Rabson 
142dfdcada3SDoug Rabson 	if (nconf == NULL) {
143dfdcada3SDoug Rabson 		printf("svc_tli_create: invalid netconfig\n");
144dfdcada3SDoug Rabson 		return (NULL);
145dfdcada3SDoug Rabson 	}
146dfdcada3SDoug Rabson 	so = __rpc_nconf2socket(nconf);
147dfdcada3SDoug Rabson 	if (!so) {
148dfdcada3SDoug Rabson 		printf(
149dfdcada3SDoug Rabson 		    "svc_tli_create: could not open connection for %s\n",
150dfdcada3SDoug Rabson 				nconf->nc_netid);
151dfdcada3SDoug Rabson 		return (NULL);
152dfdcada3SDoug Rabson 	}
153dfdcada3SDoug Rabson 	__rpc_nconf2sockinfo(nconf, &si);
154dfdcada3SDoug Rabson 
155dfdcada3SDoug Rabson 	if (bindaddr == NULL) {
156dfdcada3SDoug Rabson 		if (bindresvport(so, NULL)) {
157dfdcada3SDoug Rabson 			memset(&ss, 0, sizeof ss);
158dfdcada3SDoug Rabson 			ss.ss_family = si.si_af;
159dfdcada3SDoug Rabson 			ss.ss_len = si.si_alen;
160dfdcada3SDoug Rabson 			if (sobind(so, (struct sockaddr *)&ss,
161dfdcada3SDoug Rabson 				curthread)) {
162dfdcada3SDoug Rabson 				printf(
163dfdcada3SDoug Rabson 		"svc_tli_create: could not bind to anonymous port\n");
164dfdcada3SDoug Rabson 				goto freedata;
165dfdcada3SDoug Rabson 			}
166dfdcada3SDoug Rabson 		}
16780867e61SAlexander Motin 		solisten(so, -1, curthread);
168dfdcada3SDoug Rabson 	} else {
169dfdcada3SDoug Rabson 		if (bindresvport(so,
170dfdcada3SDoug Rabson 			(struct sockaddr *)bindaddr->addr.buf)) {
171dfdcada3SDoug Rabson 			printf(
172dfdcada3SDoug Rabson 	"svc_tli_create: could not bind to requested address\n");
173dfdcada3SDoug Rabson 			goto freedata;
174dfdcada3SDoug Rabson 		}
175dfdcada3SDoug Rabson 		solisten(so, (int)bindaddr->qlen, curthread);
176dfdcada3SDoug Rabson 	}
177dfdcada3SDoug Rabson 
178dfdcada3SDoug Rabson 	/*
179dfdcada3SDoug Rabson 	 * call transport specific function.
180dfdcada3SDoug Rabson 	 */
181dfdcada3SDoug Rabson 	switch (si.si_socktype) {
182dfdcada3SDoug Rabson 		case SOCK_STREAM:
183dfdcada3SDoug Rabson #if 0
184dfdcada3SDoug Rabson 			slen = sizeof ss;
185dfdcada3SDoug Rabson 			if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen)
186dfdcada3SDoug Rabson 			    == 0) {
187dfdcada3SDoug Rabson 				/* accepted socket */
188dfdcada3SDoug Rabson 				xprt = svc_fd_create(fd, sendsz, recvsz);
189dfdcada3SDoug Rabson 			} else
190dfdcada3SDoug Rabson #endif
191dfdcada3SDoug Rabson 				xprt = svc_vc_create(pool, so, sendsz, recvsz);
192dfdcada3SDoug Rabson 			if (!nconf || !xprt)
193dfdcada3SDoug Rabson 				break;
194dfdcada3SDoug Rabson #if 0
195dfdcada3SDoug Rabson 			/* XXX fvdl */
196dfdcada3SDoug Rabson 			if (strcmp(nconf->nc_protofmly, "inet") == 0 ||
197dfdcada3SDoug Rabson 			    strcmp(nconf->nc_protofmly, "inet6") == 0)
198dfdcada3SDoug Rabson 				(void) __svc_vc_setflag(xprt, TRUE);
199dfdcada3SDoug Rabson #endif
200dfdcada3SDoug Rabson 			break;
201dfdcada3SDoug Rabson 		case SOCK_DGRAM:
202dfdcada3SDoug Rabson 			xprt = svc_dg_create(pool, so, sendsz, recvsz);
203dfdcada3SDoug Rabson 			break;
204dfdcada3SDoug Rabson 		default:
205dfdcada3SDoug Rabson 			printf("svc_tli_create: bad service type");
206dfdcada3SDoug Rabson 			goto freedata;
207dfdcada3SDoug Rabson 	}
208dfdcada3SDoug Rabson 
209dfdcada3SDoug Rabson 	if (xprt == NULL)
210dfdcada3SDoug Rabson 		/*
211dfdcada3SDoug Rabson 		 * The error messages here are spitted out by the lower layers:
212dfdcada3SDoug Rabson 		 * svc_vc_create(), svc_fd_create() and svc_dg_create().
213dfdcada3SDoug Rabson 		 */
214dfdcada3SDoug Rabson 		goto freedata;
215dfdcada3SDoug Rabson 
216dfdcada3SDoug Rabson 	/* Fill in type of service */
217dfdcada3SDoug Rabson 	xprt->xp_type = __rpc_socktype2seman(si.si_socktype);
218dfdcada3SDoug Rabson 
219dfdcada3SDoug Rabson 	if (nconf) {
220dfdcada3SDoug Rabson 		xprt->xp_netid = strdup(nconf->nc_netid, M_RPC);
221dfdcada3SDoug Rabson 	}
222dfdcada3SDoug Rabson 	return (xprt);
223dfdcada3SDoug Rabson 
224dfdcada3SDoug Rabson freedata:
225dfdcada3SDoug Rabson 	(void)soclose(so);
226*d052fcbdSGleb Smirnoff 	if (xprt)
227a9148abdSDoug Rabson 		xprt_unregister(xprt);
228dfdcada3SDoug Rabson 	return (NULL);
229dfdcada3SDoug Rabson }
230