xref: /openbsd-src/usr.sbin/ospfd/ospfe.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: ospfe.c,v 1.94 2015/12/05 12:20:13 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
6  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/queue.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <net/if_types.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <pwd.h>
32 #include <unistd.h>
33 #include <event.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <stdio.h>
37 
38 #include "ospf.h"
39 #include "ospfd.h"
40 #include "ospfe.h"
41 #include "rde.h"
42 #include "control.h"
43 #include "log.h"
44 
45 void		 ospfe_sig_handler(int, short, void *);
46 void		 ospfe_shutdown(void);
47 void		 orig_rtr_lsa_all(struct area *);
48 struct iface	*find_vlink(struct abr_rtr *);
49 
50 struct ospfd_conf	*oeconf = NULL, *nconf;
51 struct imsgev		*iev_main;
52 struct imsgev		*iev_rde;
53 int			 oe_nofib;
54 
55 /* ARGSUSED */
56 void
57 ospfe_sig_handler(int sig, short event, void *bula)
58 {
59 	switch (sig) {
60 	case SIGINT:
61 	case SIGTERM:
62 		ospfe_shutdown();
63 		/* NOTREACHED */
64 	default:
65 		fatalx("unexpected signal");
66 	}
67 }
68 
69 /* ospf engine */
70 pid_t
71 ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2],
72     int pipe_parent2rde[2])
73 {
74 	struct area	*area;
75 	struct iface	*iface;
76 	struct redistribute *r;
77 	struct passwd	*pw;
78 	struct event	 ev_sigint, ev_sigterm;
79 	pid_t		 pid;
80 
81 	switch (pid = fork()) {
82 	case -1:
83 		fatal("cannot fork");
84 	case 0:
85 		break;
86 	default:
87 		return (pid);
88 	}
89 
90 	/* cleanup a bit */
91 	kif_clear();
92 
93 	/* create ospfd control socket outside chroot */
94 	if (control_init(xconf->csock) == -1)
95 		fatalx("control socket setup failed");
96 
97 	/* create the raw ip socket */
98 	if ((xconf->ospf_socket = socket(AF_INET,
99 	    SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
100 	    IPPROTO_OSPF)) == -1)
101 		fatal("error creating raw socket");
102 
103 	/* set some defaults */
104 	if (if_set_mcast_loop(xconf->ospf_socket) == -1)
105 		fatal("if_set_mcast_loop");
106 	if (if_set_ip_hdrincl(xconf->ospf_socket) == -1)
107 		fatal("if_set_ip_hdrincl");
108 	if (if_set_recvif(xconf->ospf_socket, 1) == -1)
109 		fatal("if_set_recvif");
110 	if_set_sockbuf(xconf->ospf_socket);
111 
112 	oeconf = xconf;
113 	if (oeconf->flags & OSPFD_FLAG_NO_FIB_UPDATE)
114 		oe_nofib = 1;
115 
116 	if ((pw = getpwnam(OSPFD_USER)) == NULL)
117 		fatal("getpwnam");
118 
119 	if (chroot(pw->pw_dir) == -1)
120 		fatal("chroot");
121 	if (chdir("/") == -1)
122 		fatal("chdir(\"/\")");
123 
124 	setproctitle("ospf engine");
125 	ospfd_process = PROC_OSPF_ENGINE;
126 
127 	if (setgroups(1, &pw->pw_gid) ||
128 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
129 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
130 		fatal("can't drop privileges");
131 
132 	if (pledge("stdio inet mcast", NULL) == -1)
133 		fatal("pledge");
134 
135 	event_init();
136 	nbr_init(NBR_HASHSIZE);
137 	lsa_cache_init(LSA_HASHSIZE);
138 
139 	/* setup signal handler */
140 	signal_set(&ev_sigint, SIGINT, ospfe_sig_handler, NULL);
141 	signal_set(&ev_sigterm, SIGTERM, ospfe_sig_handler, NULL);
142 	signal_add(&ev_sigint, NULL);
143 	signal_add(&ev_sigterm, NULL);
144 	signal(SIGPIPE, SIG_IGN);
145 	signal(SIGHUP, SIG_IGN);
146 
147 	/* setup pipes */
148 	close(pipe_parent2ospfe[0]);
149 	close(pipe_ospfe2rde[1]);
150 	close(pipe_parent2rde[0]);
151 	close(pipe_parent2rde[1]);
152 
153 	if ((iev_rde = malloc(sizeof(struct imsgev))) == NULL ||
154 	    (iev_main = malloc(sizeof(struct imsgev))) == NULL)
155 		fatal(NULL);
156 	imsg_init(&iev_rde->ibuf, pipe_ospfe2rde[0]);
157 	iev_rde->handler = ospfe_dispatch_rde;
158 	imsg_init(&iev_main->ibuf, pipe_parent2ospfe[1]);
159 	iev_main->handler = ospfe_dispatch_main;
160 
161 	/* setup event handler */
162 	iev_rde->events = EV_READ;
163 	event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
164 	    iev_rde->handler, iev_rde);
165 	event_add(&iev_rde->ev, NULL);
166 
167 	iev_main->events = EV_READ;
168 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
169 	    iev_main->handler, iev_main);
170 	event_add(&iev_main->ev, NULL);
171 
172 	event_set(&oeconf->ev, oeconf->ospf_socket, EV_READ|EV_PERSIST,
173 	    recv_packet, oeconf);
174 	event_add(&oeconf->ev, NULL);
175 
176 	/* remove unneeded config stuff */
177 	while ((r = SIMPLEQ_FIRST(&oeconf->redist_list)) != NULL) {
178 		SIMPLEQ_REMOVE_HEAD(&oeconf->redist_list, entry);
179 		free(r);
180 	}
181 	LIST_FOREACH(area, &oeconf->area_list, entry) {
182 		while ((r = SIMPLEQ_FIRST(&area->redist_list)) != NULL) {
183 			SIMPLEQ_REMOVE_HEAD(&area->redist_list, entry);
184 			free(r);
185 		}
186 	}
187 
188 	/* listen on ospfd control socket */
189 	TAILQ_INIT(&ctl_conns);
190 	control_listen();
191 
192 	if ((pkt_ptr = calloc(1, READ_BUF_SIZE)) == NULL)
193 		fatal("ospfe");
194 
195 	/* start interfaces */
196 	LIST_FOREACH(area, &oeconf->area_list, entry) {
197 		ospfe_demote_area(area, 0);
198 		LIST_FOREACH(iface, &area->iface_list, entry) {
199 			if_init(xconf, iface);
200 			if (if_fsm(iface, IF_EVT_UP)) {
201 				log_debug("error starting interface %s",
202 				    iface->name);
203 			}
204 		}
205 	}
206 
207 	event_dispatch();
208 
209 	ospfe_shutdown();
210 	/* NOTREACHED */
211 	return (0);
212 }
213 
214 void
215 ospfe_shutdown(void)
216 {
217 	struct area	*area;
218 	struct iface	*iface;
219 
220 	/* stop all interfaces and remove all areas */
221 	while ((area = LIST_FIRST(&oeconf->area_list)) != NULL) {
222 		LIST_FOREACH(iface, &area->iface_list, entry) {
223 			if (if_fsm(iface, IF_EVT_DOWN)) {
224 				log_debug("error stopping interface %s",
225 				    iface->name);
226 			}
227 		}
228 		LIST_REMOVE(area, entry);
229 		area_del(area);
230 	}
231 
232 	nbr_del(nbr_find_peerid(NBR_IDSELF));
233 	close(oeconf->ospf_socket);
234 
235 	/* clean up */
236 	msgbuf_write(&iev_rde->ibuf.w);
237 	msgbuf_clear(&iev_rde->ibuf.w);
238 	free(iev_rde);
239 	msgbuf_write(&iev_main->ibuf.w);
240 	msgbuf_clear(&iev_main->ibuf.w);
241 	free(iev_main);
242 	free(oeconf);
243 	free(pkt_ptr);
244 
245 	log_info("ospf engine exiting");
246 	_exit(0);
247 }
248 
249 /* imesg */
250 int
251 ospfe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
252 {
253 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
254 }
255 
256 int
257 ospfe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid,
258     void *data, u_int16_t datalen)
259 {
260 	return (imsg_compose_event(iev_rde, type, peerid, pid, -1,
261 	    data, datalen));
262 }
263 
264 /* ARGSUSED */
265 void
266 ospfe_dispatch_main(int fd, short event, void *bula)
267 {
268 	static struct area	*narea;
269 	static struct iface	*niface;
270 	struct ifaddrdel	*ifc;
271 	struct imsg	 imsg;
272 	struct imsgev	*iev = bula;
273 	struct imsgbuf	*ibuf = &iev->ibuf;
274 	struct area	*area = NULL;
275 	struct iface	*iface = NULL;
276 	struct kif	*kif;
277 	struct auth_md	 md;
278 	int		 n, link_ok, stub_changed, shut = 0;
279 
280 	if (event & EV_READ) {
281 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
282 			fatal("imsg_read error");
283 		if (n == 0)	/* connection closed */
284 			shut = 1;
285 	}
286 	if (event & EV_WRITE) {
287 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
288 			fatal("msgbuf_write");
289 		if (n == 0)	/* connection closed */
290 			shut = 1;
291 	}
292 
293 	for (;;) {
294 		if ((n = imsg_get(ibuf, &imsg)) == -1)
295 			fatal("ospfe_dispatch_main: imsg_get error");
296 		if (n == 0)
297 			break;
298 
299 		switch (imsg.hdr.type) {
300 		case IMSG_IFINFO:
301 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
302 			    sizeof(struct kif))
303 				fatalx("IFINFO imsg with wrong len");
304 			kif = imsg.data;
305 			link_ok = (kif->flags & IFF_UP) &&
306 			    LINK_STATE_IS_UP(kif->link_state);
307 
308 			LIST_FOREACH(area, &oeconf->area_list, entry) {
309 				LIST_FOREACH(iface, &area->iface_list, entry) {
310 					if (kif->ifindex == iface->ifindex &&
311 					    iface->type !=
312 					    IF_TYPE_VIRTUALLINK) {
313 						iface->flags = kif->flags;
314 						iface->linkstate =
315 						    kif->link_state;
316 
317 						if (link_ok) {
318 							if_fsm(iface,
319 							    IF_EVT_UP);
320 							log_warnx("interface %s"
321 							    " up", iface->name);
322 						} else {
323 							if_fsm(iface,
324 							    IF_EVT_DOWN);
325 							log_warnx("interface %s"
326 							    " down",
327 							    iface->name);
328 						}
329 					}
330 				}
331 			}
332 			break;
333 		case IMSG_IFADDRDEL:
334 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
335 			    sizeof(struct ifaddrdel))
336 				fatalx("IFADDRDEL imsg with wrong len");
337 			ifc = imsg.data;
338 
339 			LIST_FOREACH(area, &oeconf->area_list, entry) {
340 				LIST_FOREACH(iface, &area->iface_list, entry) {
341 					if (ifc->ifindex == iface->ifindex &&
342 					    ifc->addr.s_addr ==
343 					    iface->addr.s_addr) {
344 						if_fsm(iface, IF_EVT_DOWN);
345 						log_warnx("interface %s:%s "
346 						    "gone", iface->name,
347 						    inet_ntoa(iface->addr));
348 						break;
349 					}
350 				}
351 			}
352 			break;
353 		case IMSG_RECONF_CONF:
354 			if ((nconf = malloc(sizeof(struct ospfd_conf))) ==
355 			    NULL)
356 				fatal(NULL);
357 			memcpy(nconf, imsg.data, sizeof(struct ospfd_conf));
358 
359 			LIST_INIT(&nconf->area_list);
360 			LIST_INIT(&nconf->cand_list);
361 			break;
362 		case IMSG_RECONF_AREA:
363 			if ((narea = area_new()) == NULL)
364 				fatal(NULL);
365 			memcpy(narea, imsg.data, sizeof(struct area));
366 
367 			LIST_INIT(&narea->iface_list);
368 			LIST_INIT(&narea->nbr_list);
369 			RB_INIT(&narea->lsa_tree);
370 			SIMPLEQ_INIT(&narea->redist_list);
371 
372 			LIST_INSERT_HEAD(&nconf->area_list, narea, entry);
373 			break;
374 		case IMSG_RECONF_IFACE:
375 			if ((niface = malloc(sizeof(struct iface))) == NULL)
376 				fatal(NULL);
377 			memcpy(niface, imsg.data, sizeof(struct iface));
378 
379 			LIST_INIT(&niface->nbr_list);
380 			TAILQ_INIT(&niface->ls_ack_list);
381 			TAILQ_INIT(&niface->auth_md_list);
382 			RB_INIT(&niface->lsa_tree);
383 
384 			niface->area = narea;
385 			LIST_INSERT_HEAD(&narea->iface_list, niface, entry);
386 			break;
387 		case IMSG_RECONF_AUTHMD:
388 			memcpy(&md, imsg.data, sizeof(struct auth_md));
389 			md_list_add(&niface->auth_md_list, md.keyid, md.key);
390 			break;
391 		case IMSG_RECONF_END:
392 			if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER) !=
393 			    (nconf->flags & OSPFD_FLAG_STUB_ROUTER))
394 				stub_changed = 1;
395 			else
396 				stub_changed = 0;
397 			merge_config(oeconf, nconf);
398 			nconf = NULL;
399 			if (stub_changed)
400 				orig_rtr_lsa_all(NULL);
401 			break;
402 		case IMSG_CTL_KROUTE:
403 		case IMSG_CTL_KROUTE_ADDR:
404 		case IMSG_CTL_IFINFO:
405 		case IMSG_CTL_END:
406 			control_imsg_relay(&imsg);
407 			break;
408 		default:
409 			log_debug("ospfe_dispatch_main: error handling imsg %d",
410 			    imsg.hdr.type);
411 			break;
412 		}
413 		imsg_free(&imsg);
414 	}
415 	if (!shut)
416 		imsg_event_add(iev);
417 	else {
418 		/* this pipe is dead, so remove the event handler */
419 		event_del(&iev->ev);
420 		event_loopexit(NULL);
421 	}
422 }
423 
424 /* ARGSUSED */
425 void
426 ospfe_dispatch_rde(int fd, short event, void *bula)
427 {
428 	struct lsa_hdr		 lsa_hdr;
429 	struct imsgev		*iev = bula;
430 	struct imsgbuf		*ibuf = &iev->ibuf;
431 	struct nbr		*nbr;
432 	struct lsa_hdr		*lhp;
433 	struct lsa_ref		*ref;
434 	struct area		*area;
435 	struct iface		*iface;
436 	struct lsa_entry	*le;
437 	struct imsg		 imsg;
438 	struct abr_rtr		 ar;
439 	int			 n, noack = 0, shut = 0;
440 	u_int16_t		 l, age;
441 
442 	if (event & EV_READ) {
443 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
444 			fatal("imsg_read error");
445 		if (n == 0)	/* connection closed */
446 			shut = 1;
447 	}
448 	if (event & EV_WRITE) {
449 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
450 			fatal("msgbuf_write");
451 		if (n == 0)	/* connection closed */
452 			shut = 1;
453 	}
454 
455 	for (;;) {
456 		if ((n = imsg_get(ibuf, &imsg)) == -1)
457 			fatal("ospfe_dispatch_rde: imsg_get error");
458 		if (n == 0)
459 			break;
460 
461 		switch (imsg.hdr.type) {
462 		case IMSG_DD:
463 			nbr = nbr_find_peerid(imsg.hdr.peerid);
464 			if (nbr == NULL)
465 				break;
466 
467 			/*
468 			 * Ignore imsg when in the wrong state because a
469 			 * NBR_EVT_SEQ_NUM_MIS may have been issued in between.
470 			 * Luckily regetting the DB snapshot acts as a barrier
471 			 * for both state and process synchronisation.
472 			 */
473 			if ((nbr->state & NBR_STA_FLOOD) == 0)
474 				break;
475 
476 			/* put these on my ls_req_list for retrieval */
477 			lhp = lsa_hdr_new();
478 			memcpy(lhp, imsg.data, sizeof(*lhp));
479 			ls_req_list_add(nbr, lhp);
480 			break;
481 		case IMSG_DD_END:
482 			nbr = nbr_find_peerid(imsg.hdr.peerid);
483 			if (nbr == NULL)
484 				break;
485 
486 			/* see above */
487 			if ((nbr->state & NBR_STA_FLOOD) == 0)
488 				break;
489 
490 			nbr->dd_pending--;
491 			if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD) {
492 				if (ls_req_list_empty(nbr))
493 					nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
494 				else
495 					start_ls_req_tx_timer(nbr);
496 			}
497 			break;
498 		case IMSG_DD_BADLSA:
499 			nbr = nbr_find_peerid(imsg.hdr.peerid);
500 			if (nbr == NULL)
501 				break;
502 
503 			if (nbr->iface->self == nbr)
504 				fatalx("ospfe_dispatch_rde: "
505 				    "dummy neighbor got BADREQ");
506 
507 			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
508 			break;
509 		case IMSG_DB_SNAPSHOT:
510 			nbr = nbr_find_peerid(imsg.hdr.peerid);
511 			if (nbr == NULL)
512 				break;
513 			if (nbr->state != NBR_STA_SNAP)	/* discard */
514 				break;
515 
516 			/* add LSA header to the neighbor db_sum_list */
517 			lhp = lsa_hdr_new();
518 			memcpy(lhp, imsg.data, sizeof(*lhp));
519 			db_sum_list_add(nbr, lhp);
520 			break;
521 		case IMSG_DB_END:
522 			nbr = nbr_find_peerid(imsg.hdr.peerid);
523 			if (nbr == NULL)
524 				break;
525 
526 			nbr->dd_snapshot = 0;
527 			if (nbr->state != NBR_STA_SNAP)
528 				break;
529 
530 			/* snapshot done, start tx of dd packets */
531 			nbr_fsm(nbr, NBR_EVT_SNAP_DONE);
532 			break;
533 		case IMSG_LS_FLOOD:
534 			nbr = nbr_find_peerid(imsg.hdr.peerid);
535 			if (nbr == NULL)
536 				break;
537 
538 			l = imsg.hdr.len - IMSG_HEADER_SIZE;
539 			if (l < sizeof(lsa_hdr))
540 				fatalx("ospfe_dispatch_rde: "
541 				    "bad imsg size");
542 			memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
543 
544 			ref = lsa_cache_add(imsg.data, l);
545 
546 			if (lsa_hdr.type == LSA_TYPE_EXTERNAL) {
547 				/*
548 				 * flood on all areas but stub areas and
549 				 * virtual links
550 				 */
551 				LIST_FOREACH(area, &oeconf->area_list, entry) {
552 				    if (area->stub)
553 					    continue;
554 				    LIST_FOREACH(iface, &area->iface_list,
555 					entry) {
556 					    noack += lsa_flood(iface, nbr,
557 						&lsa_hdr, imsg.data);
558 				    }
559 				}
560 			} else if (lsa_hdr.type == LSA_TYPE_LINK_OPAQ) {
561 				/*
562 				 * Flood on interface only
563 				 */
564 				noack += lsa_flood(nbr->iface, nbr,
565 				    &lsa_hdr, imsg.data);
566 			} else {
567 				/*
568 				 * Flood on all area interfaces. For
569 				 * area 0.0.0.0 include the virtual links.
570 				 */
571 				area = nbr->iface->area;
572 				LIST_FOREACH(iface, &area->iface_list, entry) {
573 					noack += lsa_flood(iface, nbr,
574 					    &lsa_hdr, imsg.data);
575 				}
576 				/* XXX virtual links */
577 			}
578 
579 			/* remove from ls_req_list */
580 			le = ls_req_list_get(nbr, &lsa_hdr);
581 			if (!(nbr->state & NBR_STA_FULL) && le != NULL) {
582 				ls_req_list_free(nbr, le);
583 				/*
584 				 * XXX no need to ack requested lsa
585 				 * the problem is that the RFC is very
586 				 * unclear about this.
587 				 */
588 				noack = 1;
589 			}
590 
591 			if (!noack && nbr->iface != NULL &&
592 			    nbr->iface->self != nbr) {
593 				if (!(nbr->iface->state & IF_STA_BACKUP) ||
594 				    nbr->iface->dr == nbr) {
595 					/* delayed ack */
596 					lhp = lsa_hdr_new();
597 					memcpy(lhp, &lsa_hdr, sizeof(*lhp));
598 					ls_ack_list_add(nbr->iface, lhp);
599 				}
600 			}
601 
602 			lsa_cache_put(ref, nbr);
603 			break;
604 		case IMSG_LS_UPD:
605 		case IMSG_LS_SNAP:
606 			/*
607 			 * IMSG_LS_UPD is used in two cases:
608 			 * 1. as response to ls requests
609 			 * 2. as response to ls updates where the DB
610 			 *    is newer then the sent LSA
611 			 * IMSG_LS_SNAP is used in one case:
612 			 *    in EXSTART when the LSA has age MaxAge
613 			 */
614 			l = imsg.hdr.len - IMSG_HEADER_SIZE;
615 			if (l < sizeof(lsa_hdr))
616 				fatalx("ospfe_dispatch_rde: "
617 				    "bad imsg size");
618 
619 			nbr = nbr_find_peerid(imsg.hdr.peerid);
620 			if (nbr == NULL)
621 				break;
622 
623 			if (nbr->iface->self == nbr)
624 				break;
625 
626 			if (imsg.hdr.type == IMSG_LS_SNAP &&
627 			    nbr->state != NBR_STA_SNAP)
628 				break;
629 
630 			memcpy(&age, imsg.data, sizeof(age));
631 			ref = lsa_cache_add(imsg.data, l);
632 			if (ntohs(age) >= MAX_AGE)
633 				/* add to retransmit list */
634 				ls_retrans_list_add(nbr, imsg.data, 0, 0);
635 			else
636 				ls_retrans_list_add(nbr, imsg.data, 0, 1);
637 
638 			lsa_cache_put(ref, nbr);
639 			break;
640 		case IMSG_LS_ACK:
641 			/*
642 			 * IMSG_LS_ACK is used in two cases:
643 			 * 1. LSA was a duplicate
644 			 * 2. LS age is MaxAge and there is no current
645 			 *    instance in the DB plus no neighbor in state
646 			 *    Exchange or Loading
647 			 */
648 			nbr = nbr_find_peerid(imsg.hdr.peerid);
649 			if (nbr == NULL)
650 				break;
651 
652 			if (nbr->iface->self == nbr)
653 				break;
654 
655 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lsa_hdr))
656 				fatalx("ospfe_dispatch_rde: bad imsg size");
657 			memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
658 
659 			/* for case one check for implied acks */
660 			if (nbr->iface->state & IF_STA_DROTHER)
661 				if (ls_retrans_list_del(nbr->iface->self,
662 				    &lsa_hdr) == 0)
663 					break;
664 			if (ls_retrans_list_del(nbr, &lsa_hdr) == 0)
665 				break;
666 
667 			/* send a direct acknowledgement */
668 			send_direct_ack(nbr->iface, nbr->addr, imsg.data,
669 			    imsg.hdr.len - IMSG_HEADER_SIZE);
670 
671 			break;
672 		case IMSG_LS_BADREQ:
673 			nbr = nbr_find_peerid(imsg.hdr.peerid);
674 			if (nbr == NULL)
675 				break;
676 
677 			if (nbr->iface->self == nbr)
678 				fatalx("ospfe_dispatch_rde: "
679 				    "dummy neighbor got BADREQ");
680 
681 			nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ);
682 			break;
683 		case IMSG_ABR_UP:
684 			memcpy(&ar, imsg.data, sizeof(ar));
685 
686 			if ((iface = find_vlink(&ar)) != NULL &&
687 			    iface->state == IF_STA_DOWN)
688 				if (if_fsm(iface, IF_EVT_UP)) {
689 					log_debug("error starting interface %s",
690 					    iface->name);
691 				}
692 			break;
693 		case IMSG_ABR_DOWN:
694 			memcpy(&ar, imsg.data, sizeof(ar));
695 
696 			if ((iface = find_vlink(&ar)) != NULL &&
697 			    iface->state == IF_STA_POINTTOPOINT)
698 				if (if_fsm(iface, IF_EVT_DOWN)) {
699 					log_debug("error stopping interface %s",
700 					    iface->name);
701 				}
702 			break;
703 		case IMSG_CTL_AREA:
704 		case IMSG_CTL_IFACE:
705 		case IMSG_CTL_END:
706 		case IMSG_CTL_SHOW_DATABASE:
707 		case IMSG_CTL_SHOW_DB_EXT:
708 		case IMSG_CTL_SHOW_DB_NET:
709 		case IMSG_CTL_SHOW_DB_RTR:
710 		case IMSG_CTL_SHOW_DB_SELF:
711 		case IMSG_CTL_SHOW_DB_SUM:
712 		case IMSG_CTL_SHOW_DB_ASBR:
713 		case IMSG_CTL_SHOW_DB_OPAQ:
714 		case IMSG_CTL_SHOW_RIB:
715 		case IMSG_CTL_SHOW_SUM:
716 		case IMSG_CTL_SHOW_SUM_AREA:
717 			control_imsg_relay(&imsg);
718 			break;
719 		default:
720 			log_debug("ospfe_dispatch_rde: error handling imsg %d",
721 			    imsg.hdr.type);
722 			break;
723 		}
724 		imsg_free(&imsg);
725 	}
726 	if (!shut)
727 		imsg_event_add(iev);
728 	else {
729 		/* this pipe is dead, so remove the event handler */
730 		event_del(&iev->ev);
731 		event_loopexit(NULL);
732 	}
733 }
734 
735 struct iface *
736 find_vlink(struct abr_rtr *ar)
737 {
738 	struct area	*area;
739 	struct iface	*iface = NULL;
740 
741 	LIST_FOREACH(area, &oeconf->area_list, entry)
742 		LIST_FOREACH(iface, &area->iface_list, entry)
743 			if (iface->abr_id.s_addr == ar->abr_id.s_addr &&
744 			    iface->type == IF_TYPE_VIRTUALLINK &&
745 			    iface->area->id.s_addr == ar->area.s_addr) {
746 				iface->dst.s_addr = ar->dst_ip.s_addr;
747 				iface->addr.s_addr = ar->addr.s_addr;
748 				iface->metric = ar->metric;
749 
750 				return (iface);
751 			}
752 
753 	return (iface);
754 }
755 
756 void
757 orig_rtr_lsa_all(struct area *area)
758 {
759 	struct area	*a;
760 
761 	/*
762 	 * update all router LSA in all areas except area itself,
763 	 * as this update is already running.
764 	 */
765 	LIST_FOREACH(a, &oeconf->area_list, entry)
766 		if (a != area)
767 			orig_rtr_lsa(a);
768 }
769 
770 void
771 orig_rtr_lsa(struct area *area)
772 {
773 	struct lsa_hdr		 lsa_hdr;
774 	struct lsa_rtr		 lsa_rtr;
775 	struct lsa_rtr_link	 rtr_link;
776 	struct iface		*iface;
777 	struct ibuf		*buf;
778 	struct nbr		*nbr, *self = NULL;
779 	u_int16_t		 num_links = 0;
780 	u_int16_t		 chksum;
781 	u_int8_t		 border, virtual = 0;
782 
783 	log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id));
784 
785 	if ((buf = ibuf_dynamic(sizeof(lsa_hdr),
786 	    IP_MAXPACKET - sizeof(struct ip) - sizeof(struct ospf_hdr) -
787 	    sizeof(u_int32_t) - MD5_DIGEST_LENGTH)) == NULL)
788 		fatal("orig_rtr_lsa");
789 
790 	/* reserve space for LSA header and LSA Router header */
791 	if (ibuf_reserve(buf, sizeof(lsa_hdr)) == NULL)
792 		fatal("orig_rtr_lsa: ibuf_reserve failed");
793 
794 	if (ibuf_reserve(buf, sizeof(lsa_rtr)) == NULL)
795 		fatal("orig_rtr_lsa: ibuf_reserve failed");
796 
797 	/* links */
798 	LIST_FOREACH(iface, &area->iface_list, entry) {
799 		if (self == NULL && iface->self != NULL)
800 			self = iface->self;
801 
802 		bzero(&rtr_link, sizeof(rtr_link));
803 
804 		if (iface->state & IF_STA_LOOPBACK) {
805 			rtr_link.id = iface->addr.s_addr;
806 			rtr_link.data = 0xffffffff;
807 			rtr_link.type = LINK_TYPE_STUB_NET;
808 			rtr_link.metric = htons(iface->metric);
809 			num_links++;
810 			if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
811 				fatalx("orig_rtr_lsa: ibuf_add failed");
812 			continue;
813 		}
814 
815 		switch (iface->type) {
816 		case IF_TYPE_POINTOPOINT:
817 			LIST_FOREACH(nbr, &iface->nbr_list, entry)
818 				if (nbr != iface->self &&
819 				    nbr->state & NBR_STA_FULL)
820 					break;
821 			if (nbr) {
822 				log_debug("orig_rtr_lsa: point-to-point, "
823 				    "interface %s", iface->name);
824 				rtr_link.id = nbr->id.s_addr;
825 				rtr_link.data = iface->addr.s_addr;
826 				rtr_link.type = LINK_TYPE_POINTTOPOINT;
827 				/* RFC 3137: stub router support */
828 				if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER ||
829 				    oe_nofib)
830 					rtr_link.metric = MAX_METRIC;
831 				else
832 					rtr_link.metric = htons(iface->metric);
833 				num_links++;
834 				if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
835 					fatalx("orig_rtr_lsa: ibuf_add failed");
836 			}
837 			if (iface->state & IF_STA_POINTTOPOINT) {
838 				log_debug("orig_rtr_lsa: stub net, "
839 				    "interface %s", iface->name);
840 				bzero(&rtr_link, sizeof(rtr_link));
841 				if (nbr) {
842 					rtr_link.id = nbr->addr.s_addr;
843 					rtr_link.data = 0xffffffff;
844 				} else {
845 					rtr_link.id = iface->addr.s_addr;
846 					rtr_link.data = iface->mask.s_addr;
847 				}
848 				rtr_link.type = LINK_TYPE_STUB_NET;
849 				rtr_link.metric = htons(iface->metric);
850 				num_links++;
851 				if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
852 					fatalx("orig_rtr_lsa: ibuf_add failed");
853 			}
854 			continue;
855 		case IF_TYPE_BROADCAST:
856 		case IF_TYPE_NBMA:
857 			if ((iface->state & IF_STA_MULTI)) {
858 				if (iface->dr == iface->self) {
859 					LIST_FOREACH(nbr, &iface->nbr_list,
860 					    entry)
861 						if (nbr != iface->self &&
862 						    nbr->state & NBR_STA_FULL)
863 							break;
864 				} else
865 					nbr = iface->dr;
866 
867 				if (nbr && nbr->state & NBR_STA_FULL) {
868 					log_debug("orig_rtr_lsa: transit net, "
869 					    "interface %s", iface->name);
870 
871 					rtr_link.id = iface->dr->addr.s_addr;
872 					rtr_link.data = iface->addr.s_addr;
873 					rtr_link.type = LINK_TYPE_TRANSIT_NET;
874 					break;
875 				}
876 			}
877 
878 			/*
879 			 * do not add a stub net LSA for interfaces that are:
880 			 *  - down
881 			 *  - have a linkstate which is down, apart from carp:
882 			 *    backup carp interfaces have linkstate down, but
883 			 *    we still announce them.
884 			 */
885 			if (!(iface->flags & IFF_UP) ||
886 			    (!LINK_STATE_IS_UP(iface->linkstate) &&
887 			    !(iface->if_type == IFT_CARP &&
888 			    iface->linkstate == LINK_STATE_DOWN)))
889 				continue;
890 			log_debug("orig_rtr_lsa: stub net, "
891 			    "interface %s", iface->name);
892 
893 			rtr_link.id =
894 			    iface->addr.s_addr & iface->mask.s_addr;
895 			rtr_link.data = iface->mask.s_addr;
896 			rtr_link.type = LINK_TYPE_STUB_NET;
897 
898 			rtr_link.num_tos = 0;
899 			/*
900 			 * backup carp interfaces are anounced with high metric
901 			 * for faster failover.
902 			 */
903 			if (iface->if_type == IFT_CARP &&
904 			    iface->linkstate == LINK_STATE_DOWN)
905 				rtr_link.metric = MAX_METRIC;
906 			else
907 				rtr_link.metric = htons(iface->metric);
908 			num_links++;
909 			if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
910 				fatalx("orig_rtr_lsa: ibuf_add failed");
911 			continue;
912 		case IF_TYPE_VIRTUALLINK:
913 			LIST_FOREACH(nbr, &iface->nbr_list, entry) {
914 				if (nbr != iface->self &&
915 				    nbr->state & NBR_STA_FULL)
916 					break;
917 			}
918 			if (nbr) {
919 				rtr_link.id = nbr->id.s_addr;
920 				rtr_link.data = iface->addr.s_addr;
921 				rtr_link.type = LINK_TYPE_VIRTUAL;
922 				/* RFC 3137: stub router support */
923 				if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER ||
924 				    oe_nofib)
925 					rtr_link.metric = MAX_METRIC;
926 				else
927 					rtr_link.metric = htons(iface->metric);
928 				num_links++;
929 				virtual = 1;
930 				if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
931 					fatalx("orig_rtr_lsa: ibuf_add failed");
932 
933 				log_debug("orig_rtr_lsa: virtual link, "
934 				    "interface %s", iface->name);
935 			}
936 			continue;
937 		case IF_TYPE_POINTOMULTIPOINT:
938 			log_debug("orig_rtr_lsa: stub net, "
939 			    "interface %s", iface->name);
940 			rtr_link.id = iface->addr.s_addr;
941 			rtr_link.data = 0xffffffff;
942 			rtr_link.type = LINK_TYPE_STUB_NET;
943 			rtr_link.metric = htons(iface->metric);
944 			num_links++;
945 			if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
946 				fatalx("orig_rtr_lsa: ibuf_add failed");
947 
948 			LIST_FOREACH(nbr, &iface->nbr_list, entry) {
949 				if (nbr != iface->self &&
950 				    nbr->state & NBR_STA_FULL) {
951 					bzero(&rtr_link, sizeof(rtr_link));
952 					log_debug("orig_rtr_lsa: "
953 					    "point-to-multipoint, interface %s",
954 					    iface->name);
955 					rtr_link.id = nbr->addr.s_addr;
956 					rtr_link.data = iface->addr.s_addr;
957 					rtr_link.type = LINK_TYPE_POINTTOPOINT;
958 					/* RFC 3137: stub router support */
959 					if (oe_nofib || oeconf->flags &
960 					    OSPFD_FLAG_STUB_ROUTER)
961 						rtr_link.metric = MAX_METRIC;
962 					else
963 						rtr_link.metric =
964 						    htons(iface->metric);
965 					num_links++;
966 					if (ibuf_add(buf, &rtr_link,
967 					    sizeof(rtr_link)))
968 						fatalx("orig_rtr_lsa: "
969 						    "ibuf_add failed");
970 				}
971 			}
972 			continue;
973 		default:
974 			fatalx("orig_rtr_lsa: unknown interface type");
975 		}
976 
977 		rtr_link.num_tos = 0;
978 		/* RFC 3137: stub router support */
979 		if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER || oe_nofib) &&
980 		    rtr_link.type != LINK_TYPE_STUB_NET)
981 			rtr_link.metric = MAX_METRIC;
982 		else
983 			rtr_link.metric = htons(iface->metric);
984 		num_links++;
985 		if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
986 			fatalx("orig_rtr_lsa: ibuf_add failed");
987 	}
988 
989 	/* LSA router header */
990 	lsa_rtr.flags = 0;
991 	/*
992 	 * Set the E bit as soon as an as-ext lsa may be redistributed, only
993 	 * setting it in case we redistribute something is not worth the fuss.
994 	 * Do not set the E bit in case of a stub area.
995 	 */
996 	if (oeconf->redistribute && !area->stub)
997 		lsa_rtr.flags |= OSPF_RTR_E;
998 
999 	border = (area_border_router(oeconf) != 0);
1000 	if (border != oeconf->border) {
1001 		oeconf->border = border;
1002 		orig_rtr_lsa_all(area);
1003 	}
1004 	if (oeconf->border)
1005 		lsa_rtr.flags |= OSPF_RTR_B;
1006 
1007 	/* TODO set V flag if a active virtual link ends here and the
1008 	 * area is the transit area for this link. */
1009 	if (virtual)
1010 		lsa_rtr.flags |= OSPF_RTR_V;
1011 
1012 	lsa_rtr.dummy = 0;
1013 	lsa_rtr.nlinks = htons(num_links);
1014 	memcpy(ibuf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_rtr)),
1015 	    &lsa_rtr, sizeof(lsa_rtr));
1016 
1017 	/* LSA header */
1018 	lsa_hdr.age = htons(DEFAULT_AGE);
1019 	lsa_hdr.opts = area_ospf_options(area);
1020 	lsa_hdr.type = LSA_TYPE_ROUTER;
1021 	lsa_hdr.ls_id = oeconf->rtr_id.s_addr;
1022 	lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
1023 	lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
1024 	lsa_hdr.len = htons(ibuf_size(buf));
1025 	lsa_hdr.ls_chksum = 0;		/* updated later */
1026 	memcpy(ibuf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
1027 
1028 	chksum = htons(iso_cksum(buf->buf, ibuf_size(buf), LS_CKSUM_OFFSET));
1029 	memcpy(ibuf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)),
1030 	    &chksum, sizeof(chksum));
1031 
1032 	if (self && num_links)
1033 		imsg_compose_event(iev_rde, IMSG_LS_UPD, self->peerid, 0,
1034 		    -1, buf->buf, ibuf_size(buf));
1035 	else
1036 		log_warnx("orig_rtr_lsa: empty area %s",
1037 		    inet_ntoa(area->id));
1038 
1039 	ibuf_free(buf);
1040 }
1041 
1042 void
1043 orig_net_lsa(struct iface *iface)
1044 {
1045 	struct lsa_hdr		 lsa_hdr;
1046 	struct nbr		*nbr;
1047 	struct ibuf		*buf;
1048 	int			 num_rtr = 0;
1049 	u_int16_t		 chksum;
1050 
1051 	if ((buf = ibuf_dynamic(sizeof(lsa_hdr),
1052 	    IP_MAXPACKET - sizeof(struct ip) - sizeof(struct ospf_hdr) -
1053 	    sizeof(u_int32_t) - MD5_DIGEST_LENGTH)) == NULL)
1054 		fatal("orig_net_lsa");
1055 
1056 	/* reserve space for LSA header and LSA Router header */
1057 	if (ibuf_reserve(buf, sizeof(lsa_hdr)) == NULL)
1058 		fatal("orig_net_lsa: ibuf_reserve failed");
1059 
1060 	/* LSA net mask and then all fully adjacent routers */
1061 	if (ibuf_add(buf, &iface->mask, sizeof(iface->mask)))
1062 		fatal("orig_net_lsa: ibuf_add failed");
1063 
1064 	/* fully adjacent neighbors + self */
1065 	LIST_FOREACH(nbr, &iface->nbr_list, entry)
1066 		if (nbr->state & NBR_STA_FULL) {
1067 			if (ibuf_add(buf, &nbr->id, sizeof(nbr->id)))
1068 				fatal("orig_net_lsa: ibuf_add failed");
1069 			num_rtr++;
1070 		}
1071 
1072 	if (num_rtr == 1) {
1073 		/* non transit net therefore no need to generate a net lsa */
1074 		ibuf_free(buf);
1075 		return;
1076 	}
1077 
1078 	/* LSA header */
1079 	if (iface->state & IF_STA_DR)
1080 		lsa_hdr.age = htons(DEFAULT_AGE);
1081 	else
1082 		lsa_hdr.age = htons(MAX_AGE);
1083 
1084 	lsa_hdr.opts = area_ospf_options(iface->area);
1085 	lsa_hdr.type = LSA_TYPE_NETWORK;
1086 	lsa_hdr.ls_id = iface->addr.s_addr;
1087 	lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
1088 	lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
1089 	lsa_hdr.len = htons(ibuf_size(buf));
1090 	lsa_hdr.ls_chksum = 0;		/* updated later */
1091 	memcpy(ibuf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
1092 
1093 	chksum = htons(iso_cksum(buf->buf, ibuf_size(buf), LS_CKSUM_OFFSET));
1094 	memcpy(ibuf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)),
1095 	    &chksum, sizeof(chksum));
1096 
1097 	imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0,
1098 	    -1, buf->buf, ibuf_size(buf));
1099 
1100 	ibuf_free(buf);
1101 }
1102 
1103 u_int32_t
1104 ospfe_router_id(void)
1105 {
1106 	return (oeconf->rtr_id.s_addr);
1107 }
1108 
1109 void
1110 ospfe_fib_update(int type)
1111 {
1112 	int	old = oe_nofib;
1113 
1114 	if (type == IMSG_CTL_FIB_COUPLE)
1115 		oe_nofib = 0;
1116 	if (type == IMSG_CTL_FIB_DECOUPLE)
1117 		oe_nofib = 1;
1118 	if (old != oe_nofib)
1119 		orig_rtr_lsa_all(NULL);
1120 }
1121 
1122 void
1123 ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx)
1124 {
1125 	struct area		*area;
1126 	struct iface		*iface;
1127 	struct ctl_iface	*ictl;
1128 
1129 	LIST_FOREACH(area, &oeconf->area_list, entry)
1130 		LIST_FOREACH(iface, &area->iface_list, entry)
1131 			if (idx == 0 || idx == iface->ifindex) {
1132 				ictl = if_to_ctl(iface);
1133 				imsg_compose_event(&c->iev,
1134 				    IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
1135 				    ictl, sizeof(struct ctl_iface));
1136 			}
1137 }
1138 
1139 void
1140 ospfe_nbr_ctl(struct ctl_conn *c)
1141 {
1142 	struct area	*area;
1143 	struct iface	*iface;
1144 	struct nbr	*nbr;
1145 	struct ctl_nbr	*nctl;
1146 
1147 	LIST_FOREACH(area, &oeconf->area_list, entry)
1148 		LIST_FOREACH(iface, &area->iface_list, entry)
1149 			LIST_FOREACH(nbr, &iface->nbr_list, entry) {
1150 				if (iface->self != nbr) {
1151 					nctl = nbr_to_ctl(nbr);
1152 					imsg_compose_event(&c->iev,
1153 					    IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
1154 					    sizeof(struct ctl_nbr));
1155 				}
1156 			}
1157 
1158 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
1159 }
1160 
1161 void
1162 ospfe_demote_area(struct area *area, int active)
1163 {
1164 	struct demote_msg	dmsg;
1165 
1166 	if (ospfd_process != PROC_OSPF_ENGINE ||
1167 	    area->demote_group[0] == '\0')
1168 		return;
1169 
1170 	bzero(&dmsg, sizeof(dmsg));
1171 	strlcpy(dmsg.demote_group, area->demote_group,
1172 	    sizeof(dmsg.demote_group));
1173 	dmsg.level = area->demote_level;
1174 	if (active)
1175 		dmsg.level = -dmsg.level;
1176 
1177 	ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
1178 }
1179 
1180 void
1181 ospfe_demote_iface(struct iface *iface, int active)
1182 {
1183 	struct demote_msg	dmsg;
1184 
1185 	if (ospfd_process != PROC_OSPF_ENGINE ||
1186 	    iface->demote_group[0] == '\0')
1187 		return;
1188 
1189 	bzero(&dmsg, sizeof(dmsg));
1190 	strlcpy(dmsg.demote_group, iface->demote_group,
1191 	sizeof(dmsg.demote_group));
1192 	if (active)
1193 		dmsg.level = -1;
1194 	else
1195 		dmsg.level = 1;
1196 
1197 	log_warnx("ospfe_demote_iface: group %s level %d", dmsg.demote_group,
1198 	    dmsg.level);
1199 
1200 	ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
1201 }
1202