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