rpc_generic.c revision 331722
11558Srgrimes/* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */ 21558Srgrimes 31558Srgrimes/*- 41558Srgrimes * Copyright (c) 2009, Sun Microsystems, Inc. 51558Srgrimes * All rights reserved. 61558Srgrimes * 71558Srgrimes * Redistribution and use in source and binary forms, with or without 81558Srgrimes * modification, are permitted provided that the following conditions are met: 91558Srgrimes * - Redistributions of source code must retain the above copyright notice, 101558Srgrimes * this list of conditions and the following disclaimer. 111558Srgrimes * - Redistributions in binary form must reproduce the above copyright notice, 121558Srgrimes * this list of conditions and the following disclaimer in the documentation 131558Srgrimes * and/or other materials provided with the distribution. 141558Srgrimes * - Neither the name of Sun Microsystems, Inc. nor the names of its 151558Srgrimes * contributors may be used to endorse or promote products derived 161558Srgrimes * from this software without specific prior written permission. 171558Srgrimes * 181558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 191558Srgrimes * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 201558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 211558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 221558Srgrimes * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 231558Srgrimes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 241558Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 251558Srgrimes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 261558Srgrimes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 271558Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 281558Srgrimes * POSSIBILITY OF SUCH DAMAGE. 291558Srgrimes */ 301558Srgrimes/* 311558Srgrimes * Copyright (c) 1986-1991 by Sun Microsystems Inc. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes/* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */ 3541477Sjulian#include <sys/cdefs.h> 3623675Speter__FBSDID("$FreeBSD: stable/11/lib/libc/rpc/rpc_generic.c 331722 2018-03-29 02:50:57Z eadler $"); 3741477Sjulian 3841477Sjulian/* 3950476Speter * rpc_generic.c, Miscl routines for RPC. 401558Srgrimes * 411558Srgrimes */ 421558Srgrimes 4323675Speter#include "namespace.h" 441558Srgrimes#include "reentrant.h" 4541474Sjulian#include <sys/param.h> 4623675Speter#include <sys/socket.h> 4723675Speter#include <sys/time.h> 481558Srgrimes#include <sys/un.h> 4923675Speter#include <sys/resource.h> 501558Srgrimes#include <netinet/in.h> 511558Srgrimes#include <arpa/inet.h> 527585Sbde#include <rpc/rpc.h> 5392839Simp#include <ctype.h> 541558Srgrimes#include <stddef.h> 5592806Sobrien#include <stdio.h> 5692806Sobrien#include <netdb.h> 5798542Smckusick#include <netconfig.h> 581558Srgrimes#include <stdlib.h> 5941474Sjulian#include <string.h> 601558Srgrimes#include <syslog.h> 6123675Speter#include <rpc/nettype.h> 621558Srgrimes#include "un-namespace.h" 631558Srgrimes#include "rpc_com.h" 6441474Sjulian#include "mt_misc.h" 6570050Siedowse 6670050Siedowsestruct handle { 6770050Siedowse NCONF_HANDLE *nhandle; 6870050Siedowse int nflag; /* Whether NETPATH or NETCONFIG */ 6970050Siedowse int nettype; 7070050Siedowse}; 7141474Sjulian 7241474Sjulianstatic const struct _rpcnettype { 7341474Sjulian const char *name; 7441474Sjulian const int type; 7541474Sjulian} _rpctypelist[] = { 7641474Sjulian { "netpath", _RPC_NETPATH }, 771558Srgrimes { "visible", _RPC_VISIBLE }, 7841474Sjulian { "circuit_v", _RPC_CIRCUIT_V }, 7941474Sjulian { "datagram_v", _RPC_DATAGRAM_V }, 8041474Sjulian { "circuit_n", _RPC_CIRCUIT_N }, 8141474Sjulian { "datagram_n", _RPC_DATAGRAM_N }, 8241474Sjulian { "tcp", _RPC_TCP }, 8341474Sjulian { "udp", _RPC_UDP }, 8441474Sjulian { 0, _RPC_NONE } 8541474Sjulian}; 861558Srgrimes 871558Srgrimesstruct netid_af { 881558Srgrimes const char *netid; 891558Srgrimes int af; 901558Srgrimes int protocol; 911558Srgrimes}; 921558Srgrimes 931558Srgrimesstatic const struct netid_af na_cvt[] = { 9441474Sjulian { "udp", AF_INET, IPPROTO_UDP }, 9541474Sjulian { "tcp", AF_INET, IPPROTO_TCP }, 961558Srgrimes#ifdef INET6 9741474Sjulian { "udp6", AF_INET6, IPPROTO_UDP }, 9841474Sjulian { "tcp6", AF_INET6, IPPROTO_TCP }, 9941474Sjulian#endif 1001558Srgrimes { "local", AF_LOCAL, 0 } 10141474Sjulian}; 10241474Sjulian 10398542Smckusick#if 0 10441474Sjulianstatic char *strlocase(char *); 10541474Sjulian#endif 10641474Sjulianstatic int getnettype(const char *); 10741474Sjulian 10841474Sjulian/* 10941474Sjulian * Cache the result of getrlimit(), so we don't have to do an 1101558Srgrimes * expensive call every time. 1111558Srgrimes */ 11241474Sjulianint 11341474Sjulian__rpc_dtbsize(void) 1141558Srgrimes{ 11541474Sjulian static int tbsize; 11641474Sjulian struct rlimit rl; 11741474Sjulian 11841474Sjulian if (tbsize) { 1191558Srgrimes return (tbsize); 1201558Srgrimes } 1211558Srgrimes if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 1221558Srgrimes return (tbsize = (int)rl.rlim_max); 1237585Sbde } 12492839Simp /* 1251558Srgrimes * Something wrong. I'll try to save face by returning a 12692806Sobrien * pessimistic number. 1271558Srgrimes */ 12898542Smckusick return (32); 1291558Srgrimes} 1301558Srgrimes 1311558Srgrimes 1321558Srgrimes/* 1331558Srgrimes * Find the appropriate buffer size 1341558Srgrimes * 1351558Srgrimes * size - Size requested 1361558Srgrimes */ 1371558Srgrimesu_int 1381558Srgrimes/*ARGSUSED*/ 1391558Srgrimes__rpc_get_t_size(int af, int proto, int size) 1401558Srgrimes{ 1411558Srgrimes int maxsize, defsize; 1421558Srgrimes 1431558Srgrimes maxsize = 256 * 1024; /* XXX */ 1441558Srgrimes switch (proto) { 1451558Srgrimes case IPPROTO_TCP: 1461558Srgrimes defsize = 64 * 1024; /* XXX */ 1471558Srgrimes break; 1481558Srgrimes case IPPROTO_UDP: 1491558Srgrimes defsize = UDPMSGSIZE; 1501558Srgrimes break; 151 default: 152 defsize = RPC_MAXDATASIZE; 153 break; 154 } 155 if (size == 0) 156 return defsize; 157 158 /* Check whether the value is within the upper max limit */ 159 return (size > maxsize ? (u_int)maxsize : (u_int)size); 160} 161 162/* 163 * Find the appropriate address buffer size 164 */ 165u_int 166__rpc_get_a_size(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(char *p) 186{ 187 char *t = p; 188 189 for (; *p; p++) 190 if (isupper(*p)) 191 *p = tolower(*p); 192 return (t); 193} 194#endif 195 196/* 197 * Returns the type of the network as defined in <rpc/nettype.h> 198 * If nettype is NULL, it defaults to NETPATH. 199 */ 200static int 201getnettype(const char *nettype) 202{ 203 int i; 204 205 if ((nettype == NULL) || (nettype[0] == 0)) { 206 return (_RPC_NETPATH); /* Default */ 207 } 208 209#if 0 210 nettype = strlocase(nettype); 211#endif 212 for (i = 0; _rpctypelist[i].name; i++) 213 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 214 return (_rpctypelist[i].type); 215 } 216 return (_rpctypelist[i].type); 217} 218 219static thread_key_t tcp_key, udp_key; 220static once_t keys_once = ONCE_INITIALIZER; 221static int tcp_key_error, udp_key_error; 222 223static void 224keys_init(void) 225{ 226 227 tcp_key_error = thr_keycreate(&tcp_key, free); 228 udp_key_error = thr_keycreate(&udp_key, free); 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 */ 235struct netconfig * 236__rpc_getconfip(const char *nettype) 237{ 238 char *netid; 239 char *netid_tcp = (char *) NULL; 240 char *netid_udp = (char *) NULL; 241 static char *netid_tcp_main; 242 static char *netid_udp_main; 243 struct netconfig *dummy; 244 int main_thread; 245 246 if ((main_thread = thr_main())) { 247 netid_udp = netid_udp_main; 248 netid_tcp = netid_tcp_main; 249 } else { 250 if (thr_once(&keys_once, keys_init) != 0 || 251 tcp_key_error != 0 || udp_key_error != 0) 252 return (NULL); 253 netid_tcp = (char *)thr_getspecific(tcp_key); 254 netid_udp = (char *)thr_getspecific(udp_key); 255 } 256 if (!netid_udp && !netid_tcp) { 257 struct netconfig *nconf; 258 void *confighandle; 259 260 if (!(confighandle = setnetconfig())) { 261 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 262 return (NULL); 263 } 264 while ((nconf = getnetconfig(confighandle)) != NULL) { 265 if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 266 if (strcmp(nconf->nc_proto, NC_TCP) == 0 && 267 netid_tcp == NULL) { 268 netid_tcp = strdup(nconf->nc_netid); 269 if (main_thread) 270 netid_tcp_main = netid_tcp; 271 else 272 thr_setspecific(tcp_key, 273 (void *) netid_tcp); 274 } else 275 if (strcmp(nconf->nc_proto, NC_UDP) == 0 && 276 netid_udp == NULL) { 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] == 0)) { 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(const char *nettype) 308{ 309 struct handle *handle; 310 311 handle = (struct handle *) malloc(sizeof (struct handle)); 312 if (handle == NULL) { 313 return (NULL); 314 } 315 switch (handle->nettype = getnettype(nettype)) { 316 case _RPC_NETPATH: 317 case _RPC_CIRCUIT_N: 318 case _RPC_DATAGRAM_N: 319 if (!(handle->nhandle = setnetpath())) 320 goto failed; 321 handle->nflag = TRUE; 322 break; 323 case _RPC_VISIBLE: 324 case _RPC_CIRCUIT_V: 325 case _RPC_DATAGRAM_V: 326 case _RPC_TCP: 327 case _RPC_UDP: 328 if (!(handle->nhandle = setnetconfig())) { 329 syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 330 goto failed; 331 } 332 handle->nflag = FALSE; 333 break; 334 default: 335 goto failed; 336 } 337 338 return (handle); 339 340failed: 341 free(handle); 342 return (NULL); 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(void *vhandle) 351{ 352 struct handle *handle; 353 struct netconfig *nconf; 354 355 handle = (struct handle *)vhandle; 356 if (handle == NULL) { 357 return (NULL); 358 } 359 for (;;) { 360 if (handle->nflag) 361 nconf = getnetpath(handle->nhandle); 362 else 363 nconf = getnetconfig(handle->nhandle); 364 if (nconf == NULL) 365 break; 366 if ((nconf->nc_semantics != NC_TPI_CLTS) && 367 (nconf->nc_semantics != NC_TPI_COTS) && 368 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 369 continue; 370 switch (handle->nettype) { 371 case _RPC_VISIBLE: 372 if (!(nconf->nc_flag & NC_VISIBLE)) 373 continue; 374 /* FALLTHROUGH */ 375 case _RPC_NETPATH: /* Be happy */ 376 break; 377 case _RPC_CIRCUIT_V: 378 if (!(nconf->nc_flag & NC_VISIBLE)) 379 continue; 380 /* FALLTHROUGH */ 381 case _RPC_CIRCUIT_N: 382 if ((nconf->nc_semantics != NC_TPI_COTS) && 383 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 384 continue; 385 break; 386 case _RPC_DATAGRAM_V: 387 if (!(nconf->nc_flag & NC_VISIBLE)) 388 continue; 389 /* FALLTHROUGH */ 390 case _RPC_DATAGRAM_N: 391 if (nconf->nc_semantics != NC_TPI_CLTS) 392 continue; 393 break; 394 case _RPC_TCP: 395 if (((nconf->nc_semantics != NC_TPI_COTS) && 396 (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 397 (strcmp(nconf->nc_protofmly, NC_INET) 398#ifdef INET6 399 && strcmp(nconf->nc_protofmly, NC_INET6)) 400#else 401 ) 402#endif 403 || 404 strcmp(nconf->nc_proto, NC_TCP)) 405 continue; 406 break; 407 case _RPC_UDP: 408 if ((nconf->nc_semantics != NC_TPI_CLTS) || 409 (strcmp(nconf->nc_protofmly, NC_INET) 410#ifdef INET6 411 && strcmp(nconf->nc_protofmly, NC_INET6)) 412#else 413 ) 414#endif 415 || 416 strcmp(nconf->nc_proto, NC_UDP)) 417 continue; 418 break; 419 } 420 break; 421 } 422 return (nconf); 423} 424 425void 426__rpc_endconf(void *vhandle) 427{ 428 struct handle *handle; 429 430 handle = (struct handle *) vhandle; 431 if (handle == NULL) { 432 return; 433 } 434 if (handle->nflag) { 435 endnetpath(handle->nhandle); 436 } else { 437 endnetconfig(handle->nhandle); 438 } 439 free(handle); 440} 441 442/* 443 * Used to ping the NULL procedure for clnt handle. 444 * Returns NULL if fails, else a non-NULL pointer. 445 */ 446void * 447rpc_nullproc(CLIENT *clnt) 448{ 449 struct timeval TIMEOUT = {25, 0}; 450 451 if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 452 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 453 return (NULL); 454 } 455 return ((void *) clnt); 456} 457 458/* 459 * Try all possible transports until 460 * one succeeds in finding the netconf for the given fd. 461 */ 462struct netconfig * 463__rpcgettp(int fd) 464{ 465 const char *netid; 466 struct __rpc_sockinfo si; 467 468 if (!__rpc_fd2sockinfo(fd, &si)) 469 return NULL; 470 471 if (!__rpc_sockinfo2netid(&si, &netid)) 472 return NULL; 473 474 /*LINTED const castaway*/ 475 return getnetconfigent((char *)netid); 476} 477 478int 479__rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) 480{ 481 socklen_t len; 482 int type, proto; 483 struct sockaddr_storage ss; 484 485 len = sizeof ss; 486 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0) 487 return 0; 488 sip->si_alen = len; 489 490 len = sizeof type; 491 if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) 492 return 0; 493 494 /* XXX */ 495 if (ss.ss_family != AF_LOCAL) { 496 if (type == SOCK_STREAM) 497 proto = IPPROTO_TCP; 498 else if (type == SOCK_DGRAM) 499 proto = IPPROTO_UDP; 500 else 501 return 0; 502 } else 503 proto = 0; 504 505 sip->si_af = ss.ss_family; 506 sip->si_proto = proto; 507 sip->si_socktype = type; 508 509 return 1; 510} 511 512/* 513 * Linear search, but the number of entries is small. 514 */ 515int 516__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 517{ 518 int i; 519 520 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 521 if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 522 strcmp(nconf->nc_netid, "unix") == 0 && 523 strcmp(na_cvt[i].netid, "local") == 0)) { 524 sip->si_af = na_cvt[i].af; 525 sip->si_proto = na_cvt[i].protocol; 526 sip->si_socktype = 527 __rpc_seman2socktype((int)nconf->nc_semantics); 528 if (sip->si_socktype == -1) 529 return 0; 530 sip->si_alen = __rpc_get_a_size(sip->si_af); 531 return 1; 532 } 533 534 return 0; 535} 536 537int 538__rpc_nconf2fd(const struct netconfig *nconf) 539{ 540 struct __rpc_sockinfo si; 541 542 if (!__rpc_nconf2sockinfo(nconf, &si)) 543 return 0; 544 545 return _socket(si.si_af, si.si_socktype, si.si_proto); 546} 547 548int 549__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) 550{ 551 int i; 552 struct netconfig *nconf; 553 554 nconf = getnetconfigent("local"); 555 556 for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) { 557 if (na_cvt[i].af == sip->si_af && 558 na_cvt[i].protocol == sip->si_proto) { 559 if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) { 560 if (netid) 561 *netid = "unix"; 562 } else { 563 if (netid) 564 *netid = na_cvt[i].netid; 565 } 566 if (nconf != NULL) 567 freenetconfigent(nconf); 568 return 1; 569 } 570 } 571 if (nconf != NULL) 572 freenetconfigent(nconf); 573 574 return 0; 575} 576 577char * 578taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 579{ 580 struct __rpc_sockinfo si; 581 582 if (!__rpc_nconf2sockinfo(nconf, &si)) 583 return NULL; 584 return __rpc_taddr2uaddr_af(si.si_af, nbuf); 585} 586 587struct netbuf * 588uaddr2taddr(const struct netconfig *nconf, const char *uaddr) 589{ 590 struct __rpc_sockinfo si; 591 592 if (!__rpc_nconf2sockinfo(nconf, &si)) 593 return NULL; 594 return __rpc_uaddr2taddr_af(si.si_af, uaddr); 595} 596 597char * 598__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 599{ 600 char *ret; 601 struct sockaddr_in *sin; 602 struct sockaddr_un *sun; 603 char namebuf[INET_ADDRSTRLEN]; 604#ifdef INET6 605 struct sockaddr_in6 *sin6; 606 char namebuf6[INET6_ADDRSTRLEN]; 607#endif 608 u_int16_t port; 609 610 switch (af) { 611 case AF_INET: 612 if (nbuf->len < sizeof(*sin)) 613 return NULL; 614 sin = nbuf->buf; 615 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 616 == NULL) 617 return NULL; 618 port = ntohs(sin->sin_port); 619 if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8, 620 port & 0xff) < 0) 621 return NULL; 622 break; 623#ifdef INET6 624 case AF_INET6: 625 if (nbuf->len < sizeof(*sin6)) 626 return NULL; 627 sin6 = nbuf->buf; 628 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 629 == NULL) 630 return NULL; 631 port = ntohs(sin6->sin6_port); 632 if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8, 633 port & 0xff) < 0) 634 return NULL; 635 break; 636#endif 637 case AF_LOCAL: 638 sun = nbuf->buf; 639 if (asprintf(&ret, "%.*s", (int)(sun->sun_len - 640 offsetof(struct sockaddr_un, sun_path)), 641 sun->sun_path) < 0) 642 return (NULL); 643 break; 644 default: 645 return NULL; 646 } 647 648 return ret; 649} 650 651struct netbuf * 652__rpc_uaddr2taddr_af(int af, const char *uaddr) 653{ 654 struct netbuf *ret = NULL; 655 char *addrstr, *p; 656 unsigned port, portlo, porthi; 657 struct sockaddr_in *sin; 658#ifdef INET6 659 struct sockaddr_in6 *sin6; 660#endif 661 struct sockaddr_un *sun; 662 663 port = 0; 664 sin = NULL; 665 666 if (uaddr == NULL) 667 return NULL; 668 669 addrstr = strdup(uaddr); 670 if (addrstr == NULL) 671 return NULL; 672 673 /* 674 * AF_LOCAL addresses are expected to be absolute 675 * pathnames, anything else will be AF_INET or AF_INET6. 676 */ 677 if (*addrstr != '/') { 678 p = strrchr(addrstr, '.'); 679 if (p == NULL) 680 goto out; 681 portlo = (unsigned)atoi(p + 1); 682 *p = '\0'; 683 684 p = strrchr(addrstr, '.'); 685 if (p == NULL) 686 goto out; 687 porthi = (unsigned)atoi(p + 1); 688 *p = '\0'; 689 port = (porthi << 8) | portlo; 690 } 691 692 ret = (struct netbuf *)malloc(sizeof *ret); 693 if (ret == NULL) 694 goto out; 695 696 switch (af) { 697 case AF_INET: 698 sin = (struct sockaddr_in *)malloc(sizeof *sin); 699 if (sin == NULL) 700 goto out; 701 memset(sin, 0, sizeof *sin); 702 sin->sin_family = AF_INET; 703 sin->sin_port = htons(port); 704 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 705 free(sin); 706 free(ret); 707 ret = NULL; 708 goto out; 709 } 710 sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 711 ret->buf = sin; 712 break; 713#ifdef INET6 714 case AF_INET6: 715 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6); 716 if (sin6 == NULL) 717 goto out; 718 memset(sin6, 0, sizeof *sin6); 719 sin6->sin6_family = AF_INET6; 720 sin6->sin6_port = htons(port); 721 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 722 free(sin6); 723 free(ret); 724 ret = NULL; 725 goto out; 726 } 727 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 728 ret->buf = sin6; 729 break; 730#endif 731 case AF_LOCAL: 732 sun = (struct sockaddr_un *)malloc(sizeof *sun); 733 if (sun == NULL) 734 goto out; 735 memset(sun, 0, sizeof *sun); 736 sun->sun_family = AF_LOCAL; 737 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 738 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 739 ret->buf = sun; 740 break; 741 default: 742 break; 743 } 744out: 745 free(addrstr); 746 return ret; 747} 748 749int 750__rpc_seman2socktype(int semantics) 751{ 752 switch (semantics) { 753 case NC_TPI_CLTS: 754 return SOCK_DGRAM; 755 case NC_TPI_COTS_ORD: 756 return SOCK_STREAM; 757 case NC_TPI_RAW: 758 return SOCK_RAW; 759 default: 760 break; 761 } 762 763 return -1; 764} 765 766int 767__rpc_socktype2seman(int socktype) 768{ 769 switch (socktype) { 770 case SOCK_DGRAM: 771 return NC_TPI_CLTS; 772 case SOCK_STREAM: 773 return NC_TPI_COTS_ORD; 774 case SOCK_RAW: 775 return NC_TPI_RAW; 776 default: 777 break; 778 } 779 780 return -1; 781} 782 783/* 784 * XXXX - IPv6 scope IDs can't be handled in universal addresses. 785 * Here, we compare the original server address to that of the RPC 786 * service we just received back from a call to rpcbind on the remote 787 * machine. If they are both "link local" or "site local", copy 788 * the scope id of the server address over to the service address. 789 */ 790int 791__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 792{ 793#ifdef INET6 794 struct sockaddr *sa_new, *sa_svc; 795 struct sockaddr_in6 *sin6_new, *sin6_svc; 796 797 sa_svc = (struct sockaddr *)svc->buf; 798 sa_new = (struct sockaddr *)new->buf; 799 800 if (sa_new->sa_family == sa_svc->sa_family && 801 sa_new->sa_family == AF_INET6) { 802 sin6_new = (struct sockaddr_in6 *)new->buf; 803 sin6_svc = (struct sockaddr_in6 *)svc->buf; 804 805 if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 806 IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 807 (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 808 IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 809 sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 810 } 811 } 812#endif 813 return 1; 814} 815 816int 817__rpc_sockisbound(int fd) 818{ 819 struct sockaddr_storage ss; 820 socklen_t slen; 821 822 slen = sizeof (struct sockaddr_storage); 823 if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 824 return 0; 825 826 switch (ss.ss_family) { 827 case AF_INET: 828 return (((struct sockaddr_in *) 829 (void *)&ss)->sin_port != 0); 830#ifdef INET6 831 case AF_INET6: 832 return (((struct sockaddr_in6 *) 833 (void *)&ss)->sin6_port != 0); 834#endif 835 case AF_LOCAL: 836 /* XXX check this */ 837 return (((struct sockaddr_un *) 838 (void *)&ss)->sun_path[0] != '\0'); 839 default: 840 break; 841 } 842 843 return 0; 844} 845