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