svc_generic.c revision 177633
1177633Sdfr/* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */ 2177633Sdfr 3177633Sdfr/* 4177633Sdfr * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5177633Sdfr * unrestricted use provided that this legend is included on all tape 6177633Sdfr * media and as a part of the software program in whole or part. Users 7177633Sdfr * may copy or modify Sun RPC without charge, but are not authorized 8177633Sdfr * to license or distribute it to anyone else except as part of a product or 9177633Sdfr * program developed by the user. 10177633Sdfr * 11177633Sdfr * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12177633Sdfr * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13177633Sdfr * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14177633Sdfr * 15177633Sdfr * Sun RPC is provided with no support and without any obligation on the 16177633Sdfr * part of Sun Microsystems, Inc. to assist in its use, correction, 17177633Sdfr * modification or enhancement. 18177633Sdfr * 19177633Sdfr * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20177633Sdfr * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21177633Sdfr * OR ANY PART THEREOF. 22177633Sdfr * 23177633Sdfr * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24177633Sdfr * or profits or other special, indirect and consequential damages, even if 25177633Sdfr * Sun has been advised of the possibility of such damages. 26177633Sdfr * 27177633Sdfr * Sun Microsystems, Inc. 28177633Sdfr * 2550 Garcia Avenue 29177633Sdfr * Mountain View, California 94043 30177633Sdfr */ 31177633Sdfr 32177633Sdfr/* 33177633Sdfr * Copyright (c) 1986-1991 by Sun Microsystems Inc. 34177633Sdfr */ 35177633Sdfr 36177633Sdfr#if defined(LIBC_SCCS) && !defined(lint) 37177633Sdfr#ident "@(#)svc_generic.c 1.19 94/04/24 SMI" 38177633Sdfrstatic char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro"; 39177633Sdfr#endif 40177633Sdfr#include <sys/cdefs.h> 41177633Sdfr__FBSDID("$FreeBSD: head/sys/rpc/svc_generic.c 177633 2008-03-26 15:23:12Z dfr $"); 42177633Sdfr 43177633Sdfr/* 44177633Sdfr * svc_generic.c, Server side for RPC. 45177633Sdfr * 46177633Sdfr */ 47177633Sdfr 48177633Sdfr#include "opt_inet6.h" 49177633Sdfr 50177633Sdfr#include <sys/param.h> 51177633Sdfr#include <sys/lock.h> 52177633Sdfr#include <sys/kernel.h> 53177633Sdfr#include <sys/malloc.h> 54177633Sdfr#include <sys/mutex.h> 55177633Sdfr#include <sys/protosw.h> 56177633Sdfr#include <sys/queue.h> 57177633Sdfr#include <sys/socket.h> 58177633Sdfr#include <sys/socketvar.h> 59177633Sdfr#include <sys/systm.h> 60177633Sdfr#include <sys/sx.h> 61177633Sdfr#include <sys/ucred.h> 62177633Sdfr 63177633Sdfr#include <rpc/rpc.h> 64177633Sdfr#include <rpc/rpcb_clnt.h> 65177633Sdfr#include <rpc/nettype.h> 66177633Sdfr 67177633Sdfr#include "rpc_com.h" 68177633Sdfr 69177633Sdfrextern int __svc_vc_setflag(SVCXPRT *, int); 70177633Sdfr 71177633Sdfr/* 72177633Sdfr * The highest level interface for server creation. 73177633Sdfr * It tries for all the nettokens in that particular class of token 74177633Sdfr * and returns the number of handles it can create and/or find. 75177633Sdfr * 76177633Sdfr * It creates a link list of all the handles it could create. 77177633Sdfr * If svc_create() is called multiple times, it uses the handle 78177633Sdfr * created earlier instead of creating a new handle every time. 79177633Sdfr */ 80177633Sdfrint 81177633Sdfrsvc_create( 82177633Sdfr SVCPOOL *pool, 83177633Sdfr void (*dispatch)(struct svc_req *, SVCXPRT *), 84177633Sdfr rpcprog_t prognum, /* Program number */ 85177633Sdfr rpcvers_t versnum, /* Version number */ 86177633Sdfr const char *nettype) /* Networktype token */ 87177633Sdfr{ 88177633Sdfr int num = 0; 89177633Sdfr SVCXPRT *xprt; 90177633Sdfr struct netconfig *nconf; 91177633Sdfr void *handle; 92177633Sdfr 93177633Sdfr if ((handle = __rpc_setconf(nettype)) == NULL) { 94177633Sdfr printf("svc_create: unknown protocol"); 95177633Sdfr return (0); 96177633Sdfr } 97177633Sdfr while ((nconf = __rpc_getconf(handle)) != NULL) { 98177633Sdfr mtx_lock(&pool->sp_lock); 99177633Sdfr TAILQ_FOREACH(xprt, &pool->sp_xlist, xp_link) { 100177633Sdfr if (strcmp(xprt->xp_netid, nconf->nc_netid) == 0) { 101177633Sdfr /* Found an old one, use it */ 102177633Sdfr mtx_unlock(&pool->sp_lock); 103177633Sdfr (void) rpcb_unset(prognum, versnum, nconf); 104177633Sdfr if (svc_reg(xprt, prognum, versnum, 105177633Sdfr dispatch, nconf) == FALSE) { 106177633Sdfr printf( 107177633Sdfr "svc_create: could not register prog %u vers %u on %s\n", 108177633Sdfr (unsigned)prognum, (unsigned)versnum, 109177633Sdfr nconf->nc_netid); 110177633Sdfr mtx_lock(&pool->sp_lock); 111177633Sdfr } else { 112177633Sdfr num++; 113177633Sdfr mtx_lock(&pool->sp_lock); 114177633Sdfr break; 115177633Sdfr } 116177633Sdfr } 117177633Sdfr } 118177633Sdfr mtx_unlock(&pool->sp_lock); 119177633Sdfr if (xprt == NULL) { 120177633Sdfr /* It was not found. Now create a new one */ 121177633Sdfr xprt = svc_tp_create(pool, dispatch, prognum, versnum, 122177633Sdfr NULL, nconf); 123177633Sdfr if (xprt) 124177633Sdfr num++; 125177633Sdfr } 126177633Sdfr } 127177633Sdfr __rpc_endconf(handle); 128177633Sdfr /* 129177633Sdfr * In case of num == 0; the error messages are generated by the 130177633Sdfr * underlying layers; and hence not needed here. 131177633Sdfr */ 132177633Sdfr return (num); 133177633Sdfr} 134177633Sdfr 135177633Sdfr/* 136177633Sdfr * The high level interface to svc_tli_create(). 137177633Sdfr * It tries to create a server for "nconf" and registers the service 138177633Sdfr * with the rpcbind. It calls svc_tli_create(); 139177633Sdfr */ 140177633SdfrSVCXPRT * 141177633Sdfrsvc_tp_create( 142177633Sdfr SVCPOOL *pool, 143177633Sdfr void (*dispatch)(struct svc_req *, SVCXPRT *), 144177633Sdfr rpcprog_t prognum, /* Program number */ 145177633Sdfr rpcvers_t versnum, /* Version number */ 146177633Sdfr const char *uaddr, /* Address (or null for default) */ 147177633Sdfr const struct netconfig *nconf) /* Netconfig structure for the network */ 148177633Sdfr{ 149177633Sdfr struct netconfig nconfcopy; 150177633Sdfr struct netbuf *taddr; 151177633Sdfr struct t_bind bind; 152177633Sdfr SVCXPRT *xprt; 153177633Sdfr 154177633Sdfr if (nconf == NULL) { 155177633Sdfr printf( 156177633Sdfr "svc_tp_create: invalid netconfig structure for prog %u vers %u\n", 157177633Sdfr (unsigned)prognum, (unsigned)versnum); 158177633Sdfr return (NULL); 159177633Sdfr } 160177633Sdfr if (uaddr) { 161177633Sdfr taddr = uaddr2taddr(nconf, uaddr); 162177633Sdfr bind.addr = *taddr; 163177633Sdfr free(taddr, M_RPC); 164177633Sdfr bind.qlen = SOMAXCONN; 165177633Sdfr xprt = svc_tli_create(pool, NULL, nconf, &bind, 0, 0); 166177633Sdfr free(bind.addr.buf, M_RPC); 167177633Sdfr } else { 168177633Sdfr xprt = svc_tli_create(pool, NULL, nconf, NULL, 0, 0); 169177633Sdfr } 170177633Sdfr if (xprt == NULL) { 171177633Sdfr return (NULL); 172177633Sdfr } 173177633Sdfr /*LINTED const castaway*/ 174177633Sdfr nconfcopy = *nconf; 175177633Sdfr (void) rpcb_unset(prognum, versnum, &nconfcopy); 176177633Sdfr if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) { 177177633Sdfr printf( 178177633Sdfr "svc_tp_create: Could not register prog %u vers %u on %s\n", 179177633Sdfr (unsigned)prognum, (unsigned)versnum, 180177633Sdfr nconf->nc_netid); 181177633Sdfr SVC_DESTROY(xprt); 182177633Sdfr return (NULL); 183177633Sdfr } 184177633Sdfr return (xprt); 185177633Sdfr} 186177633Sdfr 187177633Sdfr/* 188177633Sdfr * Bind a socket to a privileged IP port 189177633Sdfr */ 190177633Sdfrint bindresvport(struct socket *so, struct sockaddr *sa); 191177633Sdfrint 192177633Sdfrbindresvport(struct socket *so, struct sockaddr *sa) 193177633Sdfr{ 194177633Sdfr int old, error, af; 195177633Sdfr bool_t freesa = FALSE; 196177633Sdfr struct sockaddr_in *sin; 197177633Sdfr#ifdef INET6 198177633Sdfr struct sockaddr_in6 *sin6; 199177633Sdfr#endif 200177633Sdfr struct sockopt opt; 201177633Sdfr int proto, portrange, portlow; 202177633Sdfr u_int16_t *portp; 203177633Sdfr socklen_t salen; 204177633Sdfr 205177633Sdfr if (sa == NULL) { 206177633Sdfr error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); 207177633Sdfr if (error) 208177633Sdfr return (error); 209177633Sdfr freesa = TRUE; 210177633Sdfr af = sa->sa_family; 211177633Sdfr salen = sa->sa_len; 212177633Sdfr memset(sa, 0, sa->sa_len); 213177633Sdfr } else { 214177633Sdfr af = sa->sa_family; 215177633Sdfr salen = sa->sa_len; 216177633Sdfr } 217177633Sdfr 218177633Sdfr switch (af) { 219177633Sdfr case AF_INET: 220177633Sdfr proto = IPPROTO_IP; 221177633Sdfr portrange = IP_PORTRANGE; 222177633Sdfr portlow = IP_PORTRANGE_LOW; 223177633Sdfr sin = (struct sockaddr_in *)sa; 224177633Sdfr portp = &sin->sin_port; 225177633Sdfr break; 226177633Sdfr#ifdef INET6 227177633Sdfr case AF_INET6: 228177633Sdfr proto = IPPROTO_IPV6; 229177633Sdfr portrange = IPV6_PORTRANGE; 230177633Sdfr portlow = IPV6_PORTRANGE_LOW; 231177633Sdfr sin6 = (struct sockaddr_in6 *)sa; 232177633Sdfr portp = &sin6->sin6_port; 233177633Sdfr break; 234177633Sdfr#endif 235177633Sdfr default: 236177633Sdfr return (EPFNOSUPPORT); 237177633Sdfr } 238177633Sdfr 239177633Sdfr sa->sa_family = af; 240177633Sdfr sa->sa_len = salen; 241177633Sdfr 242177633Sdfr if (*portp == 0) { 243177633Sdfr bzero(&opt, sizeof(opt)); 244177633Sdfr opt.sopt_dir = SOPT_GET; 245177633Sdfr opt.sopt_level = proto; 246177633Sdfr opt.sopt_name = portrange; 247177633Sdfr opt.sopt_val = &old; 248177633Sdfr opt.sopt_valsize = sizeof(old); 249177633Sdfr error = sogetopt(so, &opt); 250177633Sdfr if (error) 251177633Sdfr goto out; 252177633Sdfr 253177633Sdfr opt.sopt_dir = SOPT_SET; 254177633Sdfr opt.sopt_val = &portlow; 255177633Sdfr error = sosetopt(so, &opt); 256177633Sdfr if (error) 257177633Sdfr goto out; 258177633Sdfr } 259177633Sdfr 260177633Sdfr error = sobind(so, sa, curthread); 261177633Sdfr 262177633Sdfr if (*portp == 0) { 263177633Sdfr if (error) { 264177633Sdfr opt.sopt_dir = SOPT_SET; 265177633Sdfr opt.sopt_val = &old; 266177633Sdfr sosetopt(so, &opt); 267177633Sdfr } 268177633Sdfr } 269177633Sdfrout: 270177633Sdfr if (freesa) 271177633Sdfr free(sa, M_SONAME); 272177633Sdfr 273177633Sdfr return (error); 274177633Sdfr} 275177633Sdfr 276177633Sdfr/* 277177633Sdfr * If so is NULL, then it opens a socket for the given transport 278177633Sdfr * provider (nconf cannot be NULL then). If the t_state is T_UNBND and 279177633Sdfr * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For 280177633Sdfr * NULL bindadr and Connection oriented transports, the value of qlen 281177633Sdfr * is set to 8. 282177633Sdfr * 283177633Sdfr * If sendsz or recvsz are zero, their default values are chosen. 284177633Sdfr */ 285177633SdfrSVCXPRT * 286177633Sdfrsvc_tli_create( 287177633Sdfr SVCPOOL *pool, 288177633Sdfr struct socket *so, /* Connection end point */ 289177633Sdfr const struct netconfig *nconf, /* Netconfig struct for nettoken */ 290177633Sdfr const struct t_bind *bindaddr, /* Local bind address */ 291177633Sdfr size_t sendsz, /* Max sendsize */ 292177633Sdfr size_t recvsz) /* Max recvsize */ 293177633Sdfr{ 294177633Sdfr SVCXPRT *xprt = NULL; /* service handle */ 295177633Sdfr bool_t madeso = FALSE; /* whether so opened here */ 296177633Sdfr struct __rpc_sockinfo si; 297177633Sdfr struct sockaddr_storage ss; 298177633Sdfr 299177633Sdfr if (!so) { 300177633Sdfr if (nconf == NULL) { 301177633Sdfr printf("svc_tli_create: invalid netconfig\n"); 302177633Sdfr return (NULL); 303177633Sdfr } 304177633Sdfr so = __rpc_nconf2socket(nconf); 305177633Sdfr if (!so) { 306177633Sdfr printf( 307177633Sdfr "svc_tli_create: could not open connection for %s\n", 308177633Sdfr nconf->nc_netid); 309177633Sdfr return (NULL); 310177633Sdfr } 311177633Sdfr __rpc_nconf2sockinfo(nconf, &si); 312177633Sdfr madeso = TRUE; 313177633Sdfr } else { 314177633Sdfr /* 315177633Sdfr * It is an open socket. Get the transport info. 316177633Sdfr */ 317177633Sdfr if (!__rpc_socket2sockinfo(so, &si)) { 318177633Sdfr printf( 319177633Sdfr "svc_tli_create: could not get transport information\n"); 320177633Sdfr return (NULL); 321177633Sdfr } 322177633Sdfr } 323177633Sdfr 324177633Sdfr /* 325177633Sdfr * If the socket is unbound, try to bind it. 326177633Sdfr */ 327177633Sdfr if (madeso || !__rpc_sockisbound(so)) { 328177633Sdfr if (bindaddr == NULL) { 329177633Sdfr if (bindresvport(so, NULL)) { 330177633Sdfr memset(&ss, 0, sizeof ss); 331177633Sdfr ss.ss_family = si.si_af; 332177633Sdfr ss.ss_len = si.si_alen; 333177633Sdfr if (sobind(so, (struct sockaddr *)&ss, 334177633Sdfr curthread)) { 335177633Sdfr printf( 336177633Sdfr "svc_tli_create: could not bind to anonymous port\n"); 337177633Sdfr goto freedata; 338177633Sdfr } 339177633Sdfr } 340177633Sdfr solisten(so, SOMAXCONN, curthread); 341177633Sdfr } else { 342177633Sdfr if (bindresvport(so, 343177633Sdfr (struct sockaddr *)bindaddr->addr.buf)) { 344177633Sdfr printf( 345177633Sdfr "svc_tli_create: could not bind to requested address\n"); 346177633Sdfr goto freedata; 347177633Sdfr } 348177633Sdfr solisten(so, (int)bindaddr->qlen, curthread); 349177633Sdfr } 350177633Sdfr 351177633Sdfr } 352177633Sdfr /* 353177633Sdfr * call transport specific function. 354177633Sdfr */ 355177633Sdfr switch (si.si_socktype) { 356177633Sdfr case SOCK_STREAM: 357177633Sdfr#if 0 358177633Sdfr slen = sizeof ss; 359177633Sdfr if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) 360177633Sdfr == 0) { 361177633Sdfr /* accepted socket */ 362177633Sdfr xprt = svc_fd_create(fd, sendsz, recvsz); 363177633Sdfr } else 364177633Sdfr#endif 365177633Sdfr xprt = svc_vc_create(pool, so, sendsz, recvsz); 366177633Sdfr if (!nconf || !xprt) 367177633Sdfr break; 368177633Sdfr#if 0 369177633Sdfr /* XXX fvdl */ 370177633Sdfr if (strcmp(nconf->nc_protofmly, "inet") == 0 || 371177633Sdfr strcmp(nconf->nc_protofmly, "inet6") == 0) 372177633Sdfr (void) __svc_vc_setflag(xprt, TRUE); 373177633Sdfr#endif 374177633Sdfr break; 375177633Sdfr case SOCK_DGRAM: 376177633Sdfr xprt = svc_dg_create(pool, so, sendsz, recvsz); 377177633Sdfr break; 378177633Sdfr default: 379177633Sdfr printf("svc_tli_create: bad service type"); 380177633Sdfr goto freedata; 381177633Sdfr } 382177633Sdfr 383177633Sdfr if (xprt == NULL) 384177633Sdfr /* 385177633Sdfr * The error messages here are spitted out by the lower layers: 386177633Sdfr * svc_vc_create(), svc_fd_create() and svc_dg_create(). 387177633Sdfr */ 388177633Sdfr goto freedata; 389177633Sdfr 390177633Sdfr /* Fill in type of service */ 391177633Sdfr xprt->xp_type = __rpc_socktype2seman(si.si_socktype); 392177633Sdfr 393177633Sdfr if (nconf) { 394177633Sdfr xprt->xp_netid = strdup(nconf->nc_netid, M_RPC); 395177633Sdfr } 396177633Sdfr return (xprt); 397177633Sdfr 398177633Sdfrfreedata: 399177633Sdfr if (madeso) 400177633Sdfr (void)soclose(so); 401177633Sdfr if (xprt) { 402177633Sdfr if (!madeso) /* so that svc_destroy doesnt close fd */ 403177633Sdfr xprt->xp_socket = NULL; 404177633Sdfr SVC_DESTROY(xprt); 405177633Sdfr } 406177633Sdfr return (NULL); 407177633Sdfr} 408