[LIBTIRPC]
[reactos.git] / reactos / dll / win32 / libtirpc / src / rpc_generic.c
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 int err = WSAGetLastError();
492 return 0;
493 }
494 len = proto_info.iMaxSockAddr;
495 ss.ss_family = (ADDRESS_FAMILY)proto_info.iAddressFamily;
496 #else
497 len = sizeof ss;
498 if (getsockname(fd, (struct sockaddr *)&ss, &len) == SOCKET_ERROR) {
499 return 0;
500 }
501 #endif
502 sip->si_alen = len;
503
504 len = sizeof type;
505 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&type, &len) == SOCKET_ERROR) {
506 int err = WSAGetLastError();
507 return 0;
508 }
509
510 /* XXX */
511 #ifdef AF_LOCAL
512 if (ss.ss_family != AF_LOCAL) {
513 #endif
514 if (type == SOCK_STREAM)
515 proto = IPPROTO_TCP;
516 else if (type == SOCK_DGRAM)
517 proto = IPPROTO_UDP;
518 else
519 return 0;
520 #ifdef AF_LOCAL
521 } else
522 proto = 0;
523 #endif
524
525 sip->si_af = ss.ss_family;
526 sip->si_proto = proto;
527 sip->si_socktype = type;
528
529 return 1;
530 }
531
532 /*
533 * Linear search, but the number of entries is small.
534 */
535 int
536 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
537 {
538 int i;
539
540 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
541 if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
542 strcmp(nconf->nc_netid, "unix") == 0 &&
543 strcmp(na_cvt[i].netid, "local") == 0)) {
544 sip->si_af = na_cvt[i].af;
545 sip->si_proto = na_cvt[i].protocol;
546 sip->si_socktype =
547 __rpc_seman2socktype((int)nconf->nc_semantics);
548 if (sip->si_socktype == -1)
549 return 0;
550 sip->si_alen = __rpc_get_a_size(sip->si_af);
551 return 1;
552 }
553
554 return 0;
555 }
556
557 SOCKET
558 __rpc_nconf2fd(const struct netconfig *nconf)
559 {
560 struct __rpc_sockinfo si;
561 SOCKET fd;
562
563 if (!__rpc_nconf2sockinfo(nconf, &si))
564 return 0;
565
566 if ((fd = socket(si.si_af, si.si_socktype, si.si_proto)) != INVALID_SOCKET &&
567 si.si_af == AF_INET6) {
568 int val = 1;
569
570 setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (const char *)&val, sizeof(val));
571 }
572 return fd;
573 }
574
575 int
576 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
577 {
578 int i;
579 struct netconfig *nconf;
580
581 nconf = getnetconfigent("local");
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 (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) {
587 if (netid)
588 *netid = "unix";
589 } else {
590 if (netid)
591 *netid = na_cvt[i].netid;
592 }
593 if (nconf != NULL)
594 freenetconfigent(nconf);
595 return 1;
596 }
597 }
598 if (nconf != NULL)
599 freenetconfigent(nconf);
600
601 return 0;
602 }
603
604 char *
605 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
606 {
607 struct __rpc_sockinfo si;
608
609 if (!__rpc_nconf2sockinfo(nconf, &si))
610 return NULL;
611 return __rpc_taddr2uaddr_af(si.si_af, nbuf);
612 }
613
614 struct netbuf *
615 uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
616 {
617 struct __rpc_sockinfo si;
618
619 if (!__rpc_nconf2sockinfo(nconf, &si))
620 return NULL;
621 return __rpc_uaddr2taddr_af(si.si_af, uaddr);
622 }
623
624 void freeuaddr(char *uaddr)
625 {
626 free(uaddr);
627 }
628
629 void freenetbuf(struct netbuf *nbuf)
630 {
631 if (nbuf) {
632 free(nbuf->buf);
633 free(nbuf);
634 }
635 }
636
637 #ifdef __REACTOS__
638 PCSTR
639 WSAAPI
640 inet_ntop(INT af, PVOID src, PSTR dst, size_t cnt)
641 {
642 struct in_addr in;
643 char *text_addr;
644
645 if (af == AF_INET) {
646 memcpy(&in.s_addr, src, sizeof(in.s_addr));
647 text_addr = inet_ntoa(in);
648 if (text_addr && dst) {
649 strncpy(dst, text_addr, cnt);
650 return dst;
651 }
652 }
653
654 return 0;
655 }
656 #endif
657
658 char *
659 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
660 {
661 char *ret;
662 struct sockaddr_in *sin;
663 #ifdef AF_LOCAL
664 struct sockaddr_un *sun;
665 #endif
666 char namebuf[INET_ADDRSTRLEN];
667 #ifdef INET6
668 struct sockaddr_in6 *sin6;
669 char namebuf6[INET6_ADDRSTRLEN];
670 #endif
671 u_int16_t port;
672
673 if (nbuf->len <= 0)
674 return NULL;
675
676 switch (af) {
677 case AF_INET:
678 sin = nbuf->buf;
679 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
680 == NULL)
681 return NULL;
682 port = ntohs(sin->sin_port);
683 if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
684 port & 0xff) < 0)
685 return NULL;
686 break;
687 #ifdef INET6
688 case AF_INET6:
689 sin6 = nbuf->buf;
690 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
691 == NULL)
692 return NULL;
693 port = ntohs(sin6->sin6_port);
694 if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
695 port & 0xff) < 0)
696 return NULL;
697 break;
698 #endif
699 #ifdef AF_LOCAL
700 case AF_LOCAL:
701 sun = nbuf->buf;
702 /* if (asprintf(&ret, "%.*s", (int)(sun->sun_len -
703 offsetof(struct sockaddr_un, sun_path)),
704 sun->sun_path) < 0)*/
705 if (asprintf(&ret, "%.*s", (int)(sizeof(*sun) -
706 offsetof(struct sockaddr_un, sun_path)),
707 sun->sun_path) < 0)
708
709 return (NULL);
710 break;
711 #endif
712 default:
713 return NULL;
714 }
715
716 return ret;
717 }
718
719 struct netbuf *
720 __rpc_uaddr2taddr_af(int af, const char *uaddr)
721 {
722 struct netbuf *ret = NULL;
723 char *addrstr, *p;
724 unsigned short port, portlo, porthi;
725 struct sockaddr_in *sin;
726 #ifdef INET6
727 struct sockaddr_in6 *sin6;
728 #endif
729 #ifdef AF_LOCAL
730 struct sockaddr_un *sun;
731 #endif
732
733 port = 0;
734 sin = NULL;
735 addrstr = strdup(uaddr);
736 if (addrstr == NULL)
737 return NULL;
738
739 /*
740 * AF_LOCAL addresses are expected to be absolute
741 * pathnames, anything else will be AF_INET or AF_INET6.
742 */
743 if (*addrstr != '/') {
744 p = strrchr(addrstr, '.');
745 if (p == NULL)
746 goto out;
747 portlo = (unsigned)atoi(p + 1);
748 *p = '\0';
749
750 p = strrchr(addrstr, '.');
751 if (p == NULL)
752 goto out;
753 porthi = (unsigned)atoi(p + 1);
754 *p = '\0';
755 port = (porthi << 8) | portlo;
756 }
757
758 ret = (struct netbuf *)malloc(sizeof *ret);
759 if (ret == NULL)
760 goto out;
761
762 switch (af) {
763 case AF_INET:
764 sin = (struct sockaddr_in *)malloc(sizeof *sin);
765 if (sin == NULL)
766 goto out;
767 memset(sin, 0, sizeof *sin);
768 sin->sin_family = AF_INET;
769 sin->sin_port = htons(port);
770 #ifndef __REACTOS__
771 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
772 #else
773 sin->sin_addr.S_un.S_addr = inet_addr(addrstr);
774 if (sin->sin_addr.S_un.S_addr == INADDR_NONE) {
775 #endif
776 free(sin);
777 free(ret);
778 ret = NULL;
779 goto out;
780 }
781 ret->maxlen = ret->len = sizeof *sin;
782 ret->buf = sin;
783 break;
784 #ifdef INET6
785 case AF_INET6:
786 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
787 if (sin6 == NULL)
788 goto out;
789 memset(sin6, 0, sizeof *sin6);
790 sin6->sin6_family = AF_INET6;
791 sin6->sin6_port = htons(port);
792 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
793 free(sin6);
794 free(ret);
795 ret = NULL;
796 goto out;
797 }
798 ret->maxlen = ret->len = sizeof *sin6;
799 ret->buf = sin6;
800 break;
801 #endif
802 #ifdef AF_LOCAL
803 case AF_LOCAL:
804 sun = (struct sockaddr_un *)malloc(sizeof *sun);
805 if (sun == NULL)
806 goto out;
807 memset(sun, 0, sizeof *sun);
808 sun->sun_family = AF_LOCAL;
809 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
810 ret->len = SUN_LEN(sun);
811 ret->maxlen = sizeof(struct sockaddr_un);
812 ret->buf = sun;
813 break;
814 #endif
815 default:
816 break;
817 }
818 out:
819 free(addrstr);
820 return ret;
821 }
822
823 int
824 __rpc_seman2socktype(int semantics)
825 {
826 switch (semantics) {
827 case NC_TPI_CLTS:
828 return SOCK_DGRAM;
829 case NC_TPI_COTS_ORD:
830 return SOCK_STREAM;
831 case NC_TPI_RAW:
832 return SOCK_RAW;
833 default:
834 break;
835 }
836
837 return -1;
838 }
839
840 int
841 __rpc_socktype2seman(int socktype)
842 {
843 switch (socktype) {
844 case SOCK_DGRAM:
845 return NC_TPI_CLTS;
846 case SOCK_STREAM:
847 return NC_TPI_COTS_ORD;
848 case SOCK_RAW:
849 return NC_TPI_RAW;
850 default:
851 break;
852 }
853
854 return -1;
855 }
856
857 /*
858 * XXXX - IPv6 scope IDs can't be handled in universal addresses.
859 * Here, we compare the original server address to that of the RPC
860 * service we just received back from a call to rpcbind on the remote
861 * machine. If they are both "link local" or "site local", copy
862 * the scope id of the server address over to the service address.
863 */
864 int
865 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
866 {
867 #ifdef INET6
868 struct sockaddr *sa_new, *sa_svc;
869 struct sockaddr_in6 *sin6_new, *sin6_svc;
870
871 sa_svc = (struct sockaddr *)svc->buf;
872 sa_new = (struct sockaddr *)new->buf;
873
874 if (sa_new->sa_family == sa_svc->sa_family &&
875 sa_new->sa_family == AF_INET6) {
876 sin6_new = (struct sockaddr_in6 *)new->buf;
877 sin6_svc = (struct sockaddr_in6 *)svc->buf;
878
879 if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
880 IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
881 (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
882 IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
883 sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
884 }
885 }
886 #endif
887 return 1;
888 }
889
890 int
891 __rpc_sockisbound(SOCKET fd)
892 {
893 struct sockaddr_storage ss;
894 union {
895 struct sockaddr_in sin;
896 struct sockaddr_in6 sin6;
897 #ifdef AF_LOCAL
898 struct sockaddr_un usin;
899 #endif
900 } u_addr;
901 socklen_t slen;
902
903 slen = sizeof (struct sockaddr_storage);
904 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) == SOCKET_ERROR)
905 return 0;
906
907 switch (ss.ss_family) {
908 case AF_INET:
909 memcpy(&u_addr.sin, &ss, sizeof(u_addr.sin));
910 return (u_addr.sin.sin_port != 0);
911 #ifdef INET6
912 case AF_INET6:
913 memcpy(&u_addr.sin6, &ss, sizeof(u_addr.sin6));
914 return (u_addr.sin6.sin6_port != 0);
915 #endif
916 #ifdef AF_LOCAL
917 case AF_LOCAL:
918 /* XXX check this */
919 memcpy(&u_addr.usin, &ss, sizeof(u_addr.usin));
920 return (u_addr.usin.sun_path[0] != 0);
921 #endif
922 default:
923 break;
924 }
925
926 return 0;
927 }
928
929 /*
930 * Helper function to set up a netbuf
931 */
932 struct netbuf *
933 __rpc_set_netbuf(struct netbuf *nb, const void *ptr, size_t len)
934 {
935 if (nb->len != len) {
936 if (nb->len)
937 mem_free(nb->buf, nb->len);
938 nb->buf = mem_alloc(len);
939 if (nb->buf == NULL)
940 return NULL;
941
942 nb->maxlen = nb->len = len;
943 }
944 memcpy(nb->buf, ptr, len);
945 return nb;
946 }