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