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 /* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */ 37 /* 38 * rpc_generic.c, Miscl routines for RPC. 39 * 40 */ 41 42 #include "namespace.h" 43 #include "reentrant.h" 44 #include <sys/param.h> 45 #include <sys/socket.h> 46 #include <sys/time.h> 47 #include <sys/un.h> 48 #include <sys/resource.h> 49 #include <netinet/in.h> 50 #include <arpa/inet.h> 51 #include <rpc/rpc.h> 52 #include <ctype.h> 53 #include <stddef.h> 54 #include <stdio.h> 55 #include <netdb.h> 56 #include <netconfig.h> 57 #include <stdlib.h> 58 #include <string.h> 59 #include <syslog.h> 60 #include <rpc/nettype.h> 61 #include "un-namespace.h" 62 #include "rpc_com.h" 63 #include "mt_misc.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 { "local", AF_LOCAL, 0 } 100 }; 101 102 #if 0 103 static char *strlocase(char *); 104 #endif 105 static int getnettype(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(void) 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 * size - Size requested 135 */ 136 u_int 137 /*ARGSUSED*/ 138 __rpc_get_t_size(int af, int proto, int size) 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(int af) 166 { 167 switch (af) { 168 case AF_INET: 169 return sizeof (struct sockaddr_in); 170 #ifdef INET6 171 case AF_INET6: 172 return sizeof (struct sockaddr_in6); 173 #endif 174 case AF_LOCAL: 175 return sizeof (struct sockaddr_un); 176 default: 177 break; 178 } 179 return ((u_int)RPC_MAXADDRSIZE); 180 } 181 182 #if 0 183 static char * 184 strlocase(char *p) 185 { 186 char *t = p; 187 188 for (; *p; p++) 189 if (isupper(*p)) 190 *p = tolower(*p); 191 return (t); 192 } 193 #endif 194 195 /* 196 * Returns the type of the network as defined in <rpc/nettype.h> 197 * If nettype is NULL, it defaults to NETPATH. 198 */ 199 static int 200 getnettype(const char *nettype) 201 { 202 int i; 203 204 if ((nettype == NULL) || (nettype[0] == 0)) { 205 return (_RPC_NETPATH); /* Default */ 206 } 207 208 #if 0 209 nettype = strlocase(nettype); 210 #endif 211 for (i = 0; _rpctypelist[i].name; i++) 212 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 213 return (_rpctypelist[i].type); 214 } 215 return (_rpctypelist[i].type); 216 } 217 218 static thread_key_t tcp_key, udp_key; 219 static once_t keys_once = ONCE_INITIALIZER; 220 static int tcp_key_error, udp_key_error; 221 222 static void 223 keys_init(void) 224 { 225 226 tcp_key_error = thr_keycreate(&tcp_key, free); 227 udp_key_error = thr_keycreate(&udp_key, free); 228 } 229 230 /* 231 * For the given nettype (tcp or udp only), return the first structure found. 232 * This should be freed by calling freenetconfigent() 233 */ 234 struct netconfig * 235 __rpc_getconfip(const char *nettype) 236 { 237 char *netid; 238 char *netid_tcp = (char *) NULL; 239 char *netid_udp = (char *) NULL; 240 static char *netid_tcp_main; 241 static char *netid_udp_main; 242 struct netconfig *dummy; 243 int main_thread; 244 245 if ((main_thread = thr_main())) { 246 netid_udp = netid_udp_main; 247 netid_tcp = netid_tcp_main; 248 } else { 249 if (thr_once(&keys_once, keys_init) != 0 || 250 tcp_key_error != 0 || udp_key_error != 0) 251 return (NULL); 252 netid_tcp = (char *)thr_getspecific(tcp_key); 253 netid_udp = (char *)thr_getspecific(udp_key); 254 } 255 if (!netid_udp && !netid_tcp) { 256 struct netconfig *nconf; 257 void *confighandle; 258 259 if (!(confighandle = setnetconfig())) { 260 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 261 return (NULL); 262 } 263 while ((nconf = getnetconfig(confighandle)) != NULL) { 264 if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 265 if (strcmp(nconf->nc_proto, NC_TCP) == 0 && 266 netid_tcp == NULL) { 267 netid_tcp = strdup(nconf->nc_netid); 268 if (main_thread) 269 netid_tcp_main = netid_tcp; 270 else 271 thr_setspecific(tcp_key, 272 (void *) netid_tcp); 273 } else 274 if (strcmp(nconf->nc_proto, NC_UDP) == 0 && 275 netid_udp == NULL) { 276 netid_udp = strdup(nconf->nc_netid); 277 if (main_thread) 278 netid_udp_main = netid_udp; 279 else 280 thr_setspecific(udp_key, 281 (void *) netid_udp); 282 } 283 } 284 } 285 endnetconfig(confighandle); 286 } 287 if (strcmp(nettype, "udp") == 0) 288 netid = netid_udp; 289 else if (strcmp(nettype, "tcp") == 0) 290 netid = netid_tcp; 291 else { 292 return (NULL); 293 } 294 if ((netid == NULL) || (netid[0] == 0)) { 295 return (NULL); 296 } 297 dummy = getnetconfigent(netid); 298 return (dummy); 299 } 300 301 /* 302 * Returns the type of the nettype, which should then be used with 303 * __rpc_getconf(). 304 */ 305 void * 306 __rpc_setconf(const char *nettype) 307 { 308 struct handle *handle; 309 310 handle = (struct handle *) malloc(sizeof (struct handle)); 311 if (handle == NULL) { 312 return (NULL); 313 } 314 switch (handle->nettype = getnettype(nettype)) { 315 case _RPC_NETPATH: 316 case _RPC_CIRCUIT_N: 317 case _RPC_DATAGRAM_N: 318 if (!(handle->nhandle = setnetpath())) 319 goto failed; 320 handle->nflag = TRUE; 321 break; 322 case _RPC_VISIBLE: 323 case _RPC_CIRCUIT_V: 324 case _RPC_DATAGRAM_V: 325 case _RPC_TCP: 326 case _RPC_UDP: 327 if (!(handle->nhandle = setnetconfig())) { 328 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 329 goto failed; 330 } 331 handle->nflag = FALSE; 332 break; 333 default: 334 goto failed; 335 } 336 337 return (handle); 338 339 failed: 340 free(handle); 341 return (NULL); 342 } 343 344 /* 345 * Returns the next netconfig struct for the given "net" type. 346 * __rpc_setconf() should have been called previously. 347 */ 348 struct netconfig * 349 __rpc_getconf(void *vhandle) 350 { 351 struct handle *handle; 352 struct netconfig *nconf; 353 354 handle = (struct handle *)vhandle; 355 if (handle == NULL) { 356 return (NULL); 357 } 358 for (;;) { 359 if (handle->nflag) 360 nconf = getnetpath(handle->nhandle); 361 else 362 nconf = getnetconfig(handle->nhandle); 363 if (nconf == NULL) 364 break; 365 if ((nconf->nc_semantics != NC_TPI_CLTS) && 366 (nconf->nc_semantics != NC_TPI_COTS) && 367 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 368 continue; 369 switch (handle->nettype) { 370 case _RPC_VISIBLE: 371 if (!(nconf->nc_flag & NC_VISIBLE)) 372 continue; 373 /* FALLTHROUGH */ 374 case _RPC_NETPATH: /* Be happy */ 375 break; 376 case _RPC_CIRCUIT_V: 377 if (!(nconf->nc_flag & NC_VISIBLE)) 378 continue; 379 /* FALLTHROUGH */ 380 case _RPC_CIRCUIT_N: 381 if ((nconf->nc_semantics != NC_TPI_COTS) && 382 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 383 continue; 384 break; 385 case _RPC_DATAGRAM_V: 386 if (!(nconf->nc_flag & NC_VISIBLE)) 387 continue; 388 /* FALLTHROUGH */ 389 case _RPC_DATAGRAM_N: 390 if (nconf->nc_semantics != NC_TPI_CLTS) 391 continue; 392 break; 393 case _RPC_TCP: 394 if (((nconf->nc_semantics != NC_TPI_COTS) && 395 (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 396 (strcmp(nconf->nc_protofmly, NC_INET) 397 #ifdef INET6 398 && strcmp(nconf->nc_protofmly, NC_INET6)) 399 #else 400 ) 401 #endif 402 || 403 strcmp(nconf->nc_proto, NC_TCP)) 404 continue; 405 break; 406 case _RPC_UDP: 407 if ((nconf->nc_semantics != NC_TPI_CLTS) || 408 (strcmp(nconf->nc_protofmly, NC_INET) 409 #ifdef INET6 410 && strcmp(nconf->nc_protofmly, NC_INET6)) 411 #else 412 ) 413 #endif 414 || 415 strcmp(nconf->nc_proto, NC_UDP)) 416 continue; 417 break; 418 } 419 break; 420 } 421 return (nconf); 422 } 423 424 void 425 __rpc_endconf(void *vhandle) 426 { 427 struct handle *handle; 428 429 handle = (struct handle *) vhandle; 430 if (handle == NULL) { 431 return; 432 } 433 if (handle->nflag) { 434 endnetpath(handle->nhandle); 435 } else { 436 endnetconfig(handle->nhandle); 437 } 438 free(handle); 439 } 440 441 /* 442 * Used to ping the NULL procedure for clnt handle. 443 * Returns NULL if fails, else a non-NULL pointer. 444 */ 445 void * 446 rpc_nullproc(CLIENT *clnt) 447 { 448 struct timeval TIMEOUT = {25, 0}; 449 450 if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 451 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 452 return (NULL); 453 } 454 return ((void *) clnt); 455 } 456 457 /* 458 * Try all possible transports until 459 * one succeeds in finding the netconf for the given fd. 460 */ 461 struct netconfig * 462 __rpcgettp(int fd) 463 { 464 const char *netid; 465 struct __rpc_sockinfo si; 466 467 if (!__rpc_fd2sockinfo(fd, &si)) 468 return NULL; 469 470 if (!__rpc_sockinfo2netid(&si, &netid)) 471 return NULL; 472 473 /*LINTED const castaway*/ 474 return getnetconfigent((char *)netid); 475 } 476 477 int 478 __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) 479 { 480 socklen_t len; 481 int type, proto; 482 struct sockaddr_storage ss; 483 484 len = sizeof ss; 485 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0) 486 return 0; 487 sip->si_alen = len; 488 489 len = sizeof type; 490 if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) 491 return 0; 492 493 /* XXX */ 494 if (ss.ss_family != AF_LOCAL) { 495 if (type == SOCK_STREAM) 496 proto = IPPROTO_TCP; 497 else if (type == SOCK_DGRAM) 498 proto = IPPROTO_UDP; 499 else 500 return 0; 501 } else 502 proto = 0; 503 504 sip->si_af = ss.ss_family; 505 sip->si_proto = proto; 506 sip->si_socktype = type; 507 508 return 1; 509 } 510 511 /* 512 * Linear search, but the number of entries is small. 513 */ 514 int 515 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 516 { 517 int i; 518 519 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 520 if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 521 strcmp(nconf->nc_netid, "unix") == 0 && 522 strcmp(na_cvt[i].netid, "local") == 0)) { 523 sip->si_af = na_cvt[i].af; 524 sip->si_proto = na_cvt[i].protocol; 525 sip->si_socktype = 526 __rpc_seman2socktype((int)nconf->nc_semantics); 527 if (sip->si_socktype == -1) 528 return 0; 529 sip->si_alen = __rpc_get_a_size(sip->si_af); 530 return 1; 531 } 532 533 return 0; 534 } 535 536 int 537 __rpc_nconf2fd(const struct netconfig *nconf) 538 { 539 struct __rpc_sockinfo si; 540 541 if (!__rpc_nconf2sockinfo(nconf, &si)) 542 return 0; 543 544 return _socket(si.si_af, si.si_socktype, si.si_proto); 545 } 546 547 int 548 __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) 549 { 550 int i; 551 struct netconfig *nconf; 552 553 nconf = getnetconfigent("local"); 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 (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) { 559 if (netid) 560 *netid = "unix"; 561 } else { 562 if (netid) 563 *netid = na_cvt[i].netid; 564 } 565 if (nconf != NULL) 566 freenetconfigent(nconf); 567 return 1; 568 } 569 } 570 if (nconf != NULL) 571 freenetconfigent(nconf); 572 573 return 0; 574 } 575 576 char * 577 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 578 { 579 struct __rpc_sockinfo si; 580 581 if (!__rpc_nconf2sockinfo(nconf, &si)) 582 return NULL; 583 return __rpc_taddr2uaddr_af(si.si_af, nbuf); 584 } 585 586 struct netbuf * 587 uaddr2taddr(const struct netconfig *nconf, const char *uaddr) 588 { 589 struct __rpc_sockinfo si; 590 591 if (!__rpc_nconf2sockinfo(nconf, &si)) 592 return NULL; 593 return __rpc_uaddr2taddr_af(si.si_af, uaddr); 594 } 595 596 char * 597 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 598 { 599 char *ret; 600 struct sockaddr_in *sin; 601 struct sockaddr_un *sun; 602 char namebuf[INET_ADDRSTRLEN]; 603 #ifdef INET6 604 struct sockaddr_in6 *sin6; 605 char namebuf6[INET6_ADDRSTRLEN]; 606 #endif 607 u_int16_t port; 608 609 switch (af) { 610 case AF_INET: 611 if (nbuf->len < sizeof(*sin)) 612 return NULL; 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 if (nbuf->len < sizeof(*sin6)) 625 return NULL; 626 sin6 = nbuf->buf; 627 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 628 == NULL) 629 return NULL; 630 port = ntohs(sin6->sin6_port); 631 if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8, 632 port & 0xff) < 0) 633 return NULL; 634 break; 635 #endif 636 case AF_LOCAL: 637 sun = nbuf->buf; 638 if (asprintf(&ret, "%.*s", (int)(sun->sun_len - 639 offsetof(struct sockaddr_un, sun_path)), 640 sun->sun_path) < 0) 641 return (NULL); 642 break; 643 default: 644 return NULL; 645 } 646 647 return ret; 648 } 649 650 struct netbuf * 651 __rpc_uaddr2taddr_af(int af, const char *uaddr) 652 { 653 struct netbuf *ret = NULL; 654 char *addrstr, *p; 655 unsigned port, portlo, porthi; 656 struct sockaddr_in *sin; 657 #ifdef INET6 658 struct sockaddr_in6 *sin6; 659 #endif 660 struct sockaddr_un *sun; 661 662 port = 0; 663 sin = NULL; 664 665 if (uaddr == NULL) 666 return NULL; 667 668 addrstr = strdup(uaddr); 669 if (addrstr == NULL) 670 return NULL; 671 672 /* 673 * AF_LOCAL addresses are expected to be absolute 674 * pathnames, anything else will be AF_INET or AF_INET6. 675 */ 676 if (*addrstr != '/') { 677 p = strrchr(addrstr, '.'); 678 if (p == NULL) 679 goto out; 680 portlo = (unsigned)atoi(p + 1); 681 *p = '\0'; 682 683 p = strrchr(addrstr, '.'); 684 if (p == NULL) 685 goto out; 686 porthi = (unsigned)atoi(p + 1); 687 *p = '\0'; 688 port = (porthi << 8) | portlo; 689 } 690 691 ret = (struct netbuf *)malloc(sizeof *ret); 692 if (ret == NULL) 693 goto out; 694 695 switch (af) { 696 case AF_INET: 697 sin = (struct sockaddr_in *)malloc(sizeof *sin); 698 if (sin == NULL) 699 goto out; 700 memset(sin, 0, sizeof *sin); 701 sin->sin_family = AF_INET; 702 sin->sin_port = htons(port); 703 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 704 free(sin); 705 free(ret); 706 ret = NULL; 707 goto out; 708 } 709 sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 710 ret->buf = sin; 711 break; 712 #ifdef INET6 713 case AF_INET6: 714 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6); 715 if (sin6 == NULL) 716 goto out; 717 memset(sin6, 0, sizeof *sin6); 718 sin6->sin6_family = AF_INET6; 719 sin6->sin6_port = htons(port); 720 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 721 free(sin6); 722 free(ret); 723 ret = NULL; 724 goto out; 725 } 726 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 727 ret->buf = sin6; 728 break; 729 #endif 730 case AF_LOCAL: 731 sun = (struct sockaddr_un *)malloc(sizeof *sun); 732 if (sun == NULL) 733 goto out; 734 memset(sun, 0, sizeof *sun); 735 sun->sun_family = AF_LOCAL; 736 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 737 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 738 ret->buf = sun; 739 break; 740 default: 741 break; 742 } 743 out: 744 free(addrstr); 745 return ret; 746 } 747 748 int 749 __rpc_seman2socktype(int semantics) 750 { 751 switch (semantics) { 752 case NC_TPI_CLTS: 753 return SOCK_DGRAM; 754 case NC_TPI_COTS_ORD: 755 return SOCK_STREAM; 756 case NC_TPI_RAW: 757 return SOCK_RAW; 758 default: 759 break; 760 } 761 762 return -1; 763 } 764 765 int 766 __rpc_socktype2seman(int socktype) 767 { 768 switch (socktype) { 769 case SOCK_DGRAM: 770 return NC_TPI_CLTS; 771 case SOCK_STREAM: 772 return NC_TPI_COTS_ORD; 773 case SOCK_RAW: 774 return NC_TPI_RAW; 775 default: 776 break; 777 } 778 779 return -1; 780 } 781 782 /* 783 * XXXX - IPv6 scope IDs can't be handled in universal addresses. 784 * Here, we compare the original server address to that of the RPC 785 * service we just received back from a call to rpcbind on the remote 786 * machine. If they are both "link local" or "site local", copy 787 * the scope id of the server address over to the service address. 788 */ 789 int 790 __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 791 { 792 #ifdef INET6 793 struct sockaddr *sa_new, *sa_svc; 794 struct sockaddr_in6 *sin6_new, *sin6_svc; 795 796 sa_svc = (struct sockaddr *)svc->buf; 797 sa_new = (struct sockaddr *)new->buf; 798 799 if (sa_new->sa_family == sa_svc->sa_family && 800 sa_new->sa_family == AF_INET6) { 801 sin6_new = (struct sockaddr_in6 *)new->buf; 802 sin6_svc = (struct sockaddr_in6 *)svc->buf; 803 804 if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 805 IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 806 (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 807 IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 808 sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 809 } 810 } 811 #endif 812 return 1; 813 } 814 815 int 816 __rpc_sockisbound(int fd) 817 { 818 struct sockaddr_storage ss; 819 socklen_t slen; 820 821 slen = sizeof (struct sockaddr_storage); 822 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 823 return 0; 824 825 switch (ss.ss_family) { 826 case AF_INET: 827 return (((struct sockaddr_in *) 828 (void *)&ss)->sin_port != 0); 829 #ifdef INET6 830 case AF_INET6: 831 return (((struct sockaddr_in6 *) 832 (void *)&ss)->sin6_port != 0); 833 #endif 834 case AF_LOCAL: 835 /* XXX check this */ 836 return (((struct sockaddr_un *) 837 (void *)&ss)->sun_path[0] != '\0'); 838 default: 839 break; 840 } 841 842 return 0; 843 } 844