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