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