1dfdcada3SDoug Rabson /* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */ 2dfdcada3SDoug Rabson 32e322d37SHiroki Sato /*- 4*51369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 5*51369649SPedro 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 #if defined(LIBC_SCCS) && !defined(lint) 38dfdcada3SDoug Rabson #ident "@(#)svc_generic.c 1.19 94/04/24 SMI" 39dfdcada3SDoug Rabson static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro"; 40dfdcada3SDoug Rabson #endif 41dfdcada3SDoug Rabson #include <sys/cdefs.h> 42dfdcada3SDoug Rabson __FBSDID("$FreeBSD$"); 43dfdcada3SDoug Rabson 44dfdcada3SDoug Rabson /* 45dfdcada3SDoug Rabson * svc_generic.c, Server side for RPC. 46dfdcada3SDoug Rabson * 47dfdcada3SDoug Rabson */ 48dfdcada3SDoug Rabson 49dfdcada3SDoug Rabson #include "opt_inet6.h" 50dfdcada3SDoug Rabson 51dfdcada3SDoug Rabson #include <sys/param.h> 52dfdcada3SDoug Rabson #include <sys/lock.h> 53dfdcada3SDoug Rabson #include <sys/kernel.h> 54dfdcada3SDoug Rabson #include <sys/malloc.h> 55dfdcada3SDoug Rabson #include <sys/mutex.h> 56dfdcada3SDoug Rabson #include <sys/protosw.h> 57dfdcada3SDoug Rabson #include <sys/queue.h> 58dfdcada3SDoug Rabson #include <sys/socket.h> 59dfdcada3SDoug Rabson #include <sys/socketvar.h> 60dfdcada3SDoug Rabson #include <sys/systm.h> 61dfdcada3SDoug Rabson #include <sys/sx.h> 62dfdcada3SDoug Rabson #include <sys/ucred.h> 63dfdcada3SDoug Rabson 640348c661SMarko Zec #include <net/vnet.h> 650348c661SMarko Zec 66dfdcada3SDoug Rabson #include <rpc/rpc.h> 67dfdcada3SDoug Rabson #include <rpc/rpcb_clnt.h> 68dfdcada3SDoug Rabson #include <rpc/nettype.h> 69dfdcada3SDoug Rabson 70ee31b83aSDoug Rabson #include <rpc/rpc_com.h> 71dfdcada3SDoug Rabson 72dfdcada3SDoug Rabson extern int __svc_vc_setflag(SVCXPRT *, int); 73dfdcada3SDoug Rabson 74dfdcada3SDoug Rabson /* 75dfdcada3SDoug Rabson * The highest level interface for server creation. 76dfdcada3SDoug Rabson * It tries for all the nettokens in that particular class of token 77dfdcada3SDoug Rabson * and returns the number of handles it can create and/or find. 78dfdcada3SDoug Rabson * 79dfdcada3SDoug Rabson * It creates a link list of all the handles it could create. 80dfdcada3SDoug Rabson * If svc_create() is called multiple times, it uses the handle 81dfdcada3SDoug Rabson * created earlier instead of creating a new handle every time. 82dfdcada3SDoug Rabson */ 83dfdcada3SDoug Rabson int 84dfdcada3SDoug Rabson svc_create( 85dfdcada3SDoug Rabson SVCPOOL *pool, 86dfdcada3SDoug Rabson void (*dispatch)(struct svc_req *, SVCXPRT *), 87dfdcada3SDoug Rabson rpcprog_t prognum, /* Program number */ 88dfdcada3SDoug Rabson rpcvers_t versnum, /* Version number */ 89dfdcada3SDoug Rabson const char *nettype) /* Networktype token */ 90dfdcada3SDoug Rabson { 91b563304cSAlexander Motin int g, num = 0; 92b563304cSAlexander Motin SVCGROUP *grp; 93dfdcada3SDoug Rabson SVCXPRT *xprt; 94dfdcada3SDoug Rabson struct netconfig *nconf; 95dfdcada3SDoug Rabson void *handle; 96dfdcada3SDoug Rabson 97dfdcada3SDoug Rabson if ((handle = __rpc_setconf(nettype)) == NULL) { 98dfdcada3SDoug Rabson printf("svc_create: unknown protocol"); 99dfdcada3SDoug Rabson return (0); 100dfdcada3SDoug Rabson } 101dfdcada3SDoug Rabson while ((nconf = __rpc_getconf(handle)) != NULL) { 102b563304cSAlexander Motin for (g = 0; g < SVC_MAXGROUPS; g++) { 103b563304cSAlexander Motin grp = &pool->sp_groups[g]; 104b563304cSAlexander Motin mtx_lock(&grp->sg_lock); 105b563304cSAlexander Motin TAILQ_FOREACH(xprt, &grp->sg_xlist, xp_link) { 106b563304cSAlexander Motin if (strcmp(xprt->xp_netid, nconf->nc_netid)) 107b563304cSAlexander Motin continue; 108dfdcada3SDoug Rabson /* Found an old one, use it */ 109b563304cSAlexander Motin mtx_unlock(&grp->sg_lock); 110dfdcada3SDoug Rabson (void) rpcb_unset(prognum, versnum, nconf); 111dfdcada3SDoug Rabson if (svc_reg(xprt, prognum, versnum, 112dfdcada3SDoug Rabson dispatch, nconf) == FALSE) { 113dfdcada3SDoug Rabson printf( 114dfdcada3SDoug Rabson "svc_create: could not register prog %u vers %u on %s\n", 115dfdcada3SDoug Rabson (unsigned)prognum, (unsigned)versnum, 116dfdcada3SDoug Rabson nconf->nc_netid); 117b563304cSAlexander Motin mtx_lock(&grp->sg_lock); 118dfdcada3SDoug Rabson } else { 119dfdcada3SDoug Rabson num++; 120b563304cSAlexander Motin mtx_lock(&grp->sg_lock); 121dfdcada3SDoug Rabson break; 122dfdcada3SDoug Rabson } 123dfdcada3SDoug Rabson } 124b563304cSAlexander Motin mtx_unlock(&grp->sg_lock); 125dfdcada3SDoug Rabson } 126dfdcada3SDoug Rabson if (xprt == NULL) { 127dfdcada3SDoug Rabson /* It was not found. Now create a new one */ 128dfdcada3SDoug Rabson xprt = svc_tp_create(pool, dispatch, prognum, versnum, 129dfdcada3SDoug Rabson NULL, nconf); 1306b97c9f0SRick Macklem if (xprt) { 131dfdcada3SDoug Rabson num++; 1326b97c9f0SRick Macklem SVC_RELEASE(xprt); 1336b97c9f0SRick Macklem } 134dfdcada3SDoug Rabson } 135dfdcada3SDoug Rabson } 136dfdcada3SDoug Rabson __rpc_endconf(handle); 137dfdcada3SDoug Rabson /* 138dfdcada3SDoug Rabson * In case of num == 0; the error messages are generated by the 139dfdcada3SDoug Rabson * underlying layers; and hence not needed here. 140dfdcada3SDoug Rabson */ 141dfdcada3SDoug Rabson return (num); 142dfdcada3SDoug Rabson } 143dfdcada3SDoug Rabson 144dfdcada3SDoug Rabson /* 145dfdcada3SDoug Rabson * The high level interface to svc_tli_create(). 146dfdcada3SDoug Rabson * It tries to create a server for "nconf" and registers the service 147dfdcada3SDoug Rabson * with the rpcbind. It calls svc_tli_create(); 148dfdcada3SDoug Rabson */ 149dfdcada3SDoug Rabson SVCXPRT * 150dfdcada3SDoug Rabson svc_tp_create( 151dfdcada3SDoug Rabson SVCPOOL *pool, 152dfdcada3SDoug Rabson void (*dispatch)(struct svc_req *, SVCXPRT *), 153dfdcada3SDoug Rabson rpcprog_t prognum, /* Program number */ 154dfdcada3SDoug Rabson rpcvers_t versnum, /* Version number */ 155dfdcada3SDoug Rabson const char *uaddr, /* Address (or null for default) */ 156dfdcada3SDoug Rabson const struct netconfig *nconf) /* Netconfig structure for the network */ 157dfdcada3SDoug Rabson { 158dfdcada3SDoug Rabson struct netconfig nconfcopy; 159dfdcada3SDoug Rabson struct netbuf *taddr; 160dfdcada3SDoug Rabson struct t_bind bind; 161dfdcada3SDoug Rabson SVCXPRT *xprt; 162dfdcada3SDoug Rabson 163dfdcada3SDoug Rabson if (nconf == NULL) { 164dfdcada3SDoug Rabson printf( 165dfdcada3SDoug Rabson "svc_tp_create: invalid netconfig structure for prog %u vers %u\n", 166dfdcada3SDoug Rabson (unsigned)prognum, (unsigned)versnum); 167dfdcada3SDoug Rabson return (NULL); 168dfdcada3SDoug Rabson } 169dfdcada3SDoug Rabson if (uaddr) { 170dfdcada3SDoug Rabson taddr = uaddr2taddr(nconf, uaddr); 171dfdcada3SDoug Rabson bind.addr = *taddr; 172dfdcada3SDoug Rabson free(taddr, M_RPC); 17380867e61SAlexander Motin bind.qlen = -1; 174dfdcada3SDoug Rabson xprt = svc_tli_create(pool, NULL, nconf, &bind, 0, 0); 175dfdcada3SDoug Rabson free(bind.addr.buf, M_RPC); 176dfdcada3SDoug Rabson } else { 177dfdcada3SDoug Rabson xprt = svc_tli_create(pool, NULL, nconf, NULL, 0, 0); 178dfdcada3SDoug Rabson } 179dfdcada3SDoug Rabson if (xprt == NULL) { 180dfdcada3SDoug Rabson return (NULL); 181dfdcada3SDoug Rabson } 182dfdcada3SDoug Rabson /*LINTED const castaway*/ 183dfdcada3SDoug Rabson nconfcopy = *nconf; 184dfdcada3SDoug Rabson (void) rpcb_unset(prognum, versnum, &nconfcopy); 185dfdcada3SDoug Rabson if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) { 186dfdcada3SDoug Rabson printf( 187dfdcada3SDoug Rabson "svc_tp_create: Could not register prog %u vers %u on %s\n", 188dfdcada3SDoug Rabson (unsigned)prognum, (unsigned)versnum, 189dfdcada3SDoug Rabson nconf->nc_netid); 190a9148abdSDoug Rabson xprt_unregister(xprt); 1916b97c9f0SRick Macklem SVC_RELEASE(xprt); 192dfdcada3SDoug Rabson return (NULL); 193dfdcada3SDoug Rabson } 194dfdcada3SDoug Rabson return (xprt); 195dfdcada3SDoug Rabson } 196dfdcada3SDoug Rabson 197dfdcada3SDoug Rabson /* 198dfdcada3SDoug Rabson * If so is NULL, then it opens a socket for the given transport 199dfdcada3SDoug Rabson * provider (nconf cannot be NULL then). If the t_state is T_UNBND and 200dfdcada3SDoug Rabson * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For 201dfdcada3SDoug Rabson * NULL bindadr and Connection oriented transports, the value of qlen 202dfdcada3SDoug Rabson * is set to 8. 203dfdcada3SDoug Rabson * 204dfdcada3SDoug Rabson * If sendsz or recvsz are zero, their default values are chosen. 205dfdcada3SDoug Rabson */ 206dfdcada3SDoug Rabson SVCXPRT * 207dfdcada3SDoug Rabson svc_tli_create( 208dfdcada3SDoug Rabson SVCPOOL *pool, 209dfdcada3SDoug Rabson struct socket *so, /* Connection end point */ 210dfdcada3SDoug Rabson const struct netconfig *nconf, /* Netconfig struct for nettoken */ 211dfdcada3SDoug Rabson const struct t_bind *bindaddr, /* Local bind address */ 212dfdcada3SDoug Rabson size_t sendsz, /* Max sendsize */ 213dfdcada3SDoug Rabson size_t recvsz) /* Max recvsize */ 214dfdcada3SDoug Rabson { 215dfdcada3SDoug Rabson SVCXPRT *xprt = NULL; /* service handle */ 216dfdcada3SDoug Rabson bool_t madeso = FALSE; /* whether so opened here */ 217dfdcada3SDoug Rabson struct __rpc_sockinfo si; 218dfdcada3SDoug Rabson struct sockaddr_storage ss; 219dfdcada3SDoug Rabson 220dfdcada3SDoug Rabson if (!so) { 221dfdcada3SDoug Rabson if (nconf == NULL) { 222dfdcada3SDoug Rabson printf("svc_tli_create: invalid netconfig\n"); 223dfdcada3SDoug Rabson return (NULL); 224dfdcada3SDoug Rabson } 225dfdcada3SDoug Rabson so = __rpc_nconf2socket(nconf); 226dfdcada3SDoug Rabson if (!so) { 227dfdcada3SDoug Rabson printf( 228dfdcada3SDoug Rabson "svc_tli_create: could not open connection for %s\n", 229dfdcada3SDoug Rabson nconf->nc_netid); 230dfdcada3SDoug Rabson return (NULL); 231dfdcada3SDoug Rabson } 232dfdcada3SDoug Rabson __rpc_nconf2sockinfo(nconf, &si); 233dfdcada3SDoug Rabson madeso = TRUE; 234dfdcada3SDoug Rabson } else { 235dfdcada3SDoug Rabson /* 236dfdcada3SDoug Rabson * It is an open socket. Get the transport info. 237dfdcada3SDoug Rabson */ 238dfdcada3SDoug Rabson if (!__rpc_socket2sockinfo(so, &si)) { 239dfdcada3SDoug Rabson printf( 240dfdcada3SDoug Rabson "svc_tli_create: could not get transport information\n"); 241dfdcada3SDoug Rabson return (NULL); 242dfdcada3SDoug Rabson } 243dfdcada3SDoug Rabson } 244dfdcada3SDoug Rabson 245dfdcada3SDoug Rabson /* 246dfdcada3SDoug Rabson * If the socket is unbound, try to bind it. 247dfdcada3SDoug Rabson */ 248dfdcada3SDoug Rabson if (madeso || !__rpc_sockisbound(so)) { 249dfdcada3SDoug Rabson if (bindaddr == NULL) { 250dfdcada3SDoug Rabson if (bindresvport(so, NULL)) { 251dfdcada3SDoug Rabson memset(&ss, 0, sizeof ss); 252dfdcada3SDoug Rabson ss.ss_family = si.si_af; 253dfdcada3SDoug Rabson ss.ss_len = si.si_alen; 254dfdcada3SDoug Rabson if (sobind(so, (struct sockaddr *)&ss, 255dfdcada3SDoug Rabson curthread)) { 256dfdcada3SDoug Rabson printf( 257dfdcada3SDoug Rabson "svc_tli_create: could not bind to anonymous port\n"); 258dfdcada3SDoug Rabson goto freedata; 259dfdcada3SDoug Rabson } 260dfdcada3SDoug Rabson } 26180867e61SAlexander Motin solisten(so, -1, curthread); 262dfdcada3SDoug Rabson } else { 263dfdcada3SDoug Rabson if (bindresvport(so, 264dfdcada3SDoug Rabson (struct sockaddr *)bindaddr->addr.buf)) { 265dfdcada3SDoug Rabson printf( 266dfdcada3SDoug Rabson "svc_tli_create: could not bind to requested address\n"); 267dfdcada3SDoug Rabson goto freedata; 268dfdcada3SDoug Rabson } 269dfdcada3SDoug Rabson solisten(so, (int)bindaddr->qlen, curthread); 270dfdcada3SDoug Rabson } 271dfdcada3SDoug Rabson 272dfdcada3SDoug Rabson } 273dfdcada3SDoug Rabson /* 274dfdcada3SDoug Rabson * call transport specific function. 275dfdcada3SDoug Rabson */ 276dfdcada3SDoug Rabson switch (si.si_socktype) { 277dfdcada3SDoug Rabson case SOCK_STREAM: 278dfdcada3SDoug Rabson #if 0 279dfdcada3SDoug Rabson slen = sizeof ss; 280dfdcada3SDoug Rabson if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) 281dfdcada3SDoug Rabson == 0) { 282dfdcada3SDoug Rabson /* accepted socket */ 283dfdcada3SDoug Rabson xprt = svc_fd_create(fd, sendsz, recvsz); 284dfdcada3SDoug Rabson } else 285dfdcada3SDoug Rabson #endif 286dfdcada3SDoug Rabson xprt = svc_vc_create(pool, so, sendsz, recvsz); 287dfdcada3SDoug Rabson if (!nconf || !xprt) 288dfdcada3SDoug Rabson break; 289dfdcada3SDoug Rabson #if 0 290dfdcada3SDoug Rabson /* XXX fvdl */ 291dfdcada3SDoug Rabson if (strcmp(nconf->nc_protofmly, "inet") == 0 || 292dfdcada3SDoug Rabson strcmp(nconf->nc_protofmly, "inet6") == 0) 293dfdcada3SDoug Rabson (void) __svc_vc_setflag(xprt, TRUE); 294dfdcada3SDoug Rabson #endif 295dfdcada3SDoug Rabson break; 296dfdcada3SDoug Rabson case SOCK_DGRAM: 297dfdcada3SDoug Rabson xprt = svc_dg_create(pool, so, sendsz, recvsz); 298dfdcada3SDoug Rabson break; 299dfdcada3SDoug Rabson default: 300dfdcada3SDoug Rabson printf("svc_tli_create: bad service type"); 301dfdcada3SDoug Rabson goto freedata; 302dfdcada3SDoug Rabson } 303dfdcada3SDoug Rabson 304dfdcada3SDoug Rabson if (xprt == NULL) 305dfdcada3SDoug Rabson /* 306dfdcada3SDoug Rabson * The error messages here are spitted out by the lower layers: 307dfdcada3SDoug Rabson * svc_vc_create(), svc_fd_create() and svc_dg_create(). 308dfdcada3SDoug Rabson */ 309dfdcada3SDoug Rabson goto freedata; 310dfdcada3SDoug Rabson 311dfdcada3SDoug Rabson /* Fill in type of service */ 312dfdcada3SDoug Rabson xprt->xp_type = __rpc_socktype2seman(si.si_socktype); 313dfdcada3SDoug Rabson 314dfdcada3SDoug Rabson if (nconf) { 315dfdcada3SDoug Rabson xprt->xp_netid = strdup(nconf->nc_netid, M_RPC); 316dfdcada3SDoug Rabson } 317dfdcada3SDoug Rabson return (xprt); 318dfdcada3SDoug Rabson 319dfdcada3SDoug Rabson freedata: 320dfdcada3SDoug Rabson if (madeso) 321dfdcada3SDoug Rabson (void)soclose(so); 322dfdcada3SDoug Rabson if (xprt) { 323dfdcada3SDoug Rabson if (!madeso) /* so that svc_destroy doesnt close fd */ 324dfdcada3SDoug Rabson xprt->xp_socket = NULL; 325a9148abdSDoug Rabson xprt_unregister(xprt); 326dfdcada3SDoug Rabson } 327dfdcada3SDoug Rabson return (NULL); 328dfdcada3SDoug Rabson } 329