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