Home | History | Annotate | Line # | Download | only in rpc
rpc_generic.c revision 1.7
      1 /*	$NetBSD: rpc_generic.c,v 1.7 2001/04/22 20:51:25 fvdl 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_com.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 	int 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 	int 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 *sin;
    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 		sin = nbuf->buf;
    636 		if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
    637 		    == NULL)
    638 			return NULL;
    639 		port = ntohs(sin->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 *sin;
    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 
    707 	switch (af) {
    708 	case AF_INET:
    709 		sin = (struct sockaddr_in *)malloc(sizeof *sin);
    710 		if (sin == NULL)
    711 			goto out;
    712 		memset(sin, 0, sizeof *sin);
    713 		sin->sin_family = AF_INET;
    714 		sin->sin_port = htons(port);
    715 		if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
    716 			free(sin);
    717 			free(ret);
    718 			ret = NULL;
    719 			goto out;
    720 		}
    721 		sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
    722 		ret->buf = sin;
    723 		break;
    724 #ifdef INET6
    725 	case AF_INET6:
    726 		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
    727 		if (sin6 == NULL)
    728 			goto out;
    729 		memset(sin6, 0, sizeof *sin6);
    730 		sin6->sin6_family = AF_INET6;
    731 		sin6->sin6_port = htons(port);
    732 		if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
    733 			free(sin);
    734 			free(ret);
    735 			ret = NULL;
    736 			goto out;
    737 		}
    738 		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
    739 		ret->buf = sin6;
    740 		break;
    741 #endif
    742 	case AF_LOCAL:
    743 		sun = (struct sockaddr_un *)malloc(sizeof *sun);
    744 		if (sun == NULL)
    745 			goto out;
    746 		memset(sun, 0, sizeof *sun);
    747 		sun->sun_family = AF_LOCAL;
    748 		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
    749 		ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
    750 		ret->buf = sun;
    751 		break;
    752 	default:
    753 		break;
    754 	}
    755 out:
    756 	free(addrstr);
    757 	return ret;
    758 }
    759 
    760 int
    761 __rpc_seman2socktype(int semantics)
    762 {
    763 	switch (semantics) {
    764 	case NC_TPI_CLTS:
    765 		return SOCK_DGRAM;
    766 	case NC_TPI_COTS_ORD:
    767 		return SOCK_STREAM;
    768 	case NC_TPI_RAW:
    769 		return SOCK_RAW;
    770 	default:
    771 		break;
    772 	}
    773 
    774 	return -1;
    775 }
    776 
    777 int
    778 __rpc_socktype2seman(int socktype)
    779 {
    780 	switch (socktype) {
    781 	case SOCK_DGRAM:
    782 		return NC_TPI_CLTS;
    783 	case SOCK_STREAM:
    784 		return NC_TPI_COTS_ORD;
    785 	case SOCK_RAW:
    786 		return NC_TPI_RAW;
    787 	default:
    788 		break;
    789 	}
    790 
    791 	return -1;
    792 }
    793 
    794 /*
    795  * XXXX - IPv6 scope IDs can't be handled in universal addresses.
    796  * Here, we compare the original server address to that of the RPC
    797  * service we just received back from a call to rpcbind on the remote
    798  * machine. If they are both "link local" or "site local", copy
    799  * the scope id of the server address over to the service address.
    800  */
    801 int
    802 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
    803 {
    804 #ifdef INET6
    805 	struct sockaddr *sa_new, *sa_svc;
    806 	struct sockaddr_in6 *sin6_new, *sin6_svc;
    807 
    808 	_DIAGASSERT(new != NULL);
    809 	_DIAGASSERT(svc != NULL);
    810 
    811 	sa_svc = (struct sockaddr *)svc->buf;
    812 	sa_new = (struct sockaddr *)new->buf;
    813 
    814 	if (sa_new->sa_family == sa_svc->sa_family &&
    815 	    sa_new->sa_family == AF_INET6) {
    816 		sin6_new = (struct sockaddr_in6 *)new->buf;
    817 		sin6_svc = (struct sockaddr_in6 *)svc->buf;
    818 
    819 		if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
    820 		     IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
    821 		    (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
    822 		     IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
    823 			sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
    824 		}
    825 	}
    826 #endif
    827 	return 1;
    828 }
    829 
    830 int
    831 __rpc_sockisbound(int fd)
    832 {
    833 	struct sockaddr_storage ss;
    834 	socklen_t slen;
    835 
    836 	slen = sizeof (struct sockaddr_storage);
    837 	if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
    838 		return 0;
    839 
    840 	switch (ss.ss_family) {
    841 		case AF_INET:
    842 			return (((struct sockaddr_in *)
    843 			    (void *)&ss)->sin_port != 0);
    844 #ifdef INET6
    845 		case AF_INET6:
    846 			return (((struct sockaddr_in6 *)
    847 			    (void *)&ss)->sin6_port != 0);
    848 #endif
    849 		case AF_LOCAL:
    850 			/* XXX check this */
    851 			return (((struct sockaddr_un *)
    852 			    (void *)&ss)->sun_path[0] != '\0');
    853 		default:
    854 			break;
    855 	}
    856 
    857 	return 0;
    858 }
    859