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