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