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