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.
--
: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 7 Jun 2022 17:05:37 -0000
@@ -130,7 +130,7 @@ 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 +138,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 +188,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 +1781,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 +1934,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 +3181,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,144 +3217,48 @@ 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)
- continue;
- /* Skip ARP/ND cache and broadcast routes. */
- if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
+ if (dispatch_rtmsg_addr(rtm, &kl) == -1)
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) {
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) {
+ } 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 (rtm->rtm_priority == kr_state.fib_prio) {
send_rt6msg(kr_state.fd, RTM_DELETE, kt,
&kr6->r);
@@ -3454,8 +3356,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 +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;
+
+ 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 +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)
{
- 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(kr, 0, sizeof(*kr));
+ kr->flags = F_KERNEL;
+
if (rtm->rtm_flags & RTF_STATIC)
- flags |= F_STATIC;
+ kr->flags |= F_STATIC;
if (rtm->rtm_flags & RTF_BLACKHOLE)
- flags |= F_BLACKHOLE;
+ kr->flags |= F_BLACKHOLE;
if (rtm->rtm_flags & RTF_REJECT)
- flags |= F_REJECT;
+ kr->flags |= F_REJECT;
if (rtm->rtm_flags & RTF_DYNAMIC)
- flags |= F_DYNAMIC;
-#ifdef RTF_MPATH
- if (rtm->rtm_flags & RTF_MPATH)
- mpath = 1;
-#endif
+ kr->flags |= F_DYNAMIC;
- prio = rtm->rtm_priority;
+ kr->priority = rtm->rtm_priority;
label = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL];
+ if (label != NULL)
+ if (strlcpy(kr->label, label->sr_label, sizeof(kr->label)) >=
+ sizeof(kr->label))
+ fatalx("rtm label overflow");
+ sa2addr(sa, &kr->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(
+ kr->prefixlen = mask2prefixlen(
sa_in->sin_addr.s_addr);
} else if (rtm->rtm_flags & RTF_HOST)
- prefixlen = 32;
+ kr->prefixlen = 32;
else
- prefixlen =
- prefixlen_classful(prefix.v4.s_addr);
+ kr->prefixlen =
+ prefixlen_classful(kr->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);
+ kr->prefixlen = mask2prefixlen6(sa_in6);
} else if (rtm->rtm_flags & RTF_HOST)
- prefixlen = 128;
+ kr->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(&kr->prefix), kr->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 */
+ kr->flags |= F_CONNECTED;
+ kr->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], &kr->nexthop, NULL);
break;
}
+ } else {
+ kr->flags |= F_CONNECTED;
+ kr->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 +3642,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 +3649,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 +3725,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 +3732,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;