Home | History | Annotate | Line # | Download | only in rpc
rpc_generic.c revision 1.14
      1 /*	$NetBSD: rpc_generic.c,v 1.14 2003/09/09 00:22:17 itojun 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, defsize;
    139 
    140 	maxsize = 256 * 1024;	/* XXX */
    141 	switch (proto) {
    142 	case IPPROTO_TCP:
    143 		defsize = 64 * 1024;	/* XXX */
    144 		break;
    145 	case IPPROTO_UDP:
    146 		defsize = UDPMSGSIZE;
    147 		break;
    148 	default:
    149 		defsize = RPC_MAXDATASIZE;
    150 		break;
    151 	}
    152 	if (size == 0)
    153 		return defsize;
    154 
    155 	/* Check whether the value is within the upper max limit */
    156 	return (size > maxsize ? (u_int)maxsize : (u_int)size);
    157 }
    158 
    159 /*
    160  * Find the appropriate address buffer size
    161  */
    162 u_int
    163 __rpc_get_a_size(af)
    164 	int af;
    165 {
    166 	switch (af) {
    167 	case AF_INET:
    168 		return sizeof (struct sockaddr_in);
    169 #ifdef INET6
    170 	case AF_INET6:
    171 		return sizeof (struct sockaddr_in6);
    172 #endif
    173 	case AF_LOCAL:
    174 		return sizeof (struct sockaddr_un);
    175 	default:
    176 		break;
    177 	}
    178 	return ((u_int)RPC_MAXADDRSIZE);
    179 }
    180 
    181 #if 0
    182 static char *
    183 strlocase(p)
    184 	char *p;
    185 {
    186 	char *t = p;
    187 
    188 	_DIAGASSERT(p != NULL);
    189 
    190 	for (; *p; p++)
    191 		if (isupper(*p))
    192 			*p = tolower(*p);
    193 	return (t);
    194 }
    195 #endif
    196 
    197 /*
    198  * Returns the type of the network as defined in <rpc/nettype.h>
    199  * If nettype is NULL, it defaults to NETPATH.
    200  */
    201 static int
    202 getnettype(nettype)
    203 	const char *nettype;
    204 {
    205 	int i;
    206 
    207 	if ((nettype == NULL) || (nettype[0] == NULL)) {
    208 		return (_RPC_NETPATH);	/* Default */
    209 	}
    210 
    211 #if 0
    212 	nettype = strlocase(nettype);
    213 #endif
    214 	for (i = 0; _rpctypelist[i].name; i++)
    215 		if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
    216 			return (_rpctypelist[i].type);
    217 		}
    218 	return (_rpctypelist[i].type);
    219 }
    220 
    221 /*
    222  * For the given nettype (tcp or udp only), return the first structure found.
    223  * This should be freed by calling freenetconfigent()
    224  */
    225 
    226 #ifdef _REENTRANT
    227 static thread_key_t tcp_key, udp_key;
    228 static once_t __rpc_getconfigp_once = ONCE_INITIALIZER;
    229 
    230 static void
    231 __rpc_getconfigp_setup(void)
    232 {
    233 
    234 	thr_keycreate(&tcp_key, free);
    235 	thr_keycreate(&udp_key, free);
    236 }
    237 #endif
    238 
    239 struct netconfig *
    240 __rpc_getconfip(nettype)
    241 	const char *nettype;
    242 {
    243 	char *netid;
    244 	char *netid_tcp = (char *) NULL;
    245 	char *netid_udp = (char *) NULL;
    246 	static char *netid_tcp_main;
    247 	static char *netid_udp_main;
    248 	struct netconfig *dummy;
    249 #ifdef _REENTRANT
    250 	extern int __isthreaded;
    251 
    252 	if (__isthreaded == 0) {
    253 		netid_udp = netid_udp_main;
    254 		netid_tcp = netid_tcp_main;
    255 	} else {
    256 		thr_once(&__rpc_getconfigp_once, __rpc_getconfigp_setup);
    257 		netid_tcp = thr_getspecific(tcp_key);
    258 		netid_udp = thr_getspecific(udp_key);
    259 	}
    260 #else
    261 	netid_udp = netid_udp_main;
    262 	netid_tcp = netid_tcp_main;
    263 #endif
    264 
    265 	_DIAGASSERT(nettype != NULL);
    266 
    267 	if (!netid_udp && !netid_tcp) {
    268 		struct netconfig *nconf;
    269 		void *confighandle;
    270 
    271 		if (!(confighandle = setnetconfig())) {
    272 			syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
    273 			return (NULL);
    274 		}
    275 		while ((nconf = getnetconfig(confighandle)) != NULL) {
    276 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
    277 				if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
    278 					netid_tcp = strdup(nconf->nc_netid);
    279 #ifdef _REENTRANT
    280 					if (__isthreaded == 0)
    281 						netid_tcp_main = netid_tcp;
    282 					else
    283 						thr_setspecific(tcp_key,
    284 							(void *) netid_tcp);
    285 #else
    286 					netid_tcp_main = netid_tcp;
    287 #endif
    288 				} else
    289 				if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
    290 					netid_udp = strdup(nconf->nc_netid);
    291 #ifdef _REENTRANT
    292 					if (__isthreaded == 0)
    293 						netid_udp_main = netid_udp;
    294 					else
    295 						thr_setspecific(udp_key,
    296 							(void *) netid_udp);
    297 #else
    298 					netid_udp_main = netid_udp;
    299 #endif
    300 				}
    301 			}
    302 		}
    303 		endnetconfig(confighandle);
    304 	}
    305 	if (strcmp(nettype, "udp") == 0)
    306 		netid = netid_udp;
    307 	else if (strcmp(nettype, "tcp") == 0)
    308 		netid = netid_tcp;
    309 	else {
    310 		return (NULL);
    311 	}
    312 	if ((netid == NULL) || (netid[0] == NULL)) {
    313 		return (NULL);
    314 	}
    315 	dummy = getnetconfigent(netid);
    316 	return (dummy);
    317 }
    318 
    319 /*
    320  * Returns the type of the nettype, which should then be used with
    321  * __rpc_getconf().
    322  */
    323 void *
    324 __rpc_setconf(nettype)
    325 	const char *nettype;
    326 {
    327 	struct handle *handle;
    328 
    329 	/* nettype may be NULL; getnettype() supports that */
    330 
    331 	handle = (struct handle *) malloc(sizeof (struct handle));
    332 	if (handle == NULL) {
    333 		return (NULL);
    334 	}
    335 	switch (handle->nettype = getnettype(nettype)) {
    336 	case _RPC_NETPATH:
    337 	case _RPC_CIRCUIT_N:
    338 	case _RPC_DATAGRAM_N:
    339 		if (!(handle->nhandle = setnetpath())) {
    340 			free(handle);
    341 			return (NULL);
    342 		}
    343 		handle->nflag = TRUE;
    344 		break;
    345 	case _RPC_VISIBLE:
    346 	case _RPC_CIRCUIT_V:
    347 	case _RPC_DATAGRAM_V:
    348 	case _RPC_TCP:
    349 	case _RPC_UDP:
    350 		if (!(handle->nhandle = setnetconfig())) {
    351 		        syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
    352 			free(handle);
    353 			return (NULL);
    354 		}
    355 		handle->nflag = FALSE;
    356 		break;
    357 	default:
    358 		return (NULL);
    359 	}
    360 
    361 	return (handle);
    362 }
    363 
    364 /*
    365  * Returns the next netconfig struct for the given "net" type.
    366  * __rpc_setconf() should have been called previously.
    367  */
    368 struct netconfig *
    369 __rpc_getconf(vhandle)
    370 	void *vhandle;
    371 {
    372 	struct handle *handle;
    373 	struct netconfig *nconf;
    374 
    375 	handle = (struct handle *)vhandle;
    376 	if (handle == NULL) {
    377 		return (NULL);
    378 	}
    379 	for (;;) {
    380 		if (handle->nflag)
    381 			nconf = getnetpath(handle->nhandle);
    382 		else
    383 			nconf = getnetconfig(handle->nhandle);
    384 		if (nconf == NULL)
    385 			break;
    386 		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
    387 			(nconf->nc_semantics != NC_TPI_COTS) &&
    388 			(nconf->nc_semantics != NC_TPI_COTS_ORD))
    389 			continue;
    390 		switch (handle->nettype) {
    391 		case _RPC_VISIBLE:
    392 			if (!(nconf->nc_flag & NC_VISIBLE))
    393 				continue;
    394 			/* FALLTHROUGH */
    395 		case _RPC_NETPATH:	/* Be happy */
    396 			break;
    397 		case _RPC_CIRCUIT_V:
    398 			if (!(nconf->nc_flag & NC_VISIBLE))
    399 				continue;
    400 			/* FALLTHROUGH */
    401 		case _RPC_CIRCUIT_N:
    402 			if ((nconf->nc_semantics != NC_TPI_COTS) &&
    403 				(nconf->nc_semantics != NC_TPI_COTS_ORD))
    404 				continue;
    405 			break;
    406 		case _RPC_DATAGRAM_V:
    407 			if (!(nconf->nc_flag & NC_VISIBLE))
    408 				continue;
    409 			/* FALLTHROUGH */
    410 		case _RPC_DATAGRAM_N:
    411 			if (nconf->nc_semantics != NC_TPI_CLTS)
    412 				continue;
    413 			break;
    414 		case _RPC_TCP:
    415 			if (((nconf->nc_semantics != NC_TPI_COTS) &&
    416 				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
    417 				(strcmp(nconf->nc_protofmly, NC_INET)
    418 #ifdef INET6
    419 				 && strcmp(nconf->nc_protofmly, NC_INET6))
    420 #else
    421 				)
    422 #endif
    423 				||
    424 				strcmp(nconf->nc_proto, NC_TCP))
    425 				continue;
    426 			break;
    427 		case _RPC_UDP:
    428 			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
    429 				(strcmp(nconf->nc_protofmly, NC_INET)
    430 #ifdef INET6
    431 				&& strcmp(nconf->nc_protofmly, NC_INET6))
    432 #else
    433 				)
    434 #endif
    435 				||
    436 				strcmp(nconf->nc_proto, NC_UDP))
    437 				continue;
    438 			break;
    439 		}
    440 		break;
    441 	}
    442 	return (nconf);
    443 }
    444 
    445 void
    446 __rpc_endconf(vhandle)
    447 	void * vhandle;
    448 {
    449 	struct handle *handle;
    450 
    451 	handle = (struct handle *) vhandle;
    452 	if (handle == NULL) {
    453 		return;
    454 	}
    455 	if (handle->nflag) {
    456 		endnetpath(handle->nhandle);
    457 	} else {
    458 		endnetconfig(handle->nhandle);
    459 	}
    460 	free(handle);
    461 }
    462 
    463 /*
    464  * Used to ping the NULL procedure for clnt handle.
    465  * Returns NULL if fails, else a non-NULL pointer.
    466  */
    467 void *
    468 rpc_nullproc(clnt)
    469 	CLIENT *clnt;
    470 {
    471 	struct timeval TIMEOUT = {25, 0};
    472 
    473 	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
    474 		(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
    475 		return (NULL);
    476 	}
    477 	return ((void *) clnt);
    478 }
    479 
    480 /*
    481  * Try all possible transports until
    482  * one succeeds in finding the netconf for the given fd.
    483  */
    484 struct netconfig *
    485 __rpcgettp(fd)
    486 	int fd;
    487 {
    488 	const char *netid;
    489 	struct __rpc_sockinfo si;
    490 
    491 	if (!__rpc_fd2sockinfo(fd, &si))
    492 		return NULL;
    493 
    494 	if (!__rpc_sockinfo2netid(&si, &netid))
    495 		return NULL;
    496 
    497 	/*LINTED const castaway*/
    498 	return getnetconfigent((char *)netid);
    499 }
    500 
    501 int
    502 __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip)
    503 {
    504 	socklen_t len;
    505 	int type, proto;
    506 	struct sockaddr_storage ss;
    507 
    508 	_DIAGASSERT(sip != NULL);
    509 
    510 	len = sizeof ss;
    511 	if (getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0)
    512 		return 0;
    513 	sip->si_alen = len;
    514 
    515 	len = sizeof type;
    516 	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
    517 		return 0;
    518 
    519 	/* XXX */
    520 	if (ss.ss_family != AF_LOCAL) {
    521 		if (type == SOCK_STREAM)
    522 			proto = IPPROTO_TCP;
    523 		else if (type == SOCK_DGRAM)
    524 			proto = IPPROTO_UDP;
    525 		else
    526 			return 0;
    527 	} else
    528 		proto = 0;
    529 
    530 	sip->si_af = ss.ss_family;
    531 	sip->si_proto = proto;
    532 	sip->si_socktype = type;
    533 
    534 	return 1;
    535 }
    536 
    537 /*
    538  * Linear search, but the number of entries is small.
    539  */
    540 int
    541 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
    542 {
    543 	size_t i;
    544 
    545 	_DIAGASSERT(nconf != NULL);
    546 	_DIAGASSERT(sip != NULL);
    547 
    548 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
    549 		if (!strcmp(na_cvt[i].netid, nconf->nc_netid)) {
    550 			sip->si_af = na_cvt[i].af;
    551 			sip->si_proto = na_cvt[i].protocol;
    552 			sip->si_socktype =
    553 			    __rpc_seman2socktype((int)nconf->nc_semantics);
    554 			if (sip->si_socktype == -1)
    555 				return 0;
    556 			sip->si_alen = __rpc_get_a_size(sip->si_af);
    557 			return 1;
    558 		}
    559 
    560 	return 0;
    561 }
    562 
    563 int
    564 __rpc_nconf2fd(const struct netconfig *nconf)
    565 {
    566 	struct __rpc_sockinfo si;
    567 
    568 	_DIAGASSERT(nconf != NULL);
    569 
    570 	if (!__rpc_nconf2sockinfo(nconf, &si))
    571 		return 0;
    572 
    573 	return socket(si.si_af, si.si_socktype, si.si_proto);
    574 }
    575 
    576 int
    577 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
    578 {
    579 	size_t i;
    580 
    581 	_DIAGASSERT(sip != NULL);
    582 	/* netid may be NULL */
    583 
    584 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
    585 		if (na_cvt[i].af == sip->si_af &&
    586 		    na_cvt[i].protocol == sip->si_proto) {
    587 			if (netid)
    588 				*netid = na_cvt[i].netid;
    589 			return 1;
    590 		}
    591 
    592 	return 0;
    593 }
    594 
    595 char *
    596 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
    597 {
    598 	struct __rpc_sockinfo si;
    599 
    600 	_DIAGASSERT(nconf != NULL);
    601 	_DIAGASSERT(nbuf != NULL);
    602 
    603 	if (!__rpc_nconf2sockinfo(nconf, &si))
    604 		return NULL;
    605 	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
    606 }
    607 
    608 struct netbuf *
    609 uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
    610 {
    611 	struct __rpc_sockinfo si;
    612 
    613 	_DIAGASSERT(nconf != NULL);
    614 	_DIAGASSERT(uaddr != NULL);
    615 
    616 	if (!__rpc_nconf2sockinfo(nconf, &si))
    617 		return NULL;
    618 	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
    619 }
    620 
    621 char *
    622 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
    623 {
    624 	char *ret;
    625 	struct sockaddr_in *sinp;
    626 	struct sockaddr_un *sun;
    627 	char namebuf[INET_ADDRSTRLEN];
    628 #ifdef INET6
    629 	struct sockaddr_in6 *sin6;
    630 	char namebuf6[INET6_ADDRSTRLEN];
    631 #endif
    632 	u_int16_t port;
    633 
    634 	_DIAGASSERT(nbuf != NULL);
    635 
    636 	switch (af) {
    637 	case AF_INET:
    638 		sinp = nbuf->buf;
    639 		if (inet_ntop(af, &sinp->sin_addr, namebuf, sizeof namebuf)
    640 		    == NULL)
    641 			return NULL;
    642 		port = ntohs(sinp->sin_port);
    643 		if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
    644 		    port & 0xff) < 0)
    645 			return NULL;
    646 		break;
    647 #ifdef INET6
    648 	case AF_INET6:
    649 		sin6 = nbuf->buf;
    650 		if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
    651 		    == NULL)
    652 			return NULL;
    653 		port = ntohs(sin6->sin6_port);
    654 		if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
    655 		    port & 0xff) < 0)
    656 			return NULL;
    657 		break;
    658 #endif
    659 	case AF_LOCAL:
    660 		sun = nbuf->buf;
    661 		sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */
    662 		ret = strdup(sun->sun_path);
    663 		break;
    664 	default:
    665 		return NULL;
    666 	}
    667 
    668 	return ret;
    669 }
    670 
    671 struct netbuf *
    672 __rpc_uaddr2taddr_af(int af, const char *uaddr)
    673 {
    674 	struct netbuf *ret = NULL;
    675 	char *addrstr, *p;
    676 	unsigned port, portlo, porthi;
    677 	struct sockaddr_in *sinp;
    678 #ifdef INET6
    679 	struct sockaddr_in6 *sin6;
    680 #endif
    681 	struct sockaddr_un *sun;
    682 
    683 	_DIAGASSERT(uaddr != NULL);
    684 
    685 	addrstr = strdup(uaddr);
    686 	if (addrstr == NULL)
    687 		return NULL;
    688 
    689 	/*
    690 	 * AF_LOCAL addresses are expected to be absolute
    691 	 * pathnames, anything else will be AF_INET or AF_INET6.
    692 	 */
    693 	if (*addrstr != '/') {
    694 		p = strrchr(addrstr, '.');
    695 		if (p == NULL)
    696 			goto out;
    697 		portlo = (unsigned)atoi(p + 1);
    698 		*p = '\0';
    699 
    700 		p = strrchr(addrstr, '.');
    701 		if (p == NULL)
    702 			goto out;
    703 		porthi = (unsigned)atoi(p + 1);
    704 		*p = '\0';
    705 		port = (porthi << 8) | portlo;
    706 	}
    707 
    708 	ret = (struct netbuf *)malloc(sizeof *ret);
    709 	if (ret == NULL)
    710 		goto out;
    711 
    712 	switch (af) {
    713 	case AF_INET:
    714 		sinp = (struct sockaddr_in *)malloc(sizeof *sinp);
    715 		if (sinp == NULL)
    716 			goto out;
    717 		memset(sinp, 0, sizeof *sinp);
    718 		sinp->sin_family = AF_INET;
    719 		sinp->sin_port = htons(port);
    720 		if (inet_pton(AF_INET, addrstr, &sinp->sin_addr) <= 0) {
    721 			free(sinp);
    722 			free(ret);
    723 			ret = NULL;
    724 			goto out;
    725 		}
    726 		sinp->sin_len = ret->maxlen = ret->len = sizeof *sinp;
    727 		ret->buf = sinp;
    728 		break;
    729 #ifdef INET6
    730 	case AF_INET6:
    731 		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
    732 		if (sin6 == NULL)
    733 			goto out;
    734 		memset(sin6, 0, sizeof *sin6);
    735 		sin6->sin6_family = AF_INET6;
    736 		sin6->sin6_port = htons(port);
    737 		if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
    738 			free(sin6);
    739 			free(ret);
    740 			ret = NULL;
    741 			goto out;
    742 		}
    743 		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
    744 		ret->buf = sin6;
    745 		break;
    746 #endif
    747 	case AF_LOCAL:
    748 		sun = (struct sockaddr_un *)malloc(sizeof *sun);
    749 		if (sun == NULL)
    750 			goto out;
    751 		memset(sun, 0, sizeof *sun);
    752 		sun->sun_family = AF_LOCAL;
    753 		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
    754 		ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
    755 		ret->buf = sun;
    756 		break;
    757 	default:
    758 		break;
    759 	}
    760 out:
    761 	free(addrstr);
    762 	return ret;
    763 }
    764 
    765 int
    766 __rpc_seman2socktype(int semantics)
    767 {
    768 	switch (semantics) {
    769 	case NC_TPI_CLTS:
    770 		return SOCK_DGRAM;
    771 	case NC_TPI_COTS_ORD:
    772 		return SOCK_STREAM;
    773 	case NC_TPI_RAW:
    774 		return SOCK_RAW;
    775 	default:
    776 		break;
    777 	}
    778 
    779 	return -1;
    780 }
    781 
    782 int
    783 __rpc_socktype2seman(int socktype)
    784 {
    785 	switch (socktype) {
    786 	case SOCK_DGRAM:
    787 		return NC_TPI_CLTS;
    788 	case SOCK_STREAM:
    789 		return NC_TPI_COTS_ORD;
    790 	case SOCK_RAW:
    791 		return NC_TPI_RAW;
    792 	default:
    793 		break;
    794 	}
    795 
    796 	return -1;
    797 }
    798 
    799 /*
    800  * XXXX - IPv6 scope IDs can't be handled in universal addresses.
    801  * Here, we compare the original server address to that of the RPC
    802  * service we just received back from a call to rpcbind on the remote
    803  * machine. If they are both "link local" or "site local", copy
    804  * the scope id of the server address over to the service address.
    805  */
    806 int
    807 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
    808 {
    809 #ifdef INET6
    810 	struct sockaddr *sa_new, *sa_svc;
    811 	struct sockaddr_in6 *sin6_new, *sin6_svc;
    812 
    813 	_DIAGASSERT(new != NULL);
    814 	_DIAGASSERT(svc != NULL);
    815 
    816 	sa_svc = (struct sockaddr *)svc->buf;
    817 	sa_new = (struct sockaddr *)new->buf;
    818 
    819 	if (sa_new->sa_family == sa_svc->sa_family &&
    820 	    sa_new->sa_family == AF_INET6) {
    821 		sin6_new = (struct sockaddr_in6 *)new->buf;
    822 		sin6_svc = (struct sockaddr_in6 *)svc->buf;
    823 
    824 		if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
    825 		     IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
    826 		    (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
    827 		     IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
    828 			sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
    829 		}
    830 	}
    831 #endif
    832 	return 1;
    833 }
    834 
    835 int
    836 __rpc_sockisbound(int fd)
    837 {
    838 	struct sockaddr_storage ss;
    839 	socklen_t slen;
    840 
    841 	slen = sizeof (struct sockaddr_storage);
    842 	if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
    843 		return 0;
    844 
    845 	switch (ss.ss_family) {
    846 		case AF_INET:
    847 			return (((struct sockaddr_in *)
    848 			    (void *)&ss)->sin_port != 0);
    849 #ifdef INET6
    850 		case AF_INET6:
    851 			return (((struct sockaddr_in6 *)
    852 			    (void *)&ss)->sin6_port != 0);
    853 #endif
    854 		case AF_LOCAL:
    855 			/* XXX check this */
    856 			return (((struct sockaddr_un *)
    857 			    (void *)&ss)->sun_path[0] != '\0');
    858 		default:
    859 			break;
    860 	}
    861 
    862 	return 0;
    863 }
    864 
    865 /*	$OpenBSD: ip_id.c,v 1.6 2002/03/15 18:19:52 millert Exp $	*/
    866 
    867 /*
    868  * Copyright 1998 Niels Provos <provos (at) citi.umich.edu>
    869  * All rights reserved.
    870  *
    871  * Theo de Raadt <deraadt (at) openbsd.org> came up with the idea of using
    872  * such a mathematical system to generate more random (yet non-repeating)
    873  * ids to solve the resolver/named problem.  But Niels designed the
    874  * actual system based on the constraints.
    875  *
    876  * Redistribution and use in source and binary forms, with or without
    877  * modification, are permitted provided that the following conditions
    878  * are met:
    879  * 1. Redistributions of source code must retain the above copyright
    880  *    notice, this list of conditions and the following disclaimer.
    881  * 2. Redistributions in binary form must reproduce the above copyright
    882  *    notice, this list of conditions and the following disclaimer in the
    883  *    documentation and/or other materials provided with the distribution.
    884  * 3. All advertising materials mentioning features or use of this software
    885  *    must display the following acknowledgement:
    886  *      This product includes software developed by Niels Provos.
    887  * 4. The name of the author may not be used to endorse or promote products
    888  *    derived from this software without specific prior written permission.
    889  *
    890  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    891  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    892  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    893  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    894  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    895  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    896  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    897  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    898  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    899  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    900  */
    901 
    902 /*
    903  * seed = random 31bit
    904  * n = prime, g0 = generator to n,
    905  * j = random so that gcd(j,n-1) == 1
    906  * g = g0^j mod n will be a generator again.
    907  *
    908  * X[0] = random seed.
    909  * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
    910  * with a = 7^(even random) mod m,
    911  *      b = random with gcd(b,m) == 1
    912  *      m = 1836660096 and a maximal period of m-1.
    913  *
    914  * The transaction id is determined by:
    915  * id[n] = seed xor (g^X[n] mod n)
    916  *
    917  * Effectivly the id is restricted to the lower 31 bits, thus
    918  * yielding two different cycles by toggling the msb on and off.
    919  * This avoids reuse issues caused by reseeding.
    920  */
    921 
    922 #define RU_OUT  180		/* Time after wich will be reseeded */
    923 #define RU_MAX	1000000000	/* Uniq cycle, avoid blackjack prediction */
    924 #define RU_GEN	2		/* Starting generator */
    925 #define RU_N	2147483629	/* RU_N-1 = 2^2*3^2*59652323 */
    926 #define RU_AGEN	7		/* determine ru_a as RU_AGEN^(2*rand) */
    927 #define RU_M	1836660096	/* RU_M = 2^7*3^15 - don't change */
    928 
    929 #define PFAC_N 3
    930 const static u_int32_t pfacts[PFAC_N] = {
    931 	2,
    932 	3,
    933 	59652323
    934 };
    935 
    936 static u_int32_t ru_x;
    937 static u_int32_t ru_seed, ru_seed2;
    938 static u_int32_t ru_a, ru_b;
    939 static u_int32_t ru_g;
    940 static u_int32_t ru_counter = 0;
    941 static u_int32_t ru_msb = 0;
    942 static long ru_reseed;
    943 
    944 static u_int32_t pmod(u_int32_t, u_int32_t, u_int32_t);
    945 static void initid(void);
    946 
    947 /*
    948  * Do a fast modular exponation, returned value will be in the range
    949  * of 0 - (mod-1)
    950  */
    951 static u_int32_t
    952 pmod(u_int32_t gen, u_int32_t exp, u_int32_t mod)
    953 {
    954 	u_int64_t s, t, u;
    955 
    956 	s = 1;
    957 	t = gen;
    958 	u = exp;
    959 
    960 	while (u) {
    961 		if (u & 1)
    962 			s = (s * t) % mod;
    963 		u >>= 1;
    964 		t = (t * t) % mod;
    965 	}
    966 	return ((u_int32_t)s & 0xffffffff);
    967 }
    968 
    969 /*
    970  * Initalizes the seed and chooses a suitable generator. Also toggles
    971  * the msb flag. The msb flag is used to generate two distinct
    972  * cycles of random numbers and thus avoiding reuse of ids.
    973  *
    974  * This function is called from id_randomid() when needed, an
    975  * application does not have to worry about it.
    976  */
    977 static void
    978 initid(void)
    979 {
    980 	u_int32_t j, i;
    981 	int noprime = 1;
    982 	struct timeval tv;
    983 
    984 	ru_x = arc4random() % RU_M;
    985 
    986 	/* 31 bits of random seed */
    987 	ru_seed = arc4random() & INT32_MAX;
    988 	ru_seed2 = arc4random() & INT32_MAX;
    989 
    990 	/* Determine the LCG we use */
    991 	ru_b = arc4random() | 1;
    992 	ru_a = pmod(RU_AGEN, arc4random() & (~1U), RU_M);
    993 	while (ru_b % 3 == 0)
    994 		ru_b += 2;
    995 
    996 	j = arc4random() % RU_N;
    997 
    998 	/*
    999 	 * Do a fast gcd(j,RU_N-1), so we can find a j with
   1000 	 * gcd(j, RU_N-1) == 1, giving a new generator for
   1001 	 * RU_GEN^j mod RU_N
   1002 	 */
   1003 	while (noprime) {
   1004 		for (i = 0; i < PFAC_N; i++)
   1005 			if (j % pfacts[i] == 0)
   1006 				break;
   1007 
   1008 		if (i >= PFAC_N)
   1009 			noprime = 0;
   1010 		else
   1011 			j = (j + 1) % RU_N;
   1012 	}
   1013 
   1014 	ru_g = pmod(RU_GEN, j, RU_N);
   1015 	ru_counter = 0;
   1016 
   1017 	gettimeofday(&tv, NULL);
   1018 	ru_reseed = tv.tv_sec + RU_OUT;
   1019 	ru_msb = ru_msb ? 0 : 0x80000000;
   1020 }
   1021 
   1022 u_int32_t
   1023 __rpc_getxid(void)
   1024 {
   1025 	int i, n;
   1026 	u_int32_t tmp;
   1027 	struct timeval tv;
   1028 
   1029 	gettimeofday(&tv, NULL);
   1030 	if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed)
   1031 		initid();
   1032 
   1033 	tmp = arc4random();
   1034 
   1035 	/* Skip a random number of ids */
   1036 	n = tmp & 0x3; tmp = tmp >> 2;
   1037 	if (ru_counter + n >= RU_MAX)
   1038 		initid();
   1039 
   1040 	for (i = 0; i <= n; i++) {
   1041 		/* Linear Congruential Generator */
   1042 		ru_x = (ru_a * ru_x + ru_b) % RU_M;
   1043 	}
   1044 
   1045 	ru_counter += i;
   1046 
   1047 	return (ru_seed ^ pmod(ru_g, ru_seed2 ^ ru_x,RU_N)) | ru_msb;
   1048 }
   1049