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