1 /* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */ 2 3 /*- 4 * Copyright (c) 2009, Sun Microsystems, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * - Neither the name of Sun Microsystems, Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 /* 31 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 32 */ 33 34 /* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */ 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 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 #include "mt_misc.h" 66 67 struct handle { 68 NCONF_HANDLE *nhandle; 69 int nflag; /* Whether NETPATH or NETCONFIG */ 70 int nettype; 71 }; 72 73 static const struct _rpcnettype { 74 const char *name; 75 const int type; 76 } _rpctypelist[] = { 77 { "netpath", _RPC_NETPATH }, 78 { "visible", _RPC_VISIBLE }, 79 { "circuit_v", _RPC_CIRCUIT_V }, 80 { "datagram_v", _RPC_DATAGRAM_V }, 81 { "circuit_n", _RPC_CIRCUIT_N }, 82 { "datagram_n", _RPC_DATAGRAM_N }, 83 { "tcp", _RPC_TCP }, 84 { "udp", _RPC_UDP }, 85 { 0, _RPC_NONE } 86 }; 87 88 struct netid_af { 89 const char *netid; 90 int af; 91 int protocol; 92 }; 93 94 static const struct netid_af na_cvt[] = { 95 { "udp", AF_INET, IPPROTO_UDP }, 96 { "tcp", AF_INET, IPPROTO_TCP }, 97 #ifdef INET6 98 { "udp6", AF_INET6, IPPROTO_UDP }, 99 { "tcp6", AF_INET6, IPPROTO_TCP }, 100 #endif 101 { "local", AF_LOCAL, 0 } 102 }; 103 104 #if 0 105 static char *strlocase(char *); 106 #endif 107 static int getnettype(const char *); 108 109 /* 110 * Cache the result of getrlimit(), so we don't have to do an 111 * expensive call every time. 112 */ 113 int 114 __rpc_dtbsize(void) 115 { 116 static int tbsize; 117 struct rlimit rl; 118 119 if (tbsize) { 120 return (tbsize); 121 } 122 if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 123 return (tbsize = (int)rl.rlim_max); 124 } 125 /* 126 * Something wrong. I'll try to save face by returning a 127 * pessimistic number. 128 */ 129 return (32); 130 } 131 132 133 /* 134 * Find the appropriate buffer size 135 * 136 * size - Size requested 137 */ 138 u_int 139 /*ARGSUSED*/ 140 __rpc_get_t_size(int af, int proto, int size) 141 { 142 int maxsize, defsize; 143 144 maxsize = 256 * 1024; /* XXX */ 145 switch (proto) { 146 case IPPROTO_TCP: 147 defsize = 64 * 1024; /* XXX */ 148 break; 149 case IPPROTO_UDP: 150 defsize = UDPMSGSIZE; 151 break; 152 default: 153 defsize = RPC_MAXDATASIZE; 154 break; 155 } 156 if (size == 0) 157 return defsize; 158 159 /* Check whether the value is within the upper max limit */ 160 return (size > maxsize ? (u_int)maxsize : (u_int)size); 161 } 162 163 /* 164 * Find the appropriate address buffer size 165 */ 166 u_int 167 __rpc_get_a_size(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(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(const char *nettype) 203 { 204 int i; 205 206 if ((nettype == NULL) || (nettype[0] == 0)) { 207 return (_RPC_NETPATH); /* Default */ 208 } 209 210 #if 0 211 nettype = strlocase(nettype); 212 #endif 213 for (i = 0; _rpctypelist[i].name; i++) 214 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 215 return (_rpctypelist[i].type); 216 } 217 return (_rpctypelist[i].type); 218 } 219 220 static thread_key_t tcp_key, udp_key; 221 static once_t keys_once = ONCE_INITIALIZER; 222 static int tcp_key_error, udp_key_error; 223 224 static void 225 keys_init(void) 226 { 227 228 tcp_key_error = thr_keycreate(&tcp_key, free); 229 udp_key_error = thr_keycreate(&udp_key, free); 230 } 231 232 /* 233 * For the given nettype (tcp or udp only), return the first structure found. 234 * This should be freed by calling freenetconfigent() 235 */ 236 struct netconfig * 237 __rpc_getconfip(const char *nettype) 238 { 239 char *netid; 240 char *netid_tcp = (char *) NULL; 241 char *netid_udp = (char *) NULL; 242 static char *netid_tcp_main; 243 static char *netid_udp_main; 244 struct netconfig *dummy; 245 int main_thread; 246 247 if ((main_thread = thr_main())) { 248 netid_udp = netid_udp_main; 249 netid_tcp = netid_tcp_main; 250 } else { 251 if (thr_once(&keys_once, keys_init) != 0 || 252 tcp_key_error != 0 || udp_key_error != 0) 253 return (NULL); 254 netid_tcp = (char *)thr_getspecific(tcp_key); 255 netid_udp = (char *)thr_getspecific(udp_key); 256 } 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 == NULL) { 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 == NULL) { 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] == 0)) { 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(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 goto failed; 322 handle->nflag = TRUE; 323 break; 324 case _RPC_VISIBLE: 325 case _RPC_CIRCUIT_V: 326 case _RPC_DATAGRAM_V: 327 case _RPC_TCP: 328 case _RPC_UDP: 329 if (!(handle->nhandle = setnetconfig())) { 330 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 331 goto failed; 332 } 333 handle->nflag = FALSE; 334 break; 335 default: 336 goto failed; 337 } 338 339 return (handle); 340 341 failed: 342 free(handle); 343 return (NULL); 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(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(void *vhandle) 428 { 429 struct handle *handle; 430 431 handle = (struct handle *) vhandle; 432 if (handle == NULL) { 433 return; 434 } 435 if (handle->nflag) { 436 endnetpath(handle->nhandle); 437 } else { 438 endnetconfig(handle->nhandle); 439 } 440 free(handle); 441 } 442 443 /* 444 * Used to ping the NULL procedure for clnt handle. 445 * Returns NULL if fails, else a non-NULL pointer. 446 */ 447 void * 448 rpc_nullproc(CLIENT *clnt) 449 { 450 struct timeval TIMEOUT = {25, 0}; 451 452 if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 453 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 454 return (NULL); 455 } 456 return ((void *) clnt); 457 } 458 459 /* 460 * Try all possible transports until 461 * one succeeds in finding the netconf for the given fd. 462 */ 463 struct netconfig * 464 __rpcgettp(int fd) 465 { 466 const char *netid; 467 struct __rpc_sockinfo si; 468 469 if (!__rpc_fd2sockinfo(fd, &si)) 470 return NULL; 471 472 if (!__rpc_sockinfo2netid(&si, &netid)) 473 return NULL; 474 475 /*LINTED const castaway*/ 476 return getnetconfigent((char *)netid); 477 } 478 479 int 480 __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) 481 { 482 socklen_t len; 483 int type, proto; 484 struct sockaddr_storage ss; 485 486 len = sizeof ss; 487 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0) 488 return 0; 489 sip->si_alen = len; 490 491 len = sizeof type; 492 if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) 493 return 0; 494 495 /* XXX */ 496 if (ss.ss_family != AF_LOCAL) { 497 if (type == SOCK_STREAM) 498 proto = IPPROTO_TCP; 499 else if (type == SOCK_DGRAM) 500 proto = IPPROTO_UDP; 501 else 502 return 0; 503 } else 504 proto = 0; 505 506 sip->si_af = ss.ss_family; 507 sip->si_proto = proto; 508 sip->si_socktype = type; 509 510 return 1; 511 } 512 513 /* 514 * Linear search, but the number of entries is small. 515 */ 516 int 517 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 518 { 519 int i; 520 521 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 522 if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 523 strcmp(nconf->nc_netid, "unix") == 0 && 524 strcmp(na_cvt[i].netid, "local") == 0)) { 525 sip->si_af = na_cvt[i].af; 526 sip->si_proto = na_cvt[i].protocol; 527 sip->si_socktype = 528 __rpc_seman2socktype((int)nconf->nc_semantics); 529 if (sip->si_socktype == -1) 530 return 0; 531 sip->si_alen = __rpc_get_a_size(sip->si_af); 532 return 1; 533 } 534 535 return 0; 536 } 537 538 int 539 __rpc_nconf2fd(const struct netconfig *nconf) 540 { 541 struct __rpc_sockinfo si; 542 543 if (!__rpc_nconf2sockinfo(nconf, &si)) 544 return 0; 545 546 return _socket(si.si_af, si.si_socktype, si.si_proto); 547 } 548 549 int 550 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) 551 { 552 int i; 553 struct netconfig *nconf; 554 555 nconf = getnetconfigent("local"); 556 557 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) { 558 if (na_cvt[i].af == sip->si_af && 559 na_cvt[i].protocol == sip->si_proto) { 560 if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) { 561 if (netid) 562 *netid = "unix"; 563 } else { 564 if (netid) 565 *netid = na_cvt[i].netid; 566 } 567 if (nconf != NULL) 568 freenetconfigent(nconf); 569 return 1; 570 } 571 } 572 if (nconf != NULL) 573 freenetconfigent(nconf); 574 575 return 0; 576 } 577 578 char * 579 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 580 { 581 struct __rpc_sockinfo si; 582 583 if (!__rpc_nconf2sockinfo(nconf, &si)) 584 return NULL; 585 return __rpc_taddr2uaddr_af(si.si_af, nbuf); 586 } 587 588 struct netbuf * 589 uaddr2taddr(const struct netconfig *nconf, const char *uaddr) 590 { 591 struct __rpc_sockinfo si; 592 593 if (!__rpc_nconf2sockinfo(nconf, &si)) 594 return NULL; 595 return __rpc_uaddr2taddr_af(si.si_af, uaddr); 596 } 597 598 char * 599 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 600 { 601 char *ret; 602 struct sockaddr_in *sin; 603 struct sockaddr_un *sun; 604 char namebuf[INET_ADDRSTRLEN]; 605 #ifdef INET6 606 struct sockaddr_in6 *sin6; 607 char namebuf6[INET6_ADDRSTRLEN]; 608 #endif 609 u_int16_t port; 610 611 switch (af) { 612 case AF_INET: 613 sin = nbuf->buf; 614 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 615 == NULL) 616 return NULL; 617 port = ntohs(sin->sin_port); 618 if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8, 619 port & 0xff) < 0) 620 return NULL; 621 break; 622 #ifdef INET6 623 case AF_INET6: 624 sin6 = nbuf->buf; 625 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 626 == NULL) 627 return NULL; 628 port = ntohs(sin6->sin6_port); 629 if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8, 630 port & 0xff) < 0) 631 return NULL; 632 break; 633 #endif 634 case AF_LOCAL: 635 sun = nbuf->buf; 636 if (asprintf(&ret, "%.*s", (int)(sun->sun_len - 637 offsetof(struct sockaddr_un, sun_path)), 638 sun->sun_path) < 0) 639 return (NULL); 640 break; 641 default: 642 return NULL; 643 } 644 645 return ret; 646 } 647 648 struct netbuf * 649 __rpc_uaddr2taddr_af(int af, const char *uaddr) 650 { 651 struct netbuf *ret = NULL; 652 char *addrstr, *p; 653 unsigned port, portlo, porthi; 654 struct sockaddr_in *sin; 655 #ifdef INET6 656 struct sockaddr_in6 *sin6; 657 #endif 658 struct sockaddr_un *sun; 659 660 port = 0; 661 sin = NULL; 662 addrstr = strdup(uaddr); 663 if (addrstr == NULL) 664 return NULL; 665 666 /* 667 * AF_LOCAL addresses are expected to be absolute 668 * pathnames, anything else will be AF_INET or AF_INET6. 669 */ 670 if (*addrstr != '/') { 671 p = strrchr(addrstr, '.'); 672 if (p == NULL) 673 goto out; 674 portlo = (unsigned)atoi(p + 1); 675 *p = '\0'; 676 677 p = strrchr(addrstr, '.'); 678 if (p == NULL) 679 goto out; 680 porthi = (unsigned)atoi(p + 1); 681 *p = '\0'; 682 port = (porthi << 8) | portlo; 683 } 684 685 ret = (struct netbuf *)malloc(sizeof *ret); 686 if (ret == NULL) 687 goto out; 688 689 switch (af) { 690 case AF_INET: 691 sin = (struct sockaddr_in *)malloc(sizeof *sin); 692 if (sin == NULL) 693 goto out; 694 memset(sin, 0, sizeof *sin); 695 sin->sin_family = AF_INET; 696 sin->sin_port = htons(port); 697 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 698 free(sin); 699 free(ret); 700 ret = NULL; 701 goto out; 702 } 703 sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 704 ret->buf = sin; 705 break; 706 #ifdef INET6 707 case AF_INET6: 708 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6); 709 if (sin6 == NULL) 710 goto out; 711 memset(sin6, 0, sizeof *sin6); 712 sin6->sin6_family = AF_INET6; 713 sin6->sin6_port = htons(port); 714 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 715 free(sin6); 716 free(ret); 717 ret = NULL; 718 goto out; 719 } 720 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 721 ret->buf = sin6; 722 break; 723 #endif 724 case AF_LOCAL: 725 sun = (struct sockaddr_un *)malloc(sizeof *sun); 726 if (sun == NULL) 727 goto out; 728 memset(sun, 0, sizeof *sun); 729 sun->sun_family = AF_LOCAL; 730 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 731 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 732 ret->buf = sun; 733 break; 734 default: 735 break; 736 } 737 out: 738 free(addrstr); 739 return ret; 740 } 741 742 int 743 __rpc_seman2socktype(int semantics) 744 { 745 switch (semantics) { 746 case NC_TPI_CLTS: 747 return SOCK_DGRAM; 748 case NC_TPI_COTS_ORD: 749 return SOCK_STREAM; 750 case NC_TPI_RAW: 751 return SOCK_RAW; 752 default: 753 break; 754 } 755 756 return -1; 757 } 758 759 int 760 __rpc_socktype2seman(int socktype) 761 { 762 switch (socktype) { 763 case SOCK_DGRAM: 764 return NC_TPI_CLTS; 765 case SOCK_STREAM: 766 return NC_TPI_COTS_ORD; 767 case SOCK_RAW: 768 return NC_TPI_RAW; 769 default: 770 break; 771 } 772 773 return -1; 774 } 775 776 /* 777 * XXXX - IPv6 scope IDs can't be handled in universal addresses. 778 * Here, we compare the original server address to that of the RPC 779 * service we just received back from a call to rpcbind on the remote 780 * machine. If they are both "link local" or "site local", copy 781 * the scope id of the server address over to the service address. 782 */ 783 int 784 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 785 { 786 #ifdef INET6 787 struct sockaddr *sa_new, *sa_svc; 788 struct sockaddr_in6 *sin6_new, *sin6_svc; 789 790 sa_svc = (struct sockaddr *)svc->buf; 791 sa_new = (struct sockaddr *)new->buf; 792 793 if (sa_new->sa_family == sa_svc->sa_family && 794 sa_new->sa_family == AF_INET6) { 795 sin6_new = (struct sockaddr_in6 *)new->buf; 796 sin6_svc = (struct sockaddr_in6 *)svc->buf; 797 798 if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 799 IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 800 (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 801 IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 802 sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 803 } 804 } 805 #endif 806 return 1; 807 } 808 809 int 810 __rpc_sockisbound(int fd) 811 { 812 struct sockaddr_storage ss; 813 socklen_t slen; 814 815 slen = sizeof (struct sockaddr_storage); 816 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 817 return 0; 818 819 switch (ss.ss_family) { 820 case AF_INET: 821 return (((struct sockaddr_in *) 822 (void *)&ss)->sin_port != 0); 823 #ifdef INET6 824 case AF_INET6: 825 return (((struct sockaddr_in6 *) 826 (void *)&ss)->sin6_port != 0); 827 #endif 828 case AF_LOCAL: 829 /* XXX check this */ 830 return (((struct sockaddr_un *) 831 (void *)&ss)->sun_path[0] != '\0'); 832 default: 833 break; 834 } 835 836 return 0; 837 } 838