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