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