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 int terminate_rfd; /* Pipefd to wake on signal */ 83 volatile sig_atomic_t doterminate = 0; /* Terminal signal received */ 84 rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */ 85 int rpcbindlockfd; 86 87 /* who to suid to if -s is given */ 88 #define RUN_AS "daemon" 89 90 #define RPCBINDDLOCK "/var/run/rpcbind.lock" 91 92 static int runasdaemon = 0; 93 int insecure = 0; 94 int oldstyle_local = 0; 95 #ifdef LIBWRAP 96 int libwrap = 0; 97 #endif 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 { 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 syslog(LOG_ERR, 569 "cannot have more than one TCP transport"); 570 goto error; 571 } 572 tcptrans = strdup(nconf->nc_netid); 573 pml->pml_map.pm_prot = IPPROTO_TCP; 574 575 /* Let's snarf the universal address */ 576 /* "h1.h2.h3.h4.p1.p2" */ 577 tcp_uaddr = taddr2uaddr(nconf, &taddr.addr); 578 } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 579 if (udptrans[0]) { 580 syslog(LOG_ERR, 581 "cannot have more than one UDP transport"); 582 goto error; 583 } 584 udptrans = strdup(nconf->nc_netid); 585 pml->pml_map.pm_prot = IPPROTO_UDP; 586 587 /* Let's snarf the universal address */ 588 /* "h1.h2.h3.h4.p1.p2" */ 589 udp_uaddr = taddr2uaddr(nconf, &taddr.addr); 590 } else if (strcmp(nconf->nc_netid, "local") == 0) 591 pml->pml_map.pm_prot = IPPROTO_ST; 592 else if (strcmp(nconf->nc_netid, "unix") == 0) 593 pml->pml_map.pm_prot = IPPROTO_ST; 594 pml->pml_next = list_pml; 595 list_pml = pml; 596 597 /* Add version 3 information */ 598 pml = malloc(sizeof (struct pmaplist)); 599 if (pml == NULL) { 600 syslog(LOG_ERR, "no memory!"); 601 exit(1); 602 } 603 pml->pml_map = list_pml->pml_map; 604 pml->pml_map.pm_vers = RPCBVERS; 605 pml->pml_next = list_pml; 606 list_pml = pml; 607 608 /* Add version 4 information */ 609 pml = malloc (sizeof (struct pmaplist)); 610 if (pml == NULL) { 611 syslog(LOG_ERR, "no memory!"); 612 exit(1); 613 } 614 pml->pml_map = list_pml->pml_map; 615 pml->pml_map.pm_vers = RPCBVERS4; 616 pml->pml_next = list_pml; 617 list_pml = pml; 618 619 /* Also add version 2 stuff to rpcbind list */ 620 rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); 621 } 622 #endif 623 624 /* version 3 registration */ 625 if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { 626 syslog(LOG_ERR, "could not register %s version 3", 627 nconf->nc_netid); 628 goto error; 629 } 630 rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); 631 632 /* version 4 registration */ 633 if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { 634 syslog(LOG_ERR, "could not register %s version 4", 635 nconf->nc_netid); 636 goto error; 637 } 638 rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); 639 640 /* decide if bound checking works for this transport */ 641 status = add_bndlist(nconf, &taddr.addr); 642 #ifdef BIND_DEBUG 643 if (debugging) { 644 if (status < 0) { 645 fprintf(stderr, "Error in finding bind status for %s\n", 646 nconf->nc_netid); 647 } else if (status == 0) { 648 fprintf(stderr, "check binding for %s\n", 649 nconf->nc_netid); 650 } else if (status > 0) { 651 fprintf(stderr, "No check binding for %s\n", 652 nconf->nc_netid); 653 } 654 } 655 #endif 656 /* 657 * rmtcall only supported on CLTS transports for now. 658 */ 659 if (nconf->nc_semantics == NC_TPI_CLTS) { 660 status = create_rmtcall_fd(nconf); 661 662 #ifdef BIND_DEBUG 663 if (debugging) { 664 if (status < 0) { 665 fprintf(stderr, 666 "Could not create rmtcall fd for %s\n", 667 nconf->nc_netid); 668 } else { 669 fprintf(stderr, "rmtcall fd for %s is %d\n", 670 nconf->nc_netid, status); 671 } 672 } 673 #endif 674 } 675 return (0); 676 error: 677 close(fd); 678 return (1); 679 } 680 681 /* 682 * Create the list of addresses that we're bound to. Normally, this 683 * list is empty because we're listening on the wildcard address 684 * (nhost == 0). If -h is specified on the command line, then 685 * bound_sa will have a list of the addresses that the program binds 686 * to specifically. This function takes that list and converts them to 687 * struct sockaddr * and stores them in bound_sa. 688 */ 689 static void 690 update_bound_sa(void) 691 { 692 struct addrinfo hints, *res = NULL; 693 int i; 694 695 if (nhosts == 0) 696 return; 697 bound_sa = malloc(sizeof(*bound_sa) * nhosts); 698 memset(&hints, 0, sizeof(hints)); 699 hints.ai_family = PF_UNSPEC; 700 for (i = 0; i < nhosts; i++) { 701 if (getaddrinfo(hosts[i], NULL, &hints, &res) != 0) 702 continue; 703 bound_sa[i] = malloc(res->ai_addrlen); 704 memcpy(bound_sa[i], res->ai_addr, res->ai_addrlen); 705 } 706 } 707 708 /* 709 * Match the sa against the list of addresses we've bound to. If 710 * we've not specifically bound to anything, we match everything. 711 * Otherwise, if the IPv4 or IPv6 address matches one of the addresses 712 * in bound_sa, we return true. If not, we return false. 713 */ 714 int 715 listen_addr(const struct sockaddr *sa) 716 { 717 int i; 718 719 /* 720 * If nhosts == 0, then there were no -h options on the 721 * command line, so all addresses are addresses we're 722 * listening to. 723 */ 724 if (nhosts == 0) 725 return 1; 726 for (i = 0; i < nhosts; i++) { 727 if (bound_sa[i] == NULL || 728 sa->sa_family != bound_sa[i]->sa_family) 729 continue; 730 switch (sa->sa_family) { 731 case AF_INET: 732 if (memcmp(&SA2SINADDR(sa), &SA2SINADDR(bound_sa[i]), 733 sizeof(struct in_addr)) == 0) 734 return (1); 735 break; 736 #ifdef INET6 737 case AF_INET6: 738 if (memcmp(&SA2SIN6ADDR(sa), &SA2SIN6ADDR(bound_sa[i]), 739 sizeof(struct in6_addr)) == 0) 740 return (1); 741 break; 742 #endif 743 default: 744 break; 745 } 746 } 747 return (0); 748 } 749 750 static void 751 rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf, 752 struct netbuf *addr) 753 { 754 rpcblist_ptr rbl; 755 756 rbl = malloc(sizeof (rpcblist)); 757 if (rbl == NULL) { 758 syslog(LOG_ERR, "no memory!"); 759 exit(1); 760 } 761 762 rbl->rpcb_map.r_prog = prog; 763 rbl->rpcb_map.r_vers = vers; 764 rbl->rpcb_map.r_netid = strdup(nconf->nc_netid); 765 rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr); 766 rbl->rpcb_map.r_owner = strdup(superuser); 767 rbl->rpcb_next = list_rbl; /* Attach to global list */ 768 list_rbl = rbl; 769 } 770 771 /* 772 * Catch the signal and die 773 */ 774 static void 775 terminate(int signum) 776 { 777 char c = '\0'; 778 ssize_t wr; 779 780 doterminate = signum; 781 wr = write(terminate_wfd, &c, 1); 782 if (wr < 1) 783 _exit(2); 784 } 785 786 void 787 rpcbind_abort(void) 788 { 789 #ifdef WARMSTART 790 write_warmstart(); /* Dump yourself */ 791 #endif 792 abort(); 793 } 794 795 /* get command line options */ 796 static void 797 parseargs(int argc, char *argv[]) 798 { 799 int c; 800 801 #ifdef WARMSTART 802 #define WSOP "w" 803 #else 804 #define WSOP "" 805 #endif 806 #ifdef LIBWRAP 807 #define WRAPOP "W" 808 #else 809 #define WRAPOP "" 810 #endif 811 while ((c = getopt(argc, argv, "6adh:iLls" WRAPOP WSOP)) != -1) { 812 switch (c) { 813 case '6': 814 ipv6_only = 1; 815 break; 816 case 'a': 817 doabort = 1; /* when debugging, do an abort on */ 818 break; /* errors; for rpcbind developers */ 819 /* only! */ 820 case 'd': 821 debugging = 1; 822 break; 823 case 'h': 824 ++nhosts; 825 hosts = realloc(hosts, nhosts * sizeof(char *)); 826 if (hosts == NULL) 827 errx(1, "Out of memory"); 828 hosts[nhosts - 1] = strdup(optarg); 829 if (hosts[nhosts - 1] == NULL) 830 errx(1, "Out of memory"); 831 break; 832 case 'i': 833 insecure = 1; 834 break; 835 case 'L': 836 oldstyle_local = 1; 837 break; 838 case 'l': 839 verboselog = 1; 840 break; 841 case 's': 842 runasdaemon = 1; 843 break; 844 #ifdef LIBWRAP 845 case 'W': 846 libwrap = 1; 847 break; 848 #endif 849 #ifdef WARMSTART 850 case 'w': 851 warmstart = 1; 852 break; 853 #endif 854 default: /* error */ 855 fprintf(stderr, 856 "usage: rpcbind [-6adiLls%s%s] [-h bindip]\n", 857 WRAPOP, WSOP); 858 exit (1); 859 } 860 } 861 if (doabort && !debugging) { 862 fprintf(stderr, 863 "-a (abort) specified without -d (debugging) -- ignored.\n"); 864 doabort = 0; 865 } 866 #undef WSOP 867 } 868 869 void 870 reap(int dummy __unused) 871 { 872 int save_errno = errno; 873 874 while (wait3(NULL, WNOHANG, NULL) > 0) 875 ; 876 errno = save_errno; 877 } 878 879 void 880 toggle_verboselog(int dummy __unused) 881 { 882 verboselog = !verboselog; 883 } 884