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