1 /* $NetBSD: rpc_generic.c,v 1.12 2003/01/18 11:29:05 thorpej Exp $ */ 2 3 /* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 /* 32 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 33 */ 34 35 /* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */ 36 37 /* 38 * rpc_generic.c, Miscl routines for RPC. 39 * 40 */ 41 42 #include "namespace.h" 43 #include "reentrant.h" 44 #include <sys/types.h> 45 #include <sys/param.h> 46 #include <sys/socket.h> 47 #include <sys/un.h> 48 #include <sys/resource.h> 49 #include <netinet/in.h> 50 #include <arpa/inet.h> 51 #include <rpc/rpc.h> 52 #include <assert.h> 53 #include <ctype.h> 54 #include <stdio.h> 55 #include <netdb.h> 56 #include <netconfig.h> 57 #include <malloc.h> 58 #include <string.h> 59 #include <syslog.h> 60 #include <rpc/nettype.h> 61 #include "rpc_internal.h" 62 63 struct handle { 64 NCONF_HANDLE *nhandle; 65 int nflag; /* Whether NETPATH or NETCONFIG */ 66 int nettype; 67 }; 68 69 static const struct _rpcnettype { 70 const char *name; 71 const int type; 72 } _rpctypelist[] = { 73 { "netpath", _RPC_NETPATH }, 74 { "visible", _RPC_VISIBLE }, 75 { "circuit_v", _RPC_CIRCUIT_V }, 76 { "datagram_v", _RPC_DATAGRAM_V }, 77 { "circuit_n", _RPC_CIRCUIT_N }, 78 { "datagram_n", _RPC_DATAGRAM_N }, 79 { "tcp", _RPC_TCP }, 80 { "udp", _RPC_UDP }, 81 { 0, _RPC_NONE } 82 }; 83 84 struct netid_af { 85 const char *netid; 86 int af; 87 int protocol; 88 }; 89 90 static const struct netid_af na_cvt[] = { 91 { "udp", AF_INET, IPPROTO_UDP }, 92 { "tcp", AF_INET, IPPROTO_TCP }, 93 #ifdef INET6 94 { "udp6", AF_INET6, IPPROTO_UDP }, 95 { "tcp6", AF_INET6, IPPROTO_TCP }, 96 #endif 97 { "local", AF_LOCAL, 0 } 98 }; 99 100 #if 0 101 static char *strlocase __P((char *)); 102 #endif 103 static int getnettype __P((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 static int tbsize; 113 struct rlimit rl; 114 115 if (tbsize) { 116 return (tbsize); 117 } 118 if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 119 return (tbsize = (int)rl.rlim_max); 120 } 121 /* 122 * Something wrong. I'll try to save face by returning a 123 * pessimistic number. 124 */ 125 return (32); 126 } 127 128 129 /* 130 * Find the appropriate buffer size 131 */ 132 u_int 133 /*ARGSUSED*/ 134 __rpc_get_t_size(af, proto, size) 135 int af, proto; 136 int size; /* Size requested */ 137 { 138 int maxsize; 139 140 switch (proto) { 141 case IPPROTO_TCP: 142 maxsize = 65536; /* XXX */ 143 break; 144 case IPPROTO_UDP: 145 maxsize = 8192; /* XXX */ 146 break; 147 default: 148 maxsize = RPC_MAXDATASIZE; 149 break; 150 } 151 if (size == 0) 152 return maxsize; 153 154 /* Check whether the value is within the upper max limit */ 155 return (size > maxsize ? (u_int)maxsize : (u_int)size); 156 } 157 158 /* 159 * Find the appropriate address buffer size 160 */ 161 u_int 162 __rpc_get_a_size(af) 163 int af; 164 { 165 switch (af) { 166 case AF_INET: 167 return sizeof (struct sockaddr_in); 168 #ifdef INET6 169 case AF_INET6: 170 return sizeof (struct sockaddr_in6); 171 #endif 172 case AF_LOCAL: 173 return sizeof (struct sockaddr_un); 174 default: 175 break; 176 } 177 return ((u_int)RPC_MAXADDRSIZE); 178 } 179 180 #if 0 181 static char * 182 strlocase(p) 183 char *p; 184 { 185 char *t = p; 186 187 _DIAGASSERT(p != NULL); 188 189 for (; *p; p++) 190 if (isupper(*p)) 191 *p = tolower(*p); 192 return (t); 193 } 194 #endif 195 196 /* 197 * Returns the type of the network as defined in <rpc/nettype.h> 198 * If nettype is NULL, it defaults to NETPATH. 199 */ 200 static int 201 getnettype(nettype) 202 const char *nettype; 203 { 204 int i; 205 206 if ((nettype == NULL) || (nettype[0] == NULL)) { 207 return (_RPC_NETPATH); /* Default */ 208 } 209 210 #if 0 211 nettype = strlocase(nettype); 212 #endif 213 for (i = 0; _rpctypelist[i].name; i++) 214 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 215 return (_rpctypelist[i].type); 216 } 217 return (_rpctypelist[i].type); 218 } 219 220 /* 221 * For the given nettype (tcp or udp only), return the first structure found. 222 * This should be freed by calling freenetconfigent() 223 */ 224 225 #ifdef _REENTRANT 226 static thread_key_t tcp_key, udp_key; 227 static once_t __rpc_getconfigp_once = ONCE_INITIALIZER; 228 229 static void 230 __rpc_getconfigp_setup(void) 231 { 232 233 thr_keycreate(&tcp_key, free); 234 thr_keycreate(&udp_key, free); 235 } 236 #endif 237 238 struct netconfig * 239 __rpc_getconfip(nettype) 240 const char *nettype; 241 { 242 char *netid; 243 char *netid_tcp = (char *) NULL; 244 char *netid_udp = (char *) NULL; 245 static char *netid_tcp_main; 246 static char *netid_udp_main; 247 struct netconfig *dummy; 248 #ifdef _REENTRANT 249 extern int __isthreaded; 250 251 if (__isthreaded == 0) { 252 netid_udp = netid_udp_main; 253 netid_tcp = netid_tcp_main; 254 } else { 255 thr_once(&__rpc_getconfigp_once, __rpc_getconfigp_setup); 256 netid_tcp = thr_getspecific(tcp_key); 257 netid_udp = thr_getspecific(udp_key); 258 } 259 #else 260 netid_udp = netid_udp_main; 261 netid_tcp = netid_tcp_main; 262 #endif 263 264 _DIAGASSERT(nettype != NULL); 265 266 if (!netid_udp && !netid_tcp) { 267 struct netconfig *nconf; 268 void *confighandle; 269 270 if (!(confighandle = setnetconfig())) { 271 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 272 return (NULL); 273 } 274 while ((nconf = getnetconfig(confighandle)) != NULL) { 275 if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 276 if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 277 netid_tcp = strdup(nconf->nc_netid); 278 #ifdef _REENTRANT 279 if (__isthreaded == 0) 280 netid_tcp_main = netid_tcp; 281 else 282 thr_setspecific(tcp_key, 283 (void *) netid_tcp); 284 #else 285 netid_tcp_main = netid_tcp; 286 #endif 287 } else 288 if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 289 netid_udp = strdup(nconf->nc_netid); 290 #ifdef _REENTRANT 291 if (__isthreaded == 0) 292 netid_udp_main = netid_udp; 293 else 294 thr_setspecific(udp_key, 295 (void *) netid_udp); 296 #else 297 netid_udp_main = netid_udp; 298 #endif 299 } 300 } 301 } 302 endnetconfig(confighandle); 303 } 304 if (strcmp(nettype, "udp") == 0) 305 netid = netid_udp; 306 else if (strcmp(nettype, "tcp") == 0) 307 netid = netid_tcp; 308 else { 309 return (NULL); 310 } 311 if ((netid == NULL) || (netid[0] == NULL)) { 312 return (NULL); 313 } 314 dummy = getnetconfigent(netid); 315 return (dummy); 316 } 317 318 /* 319 * Returns the type of the nettype, which should then be used with 320 * __rpc_getconf(). 321 */ 322 void * 323 __rpc_setconf(nettype) 324 const char *nettype; 325 { 326 struct handle *handle; 327 328 /* nettype may be NULL; getnettype() supports that */ 329 330 handle = (struct handle *) malloc(sizeof (struct handle)); 331 if (handle == NULL) { 332 return (NULL); 333 } 334 switch (handle->nettype = getnettype(nettype)) { 335 case _RPC_NETPATH: 336 case _RPC_CIRCUIT_N: 337 case _RPC_DATAGRAM_N: 338 if (!(handle->nhandle = setnetpath())) { 339 free(handle); 340 return (NULL); 341 } 342 handle->nflag = TRUE; 343 break; 344 case _RPC_VISIBLE: 345 case _RPC_CIRCUIT_V: 346 case _RPC_DATAGRAM_V: 347 case _RPC_TCP: 348 case _RPC_UDP: 349 if (!(handle->nhandle = setnetconfig())) { 350 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 351 free(handle); 352 return (NULL); 353 } 354 handle->nflag = FALSE; 355 break; 356 default: 357 return (NULL); 358 } 359 360 return (handle); 361 } 362 363 /* 364 * Returns the next netconfig struct for the given "net" type. 365 * __rpc_setconf() should have been called previously. 366 */ 367 struct netconfig * 368 __rpc_getconf(vhandle) 369 void *vhandle; 370 { 371 struct handle *handle; 372 struct netconfig *nconf; 373 374 handle = (struct handle *)vhandle; 375 if (handle == NULL) { 376 return (NULL); 377 } 378 for (;;) { 379 if (handle->nflag) 380 nconf = getnetpath(handle->nhandle); 381 else 382 nconf = getnetconfig(handle->nhandle); 383 if (nconf == NULL) 384 break; 385 if ((nconf->nc_semantics != NC_TPI_CLTS) && 386 (nconf->nc_semantics != NC_TPI_COTS) && 387 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 388 continue; 389 switch (handle->nettype) { 390 case _RPC_VISIBLE: 391 if (!(nconf->nc_flag & NC_VISIBLE)) 392 continue; 393 /* FALLTHROUGH */ 394 case _RPC_NETPATH: /* Be happy */ 395 break; 396 case _RPC_CIRCUIT_V: 397 if (!(nconf->nc_flag & NC_VISIBLE)) 398 continue; 399 /* FALLTHROUGH */ 400 case _RPC_CIRCUIT_N: 401 if ((nconf->nc_semantics != NC_TPI_COTS) && 402 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 403 continue; 404 break; 405 case _RPC_DATAGRAM_V: 406 if (!(nconf->nc_flag & NC_VISIBLE)) 407 continue; 408 /* FALLTHROUGH */ 409 case _RPC_DATAGRAM_N: 410 if (nconf->nc_semantics != NC_TPI_CLTS) 411 continue; 412 break; 413 case _RPC_TCP: 414 if (((nconf->nc_semantics != NC_TPI_COTS) && 415 (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 416 (strcmp(nconf->nc_protofmly, NC_INET) 417 #ifdef INET6 418 && strcmp(nconf->nc_protofmly, NC_INET6)) 419 #else 420 ) 421 #endif 422 || 423 strcmp(nconf->nc_proto, NC_TCP)) 424 continue; 425 break; 426 case _RPC_UDP: 427 if ((nconf->nc_semantics != NC_TPI_CLTS) || 428 (strcmp(nconf->nc_protofmly, NC_INET) 429 #ifdef INET6 430 && strcmp(nconf->nc_protofmly, NC_INET6)) 431 #else 432 ) 433 #endif 434 || 435 strcmp(nconf->nc_proto, NC_UDP)) 436 continue; 437 break; 438 } 439 break; 440 } 441 return (nconf); 442 } 443 444 void 445 __rpc_endconf(vhandle) 446 void * vhandle; 447 { 448 struct handle *handle; 449 450 handle = (struct handle *) vhandle; 451 if (handle == NULL) { 452 return; 453 } 454 if (handle->nflag) { 455 endnetpath(handle->nhandle); 456 } else { 457 endnetconfig(handle->nhandle); 458 } 459 free(handle); 460 } 461 462 /* 463 * Used to ping the NULL procedure for clnt handle. 464 * Returns NULL if fails, else a non-NULL pointer. 465 */ 466 void * 467 rpc_nullproc(clnt) 468 CLIENT *clnt; 469 { 470 struct timeval TIMEOUT = {25, 0}; 471 472 if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 473 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 474 return (NULL); 475 } 476 return ((void *) clnt); 477 } 478 479 /* 480 * Try all possible transports until 481 * one succeeds in finding the netconf for the given fd. 482 */ 483 struct netconfig * 484 __rpcgettp(fd) 485 int fd; 486 { 487 const char *netid; 488 struct __rpc_sockinfo si; 489 490 if (!__rpc_fd2sockinfo(fd, &si)) 491 return NULL; 492 493 if (!__rpc_sockinfo2netid(&si, &netid)) 494 return NULL; 495 496 /*LINTED const castaway*/ 497 return getnetconfigent((char *)netid); 498 } 499 500 int 501 __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) 502 { 503 socklen_t len; 504 int type, proto; 505 struct sockaddr_storage ss; 506 507 _DIAGASSERT(sip != NULL); 508 509 len = sizeof ss; 510 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0) 511 return 0; 512 sip->si_alen = len; 513 514 len = sizeof type; 515 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) 516 return 0; 517 518 /* XXX */ 519 if (ss.ss_family != AF_LOCAL) { 520 if (type == SOCK_STREAM) 521 proto = IPPROTO_TCP; 522 else if (type == SOCK_DGRAM) 523 proto = IPPROTO_UDP; 524 else 525 return 0; 526 } else 527 proto = 0; 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 size_t i; 543 544 _DIAGASSERT(nconf != NULL); 545 _DIAGASSERT(sip != NULL); 546 547 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 548 if (!strcmp(na_cvt[i].netid, nconf->nc_netid)) { 549 sip->si_af = na_cvt[i].af; 550 sip->si_proto = na_cvt[i].protocol; 551 sip->si_socktype = 552 __rpc_seman2socktype((int)nconf->nc_semantics); 553 if (sip->si_socktype == -1) 554 return 0; 555 sip->si_alen = __rpc_get_a_size(sip->si_af); 556 return 1; 557 } 558 559 return 0; 560 } 561 562 int 563 __rpc_nconf2fd(const struct netconfig *nconf) 564 { 565 struct __rpc_sockinfo si; 566 567 _DIAGASSERT(nconf != NULL); 568 569 if (!__rpc_nconf2sockinfo(nconf, &si)) 570 return 0; 571 572 return socket(si.si_af, si.si_socktype, si.si_proto); 573 } 574 575 int 576 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) 577 { 578 size_t i; 579 580 _DIAGASSERT(sip != NULL); 581 /* netid may be NULL */ 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 (netid) 587 *netid = na_cvt[i].netid; 588 return 1; 589 } 590 591 return 0; 592 } 593 594 char * 595 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 596 { 597 struct __rpc_sockinfo si; 598 599 _DIAGASSERT(nconf != NULL); 600 _DIAGASSERT(nbuf != NULL); 601 602 if (!__rpc_nconf2sockinfo(nconf, &si)) 603 return NULL; 604 return __rpc_taddr2uaddr_af(si.si_af, nbuf); 605 } 606 607 struct netbuf * 608 uaddr2taddr(const struct netconfig *nconf, const char *uaddr) 609 { 610 struct __rpc_sockinfo si; 611 612 _DIAGASSERT(nconf != NULL); 613 _DIAGASSERT(uaddr != NULL); 614 615 if (!__rpc_nconf2sockinfo(nconf, &si)) 616 return NULL; 617 return __rpc_uaddr2taddr_af(si.si_af, uaddr); 618 } 619 620 char * 621 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 622 { 623 char *ret; 624 struct sockaddr_in *sinp; 625 struct sockaddr_un *sun; 626 char namebuf[INET_ADDRSTRLEN]; 627 #ifdef INET6 628 struct sockaddr_in6 *sin6; 629 char namebuf6[INET6_ADDRSTRLEN]; 630 #endif 631 u_int16_t port; 632 633 _DIAGASSERT(nbuf != NULL); 634 635 switch (af) { 636 case AF_INET: 637 sinp = nbuf->buf; 638 if (inet_ntop(af, &sinp->sin_addr, namebuf, sizeof namebuf) 639 == NULL) 640 return NULL; 641 port = ntohs(sinp->sin_port); 642 if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8, 643 port & 0xff) < 0) 644 return NULL; 645 break; 646 #ifdef INET6 647 case AF_INET6: 648 sin6 = nbuf->buf; 649 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 650 == NULL) 651 return NULL; 652 port = ntohs(sin6->sin6_port); 653 if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8, 654 port & 0xff) < 0) 655 return NULL; 656 break; 657 #endif 658 case AF_LOCAL: 659 sun = nbuf->buf; 660 sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */ 661 ret = strdup(sun->sun_path); 662 break; 663 default: 664 return NULL; 665 } 666 667 return ret; 668 } 669 670 struct netbuf * 671 __rpc_uaddr2taddr_af(int af, const char *uaddr) 672 { 673 struct netbuf *ret = NULL; 674 char *addrstr, *p; 675 unsigned port, portlo, porthi; 676 struct sockaddr_in *sinp; 677 #ifdef INET6 678 struct sockaddr_in6 *sin6; 679 #endif 680 struct sockaddr_un *sun; 681 682 _DIAGASSERT(uaddr != NULL); 683 684 addrstr = strdup(uaddr); 685 if (addrstr == NULL) 686 return NULL; 687 688 /* 689 * AF_LOCAL addresses are expected to be absolute 690 * pathnames, anything else will be AF_INET or AF_INET6. 691 */ 692 if (*addrstr != '/') { 693 p = strrchr(addrstr, '.'); 694 if (p == NULL) 695 goto out; 696 portlo = (unsigned)atoi(p + 1); 697 *p = '\0'; 698 699 p = strrchr(addrstr, '.'); 700 if (p == NULL) 701 goto out; 702 porthi = (unsigned)atoi(p + 1); 703 *p = '\0'; 704 port = (porthi << 8) | portlo; 705 } 706 707 ret = (struct netbuf *)malloc(sizeof *ret); 708 if (ret == NULL) 709 goto out; 710 711 switch (af) { 712 case AF_INET: 713 sinp = (struct sockaddr_in *)malloc(sizeof *sinp); 714 if (sinp == NULL) 715 goto out; 716 memset(sinp, 0, sizeof *sinp); 717 sinp->sin_family = AF_INET; 718 sinp->sin_port = htons(port); 719 if (inet_pton(AF_INET, addrstr, &sinp->sin_addr) <= 0) { 720 free(sinp); 721 free(ret); 722 ret = NULL; 723 goto out; 724 } 725 sinp->sin_len = ret->maxlen = ret->len = sizeof *sinp; 726 ret->buf = sinp; 727 break; 728 #ifdef INET6 729 case AF_INET6: 730 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6); 731 if (sin6 == NULL) 732 goto out; 733 memset(sin6, 0, sizeof *sin6); 734 sin6->sin6_family = AF_INET6; 735 sin6->sin6_port = htons(port); 736 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 737 free(sin6); 738 free(ret); 739 ret = NULL; 740 goto out; 741 } 742 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 743 ret->buf = sin6; 744 break; 745 #endif 746 case AF_LOCAL: 747 sun = (struct sockaddr_un *)malloc(sizeof *sun); 748 if (sun == NULL) 749 goto out; 750 memset(sun, 0, sizeof *sun); 751 sun->sun_family = AF_LOCAL; 752 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 753 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 754 ret->buf = sun; 755 break; 756 default: 757 break; 758 } 759 out: 760 free(addrstr); 761 return ret; 762 } 763 764 int 765 __rpc_seman2socktype(int semantics) 766 { 767 switch (semantics) { 768 case NC_TPI_CLTS: 769 return SOCK_DGRAM; 770 case NC_TPI_COTS_ORD: 771 return SOCK_STREAM; 772 case NC_TPI_RAW: 773 return SOCK_RAW; 774 default: 775 break; 776 } 777 778 return -1; 779 } 780 781 int 782 __rpc_socktype2seman(int socktype) 783 { 784 switch (socktype) { 785 case SOCK_DGRAM: 786 return NC_TPI_CLTS; 787 case SOCK_STREAM: 788 return NC_TPI_COTS_ORD; 789 case SOCK_RAW: 790 return NC_TPI_RAW; 791 default: 792 break; 793 } 794 795 return -1; 796 } 797 798 /* 799 * XXXX - IPv6 scope IDs can't be handled in universal addresses. 800 * Here, we compare the original server address to that of the RPC 801 * service we just received back from a call to rpcbind on the remote 802 * machine. If they are both "link local" or "site local", copy 803 * the scope id of the server address over to the service address. 804 */ 805 int 806 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 807 { 808 #ifdef INET6 809 struct sockaddr *sa_new, *sa_svc; 810 struct sockaddr_in6 *sin6_new, *sin6_svc; 811 812 _DIAGASSERT(new != NULL); 813 _DIAGASSERT(svc != NULL); 814 815 sa_svc = (struct sockaddr *)svc->buf; 816 sa_new = (struct sockaddr *)new->buf; 817 818 if (sa_new->sa_family == sa_svc->sa_family && 819 sa_new->sa_family == AF_INET6) { 820 sin6_new = (struct sockaddr_in6 *)new->buf; 821 sin6_svc = (struct sockaddr_in6 *)svc->buf; 822 823 if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 824 IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 825 (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 826 IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 827 sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 828 } 829 } 830 #endif 831 return 1; 832 } 833 834 int 835 __rpc_sockisbound(int fd) 836 { 837 struct sockaddr_storage ss; 838 socklen_t slen; 839 840 slen = sizeof (struct sockaddr_storage); 841 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 842 return 0; 843 844 switch (ss.ss_family) { 845 case AF_INET: 846 return (((struct sockaddr_in *) 847 (void *)&ss)->sin_port != 0); 848 #ifdef INET6 849 case AF_INET6: 850 return (((struct sockaddr_in6 *) 851 (void *)&ss)->sin6_port != 0); 852 #endif 853 case AF_LOCAL: 854 /* XXX check this */ 855 return (((struct sockaddr_un *) 856 (void *)&ss)->sun_path[0] != '\0'); 857 default: 858 break; 859 } 860 861 return 0; 862 } 863