xref: /openbsd-src/usr.sbin/ospfd/ospfe.c (revision 43003dfe3ad45d1698bed8a37f2b0f5b14f20d4f)
1 /*	$OpenBSD: ospfe.c,v 1.73 2009/09/30 14:37:11 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 	close(oeconf->ospf_socket);
227 
228 	/* clean up */
229 	msgbuf_write(&iev_rde->ibuf.w);
230 	msgbuf_clear(&iev_rde->ibuf.w);
231 	free(iev_rde);
232 	msgbuf_write(&iev_main->ibuf.w);
233 	msgbuf_clear(&iev_main->ibuf.w);
234 	free(iev_main);
235 	free(oeconf);
236 	free(pkt_ptr);
237 
238 	log_info("ospf engine exiting");
239 	_exit(0);
240 }
241 
242 /* imesg */
243 int
244 ospfe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
245 {
246 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
247 }
248 
249 int
250 ospfe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid,
251     void *data, u_int16_t datalen)
252 {
253 	return (imsg_compose_event(iev_rde, type, peerid, pid, -1, data, datalen));
254 }
255 
256 /* ARGSUSED */
257 void
258 ospfe_dispatch_main(int fd, short event, void *bula)
259 {
260 	static struct area	*narea;
261 	static struct iface	*niface;
262 	struct imsg	 imsg;
263 	struct imsgev	*iev = bula;
264 	struct imsgbuf	*ibuf;
265 	struct area	*area = NULL;
266 	struct iface	*iface = NULL;
267 	struct kif	*kif;
268 	struct auth_md	 md;
269 	int		 n, link_ok, stub_changed, shut = 0;
270 
271 	ibuf = &iev->ibuf;
272 
273 	if (event & EV_READ) {
274 		if ((n = imsg_read(ibuf)) == -1)
275 			fatal("imsg_read error");
276 		if (n == 0)	/* connection closed */
277 			shut = 1;
278 	}
279 	if (event & EV_WRITE) {
280 		if (msgbuf_write(&ibuf->w) == -1)
281 			fatal("msgbuf_write");
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(iev);
390 	else {
391 		/* this pipe is dead, so remove the event handler */
392 		event_del(&iev->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 imsgev		*iev = bula;
403 	struct imsgbuf		*ibuf;
404 	struct nbr		*nbr;
405 	struct lsa_hdr		*lhp;
406 	struct lsa_ref		*ref;
407 	struct area		*area;
408 	struct iface		*iface;
409 	struct lsa_entry	*le;
410 	struct imsg		 imsg;
411 	struct abr_rtr		 ar;
412 	int			 n, noack = 0, shut = 0;
413 	u_int16_t		 l, age;
414 
415 	ibuf = &iev->ibuf;
416 
417 	if (event & EV_READ) {
418 		if ((n = imsg_read(ibuf)) == -1)
419 			fatal("imsg_read error");
420 		if (n == 0)	/* connection closed */
421 			shut = 1;
422 	}
423 	if (event & EV_WRITE) {
424 		if (msgbuf_write(&ibuf->w) == -1)
425 			fatal("msgbuf_write");
426 	}
427 
428 	for (;;) {
429 		if ((n = imsg_get(ibuf, &imsg)) == -1)
430 			fatal("ospfe_dispatch_rde: imsg_read error");
431 		if (n == 0)
432 			break;
433 
434 		switch (imsg.hdr.type) {
435 		case IMSG_DD:
436 			nbr = nbr_find_peerid(imsg.hdr.peerid);
437 			if (nbr == NULL)
438 				break;
439 
440 			/*
441 			 * Ignore imsg when in the wrong state because a
442 			 * NBR_EVT_SEQ_NUM_MIS may have been issued in between.
443 			 * Luckily regetting the DB snapshot acts as a barrier
444 			 * for both state and process synchronisation.
445 			 */
446 			if ((nbr->state & NBR_STA_FLOOD) == 0)
447 				break;
448 
449 			/* put these on my ls_req_list for retrieval */
450 			lhp = lsa_hdr_new();
451 			memcpy(lhp, imsg.data, sizeof(*lhp));
452 			ls_req_list_add(nbr, lhp);
453 			break;
454 		case IMSG_DD_END:
455 			nbr = nbr_find_peerid(imsg.hdr.peerid);
456 			if (nbr == NULL)
457 				break;
458 
459 			/* see above */
460 			if ((nbr->state & NBR_STA_FLOOD) == 0)
461 				break;
462 
463 			nbr->dd_pending--;
464 			if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD) {
465 				if (ls_req_list_empty(nbr))
466 					nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
467 				else
468 					start_ls_req_tx_timer(nbr);
469 			}
470 			break;
471 		case IMSG_DD_BADLSA:
472 			nbr = nbr_find_peerid(imsg.hdr.peerid);
473 			if (nbr == NULL)
474 				break;
475 
476 			if (nbr->iface->self == nbr)
477 				fatalx("ospfe_dispatch_rde: "
478 				    "dummy neighbor got BADREQ");
479 
480 			nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
481 			break;
482 		case IMSG_DB_SNAPSHOT:
483 			nbr = nbr_find_peerid(imsg.hdr.peerid);
484 			if (nbr == NULL)
485 				break;
486 
487 			/* add LSA header to the neighbor db_sum_list */
488 			lhp = lsa_hdr_new();
489 			memcpy(lhp, imsg.data, sizeof(*lhp));
490 			db_sum_list_add(nbr, lhp);
491 			break;
492 		case IMSG_DB_END:
493 			nbr = nbr_find_peerid(imsg.hdr.peerid);
494 			if (nbr == NULL)
495 				break;
496 
497 			/* snapshot done, start tx of dd packets */
498 			nbr_fsm(nbr, NBR_EVT_SNAP_DONE);
499 			break;
500 		case IMSG_LS_FLOOD:
501 			nbr = nbr_find_peerid(imsg.hdr.peerid);
502 			if (nbr == NULL)
503 				break;
504 
505 			l = imsg.hdr.len - IMSG_HEADER_SIZE;
506 			if (l < sizeof(lsa_hdr))
507 				fatalx("ospfe_dispatch_rde: "
508 				    "bad imsg size");
509 			memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
510 
511 			ref = lsa_cache_add(imsg.data, l);
512 
513 			if (lsa_hdr.type == LSA_TYPE_EXTERNAL) {
514 				/*
515 				 * flood on all areas but stub areas and
516 				 * virtual links
517 				 */
518 				LIST_FOREACH(area, &oeconf->area_list, entry) {
519 				    if (area->stub)
520 					    continue;
521 				    LIST_FOREACH(iface, &area->iface_list,
522 					entry) {
523 					    noack += lsa_flood(iface, nbr,
524 						&lsa_hdr, imsg.data);
525 				    }
526 				}
527 			} else {
528 				/*
529 				 * flood on all area interfaces on
530 				 * area 0.0.0.0 include also virtual links.
531 				 */
532 				area = nbr->iface->area;
533 				LIST_FOREACH(iface, &area->iface_list, entry) {
534 					noack += lsa_flood(iface, nbr,
535 					    &lsa_hdr, imsg.data);
536 				}
537 				/* XXX virtual links */
538 			}
539 
540 			/* remove from ls_req_list */
541 			le = ls_req_list_get(nbr, &lsa_hdr);
542 			if (!(nbr->state & NBR_STA_FULL) && le != NULL) {
543 				ls_req_list_free(nbr, le);
544 				/*
545 				 * XXX no need to ack requested lsa
546 				 * the problem is that the RFC is very
547 				 * unclear about this.
548 				 */
549 				noack = 1;
550 			}
551 
552 			if (!noack && nbr->iface != NULL &&
553 			    nbr->iface->self != nbr) {
554 				if (!(nbr->iface->state & IF_STA_BACKUP) ||
555 				    nbr->iface->dr == nbr) {
556 					/* delayed ack */
557 					lhp = lsa_hdr_new();
558 					memcpy(lhp, &lsa_hdr, sizeof(*lhp));
559 					ls_ack_list_add(nbr->iface, lhp);
560 				}
561 			}
562 
563 			lsa_cache_put(ref, nbr);
564 			break;
565 		case IMSG_LS_UPD:
566 			/*
567 			 * IMSG_LS_UPD is used in three cases:
568 			 * 1. as response to ls requests
569 			 * 2. as response to ls updates where the DB
570 			 *    is newer then the sent LSA
571 			 * 3. in EXSTART when the LSA has age MaxAge
572 			 */
573 			l = imsg.hdr.len - IMSG_HEADER_SIZE;
574 			if (l < sizeof(lsa_hdr))
575 				fatalx("ospfe_dispatch_rde: "
576 				    "bad imsg size");
577 
578 			nbr = nbr_find_peerid(imsg.hdr.peerid);
579 			if (nbr == NULL)
580 				break;
581 
582 			if (nbr->iface->self == nbr)
583 				break;
584 
585 			memcpy(&age, imsg.data, sizeof(age));
586 			ref = lsa_cache_add(imsg.data, l);
587 			if (ntohs(age) >= MAX_AGE)
588 				/* add to retransmit list */
589 				ls_retrans_list_add(nbr, imsg.data, 0, 0);
590 			else
591 				ls_retrans_list_add(nbr, imsg.data, 0, 1);
592 
593 			lsa_cache_put(ref, nbr);
594 			break;
595 		case IMSG_LS_ACK:
596 			/*
597 			 * IMSG_LS_ACK is used in two cases:
598 			 * 1. LSA was a duplicate
599 			 * 2. LS age is MaxAge and there is no current
600 			 *    instance in the DB plus no neighbor in state
601 			 *    Exchange or Loading
602 			 */
603 			nbr = nbr_find_peerid(imsg.hdr.peerid);
604 			if (nbr == NULL)
605 				break;
606 
607 			if (nbr->iface->self == nbr)
608 				break;
609 
610 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lsa_hdr))
611 				fatalx("ospfe_dispatch_rde: bad imsg size");
612 			memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
613 
614 			/* for case one check for implied acks */
615 			if (nbr->iface->state & IF_STA_DROTHER)
616 				if (ls_retrans_list_del(nbr->iface->self,
617 				    &lsa_hdr) == 0)
618 					break;
619 			if (ls_retrans_list_del(nbr, &lsa_hdr) == 0)
620 				break;
621 
622 			/* send a direct acknowledgement */
623 			send_ls_ack(nbr->iface, nbr->addr, imsg.data,
624 			    imsg.hdr.len - IMSG_HEADER_SIZE);
625 
626 			break;
627 		case IMSG_LS_BADREQ:
628 			nbr = nbr_find_peerid(imsg.hdr.peerid);
629 			if (nbr == NULL)
630 				break;
631 
632 			if (nbr->iface->self == nbr)
633 				fatalx("ospfe_dispatch_rde: "
634 				    "dummy neighbor got BADREQ");
635 
636 			nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ);
637 			break;
638 		case IMSG_ABR_UP:
639 			memcpy(&ar, imsg.data, sizeof(ar));
640 
641 			if ((iface = find_vlink(&ar)) != NULL &&
642 			    iface->state == IF_STA_DOWN)
643 				if (if_fsm(iface, IF_EVT_UP)) {
644 					log_debug("error starting interface %s",
645 					    iface->name);
646 				}
647 			break;
648 		case IMSG_ABR_DOWN:
649 			memcpy(&ar, imsg.data, sizeof(ar));
650 
651 			if ((iface = find_vlink(&ar)) != NULL &&
652 			    iface->state == IF_STA_POINTTOPOINT)
653 				if (if_fsm(iface, IF_EVT_DOWN)) {
654 					log_debug("error stopping interface %s",
655 					    iface->name);
656 				}
657 			break;
658 		case IMSG_CTL_AREA:
659 		case IMSG_CTL_END:
660 		case IMSG_CTL_SHOW_DATABASE:
661 		case IMSG_CTL_SHOW_DB_EXT:
662 		case IMSG_CTL_SHOW_DB_NET:
663 		case IMSG_CTL_SHOW_DB_RTR:
664 		case IMSG_CTL_SHOW_DB_SELF:
665 		case IMSG_CTL_SHOW_DB_SUM:
666 		case IMSG_CTL_SHOW_DB_ASBR:
667 		case IMSG_CTL_SHOW_RIB:
668 		case IMSG_CTL_SHOW_SUM:
669 		case IMSG_CTL_SHOW_SUM_AREA:
670 			control_imsg_relay(&imsg);
671 			break;
672 		default:
673 			log_debug("ospfe_dispatch_rde: error handling imsg %d",
674 			    imsg.hdr.type);
675 			break;
676 		}
677 		imsg_free(&imsg);
678 	}
679 	if (!shut)
680 		imsg_event_add(iev);
681 	else {
682 		/* this pipe is dead, so remove the event handler */
683 		event_del(&iev->ev);
684 		event_loopexit(NULL);
685 	}
686 }
687 
688 struct iface *
689 find_vlink(struct abr_rtr *ar)
690 {
691 	struct area	*area;
692 	struct iface	*iface = NULL;
693 
694 	LIST_FOREACH(area, &oeconf->area_list, entry)
695 		LIST_FOREACH(iface, &area->iface_list, entry)
696 			if (iface->abr_id.s_addr == ar->abr_id.s_addr &&
697 			    iface->type == IF_TYPE_VIRTUALLINK &&
698 			    iface->area->id.s_addr == ar->area.s_addr) {
699 				iface->dst.s_addr = ar->dst_ip.s_addr;
700 				iface->addr.s_addr = ar->addr.s_addr;
701 				iface->metric = ar->metric;
702 
703 				return (iface);
704 			}
705 
706 	return (iface);
707 }
708 
709 void
710 orig_rtr_lsa_all(struct area *area)
711 {
712 	struct area	*a;
713 
714 	/*
715 	 * update all router LSA in all areas except area itself,
716 	 * as this update is already running.
717 	 */
718 	LIST_FOREACH(a, &oeconf->area_list, entry)
719 		if (a != area)
720 			orig_rtr_lsa(a);
721 }
722 
723 void
724 orig_rtr_lsa(struct area *area)
725 {
726 	struct lsa_hdr		 lsa_hdr;
727 	struct lsa_rtr		 lsa_rtr;
728 	struct lsa_rtr_link	 rtr_link;
729 	struct iface		*iface;
730 	struct buf		*buf;
731 	struct nbr		*nbr, *self = NULL;
732 	u_int16_t		 num_links = 0;
733 	u_int16_t		 chksum;
734 	u_int8_t		 border, virtual = 0;
735 
736 	log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id));
737 
738 	/* XXX READ_BUF_SIZE */
739 	if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE)) == NULL)
740 		fatal("orig_rtr_lsa");
741 
742 	/* reserve space for LSA header and LSA Router header */
743 	if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL)
744 		fatal("orig_rtr_lsa: buf_reserve failed");
745 
746 	if (buf_reserve(buf, sizeof(lsa_rtr)) == NULL)
747 		fatal("orig_rtr_lsa: buf_reserve failed");
748 
749 	/* links */
750 	LIST_FOREACH(iface, &area->iface_list, entry) {
751 		if (self == NULL && iface->self != NULL)
752 			self = iface->self;
753 
754 		bzero(&rtr_link, sizeof(rtr_link));
755 
756 		if (iface->state & IF_STA_LOOPBACK) {
757 			rtr_link.id = iface->addr.s_addr;
758 			rtr_link.data = 0xffffffff;
759 			rtr_link.type = LINK_TYPE_STUB_NET;
760 			rtr_link.metric = htons(iface->metric);
761 			num_links++;
762 			if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
763 				fatalx("orig_rtr_lsa: buf_add failed");
764 			continue;
765 		}
766 
767 		switch (iface->type) {
768 		case IF_TYPE_POINTOPOINT:
769 			LIST_FOREACH(nbr, &iface->nbr_list, entry)
770 				if (nbr != iface->self &&
771 				    nbr->state & NBR_STA_FULL)
772 					break;
773 			if (nbr) {
774 				log_debug("orig_rtr_lsa: point-to-point, "
775 				    "interface %s", iface->name);
776 				rtr_link.id = nbr->id.s_addr;
777 				rtr_link.data = iface->addr.s_addr;
778 				rtr_link.type = LINK_TYPE_POINTTOPOINT;
779 				/* RFC 3137: stub router support */
780 				if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER ||
781 				    oe_nofib)
782 					rtr_link.metric = MAX_METRIC;
783 				else
784 					rtr_link.metric = htons(iface->metric);
785 				num_links++;
786 				if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
787 					fatalx("orig_rtr_lsa: buf_add failed");
788 			}
789 			if (iface->state & IF_STA_POINTTOPOINT) {
790 				log_debug("orig_rtr_lsa: stub net, "
791 				    "interface %s", iface->name);
792 				bzero(&rtr_link, sizeof(rtr_link));
793 				if (nbr) {
794 					rtr_link.id = nbr->addr.s_addr;
795 					rtr_link.data = 0xffffffff;
796 				} else {
797 					rtr_link.id = iface->addr.s_addr;
798 					rtr_link.data = iface->mask.s_addr;
799 				}
800 				rtr_link.type = LINK_TYPE_STUB_NET;
801 				rtr_link.metric = htons(iface->metric);
802 				num_links++;
803 				if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
804 					fatalx("orig_rtr_lsa: buf_add failed");
805 			}
806 			continue;
807 		case IF_TYPE_BROADCAST:
808 		case IF_TYPE_NBMA:
809 			if ((iface->state & IF_STA_MULTI)) {
810 				if (iface->dr == iface->self) {
811 					LIST_FOREACH(nbr, &iface->nbr_list,
812 					    entry)
813 						if (nbr != iface->self &&
814 						    nbr->state & NBR_STA_FULL)
815 							break;
816 				} else
817 					nbr = iface->dr;
818 
819 				if (nbr && nbr->state & NBR_STA_FULL) {
820 					log_debug("orig_rtr_lsa: transit net, "
821 					    "interface %s", iface->name);
822 
823 					rtr_link.id = iface->dr->addr.s_addr;
824 					rtr_link.data = iface->addr.s_addr;
825 					rtr_link.type = LINK_TYPE_TRANSIT_NET;
826 					break;
827 				}
828 			}
829 
830 			/*
831 			 * do not add a stub net LSA for interfaces that are:
832 			 *  - down
833 			 *  - have a linkstate which is down and are not carp
834 			 *  - have a linkstate unknown and are carp
835 			 * carp uses linkstate down for backup and unknown
836 			 * in cases where a major fubar happend.
837 			 */
838 			if (!(iface->flags & IFF_UP) ||
839 			    (iface->media_type != IFT_CARP &&
840 			    !(LINK_STATE_IS_UP(iface->linkstate) ||
841 			    iface->linkstate == LINK_STATE_UNKNOWN)) ||
842 			    (iface->media_type == IFT_CARP &&
843 			    iface->linkstate == LINK_STATE_UNKNOWN))
844 				continue;
845 			log_debug("orig_rtr_lsa: stub net, "
846 			    "interface %s", iface->name);
847 
848 			rtr_link.id =
849 			    iface->addr.s_addr & iface->mask.s_addr;
850 			rtr_link.data = iface->mask.s_addr;
851 			rtr_link.type = LINK_TYPE_STUB_NET;
852 
853 			rtr_link.num_tos = 0;
854 			/*
855 			 * backup carp interfaces are anounced with high metric
856 			 * for faster failover.
857 			 */
858 			if (iface->media_type == IFT_CARP &&
859 			    iface->linkstate == LINK_STATE_DOWN)
860 				rtr_link.metric = MAX_METRIC;
861 			else
862 				rtr_link.metric = htons(iface->metric);
863 			num_links++;
864 			if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
865 				fatalx("orig_rtr_lsa: buf_add failed");
866 			continue;
867 		case IF_TYPE_VIRTUALLINK:
868 			LIST_FOREACH(nbr, &iface->nbr_list, entry) {
869 				if (nbr != iface->self &&
870 				    nbr->state & NBR_STA_FULL)
871 					break;
872 			}
873 			if (nbr) {
874 				rtr_link.id = nbr->id.s_addr;
875 				rtr_link.data = iface->addr.s_addr;
876 				rtr_link.type = LINK_TYPE_VIRTUAL;
877 				/* RFC 3137: stub router support */
878 				if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER ||
879 				    oe_nofib)
880 					rtr_link.metric = MAX_METRIC;
881 				else
882 					rtr_link.metric = htons(iface->metric);
883 				num_links++;
884 				virtual = 1;
885 				if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
886 					fatalx("orig_rtr_lsa: buf_add failed");
887 
888 				log_debug("orig_rtr_lsa: virtual link, "
889 				    "interface %s", iface->name);
890 			}
891 			continue;
892 		case IF_TYPE_POINTOMULTIPOINT:
893 			log_debug("orig_rtr_lsa: stub net, "
894 			    "interface %s", iface->name);
895 			rtr_link.id = iface->addr.s_addr;
896 			rtr_link.data = 0xffffffff;
897 			rtr_link.type = LINK_TYPE_STUB_NET;
898 			rtr_link.metric = htons(iface->metric);
899 			num_links++;
900 			if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
901 				fatalx("orig_rtr_lsa: buf_add failed");
902 
903 			LIST_FOREACH(nbr, &iface->nbr_list, entry) {
904 				if (nbr != iface->self &&
905 				    nbr->state & NBR_STA_FULL) {
906 					bzero(&rtr_link, sizeof(rtr_link));
907 					log_debug("orig_rtr_lsa: "
908 					    "point-to-multipoint, interface %s",
909 					    iface->name);
910 					rtr_link.id = nbr->addr.s_addr;
911 					rtr_link.data = iface->addr.s_addr;
912 					rtr_link.type = LINK_TYPE_POINTTOPOINT;
913 					/* RFC 3137: stub router support */
914 					if (oe_nofib || oeconf->flags &
915 					    OSPFD_FLAG_STUB_ROUTER)
916 						rtr_link.metric = MAX_METRIC;
917 					else
918 						rtr_link.metric =
919 						    htons(iface->metric);
920 					num_links++;
921 					if (buf_add(buf, &rtr_link,
922 					    sizeof(rtr_link)))
923 						fatalx("orig_rtr_lsa: "
924 						    "buf_add failed");
925 				}
926 			}
927 			continue;
928 		default:
929 			fatalx("orig_rtr_lsa: unknown interface type");
930 		}
931 
932 		rtr_link.num_tos = 0;
933 		/* RFC 3137: stub router support */
934 		if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER || oe_nofib) &&
935 		    rtr_link.type != LINK_TYPE_STUB_NET)
936 			rtr_link.metric = MAX_METRIC;
937 		else
938 			rtr_link.metric = htons(iface->metric);
939 		num_links++;
940 		if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
941 			fatalx("orig_rtr_lsa: buf_add failed");
942 	}
943 
944 	/* LSA router header */
945 	lsa_rtr.flags = 0;
946 	/*
947 	 * Set the E bit as soon as an as-ext lsa may be redistributed, only
948 	 * setting it in case we redistribute something is not worth the fuss.
949 	 * Do not set the E bit in case of a stub area.
950 	 */
951 	if (oeconf->redistribute && !area->stub)
952 		lsa_rtr.flags |= OSPF_RTR_E;
953 
954 	border = (area_border_router(oeconf) != 0);
955 	if (border != oeconf->border) {
956 		oeconf->border = border;
957 		orig_rtr_lsa_all(area);
958 	}
959 
960 	if (oeconf->border)
961 		lsa_rtr.flags |= OSPF_RTR_B;
962 	/* TODO set V flag if a active virtual link ends here and the
963 	 * area is the transit area for this link. */
964 	if (virtual)
965 		lsa_rtr.flags |= OSPF_RTR_V;
966 
967 	lsa_rtr.dummy = 0;
968 	lsa_rtr.nlinks = htons(num_links);
969 	memcpy(buf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_rtr)),
970 	    &lsa_rtr, sizeof(lsa_rtr));
971 
972 	/* LSA header */
973 	lsa_hdr.age = htons(DEFAULT_AGE);
974 	lsa_hdr.opts = area_ospf_options(area);
975 	lsa_hdr.type = LSA_TYPE_ROUTER;
976 	lsa_hdr.ls_id = oeconf->rtr_id.s_addr;
977 	lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
978 	lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
979 	lsa_hdr.len = htons(buf_size(buf));
980 	lsa_hdr.ls_chksum = 0;		/* updated later */
981 	memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
982 
983 	chksum = htons(iso_cksum(buf->buf, buf_size(buf), LS_CKSUM_OFFSET));
984 	memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)),
985 	    &chksum, sizeof(chksum));
986 
987 	if (self)
988 		imsg_compose_event(iev_rde, IMSG_LS_UPD, self->peerid, 0,
989 		    -1, buf->buf, buf_size(buf));
990 	else
991 		log_warnx("orig_rtr_lsa: empty area %s",
992 		    inet_ntoa(area->id));
993 
994 	buf_free(buf);
995 }
996 
997 void
998 orig_net_lsa(struct iface *iface)
999 {
1000 	struct lsa_hdr		 lsa_hdr;
1001 	struct nbr		*nbr;
1002 	struct buf		*buf;
1003 	int			 num_rtr = 0;
1004 	u_int16_t		 chksum;
1005 
1006 	/* XXX READ_BUF_SIZE */
1007 	if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE)) == NULL)
1008 		fatal("orig_net_lsa");
1009 
1010 	/* reserve space for LSA header and LSA Router header */
1011 	if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL)
1012 		fatal("orig_net_lsa: buf_reserve failed");
1013 
1014 	/* LSA net mask and then all fully adjacent routers */
1015 	if (buf_add(buf, &iface->mask, sizeof(iface->mask)))
1016 		fatal("orig_net_lsa: buf_add failed");
1017 
1018 	/* fully adjacent neighbors + self */
1019 	LIST_FOREACH(nbr, &iface->nbr_list, entry)
1020 		if (nbr->state & NBR_STA_FULL) {
1021 			if (buf_add(buf, &nbr->id, sizeof(nbr->id)))
1022 				fatal("orig_net_lsa: buf_add failed");
1023 			num_rtr++;
1024 		}
1025 
1026 	if (num_rtr == 1) {
1027 		/* non transit net therefore no need to generate a net lsa */
1028 		buf_free(buf);
1029 		return;
1030 	}
1031 
1032 	/* LSA header */
1033 	if (iface->state & IF_STA_DR)
1034 		lsa_hdr.age = htons(DEFAULT_AGE);
1035 	else
1036 		lsa_hdr.age = htons(MAX_AGE);
1037 
1038 	lsa_hdr.opts = area_ospf_options(iface->area);
1039 	lsa_hdr.type = LSA_TYPE_NETWORK;
1040 	lsa_hdr.ls_id = iface->addr.s_addr;
1041 	lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
1042 	lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
1043 	lsa_hdr.len = htons(buf_size(buf));
1044 	lsa_hdr.ls_chksum = 0;		/* updated later */
1045 	memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
1046 
1047 	chksum = htons(iso_cksum(buf->buf, buf_size(buf), LS_CKSUM_OFFSET));
1048 	memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)),
1049 	    &chksum, sizeof(chksum));
1050 
1051 	imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0,
1052 	    -1, buf->buf, buf_size(buf));
1053 
1054 	buf_free(buf);
1055 }
1056 
1057 u_int32_t
1058 ospfe_router_id(void)
1059 {
1060 	return (oeconf->rtr_id.s_addr);
1061 }
1062 
1063 void
1064 ospfe_fib_update(int type)
1065 {
1066 	int	old = oe_nofib;
1067 
1068 	if (type == IMSG_CTL_FIB_COUPLE)
1069 		oe_nofib = 0;
1070 	if (type == IMSG_CTL_FIB_DECOUPLE)
1071 		oe_nofib = 1;
1072 	if (old != oe_nofib)
1073 		orig_rtr_lsa_all(NULL);
1074 }
1075 
1076 void
1077 ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx)
1078 {
1079 	struct area		*area;
1080 	struct iface		*iface;
1081 	struct ctl_iface	*ictl;
1082 
1083 	LIST_FOREACH(area, &oeconf->area_list, entry)
1084 		LIST_FOREACH(iface, &area->iface_list, entry)
1085 			if (idx == 0 || idx == iface->ifindex) {
1086 				ictl = if_to_ctl(iface);
1087 				imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
1088 				    0, 0, -1, ictl, sizeof(struct ctl_iface));
1089 			}
1090 }
1091 
1092 void
1093 ospfe_nbr_ctl(struct ctl_conn *c)
1094 {
1095 	struct area	*area;
1096 	struct iface	*iface;
1097 	struct nbr	*nbr;
1098 	struct ctl_nbr	*nctl;
1099 
1100 	LIST_FOREACH(area, &oeconf->area_list, entry)
1101 		LIST_FOREACH(iface, &area->iface_list, entry)
1102 			LIST_FOREACH(nbr, &iface->nbr_list, entry) {
1103 				if (iface->self != nbr) {
1104 					nctl = nbr_to_ctl(nbr);
1105 					imsg_compose_event(&c->iev,
1106 					    IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
1107 					    sizeof(struct ctl_nbr));
1108 				}
1109 			}
1110 
1111 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
1112 }
1113 
1114 void
1115 ospfe_demote_area(struct area *area, int active)
1116 {
1117 	struct demote_msg	dmsg;
1118 
1119 	if (ospfd_process != PROC_OSPF_ENGINE ||
1120 	    area->demote_group[0] == '\0')
1121 		return;
1122 
1123 	bzero(&dmsg, sizeof(dmsg));
1124 	strlcpy(dmsg.demote_group, area->demote_group,
1125 	    sizeof(dmsg.demote_group));
1126 	dmsg.level = area->demote_level;
1127 	if (active)
1128 		dmsg.level = -dmsg.level;
1129 
1130 	ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
1131 }
1132 
1133 void
1134 ospfe_demote_iface(struct iface *iface, int active)
1135 {
1136 	struct demote_msg	dmsg;
1137 
1138 	if (ospfd_process != PROC_OSPF_ENGINE ||
1139 	    iface->demote_group[0] == '\0')
1140 		return;
1141 
1142 	bzero(&dmsg, sizeof(dmsg));
1143 	strlcpy(dmsg.demote_group, iface->demote_group,
1144 	sizeof(dmsg.demote_group));
1145 	if (active)
1146 		dmsg.level = -1;
1147 	else
1148 		dmsg.level = 1;
1149 
1150 	log_warnx("ospfe_demote_iface: group %s level %d", dmsg.demote_group,
1151 		dmsg.level);
1152 
1153 	ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
1154 }
1155