1 /* $NetBSD: rpcbind.c,v 1.31 2021/10/30 11:04:48 nia 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 /* 366 * If no hosts were specified, just bind to INADDR_ANY. 367 * Otherwise make sure 127.0.0.1 is added to the list. 368 */ 369 nhostsbak = nhosts + 1; 370 if (reallocarr(&hosts, nhostsbak, sizeof(*hosts)) != 0) { 371 syslog(LOG_ERR, "Can't grow hosts array"); 372 return 1; 373 } 374 if (nhostsbak == 1) 375 hosts[0] = __UNCONST("*"); 376 else { 377 if (hints.ai_family == AF_INET) { 378 hosts[nhostsbak - 1] = __UNCONST("127.0.0.1"); 379 } else if (hints.ai_family == AF_INET6) { 380 hosts[nhostsbak - 1] = __UNCONST("::1"); 381 } else 382 return 1; 383 } 384 385 /* 386 * Bind to specific IPs if asked to 387 */ 388 bound = 0; 389 while (nhostsbak > 0) { 390 --nhostsbak; 391 /* 392 * XXX - using RPC library internal functions. 393 */ 394 if ((fd = __rpc_nconf2fd(nconf)) < 0) { 395 int non_fatal = 0; 396 if (errno == EAFNOSUPPORT && 397 nconf->nc_semantics != NC_TPI_CLTS) 398 non_fatal = 1; 399 syslog(non_fatal ? LOG_DEBUG : LOG_ERR, 400 "cannot create socket for %s", 401 nconf->nc_netid); 402 return 1; 403 } 404 switch (hints.ai_family) { 405 case AF_INET: 406 if (inet_pton(AF_INET, hosts[nhostsbak], 407 host_addr) == 1) { 408 hints.ai_flags &= AI_NUMERICHOST; 409 } else { 410 /* 411 * Skip if we have an AF_INET6 address. 412 */ 413 if (inet_pton(AF_INET6, 414 hosts[nhostsbak], host_addr) == 1) { 415 close(fd); 416 continue; 417 } 418 } 419 break; 420 case AF_INET6: 421 if (inet_pton(AF_INET6, hosts[nhostsbak], 422 host_addr) == 1) { 423 hints.ai_flags &= AI_NUMERICHOST; 424 } else { 425 /* 426 * Skip if we have an AF_INET address. 427 */ 428 if (inet_pton(AF_INET, hosts[nhostsbak], 429 host_addr) == 1) { 430 close(fd); 431 continue; 432 } 433 } 434 if (setsockopt(fd, IPPROTO_IPV6, 435 IPV6_V6ONLY, &on, sizeof on) < 0) { 436 syslog(LOG_ERR, 437 "can't set v6-only binding for " 438 "ipv6 socket: %m"); 439 continue; 440 } 441 break; 442 default: 443 break; 444 } 445 446 /* 447 * If no hosts were specified, just bind to INADDR_ANY 448 */ 449 if (strcmp("*", hosts[nhostsbak]) == 0) 450 hosts[nhostsbak] = NULL; 451 if (strcmp(nconf->nc_netid, "local") != 0) { 452 if ((aicode = getaddrinfo(hosts[nhostsbak], 453 servname, &hints, &res)) != 0) { 454 syslog(LOG_ERR, 455 "cannot get local address for %s: %s", 456 nconf->nc_netid, 457 gai_strerror(aicode)); 458 continue; 459 } 460 addrlen = res->ai_addrlen; 461 sa = (struct sockaddr *)res->ai_addr; 462 } 463 #ifndef RPCBIND_RUMP 464 oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 465 #endif 466 if (bind(fd, sa, addrlen) != 0) { 467 syslog(LOG_ERR, "cannot bind %s on %s: %m", 468 (hosts[nhostsbak] == NULL) ? "*" : 469 hosts[nhostsbak], nconf->nc_netid); 470 if (res != NULL) 471 freeaddrinfo(res); 472 continue; 473 } else 474 bound = 1; 475 #ifndef RPCBIND_RUMP 476 (void)umask(oldmask); 477 #endif 478 479 /* Copy the address */ 480 taddr.addr.len = taddr.addr.maxlen = addrlen; 481 taddr.addr.buf = malloc(addrlen); 482 if (taddr.addr.buf == NULL) { 483 syslog(LOG_ERR, "%s: Cannot allocate memory", 484 __func__); 485 if (res != NULL) 486 freeaddrinfo(res); 487 return 1; 488 } 489 memcpy(taddr.addr.buf, sa, addrlen); 490 #ifdef RPCBIND_DEBUG 491 if (debugging) { 492 /* 493 * for debugging print out our universal 494 * address 495 */ 496 char *uaddr; 497 struct netbuf nb; 498 499 nb.buf = sa; 500 nb.len = nb.maxlen = sa->sa_len; 501 uaddr = taddr2uaddr(nconf, &nb); 502 (void)fprintf(stderr, 503 "rpcbind : my address is %s\n", uaddr); 504 (void)free(uaddr); 505 } 506 #endif 507 508 if (nconf->nc_semantics != NC_TPI_CLTS) 509 listen(fd, SOMAXCONN); 510 511 my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 512 RPC_MAXDATASIZE, RPC_MAXDATASIZE); 513 if (my_xprt == NULL) { 514 syslog(LOG_ERR, 515 "Could not create service for `%s'", 516 nconf->nc_netid); 517 goto error; 518 } 519 } 520 if (!bound) 521 return 1; 522 } else { 523 #ifndef RPCBIND_RUMP 524 oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 525 #endif 526 if (bind(fd, sa, addrlen) < 0) { 527 syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid); 528 if (res != NULL) 529 freeaddrinfo(res); 530 return 1; 531 } 532 #ifndef RPCBIND_RUMP 533 (void) umask(oldmask); 534 #endif 535 536 /* Copy the address */ 537 taddr.addr.len = taddr.addr.maxlen = addrlen; 538 taddr.addr.buf = malloc(addrlen); 539 if (taddr.addr.buf == NULL) { 540 syslog(LOG_ERR, "%s: Cannot allocate memory", __func__); 541 if (res != NULL) 542 freeaddrinfo(res); 543 return 1; 544 } 545 memcpy(taddr.addr.buf, sa, addrlen); 546 #ifdef RPCBIND_DEBUG 547 if (debugging) { 548 /* for debugging print out our universal address */ 549 char *uaddr; 550 struct netbuf nb; 551 552 nb.buf = sa; 553 nb.len = nb.maxlen = sa->sa_len; 554 uaddr = taddr2uaddr(nconf, &nb); 555 (void) fprintf(stderr, "rpcbind : my address is %s\n", 556 uaddr); 557 (void) free(uaddr); 558 } 559 #endif 560 561 if (nconf->nc_semantics != NC_TPI_CLTS) 562 listen(fd, SOMAXCONN); 563 564 my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 565 RPC_MAXDATASIZE, RPC_MAXDATASIZE); 566 if (my_xprt == NULL) { 567 syslog(LOG_ERR, "%s: could not create service", 568 nconf->nc_netid); 569 goto error; 570 } 571 } 572 573 #ifdef PORTMAP 574 /* 575 * Register both the versions for tcp/ip, udp/ip and local. 576 */ 577 if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 && 578 (strcmp(nconf->nc_proto, NC_TCP) == 0 || 579 strcmp(nconf->nc_proto, NC_UDP) == 0)) || 580 strcmp(nconf->nc_netid, "local") == 0) { 581 struct pmaplist *pml; 582 583 if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, 584 pmap_service, 0)) { 585 syslog(LOG_ERR, "Could not register on `%s'", 586 nconf->nc_netid); 587 goto error; 588 } 589 pml = malloc(sizeof(*pml)); 590 if (pml == NULL) { 591 syslog(LOG_ERR, "%s: Cannot allocate memory", __func__); 592 goto error; 593 } 594 595 pml->pml_map.pm_prog = PMAPPROG; 596 pml->pml_map.pm_vers = PMAPVERS; 597 pml->pml_map.pm_port = PMAPPORT; 598 if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 599 if (tcptrans[0]) { 600 syslog(LOG_ERR, 601 "Cannot have more than one TCP transport"); 602 free(pml); 603 goto error; 604 } 605 tcptrans = strdup(nconf->nc_netid); 606 if (tcptrans == NULL) { 607 free(pml); 608 syslog(LOG_ERR, "%s: Cannot allocate memory", 609 __func__); 610 goto error; 611 } 612 pml->pml_map.pm_prot = IPPROTO_TCP; 613 614 /* Let's snarf the universal address */ 615 /* "h1.h2.h3.h4.p1.p2" */ 616 tcp_uaddr = taddr2uaddr(nconf, &taddr.addr); 617 } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 618 if (udptrans[0]) { 619 free(pml); 620 syslog(LOG_ERR, 621 "Cannot have more than one UDP transport"); 622 goto error; 623 } 624 udptrans = strdup(nconf->nc_netid); 625 if (udptrans == NULL) { 626 free(pml); 627 syslog(LOG_ERR, "%s: Cannot allocate memory", 628 __func__); 629 goto error; 630 } 631 pml->pml_map.pm_prot = IPPROTO_UDP; 632 633 /* Let's snarf the universal address */ 634 /* "h1.h2.h3.h4.p1.p2" */ 635 udp_uaddr = taddr2uaddr(nconf, &taddr.addr); 636 } else if (strcmp(nconf->nc_netid, "local") == 0) { 637 #ifdef IPPROTO_ST 638 pml->pml_map.pm_prot = IPPROTO_ST; 639 #else 640 pml->pml_map.pm_prot = 0; 641 #endif 642 } 643 pml->pml_next = list_pml; 644 list_pml = pml; 645 646 /* Add version 3 information */ 647 pml = malloc(sizeof(*pml)); 648 if (pml == NULL) { 649 syslog(LOG_ERR, "%s: Cannot allocate memory", __func__); 650 goto error; 651 } 652 pml->pml_map = list_pml->pml_map; 653 pml->pml_map.pm_vers = RPCBVERS; 654 pml->pml_next = list_pml; 655 list_pml = pml; 656 657 /* Add version 4 information */ 658 pml = malloc(sizeof(*pml)); 659 if (pml == NULL) { 660 syslog(LOG_ERR, "%s: Cannot allocate memory", __func__); 661 goto error; 662 } 663 pml->pml_map = list_pml->pml_map; 664 pml->pml_map.pm_vers = RPCBVERS4; 665 pml->pml_next = list_pml; 666 list_pml = pml; 667 668 /* Also add version 2 stuff to rpcbind list */ 669 rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); 670 } 671 #endif 672 673 /* version 3 registration */ 674 if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { 675 syslog(LOG_ERR, "Could not register %s version 3", 676 nconf->nc_netid); 677 goto error; 678 } 679 rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); 680 681 /* version 4 registration */ 682 if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { 683 syslog(LOG_ERR, "Could not register %s version 4", 684 nconf->nc_netid); 685 goto error; 686 } 687 rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); 688 689 /* decide if bound checking works for this transport */ 690 status = add_bndlist(nconf, &taddr.addr); 691 #ifdef RPCBIND_DEBUG 692 if (debugging) { 693 if (status < 0) { 694 fprintf(stderr, "Error in finding bind status for %s\n", 695 nconf->nc_netid); 696 } else if (status == 0) { 697 fprintf(stderr, "check binding for %s\n", 698 nconf->nc_netid); 699 } else if (status > 0) { 700 fprintf(stderr, "No check binding for %s\n", 701 nconf->nc_netid); 702 } 703 } 704 #else 705 __USE(status); 706 #endif 707 /* 708 * rmtcall only supported on CLTS transports for now. 709 */ 710 if (nconf->nc_semantics == NC_TPI_CLTS) { 711 status = create_rmtcall_fd(nconf); 712 713 #ifdef RPCBIND_DEBUG 714 if (debugging) { 715 if (status < 0) { 716 fprintf(stderr, 717 "Could not create rmtcall fd for %s\n", 718 nconf->nc_netid); 719 } else { 720 fprintf(stderr, "rmtcall fd for %s is %d\n", 721 nconf->nc_netid, status); 722 } 723 } 724 #endif 725 } 726 return (0); 727 error: 728 #ifdef RPCBIND_RUMP 729 (void)rump_sys_close(fd); 730 #else 731 (void)close(fd); 732 #endif 733 return (1); 734 } 735 736 /* 737 * Create the list of addresses that we're bound to. Normally, this 738 * list is empty because we're listening on the wildcard address 739 * (nhost == 0). If -h is specified on the command line, then 740 * bound_sa will have a list of the addresses that the program binds 741 * to specifically. This function takes that list and converts them to 742 * struct sockaddr * and stores them in bound_sa. 743 */ 744 static void 745 update_bound_sa(void) 746 { 747 struct addrinfo hints, *res = NULL; 748 int i; 749 750 if (nhosts == 0) 751 return; 752 bound_sa = calloc(nhosts, sizeof(*bound_sa)); 753 if (bound_sa == NULL) 754 err(EXIT_FAILURE, "no space for bound address array"); 755 memset(&hints, 0, sizeof(hints)); 756 hints.ai_family = PF_UNSPEC; 757 for (i = 0; i < nhosts; i++) { 758 if (getaddrinfo(hosts[i], NULL, &hints, &res) != 0) 759 continue; 760 bound_sa[i] = malloc(res->ai_addrlen); 761 if (bound_sa[i] == NULL) 762 err(EXIT_FAILURE, "no space for bound address"); 763 memcpy(bound_sa[i], res->ai_addr, res->ai_addrlen); 764 } 765 } 766 767 /* 768 * Match the sa against the list of addresses we've bound to. If 769 * we've not specifically bound to anything, we match everything. 770 * Otherwise, if the IPv4 or IPv6 address matches one of the addresses 771 * in bound_sa, we return true. If not, we return false. 772 */ 773 int 774 listen_addr(const struct sockaddr *sa) 775 { 776 int i; 777 778 /* 779 * If nhosts == 0, then there were no -h options on the 780 * command line, so all addresses are addresses we're 781 * listening to. 782 */ 783 if (nhosts == 0) 784 return 1; 785 for (i = 0; i < nhosts; i++) { 786 if (bound_sa[i] == NULL || 787 sa->sa_family != bound_sa[i]->sa_family) 788 continue; 789 switch (sa->sa_family) { 790 case AF_INET: 791 if (memcmp(&SA2SINADDR(sa), &SA2SINADDR(bound_sa[i]), 792 sizeof(struct in_addr)) == 0) 793 return (1); 794 break; 795 #ifdef INET6 796 case AF_INET6: 797 if (memcmp(&SA2SIN6ADDR(sa), &SA2SIN6ADDR(bound_sa[i]), 798 sizeof(struct in6_addr)) == 0) 799 return (1); 800 break; 801 #endif 802 default: 803 break; 804 } 805 } 806 return (0); 807 } 808 809 static void 810 rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf, 811 struct netbuf *addr) 812 { 813 rpcblist_ptr rbl; 814 815 rbl = calloc(1, sizeof(*rbl)); 816 if (rbl == NULL) { 817 syslog(LOG_ERR, "%s: Cannot allocate memory", __func__); 818 return; 819 } 820 821 rbl->rpcb_map.r_prog = prog; 822 rbl->rpcb_map.r_vers = vers; 823 rbl->rpcb_map.r_netid = strdup(nconf->nc_netid); 824 rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr); 825 rbl->rpcb_map.r_owner = strdup(rpcbind_superuser); 826 if (rbl->rpcb_map.r_netid == NULL || 827 rbl->rpcb_map.r_addr == NULL || 828 rbl->rpcb_map.r_owner == NULL) 829 { 830 free(rbl->rpcb_map.r_netid); 831 free(rbl->rpcb_map.r_addr); 832 free(rbl->rpcb_map.r_owner); 833 free(rbl); 834 syslog(LOG_ERR, "%s: Cannot allocate memory", __func__); 835 return; 836 } 837 rbl->rpcb_next = list_rbl; /* Attach to global list */ 838 list_rbl = rbl; 839 } 840 841 /* 842 * Catch the signal and die 843 */ 844 static void 845 terminate(int signum __unused) 846 { 847 #ifndef RPCBIND_RUMP 848 close(rpcbindlockfd); 849 #endif 850 #ifdef WARMSTART 851 syslog(LOG_ERR, 852 "rpcbind terminating on signal %d. Restart with \"rpcbind -w\"", 853 signum); 854 write_warmstart(); /* Dump yourself */ 855 #endif 856 #ifdef RPCBIND_RUMP 857 exit(2); 858 #else 859 exit(EXIT_FAILURE); 860 #endif 861 } 862 863 void 864 rpcbind_abort(void) 865 { 866 #ifdef WARMSTART 867 write_warmstart(); /* Dump yourself */ 868 #endif 869 abort(); 870 } 871 872 #ifndef RPCBIND_RUMP 873 /* get command line options */ 874 static void 875 parseargs(int argc, char *argv[]) 876 { 877 int c; 878 879 #ifdef WARMSTART 880 #define WSOP "w" 881 #else 882 #define WSOP "" 883 #endif 884 #ifdef LIBWRAP 885 #define WRAPOP "W" 886 #else 887 #define WRAPOP "" 888 #endif 889 while ((c = getopt(argc, argv, "6adh:iLls" WRAPOP WSOP)) != -1) { 890 switch (c) { 891 case '6': 892 ipv6_only = 1; 893 break; 894 case 'a': 895 doabort = 1; /* when debugging, do an abort on */ 896 break; /* errors; for rpcbind developers */ 897 /* only! */ 898 case 'd': 899 debugging++; 900 break; 901 case 'h': 902 ++nhosts; 903 if (reallocarr(&hosts, nhosts, sizeof(*hosts)) != 0) 904 err(EXIT_FAILURE, "Can't allocate host array"); 905 hosts[nhosts - 1] = strdup(optarg); 906 if (hosts[nhosts - 1] == NULL) 907 err(EXIT_FAILURE, "Can't allocate host"); 908 break; 909 case 'i': 910 insecure = 1; 911 break; 912 case 'L': 913 oldstyle_local = 1; 914 break; 915 case 'l': 916 verboselog = 1; 917 break; 918 case 's': 919 runasdaemon = 1; 920 break; 921 #ifdef LIBWRAP 922 case 'W': 923 libwrap = 1; 924 break; 925 #endif 926 #ifdef WARMSTART 927 case 'w': 928 warmstart = 1; 929 break; 930 #endif 931 default: /* error */ 932 fprintf(stderr, "usage: rpcbind [-Idwils]\n"); 933 fprintf(stderr, 934 "Usage: %s [-6adiLls%s%s] [-h bindip]\n", 935 getprogname(), WRAPOP, WSOP); 936 exit(EXIT_FAILURE); 937 } 938 } 939 if (doabort && !debugging) { 940 fprintf(stderr, 941 "-a (abort) specified without -d (debugging) -- ignored.\n"); 942 doabort = 0; 943 } 944 #undef WRAPOP 945 #undef WSOP 946 } 947 #endif 948 949 void 950 reap(int dummy __unused) 951 { 952 int save_errno = errno; 953 954 while (wait3(NULL, WNOHANG, NULL) > 0) 955 ; 956 errno = save_errno; 957 } 958 959 void 960 toggle_verboselog(int dummy __unused) 961 { 962 verboselog = !verboselog; 963 } 964