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 } 951