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