1 /*
2  * Copyright (c) 2009, Sun Microsystems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * - Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  *   this list of conditions and the following disclaimer in the documentation
11  *   and/or other materials provided with the distribution.
12  * - Neither the name of Sun Microsystems, Inc. nor the names of its
13  *   contributors may be used to endorse or promote products derived
14  *   from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 /*
29  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
30  */
31 
32 //#include <sys/cdefs.h>
33 
34 /*
35  * rpc_generic.c, Miscl routines for RPC.
36  *
37  */
38 #include <wintirpc.h>
39 //#include <pthread.h>
40 #include <reentrant.h>
41 #include <sys/types.h>
42 //#include <sys/param.h>
43 //#include <sys/socket.h>
44 //#include <sys/time.h>
45 //#include <sys/un.h>
46 //#include <sys/resource.h>
47 //#include <netinet/in.h>
48 //#include <arpa/inet.h>
49 #include <rpc/rpc.h>
50 //#include <ctype.h>
51 //#include <stddef.h>
52 #include <stdio.h>
53 //#include <netdb.h>
54 #include <netconfig.h>
55 #include <stdlib.h>
56 #include <string.h>
57 //#include <syslog.h>
58 #include <rpc/nettype.h>
59 #include "rpc_com.h"
60 
61 struct handle {
62 	NCONF_HANDLE *nhandle;
63 	int nflag;		/* Whether NETPATH or NETCONFIG */
64 	int nettype;
65 };
66 
67 static const struct _rpcnettype {
68 	const char *name;
69 	const int type;
70 } _rpctypelist[] = {
71 	{ "netpath", _RPC_NETPATH },
72 	{ "visible", _RPC_VISIBLE },
73 	{ "circuit_v", _RPC_CIRCUIT_V },
74 	{ "datagram_v", _RPC_DATAGRAM_V },
75 	{ "circuit_n", _RPC_CIRCUIT_N },
76 	{ "datagram_n", _RPC_DATAGRAM_N },
77 	{ "tcp", _RPC_TCP },
78 	{ "udp", _RPC_UDP },
79 	{ 0, _RPC_NONE }
80 };
81 
82 struct netid_af {
83 	const char	*netid;
84 	ADDRESS_FAMILY		af;
85 	int		protocol;
86 };
87 
88 static const struct netid_af na_cvt[] = {
89 	{ "udp",  AF_INET,  IPPROTO_UDP },
90 	{ "tcp",  AF_INET,  IPPROTO_TCP },
91 #ifdef INET6
92 	{ "udp6", AF_INET6, IPPROTO_UDP },
93 	{ "tcp6", AF_INET6, IPPROTO_TCP },
94 #endif
95 #ifdef AF_LOCAL
96 	{ "local", AF_LOCAL, 0 }
97 #endif
98 };
99 
100 #if 0
101 static char *strlocase(char *);
102 #endif
103 static int getnettype(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 #ifdef _WIN32
113 	return (WINSOCK_HANDLE_HASH_SIZE);
114 #else
115 
116 	static int tbsize;
117 	struct rlimit rl;
118 
119 	if (tbsize) {
120 		return (tbsize);
121 	}
122 	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
123 		return (tbsize = (int)rl.rlim_max);
124 	}
125 	/*
126 	 * Something wrong.  I'll try to save face by returning a
127 	 * pessimistic number.
128 	 */
129 	return (32);
130 #endif
131 }
132 
133 
134 /*
135  * Find the appropriate buffer size
136  */
137 u_int
138 /*ARGSUSED*/
139 __rpc_get_t_size(af, proto, size)
140 	int af, proto;
141 	int size;	/* Size requested */
142 {
143 	int maxsize, defsize;
144 
145 	maxsize = 256 * 1024;	/* XXX */
146 	switch (proto) {
147 	case IPPROTO_TCP:
148 		defsize = 1024 * 1024;	/* XXX */
149 		break;
150 	case IPPROTO_UDP:
151 		defsize = UDPMSGSIZE;
152 		break;
153 	default:
154 		defsize = RPC_MAXDATASIZE;
155 		break;
156 	}
157 	if (size == 0)
158 		return defsize;
159 #if 1
160     /* cbodley- give us the size we ask for, or we'll get fragmented! */
161     return (u_int)size;
162 #else
163 	/* Check whether the value is within the upper max limit */
164 	return (size > maxsize ? (u_int)maxsize : (u_int)size);
165 #endif
166 }
167 
168 /*
169  * Find the appropriate address buffer size
170  */
171 u_int
172 __rpc_get_a_size(af)
173 	int af;
174 {
175 	switch (af) {
176 	case AF_INET:
177 		return sizeof (struct sockaddr_in);
178 #ifdef INET6
179 	case AF_INET6:
180 		return sizeof (struct sockaddr_in6);
181 #endif
182 #ifdef AF_LOCAL
183 	case AF_LOCAL:
184 		return sizeof (struct sockaddr_un);
185 #endif
186 	default:
187 		break;
188 	}
189 	return ((u_int)RPC_MAXADDRSIZE);
190 }
191 
192 #if 0
193 static char *
194 strlocase(p)
195 	char *p;
196 {
197 	char *t = p;
198 
199 	for (; *p; p++)
200 		if (isupper(*p))
201 			*p = tolower(*p);
202 	return (t);
203 }
204 #endif
205 
206 /*
207  * Returns the type of the network as defined in <rpc/nettype.h>
208  * If nettype is NULL, it defaults to NETPATH.
209  */
210 static int
211 getnettype(nettype)
212 	const char *nettype;
213 {
214 	int i;
215 
216 	if ((nettype == NULL) || (nettype[0] == 0)) {
217 		return (_RPC_NETPATH);	/* Default */
218 	}
219 
220 #if 0
221 	nettype = strlocase(nettype);
222 #endif
223 	for (i = 0; _rpctypelist[i].name; i++)
224 		if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
225 			return (_rpctypelist[i].type);
226 		}
227 	return (_rpctypelist[i].type);
228 }
229 
230 /*
231  * For the given nettype (tcp or udp only), return the first structure found.
232  * This should be freed by calling freenetconfigent()
233  */
234 struct netconfig *
235 __rpc_getconfip(nettype)
236 	const char *nettype;
237 {
238 	char *netid;
239 	char *netid_tcp = (char *) NULL;
240 	char *netid_udp = (char *) NULL;
241 	struct netconfig *dummy;
242 	extern thread_key_t tcp_key, udp_key;
243 	extern mutex_t tsd_lock;
244 
245 	if (tcp_key == -1) {
246 		mutex_lock(&tsd_lock);
247 		if (tcp_key == -1)
248 			tcp_key = TlsAlloc();	//thr_keycreate(&tcp_key, free);
249 		mutex_unlock(&tsd_lock);
250 	}
251 	netid_tcp = (char *)thr_getspecific(tcp_key);
252 	if (udp_key == -1) {
253 		mutex_lock(&tsd_lock);
254 		if (udp_key == -1)
255 			udp_key = TlsAlloc();	//thr_keycreate(&udp_key, free);
256 		mutex_unlock(&tsd_lock);
257 	}
258 	netid_udp = (char *)thr_getspecific(udp_key);
259 	if (!netid_udp && !netid_tcp) {
260 		struct netconfig *nconf;
261 		void *confighandle;
262 
263 		if (!(confighandle = setnetconfig())) {
264 			//syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
265 			return (NULL);
266 		}
267 		while ((nconf = getnetconfig(confighandle)) != NULL) {
268 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
269 			    strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
270 				if (strcmp(nconf->nc_proto, NC_TCP) == 0 &&
271 						netid_tcp == NULL) {
272 					netid_tcp = strdup(nconf->nc_netid);
273 					thr_setspecific(tcp_key,
274 							(void *) netid_tcp);
275 				} else
276 				if (strcmp(nconf->nc_proto, NC_UDP) == 0 &&
277 						netid_udp == NULL) {
278 					netid_udp = strdup(nconf->nc_netid);
279 					thr_setspecific(udp_key,
280 						(void *) netid_udp);
281 				}
282 			}
283 		}
284 		endnetconfig(confighandle);
285 	}
286 	if (strcmp(nettype, "udp") == 0)
287 		netid = netid_udp;
288 	else if (strcmp(nettype, "tcp") == 0)
289 		netid = netid_tcp;
290 	else {
291 		return (NULL);
292 	}
293 	if ((netid == NULL) || (netid[0] == 0)) {
294 		return (NULL);
295 	}
296 	dummy = getnetconfigent(netid);
297 	return (dummy);
298 }
299 
300 /*
301  * Returns the type of the nettype, which should then be used with
302  * __rpc_getconf().
303  */
304 void *
305 __rpc_setconf(nettype)
306 	const char *nettype;
307 {
308 	struct handle *handle;
309 
310 	handle = (struct handle *) malloc(sizeof (struct handle));
311 	if (handle == NULL) {
312 		return (NULL);
313 	}
314 	switch (handle->nettype = getnettype(nettype)) {
315 	case _RPC_NETPATH:
316 	case _RPC_CIRCUIT_N:
317 	case _RPC_DATAGRAM_N:
318 		if (!(handle->nhandle = setnetpath())) {
319 			free(handle);
320 			return (NULL);
321 		}
322 		handle->nflag = TRUE;
323 		break;
324 	case _RPC_VISIBLE:
325 	case _RPC_CIRCUIT_V:
326 	case _RPC_DATAGRAM_V:
327 	case _RPC_TCP:
328 	case _RPC_UDP:
329 		if (!(handle->nhandle = setnetconfig())) {
330 		        //syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
331 			free(handle);
332 			return (NULL);
333 		}
334 		handle->nflag = FALSE;
335 		break;
336 	default:
337 		return (NULL);
338 	}
339 
340 	return (handle);
341 }
342 
343 /*
344  * Returns the next netconfig struct for the given "net" type.
345  * __rpc_setconf() should have been called previously.
346  */
347 struct netconfig *
348 __rpc_getconf(vhandle)
349 	void *vhandle;
350 {
351 	struct handle *handle;
352 	struct netconfig *nconf;
353 
354 	handle = (struct handle *)vhandle;
355 	if (handle == NULL) {
356 		return (NULL);
357 	}
358 	for (;;) {
359 		if (handle->nflag)
360 			nconf = getnetpath(handle->nhandle);
361 		else
362 			nconf = getnetconfig(handle->nhandle);
363 		if (nconf == NULL)
364 			break;
365 		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
366 			(nconf->nc_semantics != NC_TPI_COTS) &&
367 			(nconf->nc_semantics != NC_TPI_COTS_ORD))
368 			continue;
369 		switch (handle->nettype) {
370 		case _RPC_VISIBLE:
371 			if (!(nconf->nc_flag & NC_VISIBLE))
372 				continue;
373 			/* FALLTHROUGH */
374 		case _RPC_NETPATH:	/* Be happy */
375 			break;
376 		case _RPC_CIRCUIT_V:
377 			if (!(nconf->nc_flag & NC_VISIBLE))
378 				continue;
379 			/* FALLTHROUGH */
380 		case _RPC_CIRCUIT_N:
381 			if ((nconf->nc_semantics != NC_TPI_COTS) &&
382 				(nconf->nc_semantics != NC_TPI_COTS_ORD))
383 				continue;
384 			break;
385 		case _RPC_DATAGRAM_V:
386 			if (!(nconf->nc_flag & NC_VISIBLE))
387 				continue;
388 			/* FALLTHROUGH */
389 		case _RPC_DATAGRAM_N:
390 			if (nconf->nc_semantics != NC_TPI_CLTS)
391 				continue;
392 			break;
393 		case _RPC_TCP:
394 			if (((nconf->nc_semantics != NC_TPI_COTS) &&
395 				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
396 				(strcmp(nconf->nc_protofmly, NC_INET)
397 #ifdef INET6
398 				 && strcmp(nconf->nc_protofmly, NC_INET6))
399 #else
400 				)
401 #endif
402 				||
403 				strcmp(nconf->nc_proto, NC_TCP))
404 				continue;
405 			break;
406 		case _RPC_UDP:
407 			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
408 				(strcmp(nconf->nc_protofmly, NC_INET)
409 #ifdef INET6
410 				&& strcmp(nconf->nc_protofmly, NC_INET6))
411 #else
412 				)
413 #endif
414 				||
415 				strcmp(nconf->nc_proto, NC_UDP))
416 				continue;
417 			break;
418 		}
419 		break;
420 	}
421 	return (nconf);
422 }
423 
424 void
425 __rpc_endconf(vhandle)
426 	void * vhandle;
427 {
428 	struct handle *handle;
429 
430 	handle = (struct handle *) vhandle;
431 	if (handle == NULL) {
432 		return;
433 	}
434 	if (handle->nflag) {
435 		endnetpath(handle->nhandle);
436 	} else {
437 		endnetconfig(handle->nhandle);
438 	}
439 	free(handle);
440 }
441 
442 /*
443  * Used to ping the NULL procedure for clnt handle.
444  * Returns NULL if fails, else a non-NULL pointer.
445  */
446 void *
447 rpc_nullproc(clnt)
448 	CLIENT *clnt;
449 {
450 	struct timeval TIMEOUT = {25, 0};
451 
452 	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
453 		(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
454 		return (NULL);
455 	}
456 	return ((void *) clnt);
457 }
458 
459 /*
460  * Try all possible transports until
461  * one succeeds in finding the netconf for the given fd.
462  */
463 struct netconfig *
464 __rpcgettp(fd)
465 	SOCKET fd;
466 {
467 	const char *netid;
468 	struct __rpc_sockinfo si;
469 
470 	if (!__rpc_fd2sockinfo(fd, &si))
471 		return NULL;
472 
473 	if (!__rpc_sockinfo2netid(&si, &netid))
474 		return NULL;
475 
476 	/*LINTED const castaway*/
477 	return getnetconfigent((char *)netid);
478 }
479 
480 int
481 __rpc_fd2sockinfo(SOCKET fd, struct __rpc_sockinfo *sip)
482 {
483 	socklen_t len;
484 	int type, proto;
485 	struct sockaddr_storage ss;
486 
487 #ifdef _WIN32
488 	WSAPROTOCOL_INFO proto_info;
489 	int proto_info_size = sizeof(proto_info);
490 	if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL_INFO, (char *)&proto_info, &proto_info_size) == SOCKET_ERROR) {
491 #ifndef __REACTOS__
492 		int err = WSAGetLastError();
493 #endif
494 		return 0;
495 	}
496 	len = proto_info.iMaxSockAddr;
497 	ss.ss_family = (ADDRESS_FAMILY)proto_info.iAddressFamily;
498 #else
499 	len = sizeof ss;
500 	if (getsockname(fd, (struct sockaddr *)&ss, &len) == SOCKET_ERROR) {
501 		return 0;
502 	}
503 #endif
504 	sip->si_alen = len;
505 
506 	len = sizeof type;
507 	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&type, &len) == SOCKET_ERROR) {
508 #ifndef __REACTOS__
509 		int err = WSAGetLastError();
510 #endif
511 		return 0;
512 	}
513 
514 	/* XXX */
515 #ifdef AF_LOCAL
516 	if (ss.ss_family != AF_LOCAL) {
517 #endif
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 #ifdef AF_LOCAL
525 	} else
526 		proto = 0;
527 #endif
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 	int i;
543 
544 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
545 		if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
546 		    strcmp(nconf->nc_netid, "unix") == 0 &&
547 		    strcmp(na_cvt[i].netid, "local") == 0)) {
548 			sip->si_af = na_cvt[i].af;
549 			sip->si_proto = na_cvt[i].protocol;
550 			sip->si_socktype =
551 			    __rpc_seman2socktype((int)nconf->nc_semantics);
552 			if (sip->si_socktype == -1)
553 				return 0;
554 			sip->si_alen = __rpc_get_a_size(sip->si_af);
555 			return 1;
556 		}
557 
558 	return 0;
559 }
560 
561 SOCKET
562 __rpc_nconf2fd(const struct netconfig *nconf)
563 {
564 	struct __rpc_sockinfo si;
565 	SOCKET fd;
566 
567 	if (!__rpc_nconf2sockinfo(nconf, &si))
568 		return 0;
569 
570 	if ((fd = socket(si.si_af, si.si_socktype, si.si_proto)) != INVALID_SOCKET &&
571 	    si.si_af == AF_INET6) {
572 		int val = 1;
573 
574 		setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (const char *)&val, sizeof(val));
575 	}
576 	return fd;
577 }
578 
579 int
580 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
581 {
582 	int i;
583 	struct netconfig *nconf;
584 
585 	nconf = getnetconfigent("local");
586 
587 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) {
588 		if (na_cvt[i].af == sip->si_af &&
589 		    na_cvt[i].protocol == sip->si_proto) {
590 			if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) {
591 				if (netid)
592 					*netid = "unix";
593 			} else {
594 				if (netid)
595 					*netid = na_cvt[i].netid;
596 			}
597 			if (nconf != NULL)
598 				freenetconfigent(nconf);
599 			return 1;
600 		}
601 	}
602 	if (nconf != NULL)
603 		freenetconfigent(nconf);
604 
605 	return 0;
606 }
607 
608 char *
609 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
610 {
611 	struct __rpc_sockinfo si;
612 
613 	if (!__rpc_nconf2sockinfo(nconf, &si))
614 		return NULL;
615 	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
616 }
617 
618 struct netbuf *
619 uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
620 {
621 	struct __rpc_sockinfo si;
622 
623 	if (!__rpc_nconf2sockinfo(nconf, &si))
624 		return NULL;
625 	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
626 }
627 
628 void freeuaddr(char *uaddr)
629 {
630 	free(uaddr);
631 }
632 
633 void freenetbuf(struct netbuf *nbuf)
634 {
635 	if (nbuf) {
636 		free(nbuf->buf);
637 		free(nbuf);
638 	}
639 }
640 
641 #ifdef __REACTOS__
642 PCSTR
643 WSAAPI
644 inet_ntop(INT af, PVOID src, PSTR dst, size_t cnt)
645 {
646 	struct in_addr in;
647 	char *text_addr;
648 
649 	if (af == AF_INET) {
650 		memcpy(&in.s_addr, src, sizeof(in.s_addr));
651 		text_addr = inet_ntoa(in);
652 		if (text_addr && dst) {
653 			strncpy(dst, text_addr, cnt);
654 			return dst;
655 		}
656 	}
657 
658 	return 0;
659 }
660 #endif
661 
662 char *
663 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
664 {
665 	char *ret;
666 	struct sockaddr_in *sin;
667 #ifdef AF_LOCAL
668 	struct sockaddr_un *sun;
669 #endif
670 	char namebuf[INET_ADDRSTRLEN];
671 #ifdef INET6
672 	struct sockaddr_in6 *sin6;
673 	char namebuf6[INET6_ADDRSTRLEN];
674 #endif
675 	u_int16_t port;
676 
677 	if (nbuf->len <= 0)
678 		return NULL;
679 
680 	switch (af) {
681 	case AF_INET:
682 #ifdef __REACTOS__ // CVE-2017-8779
683 		if (nbuf->len < sizeof(*sin)) {
684 			return NULL;
685 		}
686 #endif
687 		sin = nbuf->buf;
688 		if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
689 		    == NULL)
690 			return NULL;
691 		port = ntohs(sin->sin_port);
692 		if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
693 		    port & 0xff) < 0)
694 			return NULL;
695 		break;
696 #ifdef INET6
697 	case AF_INET6:
698 #ifdef __REACTOS__ // CVE-2017-8779
699 		if (nbuf->len < sizeof(*sin6)) {
700 			return NULL;
701 		}
702 #endif
703 		sin6 = nbuf->buf;
704 		if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
705 		    == NULL)
706 			return NULL;
707 		port = ntohs(sin6->sin6_port);
708 		if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
709 		    port & 0xff) < 0)
710 			return NULL;
711 		break;
712 #endif
713 #ifdef AF_LOCAL
714 	case AF_LOCAL:
715 		sun = nbuf->buf;
716 		/*	if (asprintf(&ret, "%.*s", (int)(sun->sun_len -
717 		    offsetof(struct sockaddr_un, sun_path)),
718 		    sun->sun_path) < 0)*/
719 		if (asprintf(&ret, "%.*s", (int)(sizeof(*sun) -
720 						 offsetof(struct sockaddr_un, sun_path)),
721 			     sun->sun_path) < 0)
722 
723 			return (NULL);
724 		break;
725 #endif
726 	default:
727 		return NULL;
728 	}
729 
730 	return ret;
731 }
732 
733 struct netbuf *
734 __rpc_uaddr2taddr_af(int af, const char *uaddr)
735 {
736 	struct netbuf *ret = NULL;
737 	char *addrstr, *p;
738 	unsigned short port, portlo, porthi;
739 	struct sockaddr_in *sin;
740 #ifdef INET6
741 	struct sockaddr_in6 *sin6;
742 #endif
743 #ifdef AF_LOCAL
744 	struct sockaddr_un *sun;
745 #endif
746 
747 	port = 0;
748 	sin = NULL;
749 #ifdef __REACTOS__ // CVE-2017-8779
750 	if (uaddr == NULL)
751 		return NULL;
752 #endif
753 	addrstr = strdup(uaddr);
754 	if (addrstr == NULL)
755 		return NULL;
756 
757 	/*
758 	 * AF_LOCAL addresses are expected to be absolute
759 	 * pathnames, anything else will be AF_INET or AF_INET6.
760 	 */
761 	if (*addrstr != '/') {
762 		p = strrchr(addrstr, '.');
763 		if (p == NULL)
764 			goto out;
765 		portlo = (unsigned)atoi(p + 1);
766 		*p = '\0';
767 
768 		p = strrchr(addrstr, '.');
769 		if (p == NULL)
770 			goto out;
771 		porthi = (unsigned)atoi(p + 1);
772 		*p = '\0';
773 		port = (porthi << 8) | portlo;
774 	}
775 
776 	ret = (struct netbuf *)malloc(sizeof *ret);
777 	if (ret == NULL)
778 		goto out;
779 
780 	switch (af) {
781 	case AF_INET:
782 		sin = (struct sockaddr_in *)malloc(sizeof *sin);
783 		if (sin == NULL)
784 			goto out;
785 		memset(sin, 0, sizeof *sin);
786 		sin->sin_family = AF_INET;
787 		sin->sin_port = htons(port);
788 #ifndef __REACTOS__
789 		if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
790 #else
791 		sin->sin_addr.S_un.S_addr = inet_addr(addrstr);
792 		if (sin->sin_addr.S_un.S_addr == INADDR_NONE) {
793 #endif
794 			free(sin);
795 			free(ret);
796 			ret = NULL;
797 			goto out;
798 		}
799 		ret->maxlen = ret->len = sizeof *sin;
800 		ret->buf = sin;
801 		break;
802 #ifdef INET6
803 	case AF_INET6:
804 		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
805 		if (sin6 == NULL)
806 			goto out;
807 		memset(sin6, 0, sizeof *sin6);
808 		sin6->sin6_family = AF_INET6;
809 		sin6->sin6_port = htons(port);
810 		if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
811 			free(sin6);
812 			free(ret);
813 			ret = NULL;
814 			goto out;
815 		}
816 		ret->maxlen = ret->len = sizeof *sin6;
817 		ret->buf = sin6;
818 		break;
819 #endif
820 #ifdef AF_LOCAL
821 	case AF_LOCAL:
822 		sun = (struct sockaddr_un *)malloc(sizeof *sun);
823 		if (sun == NULL)
824 			goto out;
825 		memset(sun, 0, sizeof *sun);
826 		sun->sun_family = AF_LOCAL;
827 		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
828 		ret->len = SUN_LEN(sun);
829 		ret->maxlen = sizeof(struct sockaddr_un);
830 		ret->buf = sun;
831 		break;
832 #endif
833 	default:
834 		break;
835 	}
836 out:
837 	free(addrstr);
838 	return ret;
839 }
840 
841 int
842 __rpc_seman2socktype(int semantics)
843 {
844 	switch (semantics) {
845 	case NC_TPI_CLTS:
846 		return SOCK_DGRAM;
847 	case NC_TPI_COTS_ORD:
848 		return SOCK_STREAM;
849 	case NC_TPI_RAW:
850 		return SOCK_RAW;
851 	default:
852 		break;
853 	}
854 
855 	return -1;
856 }
857 
858 int
859 __rpc_socktype2seman(int socktype)
860 {
861 	switch (socktype) {
862 	case SOCK_DGRAM:
863 		return NC_TPI_CLTS;
864 	case SOCK_STREAM:
865 		return NC_TPI_COTS_ORD;
866 	case SOCK_RAW:
867 		return NC_TPI_RAW;
868 	default:
869 		break;
870 	}
871 
872 	return -1;
873 }
874 
875 /*
876  * XXXX - IPv6 scope IDs can't be handled in universal addresses.
877  * Here, we compare the original server address to that of the RPC
878  * service we just received back from a call to rpcbind on the remote
879  * machine. If they are both "link local" or "site local", copy
880  * the scope id of the server address over to the service address.
881  */
882 int
883 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
884 {
885 #ifdef INET6
886 	struct sockaddr *sa_new, *sa_svc;
887 	struct sockaddr_in6 *sin6_new, *sin6_svc;
888 
889 	sa_svc = (struct sockaddr *)svc->buf;
890 	sa_new = (struct sockaddr *)new->buf;
891 
892 	if (sa_new->sa_family == sa_svc->sa_family &&
893 	    sa_new->sa_family == AF_INET6) {
894 		sin6_new = (struct sockaddr_in6 *)new->buf;
895 		sin6_svc = (struct sockaddr_in6 *)svc->buf;
896 
897 		if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
898 		     IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
899 		    (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
900 		     IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
901 			sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
902 		}
903 	}
904 #endif
905 	return 1;
906 }
907 
908 int
909 __rpc_sockisbound(SOCKET fd)
910 {
911 	struct sockaddr_storage ss;
912 	union {
913 		struct sockaddr_in  sin;
914 		struct sockaddr_in6 sin6;
915 #ifdef AF_LOCAL
916 		struct sockaddr_un  usin;
917 #endif
918 	} u_addr;
919 	socklen_t slen;
920 
921 	slen = sizeof (struct sockaddr_storage);
922 	if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) == SOCKET_ERROR)
923 		return 0;
924 
925 	switch (ss.ss_family) {
926 		case AF_INET:
927 			memcpy(&u_addr.sin, &ss, sizeof(u_addr.sin));
928 			return (u_addr.sin.sin_port != 0);
929 #ifdef INET6
930 		case AF_INET6:
931 			memcpy(&u_addr.sin6, &ss, sizeof(u_addr.sin6));
932 			return (u_addr.sin6.sin6_port != 0);
933 #endif
934 #ifdef AF_LOCAL
935 		case AF_LOCAL:
936 			/* XXX check this */
937 			memcpy(&u_addr.usin, &ss, sizeof(u_addr.usin));
938 			return (u_addr.usin.sun_path[0] != 0);
939 #endif
940 		default:
941 			break;
942 	}
943 
944 	return 0;
945 }
946 
947 /*
948  * Helper function to set up a netbuf
949  */
950 struct netbuf *
951 __rpc_set_netbuf(struct netbuf *nb, const void *ptr, size_t len)
952 {
953 	if (nb->len != len) {
954 		if (nb->len)
955 			mem_free(nb->buf, nb->len);
956 		nb->buf = mem_alloc(len);
957 		if (nb->buf == NULL)
958 			return NULL;
959 
960 		nb->maxlen = nb->len = len;
961 	}
962 	memcpy(nb->buf, ptr, len);
963 	return nb;
964 }
965