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