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