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