xref: /openbsd-src/usr.sbin/ripd/ripe.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: ripe.c,v 1.22 2016/09/03 10:28:08 renato 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 <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <net/if_types.h>
28 #include <stdlib.h>
29 #include <signal.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <pwd.h>
33 #include <unistd.h>
34 #include <event.h>
35 #include <err.h>
36 #include <errno.h>
37 #include <stdio.h>
38 
39 #include "ripd.h"
40 #include "rip.h"
41 #include "ripe.h"
42 #include "log.h"
43 #include "control.h"
44 
45 void		 ripe_sig_handler(int, short, void *);
46 __dead void	 ripe_shutdown(void);
47 
48 struct ripd_conf	*oeconf = NULL;
49 struct imsgev		*iev_main;
50 struct imsgev		*iev_rde;
51 
52 /* ARGSUSED */
53 void
54 ripe_sig_handler(int sig, short event, void *bula)
55 {
56 	switch (sig) {
57 	case SIGINT:
58 	case SIGTERM:
59 		ripe_shutdown();
60 		/* NOTREACHED */
61 	default:
62 		fatalx("unexpected signal");
63 	}
64 }
65 
66 /* rip engine */
67 pid_t
68 ripe(struct ripd_conf *xconf, int pipe_parent2ripe[2], int pipe_ripe2rde[2],
69     int pipe_parent2rde[2])
70 {
71 	struct event		 ev_sigint, ev_sigterm;
72 	struct sockaddr_in	 addr;
73 	struct iface		*iface = NULL;
74 	struct passwd		*pw;
75 	struct redistribute	*r;
76 	pid_t			 pid;
77 
78 	switch (pid = fork()) {
79 	case -1:
80 		fatal("cannot fork");
81 	case 0:
82 		break;
83 	default:
84 		return (pid);
85 	}
86 
87 	/* create ripd control socket outside chroot */
88 	if (control_init(xconf->csock) == -1)
89 		fatalx("control socket setup failed");
90 
91 	addr.sin_family = AF_INET;
92 	addr.sin_port = htons(RIP_PORT);
93 	addr.sin_addr.s_addr = INADDR_ANY;
94 
95 	if ((xconf->rip_socket = socket(AF_INET,
96 	    SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
97 	    IPPROTO_UDP)) == -1)
98 		fatalx("error creating socket");
99 
100 	if (bind(xconf->rip_socket, (struct sockaddr *)&addr,
101 	    sizeof(addr)) == -1)
102 		fatal("error binding socket");
103 
104 	/* set some defaults */
105 	if (if_set_opt(xconf->rip_socket) == -1)
106 		fatal("if_set_opt");
107 
108 	if (if_set_mcast_ttl(xconf->rip_socket, IP_DEFAULT_MULTICAST_TTL) == -1)
109 		fatal("if_set_mcast_ttl");
110 
111 	if (if_set_mcast_loop(xconf->rip_socket) == -1)
112 		fatal("if_set_mcast_loop");
113 
114 	if (if_set_tos(xconf->rip_socket, IPTOS_PREC_INTERNETCONTROL) == -1)
115 		fatal("if_set_tos");
116 
117 	if_set_recvbuf(xconf->rip_socket);
118 
119 	oeconf = xconf;
120 
121 	if ((pw = getpwnam(RIPD_USER)) == NULL)
122 		fatal("getpwnam");
123 
124 	if (chroot(pw->pw_dir) == -1)
125 		fatal("chroot");
126 	if (chdir("/") == -1)
127 		fatal("chdir(\"/\")");
128 
129 	setproctitle("rip engine");
130 	ripd_process = PROC_RIP_ENGINE;
131 	log_procname = log_procnames[ripd_process];
132 
133 	if (setgroups(1, &pw->pw_gid) ||
134 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
135 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
136 		fatal("can't drop privileges");
137 
138 	event_init();
139 	nbr_init(NBR_HASHSIZE);
140 
141 	/* setup signal handler */
142 	signal_set(&ev_sigint, SIGINT, ripe_sig_handler, NULL);
143 	signal_set(&ev_sigterm, SIGTERM, ripe_sig_handler, NULL);
144 	signal_add(&ev_sigint, NULL);
145 	signal_add(&ev_sigterm, NULL);
146 	signal(SIGPIPE, SIG_IGN);
147 	signal(SIGHUP, SIG_IGN);
148 
149 	/* setup pipes */
150 	close(pipe_parent2ripe[0]);
151 	close(pipe_ripe2rde[1]);
152 	close(pipe_parent2rde[0]);
153 	close(pipe_parent2rde[1]);
154 
155 	if ((iev_rde = malloc(sizeof(struct imsgev))) == NULL ||
156 	    (iev_main = malloc(sizeof(struct imsgev))) == NULL)
157 		fatal(NULL);
158 	imsg_init(&iev_rde->ibuf, pipe_ripe2rde[0]);
159 	iev_rde->handler = ripe_dispatch_rde;
160 	imsg_init(&iev_main->ibuf, pipe_parent2ripe[1]);
161 	iev_main->handler = ripe_dispatch_main;
162 
163 	/* setup event handler */
164 	iev_rde->events = EV_READ;
165 	event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
166 	    iev_rde->handler, iev_rde);
167 	event_add(&iev_rde->ev, NULL);
168 
169 	iev_main->events = EV_READ;
170 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
171 	    iev_main->handler, iev_main);
172 	event_add(&iev_main->ev, NULL);
173 
174 	event_set(&oeconf->ev, oeconf->rip_socket, EV_READ|EV_PERSIST,
175 	    recv_packet, oeconf);
176 	event_add(&oeconf->ev, NULL);
177 
178 	/* remove unneeded config stuff */
179 	while ((r = SIMPLEQ_FIRST(&oeconf->redist_list)) != NULL) {
180 		SIMPLEQ_REMOVE_HEAD(&oeconf->redist_list, entry);
181 		free(r);
182 	}
183 
184 	/* listen on ripd control socket */
185 	TAILQ_INIT(&ctl_conns);
186 	control_listen();
187 
188 	if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
189 		fatal("ripe");
190 
191 	/* start interfaces */
192 	LIST_FOREACH(iface, &xconf->iface_list, entry) {
193 		if_init(xconf, iface);
194 		if (if_fsm(iface, IF_EVT_UP))
195 			log_debug("ripe: error starting interface: %s",
196 			    iface->name);
197 	}
198 
199 	evtimer_set(&oeconf->report_timer, report_timer, oeconf);
200 	start_report_timer();
201 
202 	ripe_imsg_compose_rde(IMSG_FULL_REQUEST, 0, 0, NULL, 0);
203 
204 	event_dispatch();
205 
206 	ripe_shutdown();
207 	/* NOTREACHED */
208 	return (0);
209 }
210 
211 int
212 ripe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
213 {
214 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
215 }
216 
217 int
218 ripe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid,
219     void *data, u_int16_t datalen)
220 {
221 	return (imsg_compose_event(iev_rde, type, peerid, pid, -1,
222 	    data, datalen));
223 }
224 
225 /* ARGSUSED */
226 void
227 ripe_dispatch_main(int fd, short event, void *bula)
228 {
229 	struct imsg	 imsg;
230 	struct imsgev	*iev = bula;
231 	struct imsgbuf	*ibuf = &iev->ibuf;
232 	struct kif	*kif;
233 	struct iface	*iface;
234 	ssize_t		 n;
235 	int		 link_ok, shut = 0;
236 
237 	if (event & EV_READ) {
238 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
239 			fatal("imsg_read error");
240 		if (n == 0)	/* connection closed */
241 			shut = 1;
242 	}
243 	if (event & EV_WRITE) {
244 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
245 			fatal("msgbuf_write");
246 		if (n == 0)	/* connection closed */
247 			shut = 1;
248 	}
249 
250 	for (;;) {
251 		if ((n = imsg_get(ibuf, &imsg)) == -1)
252 			fatal("ripe_dispatch_main: imsg_get error");
253 		if (n == 0)
254 			break;
255 
256 		switch (imsg.hdr.type) {
257 		case IMSG_IFINFO:
258 			if (imsg.hdr.len - IMSG_HEADER_SIZE !=
259 			    sizeof(struct kif))
260 				fatalx("IFINFO imsg with wrong len");
261 			kif = imsg.data;
262 			link_ok = (kif->flags & IFF_UP) &&
263 			    LINK_STATE_IS_UP(kif->link_state);
264 
265 			LIST_FOREACH(iface, &oeconf->iface_list, entry) {
266 				if (kif->ifindex == iface->ifindex) {
267 					iface->flags = kif->flags;
268 					iface->linkstate = kif->link_state;
269 
270 					if (link_ok) {
271 						if_fsm(iface, IF_EVT_UP);
272 						log_warnx("interface %s up",
273 						    iface->name);
274 					} else {
275 						if_fsm(iface, IF_EVT_DOWN);
276 						log_warnx("interface %s down",
277 						    iface->name);
278 					}
279 				}
280 			}
281 			break;
282 		case IMSG_CTL_IFINFO:
283 		case IMSG_CTL_KROUTE:
284 		case IMSG_CTL_KROUTE_ADDR:
285 		case IMSG_CTL_END:
286 			control_imsg_relay(&imsg);
287 			break;
288 		default:
289 			log_debug("ripe_dispatch_main: error handling imsg %d",
290 			    imsg.hdr.type);
291 			break;
292 		}
293 		imsg_free(&imsg);
294 	}
295 	if (!shut)
296 		imsg_event_add(iev);
297 	else {
298 		/* this pipe is dead, so remove the event handler */
299 		event_del(&iev->ev);
300 		event_loopexit(NULL);
301 	}
302 }
303 
304 /* ARGSUSED */
305 void
306 ripe_dispatch_rde(int fd, short event, void *bula)
307 {
308 	struct rip_route	*rr;
309 	struct imsg		 imsg;
310 	struct imsgev		*iev = bula;
311 	struct imsgbuf		*ibuf = &iev->ibuf;
312 	struct iface		*iface;
313 	struct nbr		*nbr;
314 	ssize_t			 n;
315 	int			 shut = 0;
316 
317 	if (event & EV_READ) {
318 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
319 			fatal("imsg_read error");
320 		if (n == 0)	/* connection closed */
321 			shut = 1;
322 	}
323 	if (event & EV_WRITE) {
324 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
325 			fatal("msgbuf_write");
326 		if (n == 0)	/* connection closed */
327 			shut = 1;
328 	}
329 
330 	for (;;) {
331 		if ((n = imsg_get(ibuf, &imsg)) == -1)
332 			fatal("ripe_dispatch_rde: imsg_get error");
333 		if (n == 0)
334 			break;
335 
336 		switch (imsg.hdr.type) {
337 		case IMSG_REQUEST_ADD:
338 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(*rr))
339 				fatalx("invalid size of RDE request");
340 
341 			if ((rr = malloc(sizeof(*rr))) == NULL)
342 				fatal("ripe_dispatch_rde");
343 
344 			memcpy(rr, imsg.data, sizeof(*rr));
345 
346 			if (imsg.hdr.peerid != 0) {
347 				if ((nbr = nbr_find_peerid(imsg.hdr.peerid)) ==
348 				    NULL) {
349 					log_debug("unknown neighbor id %u",
350 					    imsg.hdr.peerid);
351 					break;
352 				}
353 				add_entry(&nbr->rq_list, rr);
354 				break;
355 			}
356 
357 			LIST_FOREACH(iface, &oeconf->iface_list, entry) {
358 				add_entry(&iface->rq_list, rr);
359 			}
360 			break;
361 		case IMSG_SEND_REQUEST:
362 			if (imsg.hdr.peerid != 0) {
363 				if ((nbr = nbr_find_peerid(imsg.hdr.peerid)) ==
364 				    NULL) {
365 					log_debug("unknown neighbor id %u",
366 					    imsg.hdr.peerid);
367 					break;
368 				}
369 				send_request(&nbr->rq_list, NULL, nbr);
370 				break;
371 			}
372 
373 			LIST_FOREACH(iface, &oeconf->iface_list, entry) {
374 				send_request(&iface->rq_list, iface, NULL);
375 			}
376 			break;
377 		case IMSG_RESPONSE_ADD:
378 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(*rr))
379 				fatalx("invalid size of RDE request");
380 
381 			if ((rr = malloc(sizeof(*rr))) == NULL)
382 				fatal("ripe_dispatch_rde");
383 
384 			memcpy(rr, imsg.data, sizeof(*rr));
385 
386 			if (imsg.hdr.peerid == 0) {
387 				LIST_FOREACH(iface, &oeconf->iface_list, entry)
388 					add_entry(&iface->rp_list, rr);
389 
390 				break;
391 			}
392 
393 			if ((nbr = nbr_find_peerid(imsg.hdr.peerid)) == NULL) {
394 				log_debug("unknown neighbor id %u",
395 				    imsg.hdr.peerid);
396 				break;
397 			}
398 			iface = nbr->iface;
399 			add_entry(&nbr->rp_list, rr);
400 
401 			break;
402 		case IMSG_SEND_RESPONSE:
403 			if (imsg.hdr.peerid == 0) {
404 				LIST_FOREACH(iface, &oeconf->iface_list,
405 				    entry) {
406 					send_response(&iface->rp_list,
407 					    iface, NULL);
408 				}
409 				break;
410 			}
411 
412 			if ((nbr = nbr_find_peerid(imsg.hdr.peerid)) == NULL) {
413 				log_debug("unknown neighbor id %u",
414 				    imsg.hdr.peerid);
415 				break;
416 			}
417 			send_response(&nbr->rp_list, NULL, nbr);
418 			nbr_fsm(nbr, NBR_EVT_RESPONSE_SENT);
419 			break;
420 		case IMSG_SEND_TRIGGERED_UPDATE:
421 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct
422 			    rip_route))
423 				fatalx("invalid size of RDE request");
424 
425 			rr = imsg.data;
426 
427 			LIST_FOREACH(iface, &oeconf->iface_list,
428 			    entry) {
429 				if (rr->ifindex != iface->ifindex)
430 					send_triggered_update(iface, rr);
431 			}
432 			break;
433 		case IMSG_CTL_END:
434 		case IMSG_CTL_SHOW_RIB:
435 			control_imsg_relay(&imsg);
436 			break;
437 		default:
438 			log_debug("ripe_dispatch_rde: error handling imsg %d",
439 			    imsg.hdr.type);
440 			break;
441 		}
442 		imsg_free(&imsg);
443 	}
444 	if (!shut)
445 		imsg_event_add(iev);
446 	else {
447 		/* this pipe is dead, so remove the event handler */
448 		event_del(&iev->ev);
449 		event_loopexit(NULL);
450 	}
451 }
452 
453 __dead void
454 ripe_shutdown(void)
455 {
456 	struct iface	*iface;
457 
458 	/* close pipes */
459 	msgbuf_write(&iev_rde->ibuf.w);
460 	msgbuf_clear(&iev_rde->ibuf.w);
461 	close(iev_rde->ibuf.fd);
462 	msgbuf_write(&iev_main->ibuf.w);
463 	msgbuf_clear(&iev_main->ibuf.w);
464 	close(iev_main->ibuf.fd);
465 
466 	LIST_FOREACH(iface, &oeconf->iface_list, entry) {
467 		if (if_fsm(iface, IF_EVT_DOWN)) {
468 			log_debug("error stopping interface %s",
469 			    iface->name);
470 		}
471 	}
472 	while ((iface = LIST_FIRST(&oeconf->iface_list)) != NULL) {
473 		LIST_REMOVE(iface, entry);
474 		if_del(iface);
475 	}
476 
477 	close(oeconf->rip_socket);
478 
479 	/* clean up */
480 	free(iev_rde);
481 	free(iev_main);
482 	free(oeconf);
483 	free(pkt_ptr);
484 
485 	log_info("rip engine exiting");
486 	_exit(0);
487 }
488 
489 void
490 ripe_iface_ctl(struct ctl_conn *c, unsigned int idx)
491 {
492 	struct iface		*iface;
493 	struct ctl_iface	*ictl;
494 
495 	LIST_FOREACH(iface, &oeconf->iface_list, entry) {
496 		if (idx == 0 || idx == iface->ifindex) {
497 			ictl = if_to_ctl(iface);
498 			imsg_compose_event(&c->iev, IMSG_CTL_SHOW_IFACE,
499 			    0, 0, -1, ictl, sizeof(struct ctl_iface));
500 		}
501 	}
502 }
503 
504 void
505 ripe_nbr_ctl(struct ctl_conn *c)
506 {
507 	struct iface	*iface;
508 	struct nbr	*nbr;
509 	struct ctl_nbr	*nctl;
510 
511 	LIST_FOREACH(iface, &oeconf->iface_list, entry)
512 		LIST_FOREACH(nbr, &iface->nbr_list, entry) {
513 				nctl = nbr_to_ctl(nbr);
514 				imsg_compose_event(&c->iev,
515 				    IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
516 				    sizeof(struct ctl_nbr));
517 		}
518 
519 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
520 }
521 
522 void
523 ripe_demote_iface(struct iface *iface, int active)
524 {
525 	struct demote_msg	dmsg;
526 
527 	if (ripd_process != PROC_RIP_ENGINE ||
528 	    iface->demote_group[0] == '\0')
529 		return;
530 
531 	bzero(&dmsg, sizeof(dmsg));
532 	strlcpy(dmsg.demote_group, iface->demote_group,
533 	    sizeof(dmsg.demote_group));
534 	if (active)
535 		dmsg.level = -1;
536 	else
537 		dmsg.level = 1;
538 
539 	ripe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
540 }
541