[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 #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 sin = nbuf->buf;
683 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
684 == NULL)
685 return NULL;
686 port = ntohs(sin->sin_port);
687 if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
688 port & 0xff) < 0)
689 return NULL;
690 break;
691 #ifdef INET6
692 case AF_INET6:
693 sin6 = nbuf->buf;
694 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
695 == NULL)
696 return NULL;
697 port = ntohs(sin6->sin6_port);
698 if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
699 port & 0xff) < 0)
700 return NULL;
701 break;
702 #endif
703 #ifdef AF_LOCAL
704 case AF_LOCAL:
705 sun = nbuf->buf;
706 /* if (asprintf(&ret, "%.*s", (int)(sun->sun_len -
707 offsetof(struct sockaddr_un, sun_path)),
708 sun->sun_path) < 0)*/
709 if (asprintf(&ret, "%.*s", (int)(sizeof(*sun) -
710 offsetof(struct sockaddr_un, sun_path)),
711 sun->sun_path) < 0)
712
713 return (NULL);
714 break;
715 #endif
716 default:
717 return NULL;
718 }
719
720 return ret;
721 }
722
723 struct netbuf *
724 __rpc_uaddr2taddr_af(int af, const char *uaddr)
725 {
726 struct netbuf *ret = NULL;
727 char *addrstr, *p;
728 unsigned short port, portlo, porthi;
729 struct sockaddr_in *sin;
730 #ifdef INET6
731 struct sockaddr_in6 *sin6;
732 #endif
733 #ifdef AF_LOCAL
734 struct sockaddr_un *sun;
735 #endif
736
737 port = 0;
738 sin = NULL;
739 addrstr = strdup(uaddr);
740 if (addrstr == NULL)
741 return NULL;
742
743 /*
744 * AF_LOCAL addresses are expected to be absolute
745 * pathnames, anything else will be AF_INET or AF_INET6.
746 */
747 if (*addrstr != '/') {
748 p = strrchr(addrstr, '.');
749 if (p == NULL)
750 goto out;
751 portlo = (unsigned)atoi(p + 1);
752 *p = '\0';
753
754 p = strrchr(addrstr, '.');
755 if (p == NULL)
756 goto out;
757 porthi = (unsigned)atoi(p + 1);
758 *p = '\0';
759 port = (porthi << 8) | portlo;
760 }
761
762 ret = (struct netbuf *)malloc(sizeof *ret);
763 if (ret == NULL)
764 goto out;
765
766 switch (af) {
767 case AF_INET:
768 sin = (struct sockaddr_in *)malloc(sizeof *sin);
769 if (sin == NULL)
770 goto out;
771 memset(sin, 0, sizeof *sin);
772 sin->sin_family = AF_INET;
773 sin->sin_port = htons(port);
774 #ifndef __REACTOS__
775 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
776 #else
777 sin->sin_addr.S_un.S_addr = inet_addr(addrstr);
778 if (sin->sin_addr.S_un.S_addr == INADDR_NONE) {
779 #endif
780 free(sin);
781 free(ret);
782 ret = NULL;
783 goto out;
784 }
785 ret->maxlen = ret->len = sizeof *sin;
786 ret->buf = sin;
787 break;
788 #ifdef INET6
789 case AF_INET6:
790 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
791 if (sin6 == NULL)
792 goto out;
793 memset(sin6, 0, sizeof *sin6);
794 sin6->sin6_family = AF_INET6;
795 sin6->sin6_port = htons(port);
796 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
797 free(sin6);
798 free(ret);
799 ret = NULL;
800 goto out;
801 }
802 ret->maxlen = ret->len = sizeof *sin6;
803 ret->buf = sin6;
804 break;
805 #endif
806 #ifdef AF_LOCAL
807 case AF_LOCAL:
808 sun = (struct sockaddr_un *)malloc(sizeof *sun);
809 if (sun == NULL)
810 goto out;
811 memset(sun, 0, sizeof *sun);
812 sun->sun_family = AF_LOCAL;
813 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
814 ret->len = SUN_LEN(sun);
815 ret->maxlen = sizeof(struct sockaddr_un);
816 ret->buf = sun;
817 break;
818 #endif
819 default:
820 break;
821 }
822 out:
823 free(addrstr);
824 return ret;
825 }
826
827 int
828 __rpc_seman2socktype(int semantics)
829 {
830 switch (semantics) {
831 case NC_TPI_CLTS:
832 return SOCK_DGRAM;
833 case NC_TPI_COTS_ORD:
834 return SOCK_STREAM;
835 case NC_TPI_RAW:
836 return SOCK_RAW;
837 default:
838 break;
839 }
840
841 return -1;
842 }
843
844 int
845 __rpc_socktype2seman(int socktype)
846 {
847 switch (socktype) {
848 case SOCK_DGRAM:
849 return NC_TPI_CLTS;
850 case SOCK_STREAM:
851 return NC_TPI_COTS_ORD;
852 case SOCK_RAW:
853 return NC_TPI_RAW;
854 default:
855 break;
856 }
857
858 return -1;
859 }
860
861 /*
862 * XXXX - IPv6 scope IDs can't be handled in universal addresses.
863 * Here, we compare the original server address to that of the RPC
864 * service we just received back from a call to rpcbind on the remote
865 * machine. If they are both "link local" or "site local", copy
866 * the scope id of the server address over to the service address.
867 */
868 int
869 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
870 {
871 #ifdef INET6
872 struct sockaddr *sa_new, *sa_svc;
873 struct sockaddr_in6 *sin6_new, *sin6_svc;
874
875 sa_svc = (struct sockaddr *)svc->buf;
876 sa_new = (struct sockaddr *)new->buf;
877
878 if (sa_new->sa_family == sa_svc->sa_family &&
879 sa_new->sa_family == AF_INET6) {
880 sin6_new = (struct sockaddr_in6 *)new->buf;
881 sin6_svc = (struct sockaddr_in6 *)svc->buf;
882
883 if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
884 IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
885 (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
886 IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
887 sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
888 }
889 }
890 #endif
891 return 1;
892 }
893
894 int
895 __rpc_sockisbound(SOCKET fd)
896 {
897 struct sockaddr_storage ss;
898 union {
899 struct sockaddr_in sin;
900 struct sockaddr_in6 sin6;
901 #ifdef AF_LOCAL
902 struct sockaddr_un usin;
903 #endif
904 } u_addr;
905 socklen_t slen;
906
907 slen = sizeof (struct sockaddr_storage);
908 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) == SOCKET_ERROR)
909 return 0;
910
911 switch (ss.ss_family) {
912 case AF_INET:
913 memcpy(&u_addr.sin, &ss, sizeof(u_addr.sin));
914 return (u_addr.sin.sin_port != 0);
915 #ifdef INET6
916 case AF_INET6:
917 memcpy(&u_addr.sin6, &ss, sizeof(u_addr.sin6));
918 return (u_addr.sin6.sin6_port != 0);
919 #endif
920 #ifdef AF_LOCAL
921 case AF_LOCAL:
922 /* XXX check this */
923 memcpy(&u_addr.usin, &ss, sizeof(u_addr.usin));
924 return (u_addr.usin.sun_path[0] != 0);
925 #endif
926 default:
927 break;
928 }
929
930 return 0;
931 }
932
933 /*
934 * Helper function to set up a netbuf
935 */
936 struct netbuf *
937 __rpc_set_netbuf(struct netbuf *nb, const void *ptr, size_t len)
938 {
939 if (nb->len != len) {
940 if (nb->len)
941 mem_free(nb->buf, nb->len);
942 nb->buf = mem_alloc(len);
943 if (nb->buf == NULL)
944 return NULL;
945
946 nb->maxlen = nb->len = len;
947 }
948 memcpy(nb->buf, ptr, len);
949 return nb;
950 }