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