1/* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */ 2 3/* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32/* 33 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 34 */ 35 36#if defined(LIBC_SCCS) && !defined(lint) 37#ident "@(#)svc_generic.c 1.19 94/04/24 SMI" 38static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro"; 39#endif 40#include <sys/cdefs.h>
| 1/* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */ 2 3/* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32/* 33 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 34 */ 35 36#if defined(LIBC_SCCS) && !defined(lint) 37#ident "@(#)svc_generic.c 1.19 94/04/24 SMI" 38static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro"; 39#endif 40#include <sys/cdefs.h>
|
41__FBSDID("$FreeBSD: head/sys/rpc/svc_generic.c 194407 2009-06-17 22:50:26Z rmacklem $");
| 41__FBSDID("$FreeBSD: head/sys/rpc/svc_generic.c 196503 2009-08-24 10:09:30Z zec $");
|
42 43/* 44 * svc_generic.c, Server side for RPC. 45 * 46 */ 47 48#include "opt_inet6.h" 49 50#include <sys/param.h> 51#include <sys/lock.h> 52#include <sys/kernel.h> 53#include <sys/malloc.h> 54#include <sys/mutex.h> 55#include <sys/protosw.h> 56#include <sys/queue.h> 57#include <sys/socket.h> 58#include <sys/socketvar.h> 59#include <sys/systm.h> 60#include <sys/sx.h> 61#include <sys/ucred.h> 62
| 42 43/* 44 * svc_generic.c, Server side for RPC. 45 * 46 */ 47 48#include "opt_inet6.h" 49 50#include <sys/param.h> 51#include <sys/lock.h> 52#include <sys/kernel.h> 53#include <sys/malloc.h> 54#include <sys/mutex.h> 55#include <sys/protosw.h> 56#include <sys/queue.h> 57#include <sys/socket.h> 58#include <sys/socketvar.h> 59#include <sys/systm.h> 60#include <sys/sx.h> 61#include <sys/ucred.h> 62
|
| 63#include <net/vnet.h> 64
|
63#include <rpc/rpc.h> 64#include <rpc/rpcb_clnt.h> 65#include <rpc/nettype.h> 66 67#include <rpc/rpc_com.h> 68 69extern int __svc_vc_setflag(SVCXPRT *, int); 70 71/* 72 * The highest level interface for server creation. 73 * It tries for all the nettokens in that particular class of token 74 * and returns the number of handles it can create and/or find. 75 * 76 * It creates a link list of all the handles it could create. 77 * If svc_create() is called multiple times, it uses the handle 78 * created earlier instead of creating a new handle every time. 79 */ 80int 81svc_create( 82 SVCPOOL *pool, 83 void (*dispatch)(struct svc_req *, SVCXPRT *), 84 rpcprog_t prognum, /* Program number */ 85 rpcvers_t versnum, /* Version number */ 86 const char *nettype) /* Networktype token */ 87{ 88 int num = 0; 89 SVCXPRT *xprt; 90 struct netconfig *nconf; 91 void *handle; 92 93 if ((handle = __rpc_setconf(nettype)) == NULL) { 94 printf("svc_create: unknown protocol"); 95 return (0); 96 } 97 while ((nconf = __rpc_getconf(handle)) != NULL) { 98 mtx_lock(&pool->sp_lock); 99 TAILQ_FOREACH(xprt, &pool->sp_xlist, xp_link) { 100 if (strcmp(xprt->xp_netid, nconf->nc_netid) == 0) { 101 /* Found an old one, use it */ 102 mtx_unlock(&pool->sp_lock); 103 (void) rpcb_unset(prognum, versnum, nconf); 104 if (svc_reg(xprt, prognum, versnum, 105 dispatch, nconf) == FALSE) { 106 printf( 107 "svc_create: could not register prog %u vers %u on %s\n", 108 (unsigned)prognum, (unsigned)versnum, 109 nconf->nc_netid); 110 mtx_lock(&pool->sp_lock); 111 } else { 112 num++; 113 mtx_lock(&pool->sp_lock); 114 break; 115 } 116 } 117 } 118 mtx_unlock(&pool->sp_lock); 119 if (xprt == NULL) { 120 /* It was not found. Now create a new one */ 121 xprt = svc_tp_create(pool, dispatch, prognum, versnum, 122 NULL, nconf); 123 if (xprt) { 124 num++; 125 SVC_RELEASE(xprt); 126 } 127 } 128 } 129 __rpc_endconf(handle); 130 /* 131 * In case of num == 0; the error messages are generated by the 132 * underlying layers; and hence not needed here. 133 */ 134 return (num); 135} 136 137/* 138 * The high level interface to svc_tli_create(). 139 * It tries to create a server for "nconf" and registers the service 140 * with the rpcbind. It calls svc_tli_create(); 141 */ 142SVCXPRT * 143svc_tp_create( 144 SVCPOOL *pool, 145 void (*dispatch)(struct svc_req *, SVCXPRT *), 146 rpcprog_t prognum, /* Program number */ 147 rpcvers_t versnum, /* Version number */ 148 const char *uaddr, /* Address (or null for default) */ 149 const struct netconfig *nconf) /* Netconfig structure for the network */ 150{ 151 struct netconfig nconfcopy; 152 struct netbuf *taddr; 153 struct t_bind bind; 154 SVCXPRT *xprt; 155 156 if (nconf == NULL) { 157 printf( 158 "svc_tp_create: invalid netconfig structure for prog %u vers %u\n", 159 (unsigned)prognum, (unsigned)versnum); 160 return (NULL); 161 } 162 if (uaddr) { 163 taddr = uaddr2taddr(nconf, uaddr); 164 bind.addr = *taddr; 165 free(taddr, M_RPC); 166 bind.qlen = SOMAXCONN; 167 xprt = svc_tli_create(pool, NULL, nconf, &bind, 0, 0); 168 free(bind.addr.buf, M_RPC); 169 } else { 170 xprt = svc_tli_create(pool, NULL, nconf, NULL, 0, 0); 171 } 172 if (xprt == NULL) { 173 return (NULL); 174 } 175 /*LINTED const castaway*/ 176 nconfcopy = *nconf; 177 (void) rpcb_unset(prognum, versnum, &nconfcopy); 178 if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) { 179 printf( 180 "svc_tp_create: Could not register prog %u vers %u on %s\n", 181 (unsigned)prognum, (unsigned)versnum, 182 nconf->nc_netid); 183 xprt_unregister(xprt); 184 SVC_RELEASE(xprt); 185 return (NULL); 186 } 187 return (xprt); 188} 189 190/* 191 * If so is NULL, then it opens a socket for the given transport 192 * provider (nconf cannot be NULL then). If the t_state is T_UNBND and 193 * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For 194 * NULL bindadr and Connection oriented transports, the value of qlen 195 * is set to 8. 196 * 197 * If sendsz or recvsz are zero, their default values are chosen. 198 */ 199SVCXPRT * 200svc_tli_create( 201 SVCPOOL *pool, 202 struct socket *so, /* Connection end point */ 203 const struct netconfig *nconf, /* Netconfig struct for nettoken */ 204 const struct t_bind *bindaddr, /* Local bind address */ 205 size_t sendsz, /* Max sendsize */ 206 size_t recvsz) /* Max recvsize */ 207{ 208 SVCXPRT *xprt = NULL; /* service handle */ 209 bool_t madeso = FALSE; /* whether so opened here */ 210 struct __rpc_sockinfo si; 211 struct sockaddr_storage ss; 212 213 if (!so) { 214 if (nconf == NULL) { 215 printf("svc_tli_create: invalid netconfig\n"); 216 return (NULL); 217 } 218 so = __rpc_nconf2socket(nconf); 219 if (!so) { 220 printf( 221 "svc_tli_create: could not open connection for %s\n", 222 nconf->nc_netid); 223 return (NULL); 224 } 225 __rpc_nconf2sockinfo(nconf, &si); 226 madeso = TRUE; 227 } else { 228 /* 229 * It is an open socket. Get the transport info. 230 */
| 65#include <rpc/rpc.h> 66#include <rpc/rpcb_clnt.h> 67#include <rpc/nettype.h> 68 69#include <rpc/rpc_com.h> 70 71extern int __svc_vc_setflag(SVCXPRT *, int); 72 73/* 74 * The highest level interface for server creation. 75 * It tries for all the nettokens in that particular class of token 76 * and returns the number of handles it can create and/or find. 77 * 78 * It creates a link list of all the handles it could create. 79 * If svc_create() is called multiple times, it uses the handle 80 * created earlier instead of creating a new handle every time. 81 */ 82int 83svc_create( 84 SVCPOOL *pool, 85 void (*dispatch)(struct svc_req *, SVCXPRT *), 86 rpcprog_t prognum, /* Program number */ 87 rpcvers_t versnum, /* Version number */ 88 const char *nettype) /* Networktype token */ 89{ 90 int num = 0; 91 SVCXPRT *xprt; 92 struct netconfig *nconf; 93 void *handle; 94 95 if ((handle = __rpc_setconf(nettype)) == NULL) { 96 printf("svc_create: unknown protocol"); 97 return (0); 98 } 99 while ((nconf = __rpc_getconf(handle)) != NULL) { 100 mtx_lock(&pool->sp_lock); 101 TAILQ_FOREACH(xprt, &pool->sp_xlist, xp_link) { 102 if (strcmp(xprt->xp_netid, nconf->nc_netid) == 0) { 103 /* Found an old one, use it */ 104 mtx_unlock(&pool->sp_lock); 105 (void) rpcb_unset(prognum, versnum, nconf); 106 if (svc_reg(xprt, prognum, versnum, 107 dispatch, nconf) == FALSE) { 108 printf( 109 "svc_create: could not register prog %u vers %u on %s\n", 110 (unsigned)prognum, (unsigned)versnum, 111 nconf->nc_netid); 112 mtx_lock(&pool->sp_lock); 113 } else { 114 num++; 115 mtx_lock(&pool->sp_lock); 116 break; 117 } 118 } 119 } 120 mtx_unlock(&pool->sp_lock); 121 if (xprt == NULL) { 122 /* It was not found. Now create a new one */ 123 xprt = svc_tp_create(pool, dispatch, prognum, versnum, 124 NULL, nconf); 125 if (xprt) { 126 num++; 127 SVC_RELEASE(xprt); 128 } 129 } 130 } 131 __rpc_endconf(handle); 132 /* 133 * In case of num == 0; the error messages are generated by the 134 * underlying layers; and hence not needed here. 135 */ 136 return (num); 137} 138 139/* 140 * The high level interface to svc_tli_create(). 141 * It tries to create a server for "nconf" and registers the service 142 * with the rpcbind. It calls svc_tli_create(); 143 */ 144SVCXPRT * 145svc_tp_create( 146 SVCPOOL *pool, 147 void (*dispatch)(struct svc_req *, SVCXPRT *), 148 rpcprog_t prognum, /* Program number */ 149 rpcvers_t versnum, /* Version number */ 150 const char *uaddr, /* Address (or null for default) */ 151 const struct netconfig *nconf) /* Netconfig structure for the network */ 152{ 153 struct netconfig nconfcopy; 154 struct netbuf *taddr; 155 struct t_bind bind; 156 SVCXPRT *xprt; 157 158 if (nconf == NULL) { 159 printf( 160 "svc_tp_create: invalid netconfig structure for prog %u vers %u\n", 161 (unsigned)prognum, (unsigned)versnum); 162 return (NULL); 163 } 164 if (uaddr) { 165 taddr = uaddr2taddr(nconf, uaddr); 166 bind.addr = *taddr; 167 free(taddr, M_RPC); 168 bind.qlen = SOMAXCONN; 169 xprt = svc_tli_create(pool, NULL, nconf, &bind, 0, 0); 170 free(bind.addr.buf, M_RPC); 171 } else { 172 xprt = svc_tli_create(pool, NULL, nconf, NULL, 0, 0); 173 } 174 if (xprt == NULL) { 175 return (NULL); 176 } 177 /*LINTED const castaway*/ 178 nconfcopy = *nconf; 179 (void) rpcb_unset(prognum, versnum, &nconfcopy); 180 if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) { 181 printf( 182 "svc_tp_create: Could not register prog %u vers %u on %s\n", 183 (unsigned)prognum, (unsigned)versnum, 184 nconf->nc_netid); 185 xprt_unregister(xprt); 186 SVC_RELEASE(xprt); 187 return (NULL); 188 } 189 return (xprt); 190} 191 192/* 193 * If so is NULL, then it opens a socket for the given transport 194 * provider (nconf cannot be NULL then). If the t_state is T_UNBND and 195 * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For 196 * NULL bindadr and Connection oriented transports, the value of qlen 197 * is set to 8. 198 * 199 * If sendsz or recvsz are zero, their default values are chosen. 200 */ 201SVCXPRT * 202svc_tli_create( 203 SVCPOOL *pool, 204 struct socket *so, /* Connection end point */ 205 const struct netconfig *nconf, /* Netconfig struct for nettoken */ 206 const struct t_bind *bindaddr, /* Local bind address */ 207 size_t sendsz, /* Max sendsize */ 208 size_t recvsz) /* Max recvsize */ 209{ 210 SVCXPRT *xprt = NULL; /* service handle */ 211 bool_t madeso = FALSE; /* whether so opened here */ 212 struct __rpc_sockinfo si; 213 struct sockaddr_storage ss; 214 215 if (!so) { 216 if (nconf == NULL) { 217 printf("svc_tli_create: invalid netconfig\n"); 218 return (NULL); 219 } 220 so = __rpc_nconf2socket(nconf); 221 if (!so) { 222 printf( 223 "svc_tli_create: could not open connection for %s\n", 224 nconf->nc_netid); 225 return (NULL); 226 } 227 __rpc_nconf2sockinfo(nconf, &si); 228 madeso = TRUE; 229 } else { 230 /* 231 * It is an open socket. Get the transport info. 232 */
|
| 233 CURVNET_SET(so->so_vnet);
|
231 if (!__rpc_socket2sockinfo(so, &si)) { 232 printf( 233 "svc_tli_create: could not get transport information\n");
| 234 if (!__rpc_socket2sockinfo(so, &si)) { 235 printf( 236 "svc_tli_create: could not get transport information\n");
|
| 237 CURVNET_RESTORE();
|
234 return (NULL); 235 }
| 238 return (NULL); 239 }
|
| 240 CURVNET_RESTORE();
|
236 } 237 238 /* 239 * If the socket is unbound, try to bind it. 240 */ 241 if (madeso || !__rpc_sockisbound(so)) { 242 if (bindaddr == NULL) { 243 if (bindresvport(so, NULL)) { 244 memset(&ss, 0, sizeof ss); 245 ss.ss_family = si.si_af; 246 ss.ss_len = si.si_alen; 247 if (sobind(so, (struct sockaddr *)&ss, 248 curthread)) { 249 printf( 250 "svc_tli_create: could not bind to anonymous port\n"); 251 goto freedata; 252 } 253 } 254 solisten(so, SOMAXCONN, curthread); 255 } else { 256 if (bindresvport(so, 257 (struct sockaddr *)bindaddr->addr.buf)) { 258 printf( 259 "svc_tli_create: could not bind to requested address\n"); 260 goto freedata; 261 }
| 241 } 242 243 /* 244 * If the socket is unbound, try to bind it. 245 */ 246 if (madeso || !__rpc_sockisbound(so)) { 247 if (bindaddr == NULL) { 248 if (bindresvport(so, NULL)) { 249 memset(&ss, 0, sizeof ss); 250 ss.ss_family = si.si_af; 251 ss.ss_len = si.si_alen; 252 if (sobind(so, (struct sockaddr *)&ss, 253 curthread)) { 254 printf( 255 "svc_tli_create: could not bind to anonymous port\n"); 256 goto freedata; 257 } 258 } 259 solisten(so, SOMAXCONN, curthread); 260 } else { 261 if (bindresvport(so, 262 (struct sockaddr *)bindaddr->addr.buf)) { 263 printf( 264 "svc_tli_create: could not bind to requested address\n"); 265 goto freedata; 266 }
|
| 267 CURVNET_SET(so->so_vnet);
|
262 solisten(so, (int)bindaddr->qlen, curthread);
| 268 solisten(so, (int)bindaddr->qlen, curthread);
|
| 269 CURVNET_RESTORE();
|
263 } 264 265 } 266 /* 267 * call transport specific function. 268 */ 269 switch (si.si_socktype) { 270 case SOCK_STREAM: 271#if 0 272 slen = sizeof ss; 273 if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) 274 == 0) { 275 /* accepted socket */ 276 xprt = svc_fd_create(fd, sendsz, recvsz); 277 } else 278#endif 279 xprt = svc_vc_create(pool, so, sendsz, recvsz); 280 if (!nconf || !xprt) 281 break; 282#if 0 283 /* XXX fvdl */ 284 if (strcmp(nconf->nc_protofmly, "inet") == 0 || 285 strcmp(nconf->nc_protofmly, "inet6") == 0) 286 (void) __svc_vc_setflag(xprt, TRUE); 287#endif 288 break; 289 case SOCK_DGRAM: 290 xprt = svc_dg_create(pool, so, sendsz, recvsz); 291 break; 292 default: 293 printf("svc_tli_create: bad service type"); 294 goto freedata; 295 } 296 297 if (xprt == NULL) 298 /* 299 * The error messages here are spitted out by the lower layers: 300 * svc_vc_create(), svc_fd_create() and svc_dg_create(). 301 */ 302 goto freedata; 303 304 /* Fill in type of service */ 305 xprt->xp_type = __rpc_socktype2seman(si.si_socktype); 306 307 if (nconf) { 308 xprt->xp_netid = strdup(nconf->nc_netid, M_RPC); 309 } 310 return (xprt); 311 312freedata: 313 if (madeso) 314 (void)soclose(so); 315 if (xprt) { 316 if (!madeso) /* so that svc_destroy doesnt close fd */ 317 xprt->xp_socket = NULL; 318 xprt_unregister(xprt); 319 } 320 return (NULL); 321}
| 270 } 271 272 } 273 /* 274 * call transport specific function. 275 */ 276 switch (si.si_socktype) { 277 case SOCK_STREAM: 278#if 0 279 slen = sizeof ss; 280 if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) 281 == 0) { 282 /* accepted socket */ 283 xprt = svc_fd_create(fd, sendsz, recvsz); 284 } else 285#endif 286 xprt = svc_vc_create(pool, so, sendsz, recvsz); 287 if (!nconf || !xprt) 288 break; 289#if 0 290 /* XXX fvdl */ 291 if (strcmp(nconf->nc_protofmly, "inet") == 0 || 292 strcmp(nconf->nc_protofmly, "inet6") == 0) 293 (void) __svc_vc_setflag(xprt, TRUE); 294#endif 295 break; 296 case SOCK_DGRAM: 297 xprt = svc_dg_create(pool, so, sendsz, recvsz); 298 break; 299 default: 300 printf("svc_tli_create: bad service type"); 301 goto freedata; 302 } 303 304 if (xprt == NULL) 305 /* 306 * The error messages here are spitted out by the lower layers: 307 * svc_vc_create(), svc_fd_create() and svc_dg_create(). 308 */ 309 goto freedata; 310 311 /* Fill in type of service */ 312 xprt->xp_type = __rpc_socktype2seman(si.si_socktype); 313 314 if (nconf) { 315 xprt->xp_netid = strdup(nconf->nc_netid, M_RPC); 316 } 317 return (xprt); 318 319freedata: 320 if (madeso) 321 (void)soclose(so); 322 if (xprt) { 323 if (!madeso) /* so that svc_destroy doesnt close fd */ 324 xprt->xp_socket = NULL; 325 xprt_unregister(xprt); 326 } 327 return (NULL); 328}
|