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