On Wed, Jun 08, 2022 at 06:27:36PM +0200, Claudio Jeker wrote:
> On Wed, Jun 08, 2022 at 06:10:21PM +0200, Theo Buehler wrote:
> > On Wed, Jun 08, 2022 at 01:28:14PM +0200, Claudio Jeker wrote:
> > > The idea behind this diff is to use struct kroute_full in more places.
> > > Mainly when parsing route messages. This allows to factor out the pure
> > > route message parsing into dispatch_rtmsg_addr() and use it in both the
> > > gerneral routing socket code but also in fetchtables(). Which removes some
> > > duplicated code.
> > >
> > > As a second step then this kroute_full is applied to the kroute tree. Here
> > > I limited my changes to be minimal for now. A follow up will look more
> > > into kr_fib_change() and tries to streamline that code and the bits in
> > > fetchtable().
> > >
> > > Also struct kroute_full could be used in more places with the goal to have
> > > less mostly similar function for IPv4, IPv6 and the L3VPNs. Again this is
> > > for later.
> > >
> > > This should behave the same as before but dispatch_rtmsg_addr() decides
> > > now in a different way if a route is connected or not (using the
> > > RTF_GATEWAY flag for this). With this loopback routes show now up as
> > > connected. It should have no noticable impact on routing.
> > >
> > > Please give this a good test.
> >
> > I spent some time with this diff. This is outside my comfort zone. I'll
> > need to read this once more with a fresh head.
> >
> > I like the direction and less spaghetti is good.
> >
> > Some small remarks and questions inline.
>
> Thanks for looking into this. Not many people around that actually
> understand the route socket so I know this is way out of everyones comfort
> zone. The kroute code got hammered into shape and then copied around way
> to many times. A lot of the code is pure spahetti. I try to work with
> smaller diffs to make review somewhat possible.
>
> > > Index: kroute.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
> > > retrieving revision 1.251
> > > diff -u -p -r1.251 kroute.c
> > > --- kroute.c 7 Jun 2022 16:42:07 -0000 1.251
> > > +++ kroute.c 7 Jun 2022 17:05:37 -0000
> > > @@ -3482,23 +3385,34 @@ dispatch_rtmsg(u_int rdomain)
> > > case RTM_ADD:
> > > case RTM_CHANGE:
> > > case RTM_DELETE:
> > > - sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
> > > - get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
> > > -
> > > if (rtm->rtm_pid == kr_state.pid) /* cause by us */
> > > continue;
> > >
> > > - if (rtm->rtm_errno) /* failed attempts */
> > > - continue;
> > > + /* failed attempts */
> > > + if (rtm->rtm_errno || !(rtm->rtm_flags & RTF_DONE))
> > > + return (-1);
> > >
> > > - if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
> > > + if ((kt = ktable_get(rtm->rtm_tableid)) == NULL)
> > > continue;
> > >
> > > - if ((kt = ktable_get(rtm->rtm_tableid)) == NULL)
> > > + if (dispatch_rtmsg_addr(rtm, &kl) == -1)
> > > continue;
> > >
> > > - if (dispatch_rtmsg_addr(rtm, rti_info, kt) == -1)
> > > - return (-1);
> > > + if (rtm->rtm_flags & RTF_MPATH)
> > > + mpath = 1;
> >
> > I guess the #ifdef RTF_MPATH was dropped since kroute.c is no longer
> > built outside of OpenBSD with recent -portable changes?
>
> Yes, also the time when OpenBSD had no RTF_MPATH has long passed. So
> I see no reason to clutter this code with #ifdefs.
> For portable I would love to split the code further up so that the kroute
> code is portable but the routing socket bits are per platform. Right now
> changes to kroute.c are a pain since I need to track also the protable
> files.
>
> > > @@ -3517,191 +3431,190 @@ dispatch_rtmsg(u_int rdomain)
> > > }
> > >
> > > int
> > > -dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr
> > > *rti_info[RTAX_MAX],
> > > - struct ktable *kt)
> > > +dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct kroute_full *kr)
> >
> > This is the only kroute_full called kr in the entire file. I would
> > prefer calling it kl (or kf as in the older code you don't touch).
>
> Naming is hard. I agree using kl may be better here. Will adjust the code.
>
> > > case AF_INET:
> > > - prefix.aid = AID_INET;
> > > - prefix.v4.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
> > > sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
> > > if (sa_in != NULL) {
> > > if (sa_in->sin_len != 0)
> > > - prefixlen = mask2prefixlen(
> > > + kr->prefixlen = mask2prefixlen(
> > > sa_in->sin_addr.s_addr);
> >
> > I would wrap this the same way as the assignment a few lines down:
> >
> > kr->prefixlen =
> > mask2prefixlen(sa_in->sin_addr.s_addr);
>
> Yes, indeed.
>
> > > case AID_INET:
> > > - sa_in = (struct sockaddr_in *)sa;
> > > - if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen,
> > > - prio)) != NULL) {
> > > + if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen,
> > > + kl->priority)) != NULL) {
> > > if (kr->r.flags & F_KERNEL) {
> > > /* get the correct route */
> > > - if (mpath && rtm->rtm_type == RTM_CHANGE &&
> > > - (kr = kroute_matchgw(kr, sa_in)) == NULL) {
> > > + if (mpath && type == RTM_CHANGE &&
> > > + (kr = kroute_matchgw(kr, &kl->nexthop)) ==
> > > + NULL) {
> > > log_warnx("%s[change]: "
> > > "mpath route not found", __func__);
> > > goto add4;
> > > - } else if (mpath && rtm->rtm_type == RTM_ADD)
> > > + } else if (mpath && type == RTM_ADD)
> > > goto add4;
> > >
> > > - if (sa_in != NULL) {
> > > + if (kl->nexthop.aid == AID_INET) {
> > > if (kr->r.nexthop.s_addr !=
> > > - sa_in->sin_addr.s_addr)
> > > + kl->nexthop.v4.s_addr)
> > > changed = 1;
> > > kr->r.nexthop.s_addr =
> > > - sa_in->sin_addr.s_addr;
> > > + kl->nexthop.v4.s_addr;
> >
> > why is there no kr->r.ifindex assignment here?
>
> I don't know. The old code was already like this. I remember that ifindex
> was unreliable in the old times but again that is like 5+ years ago.
> I did not want to introduce code changes which I'm sure wont cause
> trouble. I think this is something to tackle at a later stage.
>
> --
> :wq Claudio
and here is the updated diff I forgot to include
--
:wq Claudio
Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.251
diff -u -p -r1.251 kroute.c
--- kroute.c 7 Jun 2022 16:42:07 -0000 1.251
+++ kroute.c 8 Jun 2022 16:23:51 -0000
@@ -125,12 +125,11 @@ int kroute6_compare(struct kroute6_node
int knexthop_compare(struct knexthop_node *, struct knexthop_node *);
int kredist_compare(struct kredist_node *, struct kredist_node *);
int kif_compare(struct kif_node *, struct kif_node *);
-void kr_fib_update_prio(u_int, uint8_t);
struct kroute_node *kroute_find(struct ktable *, in_addr_t, uint8_t,
uint8_t);
struct kroute_node *kroute_matchgw(struct kroute_node *,
- struct sockaddr_in *);
+ struct bgpd_addr *);
int kroute_insert(struct ktable *, struct kroute_node *);
int kroute_remove(struct ktable *, struct kroute_node *);
void kroute_clear(struct ktable *);
@@ -138,7 +137,7 @@ void kroute_clear(struct ktable *);
struct kroute6_node *kroute6_find(struct ktable *, const struct in6_addr *,
uint8_t, uint8_t);
struct kroute6_node *kroute6_matchgw(struct kroute6_node *,
- struct sockaddr_in6 *);
+ struct bgpd_addr *);
int kroute6_insert(struct ktable *, struct kroute6_node *);
int kroute6_remove(struct ktable *, struct kroute6_node *);
void kroute6_clear(struct ktable *);
@@ -188,8 +187,9 @@ int send_rt6msg(int, int, struct ktable
int dispatch_rtmsg(u_int);
int fetchtable(struct ktable *);
int fetchifs(int);
-int dispatch_rtmsg_addr(struct rt_msghdr *,
- struct sockaddr *[RTAX_MAX], struct ktable *);
+int dispatch_rtmsg_addr(struct rt_msghdr *, struct kroute_full *);
+int kr_fib_delete(struct ktable *, struct kroute_full *, int);
+int kr_fib_change(struct ktable *, struct kroute_full *, int, int);
RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare)
RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare)
@@ -1780,21 +1780,21 @@ kroute_find(struct ktable *kt, in_addr_t
}
struct kroute_node *
-kroute_matchgw(struct kroute_node *kr, struct sockaddr_in *sa_in)
+kroute_matchgw(struct kroute_node *kr, struct bgpd_addr *gw)
{
in_addr_t nexthop;
- if (sa_in == NULL) {
+ if (gw->aid != AID_INET) {
log_warnx("%s: no nexthop defined", __func__);
return (NULL);
}
- nexthop = sa_in->sin_addr.s_addr;
+ nexthop = gw->v4.s_addr;
- while (kr) {
+ do {
if (kr->r.nexthop.s_addr == nexthop)
return (kr);
kr = kr->next;
- }
+ } while (kr);
return (NULL);
}
@@ -1933,21 +1933,21 @@ kroute6_find(struct ktable *kt, const st
}
struct kroute6_node *
-kroute6_matchgw(struct kroute6_node *kr, struct sockaddr_in6 *sa_in6)
+kroute6_matchgw(struct kroute6_node *kr, struct bgpd_addr *gw)
{
struct in6_addr nexthop;
- if (sa_in6 == NULL) {
+ if (gw->aid != AID_INET6) {
log_warnx("%s: no nexthop defined", __func__);
return (NULL);
}
- memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop));
+ nexthop = gw->v6;
- while (kr) {
+ do {
if (memcmp(&kr->r.nexthop, &nexthop, sizeof(nexthop)) == 0)
return (kr);
kr = kr->next;
- }
+ } while (kr);
return (NULL);
}
@@ -3180,12 +3180,9 @@ fetchtable(struct ktable *kt)
int mib[7];
char *buf = NULL, *next, *lim;
struct rt_msghdr *rtm;
- struct sockaddr *sa, *gw, *rti_info[RTAX_MAX];
- struct sockaddr_in *sa_in;
- struct sockaddr_in6 *sa_in6;
- struct sockaddr_rtlabel *label;
- struct kroute_node *kr = NULL;
- struct kroute6_node *kr6 = NULL;
+ struct kroute_full kl;
+ struct kroute_node *kr;
+ struct kroute6_node *kr6;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
@@ -3219,145 +3216,49 @@ fetchtable(struct ktable *kt)
rtm = (struct rt_msghdr *)next;
if (rtm->rtm_version != RTM_VERSION)
continue;
- sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
- get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
- if ((sa = rti_info[RTAX_DST]) == NULL)
+ if (dispatch_rtmsg_addr(rtm, &kl) == -1)
continue;
- /* Skip ARP/ND cache and broadcast routes. */
- if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
- continue;
-
- switch (sa->sa_family) {
- case AF_INET:
- if ((kr = calloc(1, sizeof(struct kroute_node))) ==
- NULL) {
- log_warn("%s", __func__);
- free(buf);
- return (-1);
- }
-
- kr->r.flags = F_KERNEL;
- kr->r.priority = rtm->rtm_priority;
- kr->r.ifindex = rtm->rtm_index;
- kr->r.prefix.s_addr =
- ((struct sockaddr_in *)sa)->sin_addr.s_addr;
- sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
- if (rtm->rtm_flags & RTF_STATIC)
- kr->r.flags |= F_STATIC;
- if (rtm->rtm_flags & RTF_BLACKHOLE)
- kr->r.flags |= F_BLACKHOLE;
- if (rtm->rtm_flags & RTF_REJECT)
- kr->r.flags |= F_REJECT;
- if (rtm->rtm_flags & RTF_DYNAMIC)
- kr->r.flags |= F_DYNAMIC;
- if (sa_in != NULL) {
- if (sa_in->sin_len == 0)
- break;
- kr->r.prefixlen =
- mask2prefixlen(sa_in->sin_addr.s_addr);
- } else if (rtm->rtm_flags & RTF_HOST)
- kr->r.prefixlen = 32;
- else
- kr->r.prefixlen =
- prefixlen_classful(kr->r.prefix.s_addr);
- if ((label = (struct sockaddr_rtlabel *)
- rti_info[RTAX_LABEL]) != NULL) {
- kr->r.labelid =
- rtlabel_name2id(label->sr_label);
- }
- break;
- case AF_INET6:
- if ((kr6 = calloc(1, sizeof(struct kroute6_node))) ==
- NULL) {
+ if (kl.prefix.aid == AID_INET) {
+ if ((kr = calloc(1,
+ sizeof(struct kroute_node))) == NULL) {
log_warn("%s", __func__);
- free(buf);
return (-1);
}
+ kr->r.prefix.s_addr = kl.prefix.v4.s_addr;
+ kr->r.prefixlen = kl.prefixlen;
+ if (kl.nexthop.aid == AID_INET)
+ kr->r.nexthop.s_addr = kl.nexthop.v4.s_addr;
+ kr->r.flags = kl.flags;
+ kr->r.ifindex = kl.ifindex;
+ kr->r.priority = kl.priority;
+ kr->r.labelid = rtlabel_name2id(kl.label);
- kr6->r.flags = F_KERNEL;
- kr6->r.priority = rtm->rtm_priority;
- kr6->r.ifindex = rtm->rtm_index;
- memcpy(&kr6->r.prefix,
- &((struct sockaddr_in6 *)sa)->sin6_addr,
- sizeof(kr6->r.prefix));
-
- sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
- if (rtm->rtm_flags & RTF_STATIC)
- kr6->r.flags |= F_STATIC;
- if (rtm->rtm_flags & RTF_BLACKHOLE)
- kr6->r.flags |= F_BLACKHOLE;
- if (rtm->rtm_flags & RTF_REJECT)
- kr6->r.flags |= F_REJECT;
- if (rtm->rtm_flags & RTF_DYNAMIC)
- kr6->r.flags |= F_DYNAMIC;
- if (sa_in6 != NULL) {
- if (sa_in6->sin6_len == 0)
- break;
- kr6->r.prefixlen = mask2prefixlen6(sa_in6);
- } else if (rtm->rtm_flags & RTF_HOST)
- kr6->r.prefixlen = 128;
- else
- fatalx("INET6 route without netmask");
- if ((label = (struct sockaddr_rtlabel *)
- rti_info[RTAX_LABEL]) != NULL) {
- kr6->r.labelid =
- rtlabel_name2id(label->sr_label);
- }
- break;
- default:
- continue;
- }
-
- if ((gw = rti_info[RTAX_GATEWAY]) != NULL)
- switch (gw->sa_family) {
- case AF_INET:
- if (kr == NULL)
- fatalx("v4 gateway for !v4 dst?!");
-
- if (rtm->rtm_flags & RTF_CONNECTED) {
- kr->r.flags |= F_CONNECTED;
- break;
- }
-
- kr->r.nexthop.s_addr =
- ((struct sockaddr_in *)gw)->sin_addr.s_addr;
- break;
- case AF_INET6:
- if (kr6 == NULL)
- fatalx("v6 gateway for !v6 dst?!");
-
- if (rtm->rtm_flags & RTF_CONNECTED) {
- kr6->r.flags |= F_CONNECTED;
- break;
- }
-
- memcpy(&kr6->r.nexthop,
- &((struct sockaddr_in6 *)gw)->sin6_addr,
- sizeof(kr6->r.nexthop));
- break;
- case AF_LINK:
- /*
- * Traditional BSD connected routes have
- * a gateway of type AF_LINK.
- */
- if (sa->sa_family == AF_INET)
- kr->r.flags |= F_CONNECTED;
- else if (sa->sa_family == AF_INET6)
- kr6->r.flags |= F_CONNECTED;
- break;
- }
-
- if (sa->sa_family == AF_INET) {
- if (rtm->rtm_priority == kr_state.fib_prio) {
+ if (kl.priority == kr_state.fib_prio) {
send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r);
rtlabel_unref(kr->r.labelid);
free(kr);
} else
kroute_insert(kt, kr);
- } else if (sa->sa_family == AF_INET6) {
- if (rtm->rtm_priority == kr_state.fib_prio) {
+ } else if (kl.prefix.aid == AID_INET6) {
+ if ((kr6 = calloc(1,
+ sizeof(struct kroute6_node))) == NULL) {
+ log_warn("%s", __func__);
+ return (-1);
+ }
+ kr6->r.prefix = kl.prefix.v6;
+ kr6->r.prefixlen = kl.prefixlen;
+ if (kl.nexthop.aid == AID_INET6)
+ kr6->r.nexthop = kl.nexthop.v6;
+ else
+ kr6->r.nexthop = in6addr_any;
+ kr6->r.flags = kl.flags;
+ kr6->r.ifindex = kl.ifindex;
+ kr6->r.priority = kl.priority;
+ kr6->r.labelid = rtlabel_name2id(kl.label);
+
+ if (kl.priority == kr_state.fib_prio) {
send_rt6msg(kr_state.fd, RTM_DELETE, kt,
&kr6->r);
rtlabel_unref(kr6->r.labelid);
@@ -3454,8 +3355,9 @@ dispatch_rtmsg(u_int rdomain)
char *next, *lim;
struct rt_msghdr *rtm;
struct if_msghdr ifm;
- struct sockaddr *sa, *rti_info[RTAX_MAX];
+ struct kroute_full kl;
struct ktable *kt;
+ int mpath = 0;
if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
if (errno == EAGAIN || errno == EINTR)
@@ -3482,23 +3384,34 @@ dispatch_rtmsg(u_int rdomain)
case RTM_ADD:
case RTM_CHANGE:
case RTM_DELETE:
- sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
- get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
-
if (rtm->rtm_pid == kr_state.pid) /* cause by us */
continue;
- if (rtm->rtm_errno) /* failed attempts */
- continue;
+ /* failed attempts */
+ if (rtm->rtm_errno || !(rtm->rtm_flags & RTF_DONE))
+ return (-1);
- if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
+ if ((kt = ktable_get(rtm->rtm_tableid)) == NULL)
continue;
- if ((kt = ktable_get(rtm->rtm_tableid)) == NULL)
+ if (dispatch_rtmsg_addr(rtm, &kl) == -1)
continue;
- if (dispatch_rtmsg_addr(rtm, rti_info, kt) == -1)
- return (-1);
+ if (rtm->rtm_flags & RTF_MPATH)
+ mpath = 1;
+
+ switch (rtm->rtm_type) {
+ case RTM_ADD:
+ case RTM_CHANGE:
+ if (kr_fib_change(kt, &kl, rtm->rtm_type,
+ mpath) == -1)
+ return -1;
+ break;
+ case RTM_DELETE:
+ if (kr_fib_delete(kt, &kl, mpath) == -1)
+ return -1;
+ break;
+ }
break;
case RTM_IFINFO:
memcpy(&ifm, next, sizeof(ifm));
@@ -3517,191 +3430,190 @@ dispatch_rtmsg(u_int rdomain)
}
int
-dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX],
- struct ktable *kt)
+dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct kroute_full *kl)
{
- struct sockaddr *sa;
+ struct sockaddr *sa, *rti_info[RTAX_MAX];
struct sockaddr_in *sa_in;
struct sockaddr_in6 *sa_in6;
struct sockaddr_rtlabel *label;
- struct kroute_node *kr;
- struct kroute6_node *kr6;
- struct bgpd_addr prefix;
- int flags, oflags, mpath = 0, changed = 0;
- int rtlabel_changed = 0;
- uint16_t ifindex, new_labelid;
- uint8_t prefixlen;
- uint8_t prio;
-
- flags = F_KERNEL;
- ifindex = 0;
- prefixlen = 0;
- bzero(&prefix, sizeof(prefix));
+
+ sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
+ get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
+
+ /* Skip ARP/ND cache and broadcast routes. */
+ if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
+ return (-1);
if ((sa = rti_info[RTAX_DST]) == NULL) {
- log_warnx("empty route message");
- return (0);
+ log_warnx("route message without destination");
+ return (-1);
}
+ memset(kl, 0, sizeof(*kl));
+ kl->flags = F_KERNEL;
+
if (rtm->rtm_flags & RTF_STATIC)
- flags |= F_STATIC;
+ kl->flags |= F_STATIC;
if (rtm->rtm_flags & RTF_BLACKHOLE)
- flags |= F_BLACKHOLE;
+ kl->flags |= F_BLACKHOLE;
if (rtm->rtm_flags & RTF_REJECT)
- flags |= F_REJECT;
+ kl->flags |= F_REJECT;
if (rtm->rtm_flags & RTF_DYNAMIC)
- flags |= F_DYNAMIC;
-#ifdef RTF_MPATH
- if (rtm->rtm_flags & RTF_MPATH)
- mpath = 1;
-#endif
+ kl->flags |= F_DYNAMIC;
- prio = rtm->rtm_priority;
+ kl->priority = rtm->rtm_priority;
label = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL];
+ if (label != NULL)
+ if (strlcpy(kl->label, label->sr_label, sizeof(kl->label)) >=
+ sizeof(kl->label))
+ fatalx("rtm label overflow");
+ sa2addr(sa, &kl->prefix, NULL);
switch (sa->sa_family) {
case AF_INET:
- prefix.aid = AID_INET;
- prefix.v4.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
if (sa_in != NULL) {
if (sa_in->sin_len != 0)
- prefixlen = mask2prefixlen(
- sa_in->sin_addr.s_addr);
+ kl->prefixlen =
+ mask2prefixlen(sa_in->sin_addr.s_addr);
} else if (rtm->rtm_flags & RTF_HOST)
- prefixlen = 32;
+ kl->prefixlen = 32;
else
- prefixlen =
- prefixlen_classful(prefix.v4.s_addr);
+ kl->prefixlen =
+ prefixlen_classful(kl->prefix.v4.s_addr);
break;
case AF_INET6:
- prefix.aid = AID_INET6;
- memcpy(&prefix.v6, &((struct sockaddr_in6 *)sa)->sin6_addr,
- sizeof(struct in6_addr));
sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
if (sa_in6 != NULL) {
if (sa_in6->sin6_len != 0)
- prefixlen = mask2prefixlen6(sa_in6);
+ kl->prefixlen = mask2prefixlen6(sa_in6);
} else if (rtm->rtm_flags & RTF_HOST)
- prefixlen = 128;
+ kl->prefixlen = 128;
else
fatalx("in6 net addr without netmask");
break;
default:
- return (0);
+ return (-1);
}
- if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
+ if ((sa = rti_info[RTAX_GATEWAY]) == NULL) {
+ log_warnx("route %s/%u without gateway",
+ log_addr(&kl->prefix), kl->prefixlen);
+ return (-1);
+ }
+
+ if (rtm->rtm_flags & RTF_GATEWAY) {
switch (sa->sa_family) {
case AF_LINK:
- flags |= F_CONNECTED;
- ifindex = rtm->rtm_index;
- sa = NULL;
- mpath = 0; /* link local stuff can't be mpath */
+ kl->flags |= F_CONNECTED;
+ kl->ifindex = rtm->rtm_index;
break;
case AF_INET:
case AF_INET6:
- if (rtm->rtm_flags & RTF_CONNECTED) {
- flags |= F_CONNECTED;
- ifindex = rtm->rtm_index;
- sa = NULL;
- mpath = 0; /* link local stuff can't be mpath */
- }
+ sa2addr(rti_info[RTAX_GATEWAY], &kl->nexthop, NULL);
break;
}
+ } else {
+ kl->flags |= F_CONNECTED;
+ kl->ifindex = rtm->rtm_index;
+ }
- if (rtm->rtm_type == RTM_DELETE) {
- switch (prefix.aid) {
- case AID_INET:
- sa_in = (struct sockaddr_in *)sa;
- if ((kr = kroute_find(kt, prefix.v4.s_addr,
- prefixlen, prio)) == NULL)
- return (0);
- if (!(kr->r.flags & F_KERNEL))
- return (0);
+ return (0);
+}
- if (mpath)
- /* get the correct route */
- if ((kr = kroute_matchgw(kr, sa_in)) == NULL) {
- log_warnx("%s[delete]: "
- "mpath route not found", __func__);
- return (0);
- }
+int
+kr_fib_delete(struct ktable *kt, struct kroute_full *kl, int mpath)
+{
+ struct kroute_node *kr;
+ struct kroute6_node *kr6;
- if (kroute_remove(kt, kr) == -1)
- return (-1);
- break;
- case AID_INET6:
- sa_in6 = (struct sockaddr_in6 *)sa;
- if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen,
- prio)) == NULL)
- return (0);
- if (!(kr6->r.flags & F_KERNEL))
- return (0);
+ switch (kl->prefix.aid) {
+ case AID_INET:
+ if ((kr = kroute_find(kt, kl->prefix.v4.s_addr,
+ kl->prefixlen, kl->priority)) == NULL)
+ return (0);
+ if (!(kr->r.flags & F_KERNEL))
+ return (0);
- if (mpath)
- /* get the correct route */
- if ((kr6 = kroute6_matchgw(kr6, sa_in6)) ==
- NULL) {
- log_warnx("%s[delete]: IPv6 mpath "
- "route not found", __func__);
- return (0);
- }
+ if (mpath) {
+ /* get the correct route */
+ if ((kr = kroute_matchgw(kr, &kl->nexthop)) == NULL) {
+ log_warnx("delete %s/%u: route not found",
+ log_addr(&kl->prefix), kl->prefixlen);
+ return (0);
+ }
+ }
+ if (kroute_remove(kt, kr) == -1)
+ return (-1);
+ break;
+ case AID_INET6:
+ if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen,
+ kl->priority)) == NULL)
+ return (0);
+ if (!(kr6->r.flags & F_KERNEL))
+ return (0);
- if (kroute6_remove(kt, kr6) == -1)
- return (-1);
- break;
+ if (mpath) {
+ /* get the correct route */
+ if ((kr6 = kroute6_matchgw(kr6, &kl->nexthop)) ==
+ NULL) {
+ log_warnx("delete %s/%u: route not found",
+ log_addr(&kl->prefix), kl->prefixlen);
+ return (0);
+ }
}
- return (0);
+ if (kroute6_remove(kt, kr6) == -1)
+ return (-1);
+ break;
}
+ return (0);
+}
- if (sa == NULL && !(flags & F_CONNECTED)) {
- log_warnx("%s: no nexthop for %s/%u",
- __func__, log_addr(&prefix), prefixlen);
- return (0);
- }
+int
+kr_fib_change(struct ktable *kt, struct kroute_full *kl, int type, int mpath)
+{
+ struct kroute_node *kr;
+ struct kroute6_node *kr6;
+ int flags, oflags;
+ int changed = 0, rtlabel_changed = 0;
+ uint16_t new_labelid;
- switch (prefix.aid) {
+ flags = kl->flags;
+ switch (kl->prefix.aid) {
case AID_INET:
- sa_in = (struct sockaddr_in *)sa;
- if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen,
- prio)) != NULL) {
+ if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen,
+ kl->priority)) != NULL) {
if (kr->r.flags & F_KERNEL) {
/* get the correct route */
- if (mpath && rtm->rtm_type == RTM_CHANGE &&
- (kr = kroute_matchgw(kr, sa_in)) == NULL) {
+ if (mpath && type == RTM_CHANGE &&
+ (kr = kroute_matchgw(kr, &kl->nexthop)) ==
+ NULL) {
log_warnx("%s[change]: "
"mpath route not found", __func__);
goto add4;
- } else if (mpath && rtm->rtm_type == RTM_ADD)
+ } else if (mpath && type == RTM_ADD)
goto add4;
- if (sa_in != NULL) {
+ if (kl->nexthop.aid == AID_INET) {
if (kr->r.nexthop.s_addr !=
- sa_in->sin_addr.s_addr)
+ kl->nexthop.v4.s_addr)
changed = 1;
kr->r.nexthop.s_addr =
- sa_in->sin_addr.s_addr;
+ kl->nexthop.v4.s_addr;
} else {
if (kr->r.nexthop.s_addr != 0)
changed = 1;
kr->r.nexthop.s_addr = 0;
+ kr->r.ifindex = kl->ifindex;
}
if (kr->r.flags & F_NEXTHOP)
flags |= F_NEXTHOP;
- if (label != NULL) {
- new_labelid =
- rtlabel_name2id(label->sr_label);
- if (kr->r.labelid != new_labelid) {
- rtlabel_unref(kr->r.labelid);
- kr->r.labelid = new_labelid;
- rtlabel_changed = 1;
- }
- } else if (kr->r.labelid) {
+ new_labelid = rtlabel_name2id(kl->label);
+ if (kr->r.labelid != new_labelid) {
rtlabel_unref(kr->r.labelid);
- kr->r.labelid = 0;
+ kr->r.labelid = new_labelid;
rtlabel_changed = 1;
}
@@ -3729,10 +3641,6 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
if (kr->r.flags & F_NEXTHOP && changed)
knexthop_track(kt, kr);
}
- } else if (rtm->rtm_type == RTM_CHANGE) {
- log_warnx("%s: change req for %s/%u: not in table",
- __func__, log_addr(&prefix), prefixlen);
- return (0);
} else {
add4:
if ((kr = calloc(1,
@@ -3740,70 +3648,54 @@ add4:
log_warn("%s", __func__);
return (-1);
}
- kr->r.prefix.s_addr = prefix.v4.s_addr;
- kr->r.prefixlen = prefixlen;
- if (sa_in != NULL)
- kr->r.nexthop.s_addr = sa_in->sin_addr.s_addr;
- else
- kr->r.nexthop.s_addr = 0;
+ kr->r.prefix.s_addr = kl->prefix.v4.s_addr;
+ kr->r.prefixlen = kl->prefixlen;
+ if (kl->nexthop.aid == AID_INET)
+ kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
kr->r.flags = flags;
- kr->r.ifindex = ifindex;
- kr->r.priority = prio;
+ kr->r.ifindex = kl->ifindex;
+ kr->r.priority = kl->priority;
+ kr->r.labelid = rtlabel_name2id(kl->label);
- if (label) {
- kr->r.labelid =
- rtlabel_name2id(label->sr_label);
- }
kroute_insert(kt, kr);
}
break;
case AID_INET6:
- sa_in6 = (struct sockaddr_in6 *)sa;
- if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen, prio)) !=
- NULL) {
+ if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen,
+ kl->priority)) != NULL) {
if (kr6->r.flags & F_KERNEL) {
/* get the correct route */
- if (mpath && rtm->rtm_type == RTM_CHANGE &&
- (kr6 = kroute6_matchgw(kr6, sa_in6)) ==
- NULL) {
+ if (mpath && type == RTM_CHANGE &&
+ (kr6 = kroute6_matchgw(kr6, &kl->nexthop))
+ == NULL) {
log_warnx("%s[change]: IPv6 mpath "
"route not found", __func__);
goto add6;
- } else if (mpath && rtm->rtm_type == RTM_ADD)
+ } else if (mpath && type == RTM_ADD)
goto add6;
- if (sa_in6 != NULL) {
+ if (kl->nexthop.aid == AID_INET6) {
if (memcmp(&kr6->r.nexthop,
- &sa_in6->sin6_addr,
+ &kl->nexthop.v6,
sizeof(struct in6_addr)))
changed = 1;
- memcpy(&kr6->r.nexthop,
- &sa_in6->sin6_addr,
- sizeof(struct in6_addr));
+ kr6->r.nexthop = kl->nexthop.v6;
} else {
if (memcmp(&kr6->r.nexthop,
&in6addr_any,
sizeof(struct in6_addr)))
changed = 1;
- memcpy(&kr6->r.nexthop,
- &in6addr_any,
- sizeof(struct in6_addr));
+ kr6->r.nexthop = in6addr_any;
+ kr6->r.ifindex = kl->ifindex;
}
if (kr6->r.flags & F_NEXTHOP)
flags |= F_NEXTHOP;
- if (label != NULL) {
- new_labelid =
- rtlabel_name2id(label->sr_label);
- if (kr6->r.labelid != new_labelid) {
- rtlabel_unref(kr6->r.labelid);
- kr6->r.labelid = new_labelid;
- rtlabel_changed = 1;
- }
- } else if (kr6->r.labelid) {
+ new_labelid = rtlabel_name2id(kl->label);
+ if (kr6->r.labelid != new_labelid) {
rtlabel_unref(kr6->r.labelid);
- kr6->r.labelid = 0;
+ kr6->r.labelid = new_labelid;
rtlabel_changed = 1;
}
@@ -3832,10 +3724,6 @@ add4:
if (kr6->r.flags & F_NEXTHOP && changed)
knexthop_track(kt, kr6);
}
- } else if (rtm->rtm_type == RTM_CHANGE) {
- log_warnx("%s: change req for %s/%u: not in table",
- __func__, log_addr(&prefix), prefixlen);
- return (0);
} else {
add6:
if ((kr6 = calloc(1,
@@ -3843,23 +3731,17 @@ add6:
log_warn("%s", __func__);
return (-1);
}
- memcpy(&kr6->r.prefix, &prefix.v6,
- sizeof(struct in6_addr));
- kr6->r.prefixlen = prefixlen;
- if (sa_in6 != NULL)
- memcpy(&kr6->r.nexthop, &sa_in6->sin6_addr,
- sizeof(struct in6_addr));
+ kr6->r.prefix = kl->prefix.v6;
+ kr6->r.prefixlen = kl->prefixlen;
+ if (kl->nexthop.aid == AID_INET6)
+ kr6->r.nexthop = kl->nexthop.v6;
else
- memcpy(&kr6->r.nexthop, &in6addr_any,
- sizeof(struct in6_addr));
+ kr6->r.nexthop = in6addr_any;
kr6->r.flags = flags;
- kr6->r.ifindex = ifindex;
- kr6->r.priority = prio;
+ kr6->r.ifindex = kl->ifindex;
+ kr6->r.priority = kl->priority;
+ kr6->r.labelid = rtlabel_name2id(kl->label);
- if (label) {
- kr6->r.labelid =
- rtlabel_name2id(label->sr_label);
- }
kroute6_insert(kt, kr6);
}
break;