usr/src/lib/libnsl/rpc/svc_generic.c
changeset 0 68f95e015346
child 132 e3f7eaf7dde4
equal deleted inserted replaced
-1:000000000000 0:68f95e015346
       
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License, Version 1.0 only
       
     6  * (the "License").  You may not use this file except in compliance
       
     7  * with the License.
       
     8  *
       
     9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
    10  * or http://www.opensolaris.org/os/licensing.
       
    11  * See the License for the specific language governing permissions
       
    12  * and limitations under the License.
       
    13  *
       
    14  * When distributing Covered Code, include this CDDL HEADER in each
       
    15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    16  * If applicable, add the following below this CDDL HEADER, with the
       
    17  * fields enclosed by brackets "[]" replaced with your own identifying
       
    18  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    19  *
       
    20  * CDDL HEADER END
       
    21  */
       
    22 /*
       
    23  * Copyright 1986-2003 Sun Microsystems, Inc.  All rights reserved.
       
    24  * Use is subject to license terms.
       
    25  */
       
    26 
       
    27 /*	Copyright (c) 1988 AT&T */
       
    28 /*	All Rights Reserved   */
       
    29 
       
    30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
       
    31 
       
    32 #if !defined(lint) && defined(SCCSIDS)
       
    33 static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro";
       
    34 #endif
       
    35 
       
    36 /*
       
    37  * svc_generic.c, Server side for RPC.
       
    38  *
       
    39  */
       
    40 
       
    41 #include "mt.h"
       
    42 #include <sys/socket.h>
       
    43 #include <netinet/in.h>
       
    44 #include <netinet/tcp.h>
       
    45 #include <netinet/udp.h>
       
    46 #include <inttypes.h>
       
    47 #include "rpc_mt.h"
       
    48 #include <stdio.h>
       
    49 #include <rpc/rpc.h>
       
    50 #include <sys/types.h>
       
    51 #include <rpc/trace.h>
       
    52 #include <errno.h>
       
    53 #include <syslog.h>
       
    54 #include <rpc/nettype.h>
       
    55 #include <malloc.h>
       
    56 #include <string.h>
       
    57 #include <stropts.h>
       
    58 
       
    59 
       
    60 extern int __svc_vc_setflag();
       
    61 
       
    62 extern SVCXPRT *svc_dg_create_private();
       
    63 extern SVCXPRT *svc_vc_create_private();
       
    64 extern SVCXPRT *svc_fd_create_private();
       
    65 
       
    66 extern bool_t __svc_add_to_xlist();
       
    67 extern void __svc_free_xlist();
       
    68 
       
    69 /*
       
    70  * The highest level interface for server creation.
       
    71  * It tries for all the nettokens in that particular class of token
       
    72  * and returns the number of handles it can create and/or find.
       
    73  *
       
    74  * It creates a link list of all the handles it could create.
       
    75  * If svc_create() is called multiple times, it uses the handle
       
    76  * created earlier instead of creating a new handle every time.
       
    77  */
       
    78 
       
    79 /* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */
       
    80 
       
    81 SVCXPRT_LIST *_svc_xprtlist = NULL;
       
    82 extern mutex_t xprtlist_lock;
       
    83 
       
    84 void
       
    85 __svc_free_xprtlist()
       
    86 {
       
    87 	__svc_free_xlist(&_svc_xprtlist, &xprtlist_lock);
       
    88 }
       
    89 
       
    90 int
       
    91 svc_create(dispatch, prognum, versnum, nettype)
       
    92 	void (*dispatch)();	/* Dispatch function */
       
    93 	rpcprog_t prognum;		/* Program number */
       
    94 	rpcvers_t versnum;		/* Version number */
       
    95 	const char *nettype;		/* Networktype token */
       
    96 {
       
    97 	SVCXPRT_LIST *l;
       
    98 	int num = 0;
       
    99 	SVCXPRT *xprt;
       
   100 	struct netconfig *nconf;
       
   101 	void *handle;
       
   102 	bool_t try_others;
       
   103 	int __rpc_try_doors();
       
   104 
       
   105 	trace3(TR_svc_create, 0, prognum, versnum);
       
   106 	/*
       
   107 	 * Check if service should register over doors transport.
       
   108 	 */
       
   109 	if (__rpc_try_doors(nettype, &try_others)) {
       
   110 		if (svc_door_create(dispatch, prognum, versnum, 0) == NULL)
       
   111 			(void) syslog(LOG_ERR,
       
   112 				"svc_create: could not register over doors");
       
   113 		else
       
   114 			num++;
       
   115 	}
       
   116 	if (!try_others)
       
   117 		return (num);
       
   118 	if ((handle = __rpc_setconf((char *)nettype)) == NULL) {
       
   119 		(void) syslog(LOG_ERR, "svc_create: unknown protocol");
       
   120 		trace3(TR_svc_create, 1, prognum, versnum);
       
   121 		return (0);
       
   122 	}
       
   123 	while (nconf = __rpc_getconf(handle)) {
       
   124 		mutex_lock(&xprtlist_lock);
       
   125 		for (l = _svc_xprtlist; l; l = l->next) {
       
   126 			if (strcmp(l->xprt->xp_netid, nconf->nc_netid) == 0) {
       
   127 				/* Found an old one, use it */
       
   128 				(void) rpcb_unset(prognum, versnum, nconf);
       
   129 				if (svc_reg(l->xprt, prognum, versnum,
       
   130 					dispatch, nconf) == FALSE)
       
   131 					(void) syslog(LOG_ERR,
       
   132 		"svc_create: could not register prog %d vers %d on %s",
       
   133 					prognum, versnum, nconf->nc_netid);
       
   134 				else
       
   135 					num++;
       
   136 				break;
       
   137 			}
       
   138 		}
       
   139 		mutex_unlock(&xprtlist_lock);
       
   140 		if (l == NULL) {
       
   141 			/* It was not found. Now create a new one */
       
   142 			xprt = svc_tp_create(dispatch, prognum, versnum, nconf);
       
   143 			if (xprt) {
       
   144 				if (!__svc_add_to_xlist(&_svc_xprtlist, xprt,
       
   145 							&xprtlist_lock)) {
       
   146 					(void) syslog(LOG_ERR,
       
   147 						"svc_create: no memory");
       
   148 					trace3(TR_svc_create, 1, prognum,
       
   149 						versnum);
       
   150 					return (0);
       
   151 				}
       
   152 				num++;
       
   153 			}
       
   154 		}
       
   155 	}
       
   156 	__rpc_endconf(handle);
       
   157 	/*
       
   158 	 * In case of num == 0; the error messages are generated by the
       
   159 	 * underlying layers; and hence not needed here.
       
   160 	 */
       
   161 	trace3(TR_svc_create, 1, prognum, versnum);
       
   162 	return (num);
       
   163 }
       
   164 
       
   165 /*
       
   166  * The high level interface to svc_tli_create().
       
   167  * It tries to create a server for "nconf" and registers the service
       
   168  * with the rpcbind. It calls svc_tli_create();
       
   169  */
       
   170 SVCXPRT *
       
   171 svc_tp_create(dispatch, prognum, versnum, nconf)
       
   172 	void (*dispatch)();	/* Dispatch function */
       
   173 	rpcprog_t prognum;	/* Program number */
       
   174 	rpcvers_t versnum;	/* Version number */
       
   175 	const struct netconfig *nconf; /* Netconfig structure for the network */
       
   176 {
       
   177 	SVCXPRT *xprt;
       
   178 
       
   179 	trace3(TR_svc_tp_create, 0, prognum, versnum);
       
   180 	if (nconf == (struct netconfig *)NULL) {
       
   181 		(void) syslog(LOG_ERR,
       
   182 	"svc_tp_create: invalid netconfig structure for prog %d vers %d",
       
   183 				prognum, versnum);
       
   184 		trace3(TR_svc_tp_create, 1, prognum, versnum);
       
   185 		return ((SVCXPRT *)NULL);
       
   186 	}
       
   187 	xprt = svc_tli_create(RPC_ANYFD, nconf, (struct t_bind *)NULL, 0, 0);
       
   188 	if (xprt == (SVCXPRT *)NULL) {
       
   189 		trace3(TR_svc_tp_create, 1, prognum, versnum);
       
   190 		return ((SVCXPRT *)NULL);
       
   191 	}
       
   192 	(void) rpcb_unset(prognum, versnum, (struct netconfig *)nconf);
       
   193 	if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {
       
   194 		(void) syslog(LOG_ERR,
       
   195 		"svc_tp_create: Could not register prog %d vers %d on %s",
       
   196 				prognum, versnum, nconf->nc_netid);
       
   197 		SVC_DESTROY(xprt);
       
   198 		trace3(TR_svc_tp_create, 1, prognum, versnum);
       
   199 		return ((SVCXPRT *)NULL);
       
   200 	}
       
   201 	trace3(TR_svc_tp_create, 1, prognum, versnum);
       
   202 	return (xprt);
       
   203 }
       
   204 
       
   205 /*
       
   206  * If fd is RPC_ANYFD, then it opens a fd for the given transport
       
   207  * provider (nconf cannot be NULL then). If the t_state is T_UNBND and
       
   208  * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
       
   209  * NULL bindadr and Connection oriented transports, the value of qlen
       
   210  * is set arbitrarily.
       
   211  *
       
   212  * If sendsz or recvsz are zero, their default values are chosen.
       
   213  */
       
   214 SVCXPRT *
       
   215 svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz)
       
   216 	int fd;				/* Connection end point */
       
   217 	const struct netconfig *nconf;	/* Netconfig struct for nettoken */
       
   218 	const struct t_bind *bindaddr;	/* Local bind address */
       
   219 	uint_t sendsz;			/* Max sendsize */
       
   220 	uint_t recvsz;			/* Max recvsize */
       
   221 {
       
   222 	SVCXPRT *xprt = NULL;		/* service handle */
       
   223 	struct t_info tinfo;		/* transport info */
       
   224 	struct t_bind *tres = NULL;	/* bind info */
       
   225 	bool_t madefd = FALSE;		/* whether fd opened here  */
       
   226 	int state;			/* state of the transport provider */
       
   227 
       
   228 	trace4(TR_svc_tli_create, 0, fd, sendsz, recvsz);
       
   229 	if (fd == RPC_ANYFD) {
       
   230 		if (nconf == (struct netconfig *)NULL) {
       
   231 			(void) syslog(LOG_ERR,
       
   232 			    "svc_tli_create: invalid netconfig");
       
   233 			trace2(TR_svc_tli_create, 1, fd);
       
   234 			return ((SVCXPRT *)NULL);
       
   235 		}
       
   236 		fd = t_open(nconf->nc_device, O_RDWR, &tinfo);
       
   237 		if (fd == -1) {
       
   238 			char errorstr[100];
       
   239 
       
   240 			__tli_sys_strerror(errorstr, sizeof (errorstr),
       
   241 					t_errno, errno);
       
   242 			(void) syslog(LOG_ERR,
       
   243 			"svc_tli_create: could not open connection for %s: %s",
       
   244 					nconf->nc_netid, errorstr);
       
   245 			trace2(TR_svc_tli_create, 1, fd);
       
   246 			return ((SVCXPRT *)NULL);
       
   247 		}
       
   248 		madefd = TRUE;
       
   249 		state = T_UNBND;
       
   250 	} else {
       
   251 		/*
       
   252 		 * It is an open descriptor. Sync it & get the transport info.
       
   253 		 */
       
   254 		if ((state = t_sync(fd)) == -1) {
       
   255 			char errorstr[100];
       
   256 
       
   257 			__tli_sys_strerror(errorstr, sizeof (errorstr),
       
   258 					t_errno, errno);
       
   259 			(void) syslog(LOG_ERR,
       
   260 		"svc_tli_create: could not do t_sync: %s",
       
   261 					errorstr);
       
   262 			trace2(TR_svc_tli_create, 1, fd);
       
   263 			return ((SVCXPRT *)NULL);
       
   264 		}
       
   265 		if (t_getinfo(fd, &tinfo) == -1) {
       
   266 			char errorstr[100];
       
   267 
       
   268 			__tli_sys_strerror(errorstr, sizeof (errorstr),
       
   269 					t_errno, errno);
       
   270 			(void) syslog(LOG_ERR,
       
   271 		"svc_tli_create: could not get transport information: %s",
       
   272 				    errorstr);
       
   273 			trace2(TR_svc_tli_create, 1, fd);
       
   274 			return ((SVCXPRT *)NULL);
       
   275 		}
       
   276 		/* Enable options of returning the ip's for udp */
       
   277 		if (nconf) {
       
   278 		    int ret = 0;
       
   279 		    if (strcmp(nconf->nc_netid, "udp6") == 0) {
       
   280 			ret = __rpc_tli_set_options(fd, IPPROTO_IPV6,
       
   281 					IPV6_RECVPKTINFO, 1);
       
   282 			if (ret < 0) {
       
   283 			    char errorstr[100];
       
   284 
       
   285 			    __tli_sys_strerror(errorstr, sizeof (errorstr),
       
   286 					t_errno, errno);
       
   287 			    (void) syslog(LOG_ERR,
       
   288 				"svc_tli_create: IPV6_RECVPKTINFO(1): %s",
       
   289 					errorstr);
       
   290 			    trace2(TR_svc_tli_create, 1, fd);
       
   291 			    return ((SVCXPRT *)NULL);
       
   292 			}
       
   293 		    } else if (strcmp(nconf->nc_netid, "udp") == 0) {
       
   294 			ret = __rpc_tli_set_options(fd, IPPROTO_IP,
       
   295 					IP_RECVDSTADDR, 1);
       
   296 			if (ret < 0) {
       
   297 			    char errorstr[100];
       
   298 
       
   299 			    __tli_sys_strerror(errorstr, sizeof (errorstr),
       
   300 					t_errno, errno);
       
   301 			    (void) syslog(LOG_ERR,
       
   302 				"svc_tli_create: IP_RECVDSTADDR(1): %s",
       
   303 					errorstr);
       
   304 			    trace2(TR_svc_tli_create, 1, fd);
       
   305 			    return ((SVCXPRT *)NULL);
       
   306 			}
       
   307 		    }
       
   308 		}
       
   309 	}
       
   310 
       
   311 	/*
       
   312 	 * If the fd is unbound, try to bind it.
       
   313 	 * In any case, try to get its bound info in tres
       
   314 	 */
       
   315 /* LINTED pointer alignment */
       
   316 	tres = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR);
       
   317 	if (tres == NULL) {
       
   318 		(void) syslog(LOG_ERR, "svc_tli_create: No memory!");
       
   319 		goto freedata;
       
   320 	}
       
   321 
       
   322 	switch (state) {
       
   323 		bool_t tcp, exclbind;
       
   324 	case T_UNBND:
       
   325 		/*
       
   326 		 * {TCP,UDP}_EXCLBIND has the following properties
       
   327 		 *    - an fd bound to port P via IPv4 will prevent an IPv6
       
   328 		 *    bind to port P (and vice versa)
       
   329 		 *    - an fd bound to a wildcard IP address for port P will
       
   330 		 *    prevent a more specific IP address bind to port P
       
   331 		 *    (see {tcp,udp}.c for details)
       
   332 		 *
       
   333 		 * We use the latter property to prevent hijacking of RPC
       
   334 		 * services that reside at non-privileged ports.
       
   335 		 */
       
   336 		tcp = nconf ? (strcmp(nconf->nc_proto, NC_TCP) == 0) : 0;
       
   337 		if (nconf &&
       
   338 		    (tcp || (strcmp(nconf->nc_proto, NC_UDP) == 0)) &&
       
   339 		    rpc_control(__RPC_SVC_EXCLBIND_GET, &exclbind)) {
       
   340 			if (exclbind) {
       
   341 				if (__rpc_tli_set_options(fd,
       
   342 					tcp ? IPPROTO_TCP : IPPROTO_UDP,
       
   343 					tcp ? TCP_EXCLBIND : UDP_EXCLBIND,
       
   344 							1) < 0) {
       
   345 					syslog(LOG_ERR,
       
   346 			    "svc_tli_create: can't set EXCLBIND [netid='%s']",
       
   347 					    nconf->nc_netid);
       
   348 					goto freedata;
       
   349 				}
       
   350 			}
       
   351 		}
       
   352 		if (bindaddr) {
       
   353 			if (t_bind(fd, (struct t_bind *)bindaddr,
       
   354 								tres) == -1) {
       
   355 				char errorstr[100];
       
   356 
       
   357 				__tli_sys_strerror(errorstr, sizeof (errorstr),
       
   358 						t_errno, errno);
       
   359 				(void) syslog(LOG_ERR,
       
   360 					"svc_tli_create: could not bind: %s",
       
   361 					    errorstr);
       
   362 				goto freedata;
       
   363 			}
       
   364 			/*
       
   365 			 * Should compare the addresses only if addr.len
       
   366 			 * was non-zero
       
   367 			 */
       
   368 			if (bindaddr->addr.len &&
       
   369 				(memcmp(bindaddr->addr.buf, tres->addr.buf,
       
   370 					(int)tres->addr.len) != 0)) {
       
   371 				(void) syslog(LOG_ERR,
       
   372 		"svc_tli_create: could not bind to requested address: %s",
       
   373 						"address mismatch");
       
   374 				goto freedata;
       
   375 			}
       
   376 		} else {
       
   377 			tres->qlen = 64; /* Chosen Arbitrarily */
       
   378 			tres->addr.len = 0;
       
   379 			if (t_bind(fd, tres, tres) == -1) {
       
   380 				char errorstr[100];
       
   381 
       
   382 				__tli_sys_strerror(errorstr, sizeof (errorstr),
       
   383 						t_errno, errno);
       
   384 				(void) syslog(LOG_ERR,
       
   385 					"svc_tli_create: could not bind: %s",
       
   386 						errorstr);
       
   387 				goto freedata;
       
   388 			}
       
   389 		}
       
   390 
       
   391 		/* Enable options of returning the ip's for udp */
       
   392 		if (nconf) {
       
   393 		    int ret = 0;
       
   394 		    if (strcmp(nconf->nc_netid, "udp6") == 0) {
       
   395 			ret = __rpc_tli_set_options(fd, IPPROTO_IPV6,
       
   396 					IPV6_RECVPKTINFO, 1);
       
   397 			if (ret < 0) {
       
   398 			    char errorstr[100];
       
   399 
       
   400 			    __tli_sys_strerror(errorstr, sizeof (errorstr),
       
   401 					t_errno, errno);
       
   402 			    (void) syslog(LOG_ERR,
       
   403 				"svc_tli_create: IPV6_RECVPKTINFO(2): %s",
       
   404 					errorstr);
       
   405 			    goto freedata;
       
   406 			}
       
   407 		    } else if (strcmp(nconf->nc_netid, "udp") == 0) {
       
   408 			ret = __rpc_tli_set_options(fd, IPPROTO_IP,
       
   409 					IP_RECVDSTADDR, 1);
       
   410 			if (ret < 0) {
       
   411 			    char errorstr[100];
       
   412 
       
   413 			    __tli_sys_strerror(errorstr, sizeof (errorstr),
       
   414 					t_errno, errno);
       
   415 			    (void) syslog(LOG_ERR,
       
   416 				"svc_tli_create: IP_RECVDSTADDR(2): %s",
       
   417 					errorstr);
       
   418 			    goto freedata;
       
   419 			}
       
   420 		    }
       
   421 		}
       
   422 		break;
       
   423 
       
   424 	case T_IDLE:
       
   425 		if (bindaddr) {
       
   426 			/* Copy the entire stuff in tres */
       
   427 			if (tres->addr.maxlen < bindaddr->addr.len) {
       
   428 				(void) syslog(LOG_ERR,
       
   429 				"svc_tli_create: illegal netbuf length");
       
   430 				goto freedata;
       
   431 			}
       
   432 			tres->addr.len = bindaddr->addr.len;
       
   433 			(void) memcpy(tres->addr.buf, bindaddr->addr.buf,
       
   434 					(int)tres->addr.len);
       
   435 		} else
       
   436 			if (t_getname(fd, &(tres->addr), LOCALNAME) == -1)
       
   437 				tres->addr.len = 0;
       
   438 		break;
       
   439 	case T_INREL:
       
   440 		(void) t_rcvrel(fd);
       
   441 		(void) t_sndrel(fd);
       
   442 		(void) syslog(LOG_ERR,
       
   443 			"svc_tli_create: other side wants to\
       
   444 release connection");
       
   445 		goto freedata;
       
   446 
       
   447 	case T_INCON:
       
   448 		/* Do nothing here. Assume this is handled in rendezvous */
       
   449 		break;
       
   450 	case T_DATAXFER:
       
   451 		/*
       
   452 		 * This takes care of the case where a fd
       
   453 		 * is passed on which a connection has already
       
   454 		 * been accepted.
       
   455 		 */
       
   456 		if (t_getname(fd, &(tres->addr), LOCALNAME) == -1)
       
   457 			tres->addr.len = 0;
       
   458 		break;
       
   459 	default:
       
   460 		(void) syslog(LOG_ERR,
       
   461 		    "svc_tli_create: connection in a wierd state (%d)", state);
       
   462 		goto freedata;
       
   463 	}
       
   464 
       
   465 	/*
       
   466 	 * call transport specific function.
       
   467 	 */
       
   468 	switch (tinfo.servtype) {
       
   469 		case T_COTS_ORD:
       
   470 		case T_COTS:
       
   471 			if (state == T_DATAXFER)
       
   472 				xprt = svc_fd_create_private(fd, sendsz,
       
   473 						recvsz);
       
   474 			else
       
   475 				xprt = svc_vc_create_private(fd, sendsz,
       
   476 						recvsz);
       
   477 			if (!nconf || !xprt)
       
   478 				break;
       
   479 			if ((tinfo.servtype == T_COTS_ORD) &&
       
   480 				(state != T_DATAXFER) &&
       
   481 				(strcmp(nconf->nc_protofmly, "inet") == 0))
       
   482 				(void) __svc_vc_setflag(xprt, TRUE);
       
   483 			break;
       
   484 		case T_CLTS:
       
   485 			xprt = svc_dg_create_private(fd, sendsz, recvsz);
       
   486 			break;
       
   487 		default:
       
   488 			(void) syslog(LOG_ERR,
       
   489 			    "svc_tli_create: bad service type");
       
   490 			goto freedata;
       
   491 	}
       
   492 	if (xprt == (SVCXPRT *)NULL)
       
   493 		/*
       
   494 		 * The error messages here are spitted out by the lower layers:
       
   495 		 * svc_vc_create(), svc_fd_create() and svc_dg_create().
       
   496 		 */
       
   497 		goto freedata;
       
   498 
       
   499 	/* fill in the other xprt information */
       
   500 
       
   501 	/* Assign the local bind address */
       
   502 	xprt->xp_ltaddr = tres->addr;
       
   503 	/* Fill in type of service */
       
   504 	xprt->xp_type = tinfo.servtype;
       
   505 	tres->addr.buf = NULL;
       
   506 	(void) t_free((char *)tres, T_BIND);
       
   507 	tres = NULL;
       
   508 
       
   509 	xprt->xp_rtaddr.len = 0;
       
   510 	xprt->xp_rtaddr.maxlen = __rpc_get_a_size(tinfo.addr);
       
   511 
       
   512 	/* Allocate space for the remote bind info */
       
   513 	if ((xprt->xp_rtaddr.buf = mem_alloc(xprt->xp_rtaddr.maxlen)) == NULL) {
       
   514 		(void) syslog(LOG_ERR, "svc_tli_create: No memory!");
       
   515 		goto freedata;
       
   516 	}
       
   517 
       
   518 	if (nconf) {
       
   519 		xprt->xp_netid = strdup(nconf->nc_netid);
       
   520 		if (xprt->xp_netid == NULL) {
       
   521 			if (xprt->xp_rtaddr.buf)
       
   522 				free(xprt->xp_rtaddr.buf);
       
   523 			syslog(LOG_ERR, "svc_tli_create: strdup failed!");
       
   524 			goto freedata;
       
   525 		}
       
   526 		xprt->xp_tp = strdup(nconf->nc_device);
       
   527 		if (xprt->xp_tp == NULL) {
       
   528 			if (xprt->xp_rtaddr.buf)
       
   529 				free(xprt->xp_rtaddr.buf);
       
   530 			if (xprt->xp_netid)
       
   531 				free(xprt->xp_netid);
       
   532 			syslog(LOG_ERR, "svc_tli_create: strdup failed!");
       
   533 			goto freedata;
       
   534 		}
       
   535 	}
       
   536 
       
   537 /*
       
   538  *	if (madefd && (tinfo.servtype == T_CLTS))
       
   539  *		(void) ioctl(fd, I_POP, (char *)NULL);
       
   540  */
       
   541 	xprt_register(xprt);
       
   542 	trace2(TR_svc_tli_create, 1, fd);
       
   543 	return (xprt);
       
   544 
       
   545 freedata:
       
   546 	if (madefd)
       
   547 		(void) t_close(fd);
       
   548 	if (tres)
       
   549 		(void) t_free((char *)tres, T_BIND);
       
   550 	if (xprt) {
       
   551 		if (!madefd) /* so that svc_destroy doesnt close fd */
       
   552 			xprt->xp_fd = RPC_ANYFD;
       
   553 		SVC_DESTROY(xprt);
       
   554 	}
       
   555 	trace2(TR_svc_tli_create, 1, fd);
       
   556 	return ((SVCXPRT *)NULL);
       
   557 }