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