xref: /openbsd/usr.sbin/ripd/ripd.c (revision f1b790a5)
1 /*	$OpenBSD: ripd.c,v 1.44 2024/11/21 13:38:15 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
5  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/queue.h>
25 #include <sys/time.h>
26 #include <sys/stat.h>
27 #include <sys/wait.h>
28 #include <sys/sysctl.h>
29 
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 
33 #include <event.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <pwd.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <signal.h>
41 #include <unistd.h>
42 
43 #include "rip.h"
44 #include "ripd.h"
45 #include "ripe.h"
46 #include "log.h"
47 #include "control.h"
48 #include "rde.h"
49 
50 __dead void		 usage(void);
51 void			 main_sig_handler(int, short, void *);
52 __dead void		 ripd_shutdown(void);
53 void			 main_dispatch_ripe(int, short, void *);
54 void			 main_dispatch_rde(int, short, void *);
55 
56 int			 pipe_parent2ripe[2];
57 int			 pipe_parent2rde[2];
58 int			 pipe_ripe2rde[2];
59 
60 struct ripd_conf	*conf = NULL;
61 static struct imsgev	*iev_ripe;
62 static struct imsgev	*iev_rde;
63 
64 pid_t			 ripe_pid = 0;
65 pid_t			 rde_pid = 0;
66 
67 __dead void
usage(void)68 usage(void)
69 {
70 	extern char *__progname;
71 
72 	fprintf(stderr,
73 	    "usage: %s [-dnv] [-D macro=value] [-f file] [-s socket]\n",
74 	    __progname);
75 	exit(1);
76 }
77 
78 void
main_sig_handler(int sig,short event,void * arg)79 main_sig_handler(int sig, short event, void *arg)
80 {
81 	/* signal handler rules don't apply, libevent decouples for us */
82 	switch (sig) {
83 	case SIGTERM:
84 	case SIGINT:
85 		ripd_shutdown();
86 		/* NOTREACHED */
87 	case SIGHUP:
88 		/* reconfigure */
89 		/* ... */
90 		break;
91 	default:
92 		fatalx("unexpected signal");
93 		/* NOTREACHED */
94 	}
95 }
96 
97 int
main(int argc,char * argv[])98 main(int argc, char *argv[])
99 {
100 	struct event	 ev_sigint, ev_sigterm, ev_sighup;
101 	int		 mib[4];
102 	int		 debug = 0;
103 	int		 ipforwarding;
104 	int		 ch;
105 	int		 opts = 0;
106 	char		*conffile;
107 	char 		*sockname;
108 	size_t		 len;
109 
110 	conffile = CONF_FILE;
111 	log_procname = "parent";
112 	sockname = RIPD_SOCKET;
113 
114 	log_init(1);	/* log to stderr until daemonized */
115 	log_verbose(1);
116 
117 	while ((ch = getopt(argc, argv, "cdD:f:ns:v")) != -1) {
118 		switch (ch) {
119 		case 'c':
120 			opts |= RIPD_OPT_FORCE_DEMOTE;
121 			break;
122 		case 'd':
123 			debug = 1;
124 			break;
125 		case 'D':
126 			if (cmdline_symset(optarg) < 0)
127 				log_warnx("could not parse macro definition %s",
128 				    optarg);
129 			break;
130 		case 'f':
131 			conffile = optarg;
132 			break;
133 		case 'n':
134 			opts |= RIPD_OPT_NOACTION;
135 			break;
136 		case 's':
137 			sockname = optarg;
138 			break;
139 		case 'v':
140 			if (opts & RIPD_OPT_VERBOSE)
141 				opts |= RIPD_OPT_VERBOSE2;
142 			opts |= RIPD_OPT_VERBOSE;
143 			break;
144 		default:
145 			usage();
146 			/* NOTREACHED */
147 		}
148 	}
149 
150 	argc -= optind;
151 	argv += optind;
152 	if (argc > 0)
153 		usage();
154 
155 	mib[0] = CTL_NET;
156 	mib[1] = PF_INET;
157 	mib[2] = IPPROTO_IP;
158 	mib[3] = IPCTL_FORWARDING;
159 	len = sizeof(ipforwarding);
160 	if (sysctl(mib, 4, &ipforwarding, &len, NULL, 0) == -1)
161 		err(1, "sysctl");
162 
163 	if (!ipforwarding)
164 		log_warnx("WARNING: IP forwarding NOT enabled");
165 
166 	/* fetch interfaces early */
167 	kif_init();
168 
169 	/* parse config file */
170 	if ((conf = parse_config(conffile, opts)) == NULL )
171 		exit(1);
172 	conf->csock = sockname;
173 
174 	if (conf->opts & RIPD_OPT_NOACTION) {
175 		if (conf->opts & RIPD_OPT_VERBOSE)
176 			print_config(conf);
177 		else
178 			fprintf(stderr, "configuration OK\n");
179 		exit(0);
180 	}
181 
182 	/* check for root privileges */
183 	if (geteuid())
184 		errx(1, "need root privileges");
185 
186 	/* check for ripd user */
187 	if (getpwnam(RIPD_USER) == NULL)
188 		errx(1, "unknown user %s", RIPD_USER);
189 
190 	log_init(debug);
191 	log_verbose(conf->opts & RIPD_OPT_VERBOSE);
192 
193 	if (!debug)
194 		daemon(1, 0);
195 
196 	log_info("startup");
197 
198 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
199 	    PF_UNSPEC, pipe_parent2ripe) == -1)
200 		fatal("socketpair");
201 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
202 	    PF_UNSPEC, pipe_parent2rde) == -1)
203 		fatal("socketpair");
204 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
205 	    PF_UNSPEC, pipe_ripe2rde) == -1)
206 		fatal("socketpair");
207 
208 	/* start children */
209 	rde_pid = rde(conf, pipe_parent2rde, pipe_ripe2rde, pipe_parent2ripe);
210 	ripe_pid = ripe(conf, pipe_parent2ripe, pipe_ripe2rde, pipe_parent2rde);
211 
212 	/* no filesystem visibility */
213 	if (unveil("/", "") == -1)
214 		fatal("unveil /");
215 	if (unveil(NULL, NULL) == -1)
216 		fatal("unveil");
217 
218 	event_init();
219 
220 	/* setup signal handler */
221 	signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL);
222 	signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL);
223 	signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL);
224 	signal_add(&ev_sigint, NULL);
225 	signal_add(&ev_sigterm, NULL);
226 	signal_add(&ev_sighup, NULL);
227 	signal(SIGPIPE, SIG_IGN);
228 
229 	/* setup pipes to children */
230 	close(pipe_parent2ripe[1]);
231 	close(pipe_parent2rde[1]);
232 	close(pipe_ripe2rde[0]);
233 	close(pipe_ripe2rde[1]);
234 
235 	if ((iev_ripe = malloc(sizeof(struct imsgev))) == NULL ||
236 	    (iev_rde = malloc(sizeof(struct imsgev))) == NULL)
237 		fatal(NULL);
238 	if (imsgbuf_init(&iev_ripe->ibuf, pipe_parent2ripe[0]) == -1)
239 		fatal(NULL);
240 	iev_ripe->handler = main_dispatch_ripe;
241 	if (imsgbuf_init(&iev_rde->ibuf, pipe_parent2rde[0]) == -1)
242 		fatal(NULL);
243 	iev_rde->handler = main_dispatch_rde;
244 
245 	/* setup event handler */
246 	iev_ripe->events = EV_READ;
247 	event_set(&iev_ripe->ev, iev_ripe->ibuf.fd, iev_ripe->events,
248 	    iev_ripe->handler, iev_ripe);
249 	event_add(&iev_ripe->ev, NULL);
250 
251 	iev_rde->events = EV_READ;
252 	event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
253 	    iev_rde->handler, iev_rde);
254 	event_add(&iev_rde->ev, NULL);
255 
256 	if (kr_init(!(conf->flags & RIPD_FLAG_NO_FIB_UPDATE),
257 	    conf->rdomain, conf->fib_priority) == -1)
258 		fatalx("kr_init failed");
259 
260 	event_dispatch();
261 
262 	ripd_shutdown();
263 	/* NOTREACHED */
264 	return (0);
265 }
266 
267 __dead void
ripd_shutdown(void)268 ripd_shutdown(void)
269 {
270 	struct iface	*i;
271 	pid_t		 pid;
272 	int		 status;
273 
274 	/* close pipes */
275 	imsgbuf_clear(&iev_ripe->ibuf);
276 	close(iev_ripe->ibuf.fd);
277 	imsgbuf_clear(&iev_rde->ibuf);
278 	close(iev_rde->ibuf.fd);
279 
280 	while ((i = LIST_FIRST(&conf->iface_list)) != NULL) {
281 		LIST_REMOVE(i, entry);
282 		if_del(i);
283 	}
284 
285 	kr_shutdown();
286 
287 	log_debug("waiting for children to terminate");
288 	do {
289 		pid = wait(&status);
290 		if (pid == -1) {
291 			if (errno != EINTR && errno != ECHILD)
292 				fatal("wait");
293 		} else if (WIFSIGNALED(status))
294 			log_warnx("%s terminated; signal %d",
295 			    (pid == rde_pid) ? "route decision engine" :
296 			    "rip engine", WTERMSIG(status));
297 	} while (pid != -1 || (pid == -1 && errno == EINTR));
298 
299 	free(iev_ripe);
300 	free(iev_rde);
301 	free(conf);
302 
303 	log_info("terminating");
304 	exit(0);
305 }
306 
307 /* imsg handling */
308 void
main_dispatch_ripe(int fd,short event,void * bula)309 main_dispatch_ripe(int fd, short event, void *bula)
310 {
311 	struct imsgev		*iev = bula;
312 	struct imsgbuf		*ibuf = &iev->ibuf;
313 	struct imsg		 imsg;
314 	struct demote_msg	 dmsg;
315 	ssize_t			 n;
316 	int			 shut = 0, verbose;
317 
318 	if (event & EV_READ) {
319 		if ((n = imsgbuf_read(ibuf)) == -1)
320 			fatal("imsgbuf_read error");
321 		if (n == 0)	/* connection closed */
322 			shut = 1;
323 	}
324 	if (event & EV_WRITE) {
325 		if (imsgbuf_write(ibuf) == -1) {
326 			if (errno == EPIPE)	/* connection closed */
327 				shut = 1;
328 			else
329 				fatal("imsgbuf_write");
330 		}
331 	}
332 
333 	for (;;) {
334 		if ((n = imsg_get(ibuf, &imsg)) == -1)
335 			fatal("imsg_get");
336 
337 		if (n == 0)
338 			break;
339 
340 		switch (imsg.hdr.type) {
341 		case IMSG_CTL_RELOAD:
342 			/* XXX reconfig */
343 			break;
344 		case IMSG_CTL_FIB_COUPLE:
345 			kr_fib_couple();
346 			break;
347 		case IMSG_CTL_FIB_DECOUPLE:
348 			kr_fib_decouple();
349 			break;
350 		case IMSG_CTL_KROUTE:
351 		case IMSG_CTL_KROUTE_ADDR:
352 			kr_show_route(&imsg);
353 			break;
354 		case IMSG_CTL_IFINFO:
355 			if (imsg.hdr.len == IMSG_HEADER_SIZE)
356 				kr_ifinfo(NULL, imsg.hdr.pid);
357 			else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ)
358 				kr_ifinfo(imsg.data, imsg.hdr.pid);
359 			else
360 				log_warnx("IFINFO request with wrong len");
361 			break;
362 		case IMSG_DEMOTE:
363 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(dmsg))
364 				fatalx("invalid size of OE request");
365 			memcpy(&dmsg, imsg.data, sizeof(dmsg));
366 			carp_demote_set(dmsg.demote_group, dmsg.level);
367 			break;
368 		case IMSG_CTL_LOG_VERBOSE:
369 			/* already checked by ripe */
370 			memcpy(&verbose, imsg.data, sizeof(verbose));
371 			log_verbose(verbose);
372 			break;
373 		default:
374 			log_debug("main_dispatch_ripe: error handling imsg %d",
375 			    imsg.hdr.type);
376 			break;
377 		}
378 		imsg_free(&imsg);
379 	}
380 	if (!shut)
381 		imsg_event_add(iev);
382 	else {
383 		/* this pipe is dead, so remove the event handler */
384 		event_del(&iev->ev);
385 		event_loopexit(NULL);
386 	}
387 }
388 
389 void
main_dispatch_rde(int fd,short event,void * bula)390 main_dispatch_rde(int fd, short event, void *bula)
391 {
392 	struct imsgev	*iev = bula;
393 	struct imsgbuf	*ibuf = &iev->ibuf;
394 	struct imsg	 imsg;
395 	ssize_t		 n;
396 	int		 shut = 0;
397 
398 	if (event & EV_READ) {
399 		if ((n = imsgbuf_read(ibuf)) == -1)
400 			fatal("imsgbuf_read error");
401 		if (n == 0)	/* connection closed */
402 			shut = 1;
403 	}
404 	if (event & EV_WRITE) {
405 		if (imsgbuf_write(ibuf) == -1) {
406 			if (errno == EPIPE)	/* connection closed */
407 				shut = 1;
408 			else
409 				fatal("imsgbuf_write");
410 		}
411 	}
412 
413 	for (;;) {
414 		if ((n = imsg_get(ibuf, &imsg)) == -1)
415 			fatal("imsg_get");
416 
417 		if (n == 0)
418 			break;
419 
420 		switch (imsg.hdr.type) {
421 		case IMSG_KROUTE_CHANGE:
422 			if (kr_change(imsg.data))
423 				log_warn("main_dispatch_rde: error changing "
424 				    "route");
425 			break;
426 		case IMSG_KROUTE_DELETE:
427 			if (kr_delete(imsg.data))
428 				log_warn("main_dispatch_rde: error deleting "
429 				    "route");
430 			break;
431 		default:
432 			log_debug("main_dispatch_rde: error handling imsg %d",
433 			    imsg.hdr.type);
434 			break;
435 		}
436 		imsg_free(&imsg);
437 	}
438 	if (!shut)
439 		imsg_event_add(iev);
440 	else {
441 		/* this pipe is dead, so remove the event handler */
442 		event_del(&iev->ev);
443 		event_loopexit(NULL);
444 	}
445 }
446 
447 void
main_imsg_compose_ripe(int type,pid_t pid,void * data,u_int16_t datalen)448 main_imsg_compose_ripe(int type, pid_t pid, void *data, u_int16_t datalen)
449 {
450 	imsg_compose_event(iev_ripe, type, 0, pid, -1, data, datalen);
451 }
452 
453 void
main_imsg_compose_rde(int type,pid_t pid,void * data,u_int16_t datalen)454 main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen)
455 {
456 	imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen);
457 }
458 
459 int
rip_redistribute(struct kroute * kr)460 rip_redistribute(struct kroute *kr)
461 {
462 	struct redistribute	*r;
463 	u_int8_t		 is_default = 0;
464 
465 	if (kr->flags & F_RIPD_INSERTED)
466 		return (1);
467 
468 	/* only allow 0.0.0.0/0 via REDIST_DEFAULT */
469 	if (kr->prefix.s_addr == INADDR_ANY && kr->netmask.s_addr == INADDR_ANY)
470 		is_default = 1;
471 
472 	SIMPLEQ_FOREACH(r, &conf->redist_list, entry) {
473 		switch (r->type & ~REDIST_NO) {
474 		case REDIST_LABEL:
475 			if (kr->rtlabel == r->label)
476 				return (r->type & REDIST_NO ? 0 : 1);
477 			break;
478 		case REDIST_STATIC:
479 			/*
480 			 * Dynamic routes are not redistributable. Placed here
481 			 * so that link local addresses can be redistributed
482 			 * via a rtlabel.
483 			 */
484 			if (is_default)
485 				continue;
486 			if (kr->flags & F_DYNAMIC)
487 				continue;
488 			if (kr->flags & F_STATIC)
489 				return (r->type & REDIST_NO ? 0 : 1);
490 			break;
491 		case REDIST_CONNECTED:
492 			if (is_default)
493 				continue;
494 			if (kr->flags & F_DYNAMIC)
495 				continue;
496 			if (kr->flags & F_CONNECTED)
497 				return (r->type & REDIST_NO ? 0 : 1);
498 			break;
499 		case REDIST_ADDR:
500 			if (kr->flags & F_DYNAMIC)
501 				continue;
502 
503 			if (r->addr.s_addr == INADDR_ANY &&
504 			    r->mask.s_addr == INADDR_ANY) {
505 				if (is_default)
506 					return (r->type & REDIST_NO? 0 : 1);
507 				else
508 					return (0);
509 			}
510 
511 			if ((kr->prefix.s_addr & r->mask.s_addr) ==
512 			    (r->addr.s_addr & r->mask.s_addr) &&
513 			    (kr->netmask.s_addr & r->mask.s_addr) ==
514 			    r->mask.s_addr)
515 				return (r->type & REDIST_NO? 0 : 1);
516 			break;
517 		case REDIST_DEFAULT:
518 			if (is_default)
519 				return (r->type & REDIST_NO? 0 : 1);
520 			break;
521 		}
522 	}
523 
524 	return (0);
525 }
526 
527 void
imsg_event_add(struct imsgev * iev)528 imsg_event_add(struct imsgev *iev)
529 {
530 	if (iev->handler == NULL) {
531 		imsgbuf_flush(&iev->ibuf);
532 		return;
533 	}
534 
535 	iev->events = EV_READ;
536 	if (imsgbuf_queuelen(&iev->ibuf) > 0)
537 		iev->events |= EV_WRITE;
538 
539 	event_del(&iev->ev);
540 	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
541 	event_add(&iev->ev, NULL);
542 }
543 
544 int
imsg_compose_event(struct imsgev * iev,u_int16_t type,u_int32_t peerid,pid_t pid,int fd,void * data,u_int16_t datalen)545 imsg_compose_event(struct imsgev *iev, u_int16_t type,
546     u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen)
547 {
548 	int	ret;
549 
550 	if ((ret = imsg_compose(&iev->ibuf, type, peerid,
551 	    pid, fd, data, datalen)) != -1)
552 		imsg_event_add(iev);
553 	return (ret);
554 }
555