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