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