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