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