xref: /openbsd-src/usr.sbin/bgpd/kroute.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: kroute.c,v 1.209 2016/04/08 12:27:05 phessler Exp $ */
2 
3 /*
4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/sysctl.h>
22 #include <sys/tree.h>
23 #include <sys/uio.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <net/if.h>
27 #include <net/if_dl.h>
28 #include <net/route.h>
29 #include <netmpls/mpls.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 #include "bgpd.h"
39 
40 struct ktable		**krt;
41 u_int			  krt_size;
42 
43 struct {
44 	u_int32_t		rtseq;
45 	pid_t			pid;
46 	int			fd;
47 } kr_state;
48 
49 struct kroute_node {
50 	RB_ENTRY(kroute_node)	 entry;
51 	struct kroute		 r;
52 	struct kroute_node	*next;
53 };
54 
55 struct kroute6_node {
56 	RB_ENTRY(kroute6_node)	 entry;
57 	struct kroute6		 r;
58 	struct kroute6_node	*next;
59 };
60 
61 struct knexthop_node {
62 	RB_ENTRY(knexthop_node)	 entry;
63 	struct bgpd_addr	 nexthop;
64 	void			*kroute;
65 };
66 
67 struct kif_kr {
68 	LIST_ENTRY(kif_kr)	 entry;
69 	struct kroute_node	*kr;
70 };
71 
72 struct kif_kr6 {
73 	LIST_ENTRY(kif_kr6)	 entry;
74 	struct kroute6_node	*kr;
75 };
76 
77 LIST_HEAD(kif_kr_head, kif_kr);
78 LIST_HEAD(kif_kr6_head, kif_kr6);
79 
80 struct kif_node {
81 	RB_ENTRY(kif_node)	 entry;
82 	struct kif		 k;
83 	struct kif_kr_head	 kroute_l;
84 	struct kif_kr6_head	 kroute6_l;
85 };
86 
87 int	ktable_new(u_int, u_int, char *, char *, int, u_int8_t);
88 void	ktable_free(u_int, u_int8_t);
89 void	ktable_destroy(struct ktable *, u_int8_t);
90 struct ktable	*ktable_get(u_int);
91 
92 int	kr4_change(struct ktable *, struct kroute_full *, u_int8_t);
93 int	kr6_change(struct ktable *, struct kroute_full *, u_int8_t);
94 int	krVPN4_change(struct ktable *, struct kroute_full *, u_int8_t);
95 int	kr4_delete(struct ktable *, struct kroute_full *, u_int8_t);
96 int	kr6_delete(struct ktable *, struct kroute_full *, u_int8_t);
97 int	krVPN4_delete(struct ktable *, struct kroute_full *, u_int8_t);
98 void	kr_net_delete(struct network *);
99 struct network *kr_net_match(struct ktable *, struct kroute *);
100 struct network *kr_net_match6(struct ktable *, struct kroute6 *);
101 struct network *kr_net_find(struct ktable *, struct network *);
102 int	kr_redistribute(int, struct ktable *, struct kroute *);
103 int	kr_redistribute6(int, struct ktable *, struct kroute6 *);
104 struct kroute_full *kr_tofull(struct kroute *);
105 struct kroute_full *kr6_tofull(struct kroute6 *);
106 int	kroute_compare(struct kroute_node *, struct kroute_node *);
107 int	kroute6_compare(struct kroute6_node *, struct kroute6_node *);
108 int	knexthop_compare(struct knexthop_node *, struct knexthop_node *);
109 int	kif_compare(struct kif_node *, struct kif_node *);
110 void	kr_fib_update_prio(u_int, u_int8_t);
111 
112 struct kroute_node	*kroute_find(struct ktable *, in_addr_t, u_int8_t,
113 			    u_int8_t);
114 struct kroute_node	*kroute_matchgw(struct kroute_node *,
115 			    struct sockaddr_in *);
116 int			 kroute_insert(struct ktable *, struct kroute_node *);
117 int			 kroute_remove(struct ktable *, struct kroute_node *);
118 void			 kroute_clear(struct ktable *);
119 
120 struct kroute6_node	*kroute6_find(struct ktable *, const struct in6_addr *,
121 			    u_int8_t, u_int8_t);
122 struct kroute6_node	*kroute6_matchgw(struct kroute6_node *,
123 			    struct sockaddr_in6 *);
124 int			 kroute6_insert(struct ktable *, struct kroute6_node *);
125 int			 kroute6_remove(struct ktable *, struct kroute6_node *);
126 void			 kroute6_clear(struct ktable *);
127 
128 struct knexthop_node	*knexthop_find(struct ktable *, struct bgpd_addr *);
129 int			 knexthop_insert(struct ktable *,
130 			    struct knexthop_node *);
131 int			 knexthop_remove(struct ktable *,
132 			    struct knexthop_node *);
133 void			 knexthop_clear(struct ktable *);
134 
135 struct kif_node		*kif_find(int);
136 int			 kif_insert(struct kif_node *);
137 int			 kif_remove(struct kif_node *);
138 void			 kif_clear(void);
139 
140 int			 kif_kr_insert(struct kroute_node *);
141 int			 kif_kr_remove(struct kroute_node *);
142 
143 int			 kif_kr6_insert(struct kroute6_node *);
144 int			 kif_kr6_remove(struct kroute6_node *);
145 
146 int			 kif_validate(struct kif *);
147 int			 kroute_validate(struct kroute *);
148 int			 kroute6_validate(struct kroute6 *);
149 void			 knexthop_validate(struct ktable *,
150 			    struct knexthop_node *);
151 void			 knexthop_track(struct ktable *, void *);
152 void			 knexthop_send_update(struct knexthop_node *);
153 struct kroute_node	*kroute_match(struct ktable *, in_addr_t, int);
154 struct kroute6_node	*kroute6_match(struct ktable *, struct in6_addr *, int);
155 void			 kroute_detach_nexthop(struct ktable *,
156 			    struct knexthop_node *);
157 
158 int		protect_lo(struct ktable *);
159 u_int8_t	prefixlen_classful(in_addr_t);
160 u_int8_t	mask2prefixlen(in_addr_t);
161 u_int8_t	mask2prefixlen6(struct sockaddr_in6 *);
162 void		get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
163 void		if_change(u_short, int, struct if_data *);
164 void		if_announce(void *);
165 
166 int		send_rtmsg(int, int, struct ktable *, struct kroute *,
167 		    u_int8_t);
168 int		send_rt6msg(int, int, struct ktable *, struct kroute6 *,
169 		    u_int8_t);
170 int		dispatch_rtmsg(void);
171 int		fetchtable(struct ktable *, u_int8_t);
172 int		fetchifs(int);
173 int		dispatch_rtmsg_addr(struct rt_msghdr *,
174 		    struct sockaddr *[RTAX_MAX], struct ktable *);
175 
176 RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare)
177 RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare)
178 
179 RB_PROTOTYPE(kroute6_tree, kroute6_node, entry, kroute6_compare)
180 RB_GENERATE(kroute6_tree, kroute6_node, entry, kroute6_compare)
181 
182 RB_PROTOTYPE(knexthop_tree, knexthop_node, entry, knexthop_compare)
183 RB_GENERATE(knexthop_tree, knexthop_node, entry, knexthop_compare)
184 
185 RB_HEAD(kif_tree, kif_node)		kit;
186 RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare)
187 RB_GENERATE(kif_tree, kif_node, entry, kif_compare)
188 
189 #define KT2KNT(x)	(&(ktable_get((x)->nhtableid)->knt))
190 
191 /*
192  * exported functions
193  */
194 
195 int
196 kr_init(void)
197 {
198 	int		opt = 0, rcvbuf, default_rcvbuf;
199 	unsigned int	tid = RTABLE_ANY;
200 	socklen_t	optlen;
201 
202 	if ((kr_state.fd = socket(AF_ROUTE,
203 	    SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) {
204 		log_warn("kr_init: socket");
205 		return (-1);
206 	}
207 
208 	/* not interested in my own messages */
209 	if (setsockopt(kr_state.fd, SOL_SOCKET, SO_USELOOPBACK,
210 	    &opt, sizeof(opt)) == -1)
211 		log_warn("kr_init: setsockopt");	/* not fatal */
212 
213 	/* grow receive buffer, don't wanna miss messages */
214 	optlen = sizeof(default_rcvbuf);
215 	if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF,
216 	    &default_rcvbuf, &optlen) == -1)
217 		log_warn("kr_init getsockopt SOL_SOCKET SO_RCVBUF");
218 	else
219 		for (rcvbuf = MAX_RTSOCK_BUF;
220 		    rcvbuf > default_rcvbuf &&
221 		    setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF,
222 		    &rcvbuf, sizeof(rcvbuf)) == -1 && errno == ENOBUFS;
223 		    rcvbuf /= 2)
224 			;	/* nothing */
225 
226 	if (setsockopt(kr_state.fd, AF_ROUTE, ROUTE_TABLEFILTER, &tid,
227 	    sizeof(tid)) == -1) {
228 		log_warn("kr_init: setsockopt AF_ROUTE ROUTE_TABLEFILTER");
229 		return (-1);
230 	}
231 
232 	kr_state.pid = getpid();
233 	kr_state.rtseq = 1;
234 
235 	RB_INIT(&kit);
236 
237 	if (fetchifs(0) == -1)
238 		return (-1);
239 
240 	return (kr_state.fd);
241 }
242 
243 int
244 ktable_new(u_int rtableid, u_int rdomid, char *name, char *ifname, int fs,
245     u_int8_t fib_prio)
246 {
247 	struct ktable	**xkrt;
248 	struct ktable	 *kt;
249 	size_t		  oldsize;
250 
251 	/* resize index table if needed */
252 	if (rtableid >= krt_size) {
253 		oldsize = sizeof(struct ktable *) * krt_size;
254 		if ((xkrt = reallocarray(krt, rtableid + 1,
255 		    sizeof(struct ktable *))) == NULL) {
256 			log_warn("ktable_new");
257 			return (-1);
258 		}
259 		krt = xkrt;
260 		krt_size = rtableid + 1;
261 		bzero((char *)krt + oldsize,
262 		    krt_size * sizeof(struct ktable *) - oldsize);
263 	}
264 
265 	if (krt[rtableid])
266 		fatalx("ktable_new: table already exists.");
267 
268 	/* allocate new element */
269 	kt = krt[rtableid] = calloc(1, sizeof(struct ktable));
270 	if (kt == NULL) {
271 		log_warn("ktable_new");
272 		return (-1);
273 	}
274 
275 	/* initialize structure ... */
276 	strlcpy(kt->descr, name, sizeof(kt->descr));
277 	RB_INIT(&kt->krt);
278 	RB_INIT(&kt->krt6);
279 	RB_INIT(&kt->knt);
280 	TAILQ_INIT(&kt->krn);
281 	kt->fib_conf = kt->fib_sync = fs;
282 	kt->rtableid = rtableid;
283 	kt->nhtableid = rdomid;
284 	/* bump refcount of rdomain table for the nexthop lookups */
285 	ktable_get(kt->nhtableid)->nhrefcnt++;
286 	if (ifname) {
287 		strlcpy(kt->ifmpe, ifname, IFNAMSIZ);
288 		kt->ifindex = if_nametoindex(ifname);
289 	}
290 
291 	/* ... and load it */
292 	if (fetchtable(kt, fib_prio) == -1)
293 		return (-1);
294 	if (protect_lo(kt) == -1)
295 		return (-1);
296 
297 	/* everything is up and running */
298 	kt->state = RECONF_REINIT;
299 	log_debug("new ktable %s for rtableid %d", name, rtableid);
300 	return (0);
301 }
302 
303 void
304 ktable_free(u_int rtableid, u_int8_t fib_prio)
305 {
306 	struct ktable	*kt, *nkt;
307 
308 	if ((kt = ktable_get(rtableid)) == NULL)
309 		return;
310 
311 	/* decouple from kernel, no new routes will be entered from here */
312 	kr_fib_decouple(kt->rtableid, fib_prio);
313 
314 	/* first unhook from the nexthop table */
315 	nkt = ktable_get(kt->nhtableid);
316 	nkt->nhrefcnt--;
317 
318 	/*
319 	 * Evil little details:
320 	 *   If kt->nhrefcnt > 0 then kt == nkt and nothing needs to be done.
321 	 *   If kt != nkt then kt->nhrefcnt must be 0 and kt must be killed.
322 	 *   If nkt is no longer referenced it must be killed (possible double
323 	 *   free so check that kt != nkt).
324 	 */
325 	if (kt != nkt && nkt->nhrefcnt <= 0)
326 		ktable_destroy(nkt, fib_prio);
327 	if (kt->nhrefcnt <= 0)
328 		ktable_destroy(kt, fib_prio);
329 }
330 
331 void
332 ktable_destroy(struct ktable *kt, u_int8_t fib_prio)
333 {
334 	/* decouple just to be sure, does not hurt */
335 	kr_fib_decouple(kt->rtableid, fib_prio);
336 
337 	log_debug("freeing ktable %s rtableid %u", kt->descr, kt->rtableid);
338 	knexthop_clear(kt);
339 	kroute_clear(kt);
340 	kroute6_clear(kt);
341 
342 	krt[kt->rtableid] = NULL;
343 	free(kt);
344 }
345 
346 struct ktable *
347 ktable_get(u_int rtableid)
348 {
349 	if (rtableid >= krt_size)
350 		return (NULL);
351 	return (krt[rtableid]);
352 }
353 
354 int
355 ktable_update(u_int rtableid, char *name, char *ifname, int flags, u_int8_t
356     fib_prio)
357 {
358 	struct ktable	*kt, *rkt;
359 	u_int		 rdomid;
360 
361 	if (!ktable_exists(rtableid, &rdomid))
362 		fatalx("King Bula lost a table");	/* may not happen */
363 
364 	if (rdomid != rtableid || flags & F_RIB_NOFIB) {
365 		rkt = ktable_get(rdomid);
366 		if (rkt == NULL) {
367 			char buf[32];
368 			snprintf(buf, sizeof(buf), "rdomain_%d", rdomid);
369 			if (ktable_new(rdomid, rdomid, buf, NULL, 0, fib_prio))
370 				return (-1);
371 		} else {
372 			/* there is no need for full fib synchronisation if
373 			 * the table is only used for nexthop lookups.
374 			 */
375 			if (rkt->state == RECONF_DELETE) {
376 				rkt->fib_conf = 0;
377 				rkt->state = RECONF_KEEP;
378 			}
379 		}
380 	}
381 
382 	if (flags & (F_RIB_NOEVALUATE | F_RIB_NOFIB))
383 		/* only rdomain table must exist */
384 		return (0);
385 
386 	kt = ktable_get(rtableid);
387 	if (kt == NULL) {
388 		if (ktable_new(rtableid, rdomid, name, ifname,
389 		    !(flags & F_RIB_NOFIBSYNC), fib_prio))
390 			return (-1);
391 	} else {
392 		/* fib sync has higher preference then no sync */
393 		if (kt->state == RECONF_DELETE) {
394 			kt->fib_conf = !(flags & F_RIB_NOFIBSYNC);
395 			kt->state = RECONF_KEEP;
396 		} else if (!kt->fib_conf)
397 			kt->fib_conf = !(flags & F_RIB_NOFIBSYNC);
398 
399 		strlcpy(kt->descr, name, sizeof(kt->descr));
400 	}
401 	return (0);
402 }
403 
404 void
405 ktable_preload(void)
406 {
407 	struct ktable	*kt;
408 	u_int		 i;
409 
410 	for (i = 0; i < krt_size; i++) {
411 		if ((kt = ktable_get(i)) == NULL)
412 			continue;
413 		kt->state = RECONF_DELETE;
414 	}
415 }
416 
417 void
418 ktable_postload(u_int8_t fib_prio)
419 {
420 	struct ktable	*kt;
421 	u_int		 i;
422 
423 	for (i = krt_size; i > 0; i--) {
424 		if ((kt = ktable_get(i - 1)) == NULL)
425 			continue;
426 		if (kt->state == RECONF_DELETE)
427 			ktable_free(i - 1, fib_prio);
428 		else if (kt->state == RECONF_REINIT)
429 			kt->fib_sync = kt->fib_conf;
430 	}
431 }
432 
433 int
434 ktable_exists(u_int rtableid, u_int *rdomid)
435 {
436 	size_t			 len;
437 	struct rt_tableinfo	 info;
438 	int			 mib[6];
439 
440 	mib[0] = CTL_NET;
441 	mib[1] = PF_ROUTE;
442 	mib[2] = 0;
443 	mib[3] = 0;
444 	mib[4] = NET_RT_TABLE;
445 	mib[5] = rtableid;
446 
447 	len = sizeof(info);
448 	if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) {
449 		if (errno == ENOENT)
450 			/* table nonexistent */
451 			return (0);
452 		log_warn("sysctl");
453 		/* must return 0 so that the table is considered non-existent */
454 		return (0);
455 	}
456 	if (rdomid)
457 		*rdomid = info.rti_domainid;
458 	return (1);
459 }
460 
461 int
462 kr_change(u_int rtableid, struct kroute_full *kl, u_int8_t fib_prio)
463 {
464 	struct ktable		*kt;
465 
466 	if ((kt = ktable_get(rtableid)) == NULL)
467 		/* too noisy during reloads, just ignore */
468 		return (0);
469 	switch (kl->prefix.aid) {
470 	case AID_INET:
471 		return (kr4_change(kt, kl, fib_prio));
472 	case AID_INET6:
473 		return (kr6_change(kt, kl, fib_prio));
474 	case AID_VPN_IPv4:
475 		return (krVPN4_change(kt, kl, fib_prio));
476 	}
477 	log_warnx("kr_change: not handled AID");
478 	return (-1);
479 }
480 
481 int
482 kr4_change(struct ktable *kt, struct kroute_full *kl, u_int8_t fib_prio)
483 {
484 	struct kroute_node	*kr;
485 	int			 action = RTM_ADD;
486 	u_int16_t		 labelid;
487 
488 	if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen,
489 	    fib_prio)) != NULL)
490 		action = RTM_CHANGE;
491 
492 	/* for blackhole and reject routes nexthop needs to be 127.0.0.1 */
493 	if (kl->flags & (F_BLACKHOLE|F_REJECT))
494 		kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK);
495 	/* nexthop within 127/8 -> ignore silently */
496 	else if ((kl->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) ==
497 	    htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
498 		return (0);
499 
500 	labelid = rtlabel_name2id(kl->label);
501 
502 	if (action == RTM_ADD) {
503 		if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
504 			log_warn("kr_change");
505 			return (-1);
506 		}
507 		kr->r.prefix.s_addr = kl->prefix.v4.s_addr;
508 		kr->r.prefixlen = kl->prefixlen;
509 		kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
510 		kr->r.flags = kl->flags | F_BGPD_INSERTED;
511 		kr->r.priority = fib_prio;
512 		kr->r.labelid = labelid;
513 
514 		if (kroute_insert(kt, kr) == -1) {
515 			free(kr);
516 			return (-1);
517 		}
518 	} else {
519 		kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
520 		rtlabel_unref(kr->r.labelid);
521 		kr->r.labelid = labelid;
522 		if (kl->flags & F_BLACKHOLE)
523 			kr->r.flags |= F_BLACKHOLE;
524 		else
525 			kr->r.flags &= ~F_BLACKHOLE;
526 		if (kl->flags & F_REJECT)
527 			kr->r.flags |= F_REJECT;
528 		else
529 			kr->r.flags &= ~F_REJECT;
530 	}
531 
532 	if (send_rtmsg(kr_state.fd, action, kt, &kr->r, fib_prio) == -1)
533 		return (-1);
534 
535 	return (0);
536 }
537 
538 int
539 kr6_change(struct ktable *kt, struct kroute_full *kl, u_int8_t fib_prio)
540 {
541 	struct kroute6_node	*kr6;
542 	struct in6_addr		 lo6 = IN6ADDR_LOOPBACK_INIT;
543 	int			 action = RTM_ADD;
544 	u_int16_t		 labelid;
545 
546 	if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, fib_prio)) !=
547 	    NULL)
548 		action = RTM_CHANGE;
549 
550 	/* for blackhole and reject routes nexthop needs to be ::1 */
551 	if (kl->flags & (F_BLACKHOLE|F_REJECT))
552 		bcopy(&lo6, &kl->nexthop.v6, sizeof(kl->nexthop.v6));
553 	/* nexthop to loopback -> ignore silently */
554 	else if (IN6_IS_ADDR_LOOPBACK(&kl->nexthop.v6))
555 		return (0);
556 
557 	labelid = rtlabel_name2id(kl->label);
558 
559 	if (action == RTM_ADD) {
560 		if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) {
561 			log_warn("kr_change");
562 			return (-1);
563 		}
564 		memcpy(&kr6->r.prefix, &kl->prefix.v6, sizeof(struct in6_addr));
565 		kr6->r.prefixlen = kl->prefixlen;
566 		memcpy(&kr6->r.nexthop, &kl->nexthop.v6,
567 		    sizeof(struct in6_addr));
568 		kr6->r.flags = kl->flags | F_BGPD_INSERTED;
569 		kr6->r.priority = fib_prio;
570 		kr6->r.labelid = labelid;
571 
572 		if (kroute6_insert(kt, kr6) == -1) {
573 			free(kr6);
574 			return (-1);
575 		}
576 	} else {
577 		memcpy(&kr6->r.nexthop, &kl->nexthop.v6,
578 		    sizeof(struct in6_addr));
579 		rtlabel_unref(kr6->r.labelid);
580 		kr6->r.labelid = labelid;
581 		if (kl->flags & F_BLACKHOLE)
582 			kr6->r.flags |= F_BLACKHOLE;
583 		else
584 			kr6->r.flags &= ~F_BLACKHOLE;
585 		if (kl->flags & F_REJECT)
586 			kr6->r.flags |= F_REJECT;
587 		else
588 			kr6->r.flags &= ~F_REJECT;
589 	}
590 
591 	if (send_rt6msg(kr_state.fd, action, kt, &kr6->r, fib_prio) == -1)
592 		return (-1);
593 
594 	return (0);
595 }
596 
597 int
598 krVPN4_change(struct ktable *kt, struct kroute_full *kl, u_int8_t fib_prio)
599 {
600 	struct kroute_node	*kr;
601 	int			 action = RTM_ADD;
602 	u_int32_t		 mplslabel = 0;
603 	u_int16_t		 labelid;
604 
605 	if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen,
606 	    fib_prio)) != NULL)
607 		action = RTM_CHANGE;
608 
609 	/* nexthop within 127/8 -> ignore silently */
610 	if ((kl->nexthop.v4.s_addr & htonl(IN_CLASSA_NET)) ==
611 	    htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
612 		return (0);
613 
614 	/* only single MPLS label are supported for now */
615 	if (kl->prefix.vpn4.labellen != 3) {
616 		log_warnx("krVPN4_change: %s/%u has not a single label",
617 		    log_addr(&kl->prefix), kl->prefixlen);
618 		return (0);
619 	}
620 	mplslabel = (kl->prefix.vpn4.labelstack[0] << 24) |
621 	    (kl->prefix.vpn4.labelstack[1] << 16) |
622 	    (kl->prefix.vpn4.labelstack[2] << 8);
623 	mplslabel = htonl(mplslabel);
624 
625 	labelid = rtlabel_name2id(kl->label);
626 
627 	/* for blackhole and reject routes nexthop needs to be 127.0.0.1 */
628 	if (kl->flags & (F_BLACKHOLE|F_REJECT))
629 		kl->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK);
630 
631 	if (action == RTM_ADD) {
632 		if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
633 			log_warn("krVPN4_change");
634 			return (-1);
635 		}
636 		kr->r.prefix.s_addr = kl->prefix.vpn4.addr.s_addr;
637 		kr->r.prefixlen = kl->prefixlen;
638 		kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
639 		kr->r.flags = kl->flags | F_BGPD_INSERTED | F_MPLS;
640 		kr->r.priority = fib_prio;
641 		kr->r.labelid = labelid;
642 		kr->r.mplslabel = mplslabel;
643 
644 		if (kroute_insert(kt, kr) == -1) {
645 			free(kr);
646 			return (-1);
647 		}
648 	} else {
649 		kr->r.mplslabel = mplslabel;
650 		kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
651 		rtlabel_unref(kr->r.labelid);
652 		kr->r.labelid = labelid;
653 		if (kl->flags & F_BLACKHOLE)
654 			kr->r.flags |= F_BLACKHOLE;
655 		else
656 			kr->r.flags &= ~F_BLACKHOLE;
657 		if (kl->flags & F_REJECT)
658 			kr->r.flags |= F_REJECT;
659 		else
660 			kr->r.flags &= ~F_REJECT;
661 	}
662 
663 	if (send_rtmsg(kr_state.fd, action, kt, &kr->r, fib_prio) == -1)
664 		return (-1);
665 
666 	return (0);
667 }
668 
669 int
670 kr_delete(u_int rtableid, struct kroute_full *kl, u_int8_t fib_prio)
671 {
672 	struct ktable		*kt;
673 
674 	if ((kt = ktable_get(rtableid)) == NULL)
675 		/* too noisy during reloads, just ignore */
676 		return (0);
677 
678 	switch (kl->prefix.aid) {
679 	case AID_INET:
680 		return (kr4_delete(kt, kl, fib_prio));
681 	case AID_INET6:
682 		return (kr6_delete(kt, kl, fib_prio));
683 	case AID_VPN_IPv4:
684 		return (krVPN4_delete(kt, kl, fib_prio));
685 	}
686 	log_warnx("%s: not handled AID", __func__);
687 	return (-1);
688 }
689 
690 int
691 kr4_delete(struct ktable *kt, struct kroute_full *kl, u_int8_t fib_prio)
692 {
693 	struct kroute_node	*kr;
694 
695 	if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen,
696 	    fib_prio)) == NULL)
697 		return (0);
698 
699 	if (!(kr->r.flags & F_BGPD_INSERTED))
700 		return (0);
701 
702 	if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r, fib_prio) == -1)
703 		return (-1);
704 
705 	rtlabel_unref(kr->r.labelid);
706 
707 	if (kroute_remove(kt, kr) == -1)
708 		return (-1);
709 
710 	return (0);
711 }
712 
713 int
714 kr6_delete(struct ktable *kt, struct kroute_full *kl, u_int8_t fib_prio)
715 {
716 	struct kroute6_node	*kr6;
717 
718 	if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, fib_prio)) ==
719 	    NULL)
720 		return (0);
721 
722 	if (!(kr6->r.flags & F_BGPD_INSERTED))
723 		return (0);
724 
725 	if (send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r, fib_prio) == -1)
726 		return (-1);
727 
728 	rtlabel_unref(kr6->r.labelid);
729 
730 	if (kroute6_remove(kt, kr6) == -1)
731 		return (-1);
732 
733 	return (0);
734 }
735 
736 int
737 krVPN4_delete(struct ktable *kt, struct kroute_full *kl, u_int8_t fib_prio)
738 {
739 	struct kroute_node	*kr;
740 
741 	if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen,
742 	    fib_prio)) == NULL)
743 		return (0);
744 
745 	if (!(kr->r.flags & F_BGPD_INSERTED))
746 		return (0);
747 
748 	if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r, fib_prio) == -1)
749 		return (-1);
750 
751 	rtlabel_unref(kr->r.labelid);
752 
753 	if (kroute_remove(kt, kr) == -1)
754 		return (-1);
755 
756 	return (0);
757 }
758 
759 void
760 kr_shutdown(u_int8_t fib_prio)
761 {
762 	u_int	i;
763 
764 	for (i = krt_size; i > 0; i--)
765 		ktable_free(i - 1, fib_prio);
766 	kif_clear();
767 }
768 
769 void
770 kr_fib_couple(u_int rtableid, u_int8_t fib_prio)
771 {
772 	struct ktable		*kt;
773 	struct kroute_node	*kr;
774 	struct kroute6_node	*kr6;
775 
776 	if ((kt = ktable_get(rtableid)) == NULL)  /* table does not exist */
777 		return;
778 
779 	if (kt->fib_sync)	/* already coupled */
780 		return;
781 
782 	kt->fib_sync = 1;
783 
784 	RB_FOREACH(kr, kroute_tree, &kt->krt)
785 		if ((kr->r.flags & F_BGPD_INSERTED))
786 			send_rtmsg(kr_state.fd, RTM_ADD, kt, &kr->r, fib_prio);
787 	RB_FOREACH(kr6, kroute6_tree, &kt->krt6)
788 		if ((kr6->r.flags & F_BGPD_INSERTED))
789 			send_rt6msg(kr_state.fd, RTM_ADD, kt, &kr6->r,
790 			    fib_prio);
791 
792 	log_info("kernel routing table %u (%s) coupled", kt->rtableid,
793 	    kt->descr);
794 }
795 
796 void
797 kr_fib_couple_all(u_int8_t fib_prio)
798 {
799 	u_int	 i;
800 
801 	for (i = krt_size; i > 0; i--)
802 		kr_fib_couple(i - 1, fib_prio);
803 }
804 
805 void
806 kr_fib_decouple(u_int rtableid, u_int8_t fib_prio)
807 {
808 	struct ktable		*kt;
809 	struct kroute_node	*kr;
810 	struct kroute6_node	*kr6;
811 
812 	if ((kt = ktable_get(rtableid)) == NULL)  /* table does not exist */
813 		return;
814 
815 	if (!kt->fib_sync)	/* already decoupled */
816 		return;
817 
818 	RB_FOREACH(kr, kroute_tree, &kt->krt)
819 		if ((kr->r.flags & F_BGPD_INSERTED))
820 			send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r,
821 			    fib_prio);
822 	RB_FOREACH(kr6, kroute6_tree, &kt->krt6)
823 		if ((kr6->r.flags & F_BGPD_INSERTED))
824 			send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r,
825 			    fib_prio);
826 
827 	kt->fib_sync = 0;
828 
829 	log_info("kernel routing table %u (%s) decoupled", kt->rtableid,
830 	    kt->descr);
831 }
832 
833 void
834 kr_fib_decouple_all(u_int8_t fib_prio)
835 {
836 	u_int	 i;
837 
838 	for (i = krt_size; i > 0; i--)
839 		kr_fib_decouple(i - 1, fib_prio);
840 }
841 
842 void
843 kr_fib_update_prio(u_int rtableid, u_int8_t fib_prio)
844 {
845 	struct ktable		*kt;
846 	struct kroute_node	*kr;
847 	struct kroute6_node	*kr6;
848 
849 	if ((kt = ktable_get(rtableid)) == NULL)  /* table does not exist */
850 		return;
851 
852 	RB_FOREACH(kr, kroute_tree, &kt->krt)
853 		if ((kr->r.flags & F_BGPD_INSERTED))
854 			kr->r.priority = fib_prio;
855 
856 	RB_FOREACH(kr6, kroute6_tree, &kt->krt6)
857 		if ((kr6->r.flags & F_BGPD_INSERTED))
858 			kr6->r.priority = fib_prio;
859 }
860 
861 void
862 kr_fib_update_prio_all(u_int8_t fib_prio)
863 {
864 	u_int	 i;
865 
866 	for (i = krt_size; i > 0; i--)
867 		kr_fib_update_prio(i - 1, fib_prio);
868 }
869 
870 int
871 kr_dispatch_msg(void)
872 {
873 	return (dispatch_rtmsg());
874 }
875 
876 int
877 kr_nexthop_add(u_int rtableid, struct bgpd_addr *addr)
878 {
879 	struct ktable		*kt;
880 	struct knexthop_node	*h;
881 
882 	if ((kt = ktable_get(rtableid)) == NULL) {
883 		log_warnx("kr_nexthop_add: non-existent rtableid %d", rtableid);
884 		return (0);
885 	}
886 	if ((h = knexthop_find(kt, addr)) != NULL) {
887 		/* should not happen... this is actually an error path */
888 		knexthop_send_update(h);
889 	} else {
890 		if ((h = calloc(1, sizeof(struct knexthop_node))) == NULL) {
891 			log_warn("kr_nexthop_add");
892 			return (-1);
893 		}
894 		memcpy(&h->nexthop, addr, sizeof(h->nexthop));
895 
896 		if (knexthop_insert(kt, h) == -1)
897 			return (-1);
898 	}
899 
900 	return (0);
901 }
902 
903 void
904 kr_nexthop_delete(u_int rtableid, struct bgpd_addr *addr)
905 {
906 	struct ktable		*kt;
907 	struct knexthop_node	*kn;
908 
909 	if ((kt = ktable_get(rtableid)) == NULL) {
910 		log_warnx("kr_nexthop_delete: non-existent rtableid %d",
911 		    rtableid);
912 		return;
913 	}
914 	if ((kn = knexthop_find(kt, addr)) == NULL)
915 		return;
916 
917 	knexthop_remove(kt, kn);
918 }
919 
920 void
921 kr_show_route(struct imsg *imsg)
922 {
923 	struct ktable		*kt;
924 	struct kroute_node	*kr, *kn;
925 	struct kroute6_node	*kr6, *kn6;
926 	struct bgpd_addr	*addr;
927 	int			 flags;
928 	sa_family_t		 af;
929 	struct ctl_show_nexthop	 snh;
930 	struct knexthop_node	*h;
931 	struct kif_node		*kif;
932 	u_int			 i;
933 	u_short			 ifindex = 0;
934 
935 	switch (imsg->hdr.type) {
936 	case IMSG_CTL_KROUTE:
937 		if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(flags) +
938 		    sizeof(af)) {
939 			log_warnx("kr_show_route: wrong imsg len");
940 			break;
941 		}
942 		kt = ktable_get(imsg->hdr.peerid);
943 		if (kt == NULL) {
944 			log_warnx("kr_show_route: table %u does not exist",
945 			    imsg->hdr.peerid);
946 			break;
947 		}
948 		memcpy(&flags, imsg->data, sizeof(flags));
949 		memcpy(&af, (char *)imsg->data + sizeof(flags), sizeof(af));
950 		if (!af || af == AF_INET)
951 			RB_FOREACH(kr, kroute_tree, &kt->krt) {
952 				if (flags && (kr->r.flags & flags) == 0)
953 					continue;
954 				kn = kr;
955 				do {
956 					send_imsg_session(IMSG_CTL_KROUTE,
957 					    imsg->hdr.pid, kr_tofull(&kn->r),
958 					    sizeof(struct kroute_full));
959 				} while ((kn = kn->next) != NULL);
960 			}
961 		if (!af || af == AF_INET6)
962 			RB_FOREACH(kr6, kroute6_tree, &kt->krt6) {
963 				if (flags && (kr6->r.flags & flags) == 0)
964 					continue;
965 				kn6 = kr6;
966 				do {
967 					send_imsg_session(IMSG_CTL_KROUTE,
968 					    imsg->hdr.pid, kr6_tofull(&kn6->r),
969 					    sizeof(struct kroute_full));
970 				} while ((kn6 = kn6->next) != NULL);
971 			}
972 		break;
973 	case IMSG_CTL_KROUTE_ADDR:
974 		if (imsg->hdr.len != IMSG_HEADER_SIZE +
975 		    sizeof(struct bgpd_addr)) {
976 			log_warnx("kr_show_route: wrong imsg len");
977 			break;
978 		}
979 		kt = ktable_get(imsg->hdr.peerid);
980 		if (kt == NULL) {
981 			log_warnx("kr_show_route: table %u does not exist",
982 			    imsg->hdr.peerid);
983 			break;
984 		}
985 		addr = imsg->data;
986 		kr = NULL;
987 		switch (addr->aid) {
988 		case AID_INET:
989 			kr = kroute_match(kt, addr->v4.s_addr, 1);
990 			if (kr != NULL)
991 				send_imsg_session(IMSG_CTL_KROUTE,
992 				    imsg->hdr.pid, kr_tofull(&kr->r),
993 				    sizeof(struct kroute_full));
994 			break;
995 		case AID_INET6:
996 			kr6 = kroute6_match(kt, &addr->v6, 1);
997 			if (kr6 != NULL)
998 				send_imsg_session(IMSG_CTL_KROUTE,
999 				    imsg->hdr.pid, kr6_tofull(&kr6->r),
1000 				    sizeof(struct kroute_full));
1001 			break;
1002 		}
1003 		break;
1004 	case IMSG_CTL_SHOW_NEXTHOP:
1005 		kt = ktable_get(imsg->hdr.peerid);
1006 		if (kt == NULL) {
1007 			log_warnx("kr_show_route: table %u does not exist",
1008 			    imsg->hdr.peerid);
1009 			break;
1010 		}
1011 		RB_FOREACH(h, knexthop_tree, KT2KNT(kt)) {
1012 			bzero(&snh, sizeof(snh));
1013 			memcpy(&snh.addr, &h->nexthop, sizeof(snh.addr));
1014 			if (h->kroute != NULL) {
1015 				switch (h->nexthop.aid) {
1016 				case AID_INET:
1017 					kr = h->kroute;
1018 					snh.valid = kroute_validate(&kr->r);
1019 					snh.krvalid = 1;
1020 					memcpy(&snh.kr.kr4, &kr->r,
1021 					    sizeof(snh.kr.kr4));
1022 					ifindex = kr->r.ifindex;
1023 					break;
1024 				case AID_INET6:
1025 					kr6 = h->kroute;
1026 					snh.valid = kroute6_validate(&kr6->r);
1027 					snh.krvalid = 1;
1028 					memcpy(&snh.kr.kr6, &kr6->r,
1029 					    sizeof(snh.kr.kr6));
1030 					ifindex = kr6->r.ifindex;
1031 					break;
1032 				}
1033 				if ((kif = kif_find(ifindex)) != NULL)
1034 					memcpy(&snh.kif, &kif->k,
1035 					    sizeof(snh.kif));
1036 			}
1037 			send_imsg_session(IMSG_CTL_SHOW_NEXTHOP, imsg->hdr.pid,
1038 			    &snh, sizeof(snh));
1039 		}
1040 		break;
1041 	case IMSG_CTL_SHOW_INTERFACE:
1042 		RB_FOREACH(kif, kif_tree, &kit)
1043 			send_imsg_session(IMSG_CTL_SHOW_INTERFACE,
1044 			    imsg->hdr.pid, &kif->k, sizeof(kif->k));
1045 		break;
1046 	case IMSG_CTL_SHOW_FIB_TABLES:
1047 		for (i = 0; i < krt_size; i++) {
1048 			struct ktable	ktab;
1049 
1050 			if ((kt = ktable_get(i)) == NULL)
1051 				continue;
1052 
1053 			ktab = *kt;
1054 			/* do not leak internal information */
1055 			RB_INIT(&ktab.krt);
1056 			RB_INIT(&ktab.krt6);
1057 			RB_INIT(&ktab.knt);
1058 			TAILQ_INIT(&ktab.krn);
1059 
1060 			send_imsg_session(IMSG_CTL_SHOW_FIB_TABLES,
1061 			    imsg->hdr.pid, &ktab, sizeof(ktab));
1062 		}
1063 		break;
1064 	default:	/* nada */
1065 		break;
1066 	}
1067 
1068 	send_imsg_session(IMSG_CTL_END, imsg->hdr.pid, NULL, 0);
1069 }
1070 
1071 void
1072 kr_ifinfo(char *ifname)
1073 {
1074 	struct kif_node	*kif;
1075 
1076 	RB_FOREACH(kif, kif_tree, &kit)
1077 		if (!strcmp(ifname, kif->k.ifname)) {
1078 			send_imsg_session(IMSG_IFINFO, 0,
1079 			    &kif->k, sizeof(kif->k));
1080 			return;
1081 		}
1082 }
1083 
1084 void
1085 kr_net_delete(struct network *n)
1086 {
1087 	filterset_free(&n->net.attrset);
1088 	free(n);
1089 }
1090 
1091 struct network *
1092 kr_net_match(struct ktable *kt, struct kroute *kr)
1093 {
1094 	struct network		*xn;
1095 
1096 	TAILQ_FOREACH(xn, &kt->krn, entry) {
1097 		if (xn->net.prefix.aid != AID_INET)
1098 			continue;
1099 		switch (xn->net.type) {
1100 		case NETWORK_DEFAULT:
1101 			if (xn->net.prefixlen == kr->prefixlen &&
1102 			    xn->net.prefix.v4.s_addr == kr->prefix.s_addr)
1103 				/* static match already redistributed */
1104 				return (NULL);
1105 			break;
1106 		case NETWORK_STATIC:
1107 			if (kr->flags & F_STATIC)
1108 				return (xn);
1109 			break;
1110 		case NETWORK_CONNECTED:
1111 			if (kr->flags & F_CONNECTED)
1112 				return (xn);
1113 			break;
1114 		case NETWORK_MRTCLONE:
1115 			/* can not happen */
1116 			break;
1117 		}
1118 	}
1119 	return (NULL);
1120 }
1121 
1122 struct network *
1123 kr_net_match6(struct ktable *kt, struct kroute6 *kr6)
1124 {
1125 	struct network		*xn;
1126 
1127 	TAILQ_FOREACH(xn, &kt->krn, entry) {
1128 		if (xn->net.prefix.aid != AID_INET6)
1129 			continue;
1130 		switch (xn->net.type) {
1131 		case NETWORK_DEFAULT:
1132 			if (xn->net.prefixlen == kr6->prefixlen &&
1133 			    memcmp(&xn->net.prefix.v6, &kr6->prefix,
1134 			    sizeof(struct in6_addr)) == 0)
1135 				/* static match already redistributed */
1136 				return (NULL);
1137 			break;
1138 		case NETWORK_STATIC:
1139 			if (kr6->flags & F_STATIC)
1140 				return (xn);
1141 			break;
1142 		case NETWORK_CONNECTED:
1143 			if (kr6->flags & F_CONNECTED)
1144 				return (xn);
1145 			break;
1146 		case NETWORK_MRTCLONE:
1147 			/* can not happen */
1148 			break;
1149 		}
1150 	}
1151 	return (NULL);
1152 }
1153 
1154 struct network *
1155 kr_net_find(struct ktable *kt, struct network *n)
1156 {
1157 	struct network		*xn;
1158 
1159 	TAILQ_FOREACH(xn, &kt->krn, entry) {
1160 		if (n->net.type != xn->net.type ||
1161 		    n->net.prefixlen != xn->net.prefixlen ||
1162 		    n->net.rtableid != xn->net.rtableid)
1163 			continue;
1164 		if (memcmp(&n->net.prefix, &xn->net.prefix,
1165 		    sizeof(n->net.prefix)) == 0)
1166 			return (xn);
1167 	}
1168 	return (NULL);
1169 }
1170 
1171 int
1172 kr_net_reload(u_int rtableid, struct network_head *nh)
1173 {
1174 	struct network		*n, *xn;
1175 	struct ktable		*kt;
1176 
1177 	if ((kt = ktable_get(rtableid)) == NULL) {
1178 		log_warnx("kr_net_reload: non-existent rtableid %d", rtableid);
1179 		return (-1);
1180 	}
1181 
1182 	TAILQ_FOREACH(n, &kt->krn, entry)
1183 		n->net.old = 1;
1184 
1185 	while ((n = TAILQ_FIRST(nh)) != NULL) {
1186 		TAILQ_REMOVE(nh, n, entry);
1187 		n->net.old = 0;
1188 		n->net.rtableid = rtableid;
1189 		xn = kr_net_find(kt, n);
1190 		if (xn) {
1191 			xn->net.old = 0;
1192 			filterset_free(&xn->net.attrset);
1193 			filterset_move(&n->net.attrset, &xn->net.attrset);
1194 			kr_net_delete(n);
1195 		} else
1196 			TAILQ_INSERT_TAIL(&kt->krn, n, entry);
1197 	}
1198 
1199 	for (n = TAILQ_FIRST(&kt->krn); n != NULL; n = xn) {
1200 		xn = TAILQ_NEXT(n, entry);
1201 		if (n->net.old) {
1202 			if (n->net.type == NETWORK_DEFAULT)
1203 				if (send_network(IMSG_NETWORK_REMOVE, &n->net,
1204 				    NULL))
1205 					return (-1);
1206 			TAILQ_REMOVE(&kt->krn, n, entry);
1207 			kr_net_delete(n);
1208 		}
1209 	}
1210 
1211 	return (0);
1212 }
1213 
1214 int
1215 kr_redistribute(int type, struct ktable *kt, struct kroute *kr)
1216 {
1217 	struct network		*match;
1218 	struct network_config	 net;
1219 	u_int32_t		 a;
1220 
1221 	/* shortcut for removals */
1222 	if (type == IMSG_NETWORK_REMOVE) {
1223 		if (!(kr->flags & F_REDISTRIBUTED))
1224 			return (0);	/* no match, don't redistribute */
1225 		kr->flags &= ~F_REDISTRIBUTED;
1226 		match = NULL;
1227 		goto sendit;
1228 	}
1229 
1230 	if (!(kr->flags & F_KERNEL))
1231 		return (0);
1232 
1233 	/* Dynamic routes are not redistributable. */
1234 	if (kr->flags & F_DYNAMIC)
1235 		return (0);
1236 
1237 	/*
1238 	 * We consider the loopback net, multicast and experimental addresses
1239 	 * as not redistributable.
1240 	 */
1241 	a = ntohl(kr->prefix.s_addr);
1242 	if (IN_MULTICAST(a) || IN_BADCLASS(a) ||
1243 	    (a >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
1244 		return (0);
1245 
1246 	/* Consider networks with nexthop loopback as not redistributable. */
1247 	if (kr->nexthop.s_addr == htonl(INADDR_LOOPBACK))
1248 		return (0);
1249 
1250 	/*
1251 	 * never allow 0.0.0.0/0 the default route can only be redistributed
1252 	 * with announce default.
1253 	 */
1254 	if (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0)
1255 		return (0);
1256 
1257 	match = kr_net_match(kt, kr);
1258 	if (match == NULL) {
1259 		if (!(kr->flags & F_REDISTRIBUTED))
1260 			return (0);	/* no match, don't redistribute */
1261 		/* route no longer matches but is redistributed, so remove */
1262 		kr->flags &= ~F_REDISTRIBUTED;
1263 		type = IMSG_NETWORK_REMOVE;
1264 	} else
1265 		kr->flags |= F_REDISTRIBUTED;
1266 
1267 sendit:
1268 	bzero(&net, sizeof(net));
1269 	net.prefix.aid = AID_INET;
1270 	net.prefix.v4.s_addr = kr->prefix.s_addr;
1271 	net.prefixlen = kr->prefixlen;
1272 	net.rtableid = kt->rtableid;
1273 
1274 	return (send_network(type, &net, match ? &match->net.attrset : NULL));
1275 }
1276 
1277 int
1278 kr_redistribute6(int type, struct ktable *kt, struct kroute6 *kr6)
1279 {
1280 	struct network		*match;
1281 	struct network_config	 net;
1282 
1283 	/* shortcut for removals */
1284 	if (type == IMSG_NETWORK_REMOVE) {
1285 		if (!(kr6->flags & F_REDISTRIBUTED))
1286 			return (0);	/* no match, don't redistribute */
1287 		kr6->flags &= ~F_REDISTRIBUTED;
1288 		match = NULL;
1289 		goto sendit;
1290 	}
1291 
1292 	if (!(kr6->flags & F_KERNEL))
1293 		return (0);
1294 
1295 	/* Dynamic routes are not redistributable. */
1296 	if (kr6->flags & F_DYNAMIC)
1297 		return (0);
1298 
1299 	/*
1300 	 * We consider unspecified, loopback, multicast, link- and site-local,
1301 	 * IPv4 mapped and IPv4 compatible addresses as not redistributable.
1302 	 */
1303 	if (IN6_IS_ADDR_UNSPECIFIED(&kr6->prefix) ||
1304 	    IN6_IS_ADDR_LOOPBACK(&kr6->prefix) ||
1305 	    IN6_IS_ADDR_MULTICAST(&kr6->prefix) ||
1306 	    IN6_IS_ADDR_LINKLOCAL(&kr6->prefix) ||
1307 	    IN6_IS_ADDR_SITELOCAL(&kr6->prefix) ||
1308 	    IN6_IS_ADDR_V4MAPPED(&kr6->prefix) ||
1309 	    IN6_IS_ADDR_V4COMPAT(&kr6->prefix))
1310 		return (0);
1311 
1312 	/*
1313 	 * Consider networks with nexthop loopback as not redistributable.
1314 	 */
1315 	if (IN6_IS_ADDR_LOOPBACK(&kr6->nexthop))
1316 		return (0);
1317 
1318 	/*
1319 	 * never allow ::/0 the default route can only be redistributed
1320 	 * with announce default.
1321 	 */
1322 	if (kr6->prefixlen == 0 &&
1323 	    memcmp(&kr6->prefix, &in6addr_any, sizeof(struct in6_addr)) == 0)
1324 		return (0);
1325 
1326 	match = kr_net_match6(kt, kr6);
1327 	if (match == NULL) {
1328 		if (!(kr6->flags & F_REDISTRIBUTED))
1329 			return (0);	/* no match, don't redistribute */
1330 		/* route no longer matches but is redistributed, so remove */
1331 		kr6->flags &= ~F_REDISTRIBUTED;
1332 		type = IMSG_NETWORK_REMOVE;
1333 	} else
1334 		kr6->flags |= F_REDISTRIBUTED;
1335 sendit:
1336 	bzero(&net, sizeof(net));
1337 	net.prefix.aid = AID_INET6;
1338 	memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
1339 	net.prefixlen = kr6->prefixlen;
1340 	net.rtableid = kt->rtableid;
1341 
1342 	return (send_network(type, &net, match ? &match->net.attrset : NULL));
1343 }
1344 
1345 int
1346 kr_reload(void)
1347 {
1348 	struct ktable		*kt;
1349 	struct kroute_node	*kr;
1350 	struct kroute6_node	*kr6;
1351 	struct knexthop_node	*nh;
1352 	struct network		*n;
1353 	u_int			 rid;
1354 	int			 hasdyn = 0;
1355 
1356 	for (rid = 0; rid < krt_size; rid++) {
1357 		if ((kt = ktable_get(rid)) == NULL)
1358 			continue;
1359 
1360 		RB_FOREACH(nh, knexthop_tree, KT2KNT(kt))
1361 			knexthop_validate(kt, nh);
1362 
1363 		TAILQ_FOREACH(n, &kt->krn, entry)
1364 			if (n->net.type == NETWORK_DEFAULT) {
1365 				if (send_network(IMSG_NETWORK_ADD, &n->net,
1366 				    &n->net.attrset))
1367 					return (-1);
1368 			} else
1369 				hasdyn = 1;
1370 
1371 		if (hasdyn) {
1372 			/* only evaluate the full tree if we need */
1373 			RB_FOREACH(kr, kroute_tree, &kt->krt)
1374 				kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r);
1375 			RB_FOREACH(kr6, kroute6_tree, &kt->krt6)
1376 				kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr6->r);
1377 		}
1378 	}
1379 
1380 	return (0);
1381 }
1382 
1383 struct kroute_full *
1384 kr_tofull(struct kroute *kr)
1385 {
1386 	static struct kroute_full	kf;
1387 
1388 	bzero(&kf, sizeof(kf));
1389 
1390 	kf.prefix.aid = AID_INET;
1391 	kf.prefix.v4.s_addr = kr->prefix.s_addr;
1392 	kf.nexthop.aid = AID_INET;
1393 	kf.nexthop.v4.s_addr = kr->nexthop.s_addr;
1394 	strlcpy(kf.label, rtlabel_id2name(kr->labelid), sizeof(kf.label));
1395 	kf.flags = kr->flags;
1396 	kf.ifindex = kr->ifindex;
1397 	kf.prefixlen = kr->prefixlen;
1398 	kf.priority = kr->priority;
1399 
1400 	return (&kf);
1401 }
1402 
1403 struct kroute_full *
1404 kr6_tofull(struct kroute6 *kr6)
1405 {
1406 	static struct kroute_full	kf;
1407 
1408 	bzero(&kf, sizeof(kf));
1409 
1410 	kf.prefix.aid = AID_INET6;
1411 	memcpy(&kf.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
1412 	kf.nexthop.aid = AID_INET6;
1413 	memcpy(&kf.nexthop.v6, &kr6->nexthop, sizeof(struct in6_addr));
1414 	strlcpy(kf.label, rtlabel_id2name(kr6->labelid), sizeof(kf.label));
1415 	kf.flags = kr6->flags;
1416 	kf.ifindex = kr6->ifindex;
1417 	kf.prefixlen = kr6->prefixlen;
1418 	kf.priority = kr6->priority;
1419 
1420 	return (&kf);
1421 }
1422 
1423 /*
1424  * RB-tree compare functions
1425  */
1426 
1427 int
1428 kroute_compare(struct kroute_node *a, struct kroute_node *b)
1429 {
1430 	if (ntohl(a->r.prefix.s_addr) < ntohl(b->r.prefix.s_addr))
1431 		return (-1);
1432 	if (ntohl(a->r.prefix.s_addr) > ntohl(b->r.prefix.s_addr))
1433 		return (1);
1434 	if (a->r.prefixlen < b->r.prefixlen)
1435 		return (-1);
1436 	if (a->r.prefixlen > b->r.prefixlen)
1437 		return (1);
1438 
1439 	/* if the priority is RTP_ANY finish on the first address hit */
1440 	if (a->r.priority == RTP_ANY || b->r.priority == RTP_ANY)
1441 		return (0);
1442 	if (a->r.priority < b->r.priority)
1443 		return (-1);
1444 	if (a->r.priority > b->r.priority)
1445 		return (1);
1446 	return (0);
1447 }
1448 
1449 int
1450 kroute6_compare(struct kroute6_node *a, struct kroute6_node *b)
1451 {
1452 	int i;
1453 
1454 	for (i = 0; i < 16; i++) {
1455 		if (a->r.prefix.s6_addr[i] < b->r.prefix.s6_addr[i])
1456 			return (-1);
1457 		if (a->r.prefix.s6_addr[i] > b->r.prefix.s6_addr[i])
1458 			return (1);
1459 	}
1460 
1461 	if (a->r.prefixlen < b->r.prefixlen)
1462 		return (-1);
1463 	if (a->r.prefixlen > b->r.prefixlen)
1464 		return (1);
1465 
1466 	/* if the priority is RTP_ANY finish on the first address hit */
1467 	if (a->r.priority == RTP_ANY || b->r.priority == RTP_ANY)
1468 		return (0);
1469 	if (a->r.priority < b->r.priority)
1470 		return (-1);
1471 	if (a->r.priority > b->r.priority)
1472 		return (1);
1473 	return (0);
1474 }
1475 
1476 int
1477 knexthop_compare(struct knexthop_node *a, struct knexthop_node *b)
1478 {
1479 	int	i;
1480 
1481 	if (a->nexthop.aid != b->nexthop.aid)
1482 		return (b->nexthop.aid - a->nexthop.aid);
1483 
1484 	switch (a->nexthop.aid) {
1485 	case AID_INET:
1486 		if (ntohl(a->nexthop.v4.s_addr) < ntohl(b->nexthop.v4.s_addr))
1487 			return (-1);
1488 		if (ntohl(a->nexthop.v4.s_addr) > ntohl(b->nexthop.v4.s_addr))
1489 			return (1);
1490 		break;
1491 	case AID_INET6:
1492 		for (i = 0; i < 16; i++) {
1493 			if (a->nexthop.v6.s6_addr[i] < b->nexthop.v6.s6_addr[i])
1494 				return (-1);
1495 			if (a->nexthop.v6.s6_addr[i] > b->nexthop.v6.s6_addr[i])
1496 				return (1);
1497 		}
1498 		break;
1499 	default:
1500 		fatalx("knexthop_compare: unknown AF");
1501 	}
1502 
1503 	return (0);
1504 }
1505 
1506 int
1507 kif_compare(struct kif_node *a, struct kif_node *b)
1508 {
1509 	return (b->k.ifindex - a->k.ifindex);
1510 }
1511 
1512 
1513 /*
1514  * tree management functions
1515  */
1516 
1517 struct kroute_node *
1518 kroute_find(struct ktable *kt, in_addr_t prefix, u_int8_t prefixlen,
1519     u_int8_t prio)
1520 {
1521 	struct kroute_node	s;
1522 	struct kroute_node	*kn, *tmp;
1523 
1524 	s.r.prefix.s_addr = prefix;
1525 	s.r.prefixlen = prefixlen;
1526 	s.r.priority = prio;
1527 
1528 	kn = RB_FIND(kroute_tree, &kt->krt, &s);
1529 	if (kn && prio == RTP_ANY) {
1530 		tmp = RB_PREV(kroute_tree, &kt->krt, kn);
1531 		while (tmp) {
1532 			if (kroute_compare(&s, tmp) == 0)
1533 				kn = tmp;
1534 			else
1535 				break;
1536 			tmp = RB_PREV(kroute_tree, &kt->krt, kn);
1537 		}
1538 	}
1539 	return (kn);
1540 }
1541 
1542 struct kroute_node *
1543 kroute_matchgw(struct kroute_node *kr, struct sockaddr_in *sa_in)
1544 {
1545 	in_addr_t	nexthop;
1546 
1547 	if (sa_in == NULL) {
1548 		log_warnx("kroute_matchgw: no nexthop defined");
1549 		return (NULL);
1550 	}
1551 	nexthop = sa_in->sin_addr.s_addr;
1552 
1553 	while (kr) {
1554 		if (kr->r.nexthop.s_addr == nexthop)
1555 			return (kr);
1556 		kr = kr->next;
1557 	}
1558 
1559 	return (NULL);
1560 }
1561 
1562 int
1563 kroute_insert(struct ktable *kt, struct kroute_node *kr)
1564 {
1565 	struct kroute_node	*krm;
1566 	struct knexthop_node	*h;
1567 	in_addr_t		 mask, ina;
1568 
1569 	if ((krm = RB_INSERT(kroute_tree, &kt->krt, kr)) != NULL) {
1570 		/* multipath route, add at end of list */
1571 		while (krm->next != NULL)
1572 			krm = krm->next;
1573 		krm->next = kr;
1574 		kr->next = NULL; /* to be sure */
1575 	}
1576 
1577 	/* XXX this is wrong for nexthop validated via BGP */
1578 	if (kr->r.flags & F_KERNEL) {
1579 		mask = prefixlen2mask(kr->r.prefixlen);
1580 		ina = ntohl(kr->r.prefix.s_addr);
1581 		RB_FOREACH(h, knexthop_tree, KT2KNT(kt))
1582 			if (h->nexthop.aid == AID_INET &&
1583 			    (ntohl(h->nexthop.v4.s_addr) & mask) == ina)
1584 				knexthop_validate(kt, h);
1585 
1586 		if (kr->r.flags & F_CONNECTED)
1587 			if (kif_kr_insert(kr) == -1)
1588 				return (-1);
1589 
1590 		if (krm == NULL)
1591 			/* redistribute multipath routes only once */
1592 			kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r);
1593 	}
1594 	return (0);
1595 }
1596 
1597 
1598 int
1599 kroute_remove(struct ktable *kt, struct kroute_node *kr)
1600 {
1601 	struct kroute_node	*krm;
1602 	struct knexthop_node	*s;
1603 
1604 	if ((krm = RB_FIND(kroute_tree, &kt->krt, kr)) == NULL) {
1605 		log_warnx("kroute_remove failed to find %s/%u",
1606 		    inet_ntoa(kr->r.prefix), kr->r.prefixlen);
1607 		return (-1);
1608 	}
1609 
1610 	if (krm == kr) {
1611 		/* head element */
1612 		if (RB_REMOVE(kroute_tree, &kt->krt, kr) == NULL) {
1613 			log_warnx("kroute_remove failed for %s/%u",
1614 			    inet_ntoa(kr->r.prefix), kr->r.prefixlen);
1615 			return (-1);
1616 		}
1617 		if (kr->next != NULL) {
1618 			if (RB_INSERT(kroute_tree, &kt->krt, kr->next) !=
1619 			    NULL) {
1620 				log_warnx("kroute_remove failed to add %s/%u",
1621 				    inet_ntoa(kr->r.prefix), kr->r.prefixlen);
1622 				return (-1);
1623 			}
1624 		}
1625 	} else {
1626 		/* somewhere in the list */
1627 		while (krm->next != kr && krm->next != NULL)
1628 			krm = krm->next;
1629 		if (krm->next == NULL) {
1630 			log_warnx("kroute_remove multipath list corrupted "
1631 			    "for %s/%u", inet_ntoa(kr->r.prefix),
1632 			    kr->r.prefixlen);
1633 			return (-1);
1634 		}
1635 		krm->next = kr->next;
1636 	}
1637 
1638 	/* check whether a nexthop depends on this kroute */
1639 	if (kr->r.flags & F_NEXTHOP)
1640 		RB_FOREACH(s, knexthop_tree, KT2KNT(kt))
1641 			if (s->kroute == kr)
1642 				knexthop_validate(kt, s);
1643 
1644 	if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL)
1645 		/* again remove only once */
1646 		kr_redistribute(IMSG_NETWORK_REMOVE, kt, &kr->r);
1647 
1648 	if (kr->r.flags & F_CONNECTED)
1649 		if (kif_kr_remove(kr) == -1) {
1650 			free(kr);
1651 			return (-1);
1652 		}
1653 
1654 	free(kr);
1655 	return (0);
1656 }
1657 
1658 void
1659 kroute_clear(struct ktable *kt)
1660 {
1661 	struct kroute_node	*kr;
1662 
1663 	while ((kr = RB_MIN(kroute_tree, &kt->krt)) != NULL)
1664 		kroute_remove(kt, kr);
1665 }
1666 
1667 struct kroute6_node *
1668 kroute6_find(struct ktable *kt, const struct in6_addr *prefix,
1669     u_int8_t prefixlen, u_int8_t prio)
1670 {
1671 	struct kroute6_node	s;
1672 	struct kroute6_node	*kn6, *tmp;
1673 
1674 	memcpy(&s.r.prefix, prefix, sizeof(struct in6_addr));
1675 	s.r.prefixlen = prefixlen;
1676 	s.r.priority = prio;
1677 
1678 	kn6 = RB_FIND(kroute6_tree, &kt->krt6, &s);
1679 	if (kn6 && prio == RTP_ANY) {
1680 		tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6);
1681 		while (tmp) {
1682 			if (kroute6_compare(&s, tmp) == 0)
1683 				kn6 = tmp;
1684 			else
1685 				break;
1686 			tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6);
1687 		}
1688 	}
1689 	return (kn6);
1690 }
1691 
1692 struct kroute6_node *
1693 kroute6_matchgw(struct kroute6_node *kr, struct sockaddr_in6 *sa_in6)
1694 {
1695 	struct in6_addr	nexthop;
1696 
1697 	if (sa_in6 == NULL) {
1698 		log_warnx("kroute6_matchgw: no nexthop defined");
1699 		return (NULL);
1700 	}
1701 	memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop));
1702 
1703 	while (kr) {
1704 		if (memcmp(&kr->r.nexthop, &nexthop, sizeof(nexthop)) == 0)
1705 			return (kr);
1706 		kr = kr->next;
1707 	}
1708 
1709 	return (NULL);
1710 }
1711 
1712 int
1713 kroute6_insert(struct ktable *kt, struct kroute6_node *kr)
1714 {
1715 	struct kroute6_node	*krm;
1716 	struct knexthop_node	*h;
1717 	struct in6_addr		 ina, inb;
1718 
1719 	if ((krm = RB_INSERT(kroute6_tree, &kt->krt6, kr)) != NULL) {
1720 		/* multipath route, add at end of list */
1721 		while (krm->next != NULL)
1722 			krm = krm->next;
1723 		krm->next = kr;
1724 		kr->next = NULL; /* to be sure */
1725 	}
1726 
1727 	/* XXX this is wrong for nexthop validated via BGP */
1728 	if (kr->r.flags & F_KERNEL) {
1729 		inet6applymask(&ina, &kr->r.prefix, kr->r.prefixlen);
1730 		RB_FOREACH(h, knexthop_tree, KT2KNT(kt))
1731 			if (h->nexthop.aid == AID_INET6) {
1732 				inet6applymask(&inb, &h->nexthop.v6,
1733 				    kr->r.prefixlen);
1734 				if (memcmp(&ina, &inb, sizeof(ina)) == 0)
1735 					knexthop_validate(kt, h);
1736 			}
1737 
1738 		if (kr->r.flags & F_CONNECTED)
1739 			if (kif_kr6_insert(kr) == -1)
1740 				return (-1);
1741 
1742 		if (krm == NULL)
1743 			/* redistribute multipath routes only once */
1744 			kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr->r);
1745 	}
1746 
1747 	return (0);
1748 }
1749 
1750 int
1751 kroute6_remove(struct ktable *kt, struct kroute6_node *kr)
1752 {
1753 	struct kroute6_node	*krm;
1754 	struct knexthop_node	*s;
1755 
1756 	if ((krm = RB_FIND(kroute6_tree, &kt->krt6, kr)) == NULL) {
1757 		log_warnx("kroute6_remove failed for %s/%u",
1758 		    log_in6addr(&kr->r.prefix), kr->r.prefixlen);
1759 		return (-1);
1760 	}
1761 
1762 	if (krm == kr) {
1763 		/* head element */
1764 		if (RB_REMOVE(kroute6_tree, &kt->krt6, kr) == NULL) {
1765 			log_warnx("kroute6_remove failed for %s/%u",
1766 			    log_in6addr(&kr->r.prefix), kr->r.prefixlen);
1767 			return (-1);
1768 		}
1769 		if (kr->next != NULL) {
1770 			if (RB_INSERT(kroute6_tree, &kt->krt6, kr->next) !=
1771 			    NULL) {
1772 				log_warnx("kroute6_remove failed to add %s/%u",
1773 				    log_in6addr(&kr->r.prefix),
1774 				    kr->r.prefixlen);
1775 				return (-1);
1776 			}
1777 		}
1778 	} else {
1779 		/* somewhere in the list */
1780 		while (krm->next != kr && krm->next != NULL)
1781 			krm = krm->next;
1782 		if (krm->next == NULL) {
1783 			log_warnx("kroute6_remove multipath list corrupted "
1784 			    "for %s/%u", log_in6addr(&kr->r.prefix),
1785 			    kr->r.prefixlen);
1786 			return (-1);
1787 		}
1788 		krm->next = kr->next;
1789 	}
1790 
1791 	/* check whether a nexthop depends on this kroute */
1792 	if (kr->r.flags & F_NEXTHOP)
1793 		RB_FOREACH(s, knexthop_tree, KT2KNT(kt))
1794 			if (s->kroute == kr)
1795 				knexthop_validate(kt, s);
1796 
1797 	if (kr->r.flags & F_KERNEL && kr == krm && kr->next == NULL)
1798 		/* again remove only once */
1799 		kr_redistribute6(IMSG_NETWORK_REMOVE, kt, &kr->r);
1800 
1801 	if (kr->r.flags & F_CONNECTED)
1802 		if (kif_kr6_remove(kr) == -1) {
1803 			free(kr);
1804 			return (-1);
1805 		}
1806 
1807 	free(kr);
1808 	return (0);
1809 }
1810 
1811 void
1812 kroute6_clear(struct ktable *kt)
1813 {
1814 	struct kroute6_node	*kr;
1815 
1816 	while ((kr = RB_MIN(kroute6_tree, &kt->krt6)) != NULL)
1817 		kroute6_remove(kt, kr);
1818 }
1819 
1820 struct knexthop_node *
1821 knexthop_find(struct ktable *kt, struct bgpd_addr *addr)
1822 {
1823 	struct knexthop_node	s;
1824 
1825 	bzero(&s, sizeof(s));
1826 	memcpy(&s.nexthop, addr, sizeof(s.nexthop));
1827 
1828 	return (RB_FIND(knexthop_tree, KT2KNT(kt), &s));
1829 }
1830 
1831 int
1832 knexthop_insert(struct ktable *kt, struct knexthop_node *kn)
1833 {
1834 	if (RB_INSERT(knexthop_tree, KT2KNT(kt), kn) != NULL) {
1835 		log_warnx("knexthop_insert failed for %s",
1836 		    log_addr(&kn->nexthop));
1837 		free(kn);
1838 		return (-1);
1839 	}
1840 
1841 	knexthop_validate(kt, kn);
1842 
1843 	return (0);
1844 }
1845 
1846 int
1847 knexthop_remove(struct ktable *kt, struct knexthop_node *kn)
1848 {
1849 	kroute_detach_nexthop(kt, kn);
1850 
1851 	if (RB_REMOVE(knexthop_tree, KT2KNT(kt), kn) == NULL) {
1852 		log_warnx("knexthop_remove failed for %s",
1853 		    log_addr(&kn->nexthop));
1854 		return (-1);
1855 	}
1856 
1857 	free(kn);
1858 	return (0);
1859 }
1860 
1861 void
1862 knexthop_clear(struct ktable *kt)
1863 {
1864 	struct knexthop_node	*kn;
1865 
1866 	while ((kn = RB_MIN(knexthop_tree, KT2KNT(kt))) != NULL)
1867 		knexthop_remove(kt, kn);
1868 }
1869 
1870 struct kif_node *
1871 kif_find(int ifindex)
1872 {
1873 	struct kif_node	s;
1874 
1875 	bzero(&s, sizeof(s));
1876 	s.k.ifindex = ifindex;
1877 
1878 	return (RB_FIND(kif_tree, &kit, &s));
1879 }
1880 
1881 int
1882 kif_insert(struct kif_node *kif)
1883 {
1884 	LIST_INIT(&kif->kroute_l);
1885 	LIST_INIT(&kif->kroute6_l);
1886 
1887 	if (RB_INSERT(kif_tree, &kit, kif) != NULL) {
1888 		log_warnx("RB_INSERT(kif_tree, &kit, kif)");
1889 		free(kif);
1890 		return (-1);
1891 	}
1892 
1893 	return (0);
1894 }
1895 
1896 int
1897 kif_remove(struct kif_node *kif)
1898 {
1899 	struct ktable	*kt;
1900 	struct kif_kr	*kkr;
1901 	struct kif_kr6	*kkr6;
1902 
1903 	if (RB_REMOVE(kif_tree, &kit, kif) == NULL) {
1904 		log_warnx("RB_REMOVE(kif_tree, &kit, kif)");
1905 		return (-1);
1906 	}
1907 
1908 	if ((kt = ktable_get(/* XXX */ 0)) == NULL)
1909 		goto done;
1910 
1911 	while ((kkr = LIST_FIRST(&kif->kroute_l)) != NULL) {
1912 		LIST_REMOVE(kkr, entry);
1913 		kkr->kr->r.flags &= ~F_NEXTHOP;
1914 		kroute_remove(kt, kkr->kr);
1915 		free(kkr);
1916 	}
1917 
1918 	while ((kkr6 = LIST_FIRST(&kif->kroute6_l)) != NULL) {
1919 		LIST_REMOVE(kkr6, entry);
1920 		kkr6->kr->r.flags &= ~F_NEXTHOP;
1921 		kroute6_remove(kt, kkr6->kr);
1922 		free(kkr6);
1923 	}
1924 done:
1925 	free(kif);
1926 	return (0);
1927 }
1928 
1929 void
1930 kif_clear(void)
1931 {
1932 	struct kif_node	*kif;
1933 
1934 	while ((kif = RB_MIN(kif_tree, &kit)) != NULL)
1935 		kif_remove(kif);
1936 }
1937 
1938 int
1939 kif_kr_insert(struct kroute_node *kr)
1940 {
1941 	struct kif_node	*kif;
1942 	struct kif_kr	*kkr;
1943 
1944 	if ((kif = kif_find(kr->r.ifindex)) == NULL) {
1945 		if (kr->r.ifindex)
1946 			log_warnx("%s: interface with index %u not found",
1947 			    __func__, kr->r.ifindex);
1948 		return (0);
1949 	}
1950 
1951 	if (kif->k.nh_reachable)
1952 		kr->r.flags &= ~F_DOWN;
1953 	else
1954 		kr->r.flags |= F_DOWN;
1955 
1956 	if ((kkr = calloc(1, sizeof(struct kif_kr))) == NULL) {
1957 		log_warn("kif_kr_insert");
1958 		return (-1);
1959 	}
1960 
1961 	kkr->kr = kr;
1962 
1963 	LIST_INSERT_HEAD(&kif->kroute_l, kkr, entry);
1964 
1965 	return (0);
1966 }
1967 
1968 int
1969 kif_kr_remove(struct kroute_node *kr)
1970 {
1971 	struct kif_node	*kif;
1972 	struct kif_kr	*kkr;
1973 
1974 	if ((kif = kif_find(kr->r.ifindex)) == NULL) {
1975 		if (kr->r.ifindex)
1976 			log_warnx("%s: interface with index %u not found",
1977 			    __func__, kr->r.ifindex);
1978 		return (0);
1979 	}
1980 
1981 	for (kkr = LIST_FIRST(&kif->kroute_l); kkr != NULL && kkr->kr != kr;
1982 	    kkr = LIST_NEXT(kkr, entry))
1983 		;	/* nothing */
1984 
1985 	if (kkr == NULL) {
1986 		log_warnx("can't remove connected route from interface "
1987 		    "with index %u: not found", kr->r.ifindex);
1988 		return (-1);
1989 	}
1990 
1991 	LIST_REMOVE(kkr, entry);
1992 	free(kkr);
1993 
1994 	return (0);
1995 }
1996 
1997 int
1998 kif_kr6_insert(struct kroute6_node *kr)
1999 {
2000 	struct kif_node	*kif;
2001 	struct kif_kr6	*kkr6;
2002 
2003 	if ((kif = kif_find(kr->r.ifindex)) == NULL) {
2004 		if (kr->r.ifindex)
2005 			log_warnx("%s: interface with index %u not found",
2006 			    __func__, kr->r.ifindex);
2007 		return (0);
2008 	}
2009 
2010 	if (kif->k.nh_reachable)
2011 		kr->r.flags &= ~F_DOWN;
2012 	else
2013 		kr->r.flags |= F_DOWN;
2014 
2015 	if ((kkr6 = calloc(1, sizeof(struct kif_kr6))) == NULL) {
2016 		log_warn("kif_kr6_insert");
2017 		return (-1);
2018 	}
2019 
2020 	kkr6->kr = kr;
2021 
2022 	LIST_INSERT_HEAD(&kif->kroute6_l, kkr6, entry);
2023 
2024 	return (0);
2025 }
2026 
2027 int
2028 kif_kr6_remove(struct kroute6_node *kr)
2029 {
2030 	struct kif_node	*kif;
2031 	struct kif_kr6	*kkr6;
2032 
2033 	if ((kif = kif_find(kr->r.ifindex)) == NULL) {
2034 		if (kr->r.ifindex)
2035 			log_warnx("%s: interface with index %u not found",
2036 			    __func__, kr->r.ifindex);
2037 		return (0);
2038 	}
2039 
2040 	for (kkr6 = LIST_FIRST(&kif->kroute6_l); kkr6 != NULL && kkr6->kr != kr;
2041 	    kkr6 = LIST_NEXT(kkr6, entry))
2042 		;	/* nothing */
2043 
2044 	if (kkr6 == NULL) {
2045 		log_warnx("can't remove connected route from interface "
2046 		    "with index %u: not found", kr->r.ifindex);
2047 		return (-1);
2048 	}
2049 
2050 	LIST_REMOVE(kkr6, entry);
2051 	free(kkr6);
2052 
2053 	return (0);
2054 }
2055 
2056 /*
2057  * nexthop validation
2058  */
2059 
2060 int
2061 kif_validate(struct kif *kif)
2062 {
2063 	if (!(kif->flags & IFF_UP))
2064 		return (0);
2065 
2066 	/*
2067 	 * we treat link_state == LINK_STATE_UNKNOWN as valid,
2068 	 * not all interfaces have a concept of "link state" and/or
2069 	 * do not report up
2070 	 */
2071 
2072 	if (kif->link_state == LINK_STATE_DOWN)
2073 		return (0);
2074 
2075 	return (1);
2076 }
2077 
2078 int
2079 kroute_validate(struct kroute *kr)
2080 {
2081 	struct kif_node		*kif;
2082 
2083 	if (kr->flags & (F_REJECT | F_BLACKHOLE))
2084 		return (0);
2085 
2086 	if ((kif = kif_find(kr->ifindex)) == NULL) {
2087 		if (kr->ifindex)
2088 			log_warnx("%s: interface with index %d not found, "
2089 			    "referenced from route for %s/%u", __func__,
2090 			    kr->ifindex, inet_ntoa(kr->prefix),
2091 			    kr->prefixlen);
2092 		return (1);
2093 	}
2094 
2095 	return (kif->k.nh_reachable);
2096 }
2097 
2098 int
2099 kroute6_validate(struct kroute6 *kr)
2100 {
2101 	struct kif_node		*kif;
2102 
2103 	if (kr->flags & (F_REJECT | F_BLACKHOLE))
2104 		return (0);
2105 
2106 	if ((kif = kif_find(kr->ifindex)) == NULL) {
2107 		if (kr->ifindex)
2108 			log_warnx("%s: interface with index %d not found, "
2109 			    "referenced from route for %s/%u", __func__,
2110 			    kr->ifindex, log_in6addr(&kr->prefix),
2111 			    kr->prefixlen);
2112 		return (1);
2113 	}
2114 
2115 	return (kif->k.nh_reachable);
2116 }
2117 
2118 void
2119 knexthop_validate(struct ktable *kt, struct knexthop_node *kn)
2120 {
2121 	void			*oldk;
2122 	struct kroute_node	*kr;
2123 	struct kroute6_node	*kr6;
2124 
2125 	oldk = kn->kroute;
2126 	kroute_detach_nexthop(kt, kn);
2127 
2128 	switch (kn->nexthop.aid) {
2129 	case AID_INET:
2130 		kr = kroute_match(kt, kn->nexthop.v4.s_addr, 0);
2131 
2132 		if (kr) {
2133 			kn->kroute = kr;
2134 			kr->r.flags |= F_NEXTHOP;
2135 		}
2136 
2137 		/*
2138 		 * Send update if nexthop route changed under us if
2139 		 * the route remains the same then the NH state has not
2140 		 * changed. State changes are tracked by knexthop_track().
2141 		 */
2142 		if (kr != oldk)
2143 			knexthop_send_update(kn);
2144 		break;
2145 	case AID_INET6:
2146 		kr6 = kroute6_match(kt, &kn->nexthop.v6, 0);
2147 
2148 		if (kr6) {
2149 			kn->kroute = kr6;
2150 			kr6->r.flags |= F_NEXTHOP;
2151 		}
2152 
2153 		if (kr6 != oldk)
2154 			knexthop_send_update(kn);
2155 		break;
2156 	}
2157 }
2158 
2159 void
2160 knexthop_track(struct ktable *kt, void *krp)
2161 {
2162 	struct knexthop_node	*kn;
2163 
2164 	RB_FOREACH(kn, knexthop_tree, KT2KNT(kt))
2165 		if (kn->kroute == krp)
2166 			knexthop_send_update(kn);
2167 }
2168 
2169 void
2170 knexthop_send_update(struct knexthop_node *kn)
2171 {
2172 	struct kroute_nexthop	 n;
2173 	struct kroute_node	*kr;
2174 	struct kroute6_node	*kr6;
2175 
2176 	bzero(&n, sizeof(n));
2177 	memcpy(&n.nexthop, &kn->nexthop, sizeof(n.nexthop));
2178 
2179 	if (kn->kroute == NULL) {
2180 		n.valid = 0;	/* NH is not valid */
2181 		send_nexthop_update(&n);
2182 		return;
2183 	}
2184 
2185 	switch (kn->nexthop.aid) {
2186 	case AID_INET:
2187 		kr = kn->kroute;
2188 		n.valid = kroute_validate(&kr->r);
2189 		n.connected = kr->r.flags & F_CONNECTED;
2190 		if ((n.gateway.v4.s_addr =
2191 		    kr->r.nexthop.s_addr) != 0)
2192 			n.gateway.aid = AID_INET;
2193 		if (n.connected) {
2194 			n.net.aid = AID_INET;
2195 			n.net.v4.s_addr = kr->r.prefix.s_addr;
2196 			n.netlen = kr->r.prefixlen;
2197 		}
2198 		break;
2199 	case AID_INET6:
2200 		kr6 = kn->kroute;
2201 		n.valid = kroute6_validate(&kr6->r);
2202 		n.connected = kr6->r.flags & F_CONNECTED;
2203 		if (memcmp(&kr6->r.nexthop, &in6addr_any,
2204 		    sizeof(struct in6_addr)) != 0) {
2205 			n.gateway.aid = AID_INET6;
2206 			memcpy(&n.gateway.v6, &kr6->r.nexthop,
2207 			    sizeof(struct in6_addr));
2208 		}
2209 		if (n.connected) {
2210 			n.net.aid = AID_INET6;
2211 			memcpy(&n.net.v6, &kr6->r.nexthop,
2212 			    sizeof(struct in6_addr));
2213 			n.netlen = kr6->r.prefixlen;
2214 		}
2215 		break;
2216 	}
2217 	send_nexthop_update(&n);
2218 }
2219 
2220 struct kroute_node *
2221 kroute_match(struct ktable *kt, in_addr_t key, int matchall)
2222 {
2223 	int			 i;
2224 	struct kroute_node	*kr;
2225 	in_addr_t		 ina;
2226 
2227 	ina = ntohl(key);
2228 
2229 	/* we will never match the default route */
2230 	for (i = 32; i > 0; i--)
2231 		if ((kr = kroute_find(kt, htonl(ina & prefixlen2mask(i)), i,
2232 		    RTP_ANY)) != NULL)
2233 			if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0)
2234 			    return (kr);
2235 
2236 	/* if we don't have a match yet, try to find a default route */
2237 	if ((kr = kroute_find(kt, 0, 0, RTP_ANY)) != NULL)
2238 		if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0)
2239 			return (kr);
2240 
2241 	return (NULL);
2242 }
2243 
2244 struct kroute6_node *
2245 kroute6_match(struct ktable *kt, struct in6_addr *key, int matchall)
2246 {
2247 	int			 i;
2248 	struct kroute6_node	*kr6;
2249 	struct in6_addr		 ina;
2250 
2251 	/* we will never match the default route */
2252 	for (i = 128; i > 0; i--) {
2253 		inet6applymask(&ina, key, i);
2254 		if ((kr6 = kroute6_find(kt, &ina, i, RTP_ANY)) != NULL)
2255 			if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0)
2256 				return (kr6);
2257 	}
2258 
2259 	/* if we don't have a match yet, try to find a default route */
2260 	if ((kr6 = kroute6_find(kt, &in6addr_any, 0, RTP_ANY)) != NULL)
2261 		if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0)
2262 			return (kr6);
2263 
2264 	return (NULL);
2265 }
2266 
2267 void
2268 kroute_detach_nexthop(struct ktable *kt, struct knexthop_node *kn)
2269 {
2270 	struct knexthop_node	*s;
2271 	struct kroute_node	*k;
2272 	struct kroute6_node	*k6;
2273 
2274 	if (kn->kroute == NULL)
2275 		return;
2276 
2277 	/*
2278 	 * check whether there's another nexthop depending on this kroute
2279 	 * if not remove the flag
2280 	 */
2281 	RB_FOREACH(s, knexthop_tree, KT2KNT(kt))
2282 		if (s->kroute == kn->kroute && s != kn)
2283 			break;
2284 
2285 	if (s == NULL) {
2286 		switch (kn->nexthop.aid) {
2287 		case AID_INET:
2288 			k = kn->kroute;
2289 			k->r.flags &= ~F_NEXTHOP;
2290 			break;
2291 		case AID_INET6:
2292 			k6 = kn->kroute;
2293 			k6->r.flags &= ~F_NEXTHOP;
2294 			break;
2295 		}
2296 	}
2297 
2298 	kn->kroute = NULL;
2299 }
2300 
2301 /*
2302  * misc helpers
2303  */
2304 
2305 int
2306 protect_lo(struct ktable *kt)
2307 {
2308 	struct kroute_node	*kr;
2309 	struct kroute6_node	*kr6;
2310 
2311 	/* special protection for 127/8 */
2312 	if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
2313 		log_warn("protect_lo");
2314 		return (-1);
2315 	}
2316 	kr->r.prefix.s_addr = htonl(INADDR_LOOPBACK & IN_CLASSA_NET);
2317 	kr->r.prefixlen = 8;
2318 	kr->r.flags = F_KERNEL|F_CONNECTED;
2319 
2320 	if (RB_INSERT(kroute_tree, &kt->krt, kr) != NULL)
2321 		free(kr);	/* kernel route already there, no problem */
2322 
2323 	/* special protection for loopback */
2324 	if ((kr6 = calloc(1, sizeof(struct kroute6_node))) == NULL) {
2325 		log_warn("protect_lo");
2326 		return (-1);
2327 	}
2328 	memcpy(&kr6->r.prefix, &in6addr_loopback, sizeof(kr6->r.prefix));
2329 	kr6->r.prefixlen = 128;
2330 	kr6->r.flags = F_KERNEL|F_CONNECTED;
2331 
2332 	if (RB_INSERT(kroute6_tree, &kt->krt6, kr6) != NULL)
2333 		free(kr6);	/* kernel route already there, no problem */
2334 
2335 	return (0);
2336 }
2337 
2338 u_int8_t
2339 prefixlen_classful(in_addr_t ina)
2340 {
2341 	/* it hurt to write this. */
2342 
2343 	if (ina >= 0xf0000000U)		/* class E */
2344 		return (32);
2345 	else if (ina >= 0xe0000000U)	/* class D */
2346 		return (4);
2347 	else if (ina >= 0xc0000000U)	/* class C */
2348 		return (24);
2349 	else if (ina >= 0x80000000U)	/* class B */
2350 		return (16);
2351 	else				/* class A */
2352 		return (8);
2353 }
2354 
2355 u_int8_t
2356 mask2prefixlen(in_addr_t ina)
2357 {
2358 	if (ina == 0)
2359 		return (0);
2360 	else
2361 		return (33 - ffs(ntohl(ina)));
2362 }
2363 
2364 u_int8_t
2365 mask2prefixlen6(struct sockaddr_in6 *sa_in6)
2366 {
2367 	u_int8_t	 l = 0, *ap, *ep;
2368 
2369 	/*
2370 	 * sin6_len is the size of the sockaddr so substract the offset of
2371 	 * the possibly truncated sin6_addr struct.
2372 	 */
2373 	ap = (u_int8_t *)&sa_in6->sin6_addr;
2374 	ep = (u_int8_t *)sa_in6 + sa_in6->sin6_len;
2375 	for (; ap < ep; ap++) {
2376 		/* this "beauty" is adopted from sbin/route/show.c ... */
2377 		switch (*ap) {
2378 		case 0xff:
2379 			l += 8;
2380 			break;
2381 		case 0xfe:
2382 			l += 7;
2383 			return (l);
2384 		case 0xfc:
2385 			l += 6;
2386 			return (l);
2387 		case 0xf8:
2388 			l += 5;
2389 			return (l);
2390 		case 0xf0:
2391 			l += 4;
2392 			return (l);
2393 		case 0xe0:
2394 			l += 3;
2395 			return (l);
2396 		case 0xc0:
2397 			l += 2;
2398 			return (l);
2399 		case 0x80:
2400 			l += 1;
2401 			return (l);
2402 		case 0x00:
2403 			return (l);
2404 		default:
2405 			fatalx("non contiguous inet6 netmask");
2406 		}
2407 	}
2408 
2409 	return (l);
2410 }
2411 
2412 struct in6_addr *
2413 prefixlen2mask6(u_int8_t prefixlen)
2414 {
2415 	static struct in6_addr	mask;
2416 	int			i;
2417 
2418 	bzero(&mask, sizeof(mask));
2419 	for (i = 0; i < prefixlen / 8; i++)
2420 		mask.s6_addr[i] = 0xff;
2421 	i = prefixlen % 8;
2422 	if (i)
2423 		mask.s6_addr[prefixlen / 8] = 0xff00 >> i;
2424 
2425 	return (&mask);
2426 }
2427 
2428 #define	ROUNDUP(a)	\
2429     (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a))
2430 
2431 void
2432 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
2433 {
2434 	int	i;
2435 
2436 	for (i = 0; i < RTAX_MAX; i++) {
2437 		if (addrs & (1 << i)) {
2438 			rti_info[i] = sa;
2439 			sa = (struct sockaddr *)((char *)(sa) +
2440 			    ROUNDUP(sa->sa_len));
2441 		} else
2442 			rti_info[i] = NULL;
2443 	}
2444 }
2445 
2446 void
2447 if_change(u_short ifindex, int flags, struct if_data *ifd)
2448 {
2449 	struct ktable		*kt;
2450 	struct kif_node		*kif;
2451 	struct kif_kr		*kkr;
2452 	struct kif_kr6		*kkr6;
2453 	u_int8_t		 reachable;
2454 
2455 	if ((kif = kif_find(ifindex)) == NULL) {
2456 		log_warnx("%s: interface with index %u not found",
2457 		    __func__, ifindex);
2458 		return;
2459 	}
2460 
2461 	kif->k.flags = flags;
2462 	kif->k.link_state = ifd->ifi_link_state;
2463 	kif->k.if_type = ifd->ifi_type;
2464 	kif->k.baudrate = ifd->ifi_baudrate;
2465 
2466 	send_imsg_session(IMSG_IFINFO, 0, &kif->k, sizeof(kif->k));
2467 
2468 	if ((reachable = kif_validate(&kif->k)) == kif->k.nh_reachable)
2469 		return;		/* nothing changed wrt nexthop validity */
2470 
2471 	kif->k.nh_reachable = reachable;
2472 
2473 	kt = ktable_get(/* XXX */ 0);
2474 
2475 	LIST_FOREACH(kkr, &kif->kroute_l, entry) {
2476 		if (reachable)
2477 			kkr->kr->r.flags &= ~F_DOWN;
2478 		else
2479 			kkr->kr->r.flags |= F_DOWN;
2480 
2481 		if (kt == NULL)
2482 			continue;
2483 
2484 		knexthop_track(kt, kkr->kr);
2485 	}
2486 	LIST_FOREACH(kkr6, &kif->kroute6_l, entry) {
2487 		if (reachable)
2488 			kkr6->kr->r.flags &= ~F_DOWN;
2489 		else
2490 			kkr6->kr->r.flags |= F_DOWN;
2491 
2492 		if (kt == NULL)
2493 			continue;
2494 
2495 		knexthop_track(kt, kkr6->kr);
2496 	}
2497 }
2498 
2499 void
2500 if_announce(void *msg)
2501 {
2502 	struct if_announcemsghdr	*ifan;
2503 	struct kif_node			*kif;
2504 
2505 	ifan = msg;
2506 
2507 	switch (ifan->ifan_what) {
2508 	case IFAN_ARRIVAL:
2509 		if ((kif = calloc(1, sizeof(struct kif_node))) == NULL) {
2510 			log_warn("if_announce");
2511 			return;
2512 		}
2513 
2514 		kif->k.ifindex = ifan->ifan_index;
2515 		strlcpy(kif->k.ifname, ifan->ifan_name, sizeof(kif->k.ifname));
2516 		kif_insert(kif);
2517 		break;
2518 	case IFAN_DEPARTURE:
2519 		kif = kif_find(ifan->ifan_index);
2520 		kif_remove(kif);
2521 		break;
2522 	}
2523 }
2524 
2525 /*
2526  * rtsock related functions
2527  */
2528 
2529 int
2530 send_rtmsg(int fd, int action, struct ktable *kt, struct kroute *kroute,
2531     u_int8_t fib_prio)
2532 {
2533 	struct iovec		iov[7];
2534 	struct rt_msghdr	hdr;
2535 	struct sockaddr_in	prefix;
2536 	struct sockaddr_in	nexthop;
2537 	struct sockaddr_in	mask;
2538 	struct {
2539 		struct sockaddr_dl	dl;
2540 		char			pad[sizeof(long)];
2541 	}			ifp;
2542 	struct sockaddr_mpls	mpls;
2543 	struct sockaddr_rtlabel	label;
2544 	int			iovcnt = 0;
2545 
2546 	if (!kt->fib_sync)
2547 		return (0);
2548 
2549 	/* initialize header */
2550 	bzero(&hdr, sizeof(hdr));
2551 	hdr.rtm_version = RTM_VERSION;
2552 	hdr.rtm_type = action;
2553 	hdr.rtm_tableid = kt->rtableid;
2554 	hdr.rtm_priority = fib_prio;
2555 	if (kroute->flags & F_BLACKHOLE)
2556 		hdr.rtm_flags |= RTF_BLACKHOLE;
2557 	if (kroute->flags & F_REJECT)
2558 		hdr.rtm_flags |= RTF_REJECT;
2559 	if (action == RTM_CHANGE)	/* reset these flags on change */
2560 		hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE;
2561 	hdr.rtm_seq = kr_state.rtseq++;	/* overflow doesn't matter */
2562 	hdr.rtm_msglen = sizeof(hdr);
2563 	/* adjust iovec */
2564 	iov[iovcnt].iov_base = &hdr;
2565 	iov[iovcnt++].iov_len = sizeof(hdr);
2566 
2567 	bzero(&prefix, sizeof(prefix));
2568 	prefix.sin_len = sizeof(prefix);
2569 	prefix.sin_family = AF_INET;
2570 	prefix.sin_addr.s_addr = kroute->prefix.s_addr;
2571 	/* adjust header */
2572 	hdr.rtm_addrs |= RTA_DST;
2573 	hdr.rtm_msglen += sizeof(prefix);
2574 	/* adjust iovec */
2575 	iov[iovcnt].iov_base = &prefix;
2576 	iov[iovcnt++].iov_len = sizeof(prefix);
2577 
2578 	if (kroute->nexthop.s_addr != 0) {
2579 		bzero(&nexthop, sizeof(nexthop));
2580 		nexthop.sin_len = sizeof(nexthop);
2581 		nexthop.sin_family = AF_INET;
2582 		nexthop.sin_addr.s_addr = kroute->nexthop.s_addr;
2583 		/* adjust header */
2584 		hdr.rtm_flags |= RTF_GATEWAY;
2585 		hdr.rtm_addrs |= RTA_GATEWAY;
2586 		hdr.rtm_msglen += sizeof(nexthop);
2587 		/* adjust iovec */
2588 		iov[iovcnt].iov_base = &nexthop;
2589 		iov[iovcnt++].iov_len = sizeof(nexthop);
2590 	}
2591 
2592 	bzero(&mask, sizeof(mask));
2593 	mask.sin_len = sizeof(mask);
2594 	mask.sin_family = AF_INET;
2595 	mask.sin_addr.s_addr = htonl(prefixlen2mask(kroute->prefixlen));
2596 	/* adjust header */
2597 	hdr.rtm_addrs |= RTA_NETMASK;
2598 	hdr.rtm_msglen += sizeof(mask);
2599 	/* adjust iovec */
2600 	iov[iovcnt].iov_base = &mask;
2601 	iov[iovcnt++].iov_len = sizeof(mask);
2602 
2603 	if (kt->ifindex) {
2604 		bzero(&ifp, sizeof(ifp));
2605 		ifp.dl.sdl_len = sizeof(struct sockaddr_dl);
2606 		ifp.dl.sdl_family = AF_LINK;
2607 		ifp.dl.sdl_index = kt->ifindex;
2608 		/* adjust header */
2609 		hdr.rtm_addrs |= RTA_IFP;
2610 		hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_dl));
2611 		/* adjust iovec */
2612 		iov[iovcnt].iov_base = &ifp;
2613 		iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_dl));
2614 	}
2615 
2616 	if (kroute->flags & F_MPLS) {
2617 		bzero(&mpls, sizeof(mpls));
2618 		mpls.smpls_len = sizeof(mpls);
2619 		mpls.smpls_family = AF_MPLS;
2620 		mpls.smpls_label = kroute->mplslabel;
2621 		/* adjust header */
2622 		hdr.rtm_flags |= RTF_MPLS;
2623 		hdr.rtm_mpls = MPLS_OP_PUSH;
2624 		hdr.rtm_addrs |= RTA_SRC;
2625 		hdr.rtm_msglen += sizeof(mpls);
2626 		/* adjust iovec */
2627 		iov[iovcnt].iov_base = &mpls;
2628 		iov[iovcnt++].iov_len = sizeof(mpls);
2629 	}
2630 
2631 	if (kroute->labelid) {
2632 		bzero(&label, sizeof(label));
2633 		label.sr_len = sizeof(label);
2634 		strlcpy(label.sr_label, rtlabel_id2name(kroute->labelid),
2635 		    sizeof(label.sr_label));
2636 		/* adjust header */
2637 		hdr.rtm_addrs |= RTA_LABEL;
2638 		hdr.rtm_msglen += sizeof(label);
2639 		/* adjust iovec */
2640 		iov[iovcnt].iov_base = &label;
2641 		iov[iovcnt++].iov_len = sizeof(label);
2642 	}
2643 
2644 retry:
2645 	if (writev(fd, iov, iovcnt) == -1) {
2646 		if (errno == ESRCH) {
2647 			if (hdr.rtm_type == RTM_CHANGE) {
2648 				hdr.rtm_type = RTM_ADD;
2649 				goto retry;
2650 			} else if (hdr.rtm_type == RTM_DELETE) {
2651 				log_info("route %s/%u vanished before delete",
2652 				    inet_ntoa(kroute->prefix),
2653 				    kroute->prefixlen);
2654 				return (0);
2655 			}
2656 		}
2657 		log_warn("send_rtmsg: action %u, prefix %s/%u", hdr.rtm_type,
2658 		    inet_ntoa(kroute->prefix), kroute->prefixlen);
2659 		return (0);
2660 	}
2661 
2662 	return (0);
2663 }
2664 
2665 int
2666 send_rt6msg(int fd, int action, struct ktable *kt, struct kroute6 *kroute,
2667     u_int8_t fib_prio)
2668 {
2669 	struct iovec		iov[5];
2670 	struct rt_msghdr	hdr;
2671 	struct pad {
2672 		struct sockaddr_in6	addr;
2673 		char			pad[sizeof(long)];
2674 	} prefix, nexthop, mask;
2675 	struct sockaddr_rtlabel	label;
2676 	int			iovcnt = 0;
2677 
2678 	if (!kt->fib_sync)
2679 		return (0);
2680 
2681 	/* initialize header */
2682 	bzero(&hdr, sizeof(hdr));
2683 	hdr.rtm_version = RTM_VERSION;
2684 	hdr.rtm_type = action;
2685 	hdr.rtm_tableid = kt->rtableid;
2686 	hdr.rtm_priority = fib_prio;
2687 	if (kroute->flags & F_BLACKHOLE)
2688 		hdr.rtm_flags |= RTF_BLACKHOLE;
2689 	if (kroute->flags & F_REJECT)
2690 		hdr.rtm_flags |= RTF_REJECT;
2691 	if (action == RTM_CHANGE)	/* reset these flags on change */
2692 		hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE;
2693 	hdr.rtm_seq = kr_state.rtseq++;	/* overflow doesn't matter */
2694 	hdr.rtm_msglen = sizeof(hdr);
2695 	/* adjust iovec */
2696 	iov[iovcnt].iov_base = &hdr;
2697 	iov[iovcnt++].iov_len = sizeof(hdr);
2698 
2699 	bzero(&prefix, sizeof(prefix));
2700 	prefix.addr.sin6_len = sizeof(struct sockaddr_in6);
2701 	prefix.addr.sin6_family = AF_INET6;
2702 	memcpy(&prefix.addr.sin6_addr, &kroute->prefix,
2703 	    sizeof(struct in6_addr));
2704 	/* XXX scope does not matter or? */
2705 	/* adjust header */
2706 	hdr.rtm_addrs |= RTA_DST;
2707 	hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
2708 	/* adjust iovec */
2709 	iov[iovcnt].iov_base = &prefix;
2710 	iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
2711 
2712 	if (memcmp(&kroute->nexthop, &in6addr_any, sizeof(struct in6_addr))) {
2713 		bzero(&nexthop, sizeof(nexthop));
2714 		nexthop.addr.sin6_len = sizeof(struct sockaddr_in6);
2715 		nexthop.addr.sin6_family = AF_INET6;
2716 		memcpy(&nexthop.addr.sin6_addr, &kroute->nexthop,
2717 		    sizeof(struct in6_addr));
2718 		/* adjust header */
2719 		hdr.rtm_flags |= RTF_GATEWAY;
2720 		hdr.rtm_addrs |= RTA_GATEWAY;
2721 		hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
2722 		/* adjust iovec */
2723 		iov[iovcnt].iov_base = &nexthop;
2724 		iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
2725 	}
2726 
2727 	bzero(&mask, sizeof(mask));
2728 	mask.addr.sin6_len = sizeof(struct sockaddr_in6);
2729 	mask.addr.sin6_family = AF_INET6;
2730 	memcpy(&mask.addr.sin6_addr, prefixlen2mask6(kroute->prefixlen),
2731 	    sizeof(struct in6_addr));
2732 	/* adjust header */
2733 	hdr.rtm_addrs |= RTA_NETMASK;
2734 	hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
2735 	/* adjust iovec */
2736 	iov[iovcnt].iov_base = &mask;
2737 	iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
2738 
2739 	if (kroute->labelid) {
2740 		bzero(&label, sizeof(label));
2741 		label.sr_len = sizeof(label);
2742 		strlcpy(label.sr_label, rtlabel_id2name(kroute->labelid),
2743 		    sizeof(label.sr_label));
2744 		/* adjust header */
2745 		hdr.rtm_addrs |= RTA_LABEL;
2746 		hdr.rtm_msglen += sizeof(label);
2747 		/* adjust iovec */
2748 		iov[iovcnt].iov_base = &label;
2749 		iov[iovcnt++].iov_len = sizeof(label);
2750 	}
2751 
2752 retry:
2753 	if (writev(fd, iov, iovcnt) == -1) {
2754 		if (errno == ESRCH) {
2755 			if (hdr.rtm_type == RTM_CHANGE) {
2756 				hdr.rtm_type = RTM_ADD;
2757 				goto retry;
2758 			} else if (hdr.rtm_type == RTM_DELETE) {
2759 				log_info("route %s/%u vanished before delete",
2760 				    log_in6addr(&kroute->prefix),
2761 				    kroute->prefixlen);
2762 				return (0);
2763 			}
2764 		}
2765 		log_warn("send_rt6msg: action %u, prefix %s/%u", hdr.rtm_type,
2766 		    log_in6addr(&kroute->prefix), kroute->prefixlen);
2767 		return (0);
2768 	}
2769 
2770 	return (0);
2771 }
2772 
2773 int
2774 fetchtable(struct ktable *kt, u_int8_t fib_prio)
2775 {
2776 	size_t			 len;
2777 	int			 mib[7];
2778 	char			*buf = NULL, *next, *lim;
2779 	struct rt_msghdr	*rtm;
2780 	struct sockaddr		*sa, *gw, *rti_info[RTAX_MAX];
2781 	struct sockaddr_in	*sa_in;
2782 	struct sockaddr_in6	*sa_in6;
2783 	struct kroute_node	*kr = NULL;
2784 	struct kroute6_node	*kr6 = NULL;
2785 
2786 	mib[0] = CTL_NET;
2787 	mib[1] = PF_ROUTE;
2788 	mib[2] = 0;
2789 	mib[3] = 0;
2790 	mib[4] = NET_RT_DUMP;
2791 	mib[5] = 0;
2792 	mib[6] = kt->rtableid;
2793 
2794 	if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) {
2795 		if (kt->rtableid != 0 && errno == EINVAL)
2796 			/* table nonexistent */
2797 			return (0);
2798 		log_warn("sysctl");
2799 		return (-1);
2800 	}
2801 	if (len > 0) {
2802 		if ((buf = malloc(len)) == NULL) {
2803 			log_warn("fetchtable");
2804 			return (-1);
2805 		}
2806 		if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) {
2807 			log_warn("sysctl2");
2808 			free(buf);
2809 			return (-1);
2810 		}
2811 	}
2812 
2813 	lim = buf + len;
2814 	for (next = buf; next < lim; next += rtm->rtm_msglen) {
2815 		rtm = (struct rt_msghdr *)next;
2816 		if (rtm->rtm_version != RTM_VERSION)
2817 			continue;
2818 		sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
2819 		get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
2820 
2821 		if ((sa = rti_info[RTAX_DST]) == NULL)
2822 			continue;
2823 
2824 		/* Skip ARP/ND cache and broadcast routes. */
2825 		if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
2826 			continue;
2827 
2828 		switch (sa->sa_family) {
2829 		case AF_INET:
2830 			if ((kr = calloc(1, sizeof(struct kroute_node))) ==
2831 			    NULL) {
2832 				log_warn("fetchtable");
2833 				free(buf);
2834 				return (-1);
2835 			}
2836 
2837 			kr->r.flags = F_KERNEL;
2838 			kr->r.priority = rtm->rtm_priority;
2839 			kr->r.ifindex = rtm->rtm_index;
2840 			kr->r.prefix.s_addr =
2841 			    ((struct sockaddr_in *)sa)->sin_addr.s_addr;
2842 			sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
2843 			if (rtm->rtm_flags & RTF_STATIC)
2844 				kr->r.flags |= F_STATIC;
2845 			if (rtm->rtm_flags & RTF_BLACKHOLE)
2846 				kr->r.flags |= F_BLACKHOLE;
2847 			if (rtm->rtm_flags & RTF_REJECT)
2848 				kr->r.flags |= F_REJECT;
2849 			if (rtm->rtm_flags & RTF_DYNAMIC)
2850 				kr->r.flags |= F_DYNAMIC;
2851 			if (sa_in != NULL) {
2852 				if (sa_in->sin_len == 0)
2853 					break;
2854 				kr->r.prefixlen =
2855 				    mask2prefixlen(sa_in->sin_addr.s_addr);
2856 			} else if (rtm->rtm_flags & RTF_HOST)
2857 				kr->r.prefixlen = 32;
2858 			else
2859 				kr->r.prefixlen =
2860 				    prefixlen_classful(kr->r.prefix.s_addr);
2861 			break;
2862 		case AF_INET6:
2863 			if ((kr6 = calloc(1, sizeof(struct kroute6_node))) ==
2864 			    NULL) {
2865 				log_warn("fetchtable");
2866 				free(buf);
2867 				return (-1);
2868 			}
2869 
2870 			kr6->r.flags = F_KERNEL;
2871 			kr6->r.priority = rtm->rtm_priority;
2872 			kr6->r.ifindex = rtm->rtm_index;
2873 			memcpy(&kr6->r.prefix,
2874 			    &((struct sockaddr_in6 *)sa)->sin6_addr,
2875 			    sizeof(kr6->r.prefix));
2876 
2877 			sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
2878 			if (rtm->rtm_flags & RTF_STATIC)
2879 				kr6->r.flags |= F_STATIC;
2880 			if (rtm->rtm_flags & RTF_BLACKHOLE)
2881 				kr6->r.flags |= F_BLACKHOLE;
2882 			if (rtm->rtm_flags & RTF_REJECT)
2883 				kr6->r.flags |= F_REJECT;
2884 			if (rtm->rtm_flags & RTF_DYNAMIC)
2885 				kr6->r.flags |= F_DYNAMIC;
2886 			if (sa_in6 != NULL) {
2887 				if (sa_in6->sin6_len == 0)
2888 					break;
2889 				kr6->r.prefixlen = mask2prefixlen6(sa_in6);
2890 			} else if (rtm->rtm_flags & RTF_HOST)
2891 				kr6->r.prefixlen = 128;
2892 			else
2893 				fatalx("INET6 route without netmask");
2894 			break;
2895 		default:
2896 			continue;
2897 		}
2898 
2899 		if ((gw = rti_info[RTAX_GATEWAY]) != NULL)
2900 			switch (gw->sa_family) {
2901 			case AF_INET:
2902 				if (kr == NULL)
2903 					fatalx("v4 gateway for !v4 dst?!");
2904 
2905 				if (rtm->rtm_flags & RTF_CONNECTED) {
2906 					kr->r.flags |= F_CONNECTED;
2907 					break;
2908 				}
2909 
2910 				kr->r.nexthop.s_addr =
2911 				    ((struct sockaddr_in *)gw)->sin_addr.s_addr;
2912 				break;
2913 			case AF_INET6:
2914 				if (kr6 == NULL)
2915 					fatalx("v6 gateway for !v6 dst?!");
2916 
2917 				if (rtm->rtm_flags & RTF_CONNECTED) {
2918 					kr6->r.flags |= F_CONNECTED;
2919 					break;
2920 				}
2921 
2922 				memcpy(&kr6->r.nexthop,
2923 				    &((struct sockaddr_in6 *)gw)->sin6_addr,
2924 				    sizeof(kr6->r.nexthop));
2925 				break;
2926 			case AF_LINK:
2927 				/*
2928 				 * Traditional BSD connected routes have
2929 				 * a gateway of type AF_LINK.
2930 				 */
2931 				if (sa->sa_family == AF_INET)
2932 					kr->r.flags |= F_CONNECTED;
2933 				else if (sa->sa_family == AF_INET6)
2934 					kr6->r.flags |= F_CONNECTED;
2935 				break;
2936 			}
2937 
2938 		if (sa->sa_family == AF_INET) {
2939 			if (rtm->rtm_priority == fib_prio)  {
2940 				send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r,
2941 				    fib_prio);
2942 				free(kr);
2943 			} else
2944 				kroute_insert(kt, kr);
2945 		} else if (sa->sa_family == AF_INET6) {
2946 			if (rtm->rtm_priority == fib_prio)  {
2947 				send_rt6msg(kr_state.fd, RTM_DELETE, kt,
2948 				    &kr6->r, fib_prio);
2949 				free(kr6);
2950 			} else
2951 				kroute6_insert(kt, kr6);
2952 		}
2953 	}
2954 	free(buf);
2955 	return (0);
2956 }
2957 
2958 int
2959 fetchifs(int ifindex)
2960 {
2961 	size_t			 len;
2962 	int			 mib[6];
2963 	char			*buf, *next, *lim;
2964 	struct if_msghdr	 ifm;
2965 	struct kif_node		*kif;
2966 	struct sockaddr		*sa, *rti_info[RTAX_MAX];
2967 	struct sockaddr_dl	*sdl;
2968 
2969 	mib[0] = CTL_NET;
2970 	mib[1] = PF_ROUTE;
2971 	mib[2] = 0;
2972 	mib[3] = AF_INET;	/* AF does not matter but AF_INET is shorter */
2973 	mib[4] = NET_RT_IFLIST;
2974 	mib[5] = ifindex;
2975 
2976 	if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) {
2977 		log_warn("sysctl");
2978 		return (-1);
2979 	}
2980 	if ((buf = malloc(len)) == NULL) {
2981 		log_warn("fetchif");
2982 		return (-1);
2983 	}
2984 	if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) {
2985 		log_warn("sysctl");
2986 		free(buf);
2987 		return (-1);
2988 	}
2989 
2990 	lim = buf + len;
2991 	for (next = buf; next < lim; next += ifm.ifm_msglen) {
2992 		memcpy(&ifm, next, sizeof(ifm));
2993 		if (ifm.ifm_version != RTM_VERSION)
2994 			continue;
2995 		if (ifm.ifm_type != RTM_IFINFO)
2996 			continue;
2997 
2998 		sa = (struct sockaddr *)(next + sizeof(ifm));
2999 		get_rtaddrs(ifm.ifm_addrs, sa, rti_info);
3000 
3001 		if ((kif = calloc(1, sizeof(struct kif_node))) == NULL) {
3002 			log_warn("fetchifs");
3003 			free(buf);
3004 			return (-1);
3005 		}
3006 
3007 		kif->k.ifindex = ifm.ifm_index;
3008 		kif->k.flags = ifm.ifm_flags;
3009 		kif->k.link_state = ifm.ifm_data.ifi_link_state;
3010 		kif->k.if_type = ifm.ifm_data.ifi_type;
3011 		kif->k.baudrate = ifm.ifm_data.ifi_baudrate;
3012 		kif->k.nh_reachable = kif_validate(&kif->k);
3013 
3014 		if ((sa = rti_info[RTAX_IFP]) != NULL)
3015 			if (sa->sa_family == AF_LINK) {
3016 				sdl = (struct sockaddr_dl *)sa;
3017 				if (sdl->sdl_nlen >= sizeof(kif->k.ifname))
3018 					memcpy(kif->k.ifname, sdl->sdl_data,
3019 					    sizeof(kif->k.ifname) - 1);
3020 				else if (sdl->sdl_nlen > 0)
3021 					memcpy(kif->k.ifname, sdl->sdl_data,
3022 					    sdl->sdl_nlen);
3023 				/* string already terminated via calloc() */
3024 			}
3025 
3026 		kif_insert(kif);
3027 	}
3028 	free(buf);
3029 	return (0);
3030 }
3031 
3032 int
3033 dispatch_rtmsg(void)
3034 {
3035 	char			 buf[RT_BUF_SIZE];
3036 	ssize_t			 n;
3037 	char			*next, *lim;
3038 	struct rt_msghdr	*rtm;
3039 	struct if_msghdr	 ifm;
3040 	struct sockaddr		*sa, *rti_info[RTAX_MAX];
3041 	struct ktable		*kt;
3042 
3043 	if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
3044 		if (errno == EAGAIN || errno == EINTR)
3045 			return (0);
3046 		log_warn("dispatch_rtmsg: read error");
3047 		return (-1);
3048 	}
3049 
3050 	if (n == 0) {
3051 		log_warnx("routing socket closed");
3052 		return (-1);
3053 	}
3054 
3055 	lim = buf + n;
3056 	for (next = buf; next < lim; next += rtm->rtm_msglen) {
3057 		rtm = (struct rt_msghdr *)next;
3058 		if (lim < next + sizeof(u_short) ||
3059 		    lim < next + rtm->rtm_msglen)
3060 			fatalx("dispatch_rtmsg: partial rtm in buffer");
3061 		if (rtm->rtm_version != RTM_VERSION)
3062 			continue;
3063 
3064 		switch (rtm->rtm_type) {
3065 		case RTM_ADD:
3066 		case RTM_CHANGE:
3067 		case RTM_DELETE:
3068 			sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
3069 			get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
3070 
3071 			if (rtm->rtm_pid == kr_state.pid) /* cause by us */
3072 				continue;
3073 
3074 			if (rtm->rtm_errno)		 /* failed attempts */
3075 				continue;
3076 
3077 			if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
3078 				continue;
3079 
3080 			if ((kt = ktable_get(rtm->rtm_tableid)) == NULL)
3081 				continue;
3082 
3083 			if (dispatch_rtmsg_addr(rtm, rti_info, kt) == -1)
3084 				return (-1);
3085 			break;
3086 		case RTM_IFINFO:
3087 			memcpy(&ifm, next, sizeof(ifm));
3088 			if_change(ifm.ifm_index, ifm.ifm_flags,
3089 			    &ifm.ifm_data);
3090 			break;
3091 		case RTM_IFANNOUNCE:
3092 			if_announce(next);
3093 			break;
3094 		default:
3095 			/* ignore for now */
3096 			break;
3097 		}
3098 	}
3099 	return (0);
3100 }
3101 
3102 int
3103 dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX],
3104     struct ktable *kt)
3105 {
3106 	struct sockaddr		*sa;
3107 	struct sockaddr_in	*sa_in;
3108 	struct sockaddr_in6	*sa_in6;
3109 	struct kroute_node	*kr;
3110 	struct kroute6_node	*kr6;
3111 	struct bgpd_addr	 prefix;
3112 	int			 flags, oflags, mpath = 0, changed = 0;
3113 	u_int16_t		 ifindex;
3114 	u_int8_t		 prefixlen;
3115 	u_int8_t		 prio;
3116 
3117 	flags = F_KERNEL;
3118 	ifindex = 0;
3119 	prefixlen = 0;
3120 	bzero(&prefix, sizeof(prefix));
3121 
3122 	if ((sa = rti_info[RTAX_DST]) == NULL) {
3123 		log_warnx("empty route message");
3124 		return (0);
3125 	}
3126 
3127 	if (rtm->rtm_flags & RTF_STATIC)
3128 		flags |= F_STATIC;
3129 	if (rtm->rtm_flags & RTF_BLACKHOLE)
3130 		flags |= F_BLACKHOLE;
3131 	if (rtm->rtm_flags & RTF_REJECT)
3132 		flags |= F_REJECT;
3133 	if (rtm->rtm_flags & RTF_DYNAMIC)
3134 		flags |= F_DYNAMIC;
3135 #ifdef RTF_MPATH
3136 	if (rtm->rtm_flags & RTF_MPATH)
3137 		mpath = 1;
3138 #endif
3139 
3140 	prio = rtm->rtm_priority;
3141 	switch (sa->sa_family) {
3142 	case AF_INET:
3143 		prefix.aid = AID_INET;
3144 		prefix.v4.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
3145 		sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
3146 		if (sa_in != NULL) {
3147 			if (sa_in->sin_len != 0)
3148 				prefixlen = mask2prefixlen(
3149 				    sa_in->sin_addr.s_addr);
3150 		} else if (rtm->rtm_flags & RTF_HOST)
3151 			prefixlen = 32;
3152 		else
3153 			prefixlen =
3154 			    prefixlen_classful(prefix.v4.s_addr);
3155 		break;
3156 	case AF_INET6:
3157 		prefix.aid = AID_INET6;
3158 		memcpy(&prefix.v6, &((struct sockaddr_in6 *)sa)->sin6_addr,
3159 		    sizeof(struct in6_addr));
3160 		sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
3161 		if (sa_in6 != NULL) {
3162 			if (sa_in6->sin6_len != 0)
3163 				prefixlen = mask2prefixlen6(sa_in6);
3164 		} else if (rtm->rtm_flags & RTF_HOST)
3165 			prefixlen = 128;
3166 		else
3167 			fatalx("in6 net addr without netmask");
3168 		break;
3169 	default:
3170 		return (0);
3171 	}
3172 
3173 	if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
3174 		switch (sa->sa_family) {
3175 		case AF_LINK:
3176 			flags |= F_CONNECTED;
3177 			ifindex = rtm->rtm_index;
3178 			sa = NULL;
3179 			mpath = 0;	/* link local stuff can't be mpath */
3180 			break;
3181 		case AF_INET:
3182 		case AF_INET6:
3183 			if (rtm->rtm_flags & RTF_CONNECTED) {
3184 				flags |= F_CONNECTED;
3185 				ifindex = rtm->rtm_index;
3186 				sa = NULL;
3187 				mpath = 0; /* link local stuff can't be mpath */
3188 			}
3189 			break;
3190 		}
3191 
3192 	if (rtm->rtm_type == RTM_DELETE) {
3193 		switch (prefix.aid) {
3194 		case AID_INET:
3195 			sa_in = (struct sockaddr_in *)sa;
3196 			if ((kr = kroute_find(kt, prefix.v4.s_addr,
3197 			    prefixlen, prio)) == NULL)
3198 				return (0);
3199 			if (!(kr->r.flags & F_KERNEL))
3200 				return (0);
3201 
3202 			if (mpath)
3203 				/* get the correct route */
3204 				if ((kr = kroute_matchgw(kr, sa_in)) == NULL) {
3205 					log_warnx("dispatch_rtmsg_addr[delete] "
3206 					    "mpath route not found");
3207 					return (0);
3208 				}
3209 
3210 			if (kroute_remove(kt, kr) == -1)
3211 				return (-1);
3212 			break;
3213 		case AID_INET6:
3214 			sa_in6 = (struct sockaddr_in6 *)sa;
3215 			if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen,
3216 			    prio)) == NULL)
3217 				return (0);
3218 			if (!(kr6->r.flags & F_KERNEL))
3219 				return (0);
3220 
3221 			if (mpath)
3222 				/* get the correct route */
3223 				if ((kr6 = kroute6_matchgw(kr6, sa_in6)) ==
3224 				    NULL) {
3225 					log_warnx("dispatch_rtmsg_addr[delete] "
3226 					    "IPv6 mpath route not found");
3227 					return (0);
3228 				}
3229 
3230 			if (kroute6_remove(kt, kr6) == -1)
3231 				return (-1);
3232 			break;
3233 		}
3234 		return (0);
3235 	}
3236 
3237 	if (sa == NULL && !(flags & F_CONNECTED)) {
3238 		log_warnx("%s: no nexthop for %s/%u",
3239 		    __func__, log_addr(&prefix), prefixlen);
3240 		return (0);
3241 	}
3242 
3243 	switch (prefix.aid) {
3244 	case AID_INET:
3245 		sa_in = (struct sockaddr_in *)sa;
3246 		if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen,
3247 		    prio)) != NULL) {
3248 			if (kr->r.flags & F_KERNEL) {
3249 				/* get the correct route */
3250 				if (mpath && rtm->rtm_type == RTM_CHANGE &&
3251 				    (kr = kroute_matchgw(kr, sa_in)) == NULL) {
3252 					log_warnx("dispatch_rtmsg_addr[change] "
3253 					    "mpath route not found");
3254 					goto add4;
3255 				} else if (mpath && rtm->rtm_type == RTM_ADD)
3256 					goto add4;
3257 
3258 				if (sa_in != NULL) {
3259 					if (kr->r.nexthop.s_addr !=
3260 					    sa_in->sin_addr.s_addr)
3261 						changed = 1;
3262 					kr->r.nexthop.s_addr =
3263 					    sa_in->sin_addr.s_addr;
3264 				} else {
3265 					if (kr->r.nexthop.s_addr != 0)
3266 						changed = 1;
3267 					kr->r.nexthop.s_addr = 0;
3268 				}
3269 
3270 				if (kr->r.flags & F_NEXTHOP)
3271 					flags |= F_NEXTHOP;
3272 				oflags = kr->r.flags;
3273 				if (flags != oflags)
3274 					changed = 1;
3275 				kr->r.flags = flags;
3276 				if ((oflags & F_CONNECTED) &&
3277 				    !(flags & F_CONNECTED)) {
3278 					kif_kr_remove(kr);
3279 					kr_redistribute(IMSG_NETWORK_REMOVE,
3280 					    kt, &kr->r);
3281 				}
3282 				if ((flags & F_CONNECTED) &&
3283 				    !(oflags & F_CONNECTED)) {
3284 					kif_kr_insert(kr);
3285 					kr_redistribute(IMSG_NETWORK_ADD,
3286 					    kt, &kr->r);
3287 				}
3288 				if (kr->r.flags & F_NEXTHOP && changed)
3289 					knexthop_track(kt, kr);
3290 			}
3291 		} else if (rtm->rtm_type == RTM_CHANGE) {
3292 			log_warnx("change req for %s/%u: not in table",
3293 			    log_addr(&prefix), prefixlen);
3294 			return (0);
3295 		} else {
3296 add4:
3297 			if ((kr = calloc(1,
3298 			    sizeof(struct kroute_node))) == NULL) {
3299 				log_warn("dispatch_rtmsg");
3300 				return (-1);
3301 			}
3302 			kr->r.prefix.s_addr = prefix.v4.s_addr;
3303 			kr->r.prefixlen = prefixlen;
3304 			if (sa_in != NULL)
3305 				kr->r.nexthop.s_addr = sa_in->sin_addr.s_addr;
3306 			else
3307 				kr->r.nexthop.s_addr = 0;
3308 			kr->r.flags = flags;
3309 			kr->r.ifindex = ifindex;
3310 			kr->r.priority = prio;
3311 
3312 			kroute_insert(kt, kr);
3313 		}
3314 		break;
3315 	case AID_INET6:
3316 		sa_in6 = (struct sockaddr_in6 *)sa;
3317 		if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen, prio)) !=
3318 		    NULL) {
3319 			if (kr6->r.flags & F_KERNEL) {
3320 				/* get the correct route */
3321 				if (mpath && rtm->rtm_type == RTM_CHANGE &&
3322 				    (kr6 = kroute6_matchgw(kr6, sa_in6)) ==
3323 				    NULL) {
3324 					log_warnx("dispatch_rtmsg[change] "
3325 					    "IPv6 mpath route not found");
3326 					goto add6;
3327 				} else if (mpath && rtm->rtm_type == RTM_ADD)
3328 					goto add6;
3329 
3330 				if (sa_in6 != NULL) {
3331 					if (memcmp(&kr6->r.nexthop,
3332 					    &sa_in6->sin6_addr,
3333 					    sizeof(struct in6_addr)))
3334 						changed = 1;
3335 					memcpy(&kr6->r.nexthop,
3336 					    &sa_in6->sin6_addr,
3337 					    sizeof(struct in6_addr));
3338 				} else {
3339 					if (memcmp(&kr6->r.nexthop,
3340 					    &in6addr_any,
3341 					    sizeof(struct in6_addr)))
3342 						changed = 1;
3343 					memcpy(&kr6->r.nexthop,
3344 					    &in6addr_any,
3345 					    sizeof(struct in6_addr));
3346 				}
3347 
3348 				if (kr6->r.flags & F_NEXTHOP)
3349 					flags |= F_NEXTHOP;
3350 				oflags = kr6->r.flags;
3351 				if (flags != oflags)
3352 					changed = 1;
3353 				kr6->r.flags = flags;
3354 				if ((oflags & F_CONNECTED) &&
3355 				    !(flags & F_CONNECTED)) {
3356 					kif_kr6_remove(kr6);
3357 					kr_redistribute6(IMSG_NETWORK_REMOVE,
3358 					    kt, &kr6->r);
3359 				}
3360 				if ((flags & F_CONNECTED) &&
3361 				    !(oflags & F_CONNECTED)) {
3362 					kif_kr6_insert(kr6);
3363 					kr_redistribute6(IMSG_NETWORK_ADD,
3364 					    kt, &kr6->r);
3365 				}
3366 				if (kr6->r.flags & F_NEXTHOP && changed)
3367 					knexthop_track(kt, kr6);
3368 			}
3369 		} else if (rtm->rtm_type == RTM_CHANGE) {
3370 			log_warnx("change req for %s/%u: not in table",
3371 			    log_addr(&prefix), prefixlen);
3372 			return (0);
3373 		} else {
3374 add6:
3375 			if ((kr6 = calloc(1,
3376 			    sizeof(struct kroute6_node))) == NULL) {
3377 				log_warn("dispatch_rtmsg_addr");
3378 				return (-1);
3379 			}
3380 			memcpy(&kr6->r.prefix, &prefix.v6,
3381 			    sizeof(struct in6_addr));
3382 			kr6->r.prefixlen = prefixlen;
3383 			if (sa_in6 != NULL)
3384 				memcpy(&kr6->r.nexthop, &sa_in6->sin6_addr,
3385 				    sizeof(struct in6_addr));
3386 			else
3387 				memcpy(&kr6->r.nexthop, &in6addr_any,
3388 				    sizeof(struct in6_addr));
3389 			kr6->r.flags = flags;
3390 			kr6->r.ifindex = ifindex;
3391 			kr6->r.priority = prio;
3392 
3393 			kroute6_insert(kt, kr6);
3394 		}
3395 		break;
3396 	}
3397 
3398 	return (0);
3399 }
3400