svc_generic.c revision 92990
174462Salfred/* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */ 274462Salfred 374462Salfred/* 474462Salfred * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 574462Salfred * unrestricted use provided that this legend is included on all tape 674462Salfred * media and as a part of the software program in whole or part. Users 774462Salfred * may copy or modify Sun RPC without charge, but are not authorized 874462Salfred * to license or distribute it to anyone else except as part of a product or 974462Salfred * program developed by the user. 1074462Salfred * 1174462Salfred * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1274462Salfred * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1374462Salfred * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1474462Salfred * 1574462Salfred * Sun RPC is provided with no support and without any obligation on the 1674462Salfred * part of Sun Microsystems, Inc. to assist in its use, correction, 1774462Salfred * modification or enhancement. 1874462Salfred * 1974462Salfred * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2074462Salfred * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2174462Salfred * OR ANY PART THEREOF. 2274462Salfred * 2374462Salfred * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2474462Salfred * or profits or other special, indirect and consequential damages, even if 2574462Salfred * Sun has been advised of the possibility of such damages. 2674462Salfred * 2774462Salfred * Sun Microsystems, Inc. 2874462Salfred * 2550 Garcia Avenue 2974462Salfred * Mountain View, California 94043 3074462Salfred */ 3174462Salfred 3274462Salfred/* 3374462Salfred * Copyright (c) 1986-1991 by Sun Microsystems Inc. 3474462Salfred */ 3574462Salfred 3674462Salfred/* #ident "@(#)svc_generic.c 1.19 94/04/24 SMI" */ 3774462Salfred 3874462Salfred#if !defined(lint) && defined(SCCSIDS) 3974462Salfredstatic char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro"; 4074462Salfred#endif 4192990Sobrien#include <sys/cdefs.h> 4292990Sobrien__FBSDID("$FreeBSD: head/lib/libc/rpc/svc_generic.c 92990 2002-03-22 23:18:37Z obrien $"); 4374462Salfred 4474462Salfred/* 4574462Salfred * svc_generic.c, Server side for RPC. 4674462Salfred * 4774462Salfred */ 4874462Salfred 4975094Siedowse#include "namespace.h" 5074462Salfred#include "reentrant.h" 5174462Salfred#include <sys/types.h> 5274462Salfred#include <sys/socket.h> 5374462Salfred#include <netinet/in.h> 5474462Salfred#include <rpc/rpc.h> 5574462Salfred#include <rpc/nettype.h> 5674462Salfred#include <stdio.h> 5774462Salfred#include <errno.h> 5874462Salfred#include <stdlib.h> 5974462Salfred#include <string.h> 6074462Salfred#include <unistd.h> 6174462Salfred#include <err.h> 6274462Salfred#include "un-namespace.h" 6374462Salfred 6474462Salfred#include "rpc_com.h" 6574462Salfred 6692905Sobrienextern int __svc_vc_setflag(SVCXPRT *, int); 6774462Salfred 6874462Salfred/* 6974462Salfred * The highest level interface for server creation. 7074462Salfred * It tries for all the nettokens in that particular class of token 7174462Salfred * and returns the number of handles it can create and/or find. 7274462Salfred * 7374462Salfred * It creates a link list of all the handles it could create. 7474462Salfred * If svc_create() is called multiple times, it uses the handle 7574462Salfred * created earlier instead of creating a new handle every time. 7674462Salfred */ 7774462Salfredint 7874462Salfredsvc_create(dispatch, prognum, versnum, nettype) 7992905Sobrien void (*dispatch)(struct svc_req *, SVCXPRT *); 8074462Salfred rpcprog_t prognum; /* Program number */ 8174462Salfred rpcvers_t versnum; /* Version number */ 8274462Salfred const char *nettype; /* Networktype token */ 8374462Salfred{ 8474462Salfred struct xlist { 8574462Salfred SVCXPRT *xprt; /* Server handle */ 8674462Salfred struct xlist *next; /* Next item */ 8774462Salfred } *l; 8874462Salfred static struct xlist *xprtlist; /* A link list of all the handles */ 8974462Salfred int num = 0; 9074462Salfred SVCXPRT *xprt; 9174462Salfred struct netconfig *nconf; 9274462Salfred void *handle; 9374462Salfred extern mutex_t xprtlist_lock; 9474462Salfred 9574462Salfred/* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */ 9674462Salfred 9774462Salfred if ((handle = __rpc_setconf(nettype)) == NULL) { 9874462Salfred warnx("svc_create: unknown protocol"); 9974462Salfred return (0); 10074462Salfred } 10174462Salfred while ((nconf = __rpc_getconf(handle)) != NULL) { 10274462Salfred mutex_lock(&xprtlist_lock); 10374462Salfred for (l = xprtlist; l; l = l->next) { 10474462Salfred if (strcmp(l->xprt->xp_netid, nconf->nc_netid) == 0) { 10574462Salfred /* Found an old one, use it */ 10674462Salfred (void) rpcb_unset(prognum, versnum, nconf); 10774462Salfred if (svc_reg(l->xprt, prognum, versnum, 10874462Salfred dispatch, nconf) == FALSE) 10974462Salfred warnx( 11074462Salfred "svc_create: could not register prog %u vers %u on %s", 11174462Salfred (unsigned)prognum, (unsigned)versnum, 11274462Salfred nconf->nc_netid); 11374462Salfred else 11474462Salfred num++; 11574462Salfred break; 11674462Salfred } 11774462Salfred } 11874462Salfred if (l == NULL) { 11974462Salfred /* It was not found. Now create a new one */ 12074462Salfred xprt = svc_tp_create(dispatch, prognum, versnum, nconf); 12174462Salfred if (xprt) { 12274462Salfred l = (struct xlist *)malloc(sizeof (*l)); 12374462Salfred if (l == NULL) { 12474462Salfred warnx("svc_create: no memory"); 12574462Salfred mutex_unlock(&xprtlist_lock); 12674462Salfred return (0); 12774462Salfred } 12874462Salfred l->xprt = xprt; 12974462Salfred l->next = xprtlist; 13074462Salfred xprtlist = l; 13174462Salfred num++; 13274462Salfred } 13374462Salfred } 13474462Salfred mutex_unlock(&xprtlist_lock); 13574462Salfred } 13674462Salfred __rpc_endconf(handle); 13774462Salfred /* 13874462Salfred * In case of num == 0; the error messages are generated by the 13974462Salfred * underlying layers; and hence not needed here. 14074462Salfred */ 14174462Salfred return (num); 14274462Salfred} 14374462Salfred 14474462Salfred/* 14574462Salfred * The high level interface to svc_tli_create(). 14674462Salfred * It tries to create a server for "nconf" and registers the service 14774462Salfred * with the rpcbind. It calls svc_tli_create(); 14874462Salfred */ 14974462SalfredSVCXPRT * 15074462Salfredsvc_tp_create(dispatch, prognum, versnum, nconf) 15192905Sobrien void (*dispatch)(struct svc_req *, SVCXPRT *); 15274462Salfred rpcprog_t prognum; /* Program number */ 15374462Salfred rpcvers_t versnum; /* Version number */ 15474462Salfred const struct netconfig *nconf; /* Netconfig structure for the network */ 15574462Salfred{ 15674462Salfred SVCXPRT *xprt; 15774462Salfred 15874462Salfred if (nconf == NULL) { 15974462Salfred warnx( 16074462Salfred "svc_tp_create: invalid netconfig structure for prog %u vers %u", 16174462Salfred (unsigned)prognum, (unsigned)versnum); 16274462Salfred return (NULL); 16374462Salfred } 16474462Salfred xprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0); 16574462Salfred if (xprt == NULL) { 16674462Salfred return (NULL); 16774462Salfred } 16874462Salfred /*LINTED const castaway*/ 16974462Salfred (void) rpcb_unset(prognum, versnum, (struct netconfig *) nconf); 17074462Salfred if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) { 17174462Salfred warnx( 17274462Salfred "svc_tp_create: Could not register prog %u vers %u on %s", 17374462Salfred (unsigned)prognum, (unsigned)versnum, 17474462Salfred nconf->nc_netid); 17574462Salfred SVC_DESTROY(xprt); 17674462Salfred return (NULL); 17774462Salfred } 17874462Salfred return (xprt); 17974462Salfred} 18074462Salfred 18174462Salfred/* 18274462Salfred * If fd is RPC_ANYFD, then it opens a fd for the given transport 18374462Salfred * provider (nconf cannot be NULL then). If the t_state is T_UNBND and 18474462Salfred * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For 18574462Salfred * NULL bindadr and Connection oriented transports, the value of qlen 18674462Salfred * is set to 8. 18774462Salfred * 18874462Salfred * If sendsz or recvsz are zero, their default values are chosen. 18974462Salfred */ 19074462SalfredSVCXPRT * 19174462Salfredsvc_tli_create(fd, nconf, bindaddr, sendsz, recvsz) 19274462Salfred int fd; /* Connection end point */ 19374462Salfred const struct netconfig *nconf; /* Netconfig struct for nettoken */ 19474462Salfred const struct t_bind *bindaddr; /* Local bind address */ 19574462Salfred u_int sendsz; /* Max sendsize */ 19674462Salfred u_int recvsz; /* Max recvsize */ 19774462Salfred{ 19874462Salfred SVCXPRT *xprt = NULL; /* service handle */ 19974462Salfred bool_t madefd = FALSE; /* whether fd opened here */ 20074462Salfred struct __rpc_sockinfo si; 20174462Salfred struct sockaddr_storage ss; 20274462Salfred socklen_t slen; 20374462Salfred 20474462Salfred if (fd == RPC_ANYFD) { 20574462Salfred if (nconf == NULL) { 20674462Salfred warnx("svc_tli_create: invalid netconfig"); 20774462Salfred return (NULL); 20874462Salfred } 20974462Salfred fd = __rpc_nconf2fd(nconf); 21074462Salfred if (fd == -1) { 21174462Salfred warnx( 21274462Salfred "svc_tli_create: could not open connection for %s", 21374462Salfred nconf->nc_netid); 21474462Salfred return (NULL); 21574462Salfred } 21674462Salfred __rpc_nconf2sockinfo(nconf, &si); 21774462Salfred madefd = TRUE; 21874462Salfred } else { 21974462Salfred /* 22074462Salfred * It is an open descriptor. Get the transport info. 22174462Salfred */ 22274462Salfred if (!__rpc_fd2sockinfo(fd, &si)) { 22374462Salfred warnx( 22474462Salfred "svc_tli_create: could not get transport information"); 22574462Salfred return (NULL); 22674462Salfred } 22774462Salfred } 22874462Salfred 22974462Salfred /* 23074462Salfred * If the fd is unbound, try to bind it. 23174462Salfred */ 23274462Salfred if (madefd || !__rpc_sockisbound(fd)) { 23374462Salfred if (bindaddr == NULL) { 23474462Salfred if (bindresvport(fd, NULL) < 0) { 23574462Salfred memset(&ss, 0, sizeof ss); 23674462Salfred ss.ss_family = si.si_af; 23774462Salfred ss.ss_len = si.si_alen; 23874462Salfred if (_bind(fd, (struct sockaddr *)(void *)&ss, 23974462Salfred (socklen_t)si.si_alen) < 0) { 24074462Salfred warnx( 24174462Salfred "svc_tli_create: could not bind to anonymous port"); 24274462Salfred goto freedata; 24374462Salfred } 24474462Salfred } 24574462Salfred _listen(fd, SOMAXCONN); 24674462Salfred } else { 24774462Salfred if (_bind(fd, 24874462Salfred (struct sockaddr *)(void *)&bindaddr->addr.buf, 24974462Salfred (socklen_t)si.si_alen) < 0) { 25074462Salfred warnx( 25174462Salfred "svc_tli_create: could not bind to requested address"); 25274462Salfred goto freedata; 25374462Salfred } 25474462Salfred _listen(fd, (int)bindaddr->qlen); 25574462Salfred } 25674462Salfred 25774462Salfred } 25874462Salfred /* 25974462Salfred * call transport specific function. 26074462Salfred */ 26174462Salfred switch (si.si_socktype) { 26274462Salfred case SOCK_STREAM: 26374462Salfred slen = sizeof ss; 26474462Salfred if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) 26574462Salfred == 0) { 26674462Salfred /* accepted socket */ 26774462Salfred xprt = svc_fd_create(fd, sendsz, recvsz); 26874462Salfred } else 26974462Salfred xprt = svc_vc_create(fd, sendsz, recvsz); 27074462Salfred if (!nconf || !xprt) 27174462Salfred break; 27274462Salfred#if 0 27374462Salfred /* XXX fvdl */ 27474462Salfred if (strcmp(nconf->nc_protofmly, "inet") == 0 || 27574462Salfred strcmp(nconf->nc_protofmly, "inet6") == 0) 27674462Salfred (void) __svc_vc_setflag(xprt, TRUE); 27774462Salfred#endif 27874462Salfred break; 27974462Salfred case SOCK_DGRAM: 28074462Salfred xprt = svc_dg_create(fd, sendsz, recvsz); 28174462Salfred break; 28274462Salfred default: 28374462Salfred warnx("svc_tli_create: bad service type"); 28474462Salfred goto freedata; 28574462Salfred } 28674462Salfred 28774462Salfred if (xprt == NULL) 28874462Salfred /* 28974462Salfred * The error messages here are spitted out by the lower layers: 29074462Salfred * svc_vc_create(), svc_fd_create() and svc_dg_create(). 29174462Salfred */ 29274462Salfred goto freedata; 29374462Salfred 29474462Salfred /* Fill in type of service */ 29574462Salfred xprt->xp_type = __rpc_socktype2seman(si.si_socktype); 29674462Salfred 29774462Salfred if (nconf) { 29874462Salfred xprt->xp_netid = strdup(nconf->nc_netid); 29974462Salfred xprt->xp_tp = strdup(nconf->nc_device); 30074462Salfred } 30174462Salfred return (xprt); 30274462Salfred 30374462Salfredfreedata: 30474462Salfred if (madefd) 30574462Salfred (void)_close(fd); 30674462Salfred if (xprt) { 30774462Salfred if (!madefd) /* so that svc_destroy doesnt close fd */ 30874462Salfred xprt->xp_fd = RPC_ANYFD; 30974462Salfred SVC_DESTROY(xprt); 31074462Salfred } 31174462Salfred return (NULL); 31274462Salfred} 313