1 /* $NetBSD: rpcbind.c,v 1.3 2002/11/08 00:16:40 fvdl 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) 1984 - 1991 by Sun Microsystems, Inc. 34 */ 35 36 /* 37 * rpcbind.c 38 * Implements the program, version to address mapping for rpc. 39 * 40 */ 41 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <sys/errno.h> 45 #include <sys/time.h> 46 #include <sys/resource.h> 47 #include <sys/wait.h> 48 #include <sys/signal.h> 49 #include <sys/socket.h> 50 #include <sys/un.h> 51 #include <rpc/rpc.h> 52 #include <rpc/rpc_com.h> 53 #ifdef PORTMAP 54 #include <netinet/in.h> 55 #endif 56 #include <arpa/inet.h> 57 #include <assert.h> 58 #include <fcntl.h> 59 #include <netdb.h> 60 #include <stdbool.h> 61 #include <stdio.h> 62 #include <netconfig.h> 63 #include <stdlib.h> 64 #include <unistd.h> 65 #include <syslog.h> 66 #include <err.h> 67 #include <pwd.h> 68 #include <string.h> 69 #include <errno.h> 70 #include "rpcbind.h" 71 72 /* Global variables */ 73 int debugging = 0; /* Tell me what's going on */ 74 int doabort = 0; /* When debugging, do an abort on errors */ 75 int terminate_rfd; /* Pipefd to wake on signal */ 76 volatile sig_atomic_t doterminate = 0; /* Terminal signal received */ 77 rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */ 78 int rpcbindlockfd; 79 80 /* who to suid to if -s is given */ 81 #define RUN_AS "daemon" 82 83 #define RPCBINDDLOCK "/var/run/rpcbind.lock" 84 85 static int runasdaemon = 0; 86 int insecure = 0; 87 int oldstyle_local = 0; 88 #ifdef LIBWRAP 89 int libwrap = 0; 90 #endif 91 int nofork = 0; 92 int verboselog = 0; 93 int nobind_localhost = 0; 94 95 static char **hosts = NULL; 96 static struct sockaddr **bound_sa; 97 static int ipv6_only = 0; 98 static int nhosts = 0; 99 static int on = 1; 100 static int terminate_wfd; 101 102 #ifdef WARMSTART 103 /* Local Variable */ 104 static int warmstart = 0; /* Grab an old copy of registrations. */ 105 #endif 106 107 #ifdef PORTMAP 108 struct pmaplist *list_pml; /* A list of version 2 rpcbind services */ 109 char *udptrans; /* Name of UDP transport */ 110 char *tcptrans; /* Name of TCP transport */ 111 char *udp_uaddr; /* Universal UDP address */ 112 char *tcp_uaddr; /* Universal TCP address */ 113 #endif 114 static char servname[] = "rpcbind"; 115 static char superuser[] = "superuser"; 116 static char nlname[] = "netlink"; 117 118 static struct netconfig netlink_nconf = { 119 .nc_netid = nlname, 120 .nc_semantics = NC_TPI_CLTS, 121 }; 122 123 static struct t_bind netlink_taddr = { 124 .addr = { 125 .maxlen = sizeof(nlname), 126 .len = sizeof(nlname), 127 .buf = nlname, 128 }, 129 }; 130 131 static int init_transport(struct netconfig *); 132 static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *, 133 struct netbuf *); 134 static void terminate(int); 135 static void parseargs(int, char *[]); 136 static void update_bound_sa(void); 137 138 int 139 main(int argc, char *argv[]) 140 { 141 struct netconfig *nconf; 142 void *nc_handle; /* Net config handle */ 143 struct rlimit rl; 144 int maxrec = RPC_MAXDATASIZE; 145 int error, fds[2]; 146 147 parseargs(argc, argv); 148 149 update_bound_sa(); 150 151 /* Check that another rpcbind isn't already running. */ 152 if ((rpcbindlockfd = (open(RPCBINDDLOCK, 153 O_RDONLY|O_CREAT, 0444))) == -1) 154 err(1, "%s", RPCBINDDLOCK); 155 156 if(flock(rpcbindlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 157 errx(1, "another rpcbind is already running. Aborting"); 158 159 getrlimit(RLIMIT_NOFILE, &rl); 160 if (rl.rlim_cur < 128) { 161 if (rl.rlim_max <= 128) 162 rl.rlim_cur = rl.rlim_max; 163 else 164 rl.rlim_cur = 128; 165 setrlimit(RLIMIT_NOFILE, &rl); 166 } 167 openlog("rpcbind", LOG_CONS, LOG_DAEMON); 168 if (geteuid()) { /* This command allowed only to root */ 169 fprintf(stderr, "Sorry. You are not superuser\n"); 170 exit(1); 171 } 172 nc_handle = setnetconfig(); /* open netconfig file */ 173 if (nc_handle == NULL) { 174 syslog(LOG_ERR, "could not read /etc/netconfig"); 175 exit(1); 176 } 177 #ifdef PORTMAP 178 udptrans = ""; 179 tcptrans = ""; 180 #endif 181 182 nconf = getnetconfigent("local"); 183 if (nconf == NULL) 184 nconf = getnetconfigent("unix"); 185 if (nconf == NULL) { 186 syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]); 187 exit(1); 188 } 189 190 rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 191 192 init_transport(nconf); 193 194 while ((nconf = getnetconfig(nc_handle))) { 195 if (nconf->nc_flag & NC_VISIBLE) { 196 if (ipv6_only == 1 && strcmp(nconf->nc_protofmly, 197 "inet") == 0) { 198 /* DO NOTHING */ 199 } else 200 init_transport(nconf); 201 } 202 } 203 endnetconfig(nc_handle); 204 205 init_transport(&netlink_nconf); 206 207 /* 208 * Allocate pipe fd to wake main thread from signal handler in non-racy 209 * way. 210 */ 211 error = pipe(fds); 212 if (error != 0) 213 err(1, "pipe failed"); 214 terminate_rfd = fds[0]; 215 terminate_wfd = fds[1]; 216 217 /* catch the usual termination signals for graceful exit */ 218 (void) signal(SIGCHLD, reap); 219 (void) signal(SIGINT, terminate); 220 (void) signal(SIGTERM, terminate); 221 (void) signal(SIGQUIT, terminate); 222 /* ignore others that could get sent */ 223 (void) signal(SIGPIPE, SIG_IGN); 224 (void) signal(SIGHUP, SIG_IGN); 225 (void) signal(SIGUSR1, SIG_IGN); 226 (void) signal(SIGUSR2, SIG_IGN); 227 #ifdef WARMSTART 228 if (warmstart) { 229 read_warmstart(); 230 } 231 #endif 232 if (debugging) { 233 printf("rpcbind debugging enabled."); 234 if (doabort) { 235 printf(" Will abort on errors!\n"); 236 } else { 237 printf("\n"); 238 } 239 } else if (!nofork) { 240 if (daemon(0, 0)) 241 err(1, "fork failed"); 242 } 243 244 if (runasdaemon) { 245 struct passwd *p; 246 247 if((p = getpwnam(RUN_AS)) == NULL) { 248 syslog(LOG_ERR, "cannot get uid of daemon: %m"); 249 exit(1); 250 } 251 if (setuid(p->pw_uid) == -1) { 252 syslog(LOG_ERR, "setuid to daemon failed: %m"); 253 exit(1); 254 } 255 } 256 257 network_init(); 258 259 my_svc_run(); 260 syslog(LOG_ERR, "svc_run returned unexpectedly"); 261 rpcbind_abort(); 262 /* NOTREACHED */ 263 264 return 0; 265 } 266 267 /* 268 * Adds the entry into the rpcbind database. 269 * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also 270 * Returns 0 if succeeds, else fails 271 */ 272 static int 273 init_transport(struct netconfig *nconf) 274 { 275 int fd = -1; 276 struct t_bind taddr; 277 struct addrinfo hints, *res = NULL; 278 struct __rpc_sockinfo si; 279 SVCXPRT *my_xprt = NULL; 280 int status; /* bound checking ? */ 281 int aicode; 282 int addrlen; 283 int nhostsbak; 284 int bound; 285 struct sockaddr *sa; 286 u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 287 struct sockaddr_un sun; 288 mode_t oldmask; 289 bool local, netlink; 290 291 local = strcmp(nconf->nc_netid, "local") == 0 || 292 strcmp(nconf->nc_netid, "unix") == 0; 293 netlink = strcmp(nconf->nc_netid, "netlink") == 0; 294 295 if ((nconf->nc_semantics != NC_TPI_CLTS) && 296 (nconf->nc_semantics != NC_TPI_COTS) && 297 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 298 return (1); /* not my type */ 299 #ifdef ND_DEBUG 300 if (debugging) { 301 int i; 302 char **s; 303 304 (void)fprintf(stderr, "%s: %ld lookup routines :\n", 305 nconf->nc_netid, nconf->nc_nlookups); 306 for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups; 307 i++, s++) 308 fprintf(stderr, "[%d] - %s\n", i, *s); 309 } 310 #endif 311 312 /* 313 * XXX - using RPC library internal functions. 314 */ 315 if (local) { 316 /* 317 * For other transports we call this later, for each socket we 318 * like to bind. 319 */ 320 if ((fd = __rpc_nconf2fd(nconf)) < 0) { 321 int non_fatal = 0; 322 if (errno == EAFNOSUPPORT) 323 non_fatal = 1; 324 syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s", 325 nconf->nc_netid); 326 return (1); 327 } 328 } 329 330 if (!__rpc_nconf2sockinfo(nconf, &si)) { 331 syslog(LOG_ERR, "cannot get information for %s", 332 nconf->nc_netid); 333 return (1); 334 } 335 336 if (local) { 337 memset(&sun, 0, sizeof sun); 338 sun.sun_family = AF_LOCAL; 339 unlink(_PATH_RPCBINDSOCK); 340 strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 341 sun.sun_len = SUN_LEN(&sun); 342 addrlen = sizeof (struct sockaddr_un); 343 sa = (struct sockaddr *)&sun; 344 } else if (!netlink) { 345 /* Get rpcbind's address on this transport */ 346 347 memset(&hints, 0, sizeof hints); 348 hints.ai_flags = AI_PASSIVE; 349 hints.ai_family = si.si_af; 350 hints.ai_socktype = si.si_socktype; 351 hints.ai_protocol = si.si_proto; 352 } 353 354 if (!local && !netlink) { 355 /* 356 * If no hosts were specified, just bind to INADDR_ANY. 357 * Otherwise make sure 127.0.0.1 is added to the list. 358 */ 359 nhostsbak = nhosts + 1; 360 hosts = realloc(hosts, nhostsbak * sizeof(char *)); 361 if (nhostsbak == 1) 362 hosts[0] = "*"; 363 else { 364 if (hints.ai_family == AF_INET && nobind_localhost == 0) { 365 hosts[nhostsbak - 1] = "127.0.0.1"; 366 } else if (hints.ai_family == AF_INET6 && nobind_localhost == 0) { 367 hosts[nhostsbak - 1] = "::1"; 368 } else 369 return 1; 370 } 371 372 /* 373 * Bind to specific IPs if asked to 374 */ 375 bound = 0; 376 while (nhostsbak > 0) { 377 --nhostsbak; 378 /* 379 * XXX - using RPC library internal functions. 380 */ 381 if ((fd = __rpc_nconf2fd(nconf)) < 0) { 382 int non_fatal = 0; 383 if (errno == EAFNOSUPPORT && 384 nconf->nc_semantics != NC_TPI_CLTS) 385 non_fatal = 1; 386 syslog(non_fatal ? LOG_DEBUG : LOG_ERR, 387 "cannot create socket for %s", nconf->nc_netid); 388 return (1); 389 } 390 switch (hints.ai_family) { 391 case AF_INET: 392 if (inet_pton(AF_INET, hosts[nhostsbak], 393 host_addr) == 1) { 394 hints.ai_flags &= AI_NUMERICHOST; 395 } else { 396 /* 397 * Skip if we have an AF_INET6 address. 398 */ 399 if (inet_pton(AF_INET6, 400 hosts[nhostsbak], host_addr) == 1) { 401 close(fd); 402 continue; 403 } 404 } 405 break; 406 case AF_INET6: 407 if (inet_pton(AF_INET6, hosts[nhostsbak], 408 host_addr) == 1) { 409 hints.ai_flags &= AI_NUMERICHOST; 410 } else { 411 /* 412 * Skip if we have an AF_INET address. 413 */ 414 if (inet_pton(AF_INET, hosts[nhostsbak], 415 host_addr) == 1) { 416 close(fd); 417 continue; 418 } 419 } 420 if (setsockopt(fd, IPPROTO_IPV6, 421 IPV6_V6ONLY, &on, sizeof on) < 0) { 422 syslog(LOG_ERR, 423 "can't set v6-only binding for " 424 "ipv6 socket: %m"); 425 continue; 426 } 427 break; 428 default: 429 break; 430 } 431 432 /* 433 * If no hosts were specified, just bind to INADDR_ANY 434 */ 435 if (strcmp("*", hosts[nhostsbak]) == 0) 436 hosts[nhostsbak] = NULL; 437 if ((aicode = getaddrinfo(hosts[nhostsbak], servname, &hints, 438 &res)) != 0) { 439 syslog(LOG_ERR, "cannot get local address for %s: %s", 440 nconf->nc_netid, gai_strerror(aicode)); 441 continue; 442 } 443 addrlen = res->ai_addrlen; 444 sa = (struct sockaddr *)res->ai_addr; 445 oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 446 if (bind(fd, sa, addrlen) != 0) { 447 syslog(LOG_ERR, "cannot bind %s on %s: %m", 448 (hosts[nhostsbak] == NULL) ? "*" : 449 hosts[nhostsbak], nconf->nc_netid); 450 if (res != NULL) 451 freeaddrinfo(res); 452 continue; 453 } else 454 bound = 1; 455 (void)umask(oldmask); 456 457 /* Copy the address */ 458 taddr.addr.len = taddr.addr.maxlen = addrlen; 459 taddr.addr.buf = malloc(addrlen); 460 if (taddr.addr.buf == NULL) { 461 syslog(LOG_ERR, 462 "cannot allocate memory for %s address", 463 nconf->nc_netid); 464 if (res != NULL) 465 freeaddrinfo(res); 466 return 1; 467 } 468 memcpy(taddr.addr.buf, sa, addrlen); 469 #ifdef ND_DEBUG 470 if (debugging) { 471 /* 472 * for debugging print out our universal 473 * address 474 */ 475 char *uaddr; 476 struct netbuf nb; 477 478 nb.buf = sa; 479 nb.len = nb.maxlen = sa->sa_len; 480 uaddr = taddr2uaddr(nconf, &nb); 481 (void)fprintf(stderr, 482 "rpcbind : my address is %s\n", uaddr); 483 (void)free(uaddr); 484 } 485 #endif 486 487 if (nconf->nc_semantics != NC_TPI_CLTS) 488 listen(fd, SOMAXCONN); 489 490 my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 491 RPC_MAXDATASIZE, RPC_MAXDATASIZE); 492 } 493 } else if (local) { 494 oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 495 if (bind(fd, sa, addrlen) < 0) { 496 syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid); 497 if (res != NULL) 498 freeaddrinfo(res); 499 return 1; 500 } 501 (void) umask(oldmask); 502 503 /* Copy the address */ 504 taddr.addr.len = taddr.addr.maxlen = addrlen; 505 taddr.addr.buf = malloc(addrlen); 506 if (taddr.addr.buf == NULL) { 507 syslog(LOG_ERR, "cannot allocate memory for %s address", 508 nconf->nc_netid); 509 if (res != NULL) 510 freeaddrinfo(res); 511 return 1; 512 } 513 memcpy(taddr.addr.buf, sa, addrlen); 514 #ifdef ND_DEBUG 515 if (debugging) { 516 /* for debugging print out our universal address */ 517 char *uaddr; 518 struct netbuf nb; 519 520 nb.buf = sa; 521 nb.len = nb.maxlen = sa->sa_len; 522 uaddr = taddr2uaddr(nconf, &nb); 523 (void) fprintf(stderr, "rpcbind : my address is %s\n", 524 uaddr); 525 (void) free(uaddr); 526 } 527 #endif 528 529 if (nconf->nc_semantics != NC_TPI_CLTS) 530 listen(fd, SOMAXCONN); 531 532 my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 533 RPC_MAXDATASIZE, RPC_MAXDATASIZE); 534 } else { 535 assert(netlink); 536 taddr = netlink_taddr; 537 my_xprt = svc_nl_create("rpcbind"); 538 } 539 540 if (my_xprt == (SVCXPRT *)NULL) { 541 syslog(LOG_ERR, "%s: could not create service", 542 nconf->nc_netid); 543 goto error; 544 } 545 546 #ifdef PORTMAP 547 /* 548 * Register both the versions for tcp/ip, udp/ip and local. 549 */ 550 if (!netlink && (local || (strcmp(nconf->nc_protofmly, NC_INET) == 0 && 551 (strcmp(nconf->nc_proto, NC_TCP) == 0 || 552 strcmp(nconf->nc_proto, NC_UDP) == 0)))) { 553 struct pmaplist *pml; 554 555 if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, 556 pmap_service, 0)) { 557 syslog(LOG_ERR, "could not register on %s", 558 nconf->nc_netid); 559 goto error; 560 } 561 pml = malloc(sizeof (struct pmaplist)); 562 if (pml == NULL) { 563 syslog(LOG_ERR, "no memory!"); 564 exit(1); 565 } 566 pml->pml_map.pm_prog = PMAPPROG; 567 pml->pml_map.pm_vers = PMAPVERS; 568 pml->pml_map.pm_port = PMAPPORT; 569 if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 570 if (tcptrans[0]) { 571 free(pml); 572 pml = NULL; 573 syslog(LOG_ERR, 574 "cannot have more than one TCP transport"); 575 goto error; 576 } 577 tcptrans = strdup(nconf->nc_netid); 578 pml->pml_map.pm_prot = IPPROTO_TCP; 579 580 /* Let's snarf the universal address */ 581 /* "h1.h2.h3.h4.p1.p2" */ 582 tcp_uaddr = taddr2uaddr(nconf, &taddr.addr); 583 } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 584 if (udptrans[0]) { 585 syslog(LOG_ERR, 586 "cannot have more than one UDP transport"); 587 goto error; 588 } 589 udptrans = strdup(nconf->nc_netid); 590 pml->pml_map.pm_prot = IPPROTO_UDP; 591 592 /* Let's snarf the universal address */ 593 /* "h1.h2.h3.h4.p1.p2" */ 594 udp_uaddr = taddr2uaddr(nconf, &taddr.addr); 595 } else if (strcmp(nconf->nc_netid, "local") == 0) 596 pml->pml_map.pm_prot = IPPROTO_ST; 597 else if (strcmp(nconf->nc_netid, "unix") == 0) 598 pml->pml_map.pm_prot = IPPROTO_ST; 599 pml->pml_next = list_pml; 600 list_pml = pml; 601 602 /* Add version 3 information */ 603 pml = malloc(sizeof (struct pmaplist)); 604 if (pml == NULL) { 605 syslog(LOG_ERR, "no memory!"); 606 exit(1); 607 } 608 pml->pml_map = list_pml->pml_map; 609 pml->pml_map.pm_vers = RPCBVERS; 610 pml->pml_next = list_pml; 611 list_pml = pml; 612 613 /* Add version 4 information */ 614 pml = malloc (sizeof (struct pmaplist)); 615 if (pml == NULL) { 616 syslog(LOG_ERR, "no memory!"); 617 exit(1); 618 } 619 pml->pml_map = list_pml->pml_map; 620 pml->pml_map.pm_vers = RPCBVERS4; 621 pml->pml_next = list_pml; 622 list_pml = pml; 623 624 /* Also add version 2 stuff to rpcbind list */ 625 rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); 626 } 627 #endif 628 629 /* version 3 registration */ 630 if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { 631 syslog(LOG_ERR, "could not register %s version 3", 632 nconf->nc_netid); 633 goto error; 634 } 635 rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); 636 637 /* version 4 registration */ 638 if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { 639 syslog(LOG_ERR, "could not register %s version 4", 640 nconf->nc_netid); 641 goto error; 642 } 643 rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); 644 645 /* decide if bound checking works for this transport */ 646 status = add_bndlist(nconf, &taddr.addr); 647 #ifdef BIND_DEBUG 648 if (debugging) { 649 if (status < 0) { 650 fprintf(stderr, "Error in finding bind status for %s\n", 651 nconf->nc_netid); 652 } else if (status == 0) { 653 fprintf(stderr, "check binding for %s\n", 654 nconf->nc_netid); 655 } else if (status > 0) { 656 fprintf(stderr, "No check binding for %s\n", 657 nconf->nc_netid); 658 } 659 } 660 #endif 661 /* 662 * rmtcall only supported on CLTS transports for now. 663 */ 664 if (!netlink && nconf->nc_semantics == NC_TPI_CLTS) { 665 status = create_rmtcall_fd(nconf); 666 667 #ifdef BIND_DEBUG 668 if (debugging) { 669 if (status < 0) { 670 fprintf(stderr, 671 "Could not create rmtcall fd for %s\n", 672 nconf->nc_netid); 673 } else { 674 fprintf(stderr, "rmtcall fd for %s is %d\n", 675 nconf->nc_netid, status); 676 } 677 } 678 #endif 679 } 680 return (0); 681 error: 682 if (fd != -1) 683 close(fd); 684 return (1); 685 } 686 687 /* 688 * Create the list of addresses that we're bound to. Normally, this 689 * list is empty because we're listening on the wildcard address 690 * (nhost == 0). If -h is specified on the command line, then 691 * bound_sa will have a list of the addresses that the program binds 692 * to specifically. This function takes that list and converts them to 693 * struct sockaddr * and stores them in bound_sa. 694 */ 695 static void 696 update_bound_sa(void) 697 { 698 struct addrinfo hints, *res = NULL; 699 int i; 700 701 if (nhosts == 0) 702 return; 703 bound_sa = malloc(sizeof(*bound_sa) * nhosts); 704 memset(&hints, 0, sizeof(hints)); 705 hints.ai_family = PF_UNSPEC; 706 for (i = 0; i < nhosts; i++) { 707 if (getaddrinfo(hosts[i], NULL, &hints, &res) != 0) 708 continue; 709 bound_sa[i] = malloc(res->ai_addrlen); 710 memcpy(bound_sa[i], res->ai_addr, res->ai_addrlen); 711 } 712 } 713 714 /* 715 * Match the sa against the list of addresses we've bound to. If 716 * we've not specifically bound to anything, we match everything. 717 * Otherwise, if the IPv4 or IPv6 address matches one of the addresses 718 * in bound_sa, we return true. If not, we return false. 719 */ 720 int 721 listen_addr(const struct sockaddr *sa) 722 { 723 int i; 724 725 /* 726 * If nhosts == 0, then there were no -h options on the 727 * command line, so all addresses are addresses we're 728 * listening to. 729 */ 730 if (nhosts == 0) 731 return 1; 732 for (i = 0; i < nhosts; i++) { 733 if (bound_sa[i] == NULL || 734 sa->sa_family != bound_sa[i]->sa_family) 735 continue; 736 switch (sa->sa_family) { 737 case AF_INET: 738 if (memcmp(&SA2SINADDR(sa), &SA2SINADDR(bound_sa[i]), 739 sizeof(struct in_addr)) == 0) 740 return (1); 741 break; 742 #ifdef INET6 743 case AF_INET6: 744 if (memcmp(&SA2SIN6ADDR(sa), &SA2SIN6ADDR(bound_sa[i]), 745 sizeof(struct in6_addr)) == 0) 746 return (1); 747 break; 748 #endif 749 default: 750 break; 751 } 752 } 753 return (0); 754 } 755 756 static void 757 rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf, 758 struct netbuf *addr) 759 { 760 rpcblist_ptr rbl; 761 762 rbl = malloc(sizeof (rpcblist)); 763 if (rbl == NULL) { 764 syslog(LOG_ERR, "no memory!"); 765 exit(1); 766 } 767 768 rbl->rpcb_map.r_prog = prog; 769 rbl->rpcb_map.r_vers = vers; 770 rbl->rpcb_map.r_netid = strdup(nconf->nc_netid); 771 rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr); 772 rbl->rpcb_map.r_owner = strdup(superuser); 773 rbl->rpcb_next = list_rbl; /* Attach to global list */ 774 list_rbl = rbl; 775 } 776 777 /* 778 * Catch the signal and die 779 */ 780 static void 781 terminate(int signum) 782 { 783 char c = '\0'; 784 ssize_t wr; 785 786 doterminate = signum; 787 wr = write(terminate_wfd, &c, 1); 788 if (wr < 1) 789 _exit(2); 790 } 791 792 void 793 rpcbind_abort(void) 794 { 795 #ifdef WARMSTART 796 write_warmstart(); /* Dump yourself */ 797 #endif 798 abort(); 799 } 800 801 /* get command line options */ 802 static void 803 parseargs(int argc, char *argv[]) 804 { 805 int c; 806 807 #ifdef WARMSTART 808 #define WSOP "w" 809 #else 810 #define WSOP "" 811 #endif 812 #ifdef LIBWRAP 813 #define WRAPOP "W" 814 #else 815 #define WRAPOP "" 816 #endif 817 while ((c = getopt(argc, argv, "6adh:IiLlNs" WRAPOP WSOP)) != -1) { 818 switch (c) { 819 case '6': 820 ipv6_only = 1; 821 break; 822 case 'a': 823 doabort = 1; /* when debugging, do an abort on */ 824 break; /* errors; for rpcbind developers */ 825 /* only! */ 826 case 'd': 827 debugging = 1; 828 break; 829 case 'h': 830 ++nhosts; 831 hosts = realloc(hosts, nhosts * sizeof(char *)); 832 if (hosts == NULL) 833 errx(1, "Out of memory"); 834 hosts[nhosts - 1] = strdup(optarg); 835 if (hosts[nhosts - 1] == NULL) 836 errx(1, "Out of memory"); 837 break; 838 case 'I': 839 nobind_localhost = 1; 840 break; 841 case 'i': 842 insecure = 1; 843 break; 844 case 'L': 845 oldstyle_local = 1; 846 break; 847 case 'l': 848 verboselog = 1; 849 break; 850 case 'N': 851 nofork = 1; 852 break; 853 case 's': 854 runasdaemon = 1; 855 break; 856 #ifdef LIBWRAP 857 case 'W': 858 libwrap = 1; 859 break; 860 #endif 861 #ifdef WARMSTART 862 case 'w': 863 warmstart = 1; 864 break; 865 #endif 866 default: /* error */ 867 fprintf(stderr, 868 "usage: rpcbind [-6adIiLls%s%s] [-h bindip]\n", 869 WRAPOP, WSOP); 870 exit (1); 871 } 872 } 873 if (doabort && !debugging) { 874 fprintf(stderr, 875 "-a (abort) specified without -d (debugging) -- ignored.\n"); 876 doabort = 0; 877 } 878 #undef WSOP 879 } 880 881 void 882 reap(int dummy __unused) 883 { 884 int save_errno = errno; 885 886 while (wait3(NULL, WNOHANG, NULL) > 0) 887 ; 888 errno = save_errno; 889 } 890 891 void 892 toggle_verboselog(int dummy __unused) 893 { 894 verboselog = !verboselog; 895 } 896