rpc_generic.c revision 177633
1177633Sdfr/*	$NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $	*/
2177633Sdfr
3177633Sdfr/*
4177633Sdfr * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5177633Sdfr * unrestricted use provided that this legend is included on all tape
6177633Sdfr * media and as a part of the software program in whole or part.  Users
7177633Sdfr * may copy or modify Sun RPC without charge, but are not authorized
8177633Sdfr * to license or distribute it to anyone else except as part of a product or
9177633Sdfr * program developed by the user.
10177633Sdfr *
11177633Sdfr * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12177633Sdfr * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13177633Sdfr * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14177633Sdfr *
15177633Sdfr * Sun RPC is provided with no support and without any obligation on the
16177633Sdfr * part of Sun Microsystems, Inc. to assist in its use, correction,
17177633Sdfr * modification or enhancement.
18177633Sdfr *
19177633Sdfr * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20177633Sdfr * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21177633Sdfr * OR ANY PART THEREOF.
22177633Sdfr *
23177633Sdfr * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24177633Sdfr * or profits or other special, indirect and consequential damages, even if
25177633Sdfr * Sun has been advised of the possibility of such damages.
26177633Sdfr *
27177633Sdfr * Sun Microsystems, Inc.
28177633Sdfr * 2550 Garcia Avenue
29177633Sdfr * Mountain View, California  94043
30177633Sdfr */
31177633Sdfr/*
32177633Sdfr * Copyright (c) 1986-1991 by Sun Microsystems Inc.
33177633Sdfr */
34177633Sdfr
35177633Sdfr/* #pragma ident	"@(#)rpc_generic.c	1.17	94/04/24 SMI" */
36177633Sdfr#include <sys/cdefs.h>
37177633Sdfr__FBSDID("$FreeBSD: head/sys/rpc/rpc_generic.c 177633 2008-03-26 15:23:12Z dfr $");
38177633Sdfr
39177633Sdfr/*
40177633Sdfr * rpc_generic.c, Miscl routines for RPC.
41177633Sdfr *
42177633Sdfr */
43177633Sdfr
44177633Sdfr#include "opt_inet6.h"
45177633Sdfr
46177633Sdfr#include <sys/param.h>
47177633Sdfr#include <sys/malloc.h>
48177633Sdfr#include <sys/proc.h>
49177633Sdfr#include <sys/protosw.h>
50177633Sdfr#include <sys/sbuf.h>
51177633Sdfr#include <sys/systm.h>
52177633Sdfr#include <sys/socket.h>
53177633Sdfr#include <sys/socketvar.h>
54177633Sdfr#include <sys/syslog.h>
55177633Sdfr
56177633Sdfr#include <rpc/rpc.h>
57177633Sdfr#include <rpc/nettype.h>
58177633Sdfr
59177633Sdfr#include "rpc_com.h"
60177633Sdfr
61177633Sdfrstruct handle {
62177633Sdfr	NCONF_HANDLE *nhandle;
63177633Sdfr	int nflag;		/* Whether NETPATH or NETCONFIG */
64177633Sdfr	int nettype;
65177633Sdfr};
66177633Sdfr
67177633Sdfrstatic const struct _rpcnettype {
68177633Sdfr	const char *name;
69177633Sdfr	const int type;
70177633Sdfr} _rpctypelist[] = {
71177633Sdfr	{ "netpath", _RPC_NETPATH },
72177633Sdfr	{ "visible", _RPC_VISIBLE },
73177633Sdfr	{ "circuit_v", _RPC_CIRCUIT_V },
74177633Sdfr	{ "datagram_v", _RPC_DATAGRAM_V },
75177633Sdfr	{ "circuit_n", _RPC_CIRCUIT_N },
76177633Sdfr	{ "datagram_n", _RPC_DATAGRAM_N },
77177633Sdfr	{ "tcp", _RPC_TCP },
78177633Sdfr	{ "udp", _RPC_UDP },
79177633Sdfr	{ 0, _RPC_NONE }
80177633Sdfr};
81177633Sdfr
82177633Sdfrstruct netid_af {
83177633Sdfr	const char	*netid;
84177633Sdfr	int		af;
85177633Sdfr	int		protocol;
86177633Sdfr};
87177633Sdfr
88177633Sdfrstatic const struct netid_af na_cvt[] = {
89177633Sdfr	{ "udp",  AF_INET,  IPPROTO_UDP },
90177633Sdfr	{ "tcp",  AF_INET,  IPPROTO_TCP },
91177633Sdfr#ifdef INET6
92177633Sdfr	{ "udp6", AF_INET6, IPPROTO_UDP },
93177633Sdfr	{ "tcp6", AF_INET6, IPPROTO_TCP },
94177633Sdfr#endif
95177633Sdfr	{ "local", AF_LOCAL, 0 }
96177633Sdfr};
97177633Sdfr
98177633Sdfrstruct rpc_createerr rpc_createerr;
99177633Sdfr
100177633Sdfr/*
101177633Sdfr * Find the appropriate buffer size
102177633Sdfr */
103177633Sdfru_int
104177633Sdfr/*ARGSUSED*/
105177633Sdfr__rpc_get_t_size(int af, int proto, int size)
106177633Sdfr{
107177633Sdfr	int maxsize, defsize;
108177633Sdfr
109177633Sdfr	maxsize = 256 * 1024;	/* XXX */
110177633Sdfr	switch (proto) {
111177633Sdfr	case IPPROTO_TCP:
112177633Sdfr		defsize = 64 * 1024;	/* XXX */
113177633Sdfr		break;
114177633Sdfr	case IPPROTO_UDP:
115177633Sdfr		defsize = UDPMSGSIZE;
116177633Sdfr		break;
117177633Sdfr	default:
118177633Sdfr		defsize = RPC_MAXDATASIZE;
119177633Sdfr		break;
120177633Sdfr	}
121177633Sdfr	if (size == 0)
122177633Sdfr		return defsize;
123177633Sdfr
124177633Sdfr	/* Check whether the value is within the upper max limit */
125177633Sdfr	return (size > maxsize ? (u_int)maxsize : (u_int)size);
126177633Sdfr}
127177633Sdfr
128177633Sdfr/*
129177633Sdfr * Find the appropriate address buffer size
130177633Sdfr */
131177633Sdfru_int
132177633Sdfr__rpc_get_a_size(af)
133177633Sdfr	int af;
134177633Sdfr{
135177633Sdfr	switch (af) {
136177633Sdfr	case AF_INET:
137177633Sdfr		return sizeof (struct sockaddr_in);
138177633Sdfr#ifdef INET6
139177633Sdfr	case AF_INET6:
140177633Sdfr		return sizeof (struct sockaddr_in6);
141177633Sdfr#endif
142177633Sdfr	case AF_LOCAL:
143177633Sdfr		return sizeof (struct sockaddr_un);
144177633Sdfr	default:
145177633Sdfr		break;
146177633Sdfr	}
147177633Sdfr	return ((u_int)RPC_MAXADDRSIZE);
148177633Sdfr}
149177633Sdfr
150177633Sdfr#if 0
151177633Sdfr
152177633Sdfr/*
153177633Sdfr * Used to ping the NULL procedure for clnt handle.
154177633Sdfr * Returns NULL if fails, else a non-NULL pointer.
155177633Sdfr */
156177633Sdfrvoid *
157177633Sdfrrpc_nullproc(clnt)
158177633Sdfr	CLIENT *clnt;
159177633Sdfr{
160177633Sdfr	struct timeval TIMEOUT = {25, 0};
161177633Sdfr
162177633Sdfr	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
163177633Sdfr		(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
164177633Sdfr		return (NULL);
165177633Sdfr	}
166177633Sdfr	return ((void *) clnt);
167177633Sdfr}
168177633Sdfr
169177633Sdfr#endif
170177633Sdfr
171177633Sdfrint
172177633Sdfr__rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip)
173177633Sdfr{
174177633Sdfr	int type, proto;
175177633Sdfr	struct sockaddr *sa;
176177633Sdfr	sa_family_t family;
177177633Sdfr	struct sockopt opt;
178177633Sdfr	int error;
179177633Sdfr
180177633Sdfr	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
181177633Sdfr	if (error)
182177633Sdfr		return 0;
183177633Sdfr
184177633Sdfr	sip->si_alen = sa->sa_len;
185177633Sdfr	family = sa->sa_family;
186177633Sdfr	free(sa, M_SONAME);
187177633Sdfr
188177633Sdfr	opt.sopt_dir = SOPT_GET;
189177633Sdfr	opt.sopt_level = SOL_SOCKET;
190177633Sdfr	opt.sopt_name = SO_TYPE;
191177633Sdfr	opt.sopt_val = &type;
192177633Sdfr	opt.sopt_valsize = sizeof type;
193177633Sdfr	opt.sopt_td = NULL;
194177633Sdfr	error = sogetopt(so, &opt);
195177633Sdfr	if (error)
196177633Sdfr		return 0;
197177633Sdfr
198177633Sdfr	/* XXX */
199177633Sdfr	if (family != AF_LOCAL) {
200177633Sdfr		if (type == SOCK_STREAM)
201177633Sdfr			proto = IPPROTO_TCP;
202177633Sdfr		else if (type == SOCK_DGRAM)
203177633Sdfr			proto = IPPROTO_UDP;
204177633Sdfr		else
205177633Sdfr			return 0;
206177633Sdfr	} else
207177633Sdfr		proto = 0;
208177633Sdfr
209177633Sdfr	sip->si_af = family;
210177633Sdfr	sip->si_proto = proto;
211177633Sdfr	sip->si_socktype = type;
212177633Sdfr
213177633Sdfr	return 1;
214177633Sdfr}
215177633Sdfr
216177633Sdfr/*
217177633Sdfr * Linear search, but the number of entries is small.
218177633Sdfr */
219177633Sdfrint
220177633Sdfr__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
221177633Sdfr{
222177633Sdfr	int i;
223177633Sdfr
224177633Sdfr	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
225177633Sdfr		if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
226177633Sdfr		    strcmp(nconf->nc_netid, "unix") == 0 &&
227177633Sdfr		    strcmp(na_cvt[i].netid, "local") == 0)) {
228177633Sdfr			sip->si_af = na_cvt[i].af;
229177633Sdfr			sip->si_proto = na_cvt[i].protocol;
230177633Sdfr			sip->si_socktype =
231177633Sdfr			    __rpc_seman2socktype((int)nconf->nc_semantics);
232177633Sdfr			if (sip->si_socktype == -1)
233177633Sdfr				return 0;
234177633Sdfr			sip->si_alen = __rpc_get_a_size(sip->si_af);
235177633Sdfr			return 1;
236177633Sdfr		}
237177633Sdfr
238177633Sdfr	return 0;
239177633Sdfr}
240177633Sdfr
241177633Sdfrstruct socket *
242177633Sdfr__rpc_nconf2socket(const struct netconfig *nconf)
243177633Sdfr{
244177633Sdfr	struct __rpc_sockinfo si;
245177633Sdfr	struct socket *so;
246177633Sdfr	int error;
247177633Sdfr
248177633Sdfr	if (!__rpc_nconf2sockinfo(nconf, &si))
249177633Sdfr		return 0;
250177633Sdfr
251177633Sdfr	so = NULL;
252177633Sdfr	error =  socreate(si.si_af, &so, si.si_socktype, si.si_proto,
253177633Sdfr	    curthread->td_ucred, curthread);
254177633Sdfr
255177633Sdfr	if (error)
256177633Sdfr		return NULL;
257177633Sdfr	else
258177633Sdfr		return so;
259177633Sdfr}
260177633Sdfr
261177633Sdfrchar *
262177633Sdfrtaddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
263177633Sdfr{
264177633Sdfr	struct __rpc_sockinfo si;
265177633Sdfr
266177633Sdfr	if (!__rpc_nconf2sockinfo(nconf, &si))
267177633Sdfr		return NULL;
268177633Sdfr	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
269177633Sdfr}
270177633Sdfr
271177633Sdfrstruct netbuf *
272177633Sdfruaddr2taddr(const struct netconfig *nconf, const char *uaddr)
273177633Sdfr{
274177633Sdfr	struct __rpc_sockinfo si;
275177633Sdfr
276177633Sdfr	if (!__rpc_nconf2sockinfo(nconf, &si))
277177633Sdfr		return NULL;
278177633Sdfr	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
279177633Sdfr}
280177633Sdfr
281177633Sdfrchar *
282177633Sdfr__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
283177633Sdfr{
284177633Sdfr	char *ret;
285177633Sdfr	struct sbuf sb;
286177633Sdfr	struct sockaddr_in *sin;
287177633Sdfr	struct sockaddr_un *sun;
288177633Sdfr	char namebuf[INET_ADDRSTRLEN];
289177633Sdfr#ifdef INET6
290177633Sdfr	struct sockaddr_in6 *sin6;
291177633Sdfr	char namebuf6[INET6_ADDRSTRLEN];
292177633Sdfr#endif
293177633Sdfr	u_int16_t port;
294177633Sdfr
295177633Sdfr	sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND);
296177633Sdfr
297177633Sdfr	switch (af) {
298177633Sdfr	case AF_INET:
299177633Sdfr		sin = nbuf->buf;
300177633Sdfr		if (__rpc_inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
301177633Sdfr		    == NULL)
302177633Sdfr			return NULL;
303177633Sdfr		port = ntohs(sin->sin_port);
304177633Sdfr		if (sbuf_printf(&sb, "%s.%u.%u", namebuf,
305177633Sdfr			((uint32_t)port) >> 8,
306177633Sdfr			port & 0xff) < 0)
307177633Sdfr			return NULL;
308177633Sdfr		break;
309177633Sdfr#ifdef INET6
310177633Sdfr	case AF_INET6:
311177633Sdfr		sin6 = nbuf->buf;
312177633Sdfr		if (__rpc_inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
313177633Sdfr		    == NULL)
314177633Sdfr			return NULL;
315177633Sdfr		port = ntohs(sin6->sin6_port);
316177633Sdfr		if (sbuf_printf(&sb, "%s.%u.%u", namebuf6,
317177633Sdfr			((uint32_t)port) >> 8,
318177633Sdfr			port & 0xff) < 0)
319177633Sdfr			return NULL;
320177633Sdfr		break;
321177633Sdfr#endif
322177633Sdfr	case AF_LOCAL:
323177633Sdfr		sun = nbuf->buf;
324177633Sdfr		if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len -
325177633Sdfr			    offsetof(struct sockaddr_un, sun_path)),
326177633Sdfr			sun->sun_path) < 0)
327177633Sdfr			return (NULL);
328177633Sdfr		break;
329177633Sdfr	default:
330177633Sdfr		return NULL;
331177633Sdfr	}
332177633Sdfr
333177633Sdfr	sbuf_finish(&sb);
334177633Sdfr	ret = strdup(sbuf_data(&sb), M_RPC);
335177633Sdfr	sbuf_delete(&sb);
336177633Sdfr
337177633Sdfr	return ret;
338177633Sdfr}
339177633Sdfr
340177633Sdfrstruct netbuf *
341177633Sdfr__rpc_uaddr2taddr_af(int af, const char *uaddr)
342177633Sdfr{
343177633Sdfr	struct netbuf *ret = NULL;
344177633Sdfr	char *addrstr, *p;
345177633Sdfr	unsigned port, portlo, porthi;
346177633Sdfr	struct sockaddr_in *sin;
347177633Sdfr#ifdef INET6
348177633Sdfr	struct sockaddr_in6 *sin6;
349177633Sdfr#endif
350177633Sdfr	struct sockaddr_un *sun;
351177633Sdfr
352177633Sdfr	port = 0;
353177633Sdfr	sin = NULL;
354177633Sdfr	addrstr = strdup(uaddr, M_RPC);
355177633Sdfr	if (addrstr == NULL)
356177633Sdfr		return NULL;
357177633Sdfr
358177633Sdfr	/*
359177633Sdfr	 * AF_LOCAL addresses are expected to be absolute
360177633Sdfr	 * pathnames, anything else will be AF_INET or AF_INET6.
361177633Sdfr	 */
362177633Sdfr	if (*addrstr != '/') {
363177633Sdfr		p = strrchr(addrstr, '.');
364177633Sdfr		if (p == NULL)
365177633Sdfr			goto out;
366177633Sdfr		portlo = (unsigned)strtol(p + 1, NULL, 10);
367177633Sdfr		*p = '\0';
368177633Sdfr
369177633Sdfr		p = strrchr(addrstr, '.');
370177633Sdfr		if (p == NULL)
371177633Sdfr			goto out;
372177633Sdfr		porthi = (unsigned)strtol(p + 1, NULL, 10);
373177633Sdfr		*p = '\0';
374177633Sdfr		port = (porthi << 8) | portlo;
375177633Sdfr	}
376177633Sdfr
377177633Sdfr	ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK);
378177633Sdfr	if (ret == NULL)
379177633Sdfr		goto out;
380177633Sdfr
381177633Sdfr	switch (af) {
382177633Sdfr	case AF_INET:
383177633Sdfr		sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC,
384177633Sdfr		    M_WAITOK);
385177633Sdfr		if (sin == NULL)
386177633Sdfr			goto out;
387177633Sdfr		memset(sin, 0, sizeof *sin);
388177633Sdfr		sin->sin_family = AF_INET;
389177633Sdfr		sin->sin_port = htons(port);
390177633Sdfr		if (__rpc_inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
391177633Sdfr			free(sin, M_RPC);
392177633Sdfr			free(ret, M_RPC);
393177633Sdfr			ret = NULL;
394177633Sdfr			goto out;
395177633Sdfr		}
396177633Sdfr		sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
397177633Sdfr		ret->buf = sin;
398177633Sdfr		break;
399177633Sdfr#ifdef INET6
400177633Sdfr	case AF_INET6:
401177633Sdfr		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC,
402177633Sdfr		    M_WAITOK);
403177633Sdfr		if (sin6 == NULL)
404177633Sdfr			goto out;
405177633Sdfr		memset(sin6, 0, sizeof *sin6);
406177633Sdfr		sin6->sin6_family = AF_INET6;
407177633Sdfr		sin6->sin6_port = htons(port);
408177633Sdfr		if (__rpc_inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
409177633Sdfr			free(sin6, M_RPC);
410177633Sdfr			free(ret, M_RPC);
411177633Sdfr			ret = NULL;
412177633Sdfr			goto out;
413177633Sdfr		}
414177633Sdfr		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
415177633Sdfr		ret->buf = sin6;
416177633Sdfr		break;
417177633Sdfr#endif
418177633Sdfr	case AF_LOCAL:
419177633Sdfr		sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC,
420177633Sdfr		    M_WAITOK);
421177633Sdfr		if (sun == NULL)
422177633Sdfr			goto out;
423177633Sdfr		memset(sun, 0, sizeof *sun);
424177633Sdfr		sun->sun_family = AF_LOCAL;
425177633Sdfr		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
426177633Sdfr		ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
427177633Sdfr		ret->buf = sun;
428177633Sdfr		break;
429177633Sdfr	default:
430177633Sdfr		break;
431177633Sdfr	}
432177633Sdfrout:
433177633Sdfr	free(addrstr, M_RPC);
434177633Sdfr	return ret;
435177633Sdfr}
436177633Sdfr
437177633Sdfrint
438177633Sdfr__rpc_seman2socktype(int semantics)
439177633Sdfr{
440177633Sdfr	switch (semantics) {
441177633Sdfr	case NC_TPI_CLTS:
442177633Sdfr		return SOCK_DGRAM;
443177633Sdfr	case NC_TPI_COTS_ORD:
444177633Sdfr		return SOCK_STREAM;
445177633Sdfr	case NC_TPI_RAW:
446177633Sdfr		return SOCK_RAW;
447177633Sdfr	default:
448177633Sdfr		break;
449177633Sdfr	}
450177633Sdfr
451177633Sdfr	return -1;
452177633Sdfr}
453177633Sdfr
454177633Sdfrint
455177633Sdfr__rpc_socktype2seman(int socktype)
456177633Sdfr{
457177633Sdfr	switch (socktype) {
458177633Sdfr	case SOCK_DGRAM:
459177633Sdfr		return NC_TPI_CLTS;
460177633Sdfr	case SOCK_STREAM:
461177633Sdfr		return NC_TPI_COTS_ORD;
462177633Sdfr	case SOCK_RAW:
463177633Sdfr		return NC_TPI_RAW;
464177633Sdfr	default:
465177633Sdfr		break;
466177633Sdfr	}
467177633Sdfr
468177633Sdfr	return -1;
469177633Sdfr}
470177633Sdfr
471177633Sdfr/*
472177633Sdfr * Returns the type of the network as defined in <rpc/nettype.h>
473177633Sdfr * If nettype is NULL, it defaults to NETPATH.
474177633Sdfr */
475177633Sdfrstatic int
476177633Sdfrgetnettype(const char *nettype)
477177633Sdfr{
478177633Sdfr	int i;
479177633Sdfr
480177633Sdfr	if ((nettype == NULL) || (nettype[0] == 0)) {
481177633Sdfr		return (_RPC_NETPATH);	/* Default */
482177633Sdfr	}
483177633Sdfr
484177633Sdfr#if 0
485177633Sdfr	nettype = strlocase(nettype);
486177633Sdfr#endif
487177633Sdfr	for (i = 0; _rpctypelist[i].name; i++)
488177633Sdfr		if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
489177633Sdfr			return (_rpctypelist[i].type);
490177633Sdfr		}
491177633Sdfr	return (_rpctypelist[i].type);
492177633Sdfr}
493177633Sdfr
494177633Sdfr/*
495177633Sdfr * For the given nettype (tcp or udp only), return the first structure found.
496177633Sdfr * This should be freed by calling freenetconfigent()
497177633Sdfr */
498177633Sdfrstruct netconfig *
499177633Sdfr__rpc_getconfip(const char *nettype)
500177633Sdfr{
501177633Sdfr	char *netid;
502177633Sdfr	static char *netid_tcp = (char *) NULL;
503177633Sdfr	static char *netid_udp = (char *) NULL;
504177633Sdfr	struct netconfig *dummy;
505177633Sdfr
506177633Sdfr	if (!netid_udp && !netid_tcp) {
507177633Sdfr		struct netconfig *nconf;
508177633Sdfr		void *confighandle;
509177633Sdfr
510177633Sdfr		if (!(confighandle = setnetconfig())) {
511177633Sdfr			log(LOG_ERR, "rpc: failed to open " NETCONFIG);
512177633Sdfr			return (NULL);
513177633Sdfr		}
514177633Sdfr		while ((nconf = getnetconfig(confighandle)) != NULL) {
515177633Sdfr			if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
516177633Sdfr				if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
517177633Sdfr					netid_tcp = strdup(nconf->nc_netid,
518177633Sdfr					    M_RPC);
519177633Sdfr				} else
520177633Sdfr				if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
521177633Sdfr					netid_udp = strdup(nconf->nc_netid,
522177633Sdfr					    M_RPC);
523177633Sdfr				}
524177633Sdfr			}
525177633Sdfr		}
526177633Sdfr		endnetconfig(confighandle);
527177633Sdfr	}
528177633Sdfr	if (strcmp(nettype, "udp") == 0)
529177633Sdfr		netid = netid_udp;
530177633Sdfr	else if (strcmp(nettype, "tcp") == 0)
531177633Sdfr		netid = netid_tcp;
532177633Sdfr	else {
533177633Sdfr		return (NULL);
534177633Sdfr	}
535177633Sdfr	if ((netid == NULL) || (netid[0] == 0)) {
536177633Sdfr		return (NULL);
537177633Sdfr	}
538177633Sdfr	dummy = getnetconfigent(netid);
539177633Sdfr	return (dummy);
540177633Sdfr}
541177633Sdfr
542177633Sdfr/*
543177633Sdfr * Returns the type of the nettype, which should then be used with
544177633Sdfr * __rpc_getconf().
545177633Sdfr *
546177633Sdfr * For simplicity in the kernel, we don't support the NETPATH
547177633Sdfr * environment variable. We behave as userland would then NETPATH is
548177633Sdfr * unset, i.e. iterate over all visible entries in netconfig.
549177633Sdfr */
550177633Sdfrvoid *
551177633Sdfr__rpc_setconf(nettype)
552177633Sdfr	const char *nettype;
553177633Sdfr{
554177633Sdfr	struct handle *handle;
555177633Sdfr
556177633Sdfr	handle = (struct handle *) malloc(sizeof (struct handle),
557177633Sdfr	    M_RPC, M_WAITOK);
558177633Sdfr	switch (handle->nettype = getnettype(nettype)) {
559177633Sdfr	case _RPC_NETPATH:
560177633Sdfr	case _RPC_CIRCUIT_N:
561177633Sdfr	case _RPC_DATAGRAM_N:
562177633Sdfr		if (!(handle->nhandle = setnetconfig()))
563177633Sdfr			goto failed;
564177633Sdfr		handle->nflag = TRUE;
565177633Sdfr		break;
566177633Sdfr	case _RPC_VISIBLE:
567177633Sdfr	case _RPC_CIRCUIT_V:
568177633Sdfr	case _RPC_DATAGRAM_V:
569177633Sdfr	case _RPC_TCP:
570177633Sdfr	case _RPC_UDP:
571177633Sdfr		if (!(handle->nhandle = setnetconfig())) {
572177633Sdfr		        log(LOG_ERR, "rpc: failed to open " NETCONFIG);
573177633Sdfr			goto failed;
574177633Sdfr		}
575177633Sdfr		handle->nflag = FALSE;
576177633Sdfr		break;
577177633Sdfr	default:
578177633Sdfr		goto failed;
579177633Sdfr	}
580177633Sdfr
581177633Sdfr	return (handle);
582177633Sdfr
583177633Sdfrfailed:
584177633Sdfr	free(handle, M_RPC);
585177633Sdfr	return (NULL);
586177633Sdfr}
587177633Sdfr
588177633Sdfr/*
589177633Sdfr * Returns the next netconfig struct for the given "net" type.
590177633Sdfr * __rpc_setconf() should have been called previously.
591177633Sdfr */
592177633Sdfrstruct netconfig *
593177633Sdfr__rpc_getconf(void *vhandle)
594177633Sdfr{
595177633Sdfr	struct handle *handle;
596177633Sdfr	struct netconfig *nconf;
597177633Sdfr
598177633Sdfr	handle = (struct handle *)vhandle;
599177633Sdfr	if (handle == NULL) {
600177633Sdfr		return (NULL);
601177633Sdfr	}
602177633Sdfr	for (;;) {
603177633Sdfr		if (handle->nflag) {
604177633Sdfr			nconf = getnetconfig(handle->nhandle);
605177633Sdfr			if (nconf && !(nconf->nc_flag & NC_VISIBLE))
606177633Sdfr				continue;
607177633Sdfr		} else {
608177633Sdfr			nconf = getnetconfig(handle->nhandle);
609177633Sdfr		}
610177633Sdfr		if (nconf == NULL)
611177633Sdfr			break;
612177633Sdfr		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
613177633Sdfr			(nconf->nc_semantics != NC_TPI_COTS) &&
614177633Sdfr			(nconf->nc_semantics != NC_TPI_COTS_ORD))
615177633Sdfr			continue;
616177633Sdfr		switch (handle->nettype) {
617177633Sdfr		case _RPC_VISIBLE:
618177633Sdfr			if (!(nconf->nc_flag & NC_VISIBLE))
619177633Sdfr				continue;
620177633Sdfr			/* FALLTHROUGH */
621177633Sdfr		case _RPC_NETPATH:	/* Be happy */
622177633Sdfr			break;
623177633Sdfr		case _RPC_CIRCUIT_V:
624177633Sdfr			if (!(nconf->nc_flag & NC_VISIBLE))
625177633Sdfr				continue;
626177633Sdfr			/* FALLTHROUGH */
627177633Sdfr		case _RPC_CIRCUIT_N:
628177633Sdfr			if ((nconf->nc_semantics != NC_TPI_COTS) &&
629177633Sdfr				(nconf->nc_semantics != NC_TPI_COTS_ORD))
630177633Sdfr				continue;
631177633Sdfr			break;
632177633Sdfr		case _RPC_DATAGRAM_V:
633177633Sdfr			if (!(nconf->nc_flag & NC_VISIBLE))
634177633Sdfr				continue;
635177633Sdfr			/* FALLTHROUGH */
636177633Sdfr		case _RPC_DATAGRAM_N:
637177633Sdfr			if (nconf->nc_semantics != NC_TPI_CLTS)
638177633Sdfr				continue;
639177633Sdfr			break;
640177633Sdfr		case _RPC_TCP:
641177633Sdfr			if (((nconf->nc_semantics != NC_TPI_COTS) &&
642177633Sdfr				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
643177633Sdfr				(strcmp(nconf->nc_protofmly, NC_INET)
644177633Sdfr#ifdef INET6
645177633Sdfr				 && strcmp(nconf->nc_protofmly, NC_INET6))
646177633Sdfr#else
647177633Sdfr				)
648177633Sdfr#endif
649177633Sdfr				||
650177633Sdfr				strcmp(nconf->nc_proto, NC_TCP))
651177633Sdfr				continue;
652177633Sdfr			break;
653177633Sdfr		case _RPC_UDP:
654177633Sdfr			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
655177633Sdfr				(strcmp(nconf->nc_protofmly, NC_INET)
656177633Sdfr#ifdef INET6
657177633Sdfr				&& strcmp(nconf->nc_protofmly, NC_INET6))
658177633Sdfr#else
659177633Sdfr				)
660177633Sdfr#endif
661177633Sdfr				||
662177633Sdfr				strcmp(nconf->nc_proto, NC_UDP))
663177633Sdfr				continue;
664177633Sdfr			break;
665177633Sdfr		}
666177633Sdfr		break;
667177633Sdfr	}
668177633Sdfr	return (nconf);
669177633Sdfr}
670177633Sdfr
671177633Sdfrvoid
672177633Sdfr__rpc_endconf(vhandle)
673177633Sdfr	void * vhandle;
674177633Sdfr{
675177633Sdfr	struct handle *handle;
676177633Sdfr
677177633Sdfr	handle = (struct handle *) vhandle;
678177633Sdfr	if (handle == NULL) {
679177633Sdfr		return;
680177633Sdfr	}
681177633Sdfr	endnetconfig(handle->nhandle);
682177633Sdfr	free(handle, M_RPC);
683177633Sdfr}
684177633Sdfr
685177633Sdfrint
686177633Sdfr__rpc_sockisbound(struct socket *so)
687177633Sdfr{
688177633Sdfr	struct sockaddr *sa;
689177633Sdfr	int error, bound;
690177633Sdfr
691177633Sdfr	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
692177633Sdfr	if (error)
693177633Sdfr		return (0);
694177633Sdfr
695177633Sdfr	switch (sa->sa_family) {
696177633Sdfr		case AF_INET:
697177633Sdfr			bound = (((struct sockaddr_in *) sa)->sin_port != 0);
698177633Sdfr			break;
699177633Sdfr#ifdef INET6
700177633Sdfr		case AF_INET6:
701177633Sdfr			bound = (((struct sockaddr_in6 *) sa)->sin6_port != 0);
702177633Sdfr			break;
703177633Sdfr#endif
704177633Sdfr		case AF_LOCAL:
705177633Sdfr			/* XXX check this */
706177633Sdfr			bound = (((struct sockaddr_un *) sa)->sun_path[0] != '\0');
707177633Sdfr			break;
708177633Sdfr		default:
709177633Sdfr			bound = FALSE;
710177633Sdfr			break;
711177633Sdfr	}
712177633Sdfr
713177633Sdfr	free(sa, M_SONAME);
714177633Sdfr
715177633Sdfr	return bound;
716177633Sdfr}
717