rpc_generic.c revision 76044
1/* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */ 2/* $FreeBSD: head/lib/libc/rpc/rpc_generic.c 76044 2001-04-26 17:24:05Z iedowse $ */ 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 65struct handle { 66 NCONF_HANDLE *nhandle; 67 int nflag; /* Whether NETPATH or NETCONFIG */ 68 int nettype; 69}; 70 71static 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 86struct netid_af { 87 const char *netid; 88 int af; 89 int protocol; 90}; 91 92static 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 103static char *strlocase __P((char *)); 104#endif 105static 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 */ 111int 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 */ 134u_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 */ 164u_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 184static char * 185strlocase(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 */ 201static int 202getnettype(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 */ 225struct 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 */ 306void * 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 */ 349struct 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 426void 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 */ 448void * 449rpc_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 */ 465struct 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 482int 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 */ 519int 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 539int 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 550int 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 566char * 567taddr2uaddr(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 576struct netbuf * 577uaddr2taddr(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 586char * 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 634struct 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 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 714 ret->buf = sun; 715 break; 716 default: 717 break; 718 } 719out: 720 free(addrstr); 721 return ret; 722} 723 724int 725__rpc_seman2socktype(int semantics) 726{ 727 switch (semantics) { 728 case NC_TPI_CLTS: 729 return SOCK_DGRAM; 730 case NC_TPI_COTS_ORD: 731 return SOCK_STREAM; 732 case NC_TPI_RAW: 733 return SOCK_RAW; 734 default: 735 break; 736 } 737 738 return -1; 739} 740 741int 742__rpc_socktype2seman(int socktype) 743{ 744 switch (socktype) { 745 case SOCK_DGRAM: 746 return NC_TPI_CLTS; 747 case SOCK_STREAM: 748 return NC_TPI_COTS_ORD; 749 case SOCK_RAW: 750 return NC_TPI_RAW; 751 default: 752 break; 753 } 754 755 return -1; 756} 757 758/* 759 * XXXX - IPv6 scope IDs can't be handled in universal addresses. 760 * Here, we compare the original server address to that of the RPC 761 * service we just received back from a call to rpcbind on the remote 762 * machine. If they are both "link local" or "site local", copy 763 * the scope id of the server address over to the service address. 764 */ 765int 766__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 767{ 768#ifdef INET6 769 struct sockaddr *sa_new, *sa_svc; 770 struct sockaddr_in6 *sin6_new, *sin6_svc; 771 772 sa_svc = (struct sockaddr *)svc->buf; 773 sa_new = (struct sockaddr *)new->buf; 774 775 if (sa_new->sa_family == sa_svc->sa_family && 776 sa_new->sa_family == AF_INET6) { 777 sin6_new = (struct sockaddr_in6 *)new->buf; 778 sin6_svc = (struct sockaddr_in6 *)svc->buf; 779 780 if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 781 IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 782 (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 783 IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 784 sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 785 } 786 } 787#endif 788 return 1; 789} 790 791int 792__rpc_sockisbound(int fd) 793{ 794 struct sockaddr_storage ss; 795 socklen_t slen; 796 797 slen = sizeof (struct sockaddr_storage); 798 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 799 return 0; 800 801 switch (ss.ss_family) { 802 case AF_INET: 803 return (((struct sockaddr_in *) 804 (void *)&ss)->sin_port != 0); 805#ifdef INET6 806 case AF_INET6: 807 return (((struct sockaddr_in6 *) 808 (void *)&ss)->sin6_port != 0); 809#endif 810 case AF_LOCAL: 811 /* XXX check this */ 812 return (((struct sockaddr_un *) 813 (void *)&ss)->sun_path[0] != '\0'); 814 default: 815 break; 816 } 817 818 return 0; 819} 820