xref: /netbsd/lib/libc/rpc/rpc_generic.c (revision c4a72b64)
1 /*	$NetBSD: rpc_generic.c,v 1.11 2002/11/11 20:34:10 thorpej 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  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
33  */
34 
35 /* #pragma ident	"@(#)rpc_generic.c	1.17	94/04/24 SMI" */
36 
37 /*
38  * rpc_generic.c, Miscl routines for RPC.
39  *
40  */
41 
42 #include "namespace.h"
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/socket.h>
46 #include <sys/un.h>
47 #include <sys/resource.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <rpc/rpc.h>
51 #include <assert.h>
52 #include <ctype.h>
53 #include <stdio.h>
54 #include <netdb.h>
55 #include <netconfig.h>
56 #include <malloc.h>
57 #include <string.h>
58 #include <syslog.h>
59 #include <rpc/nettype.h>
60 #include "rpc_internal.h"
61 
62 struct handle {
63 	NCONF_HANDLE *nhandle;
64 	int nflag;		/* Whether NETPATH or NETCONFIG */
65 	int nettype;
66 };
67 
68 static const struct _rpcnettype {
69 	const char *name;
70 	const int type;
71 } _rpctypelist[] = {
72 	{ "netpath", _RPC_NETPATH },
73 	{ "visible", _RPC_VISIBLE },
74 	{ "circuit_v", _RPC_CIRCUIT_V },
75 	{ "datagram_v", _RPC_DATAGRAM_V },
76 	{ "circuit_n", _RPC_CIRCUIT_N },
77 	{ "datagram_n", _RPC_DATAGRAM_N },
78 	{ "tcp", _RPC_TCP },
79 	{ "udp", _RPC_UDP },
80 	{ 0, _RPC_NONE }
81 };
82 
83 struct netid_af {
84 	const char	*netid;
85 	int		af;
86 	int		protocol;
87 };
88 
89 static const struct netid_af na_cvt[] = {
90 	{ "udp",  AF_INET,  IPPROTO_UDP },
91 	{ "tcp",  AF_INET,  IPPROTO_TCP },
92 #ifdef INET6
93 	{ "udp6", AF_INET6, IPPROTO_UDP },
94 	{ "tcp6", AF_INET6, IPPROTO_TCP },
95 #endif
96 	{ "local", AF_LOCAL, 0 }
97 };
98 
99 #if 0
100 static char *strlocase __P((char *));
101 #endif
102 static int getnettype __P((const char *));
103 
104 /*
105  * Cache the result of getrlimit(), so we don't have to do an
106  * expensive call every time.
107  */
108 int
109 __rpc_dtbsize()
110 {
111 	static int tbsize;
112 	struct rlimit rl;
113 
114 	if (tbsize) {
115 		return (tbsize);
116 	}
117 	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
118 		return (tbsize = (int)rl.rlim_max);
119 	}
120 	/*
121 	 * Something wrong.  I'll try to save face by returning a
122 	 * pessimistic number.
123 	 */
124 	return (32);
125 }
126 
127 
128 /*
129  * Find the appropriate buffer size
130  */
131 u_int
132 /*ARGSUSED*/
133 __rpc_get_t_size(af, proto, size)
134 	int af, proto;
135 	int size;	/* Size requested */
136 {
137 	int maxsize;
138 
139 	switch (proto) {
140 	case IPPROTO_TCP:
141 		maxsize = 65536;	/* XXX */
142 		break;
143 	case IPPROTO_UDP:
144 		maxsize = 8192;		/* XXX */
145 		break;
146 	default:
147 		maxsize = RPC_MAXDATASIZE;
148 		break;
149 	}
150 	if (size == 0)
151 		return maxsize;
152 
153 	/* Check whether the value is within the upper max limit */
154 	return (size > maxsize ? (u_int)maxsize : (u_int)size);
155 }
156 
157 /*
158  * Find the appropriate address buffer size
159  */
160 u_int
161 __rpc_get_a_size(af)
162 	int af;
163 {
164 	switch (af) {
165 	case AF_INET:
166 		return sizeof (struct sockaddr_in);
167 #ifdef INET6
168 	case AF_INET6:
169 		return sizeof (struct sockaddr_in6);
170 #endif
171 	case AF_LOCAL:
172 		return sizeof (struct sockaddr_un);
173 	default:
174 		break;
175 	}
176 	return ((u_int)RPC_MAXADDRSIZE);
177 }
178 
179 #if 0
180 static char *
181 strlocase(p)
182 	char *p;
183 {
184 	char *t = p;
185 
186 	_DIAGASSERT(p != NULL);
187 
188 	for (; *p; p++)
189 		if (isupper(*p))
190 			*p = tolower(*p);
191 	return (t);
192 }
193 #endif
194 
195 /*
196  * Returns the type of the network as defined in <rpc/nettype.h>
197  * If nettype is NULL, it defaults to NETPATH.
198  */
199 static int
200 getnettype(nettype)
201 	const char *nettype;
202 {
203 	int i;
204 
205 	if ((nettype == NULL) || (nettype[0] == NULL)) {
206 		return (_RPC_NETPATH);	/* Default */
207 	}
208 
209 #if 0
210 	nettype = strlocase(nettype);
211 #endif
212 	for (i = 0; _rpctypelist[i].name; i++)
213 		if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
214 			return (_rpctypelist[i].type);
215 		}
216 	return (_rpctypelist[i].type);
217 }
218 
219 /*
220  * For the given nettype (tcp or udp only), return the first structure found.
221  * This should be freed by calling freenetconfigent()
222  */
223 struct netconfig *
224 __rpc_getconfip(nettype)
225 	const char *nettype;
226 {
227 	char *netid;
228 	char *netid_tcp = (char *) NULL;
229 	char *netid_udp = (char *) NULL;
230 	static char *netid_tcp_main;
231 	static char *netid_udp_main;
232 	struct netconfig *dummy;
233 #ifdef __REENT
234 	int main_thread;
235 	static thread_key_t tcp_key, udp_key;
236 	extern mutex_t tsd_lock;
237 
238 	if ((main_thread = _thr_main())) {
239 		netid_udp = netid_udp_main;
240 		netid_tcp = netid_tcp_main;
241 	} else {
242 		if (tcp_key == 0) {
243 			mutex_lock(&tsd_lock);
244 			if (tcp_key == 0)
245 				thr_keycreate(&tcp_key, free);
246 			mutex_unlock(&tsd_lock);
247 		}
248 		thr_getspecific(tcp_key, (void **) &netid_tcp);
249 		if (udp_key == 0) {
250 			mutex_lock(&tsd_lock);
251 			if (udp_key == 0)
252 				thr_keycreate(&udp_key, free);
253 			mutex_unlock(&tsd_lock);
254 		}
255 		thr_getspecific(udp_key, (void **) &netid_udp);
256 	}
257 #else
258 	netid_udp = netid_udp_main;
259 	netid_tcp = netid_tcp_main;
260 #endif
261 
262 	_DIAGASSERT(nettype != NULL);
263 
264 	if (!netid_udp && !netid_tcp) {
265 		struct netconfig *nconf;
266 		void *confighandle;
267 
268 		if (!(confighandle = setnetconfig())) {
269 			syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
270 			return (NULL);
271 		}
272 		while ((nconf = getnetconfig(confighandle)) != NULL) {
273 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
274 				if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
275 					netid_tcp = strdup(nconf->nc_netid);
276 #ifdef __REENT
277 					if (main_thread)
278 						netid_tcp_main = netid_tcp;
279 					else
280 						thr_setspecific(tcp_key,
281 							(void *) netid_tcp);
282 #else
283 					netid_tcp_main = netid_tcp;
284 #endif
285 				} else
286 				if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
287 					netid_udp = strdup(nconf->nc_netid);
288 #ifdef __REENT
289 					if (main_thread)
290 						netid_udp_main = netid_udp;
291 					else
292 						thr_setspecific(udp_key,
293 							(void *) netid_udp);
294 #else
295 					netid_udp_main = netid_udp;
296 #endif
297 				}
298 			}
299 		}
300 		endnetconfig(confighandle);
301 	}
302 	if (strcmp(nettype, "udp") == 0)
303 		netid = netid_udp;
304 	else if (strcmp(nettype, "tcp") == 0)
305 		netid = netid_tcp;
306 	else {
307 		return (NULL);
308 	}
309 	if ((netid == NULL) || (netid[0] == NULL)) {
310 		return (NULL);
311 	}
312 	dummy = getnetconfigent(netid);
313 	return (dummy);
314 }
315 
316 /*
317  * Returns the type of the nettype, which should then be used with
318  * __rpc_getconf().
319  */
320 void *
321 __rpc_setconf(nettype)
322 	const char *nettype;
323 {
324 	struct handle *handle;
325 
326 	/* nettype may be NULL; getnettype() supports that */
327 
328 	handle = (struct handle *) malloc(sizeof (struct handle));
329 	if (handle == NULL) {
330 		return (NULL);
331 	}
332 	switch (handle->nettype = getnettype(nettype)) {
333 	case _RPC_NETPATH:
334 	case _RPC_CIRCUIT_N:
335 	case _RPC_DATAGRAM_N:
336 		if (!(handle->nhandle = setnetpath())) {
337 			free(handle);
338 			return (NULL);
339 		}
340 		handle->nflag = TRUE;
341 		break;
342 	case _RPC_VISIBLE:
343 	case _RPC_CIRCUIT_V:
344 	case _RPC_DATAGRAM_V:
345 	case _RPC_TCP:
346 	case _RPC_UDP:
347 		if (!(handle->nhandle = setnetconfig())) {
348 		        syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
349 			free(handle);
350 			return (NULL);
351 		}
352 		handle->nflag = FALSE;
353 		break;
354 	default:
355 		return (NULL);
356 	}
357 
358 	return (handle);
359 }
360 
361 /*
362  * Returns the next netconfig struct for the given "net" type.
363  * __rpc_setconf() should have been called previously.
364  */
365 struct netconfig *
366 __rpc_getconf(vhandle)
367 	void *vhandle;
368 {
369 	struct handle *handle;
370 	struct netconfig *nconf;
371 
372 	handle = (struct handle *)vhandle;
373 	if (handle == NULL) {
374 		return (NULL);
375 	}
376 	for (;;) {
377 		if (handle->nflag)
378 			nconf = getnetpath(handle->nhandle);
379 		else
380 			nconf = getnetconfig(handle->nhandle);
381 		if (nconf == NULL)
382 			break;
383 		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
384 			(nconf->nc_semantics != NC_TPI_COTS) &&
385 			(nconf->nc_semantics != NC_TPI_COTS_ORD))
386 			continue;
387 		switch (handle->nettype) {
388 		case _RPC_VISIBLE:
389 			if (!(nconf->nc_flag & NC_VISIBLE))
390 				continue;
391 			/* FALLTHROUGH */
392 		case _RPC_NETPATH:	/* Be happy */
393 			break;
394 		case _RPC_CIRCUIT_V:
395 			if (!(nconf->nc_flag & NC_VISIBLE))
396 				continue;
397 			/* FALLTHROUGH */
398 		case _RPC_CIRCUIT_N:
399 			if ((nconf->nc_semantics != NC_TPI_COTS) &&
400 				(nconf->nc_semantics != NC_TPI_COTS_ORD))
401 				continue;
402 			break;
403 		case _RPC_DATAGRAM_V:
404 			if (!(nconf->nc_flag & NC_VISIBLE))
405 				continue;
406 			/* FALLTHROUGH */
407 		case _RPC_DATAGRAM_N:
408 			if (nconf->nc_semantics != NC_TPI_CLTS)
409 				continue;
410 			break;
411 		case _RPC_TCP:
412 			if (((nconf->nc_semantics != NC_TPI_COTS) &&
413 				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
414 				(strcmp(nconf->nc_protofmly, NC_INET)
415 #ifdef INET6
416 				 && strcmp(nconf->nc_protofmly, NC_INET6))
417 #else
418 				)
419 #endif
420 				||
421 				strcmp(nconf->nc_proto, NC_TCP))
422 				continue;
423 			break;
424 		case _RPC_UDP:
425 			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
426 				(strcmp(nconf->nc_protofmly, NC_INET)
427 #ifdef INET6
428 				&& strcmp(nconf->nc_protofmly, NC_INET6))
429 #else
430 				)
431 #endif
432 				||
433 				strcmp(nconf->nc_proto, NC_UDP))
434 				continue;
435 			break;
436 		}
437 		break;
438 	}
439 	return (nconf);
440 }
441 
442 void
443 __rpc_endconf(vhandle)
444 	void * vhandle;
445 {
446 	struct handle *handle;
447 
448 	handle = (struct handle *) vhandle;
449 	if (handle == NULL) {
450 		return;
451 	}
452 	if (handle->nflag) {
453 		endnetpath(handle->nhandle);
454 	} else {
455 		endnetconfig(handle->nhandle);
456 	}
457 	free(handle);
458 }
459 
460 /*
461  * Used to ping the NULL procedure for clnt handle.
462  * Returns NULL if fails, else a non-NULL pointer.
463  */
464 void *
465 rpc_nullproc(clnt)
466 	CLIENT *clnt;
467 {
468 	struct timeval TIMEOUT = {25, 0};
469 
470 	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
471 		(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
472 		return (NULL);
473 	}
474 	return ((void *) clnt);
475 }
476 
477 /*
478  * Try all possible transports until
479  * one succeeds in finding the netconf for the given fd.
480  */
481 struct netconfig *
482 __rpcgettp(fd)
483 	int fd;
484 {
485 	const char *netid;
486 	struct __rpc_sockinfo si;
487 
488 	if (!__rpc_fd2sockinfo(fd, &si))
489 		return NULL;
490 
491 	if (!__rpc_sockinfo2netid(&si, &netid))
492 		return NULL;
493 
494 	/*LINTED const castaway*/
495 	return getnetconfigent((char *)netid);
496 }
497 
498 int
499 __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip)
500 {
501 	socklen_t len;
502 	int type, proto;
503 	struct sockaddr_storage ss;
504 
505 	_DIAGASSERT(sip != NULL);
506 
507 	len = sizeof ss;
508 	if (getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0)
509 		return 0;
510 	sip->si_alen = len;
511 
512 	len = sizeof type;
513 	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
514 		return 0;
515 
516 	/* XXX */
517 	if (ss.ss_family != AF_LOCAL) {
518 		if (type == SOCK_STREAM)
519 			proto = IPPROTO_TCP;
520 		else if (type == SOCK_DGRAM)
521 			proto = IPPROTO_UDP;
522 		else
523 			return 0;
524 	} else
525 		proto = 0;
526 
527 	sip->si_af = ss.ss_family;
528 	sip->si_proto = proto;
529 	sip->si_socktype = type;
530 
531 	return 1;
532 }
533 
534 /*
535  * Linear search, but the number of entries is small.
536  */
537 int
538 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
539 {
540 	size_t i;
541 
542 	_DIAGASSERT(nconf != NULL);
543 	_DIAGASSERT(sip != NULL);
544 
545 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
546 		if (!strcmp(na_cvt[i].netid, nconf->nc_netid)) {
547 			sip->si_af = na_cvt[i].af;
548 			sip->si_proto = na_cvt[i].protocol;
549 			sip->si_socktype =
550 			    __rpc_seman2socktype((int)nconf->nc_semantics);
551 			if (sip->si_socktype == -1)
552 				return 0;
553 			sip->si_alen = __rpc_get_a_size(sip->si_af);
554 			return 1;
555 		}
556 
557 	return 0;
558 }
559 
560 int
561 __rpc_nconf2fd(const struct netconfig *nconf)
562 {
563 	struct __rpc_sockinfo si;
564 
565 	_DIAGASSERT(nconf != NULL);
566 
567 	if (!__rpc_nconf2sockinfo(nconf, &si))
568 		return 0;
569 
570 	return socket(si.si_af, si.si_socktype, si.si_proto);
571 }
572 
573 int
574 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
575 {
576 	size_t i;
577 
578 	_DIAGASSERT(sip != NULL);
579 	/* netid may be NULL */
580 
581 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
582 		if (na_cvt[i].af == sip->si_af &&
583 		    na_cvt[i].protocol == sip->si_proto) {
584 			if (netid)
585 				*netid = na_cvt[i].netid;
586 			return 1;
587 		}
588 
589 	return 0;
590 }
591 
592 char *
593 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
594 {
595 	struct __rpc_sockinfo si;
596 
597 	_DIAGASSERT(nconf != NULL);
598 	_DIAGASSERT(nbuf != NULL);
599 
600 	if (!__rpc_nconf2sockinfo(nconf, &si))
601 		return NULL;
602 	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
603 }
604 
605 struct netbuf *
606 uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
607 {
608 	struct __rpc_sockinfo si;
609 
610 	_DIAGASSERT(nconf != NULL);
611 	_DIAGASSERT(uaddr != NULL);
612 
613 	if (!__rpc_nconf2sockinfo(nconf, &si))
614 		return NULL;
615 	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
616 }
617 
618 char *
619 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
620 {
621 	char *ret;
622 	struct sockaddr_in *sinp;
623 	struct sockaddr_un *sun;
624 	char namebuf[INET_ADDRSTRLEN];
625 #ifdef INET6
626 	struct sockaddr_in6 *sin6;
627 	char namebuf6[INET6_ADDRSTRLEN];
628 #endif
629 	u_int16_t port;
630 
631 	_DIAGASSERT(nbuf != NULL);
632 
633 	switch (af) {
634 	case AF_INET:
635 		sinp = nbuf->buf;
636 		if (inet_ntop(af, &sinp->sin_addr, namebuf, sizeof namebuf)
637 		    == NULL)
638 			return NULL;
639 		port = ntohs(sinp->sin_port);
640 		if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
641 		    port & 0xff) < 0)
642 			return NULL;
643 		break;
644 #ifdef INET6
645 	case AF_INET6:
646 		sin6 = nbuf->buf;
647 		if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
648 		    == NULL)
649 			return NULL;
650 		port = ntohs(sin6->sin6_port);
651 		if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
652 		    port & 0xff) < 0)
653 			return NULL;
654 		break;
655 #endif
656 	case AF_LOCAL:
657 		sun = nbuf->buf;
658 		sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */
659 		ret = strdup(sun->sun_path);
660 		break;
661 	default:
662 		return NULL;
663 	}
664 
665 	return ret;
666 }
667 
668 struct netbuf *
669 __rpc_uaddr2taddr_af(int af, const char *uaddr)
670 {
671 	struct netbuf *ret = NULL;
672 	char *addrstr, *p;
673 	unsigned port, portlo, porthi;
674 	struct sockaddr_in *sinp;
675 #ifdef INET6
676 	struct sockaddr_in6 *sin6;
677 #endif
678 	struct sockaddr_un *sun;
679 
680 	_DIAGASSERT(uaddr != NULL);
681 
682 	addrstr = strdup(uaddr);
683 	if (addrstr == NULL)
684 		return NULL;
685 
686 	/*
687 	 * AF_LOCAL addresses are expected to be absolute
688 	 * pathnames, anything else will be AF_INET or AF_INET6.
689 	 */
690 	if (*addrstr != '/') {
691 		p = strrchr(addrstr, '.');
692 		if (p == NULL)
693 			goto out;
694 		portlo = (unsigned)atoi(p + 1);
695 		*p = '\0';
696 
697 		p = strrchr(addrstr, '.');
698 		if (p == NULL)
699 			goto out;
700 		porthi = (unsigned)atoi(p + 1);
701 		*p = '\0';
702 		port = (porthi << 8) | portlo;
703 	}
704 
705 	ret = (struct netbuf *)malloc(sizeof *ret);
706 	if (ret == NULL)
707 		goto out;
708 
709 	switch (af) {
710 	case AF_INET:
711 		sinp = (struct sockaddr_in *)malloc(sizeof *sinp);
712 		if (sinp == NULL)
713 			goto out;
714 		memset(sinp, 0, sizeof *sinp);
715 		sinp->sin_family = AF_INET;
716 		sinp->sin_port = htons(port);
717 		if (inet_pton(AF_INET, addrstr, &sinp->sin_addr) <= 0) {
718 			free(sinp);
719 			free(ret);
720 			ret = NULL;
721 			goto out;
722 		}
723 		sinp->sin_len = ret->maxlen = ret->len = sizeof *sinp;
724 		ret->buf = sinp;
725 		break;
726 #ifdef INET6
727 	case AF_INET6:
728 		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
729 		if (sin6 == NULL)
730 			goto out;
731 		memset(sin6, 0, sizeof *sin6);
732 		sin6->sin6_family = AF_INET6;
733 		sin6->sin6_port = htons(port);
734 		if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
735 			free(sin6);
736 			free(ret);
737 			ret = NULL;
738 			goto out;
739 		}
740 		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
741 		ret->buf = sin6;
742 		break;
743 #endif
744 	case AF_LOCAL:
745 		sun = (struct sockaddr_un *)malloc(sizeof *sun);
746 		if (sun == NULL)
747 			goto out;
748 		memset(sun, 0, sizeof *sun);
749 		sun->sun_family = AF_LOCAL;
750 		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
751 		ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
752 		ret->buf = sun;
753 		break;
754 	default:
755 		break;
756 	}
757 out:
758 	free(addrstr);
759 	return ret;
760 }
761 
762 int
763 __rpc_seman2socktype(int semantics)
764 {
765 	switch (semantics) {
766 	case NC_TPI_CLTS:
767 		return SOCK_DGRAM;
768 	case NC_TPI_COTS_ORD:
769 		return SOCK_STREAM;
770 	case NC_TPI_RAW:
771 		return SOCK_RAW;
772 	default:
773 		break;
774 	}
775 
776 	return -1;
777 }
778 
779 int
780 __rpc_socktype2seman(int socktype)
781 {
782 	switch (socktype) {
783 	case SOCK_DGRAM:
784 		return NC_TPI_CLTS;
785 	case SOCK_STREAM:
786 		return NC_TPI_COTS_ORD;
787 	case SOCK_RAW:
788 		return NC_TPI_RAW;
789 	default:
790 		break;
791 	}
792 
793 	return -1;
794 }
795 
796 /*
797  * XXXX - IPv6 scope IDs can't be handled in universal addresses.
798  * Here, we compare the original server address to that of the RPC
799  * service we just received back from a call to rpcbind on the remote
800  * machine. If they are both "link local" or "site local", copy
801  * the scope id of the server address over to the service address.
802  */
803 int
804 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
805 {
806 #ifdef INET6
807 	struct sockaddr *sa_new, *sa_svc;
808 	struct sockaddr_in6 *sin6_new, *sin6_svc;
809 
810 	_DIAGASSERT(new != NULL);
811 	_DIAGASSERT(svc != NULL);
812 
813 	sa_svc = (struct sockaddr *)svc->buf;
814 	sa_new = (struct sockaddr *)new->buf;
815 
816 	if (sa_new->sa_family == sa_svc->sa_family &&
817 	    sa_new->sa_family == AF_INET6) {
818 		sin6_new = (struct sockaddr_in6 *)new->buf;
819 		sin6_svc = (struct sockaddr_in6 *)svc->buf;
820 
821 		if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
822 		     IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
823 		    (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
824 		     IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
825 			sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
826 		}
827 	}
828 #endif
829 	return 1;
830 }
831 
832 int
833 __rpc_sockisbound(int fd)
834 {
835 	struct sockaddr_storage ss;
836 	socklen_t slen;
837 
838 	slen = sizeof (struct sockaddr_storage);
839 	if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
840 		return 0;
841 
842 	switch (ss.ss_family) {
843 		case AF_INET:
844 			return (((struct sockaddr_in *)
845 			    (void *)&ss)->sin_port != 0);
846 #ifdef INET6
847 		case AF_INET6:
848 			return (((struct sockaddr_in6 *)
849 			    (void *)&ss)->sin6_port != 0);
850 #endif
851 		case AF_LOCAL:
852 			/* XXX check this */
853 			return (((struct sockaddr_un *)
854 			    (void *)&ss)->sun_path[0] != '\0');
855 		default:
856 			break;
857 	}
858 
859 	return 0;
860 }
861