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