1 2 /* 3 * Copyright (c) 2009, Sun Microsystems, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * - Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * - Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * - Neither the name of Sun Microsystems, Inc. nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 32 */ 33 34 /* 35 * svc_generic.c, Server side for RPC. 36 * 37 */ 38 #include <wintirpc.h> 39 //#include <pthread.h> 40 #include <reentrant.h> 41 #include <sys/types.h> 42 //#include <sys/socket.h> 43 //#include <netinet/in.h> 44 #include <rpc/rpc.h> 45 #include <rpc/nettype.h> 46 #include <stdio.h> 47 #include <errno.h> 48 #include <stdlib.h> 49 #include <string.h> 50 //#include <unistd.h> 51 //#include <err.h> 52 53 #include "rpc_com.h" 54 #include <rpc/svc.h> 55 56 extern int __svc_vc_setflag(SVCXPRT *, int); 57 58 /* 59 * The highest level interface for server creation. 60 * It tries for all the nettokens in that particular class of token 61 * and returns the number of handles it can create and/or find. 62 * 63 * It creates a link list of all the handles it could create. 64 * If svc_create() is called multiple times, it uses the handle 65 * created earlier instead of creating a new handle every time. 66 */ 67 int 68 svc_create(dispatch, prognum, versnum, nettype) 69 void (*dispatch)(struct svc_req *, SVCXPRT *); 70 rpcprog_t prognum; /* Program number */ 71 rpcvers_t versnum; /* Version number */ 72 const char *nettype; /* Networktype token */ 73 { 74 struct xlist { 75 SVCXPRT *xprt; /* Server handle */ 76 struct xlist *next; /* Next item */ 77 } *l; 78 static struct xlist *xprtlist; /* A link list of all the handles */ 79 int num = 0; 80 SVCXPRT *xprt; 81 struct netconfig *nconf; 82 void *handle; 83 extern mutex_t xprtlist_lock; 84 85 /* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */ 86 87 if ((handle = __rpc_setconf(nettype)) == NULL) { 88 // XXX warnx("svc_create: unknown protocol"); 89 return (0); 90 } 91 while ((nconf = __rpc_getconf(handle)) != NULL) { 92 mutex_lock(&xprtlist_lock); 93 for (l = xprtlist; l; l = l->next) { 94 if (strcmp(l->xprt->xp_netid, nconf->nc_netid) == 0) { 95 /* Found an old one, use it */ 96 (void) rpcb_unset(prognum, versnum, nconf); 97 if (svc_reg(l->xprt, prognum, versnum, 98 dispatch, nconf) == FALSE) { 99 // XXX warnx( 100 // "svc_create: could not register prog %u vers %u on %s", 101 // (unsigned)prognum, (unsigned)versnum, 102 // nconf->nc_netid); 103 } else { 104 num++; 105 } 106 break; 107 } 108 } 109 if (l == NULL) { 110 /* It was not found. Now create a new one */ 111 xprt = svc_tp_create(dispatch, prognum, versnum, nconf); 112 if (xprt) { 113 l = (struct xlist *)malloc(sizeof (*l)); 114 if (l == NULL) { 115 // XXX warnx("svc_create: no memory"); 116 mutex_unlock(&xprtlist_lock); 117 return (0); 118 } 119 l->xprt = xprt; 120 l->next = xprtlist; 121 xprtlist = l; 122 num++; 123 } 124 } 125 mutex_unlock(&xprtlist_lock); 126 } 127 __rpc_endconf(handle); 128 /* 129 * In case of num == 0; the error messages are generated by the 130 * underlying layers; and hence not needed here. 131 */ 132 return (num); 133 } 134 135 /* 136 * The high level interface to svc_tli_create(). 137 * It tries to create a server for "nconf" and registers the service 138 * with the rpcbind. It calls svc_tli_create(); 139 */ 140 SVCXPRT * 141 svc_tp_create(dispatch, prognum, versnum, nconf) 142 void (*dispatch)(struct svc_req *, SVCXPRT *); 143 rpcprog_t prognum; /* Program number */ 144 rpcvers_t versnum; /* Version number */ 145 const struct netconfig *nconf; /* Netconfig structure for the network */ 146 { 147 SVCXPRT *xprt; 148 149 if (nconf == NULL) { 150 // XXX warnx( 151 // "svc_tp_create: invalid netconfig structure for prog %u vers %u", 152 // (unsigned)prognum, (unsigned)versnum); 153 return (NULL); 154 } 155 xprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0); 156 if (xprt == NULL) { 157 return (NULL); 158 } 159 /*LINTED const castaway*/ 160 (void) rpcb_unset(prognum, versnum, (struct netconfig *) nconf); 161 if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) { 162 // XXX warnx( 163 // "svc_tp_create: Could not register prog %u vers %u on %s", 164 // (unsigned)prognum, (unsigned)versnum, 165 // nconf->nc_netid); 166 SVC_DESTROY(xprt); 167 return (NULL); 168 } 169 return (xprt); 170 } 171 172 /* 173 * If fd is RPC_ANYFD, then it opens a fd for the given transport 174 * provider (nconf cannot be NULL then). If the t_state is T_UNBND and 175 * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For 176 * NULL bindadr and Connection oriented transports, the value of qlen 177 * is set to 8. 178 * 179 * If sendsz or recvsz are zero, their default values are chosen. 180 */ 181 SVCXPRT * 182 svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz) 183 SOCKET fd; /* Connection end point */ 184 const struct netconfig *nconf; /* Netconfig struct for nettoken */ 185 const struct t_bind *bindaddr; /* Local bind address */ 186 u_int sendsz; /* Max sendsize */ 187 u_int recvsz; /* Max recvsize */ 188 { 189 SVCXPRT *xprt = NULL; /* service handle */ 190 bool_t madefd = FALSE; /* whether fd opened here */ 191 struct __rpc_sockinfo si; 192 struct sockaddr_storage ss; 193 socklen_t slen; 194 195 if (fd == RPC_ANYFD) { 196 if (nconf == NULL) { 197 // XXX warnx("svc_tli_create: invalid netconfig"); 198 return (NULL); 199 } 200 fd = __rpc_nconf2fd(nconf); 201 if (fd == -1) { 202 // XXX warnx( 203 // "svc_tli_create: could not open connection for %s", 204 // nconf->nc_netid); 205 return (NULL); 206 } 207 __rpc_nconf2sockinfo(nconf, &si); 208 madefd = TRUE; 209 } else { 210 /* 211 * It is an open descriptor. Get the transport info. 212 */ 213 if (!__rpc_fd2sockinfo(fd, &si)) { 214 // XXX warnx( 215 // "svc_tli_create: could not get transport information"); 216 return (NULL); 217 } 218 } 219 220 /* 221 * If the fd is unbound, try to bind it. 222 */ 223 if (madefd || !__rpc_sockisbound(fd)) { 224 if (bindaddr == NULL) { 225 if (bindresvport(fd, NULL) < 0) { 226 memset(&ss, 0, sizeof ss); 227 ss.ss_family = si.si_af; 228 if (bind(fd, (struct sockaddr *)(void *)&ss, 229 (socklen_t)si.si_alen) == SOCKET_ERROR) { 230 // XXX warnx( 231 // "svc_tli_create: could not bind to anonymous port"); 232 goto freedata; 233 } 234 } 235 listen(fd, SOMAXCONN); 236 } else { 237 if (bind(fd, 238 (struct sockaddr *)bindaddr->addr.buf, 239 (socklen_t)si.si_alen) == SOCKET_ERROR) { 240 // XXX warnx( 241 // "svc_tli_create: could not bind to requested address"); 242 goto freedata; 243 } 244 listen(fd, (int)bindaddr->qlen); 245 } 246 247 } 248 /* 249 * call transport specific function. 250 */ 251 switch (si.si_socktype) { 252 case SOCK_STREAM: 253 slen = sizeof ss; 254 if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) 255 == 0) { 256 /* accepted socket */ 257 xprt = svc_fd_create(fd, sendsz, recvsz); 258 } else 259 xprt = svc_vc_create(fd, sendsz, recvsz); 260 if (!nconf || !xprt) 261 break; 262 #if 0 263 /* XXX fvdl */ 264 if (strcmp(nconf->nc_protofmly, "inet") == 0 || 265 strcmp(nconf->nc_protofmly, "inet6") == 0) 266 (void) __svc_vc_setflag(xprt, TRUE); 267 #endif 268 break; 269 case SOCK_DGRAM: 270 xprt = svc_dg_create(fd, sendsz, recvsz); 271 break; 272 default: 273 // XXX warnx("svc_tli_create: bad service type"); 274 goto freedata; 275 } 276 277 if (xprt == NULL) 278 /* 279 * The error messages here are spitted out by the lower layers: 280 * svc_vc_create(), svc_fd_create() and svc_dg_create(). 281 */ 282 goto freedata; 283 284 /* Fill in type of service */ 285 xprt->xp_type = __rpc_socktype2seman(si.si_socktype); 286 287 if (nconf) { 288 xprt->xp_netid = strdup(nconf->nc_netid); 289 xprt->xp_tp = strdup(nconf->nc_device); 290 } 291 return (xprt); 292 293 freedata: 294 if (madefd) 295 (void)closesocket(fd); 296 if (xprt) { 297 if (!madefd) /* so that svc_destroy doesnt close fd */ 298 xprt->xp_fd = RPC_ANYFD; 299 SVC_DESTROY(xprt); 300 } 301 return (NULL); 302 } 303