xref: /openbsd/usr.sbin/ldpd/kroute.c (revision 404b540a)
1 /*	$OpenBSD: kroute.c,v 1.5 2009/09/28 09:48:46 michele Exp $ */
2 
3 /*
4  * Copyright (c) 2009 Michele Marchetto <michele@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/param.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/sysctl.h>
25 #include <sys/tree.h>
26 #include <sys/uio.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <net/if.h>
30 #include <net/if_dl.h>
31 #include <net/if_types.h>
32 #include <net/route.h>
33 #include <netmpls/mpls.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 
42 #include "ldpd.h"
43 #include "log.h"
44 
45 struct {
46 	u_int32_t		rtseq;
47 	pid_t			pid;
48 	int			fib_sync;
49 	int			fd;
50 	struct event		ev;
51 } kr_state;
52 
53 struct kroute_node {
54 	RB_ENTRY(kroute_node)	 entry;
55 	struct kroute		 r;
56 };
57 
58 struct kif_node {
59 	RB_ENTRY(kif_node)	 entry;
60 	TAILQ_HEAD(, kif_addr)	 addrs;
61 	struct kif		 k;
62 };
63 
64 void	kr_redist_remove(struct kroute_node *);
65 int	kr_redist_eval(struct kroute *, struct rroute *);
66 void	kr_redistribute(struct kroute_node *);
67 int	kroute_compare(struct kroute_node *, struct kroute_node *);
68 int	kif_compare(struct kif_node *, struct kif_node *);
69 int	kr_change_fib(struct kroute_node *, struct kroute *, int);
70 int	kr_delete_fib(struct kroute_node *);
71 
72 struct kroute_node	*kroute_find(in_addr_t, u_int8_t);
73 int			 kroute_insert(struct kroute_node *);
74 int			 kroute_remove(struct kroute_node *);
75 void			 kroute_clear(void);
76 
77 struct kif_node		*kif_find(u_short);
78 struct kif_node		*kif_insert(u_short);
79 int			 kif_remove(struct kif_node *);
80 void			 kif_clear(void);
81 struct kif		*kif_update(u_short, int, struct if_data *,
82 			    struct sockaddr_dl *);
83 int			 kif_validate(u_short);
84 
85 struct kroute_node	*kroute_match(in_addr_t);
86 
87 int		protect_lo(void);
88 u_int8_t	prefixlen_classful(in_addr_t);
89 void		get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
90 void		if_change(u_short, int, struct if_data *);
91 void		if_newaddr(u_short, struct sockaddr_in *, struct sockaddr_in *,
92 		    struct sockaddr_in *);
93 void		if_announce(void *);
94 
95 int		send_rtmsg(int, int, struct kroute *);
96 int		send_rtlabelmsg(int, int, struct kroute *, u_int32_t);
97 int		dispatch_rtmsg(void);
98 int		fetchtable(void);
99 int		fetchifs(u_short);
100 
101 RB_HEAD(kroute_tree, kroute_node)	krt;
102 RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare)
103 RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare)
104 
105 RB_HEAD(kif_tree, kif_node)		kit;
106 RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare)
107 RB_GENERATE(kif_tree, kif_node, entry, kif_compare)
108 
109 struct kroute	kr_all_routers;
110 int		flag_implicit_null = 0;
111 int		flag_all_routers = 0;
112 
113 int
114 kif_init(void)
115 {
116 	RB_INIT(&kit);
117 
118 	if (fetchifs(0) == -1)
119 		return (-1);
120 
121 	return (0);
122 }
123 
124 int
125 kr_init(int fs)
126 {
127 	int		opt = 0, rcvbuf, default_rcvbuf;
128 	socklen_t	optlen;
129 
130 	kr_state.fib_sync = fs;
131 
132 	if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
133 		log_warn("kr_init: socket");
134 		return (-1);
135 	}
136 
137 	/* not interested in my own messages */
138 	if (setsockopt(kr_state.fd, SOL_SOCKET, SO_USELOOPBACK,
139 	    &opt, sizeof(opt)) == -1)
140 		log_warn("kr_init: setsockopt");	/* not fatal */
141 
142 	/* grow receive buffer, don't wanna miss messages */
143 	optlen = sizeof(default_rcvbuf);
144 	if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF,
145 	    &default_rcvbuf, &optlen) == -1)
146 		log_warn("kr_init getsockopt SOL_SOCKET SO_RCVBUF");
147 	else
148 		for (rcvbuf = MAX_RTSOCK_BUF;
149 		    rcvbuf > default_rcvbuf &&
150 		    setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF,
151 		    &rcvbuf, sizeof(rcvbuf)) == -1 && errno == ENOBUFS;
152 		    rcvbuf /= 2)
153 			;	/* nothing */
154 
155 	kr_state.pid = getpid();
156 	kr_state.rtseq = 1;
157 
158 	RB_INIT(&krt);
159 
160 	if (fetchtable() == -1)
161 		return (-1);
162 
163 	if (protect_lo() == -1)
164 		return (-1);
165 
166 	kr_all_routers.prefix.s_addr = inet_addr(AllRouters);
167 	kr_all_routers.prefixlen = mask2prefixlen(INADDR_BROADCAST);
168 	kr_all_routers.nexthop.s_addr = htonl(INADDR_LOOPBACK);
169 
170 	kr_state.fib_sync = 1;	/* force addition of multicast route */
171 	if (send_rtmsg(kr_state.fd, RTM_ADD, &kr_all_routers) != -1)
172 		flag_all_routers = 1;
173 
174 	kr_state.fib_sync = fs;	/* now set correct sync mode */
175 
176 	event_set(&kr_state.ev, kr_state.fd, EV_READ | EV_PERSIST,
177 	    kr_dispatch_msg, NULL);
178 	event_add(&kr_state.ev, NULL);
179 
180 	return (0);
181 }
182 
183 int
184 kr_change_fib(struct kroute_node *kr, struct kroute *kroute, int action)
185 {
186 	struct kroute_node	*kn;
187 
188 	/* nexthop within 127/8 -> ignore silently */
189 	if ((kroute->nexthop.s_addr & htonl(IN_CLASSA_NET)) ==
190 	    htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
191 		return (0);
192 
193 	/* send update */
194 	if (send_rtlabelmsg(kr_state.fd, action, kroute, AF_MPLS) == -1)
195 		return (-1);
196 
197 	if (kroute->nexthop.s_addr != NULL) {
198 		if (send_rtlabelmsg(kr_state.fd, action, kroute,
199 		    AF_INET) == -1)
200 			return (-1);
201 	}
202 
203 	/* create new entry unless we are changing the first entry */
204 	if (action == RTM_ADD) {
205 		if ((kn = calloc(1, sizeof(*kn))) == NULL)
206 			fatal(NULL);
207 	} else
208 		kn = kr;
209 
210 	kn->r.prefix.s_addr = kroute->prefix.s_addr;
211 	kn->r.prefixlen = kroute->prefixlen;
212 	kn->r.local_label = kroute->local_label;
213 	kn->r.remote_label = kroute->remote_label;
214 	kn->r.nexthop.s_addr = kroute->nexthop.s_addr;
215 	kn->r.flags = kroute->flags | F_LDPD_INSERTED;
216 	kn->r.ext_tag = kroute->ext_tag;
217 	rtlabel_unref(kn->r.rtlabel);	/* for RTM_CHANGE */
218 	kn->r.rtlabel = kroute->rtlabel;
219 
220 	if (action == RTM_ADD) {
221 		if (kroute_insert(kn) == -1) {
222 			log_debug("kr_update_fib: cannot insert %s",
223 			    inet_ntoa(kn->r.nexthop));
224 			free(kn);
225 		}
226 	}
227 
228 	return  (0);
229 }
230 
231 int
232 kr_change(struct kroute *kroute)
233 {
234 	struct kroute_node	*kr;
235 	int			 action = RTM_ADD;
236 
237 	kroute->rtlabel = rtlabel_tag2id(kroute->ext_tag);
238 
239 	kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen);
240 
241 	if (kr != NULL && kr->r.flags & F_KERNEL)
242 		action = RTM_CHANGE;
243 
244 	return (kr_change_fib(kr, kroute, action));
245 }
246 
247 int
248 kr_delete_fib(struct kroute_node *kr)
249 {
250 	if (!(kr->r.flags & F_LDPD_INSERTED))
251 		return (0);
252 
253 	if (kr->r.flags & F_KERNEL) {
254 		/* remove F_LDPD_INSERTED flag, route still exists in kernel */
255 		kr->r.flags &= ~F_LDPD_INSERTED;
256 		return (0);
257 	}
258 
259 	if (send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r) == -1)
260 		return (-1);
261 
262 	if (kroute_remove(kr) == -1)
263 		return (-1);
264 
265 	return (0);
266 }
267 
268 int
269 kr_delete(struct kroute *kroute)
270 {
271 	struct kroute_node	*kr;
272 
273 	if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen)) ==
274 	    NULL)
275 		return (0);
276 
277 	if (kr_delete_fib(kr) == -1)
278 		return (-1);
279 
280 	return (0);
281 }
282 
283 void
284 kr_shutdown(void)
285 {
286 	kr_lfib_decouple();
287 
288 	if (flag_all_routers) {
289 		kr_state.fib_sync = 1;	/* force removal of mulitcast route */
290 		(void)send_rtmsg(kr_state.fd, RTM_DELETE, &kr_all_routers);
291 	}
292 
293 	kroute_clear();
294 	kif_clear();
295 }
296 
297 void
298 kr_lfib_couple(void)
299 {
300 	struct kroute_node	*kr;
301 
302 	if (kr_state.fib_sync == 1)	/* already coupled */
303 		return;
304 
305 	kr_state.fib_sync = 1;
306 
307 	RB_FOREACH(kr, kroute_tree, &krt)
308 		if (!(kr->r.flags & F_KERNEL))
309 			send_rtmsg(kr_state.fd, RTM_ADD, &kr->r);
310 
311 	log_info("kernel routing table coupled");
312 }
313 
314 void
315 kr_lfib_decouple(void)
316 {
317 	struct kroute_node	*kr;
318 
319 	if (kr_state.fib_sync == 0)	/* already decoupled */
320 		return;
321 
322 	RB_FOREACH(kr, kroute_tree, &krt) {
323 		if (kr->r.flags & F_LDPD_INSERTED) {
324 			send_rtlabelmsg(kr_state.fd, RTM_DELETE,
325 			    &kr->r, AF_MPLS);
326 
327 			if (kr->r.nexthop.s_addr != NULL) {
328 				send_rtlabelmsg(kr_state.fd, RTM_DELETE,
329 				    &kr->r, AF_INET);
330 			}
331 		}
332 	}
333 
334 	kr_state.fib_sync = 0;
335 
336 	log_info("kernel routing table decoupled");
337 }
338 
339 /* ARGSUSED */
340 void
341 kr_dispatch_msg(int fd, short event, void *bula)
342 {
343 	dispatch_rtmsg();
344 }
345 
346 void
347 kr_show_route(struct imsg *imsg)
348 {
349 	struct kroute_node	*kr;
350 	int			 flags;
351 	struct in_addr		 addr;
352 
353 	switch (imsg->hdr.type) {
354 	case IMSG_CTL_KROUTE:
355 		if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(flags)) {
356 			log_warnx("kr_show_route: wrong imsg len");
357 			return;
358 		}
359 		memcpy(&flags, imsg->data, sizeof(flags));
360 		RB_FOREACH(kr, kroute_tree, &krt)
361 			if (!flags || kr->r.flags & flags) {
362 				main_imsg_compose_ldpe(IMSG_CTL_KROUTE,
363 				    imsg->hdr.pid, &kr->r, sizeof(kr->r));
364 			}
365 		break;
366 	case IMSG_CTL_KROUTE_ADDR:
367 		if (imsg->hdr.len != IMSG_HEADER_SIZE +
368 		    sizeof(struct in_addr)) {
369 			log_warnx("kr_show_route: wrong imsg len");
370 			return;
371 		}
372 		memcpy(&addr, imsg->data, sizeof(addr));
373 		kr = NULL;
374 		kr = kroute_match(addr.s_addr);
375 		if (kr != NULL)
376 			main_imsg_compose_ldpe(IMSG_CTL_KROUTE, imsg->hdr.pid,
377 			    &kr->r, sizeof(kr->r));
378 		break;
379 	default:
380 		log_debug("kr_show_route: error handling imsg");
381 		break;
382 	}
383 
384 	main_imsg_compose_ldpe(IMSG_CTL_END, imsg->hdr.pid, NULL, 0);
385 }
386 
387 void
388 kr_ifinfo(char *ifname, pid_t pid)
389 {
390 	struct kif_node	*kif;
391 
392 	RB_FOREACH(kif, kif_tree, &kit)
393 		if (ifname == NULL || !strcmp(ifname, kif->k.ifname)) {
394 			main_imsg_compose_ldpe(IMSG_CTL_IFINFO,
395 			    pid, &kif->k, sizeof(kif->k));
396 		}
397 
398 	main_imsg_compose_ldpe(IMSG_CTL_END, pid, NULL, 0);
399 }
400 
401 void
402 kr_redist_remove(struct kroute_node *kn)
403 {
404 	struct rroute	 rr;
405 
406 	/* was the route redistributed? */
407 	if ((kn->r.flags & F_REDISTRIBUTED) == 0)
408 		return;
409 
410 	/* remove redistributed flag */
411 	kn->r.flags &= ~F_REDISTRIBUTED;
412 	rr.kr = kn->r;
413 
414 	if (kn == NULL) {
415 		main_imsg_compose_lde(IMSG_NETWORK_DEL, 0, &rr.kr,
416 		    sizeof(struct rroute));
417 	}
418 }
419 
420 int
421 kr_redist_eval(struct kroute *kr, struct rroute *rr)
422 {
423 	u_int32_t	 a, metric = 0;
424 
425 	/* Only static routes are considered for redistribution. */
426 	if (!(kr->flags & F_KERNEL))
427 		goto dont_redistribute;
428 
429 	/* Dynamic routes are not redistributable. */
430 	if (kr->flags & F_DYNAMIC)
431 		goto dont_redistribute;
432 
433 	/* interface is not up and running so don't announce */
434 	if (kr->flags & F_DOWN)
435 		goto dont_redistribute;
436 
437 	/*
438 	 * We consider the loopback net, multicast and experimental addresses
439 	 * as not redistributable.
440 	 */
441 	a = ntohl(kr->prefix.s_addr);
442 	if (IN_MULTICAST(a) || IN_BADCLASS(a) ||
443 	    (a >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
444 		goto dont_redistribute;
445 	/*
446 	 * Consider networks with nexthop loopback as not redistributable.
447 	 */
448 	if (kr->nexthop.s_addr == htonl(INADDR_LOOPBACK))
449 		goto dont_redistribute;
450 
451 	/* prefix should be redistributed */
452 	kr->flags |= F_REDISTRIBUTED;
453 	/*
454 	 * only on of all multipath routes can be redistributed so
455 	 * redistribute the best one.
456 	 */
457 	if (rr->metric > metric) {
458 		rr->kr = *kr;
459 		rr->metric = metric;
460 	}
461 	return (1);
462 
463 dont_redistribute:
464 	/* was the route redistributed? */
465 	if ((kr->flags & F_REDISTRIBUTED) == 0)
466 		return (0);
467 
468 	kr->flags &= ~F_REDISTRIBUTED;
469 	return (1);
470 }
471 
472 void
473 kr_redistribute(struct kroute_node *kh)
474 {
475 	struct rroute		 rr;
476 
477 	bzero(&rr, sizeof(rr));
478 	rr.metric = UINT_MAX;
479 	if (!kr_redist_eval(&kh->r, &rr))
480 		return;
481 
482 	if (rr.kr.flags & F_REDISTRIBUTED) {
483 		main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &rr,
484 		    sizeof(struct rroute));
485 	} else {
486 		rr.kr = kh->r;
487 		main_imsg_compose_lde(IMSG_NETWORK_DEL, 0, &rr.kr,
488 		    sizeof(struct rroute));
489 	}
490 }
491 
492 void
493 kr_reload(void)
494 {
495 	struct kroute_node	*kr;
496 
497 	RB_FOREACH(kr, kroute_tree, &krt) {
498 		if (kr->r.flags & F_REDISTRIBUTED)
499 			kr_redistribute(kr);
500 	}
501 }
502 
503 /* rb-tree compare */
504 int
505 kroute_compare(struct kroute_node *a, struct kroute_node *b)
506 {
507 	if (ntohl(a->r.prefix.s_addr) < ntohl(b->r.prefix.s_addr))
508 		return (-1);
509 	if (ntohl(a->r.prefix.s_addr) > ntohl(b->r.prefix.s_addr))
510 		return (1);
511 	if (a->r.prefixlen < b->r.prefixlen)
512 		return (-1);
513 	if (a->r.prefixlen > b->r.prefixlen)
514 		return (1);
515 	return (0);
516 }
517 
518 int
519 kif_compare(struct kif_node *a, struct kif_node *b)
520 {
521 	return (b->k.ifindex - a->k.ifindex);
522 }
523 
524 /* tree management */
525 struct kroute_node *
526 kroute_find(in_addr_t prefix, u_int8_t prefixlen)
527 {
528 	struct kroute_node	s;
529 
530 	s.r.prefix.s_addr = prefix;
531 	s.r.prefixlen = prefixlen;
532 
533 	return (RB_FIND(kroute_tree, &krt, &s));
534 }
535 
536 int
537 kroute_insert(struct kroute_node *kr)
538 {
539 	if (RB_INSERT(kroute_tree, &krt, kr) != NULL) {
540 		log_warnx("kroute_insert failed for %s/%u",
541 		    inet_ntoa(kr->r.prefix), kr->r.prefixlen);
542 		free(kr);
543 		return (-1);
544 	}
545 
546 	if (!(kr->r.flags & F_KERNEL)) {
547 		kr->r.flags &= ~F_DOWN;
548 		return (0);
549 	}
550 
551 	if (kif_validate(kr->r.ifindex))
552 		kr->r.flags &= ~F_DOWN;
553 	else
554 		kr->r.flags |= F_DOWN;
555 
556 	kr_redistribute(kr);
557 	return (0);
558 }
559 
560 int
561 kroute_insert_label(struct kroute *kr)
562 {
563 	struct kroute_node *krn;
564 
565 	krn = kroute_find(kr->prefix.s_addr, kr->prefixlen);
566 	if (krn == NULL) {
567 		log_debug("kroute_insert_label: prefix %s/%d not present",
568 		    inet_ntoa(kr->prefix), kr->prefixlen);
569 		return (-1);
570 	}
571 
572 	krn->r.flags |= F_LDPD_INSERTED;
573 	krn->r.local_label = kr->local_label;
574 	krn->r.remote_label = kr->remote_label;
575 
576 	send_rtlabelmsg(kr_state.fd, RTM_ADD, kr, AF_MPLS);
577 
578 	if (kr->nexthop.s_addr != INADDR_ANY)
579 		send_rtlabelmsg(kr_state.fd, RTM_ADD, kr, AF_INET);
580 
581 	return (0);
582 }
583 
584 int
585 kroute_remove(struct kroute_node *kr)
586 {
587 	if (RB_REMOVE(kroute_tree, &krt, kr) == NULL) {
588 		log_warnx("kroute_remove failed for %s/%u",
589 		    inet_ntoa(kr->r.prefix), kr->r.prefixlen);
590 		return (-1);
591 	}
592 
593 	kr_redist_remove(kr);
594 	rtlabel_unref(kr->r.rtlabel);
595 
596 	free(kr);
597 	return (0);
598 }
599 
600 void
601 kroute_clear(void)
602 {
603 	struct kroute_node	*kr;
604 
605 	while ((kr = RB_MIN(kroute_tree, &krt)) != NULL)
606 		kroute_remove(kr);
607 }
608 
609 struct kif_node *
610 kif_find(u_short ifindex)
611 {
612 	struct kif_node	s;
613 
614 	bzero(&s, sizeof(s));
615 	s.k.ifindex = ifindex;
616 
617 	return (RB_FIND(kif_tree, &kit, &s));
618 }
619 
620 struct kif *
621 kif_findname(char *ifname, struct in_addr addr, struct kif_addr **kap)
622 {
623 	struct kif_node	*kif;
624 	struct kif_addr	*ka;
625 
626 	RB_FOREACH(kif, kif_tree, &kit)
627 		if (!strcmp(ifname, kif->k.ifname)) {
628 			ka = TAILQ_FIRST(&kif->addrs);
629 			if (addr.s_addr != 0) {
630 				TAILQ_FOREACH(ka, &kif->addrs, entry) {
631 					if (addr.s_addr == ka->addr.s_addr)
632 						break;
633 				}
634 			}
635 			if (kap != NULL)
636 				*kap = ka;
637 			return (&kif->k);
638 		}
639 
640 	return (NULL);
641 }
642 
643 struct kif_node *
644 kif_insert(u_short ifindex)
645 {
646 	struct kif_node	*kif;
647 
648 	if ((kif = calloc(1, sizeof(struct kif_node))) == NULL)
649 		return (NULL);
650 
651 	kif->k.ifindex = ifindex;
652 	TAILQ_INIT(&kif->addrs);
653 
654 	if (RB_INSERT(kif_tree, &kit, kif) != NULL)
655 		fatalx("kif_insert: RB_INSERT");
656 
657 	return (kif);
658 }
659 
660 int
661 kif_remove(struct kif_node *kif)
662 {
663 	struct kif_addr	*ka;
664 
665 	if (RB_REMOVE(kif_tree, &kit, kif) == NULL) {
666 		log_warnx("RB_REMOVE(kif_tree, &kit, kif)");
667 		return (-1);
668 	}
669 
670 	while ((ka = TAILQ_FIRST(&kif->addrs)) != NULL) {
671 		TAILQ_REMOVE(&kif->addrs, ka, entry);
672 		free(ka);
673 	}
674 	free(kif);
675 	return (0);
676 }
677 
678 void
679 kif_clear(void)
680 {
681 	struct kif_node	*kif;
682 
683 	while ((kif = RB_MIN(kif_tree, &kit)) != NULL)
684 		kif_remove(kif);
685 }
686 
687 struct kif *
688 kif_update(u_short ifindex, int flags, struct if_data *ifd,
689     struct sockaddr_dl *sdl)
690 {
691 	struct kif_node		*kif;
692 
693 	if ((kif = kif_find(ifindex)) == NULL)
694 		if ((kif = kif_insert(ifindex)) == NULL)
695 			return (NULL);
696 
697 	kif->k.flags = flags;
698 	kif->k.link_state = ifd->ifi_link_state;
699 	kif->k.media_type = ifd->ifi_type;
700 	kif->k.baudrate = ifd->ifi_baudrate;
701 	kif->k.mtu = ifd->ifi_mtu;
702 
703 	if (sdl && sdl->sdl_family == AF_LINK) {
704 		if (sdl->sdl_nlen >= sizeof(kif->k.ifname))
705 			memcpy(kif->k.ifname, sdl->sdl_data,
706 			    sizeof(kif->k.ifname) - 1);
707 		else if (sdl->sdl_nlen > 0)
708 			memcpy(kif->k.ifname, sdl->sdl_data,
709 			    sdl->sdl_nlen);
710 		/* string already terminated via calloc() */
711 	}
712 
713 	return (&kif->k);
714 }
715 
716 int
717 kif_validate(u_short ifindex)
718 {
719 	struct kif_node		*kif;
720 
721 	if ((kif = kif_find(ifindex)) == NULL) {
722 		log_warnx("interface with index %u not found", ifindex);
723 		return (1);
724 	}
725 
726 	return (kif->k.nh_reachable);
727 }
728 
729 struct kroute_node *
730 kroute_match(in_addr_t key)
731 {
732 	int			 i;
733 	struct kroute_node	*kr;
734 
735 	/* we will never match the default route */
736 	for (i = 32; i > 0; i--)
737 		if ((kr = kroute_find(key & prefixlen2mask(i), i)) != NULL)
738 			return (kr);
739 
740 	/* if we don't have a match yet, try to find a default route */
741 	if ((kr = kroute_find(0, 0)) != NULL)
742 			return (kr);
743 
744 	return (NULL);
745 }
746 
747 /* misc */
748 int
749 protect_lo(void)
750 {
751 	struct kroute_node	*kr;
752 
753 	/* special protection for 127/8 */
754 	if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
755 		log_warn("protect_lo");
756 		return (-1);
757 	}
758 	kr->r.prefix.s_addr = htonl(INADDR_LOOPBACK);
759 	kr->r.prefixlen = 8;
760 	kr->r.flags = F_KERNEL|F_CONNECTED;
761 
762 	if (RB_INSERT(kroute_tree, &krt, kr) != NULL)
763 		free(kr);	/* kernel route already there, no problem */
764 
765 	return (0);
766 }
767 
768 u_int8_t
769 prefixlen_classful(in_addr_t ina)
770 {
771 	/* it hurt to write this. */
772 
773 	if (ina >= 0xf0000000U)		/* class E */
774 		return (32);
775 	else if (ina >= 0xe0000000U)	/* class D */
776 		return (4);
777 	else if (ina >= 0xc0000000U)	/* class C */
778 		return (24);
779 	else if (ina >= 0x80000000U)	/* class B */
780 		return (16);
781 	else				/* class A */
782 		return (8);
783 }
784 
785 u_int8_t
786 mask2prefixlen(in_addr_t ina)
787 {
788 	if (ina == 0)
789 		return (0);
790 	else
791 		return (33 - ffs(ntohl(ina)));
792 }
793 
794 in_addr_t
795 prefixlen2mask(u_int8_t prefixlen)
796 {
797 	if (prefixlen == 0)
798 		return (0);
799 
800 	return (htonl(0xffffffff << (32 - prefixlen)));
801 }
802 
803 #define	ROUNDUP(a, size)	\
804     (((a) & ((size) - 1)) ? (1 + ((a) | ((size) - 1))) : (a))
805 
806 void
807 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
808 {
809 	int	i;
810 
811 	for (i = 0; i < RTAX_MAX; i++) {
812 		if (addrs & (1 << i)) {
813 			rti_info[i] = sa;
814 			sa = (struct sockaddr *)((char *)(sa) +
815 			    ROUNDUP(sa->sa_len, sizeof(long)));
816 		} else
817 			rti_info[i] = NULL;
818 	}
819 }
820 
821 void
822 if_change(u_short ifindex, int flags, struct if_data *ifd)
823 {
824 	struct kroute_node	*kr;
825 	struct kif		*kif;
826 	u_int8_t		 reachable;
827 
828 	if ((kif = kif_update(ifindex, flags, ifd, NULL)) == NULL) {
829 		log_warn("if_change:  kif_update(%u)", ifindex);
830 		return;
831 	}
832 
833 	reachable = (kif->flags & IFF_UP) &&
834 	    (LINK_STATE_IS_UP(kif->link_state) ||
835 	    (kif->link_state == LINK_STATE_UNKNOWN &&
836 	    kif->media_type != IFT_CARP));
837 
838 	if (reachable == kif->nh_reachable)
839 		return;		/* nothing changed wrt nexthop validity */
840 
841 	kif->nh_reachable = reachable;
842 
843 	/* notify ldpe about interface link state */
844 	main_imsg_compose_ldpe(IMSG_IFINFO, 0, kif, sizeof(struct kif));
845 
846 	/* update redistribute list */
847 	RB_FOREACH(kr, kroute_tree, &krt) {
848 		if (kr->r.ifindex == ifindex) {
849 			if (reachable)
850 				kr->r.flags &= ~F_DOWN;
851 			else
852 				kr->r.flags |= F_DOWN;
853 
854 			kr_redistribute(kr);
855 		}
856 	}
857 }
858 
859 void
860 if_newaddr(u_short ifindex, struct sockaddr_in *ifa, struct sockaddr_in *mask,
861     struct sockaddr_in *brd)
862 {
863 	struct kif_node *kif;
864 	struct kif_addr *ka;
865 
866 	if (ifa == NULL || ifa->sin_family != AF_INET)
867 		return;
868 	if ((kif = kif_find(ifindex)) == NULL) {
869 		log_warnx("if_newaddr: corresponding if %i not found", ifindex);
870 		return;
871 	}
872 	if ((ka = calloc(1, sizeof(struct kif_addr))) == NULL)
873 		fatal("if_newaddr");
874 	ka->addr = ifa->sin_addr;
875 	if (mask)
876 		ka->mask = mask->sin_addr;
877 	else
878 		ka->mask.s_addr = INADDR_NONE;
879 	if (brd)
880 		ka->dstbrd = brd->sin_addr;
881 	else
882 		ka->dstbrd.s_addr = INADDR_NONE;
883 
884 	TAILQ_INSERT_TAIL(&kif->addrs, ka, entry);
885 }
886 
887 void
888 if_announce(void *msg)
889 {
890 	struct if_announcemsghdr	*ifan;
891 	struct kif_node			*kif;
892 
893 	ifan = msg;
894 
895 	switch (ifan->ifan_what) {
896 	case IFAN_ARRIVAL:
897 		kif = kif_insert(ifan->ifan_index);
898 		strlcpy(kif->k.ifname, ifan->ifan_name, sizeof(kif->k.ifname));
899 		break;
900 	case IFAN_DEPARTURE:
901 		kif = kif_find(ifan->ifan_index);
902 		kif_remove(kif);
903 		break;
904 	}
905 }
906 
907 /* rtsock */
908 int
909 send_rtlabelmsg(int fd, int action, struct kroute *kroute, u_int32_t family)
910 {
911 	struct iovec		iov[5];
912 	struct rt_msghdr	hdr;
913 	struct sockaddr_mpls	label_in, label_out;
914 	struct sockaddr_in	dst, mask, nexthop;
915 	u_int32_t		hr_label;
916 	int			iovcnt = 0;
917 
918 	if (kr_state.fib_sync == 0)
919 		return (0);
920 
921 	/* Implicit NULL label should be added/remove just one time */
922 	hr_label = ntohl(kroute->local_label) >> MPLS_LABEL_OFFSET;
923 	if (hr_label == MPLS_LABEL_IMPLNULL) {
924 		if (action == RTM_ADD && flag_implicit_null)
925 			return (0);
926 
927 		if (action == RTM_DELETE && !flag_implicit_null)
928 			return (0);
929 	}
930 
931 	if (family == AF_INET && kroute->remote_label == 0)
932 		return (0);
933 
934 	/* initialize header */
935 	bzero(&hdr, sizeof(hdr));
936 	hdr.rtm_version = RTM_VERSION;
937 
938 	/* ldpd must not add/delete AF_INET routes, instead it should just
939 	   modify existing ones adding/remove relevant MPLS infos */
940 	if (family == AF_INET)
941 		hdr.rtm_type = RTM_CHANGE;
942 	else
943 		hdr.rtm_type = action;
944 
945 	hdr.rtm_flags = RTF_UP;
946 	hdr.rtm_priority = 0;
947 	hdr.rtm_seq = kr_state.rtseq++;	/* overflow doesn't matter */
948 	hdr.rtm_msglen = sizeof(hdr);
949 	hdr.rtm_hdrlen = sizeof(struct rt_msghdr);
950 	/* adjust iovec */
951 	iov[iovcnt].iov_base = &hdr;
952 	iov[iovcnt++].iov_len = sizeof(hdr);
953 
954 	if (family == AF_MPLS) {
955 		bzero(&label_in, sizeof(label_in));
956 		label_in.smpls_len = sizeof(label_in);
957 		label_in.smpls_family = AF_MPLS;
958 		label_in.smpls_label = kroute->local_label;
959 		/* adjust header */
960 		hdr.rtm_addrs |= RTA_DST;
961 		hdr.rtm_msglen += sizeof(label_in);
962 		/* adjust iovec */
963 		iov[iovcnt].iov_base = &label_in;
964 		iov[iovcnt++].iov_len = sizeof(label_in);
965 	} else {
966 		bzero(&dst, sizeof(dst));
967 		dst.sin_len = sizeof(dst);
968 		dst.sin_family = AF_INET;
969 		dst.sin_addr.s_addr = kroute->prefix.s_addr;
970 		/* adjust header */
971 		hdr.rtm_addrs |= RTA_DST;
972 		hdr.rtm_msglen += sizeof(dst);
973 		/* adjust iovec */
974 		iov[iovcnt].iov_base = &dst;
975 		iov[iovcnt++].iov_len = sizeof(dst);
976 	}
977 
978 	bzero(&nexthop, sizeof(nexthop));
979 	nexthop.sin_len = sizeof(nexthop);
980 	nexthop.sin_family = AF_INET;
981 	nexthop.sin_addr.s_addr = kroute->nexthop.s_addr;
982 	/* adjust header */
983 	hdr.rtm_flags |= RTF_GATEWAY;
984 	hdr.rtm_addrs |= RTA_GATEWAY;
985 	hdr.rtm_msglen += sizeof(nexthop);
986 	/* adjust iovec */
987 	iov[iovcnt].iov_base = &nexthop;
988 	iov[iovcnt++].iov_len = sizeof(nexthop);
989 
990 	if (family == AF_INET) {
991 		bzero(&mask, sizeof(mask));
992 		mask.sin_len = sizeof(mask);
993 		mask.sin_family = AF_INET;
994 		mask.sin_addr.s_addr = prefixlen2mask(kroute->prefixlen);
995 		/* adjust header */
996 		hdr.rtm_addrs |= RTA_NETMASK;
997 		hdr.rtm_msglen += sizeof(mask);
998 		/* adjust iovec */
999 		iov[iovcnt].iov_base = &mask;
1000 		iov[iovcnt++].iov_len = sizeof(mask);
1001 	}
1002 
1003 	/* If action is RTM_DELETE we have to get rid of MPLS infos */
1004 	if (kroute->remote_label != 0 && action != RTM_DELETE) {
1005 		bzero(&label_out, sizeof(label_out));
1006 		label_out.smpls_len = sizeof(label_out);
1007 		label_out.smpls_family = AF_MPLS;
1008 		label_out.smpls_label = kroute->remote_label;
1009 		/* adjust header */
1010 		hdr.rtm_addrs |= RTA_SRC;
1011 		hdr.rtm_msglen += sizeof(label_out);
1012 		/* adjust iovec */
1013 		iov[iovcnt].iov_base = &label_out;
1014 		iov[iovcnt++].iov_len = sizeof(label_out);
1015 
1016 		if (family == AF_MPLS)
1017 			hdr.rtm_mpls = MPLS_OP_SWAP;
1018 		else
1019 			hdr.rtm_mpls = MPLS_OP_PUSH;
1020 	}
1021 
1022 
1023 retry:
1024 	if (writev(fd, iov, iovcnt) == -1) {
1025 		switch (errno) {
1026 		case ESRCH:
1027 			if (hdr.rtm_type == RTM_CHANGE) {
1028 				hdr.rtm_type = RTM_ADD;
1029 				goto retry;
1030 			} else if (hdr.rtm_type == RTM_DELETE) {
1031 				log_info("route %s/%u vanished before delete",
1032 				    inet_ntoa(kroute->prefix),
1033 				    kroute->prefixlen);
1034 				return (0);
1035 			} else {
1036 				log_warnx("send_rtlabelmsg: action %u, "
1037 				    "prefix %s/%u: %s", hdr.rtm_type,
1038 				    inet_ntoa(kroute->prefix),
1039 				    kroute->prefixlen, strerror(errno));
1040 				return (0);
1041 			}
1042 			break;
1043 		default:
1044 			log_warnx("send_rtlabelmsg: action %u, "
1045 			    "prefix %s/%u: %s", hdr.rtm_type,
1046 			    inet_ntoa(kroute->prefix),
1047 			    kroute->prefixlen, strerror(errno));
1048 			return (0);
1049 		}
1050 	}
1051 
1052 	if (hr_label == MPLS_LABEL_IMPLNULL) {
1053 		if (action == RTM_ADD)
1054 			flag_implicit_null = 1;
1055 
1056 		if (action == RTM_DELETE)
1057 			flag_implicit_null = 0;
1058 	}
1059 
1060 	return (0);
1061 }
1062 
1063 int
1064 send_rtmsg(int fd, int action, struct kroute *kroute)
1065 {
1066 	struct iovec		iov[5];
1067 	struct rt_msghdr	hdr;
1068 	struct sockaddr_in	prefix;
1069 	struct sockaddr_in	nexthop;
1070 	struct sockaddr_in	mask;
1071 	struct sockaddr_rtlabel	sa_rl;
1072 	int			iovcnt = 0;
1073 	const char		*label;
1074 
1075 	/* initialize header */
1076 	bzero(&hdr, sizeof(hdr));
1077 	hdr.rtm_version = RTM_VERSION;
1078 	hdr.rtm_type = action;
1079 	hdr.rtm_priority = RTP_STATIC;
1080 	if (action == RTM_CHANGE)	/* force PROTO2 reset the other flags */
1081 		hdr.rtm_fmask = RTF_PROTO2|RTF_PROTO1|RTF_REJECT|RTF_BLACKHOLE;
1082 	hdr.rtm_seq = kr_state.rtseq++;	/* overflow doesn't matter */
1083 	hdr.rtm_msglen = sizeof(hdr);
1084 	hdr.rtm_hdrlen = sizeof(struct rt_msghdr);
1085 	/* adjust iovec */
1086 	iov[iovcnt].iov_base = &hdr;
1087 	iov[iovcnt++].iov_len = sizeof(hdr);
1088 
1089 	bzero(&prefix, sizeof(prefix));
1090 	prefix.sin_len = sizeof(prefix);
1091 	prefix.sin_family = AF_INET;
1092 	prefix.sin_addr.s_addr = kroute->prefix.s_addr;
1093 	/* adjust header */
1094 	hdr.rtm_addrs |= RTA_DST;
1095 	hdr.rtm_msglen += sizeof(prefix);
1096 	/* adjust iovec */
1097 	iov[iovcnt].iov_base = &prefix;
1098 	iov[iovcnt++].iov_len = sizeof(prefix);
1099 
1100 	if (kroute->nexthop.s_addr != 0) {
1101 		bzero(&nexthop, sizeof(nexthop));
1102 		nexthop.sin_len = sizeof(nexthop);
1103 		nexthop.sin_family = AF_INET;
1104 		nexthop.sin_addr.s_addr = kroute->nexthop.s_addr;
1105 		/* adjust header */
1106 		hdr.rtm_flags |= RTF_GATEWAY;
1107 		hdr.rtm_addrs |= RTA_GATEWAY;
1108 		hdr.rtm_msglen += sizeof(nexthop);
1109 		/* adjust iovec */
1110 		iov[iovcnt].iov_base = &nexthop;
1111 		iov[iovcnt++].iov_len = sizeof(nexthop);
1112 	}
1113 
1114 	bzero(&mask, sizeof(mask));
1115 	mask.sin_len = sizeof(mask);
1116 	mask.sin_family = AF_INET;
1117 	mask.sin_addr.s_addr = prefixlen2mask(kroute->prefixlen);
1118 	/* adjust header */
1119 	hdr.rtm_addrs |= RTA_NETMASK;
1120 	hdr.rtm_msglen += sizeof(mask);
1121 	/* adjust iovec */
1122 	iov[iovcnt].iov_base = &mask;
1123 	iov[iovcnt++].iov_len = sizeof(mask);
1124 
1125 	if (kroute->rtlabel != 0) {
1126 		sa_rl.sr_len = sizeof(sa_rl);
1127 		sa_rl.sr_family = AF_UNSPEC;
1128 		label = rtlabel_id2name(kroute->rtlabel);
1129 		if (strlcpy(sa_rl.sr_label, label,
1130 		    sizeof(sa_rl.sr_label)) >= sizeof(sa_rl.sr_label)) {
1131 			log_warnx("send_rtmsg: invalid rtlabel");
1132 			return (-1);
1133 		}
1134 		/* adjust header */
1135 		hdr.rtm_addrs |= RTA_LABEL;
1136 		hdr.rtm_msglen += sizeof(sa_rl);
1137 		/* adjust iovec */
1138 		iov[iovcnt].iov_base = &sa_rl;
1139 		iov[iovcnt++].iov_len = sizeof(sa_rl);
1140 	}
1141 
1142 retry:
1143 	if (writev(fd, iov, iovcnt) == -1) {
1144 		switch (errno) {
1145 		case ESRCH:
1146 			if (hdr.rtm_type == RTM_CHANGE) {
1147 				hdr.rtm_type = RTM_ADD;
1148 				goto retry;
1149 			} else if (hdr.rtm_type == RTM_DELETE) {
1150 				log_info("route %s/%u vanished before delete",
1151 				    inet_ntoa(kroute->prefix),
1152 				    kroute->prefixlen);
1153 				return (0);
1154 			} else {
1155 				log_warnx("send_rtmsg: action %u, "
1156 				    "prefix %s/%u: %s", hdr.rtm_type,
1157 				    inet_ntoa(kroute->prefix),
1158 				    kroute->prefixlen, strerror(errno));
1159 				return (0);
1160 			}
1161 			break;
1162 		default:
1163 			log_warnx("send_rtmsg: action %u, prefix %s/%u: %s",
1164 			    hdr.rtm_type, inet_ntoa(kroute->prefix),
1165 			    kroute->prefixlen, strerror(errno));
1166 			return (0);
1167 		}
1168 	}
1169 
1170 	return (0);
1171 }
1172 
1173 int
1174 fetchtable(void)
1175 {
1176 	size_t			 len;
1177 	int			 mib[7];
1178 	char			*buf, *next, *lim;
1179 	struct rt_msghdr	*rtm;
1180 	struct sockaddr		*sa, *rti_info[RTAX_MAX];
1181 	struct sockaddr_in	*sa_in;
1182 	struct sockaddr_rtlabel	*label;
1183 	struct sockaddr_mpls	*sa_mpls;
1184 	struct kroute_node	*kr;
1185 
1186 	mib[0] = CTL_NET;
1187 	mib[1] = AF_ROUTE;
1188 	mib[2] = 0;
1189 	mib[3] = AF_INET;
1190 	mib[4] = NET_RT_DUMP;
1191 	mib[5] = 0;
1192 	mib[6] = 0;	/* rtableid */
1193 
1194 	if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) {
1195 		log_warn("sysctl");
1196 		return (-1);
1197 	}
1198 	if ((buf = malloc(len)) == NULL) {
1199 		log_warn("fetchtable");
1200 		return (-1);
1201 	}
1202 	if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) {
1203 		log_warn("sysctl");
1204 		free(buf);
1205 		return (-1);
1206 	}
1207 
1208 	lim = buf + len;
1209 	for (next = buf; next < lim; next += rtm->rtm_msglen) {
1210 		rtm = (struct rt_msghdr *)next;
1211 		if (rtm->rtm_version != RTM_VERSION)
1212 			continue;
1213 		sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
1214 		get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1215 
1216 		if ((sa = rti_info[RTAX_DST]) == NULL)
1217 			continue;
1218 
1219 		if (rtm->rtm_flags & RTF_LLINFO)	/* arp cache */
1220 			continue;
1221 
1222 		if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
1223 			log_warn("fetchtable");
1224 			free(buf);
1225 			return (-1);
1226 		}
1227 
1228 		kr->r.flags = F_KERNEL;
1229 
1230 		switch (sa->sa_family) {
1231 		case AF_INET:
1232 			kr->r.prefix.s_addr =
1233 			    ((struct sockaddr_in *)sa)->sin_addr.s_addr;
1234 			sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
1235 			if (rtm->rtm_flags & RTF_STATIC)
1236 				kr->r.flags |= F_STATIC;
1237 			if (rtm->rtm_flags & RTF_DYNAMIC)
1238 				kr->r.flags |= F_DYNAMIC;
1239 			if (rtm->rtm_flags & RTF_PROTO1)
1240 				kr->r.flags |= F_BGPD_INSERTED;
1241 			if (sa_in != NULL) {
1242 				if (sa_in->sin_len == 0)
1243 					break;
1244 				kr->r.prefixlen =
1245 				    mask2prefixlen(sa_in->sin_addr.s_addr);
1246 			} else if (rtm->rtm_flags & RTF_HOST)
1247 				kr->r.prefixlen = 32;
1248 			else
1249 				kr->r.prefixlen =
1250 				    prefixlen_classful(kr->r.prefix.s_addr);
1251 			break;
1252 		default:
1253 			free(kr);
1254 			continue;
1255 		}
1256 
1257 		kr->r.ifindex = rtm->rtm_index;
1258 		if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
1259 			switch (sa->sa_family) {
1260 			case AF_INET:
1261 				kr->r.nexthop.s_addr =
1262 				    ((struct sockaddr_in *)sa)->sin_addr.s_addr;
1263 				break;
1264 			case AF_LINK:
1265 				kr->r.flags |= F_CONNECTED;
1266 				break;
1267 			}
1268 
1269 		if ((sa_mpls = (struct sockaddr_mpls *)rti_info[RTAX_SRC])
1270 		    != NULL)
1271 			kr->r.local_label = sa_mpls->smpls_label;
1272 
1273 		if (rtm->rtm_flags & RTF_PROTO2)  {
1274 			send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r);
1275 			free(kr);
1276 		} else {
1277 			if ((label = (struct sockaddr_rtlabel *)
1278 			    rti_info[RTAX_LABEL]) != NULL) {
1279 				kr->r.rtlabel =
1280 				    rtlabel_name2id(label->sr_label);
1281 				kr->r.ext_tag =
1282 				    rtlabel_id2tag(kr->r.rtlabel);
1283 			}
1284 			kroute_insert(kr);
1285 		}
1286 
1287 	}
1288 	free(buf);
1289 	return (0);
1290 }
1291 
1292 int
1293 fetchifs(u_short ifindex)
1294 {
1295 	size_t			 len;
1296 	int			 mib[6];
1297 	char			*buf, *next, *lim;
1298 	struct rt_msghdr	*rtm;
1299 	struct if_msghdr	 ifm;
1300 	struct ifa_msghdr	*ifam;
1301 	struct kif		*kif = NULL;
1302 	struct sockaddr		*sa, *rti_info[RTAX_MAX];
1303 
1304 	mib[0] = CTL_NET;
1305 	mib[1] = AF_ROUTE;
1306 	mib[2] = 0;
1307 	mib[3] = AF_INET;
1308 	mib[4] = NET_RT_IFLIST;
1309 	mib[5] = ifindex;
1310 
1311 	if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) {
1312 		log_warn("sysctl");
1313 		return (-1);
1314 	}
1315 	if ((buf = malloc(len)) == NULL) {
1316 		log_warn("fetchif");
1317 		return (-1);
1318 	}
1319 	if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) {
1320 		log_warn("sysctl");
1321 		free(buf);
1322 		return (-1);
1323 	}
1324 
1325 	lim = buf + len;
1326 	for (next = buf; next < lim; next += rtm->rtm_msglen) {
1327 		rtm = (struct rt_msghdr *)next;
1328 		if (rtm->rtm_version != RTM_VERSION)
1329 			continue;
1330 		switch (rtm->rtm_type) {
1331 		case RTM_IFINFO:
1332 			bcopy(rtm, &ifm, sizeof ifm);
1333 			sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
1334 			get_rtaddrs(ifm.ifm_addrs, sa, rti_info);
1335 
1336 			if ((kif = kif_update(ifm.ifm_index,
1337 			    ifm.ifm_flags, &ifm.ifm_data,
1338 			    (struct sockaddr_dl *)rti_info[RTAX_IFP])) == NULL)
1339 				fatal("fetchifs");
1340 
1341 			kif->nh_reachable = (kif->flags & IFF_UP) &&
1342 			    (LINK_STATE_IS_UP(ifm.ifm_data.ifi_link_state) ||
1343 			    (ifm.ifm_data.ifi_link_state ==
1344 			    LINK_STATE_UNKNOWN &&
1345 			    ifm.ifm_data.ifi_type != IFT_CARP));
1346 			break;
1347 		case RTM_NEWADDR:
1348 			ifam = (struct ifa_msghdr *)rtm;
1349 			if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
1350 			    RTA_BRD)) == 0)
1351 				break;
1352 			sa = (struct sockaddr *)(ifam + 1);
1353 			get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
1354 
1355 			if_newaddr(ifam->ifam_index,
1356 			    (struct sockaddr_in *)rti_info[RTAX_IFA],
1357 			    (struct sockaddr_in *)rti_info[RTAX_NETMASK],
1358 			    (struct sockaddr_in *)rti_info[RTAX_BRD]);
1359 			break;
1360 		}
1361 	}
1362 	free(buf);
1363 	return (0);
1364 }
1365 
1366 int
1367 dispatch_rtmsg(void)
1368 {
1369 	char			 buf[RT_BUF_SIZE];
1370 	ssize_t			 n;
1371 	char			*next, *lim;
1372 	struct rt_msghdr	*rtm;
1373 	struct if_msghdr	 ifm;
1374 	struct ifa_msghdr	*ifam;
1375 	struct sockaddr		*sa, *rti_info[RTAX_MAX];
1376 	struct sockaddr_in	*sa_in;
1377 	struct sockaddr_rtlabel	*label;
1378 	struct kroute_node	*kr;
1379 	struct in_addr		 prefix, nexthop;
1380 	u_int8_t		 prefixlen;
1381 	int			 flags;
1382 	u_short			 ifindex = 0;
1383 
1384 	if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
1385 		log_warn("dispatch_rtmsg: read error");
1386 		return (-1);
1387 	}
1388 
1389 	if (n == 0) {
1390 		log_warnx("routing socket closed");
1391 		return (-1);
1392 	}
1393 
1394 	lim = buf + n;
1395 	for (next = buf; next < lim; next += rtm->rtm_msglen) {
1396 		rtm = (struct rt_msghdr *)next;
1397 		if (rtm->rtm_version != RTM_VERSION)
1398 			continue;
1399 
1400 		prefix.s_addr = 0;
1401 		prefixlen = 0;
1402 		flags = F_KERNEL;
1403 		nexthop.s_addr = 0;
1404 
1405 		if (rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE ||
1406 		    rtm->rtm_type == RTM_DELETE) {
1407 			sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
1408 			get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1409 
1410 			if (rtm->rtm_tableid != 0)
1411 				continue;
1412 
1413 			if (rtm->rtm_pid == kr_state.pid) /* caused by us */
1414 				continue;
1415 
1416 			if (rtm->rtm_errno)		/* failed attempts... */
1417 				continue;
1418 
1419 			if (rtm->rtm_flags & RTF_LLINFO)	/* arp cache */
1420 				continue;
1421 
1422 			switch (sa->sa_family) {
1423 			case AF_INET:
1424 				prefix.s_addr =
1425 				    ((struct sockaddr_in *)sa)->sin_addr.s_addr;
1426 				sa_in = (struct sockaddr_in *)
1427 				    rti_info[RTAX_NETMASK];
1428 				if (sa_in != NULL) {
1429 					if (sa_in->sin_len != 0)
1430 						prefixlen = mask2prefixlen(
1431 						    sa_in->sin_addr.s_addr);
1432 				} else if (rtm->rtm_flags & RTF_HOST)
1433 					prefixlen = 32;
1434 				else
1435 					prefixlen =
1436 					    prefixlen_classful(prefix.s_addr);
1437 				if (rtm->rtm_flags & RTF_STATIC)
1438 					flags |= F_STATIC;
1439 				if (rtm->rtm_flags & RTF_DYNAMIC)
1440 					flags |= F_DYNAMIC;
1441 				if (rtm->rtm_flags & RTF_PROTO1)
1442 					flags |= F_BGPD_INSERTED;
1443 				break;
1444 			default:
1445 				continue;
1446 			}
1447 
1448 			ifindex = rtm->rtm_index;
1449 			if ((sa = rti_info[RTAX_GATEWAY]) != NULL) {
1450 				switch (sa->sa_family) {
1451 				case AF_INET:
1452 					nexthop.s_addr = ((struct
1453 					    sockaddr_in *)sa)->sin_addr.s_addr;
1454 					break;
1455 				case AF_LINK:
1456 					flags |= F_CONNECTED;
1457 					break;
1458 				}
1459 			}
1460 		}
1461 
1462 		switch (rtm->rtm_type) {
1463 		case RTM_ADD:
1464 		case RTM_CHANGE:
1465 			if (nexthop.s_addr == 0 && !(flags & F_CONNECTED)) {
1466 				log_warnx("dispatch_rtmsg no nexthop for %s/%u",
1467 				    inet_ntoa(prefix), prefixlen);
1468 				continue;
1469 			}
1470 
1471 			if ((kr = kroute_find(prefix.s_addr, prefixlen)) !=
1472 			    NULL) {
1473 				/*
1474 				 * ldp route overridden by kernel. Preference
1475 				 * of the route is not checked because this is
1476 				 * forced -- most probably by a user.
1477 				 */
1478 				if (kr->r.flags & F_LDPD_INSERTED)
1479 					flags |= F_LDPD_INSERTED;
1480 				if (kr->r.flags & F_REDISTRIBUTED)
1481 					flags |= F_REDISTRIBUTED;
1482 				kr->r.nexthop.s_addr = nexthop.s_addr;
1483 				kr->r.flags = flags;
1484 				kr->r.ifindex = ifindex;
1485 
1486 				rtlabel_unref(kr->r.rtlabel);
1487 				kr->r.rtlabel = 0;
1488 				kr->r.ext_tag = 0;
1489 				if ((label = (struct sockaddr_rtlabel *)
1490 				    rti_info[RTAX_LABEL]) != NULL) {
1491 					kr->r.rtlabel =
1492 					    rtlabel_name2id(label->sr_label);
1493 					kr->r.ext_tag =
1494 					    rtlabel_id2tag(kr->r.rtlabel);
1495 				}
1496 
1497 				if (kif_validate(kr->r.ifindex))
1498 					kr->r.flags &= ~F_DOWN;
1499 				else
1500 					kr->r.flags |= F_DOWN;
1501 
1502 				/* just readd, the RDE will care */
1503 				kr_redistribute(kr);
1504 			} else {
1505 				if ((kr = calloc(1,
1506 				    sizeof(struct kroute_node))) == NULL) {
1507 					log_warn("dispatch_rtmsg");
1508 					return (-1);
1509 				}
1510 				kr->r.prefix.s_addr = prefix.s_addr;
1511 				kr->r.prefixlen = prefixlen;
1512 				kr->r.nexthop.s_addr = nexthop.s_addr;
1513 				kr->r.flags = flags;
1514 				kr->r.ifindex = ifindex;
1515 
1516 				if ((label = (struct sockaddr_rtlabel *)
1517 				    rti_info[RTAX_LABEL]) != NULL) {
1518 					kr->r.rtlabel =
1519 					    rtlabel_name2id(label->sr_label);
1520 					kr->r.ext_tag =
1521 					    rtlabel_id2tag(kr->r.rtlabel);
1522 				}
1523 
1524 				kroute_insert(kr);
1525 			}
1526 			break;
1527 		case RTM_DELETE:
1528 			if ((kr = kroute_find(prefix.s_addr, prefixlen)) ==
1529 			    NULL)
1530 				continue;
1531 			if (!(kr->r.flags & F_KERNEL))
1532 				continue;
1533 
1534 			if (kr->r.flags & F_LDPD_INSERTED) {
1535 				main_imsg_compose_lde(IMSG_NETWORK_DEL, 0,
1536 				    &kr->r, sizeof(struct kroute));
1537 
1538 				send_rtlabelmsg(kr_state.fd, RTM_DELETE,
1539 				    &kr->r, AF_MPLS);
1540 			}
1541 
1542 			if (kroute_remove(kr) == -1)
1543 				return (-1);
1544 			break;
1545 		case RTM_IFINFO:
1546 			memcpy(&ifm, next, sizeof(ifm));
1547 			if_change(ifm.ifm_index, ifm.ifm_flags,
1548 			    &ifm.ifm_data);
1549 			break;
1550 		case RTM_NEWADDR:
1551 			ifam = (struct ifa_msghdr *)rtm;
1552 			if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
1553 			    RTA_BRD)) == 0)
1554 				break;
1555 			sa = (struct sockaddr *)(ifam + 1);
1556 			get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
1557 
1558 			if_newaddr(ifam->ifam_index,
1559 			    (struct sockaddr_in *)rti_info[RTAX_IFA],
1560 			    (struct sockaddr_in *)rti_info[RTAX_NETMASK],
1561 			    (struct sockaddr_in *)rti_info[RTAX_BRD]);
1562 			break;
1563 		case RTM_IFANNOUNCE:
1564 			if_announce(next);
1565 			break;
1566 		default:
1567 			/* ignore for now */
1568 			break;
1569 		}
1570 	}
1571 	return (0);
1572 }
1573