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