1177633Sdfr/* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */ 2177633Sdfr 3261046Smav/*- 4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc. 5261046Smav * All rights reserved. 6261046Smav * 7261046Smav * Redistribution and use in source and binary forms, with or without 8261046Smav * modification, are permitted provided that the following conditions are met: 9261046Smav * - Redistributions of source code must retain the above copyright notice, 10261046Smav * this list of conditions and the following disclaimer. 11261046Smav * - Redistributions in binary form must reproduce the above copyright notice, 12261046Smav * this list of conditions and the following disclaimer in the documentation 13261046Smav * and/or other materials provided with the distribution. 14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its 15261046Smav * contributors may be used to endorse or promote products derived 16261046Smav * from this software without specific prior written permission. 17177633Sdfr * 18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28261046Smav * POSSIBILITY OF SUCH DAMAGE. 29177633Sdfr */ 30177633Sdfr 31177633Sdfr/* 32177633Sdfr * Copyright (c) 1986-1991 by Sun Microsystems Inc. 33177633Sdfr */ 34177633Sdfr 35177633Sdfr#if defined(LIBC_SCCS) && !defined(lint) 36177633Sdfr#ident "@(#)svc_generic.c 1.19 94/04/24 SMI" 37177633Sdfrstatic char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro"; 38177633Sdfr#endif 39177633Sdfr#include <sys/cdefs.h> 40177633Sdfr__FBSDID("$FreeBSD$"); 41177633Sdfr 42177633Sdfr/* 43177633Sdfr * svc_generic.c, Server side for RPC. 44177633Sdfr * 45177633Sdfr */ 46177633Sdfr 47177633Sdfr#include "opt_inet6.h" 48177633Sdfr 49177633Sdfr#include <sys/param.h> 50177633Sdfr#include <sys/lock.h> 51177633Sdfr#include <sys/kernel.h> 52177633Sdfr#include <sys/malloc.h> 53177633Sdfr#include <sys/mutex.h> 54177633Sdfr#include <sys/protosw.h> 55177633Sdfr#include <sys/queue.h> 56177633Sdfr#include <sys/socket.h> 57177633Sdfr#include <sys/socketvar.h> 58177633Sdfr#include <sys/systm.h> 59177633Sdfr#include <sys/sx.h> 60177633Sdfr#include <sys/ucred.h> 61177633Sdfr 62196503Szec#include <net/vnet.h> 63196503Szec 64177633Sdfr#include <rpc/rpc.h> 65177633Sdfr#include <rpc/rpcb_clnt.h> 66177633Sdfr#include <rpc/nettype.h> 67177633Sdfr 68177685Sdfr#include <rpc/rpc_com.h> 69177633Sdfr 70177633Sdfrextern int __svc_vc_setflag(SVCXPRT *, int); 71177633Sdfr 72177633Sdfr/* 73177633Sdfr * The highest level interface for server creation. 74177633Sdfr * It tries for all the nettokens in that particular class of token 75177633Sdfr * and returns the number of handles it can create and/or find. 76177633Sdfr * 77177633Sdfr * It creates a link list of all the handles it could create. 78177633Sdfr * If svc_create() is called multiple times, it uses the handle 79177633Sdfr * created earlier instead of creating a new handle every time. 80177633Sdfr */ 81177633Sdfrint 82177633Sdfrsvc_create( 83177633Sdfr SVCPOOL *pool, 84177633Sdfr void (*dispatch)(struct svc_req *, SVCXPRT *), 85177633Sdfr rpcprog_t prognum, /* Program number */ 86177633Sdfr rpcvers_t versnum, /* Version number */ 87177633Sdfr const char *nettype) /* Networktype token */ 88177633Sdfr{ 89267742Smav int g, num = 0; 90267742Smav SVCGROUP *grp; 91177633Sdfr SVCXPRT *xprt; 92177633Sdfr struct netconfig *nconf; 93177633Sdfr void *handle; 94177633Sdfr 95177633Sdfr if ((handle = __rpc_setconf(nettype)) == NULL) { 96177633Sdfr printf("svc_create: unknown protocol"); 97177633Sdfr return (0); 98177633Sdfr } 99177633Sdfr while ((nconf = __rpc_getconf(handle)) != NULL) { 100267742Smav for (g = 0; g < SVC_MAXGROUPS; g++) { 101267742Smav grp = &pool->sp_groups[g]; 102267742Smav mtx_lock(&grp->sg_lock); 103267742Smav TAILQ_FOREACH(xprt, &grp->sg_xlist, xp_link) { 104267742Smav if (strcmp(xprt->xp_netid, nconf->nc_netid)) 105267742Smav continue; 106177633Sdfr /* Found an old one, use it */ 107267742Smav mtx_unlock(&grp->sg_lock); 108177633Sdfr (void) rpcb_unset(prognum, versnum, nconf); 109177633Sdfr if (svc_reg(xprt, prognum, versnum, 110177633Sdfr dispatch, nconf) == FALSE) { 111177633Sdfr printf( 112177633Sdfr "svc_create: could not register prog %u vers %u on %s\n", 113177633Sdfr (unsigned)prognum, (unsigned)versnum, 114177633Sdfr nconf->nc_netid); 115267742Smav mtx_lock(&grp->sg_lock); 116177633Sdfr } else { 117177633Sdfr num++; 118267742Smav mtx_lock(&grp->sg_lock); 119177633Sdfr break; 120177633Sdfr } 121177633Sdfr } 122267742Smav mtx_unlock(&grp->sg_lock); 123177633Sdfr } 124177633Sdfr if (xprt == NULL) { 125177633Sdfr /* It was not found. Now create a new one */ 126177633Sdfr xprt = svc_tp_create(pool, dispatch, prognum, versnum, 127177633Sdfr NULL, nconf); 128194407Srmacklem if (xprt) { 129177633Sdfr num++; 130194407Srmacklem SVC_RELEASE(xprt); 131194407Srmacklem } 132177633Sdfr } 133177633Sdfr } 134177633Sdfr __rpc_endconf(handle); 135177633Sdfr /* 136177633Sdfr * In case of num == 0; the error messages are generated by the 137177633Sdfr * underlying layers; and hence not needed here. 138177633Sdfr */ 139177633Sdfr return (num); 140177633Sdfr} 141177633Sdfr 142177633Sdfr/* 143177633Sdfr * The high level interface to svc_tli_create(). 144177633Sdfr * It tries to create a server for "nconf" and registers the service 145177633Sdfr * with the rpcbind. It calls svc_tli_create(); 146177633Sdfr */ 147177633SdfrSVCXPRT * 148177633Sdfrsvc_tp_create( 149177633Sdfr SVCPOOL *pool, 150177633Sdfr void (*dispatch)(struct svc_req *, SVCXPRT *), 151177633Sdfr rpcprog_t prognum, /* Program number */ 152177633Sdfr rpcvers_t versnum, /* Version number */ 153177633Sdfr const char *uaddr, /* Address (or null for default) */ 154177633Sdfr const struct netconfig *nconf) /* Netconfig structure for the network */ 155177633Sdfr{ 156177633Sdfr struct netconfig nconfcopy; 157177633Sdfr struct netbuf *taddr; 158177633Sdfr struct t_bind bind; 159177633Sdfr SVCXPRT *xprt; 160177633Sdfr 161177633Sdfr if (nconf == NULL) { 162177633Sdfr printf( 163177633Sdfr "svc_tp_create: invalid netconfig structure for prog %u vers %u\n", 164177633Sdfr (unsigned)prognum, (unsigned)versnum); 165177633Sdfr return (NULL); 166177633Sdfr } 167177633Sdfr if (uaddr) { 168177633Sdfr taddr = uaddr2taddr(nconf, uaddr); 169177633Sdfr bind.addr = *taddr; 170177633Sdfr free(taddr, M_RPC); 171177633Sdfr bind.qlen = SOMAXCONN; 172177633Sdfr xprt = svc_tli_create(pool, NULL, nconf, &bind, 0, 0); 173177633Sdfr free(bind.addr.buf, M_RPC); 174177633Sdfr } else { 175177633Sdfr xprt = svc_tli_create(pool, NULL, nconf, NULL, 0, 0); 176177633Sdfr } 177177633Sdfr if (xprt == NULL) { 178177633Sdfr return (NULL); 179177633Sdfr } 180177633Sdfr /*LINTED const castaway*/ 181177633Sdfr nconfcopy = *nconf; 182177633Sdfr (void) rpcb_unset(prognum, versnum, &nconfcopy); 183177633Sdfr if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) { 184177633Sdfr printf( 185177633Sdfr "svc_tp_create: Could not register prog %u vers %u on %s\n", 186177633Sdfr (unsigned)prognum, (unsigned)versnum, 187177633Sdfr nconf->nc_netid); 188184588Sdfr xprt_unregister(xprt); 189194407Srmacklem SVC_RELEASE(xprt); 190177633Sdfr return (NULL); 191177633Sdfr } 192177633Sdfr return (xprt); 193177633Sdfr} 194177633Sdfr 195177633Sdfr/* 196177633Sdfr * If so is NULL, then it opens a socket for the given transport 197177633Sdfr * provider (nconf cannot be NULL then). If the t_state is T_UNBND and 198177633Sdfr * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For 199177633Sdfr * NULL bindadr and Connection oriented transports, the value of qlen 200177633Sdfr * is set to 8. 201177633Sdfr * 202177633Sdfr * If sendsz or recvsz are zero, their default values are chosen. 203177633Sdfr */ 204177633SdfrSVCXPRT * 205177633Sdfrsvc_tli_create( 206177633Sdfr SVCPOOL *pool, 207177633Sdfr struct socket *so, /* Connection end point */ 208177633Sdfr const struct netconfig *nconf, /* Netconfig struct for nettoken */ 209177633Sdfr const struct t_bind *bindaddr, /* Local bind address */ 210177633Sdfr size_t sendsz, /* Max sendsize */ 211177633Sdfr size_t recvsz) /* Max recvsize */ 212177633Sdfr{ 213177633Sdfr SVCXPRT *xprt = NULL; /* service handle */ 214177633Sdfr bool_t madeso = FALSE; /* whether so opened here */ 215177633Sdfr struct __rpc_sockinfo si; 216177633Sdfr struct sockaddr_storage ss; 217177633Sdfr 218177633Sdfr if (!so) { 219177633Sdfr if (nconf == NULL) { 220177633Sdfr printf("svc_tli_create: invalid netconfig\n"); 221177633Sdfr return (NULL); 222177633Sdfr } 223177633Sdfr so = __rpc_nconf2socket(nconf); 224177633Sdfr if (!so) { 225177633Sdfr printf( 226177633Sdfr "svc_tli_create: could not open connection for %s\n", 227177633Sdfr nconf->nc_netid); 228177633Sdfr return (NULL); 229177633Sdfr } 230177633Sdfr __rpc_nconf2sockinfo(nconf, &si); 231177633Sdfr madeso = TRUE; 232177633Sdfr } else { 233177633Sdfr /* 234177633Sdfr * It is an open socket. Get the transport info. 235177633Sdfr */ 236177633Sdfr if (!__rpc_socket2sockinfo(so, &si)) { 237177633Sdfr printf( 238177633Sdfr "svc_tli_create: could not get transport information\n"); 239177633Sdfr return (NULL); 240177633Sdfr } 241177633Sdfr } 242177633Sdfr 243177633Sdfr /* 244177633Sdfr * If the socket is unbound, try to bind it. 245177633Sdfr */ 246177633Sdfr if (madeso || !__rpc_sockisbound(so)) { 247177633Sdfr if (bindaddr == NULL) { 248177633Sdfr if (bindresvport(so, NULL)) { 249177633Sdfr memset(&ss, 0, sizeof ss); 250177633Sdfr ss.ss_family = si.si_af; 251177633Sdfr ss.ss_len = si.si_alen; 252177633Sdfr if (sobind(so, (struct sockaddr *)&ss, 253177633Sdfr curthread)) { 254177633Sdfr printf( 255177633Sdfr "svc_tli_create: could not bind to anonymous port\n"); 256177633Sdfr goto freedata; 257177633Sdfr } 258177633Sdfr } 259177633Sdfr solisten(so, SOMAXCONN, curthread); 260177633Sdfr } else { 261177633Sdfr if (bindresvport(so, 262177633Sdfr (struct sockaddr *)bindaddr->addr.buf)) { 263177633Sdfr printf( 264177633Sdfr "svc_tli_create: could not bind to requested address\n"); 265177633Sdfr goto freedata; 266177633Sdfr } 267177633Sdfr solisten(so, (int)bindaddr->qlen, curthread); 268177633Sdfr } 269177633Sdfr 270177633Sdfr } 271177633Sdfr /* 272177633Sdfr * call transport specific function. 273177633Sdfr */ 274177633Sdfr switch (si.si_socktype) { 275177633Sdfr case SOCK_STREAM: 276177633Sdfr#if 0 277177633Sdfr slen = sizeof ss; 278177633Sdfr if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) 279177633Sdfr == 0) { 280177633Sdfr /* accepted socket */ 281177633Sdfr xprt = svc_fd_create(fd, sendsz, recvsz); 282177633Sdfr } else 283177633Sdfr#endif 284177633Sdfr xprt = svc_vc_create(pool, so, sendsz, recvsz); 285177633Sdfr if (!nconf || !xprt) 286177633Sdfr break; 287177633Sdfr#if 0 288177633Sdfr /* XXX fvdl */ 289177633Sdfr if (strcmp(nconf->nc_protofmly, "inet") == 0 || 290177633Sdfr strcmp(nconf->nc_protofmly, "inet6") == 0) 291177633Sdfr (void) __svc_vc_setflag(xprt, TRUE); 292177633Sdfr#endif 293177633Sdfr break; 294177633Sdfr case SOCK_DGRAM: 295177633Sdfr xprt = svc_dg_create(pool, so, sendsz, recvsz); 296177633Sdfr break; 297177633Sdfr default: 298177633Sdfr printf("svc_tli_create: bad service type"); 299177633Sdfr goto freedata; 300177633Sdfr } 301177633Sdfr 302177633Sdfr if (xprt == NULL) 303177633Sdfr /* 304177633Sdfr * The error messages here are spitted out by the lower layers: 305177633Sdfr * svc_vc_create(), svc_fd_create() and svc_dg_create(). 306177633Sdfr */ 307177633Sdfr goto freedata; 308177633Sdfr 309177633Sdfr /* Fill in type of service */ 310177633Sdfr xprt->xp_type = __rpc_socktype2seman(si.si_socktype); 311177633Sdfr 312177633Sdfr if (nconf) { 313177633Sdfr xprt->xp_netid = strdup(nconf->nc_netid, M_RPC); 314177633Sdfr } 315177633Sdfr return (xprt); 316177633Sdfr 317177633Sdfrfreedata: 318177633Sdfr if (madeso) 319177633Sdfr (void)soclose(so); 320177633Sdfr if (xprt) { 321177633Sdfr if (!madeso) /* so that svc_destroy doesnt close fd */ 322177633Sdfr xprt->xp_socket = NULL; 323184588Sdfr xprt_unregister(xprt); 324177633Sdfr } 325177633Sdfr return (NULL); 326177633Sdfr} 327