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