-/* $OpenBSD: kroute.c,v 1.282 2022/07/26 17:12:40 claudio Exp $ */
+/* $OpenBSD: kroute.c,v 1.283 2022/07/27 17:23:17 claudio Exp $ */
/*
* Copyright (c) 2022 Claudio Jeker <claudio@openbsd.org>
struct network *kr_net_find(struct ktable *, struct network *);
void kr_net_clear(struct ktable *);
void kr_redistribute(int, struct ktable *, struct kroute_full *);
+uint8_t kr_priority(struct kroute_full *);
struct kroute_full *kr_tofull(struct kroute *);
struct kroute_full *kr6_tofull(struct kroute6 *);
int kroute_compare(struct kroute *, struct kroute *);
return (0);
if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen,
- RTP_MINE)) == NULL) {
+ kf->priority)) == NULL) {
if (kroute_insert(kt, kf) == -1)
return (-1);
} else {
return (0);
if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen,
- RTP_MINE)) == NULL) {
+ kf->priority)) == NULL) {
if (kroute_insert(kt, kf) == -1)
return (-1);
} else {
kf->nexthop.v4.s_addr = htonl(INADDR_LOOPBACK);
if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen,
- RTP_MINE)) == NULL) {
+ kf->priority)) == NULL) {
if (kroute_insert(kt, kf) == -1)
return (-1);
} else {
bcopy(&lo6, &kf->nexthop.v6, sizeof(kf->nexthop.v6));
if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen,
- RTP_MINE)) != NULL) {
+ kf->priority)) != NULL) {
if (kroute_insert(kt, kf) == -1)
return (-1);
} else {
if ((kt = ktable_get(rtableid)) == NULL)
/* too noisy during reloads, just ignore */
return (0);
-
+ kf->flags |= F_BGPD;
+ kf->priority = RTP_MINE;
switch (kf->prefix.aid) {
case AID_INET:
return (kr4_delete(kt, kf));
struct kroute *kr;
if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen,
- RTP_MINE)) == NULL)
+ kf->priority)) == NULL)
return (0);
if (!(kr->flags & F_BGPD_INSERTED))
struct kroute6 *kr6;
if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen,
- RTP_MINE)) == NULL)
+ kf->priority)) == NULL)
return (0);
if (!(kr6->flags & F_BGPD_INSERTED))
struct kroute *kr;
if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen,
- RTP_MINE)) == NULL)
+ kf->priority)) == NULL)
return (0);
if (!(kr->flags & F_BGPD_INSERTED))
struct kroute6 *kr6;
if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen,
- RTP_MINE)) == NULL)
+ kf->priority)) == NULL)
return (0);
if (!(kr6->flags & F_BGPD_INSERTED))
struct ktable *kt;
struct kroute *kr, *kn;
struct kroute6 *kr6, *kn6;
+ struct kroute_full *kf;
struct bgpd_addr *addr;
int flags;
sa_family_t af;
continue;
kn = kr;
do {
+ kf = kr_tofull(kn);
+ kf->priority = kr_priority(kf);
send_imsg_session(IMSG_CTL_KROUTE,
- imsg->hdr.pid, kr_tofull(kn),
- sizeof(struct kroute_full));
+ imsg->hdr.pid, kf, sizeof(*kf));
} while ((kn = kn->next) != NULL);
}
if (!af || af == AF_INET6)
continue;
kn6 = kr6;
do {
+ kf = kr6_tofull(kn6);
+ kf->priority = kr_priority(kf);
send_imsg_session(IMSG_CTL_KROUTE,
- imsg->hdr.pid, kr6_tofull(kn6),
- sizeof(struct kroute_full));
+ imsg->hdr.pid, kf, sizeof(*kf));
} while ((kn6 = kn6->next) != NULL);
}
break;
switch (addr->aid) {
case AID_INET:
kr = kroute_match(kt, addr, 1);
- if (kr != NULL)
+ if (kr != NULL) {
+ kf = kr_tofull(kr);
+ kf->priority = kr_priority(kf);
send_imsg_session(IMSG_CTL_KROUTE,
- imsg->hdr.pid, kr_tofull(kr),
- sizeof(struct kroute_full));
+ imsg->hdr.pid, kf, sizeof(*kf));
+ }
break;
case AID_INET6:
kr6 = kroute6_match(kt, addr, 1);
- if (kr6 != NULL)
+ if (kr6 != NULL) {
+ kf = kr6_tofull(kr6);
+ kf->priority = kr_priority(kf);
send_imsg_session(IMSG_CTL_KROUTE,
- imsg->hdr.pid, kr6_tofull(kr6),
- sizeof(struct kroute_full));
+ imsg->hdr.pid, kf, sizeof(*kf));
+ }
break;
}
break;
ifindex = kr6->ifindex;
break;
}
+ snh.kr.priority = kr_priority(&snh.kr);
if ((kif = kif_find(ifindex)) != NULL)
memcpy(&snh.iface,
kr_show_interface(&kif->k),
return;
}
- if (!(kf->flags & F_KERNEL))
+ if (kf->flags & F_BGPD)
return;
switch (kf->prefix.aid) {
return (0);
}
+uint8_t
+kr_priority(struct kroute_full *kf)
+{
+ if (kf->priority == RTP_MINE)
+ return kr_state.fib_prio;
+ return kf->priority;
+}
+
struct kroute_full *
kr_tofull(struct kroute *kr)
{
kf.flags = kr->flags;
kf.ifindex = kr->ifindex;
kf.prefixlen = kr->prefixlen;
- kf.priority = kr->priority == RTP_MINE ?
- kr_state.fib_prio : kr->priority;
+ kf.priority = kr->priority;
kf.mplslabel = kr->mplslabel;
return (&kf);
kf.flags = kr6->flags;
kf.ifindex = kr6->ifindex;
kf.prefixlen = kr6->prefixlen;
- kf.priority = kr6->priority == RTP_MINE ?
- kr_state.fib_prio : kr6->priority;
+ kf.priority = kr6->priority;
kf.mplslabel = kr6->mplslabel;
return (&kf);
}
/* XXX this is wrong for nexthop validated via BGP */
- if (kf->flags & F_KERNEL) {
+ if (!(kf->flags & F_BGPD)) {
RB_FOREACH(h, knexthop_tree, KT2KNT(kt))
if (prefix_compare(&kf->prefix, &h->nexthop,
kf->prefixlen) == 0)
if (s->kroute == kr)
knexthop_validate(kt, s);
- if (kr->flags & F_KERNEL && kr == krm && kr->next == NULL)
+ if (!(kr->flags & F_BGPD) && kr == krm && kr->next == NULL)
/* again remove only once */
kr_redistribute(IMSG_NETWORK_REMOVE, kt, kr_tofull(kr));
if (s->kroute == kr)
knexthop_validate(kt, s);
- if (kr->flags & F_KERNEL && kr == krm && kr->next == NULL)
+ if (!(kr->flags & F_BGPD) && kr == krm && kr->next == NULL)
/* again remove only once */
kr_redistribute(IMSG_NETWORK_REMOVE, kt, kr6_tofull(kr));
if (dispatch_rtmsg_addr(rtm, &kf) == -1)
continue;
- if (kf.priority == kr_state.fib_prio)
+ if (kf.priority == RTP_MINE)
send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kf);
else
kroute_insert(kt, &kf);
}
memset(kf, 0, sizeof(*kf));
- kf->flags = F_KERNEL;
if (rtm->rtm_flags & RTF_STATIC)
kf->flags |= F_STATIC;
if (rtm->rtm_flags & RTF_REJECT)
kf->flags |= F_REJECT;
- kf->priority = rtm->rtm_priority;
+ /* adjust priority here */
+ if (rtm->rtm_priority == kr_state.fib_prio)
+ kf->priority = RTP_MINE;
+ else
+ kf->priority = rtm->rtm_priority;
+
label = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL];
if (label != NULL)
if (strlcpy(kf->label, label->sr_label, sizeof(kf->label)) >=
if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen,
kf->priority)) == NULL)
return (0);
- if (!(kr->flags & F_KERNEL))
- return (0);
-
if (mpath) {
/* get the correct route */
if ((kr = kroute_matchgw(kr, &kf->nexthop)) == NULL) {
return (0);
}
}
+ if (kf->flags & F_BGPD) {
+ kr->flags &= ~F_BGPD_INSERTED;
+ return (0);
+ }
if (kroute_remove(kt, kr) == -1)
return (-1);
break;
if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen,
kf->priority)) == NULL)
return (0);
- if (!(kr6->flags & F_KERNEL))
- return (0);
-
if (mpath) {
/* get the correct route */
if ((kr6 = kroute6_matchgw(kr6, &kf->nexthop)) ==
return (0);
}
}
+ if (kf->flags & F_BGPD) {
+ kr6->flags &= ~F_BGPD_INSERTED;
+ return (0);
+ }
if (kroute6_remove(kt, kr6) == -1)
return (-1);
break;
case AID_INET:
if ((kr = kroute_find(kt, &kf->prefix, kf->prefixlen,
kf->priority)) != NULL) {
- if (kr->flags & F_KERNEL) {
+ if (!(kf->flags & F_BGPD)) {
/* get the correct route */
if (mpath && type == RTM_CHANGE &&
(kr = kroute_matchgw(kr, &kf->nexthop)) ==
kt, kr_tofull(kr));
if (kr->flags & F_NEXTHOP && changed)
knexthop_track(kt, kf->ifindex);
+ } else {
+ kr->flags &= ~F_BGPD_INSERTED;
}
} else {
add4:
case AID_INET6:
if ((kr6 = kroute6_find(kt, &kf->prefix, kf->prefixlen,
kf->priority)) != NULL) {
- if (kr6->flags & F_KERNEL) {
+ if (!(kf->flags & F_BGPD)) {
/* get the correct route */
if (mpath && type == RTM_CHANGE &&
(kr6 = kroute6_matchgw(kr6, &kf->nexthop))
if (kr6->flags & F_NEXTHOP && changed)
knexthop_track(kt, kf->ifindex);
+ } else {
+ kr6->flags &= ~F_BGPD_INSERTED;
}
} else {
add6: