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