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