174462Salfred/*	$NetBSD: rpc_soc.c,v 1.6 2000/07/06 03:10:35 christos Exp $	*/
274462Salfred
3261046Smav/*-
4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc.
5261046Smav * All rights reserved.
6261046Smav *
7261046Smav * Redistribution and use in source and binary forms, with or without
8261046Smav * modification, are permitted provided that the following conditions are met:
9261046Smav * - Redistributions of source code must retain the above copyright notice,
10261046Smav *   this list of conditions and the following disclaimer.
11261046Smav * - Redistributions in binary form must reproduce the above copyright notice,
12261046Smav *   this list of conditions and the following disclaimer in the documentation
13261046Smav *   and/or other materials provided with the distribution.
14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its
15261046Smav *   contributors may be used to endorse or promote products derived
16261046Smav *   from this software without specific prior written permission.
1774462Salfred *
18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28261046Smav * POSSIBILITY OF SUCH DAMAGE.
2974462Salfred */
3074462Salfred
3174462Salfred/* #ident	"@(#)rpc_soc.c	1.17	94/04/24 SMI" */
3274462Salfred
3374462Salfred/*
3474462Salfred * Copyright (c) 1986-1991 by Sun Microsystems Inc.
3574462Salfred * In addition, portions of such source code were derived from Berkeley
3674462Salfred * 4.3 BSD under license from the Regents of the University of
3774462Salfred * California.
3874462Salfred */
3974462Salfred
40136581Sobrien#if defined(LIBC_SCCS) && !defined(lint)
4174462Salfredstatic char sccsid[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
4274462Salfred#endif
4392990Sobrien#include <sys/cdefs.h>
4492990Sobrien__FBSDID("$FreeBSD: stable/10/lib/libc/rpc/rpc_soc.c 309489 2016-12-03 17:40:58Z ngie $");
4574462Salfred
4674462Salfred#ifdef PORTMAP
4774462Salfred/*
4874462Salfred * rpc_soc.c
4974462Salfred *
5074462Salfred * The backward compatibility routines for the earlier implementation
5174462Salfred * of RPC, where the only transports supported were tcp/ip and udp/ip.
5274462Salfred * Based on berkeley socket abstraction, now implemented on the top
5374462Salfred * of TLI/Streams
5474462Salfred */
5574462Salfred
5675094Siedowse#include "namespace.h"
5774462Salfred#include "reentrant.h"
5874462Salfred#include <sys/types.h>
5974462Salfred#include <sys/socket.h>
6074462Salfred#include <stdio.h>
6174462Salfred#include <rpc/rpc.h>
6274462Salfred#include <rpc/pmap_clnt.h>
6374462Salfred#include <rpc/pmap_prot.h>
6474462Salfred#include <rpc/nettype.h>
6574462Salfred#include <syslog.h>
6674462Salfred#include <netinet/in.h>
6774462Salfred#include <netdb.h>
6874462Salfred#include <errno.h>
6974462Salfred#include <syslog.h>
7074462Salfred#include <stdlib.h>
7174462Salfred#include <string.h>
7274462Salfred#include <unistd.h>
7374462Salfred#include "un-namespace.h"
7474462Salfred
7574462Salfred#include "rpc_com.h"
76156090Sdeischen#include "mt_misc.h"
7774462Salfred
7892941Sobrienstatic CLIENT *clnt_com_create(struct sockaddr_in *, rpcprog_t, rpcvers_t,
7992941Sobrien    int *, u_int, u_int, char *);
8092905Sobrienstatic SVCXPRT *svc_com_create(int, u_int, u_int, char *);
8192905Sobrienstatic bool_t rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *);
8274462Salfred
8374462Salfred/* XXX */
8474462Salfred#define IN4_LOCALHOST_STRING    "127.0.0.1"
8574462Salfred#define IN6_LOCALHOST_STRING    "::1"
8674462Salfred
8774462Salfred/*
8874462Salfred * A common clnt create routine
8974462Salfred */
9074462Salfredstatic CLIENT *
91309489Sngieclnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers, int *sockp,
92309489Sngie    u_int sendsz, u_int recvsz, char *tp)
9374462Salfred{
9474462Salfred	CLIENT *cl;
9574462Salfred	int madefd = FALSE;
9674462Salfred	int fd = *sockp;
9774462Salfred	struct netconfig *nconf;
9874462Salfred	struct netbuf bindaddr;
9974462Salfred
10074462Salfred	mutex_lock(&rpcsoc_lock);
10174462Salfred	if ((nconf = __rpc_getconfip(tp)) == NULL) {
10274462Salfred		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
10374462Salfred		mutex_unlock(&rpcsoc_lock);
10474462Salfred		return (NULL);
10574462Salfred	}
10674462Salfred	if (fd == RPC_ANYSOCK) {
10774462Salfred		fd = __rpc_nconf2fd(nconf);
10874462Salfred		if (fd == -1)
10974462Salfred			goto syserror;
11074462Salfred		madefd = TRUE;
11174462Salfred	}
11274462Salfred
11374462Salfred	if (raddr->sin_port == 0) {
11474462Salfred		u_int proto;
11574462Salfred		u_short sport;
11674462Salfred
11774462Salfred		mutex_unlock(&rpcsoc_lock);	/* pmap_getport is recursive */
11874462Salfred		proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
11974462Salfred		sport = pmap_getport(raddr, (u_long)prog, (u_long)vers,
12074462Salfred		    proto);
12174462Salfred		if (sport == 0) {
12274462Salfred			goto err;
12374462Salfred		}
12474462Salfred		raddr->sin_port = htons(sport);
12574462Salfred		mutex_lock(&rpcsoc_lock);	/* pmap_getport is recursive */
12674462Salfred	}
12774462Salfred
12874462Salfred	/* Transform sockaddr_in to netbuf */
12974462Salfred	bindaddr.maxlen = bindaddr.len =  sizeof (struct sockaddr_in);
13074462Salfred	bindaddr.buf = raddr;
13174462Salfred
13274462Salfred	bindresvport(fd, NULL);
13374462Salfred	cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
13474462Salfred				sendsz, recvsz);
13574462Salfred	if (cl) {
13674462Salfred		if (madefd == TRUE) {
13774462Salfred			/*
13874462Salfred			 * The fd should be closed while destroying the handle.
13974462Salfred			 */
14074462Salfred			(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
14174462Salfred			*sockp = fd;
14274462Salfred		}
14374462Salfred		(void) freenetconfigent(nconf);
14474462Salfred		mutex_unlock(&rpcsoc_lock);
14574462Salfred		return (cl);
14674462Salfred	}
14774462Salfred	goto err;
14874462Salfred
14974462Salfredsyserror:
15074462Salfred	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
15174462Salfred	rpc_createerr.cf_error.re_errno = errno;
15274462Salfred
15374462Salfrederr:	if (madefd == TRUE)
15474462Salfred		(void)_close(fd);
15574462Salfred	(void) freenetconfigent(nconf);
15674462Salfred	mutex_unlock(&rpcsoc_lock);
15774462Salfred	return (NULL);
15874462Salfred}
15974462Salfred
16074462SalfredCLIENT *
161309489Sngieclntudp_bufcreate(struct sockaddr_in *raddr, u_long prog, u_long vers,
162309489Sngie    struct timeval wait, int *sockp, u_int sendsz, u_int recvsz)
16374462Salfred{
16474462Salfred	CLIENT *cl;
16574462Salfred
16674462Salfred	cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
16774462Salfred	    sendsz, recvsz, "udp");
16874462Salfred	if (cl == NULL) {
16974462Salfred		return (NULL);
17074462Salfred	}
17195658Sdes	(void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait);
17274462Salfred	return (cl);
17374462Salfred}
17474462Salfred
17574462SalfredCLIENT *
176309489Sngieclntudp_create(struct sockaddr_in *raddr, u_long program, u_long version,
177309489Sngie    struct timeval wait, int *sockp)
17874462Salfred{
17974462Salfred
18074462Salfred	return clntudp_bufcreate(raddr, program, version, wait, sockp,
18174462Salfred					UDPMSGSIZE, UDPMSGSIZE);
18274462Salfred}
18374462Salfred
18474462SalfredCLIENT *
185309489Sngieclnttcp_create(struct sockaddr_in *raddr, u_long prog, u_long vers, int *sockp,
186309489Sngie    u_int sendsz, u_int recvsz)
18774462Salfred{
18874462Salfred
18974462Salfred	return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
19074462Salfred	    sendsz, recvsz, "tcp");
19174462Salfred}
19274462Salfred
19374462SalfredCLIENT *
194309489Sngieclntraw_create(u_long prog, u_long vers)
19574462Salfred{
19674462Salfred
19774462Salfred	return clnt_raw_create((rpcprog_t)prog, (rpcvers_t)vers);
19874462Salfred}
19974462Salfred
20074462Salfred/*
20174462Salfred * A common server create routine
20274462Salfred */
20374462Salfredstatic SVCXPRT *
204309489Sngiesvc_com_create(int fd, u_int sendsize, u_int recvsize, char *netid)
20574462Salfred{
20674462Salfred	struct netconfig *nconf;
20774462Salfred	SVCXPRT *svc;
20874462Salfred	int madefd = FALSE;
20974462Salfred	int port;
21074462Salfred	struct sockaddr_in sin;
21174462Salfred
21274462Salfred	if ((nconf = __rpc_getconfip(netid)) == NULL) {
21374462Salfred		(void) syslog(LOG_ERR, "Could not get %s transport", netid);
21474462Salfred		return (NULL);
21574462Salfred	}
21674462Salfred	if (fd == RPC_ANYSOCK) {
21774462Salfred		fd = __rpc_nconf2fd(nconf);
21874462Salfred		if (fd == -1) {
21974462Salfred			(void) freenetconfigent(nconf);
22074462Salfred			(void) syslog(LOG_ERR,
22174462Salfred			"svc%s_create: could not open connection", netid);
22274462Salfred			return (NULL);
22374462Salfred		}
22474462Salfred		madefd = TRUE;
22574462Salfred	}
22674462Salfred
22774462Salfred	memset(&sin, 0, sizeof sin);
22874462Salfred	sin.sin_family = AF_INET;
22974462Salfred	bindresvport(fd, &sin);
23074462Salfred	_listen(fd, SOMAXCONN);
23174462Salfred	svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
23274462Salfred	(void) freenetconfigent(nconf);
23374462Salfred	if (svc == NULL) {
23474462Salfred		if (madefd)
23574462Salfred			(void)_close(fd);
23674462Salfred		return (NULL);
23774462Salfred	}
23874462Salfred	port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
23974462Salfred	svc->xp_port = ntohs(port);
24074462Salfred	return (svc);
24174462Salfred}
24274462Salfred
24374462SalfredSVCXPRT *
244309489Sngiesvctcp_create(int fd, u_int sendsize, u_int recvsize)
24574462Salfred{
24674462Salfred
24774462Salfred	return svc_com_create(fd, sendsize, recvsize, "tcp");
24874462Salfred}
24974462Salfred
25074462SalfredSVCXPRT *
251309489Sngiesvcudp_bufcreate(int fd, u_int sendsz, u_int recvsz)
25274462Salfred{
25374462Salfred
25474462Salfred	return svc_com_create(fd, sendsz, recvsz, "udp");
25574462Salfred}
25674462Salfred
25774462SalfredSVCXPRT *
258309489Sngiesvcfd_create(int fd, u_int sendsize, u_int recvsize)
25974462Salfred{
26074462Salfred
26174462Salfred	return svc_fd_create(fd, sendsize, recvsize);
26274462Salfred}
26374462Salfred
26474462Salfred
26574462SalfredSVCXPRT *
266309489Sngiesvcudp_create(int fd)
26774462Salfred{
26874462Salfred
26974462Salfred	return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp");
27074462Salfred}
27174462Salfred
27274462SalfredSVCXPRT *
273309487Sngiesvcraw_create(void)
27474462Salfred{
27574462Salfred
27674462Salfred	return svc_raw_create();
27774462Salfred}
27874462Salfred
27974462Salfredint
280309489Sngieget_myaddress(struct sockaddr_in *addr)
28174462Salfred{
28274462Salfred
28374462Salfred	memset((void *) addr, 0, sizeof(*addr));
28474462Salfred	addr->sin_family = AF_INET;
28574462Salfred	addr->sin_port = htons(PMAPPORT);
28674462Salfred	addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
28774462Salfred	return (0);
28874462Salfred}
28974462Salfred
29074462Salfred/*
29174462Salfred * For connectionless "udp" transport. Obsoleted by rpc_call().
29274462Salfred */
29374462Salfredint
294309489Sngiecallrpc(const char *host, int prognum, int versnum, int procnum,
295309489Sngie    xdrproc_t inproc, void *in, xdrproc_t outproc, void *out)
29674462Salfred{
29774462Salfred
29874462Salfred	return (int)rpc_call(host, (rpcprog_t)prognum, (rpcvers_t)versnum,
29974462Salfred	    (rpcproc_t)procnum, inproc, in, outproc, out, "udp");
30074462Salfred}
30174462Salfred
30274462Salfred/*
30374462Salfred * For connectionless kind of transport. Obsoleted by rpc_reg()
30474462Salfred */
30574462Salfredint
306309489Sngieregisterrpc(int prognum, int versnum, int procnum,
307309489Sngie    char *(*progname)(char [UDPMSGSIZE]),
308309489Sngie    xdrproc_t inproc, xdrproc_t outproc)
30974462Salfred{
31074462Salfred
31174462Salfred	return rpc_reg((rpcprog_t)prognum, (rpcvers_t)versnum,
31274462Salfred	    (rpcproc_t)procnum, progname, inproc, outproc, "udp");
31374462Salfred}
31474462Salfred
31574462Salfred/*
31674462Salfred * All the following clnt_broadcast stuff is convulated; it supports
31774462Salfred * the earlier calling style of the callback function
31874462Salfred */
31974462Salfredstatic thread_key_t	clnt_broadcast_key;
32074462Salfredstatic resultproc_t	clnt_broadcast_result_main;
321204950Sjhbstatic once_t		clnt_broadcast_once = ONCE_INITIALIZER;
32274462Salfred
323204950Sjhbstatic void
324204950Sjhbclnt_broadcast_key_init(void)
325204950Sjhb{
326204950Sjhb
327204950Sjhb	thr_keycreate(&clnt_broadcast_key, free);
328204950Sjhb}
329204950Sjhb
33074462Salfred/*
33174462Salfred * Need to translate the netbuf address into sockaddr_in address.
33274462Salfred * Dont care about netid here.
33374462Salfred */
33474462Salfred/* ARGSUSED */
33574462Salfredstatic bool_t
336309489Sngierpc_wrap_bcast(char *resultp, struct netbuf *addr, struct netconfig *nconf)
337309489Sngie/*
338309489Sngie *	char *resultp;		// results of the call
339309489Sngie *	struct netbuf *addr;	// address of the guy who responded
340309489Sngie *	struct netconfig *nconf; // Netconf of the transport
341309489Sngie */
34274462Salfred{
34374462Salfred	resultproc_t clnt_broadcast_result;
34474462Salfred
34574462Salfred	if (strcmp(nconf->nc_netid, "udp"))
34674462Salfred		return (FALSE);
34774462Salfred	if (thr_main())
34874462Salfred		clnt_broadcast_result = clnt_broadcast_result_main;
34974462Salfred	else
35074462Salfred		clnt_broadcast_result = (resultproc_t)thr_getspecific(clnt_broadcast_key);
35174462Salfred	return (*clnt_broadcast_result)(resultp,
35274462Salfred				(struct sockaddr_in *)addr->buf);
35374462Salfred}
35474462Salfred
35574462Salfred/*
35674462Salfred * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
35774462Salfred */
35874462Salfredenum clnt_stat
359309489Sngieclnt_broadcast(u_long prog, u_long vers, u_long proc, xdrproc_t xargs,
360309489Sngie    void *argsp, xdrproc_t xresults, void *resultsp, resultproc_t eachresult)
361309489Sngie/*
362309489Sngie *	u_long		prog;		// program number
363309489Sngie *	u_long		vers;		// version number
364309489Sngie *	u_long		proc;		// procedure number
365309489Sngie *	xdrproc_t	xargs;		// xdr routine for args
366309489Sngie *	void	       *argsp;		// pointer to args
367309489Sngie *	xdrproc_t	xresults;	// xdr routine for results
368309489Sngie *	void	       *resultsp;	// pointer to results
369309489Sngie *	resultproc_t	eachresult;	// call with each result obtained
370309489Sngie */
37174462Salfred{
37274462Salfred
37374462Salfred	if (thr_main())
37474462Salfred		clnt_broadcast_result_main = eachresult;
37574462Salfred	else {
376204950Sjhb		thr_once(&clnt_broadcast_once, clnt_broadcast_key_init);
37774462Salfred		thr_setspecific(clnt_broadcast_key, (void *) eachresult);
37874462Salfred	}
37974462Salfred	return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
38074462Salfred	    (rpcproc_t)proc, xargs, argsp, xresults, resultsp,
38174462Salfred	    (resultproc_t) rpc_wrap_bcast, "udp");
38274462Salfred}
38374462Salfred
38474462Salfred/*
38574462Salfred * Create the client des authentication object. Obsoleted by
38674462Salfred * authdes_seccreate().
38774462Salfred */
38874462SalfredAUTH *
389309489Sngieauthdes_create(char *servername, u_int window, struct sockaddr *syncaddr,
390309489Sngie    des_block *ckey)
391309489Sngie/*
392309489Sngie *	char *servername;		// network name of server
393309489Sngie *	u_int window;			// time to live
394309489Sngie *	struct sockaddr *syncaddr;	// optional hostaddr to sync with
395309489Sngie *	des_block *ckey;		// optional conversation key to use
396309489Sngie */
39774462Salfred{
39874462Salfred	AUTH *dummy;
39974462Salfred	AUTH *nauth;
40074462Salfred	char hostname[NI_MAXHOST];
40174462Salfred
40274462Salfred	if (syncaddr) {
40374462Salfred		/*
40474462Salfred		 * Change addr to hostname, because that is the way
40574462Salfred		 * new interface takes it.
40674462Salfred		 */
40774462Salfred		if (getnameinfo(syncaddr, syncaddr->sa_len, hostname,
40874462Salfred		    sizeof hostname, NULL, 0, 0) != 0)
40974462Salfred			goto fallback;
41074462Salfred
41174462Salfred		nauth = authdes_seccreate(servername, window, hostname, ckey);
41274462Salfred		return (nauth);
41374462Salfred	}
41474462Salfredfallback:
41574462Salfred	dummy = authdes_seccreate(servername, window, NULL, ckey);
41674462Salfred	return (dummy);
41774462Salfred}
41874462Salfred
41984487Swpaul/*
42084487Swpaul * Create a client handle for a unix connection. Obsoleted by clnt_vc_create()
42184487Swpaul */
42284487SwpaulCLIENT *
423309489Sngieclntunix_create(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp,
424309489Sngie    u_int sendsz, u_int recvsz)
42584487Swpaul{
42684487Swpaul	struct netbuf *svcaddr;
42784487Swpaul	CLIENT *cl;
42884487Swpaul	int len;
42984487Swpaul
43090271Salfred	cl = NULL;
43190271Salfred	svcaddr = NULL;
43284487Swpaul	if ((raddr->sun_len == 0) ||
43384487Swpaul	   ((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) ||
43484487Swpaul	   ((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) {
435290899Sngie		free(svcaddr);
43684487Swpaul		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
43784487Swpaul		rpc_createerr.cf_error.re_errno = errno;
43884487Swpaul		return(cl);
43984487Swpaul	}
44084487Swpaul	if (*sockp < 0) {
44184487Swpaul		*sockp = _socket(AF_LOCAL, SOCK_STREAM, 0);
44284487Swpaul		len = raddr->sun_len = SUN_LEN(raddr);
44384487Swpaul		if ((*sockp < 0) || (_connect(*sockp,
44484487Swpaul		    (struct sockaddr *)raddr, len) < 0)) {
44584487Swpaul			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
44684487Swpaul			rpc_createerr.cf_error.re_errno = errno;
44784487Swpaul			if (*sockp != -1)
44884487Swpaul				(void)_close(*sockp);
44984487Swpaul			goto done;
45084487Swpaul		}
45184487Swpaul	}
45284487Swpaul	svcaddr->buf = raddr;
45384487Swpaul	svcaddr->len = raddr->sun_len;
45484487Swpaul	svcaddr->maxlen = sizeof (struct sockaddr_un);
45584487Swpaul	cl = clnt_vc_create(*sockp, svcaddr, prog,
45684487Swpaul	    vers, sendsz, recvsz);
45784487Swpauldone:
45884487Swpaul	free(svcaddr->buf);
45984487Swpaul	free(svcaddr);
46084487Swpaul	return(cl);
46184487Swpaul}
46284487Swpaul
46384487Swpaul/*
46484487Swpaul * Creates, registers, and returns a (rpc) unix based transporter.
46584487Swpaul * Obsoleted by svc_vc_create().
46684487Swpaul */
46784487SwpaulSVCXPRT *
468309489Sngiesvcunix_create(int sock, u_int sendsize, u_int recvsize, char *path)
46984487Swpaul{
47084487Swpaul	struct netconfig *nconf;
47184487Swpaul	void *localhandle;
47284487Swpaul	struct sockaddr_un sun;
47384487Swpaul	struct sockaddr *sa;
47484487Swpaul	struct t_bind taddr;
47584487Swpaul	SVCXPRT *xprt;
47684487Swpaul	int addrlen;
47784487Swpaul
47884487Swpaul	xprt = (SVCXPRT *)NULL;
47984487Swpaul	localhandle = setnetconfig();
48084487Swpaul	while ((nconf = getnetconfig(localhandle)) != NULL) {
48184487Swpaul		if (nconf->nc_protofmly != NULL &&
48284487Swpaul		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
48384487Swpaul			break;
48484487Swpaul	}
48584487Swpaul	if (nconf == NULL)
486294239Sngie		goto done;
48784487Swpaul
48884487Swpaul	if ((sock = __rpc_nconf2fd(nconf)) < 0)
48984487Swpaul		goto done;
49084487Swpaul
49184487Swpaul	memset(&sun, 0, sizeof sun);
49284487Swpaul	sun.sun_family = AF_LOCAL;
493114443Snectar	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
49484487Swpaul	    sizeof(sun.sun_path))
49584487Swpaul		goto done;
49684487Swpaul	sun.sun_len = SUN_LEN(&sun);
49784487Swpaul	addrlen = sizeof (struct sockaddr_un);
49884487Swpaul	sa = (struct sockaddr *)&sun;
49984487Swpaul
50084487Swpaul	if (_bind(sock, sa, addrlen) < 0)
50184487Swpaul		goto done;
50284487Swpaul
50384487Swpaul	taddr.addr.len = taddr.addr.maxlen = addrlen;
50484487Swpaul	taddr.addr.buf = malloc(addrlen);
50584487Swpaul	if (taddr.addr.buf == NULL)
50684487Swpaul		goto done;
50784487Swpaul	memcpy(taddr.addr.buf, sa, addrlen);
50884487Swpaul
50984487Swpaul	if (nconf->nc_semantics != NC_TPI_CLTS) {
51084487Swpaul		if (_listen(sock, SOMAXCONN) < 0) {
51184487Swpaul			free(taddr.addr.buf);
51284487Swpaul			goto done;
51384487Swpaul		}
51484487Swpaul	}
51584487Swpaul
51684487Swpaul	xprt = (SVCXPRT *)svc_tli_create(sock, nconf, &taddr, sendsize, recvsize);
51784487Swpaul
51884487Swpauldone:
51984487Swpaul	endnetconfig(localhandle);
52084487Swpaul	return(xprt);
52184487Swpaul}
52284487Swpaul
52384487Swpaul/*
52484487Swpaul * Like svunix_create(), except the routine takes any *open* UNIX file
52584487Swpaul * descriptor as its first input. Obsoleted by svc_fd_create();
52684487Swpaul */
52784487SwpaulSVCXPRT *
528309489Sngiesvcunixfd_create(int fd, u_int sendsize, u_int recvsize)
52984487Swpaul{
53084487Swpaul 	return (svc_fd_create(fd, sendsize, recvsize));
53184487Swpaul}
53284487Swpaul
53374462Salfred#endif /* PORTMAP */
534