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