/* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */12/*-3* SPDX-License-Identifier: BSD-3-Clause4*5* Copyright (c) 2009, Sun Microsystems, Inc.6* All rights reserved.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions are met:10* - Redistributions of source code must retain the above copyright notice,11* this list of conditions and the following disclaimer.12* - Redistributions in binary form must reproduce the above copyright notice,13* this list of conditions and the following disclaimer in the documentation14* and/or other materials provided with the distribution.15* - Neither the name of Sun Microsystems, Inc. nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"20* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE22* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE23* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR24* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF25* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS26* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN27* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE29* POSSIBILITY OF SUCH DAMAGE.30*/3132/*33* Copyright (c) 1986-1991 by Sun Microsystems Inc.34*/3536/*37* svc_generic.c, Server side for RPC.38*39*/4041#include "opt_inet6.h"4243#include <sys/param.h>44#include <sys/lock.h>45#include <sys/kernel.h>46#include <sys/malloc.h>47#include <sys/mutex.h>48#include <sys/protosw.h>49#include <sys/queue.h>50#include <sys/socket.h>51#include <sys/socketvar.h>52#include <sys/systm.h>53#include <sys/sx.h>54#include <sys/ucred.h>5556#include <net/vnet.h>5758#include <rpc/rpc.h>59#include <rpc/rpcb_clnt.h>60#include <rpc/nettype.h>6162#include <rpc/rpc_com.h>6364extern int __svc_vc_setflag(SVCXPRT *, int);6566/*67* The high level interface to svc_tli_create().68* It tries to create a server for "nconf" and registers the service69* with the rpcbind. It calls svc_tli_create();70*/71SVCXPRT *72svc_tp_create(73SVCPOOL *pool,74void (*dispatch)(struct svc_req *, SVCXPRT *),75rpcprog_t prognum, /* Program number */76rpcvers_t versnum, /* Version number */77const char *uaddr, /* Address (or null for default) */78const struct netconfig *nconf) /* Netconfig structure for the network */79{80struct netconfig nconfcopy;81struct netbuf *taddr;82struct t_bind bind;83SVCXPRT *xprt;8485if (nconf == NULL) {86printf(87"svc_tp_create: invalid netconfig structure for prog %u vers %u\n",88(unsigned)prognum, (unsigned)versnum);89return (NULL);90}91if (uaddr) {92taddr = uaddr2taddr(nconf, uaddr);93bind.addr = *taddr;94free(taddr, M_RPC);95bind.qlen = -1;96xprt = svc_tli_create(pool, nconf, &bind, 0, 0);97free(bind.addr.buf, M_RPC);98} else {99xprt = svc_tli_create(pool, nconf, NULL, 0, 0);100}101if (xprt == NULL) {102return (NULL);103}104/*LINTED const castaway*/105nconfcopy = *nconf;106(void) rpcb_unset(prognum, versnum, &nconfcopy);107if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {108printf(109"svc_tp_create: Could not register prog %u vers %u on %s\n",110(unsigned)prognum, (unsigned)versnum,111nconf->nc_netid);112xprt_unregister(xprt);113SVC_RELEASE(xprt);114return (NULL);115}116return (xprt);117}118119/*120* If so is NULL, then it opens a socket for the given transport121* provider (nconf cannot be NULL then). If the t_state is T_UNBND and122* bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For123* NULL bindadr and Connection oriented transports, the value of qlen124* is set to 8.125*126* If sendsz or recvsz are zero, their default values are chosen.127*/128SVCXPRT *129svc_tli_create(130SVCPOOL *pool,131const struct netconfig *nconf, /* Netconfig struct for nettoken */132const struct t_bind *bindaddr, /* Local bind address */133size_t sendsz, /* Max sendsize */134size_t recvsz) /* Max recvsize */135{136struct socket *so;137SVCXPRT *xprt = NULL; /* service handle */138struct __rpc_sockinfo si;139struct sockaddr_storage ss;140141if (nconf == NULL) {142printf("svc_tli_create: invalid netconfig\n");143return (NULL);144}145so = __rpc_nconf2socket(nconf);146if (!so) {147printf(148"svc_tli_create: could not open connection for %s\n",149nconf->nc_netid);150return (NULL);151}152__rpc_nconf2sockinfo(nconf, &si);153154if (bindaddr == NULL) {155if (bindresvport(so, NULL)) {156memset(&ss, 0, sizeof ss);157ss.ss_family = si.si_af;158ss.ss_len = si.si_alen;159if (sobind(so, (struct sockaddr *)&ss,160curthread)) {161printf(162"svc_tli_create: could not bind to anonymous port\n");163goto freedata;164}165}166solisten(so, -1, curthread);167} else {168if (bindresvport(so,169(struct sockaddr *)bindaddr->addr.buf)) {170printf(171"svc_tli_create: could not bind to requested address\n");172goto freedata;173}174solisten(so, (int)bindaddr->qlen, curthread);175}176177/*178* call transport specific function.179*/180switch (si.si_socktype) {181case SOCK_STREAM:182#if 0183slen = sizeof ss;184if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen)185== 0) {186/* accepted socket */187xprt = svc_fd_create(fd, sendsz, recvsz);188} else189#endif190xprt = svc_vc_create(pool, so, sendsz, recvsz);191if (!nconf || !xprt)192break;193#if 0194/* XXX fvdl */195if (strcmp(nconf->nc_protofmly, "inet") == 0 ||196strcmp(nconf->nc_protofmly, "inet6") == 0)197(void) __svc_vc_setflag(xprt, TRUE);198#endif199break;200case SOCK_DGRAM:201xprt = svc_dg_create(pool, so, sendsz, recvsz);202break;203default:204printf("svc_tli_create: bad service type");205goto freedata;206}207208if (xprt == NULL)209/*210* The error messages here are spitted out by the lower layers:211* svc_vc_create(), svc_fd_create() and svc_dg_create().212*/213goto freedata;214215/* Fill in type of service */216xprt->xp_type = __rpc_socktype2seman(si.si_socktype);217218if (nconf) {219xprt->xp_netid = strdup(nconf->nc_netid, M_RPC);220}221return (xprt);222223freedata:224(void)soclose(so);225if (xprt)226xprt_unregister(xprt);227return (NULL);228}229230231