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