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