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