summaryrefslogtreecommitdiff
path: root/usr.sbin/ldpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2010-03-25 12:05:19 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2010-03-25 12:05:19 +0000
commit07a0982ca6277541534cffe136bcf34aa10dd881 (patch)
tree667db48ea88cf56cb46c2a6f1e695329b108c40a /usr.sbin/ldpd
parent6d1ac969df84c0663a20365a39c3c7bf84633e8a (diff)
Kroute updates from the LDE are per FEC so do the lookup in kroute with
prefix/len and nexthop but do not consider the priority. send_rtmsg() needs to use the kroute element and not the one sent from the LDE since that one has no priority set (which is needed). This seems to solve a problem where ldpd modified the wrong routes. OK michele
Diffstat (limited to 'usr.sbin/ldpd')
-rw-r--r--usr.sbin/ldpd/kroute.c55
1 files changed, 41 insertions, 14 deletions
diff --git a/usr.sbin/ldpd/kroute.c b/usr.sbin/ldpd/kroute.c
index ab95aaac79b..37cbe5d3003 100644
--- a/usr.sbin/ldpd/kroute.c
+++ b/usr.sbin/ldpd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.8 2010/03/24 19:13:10 claudio Exp $ */
+/* $OpenBSD: kroute.c,v 1.9 2010/03/25 12:05:18 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -71,6 +71,7 @@ int kr_change_fib(struct kroute_node *, struct kroute *, int);
int kr_delete_fib(struct kroute_node *);
struct kroute_node *kroute_find(in_addr_t, u_int8_t, u_int8_t);
+struct kroute_node *kroute_find_fec(in_addr_t, u_int8_t, in_addr_t);
struct kroute_node *kroute_matchgw(struct kroute_node *, struct in_addr);
int kroute_insert(struct kroute_node *);
int kroute_remove(struct kroute_node *);
@@ -192,16 +193,6 @@ kr_change_fib(struct kroute_node *kr, struct kroute *kroute, int action)
htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
return (0);
- /* send update */
- if (send_rtmsg(kr_state.fd, action, kroute, AF_MPLS) == -1)
- return (-1);
-
- if (kroute->nexthop.s_addr != INADDR_ANY &&
- kroute->remote_label != NO_LABEL) {
- if (send_rtmsg(kr_state.fd, RTM_CHANGE, kroute, AF_INET) == -1)
- return (-1);
- }
-
kr->r.prefix.s_addr = kroute->prefix.s_addr;
kr->r.prefixlen = kroute->prefixlen;
kr->r.local_label = kroute->local_label;
@@ -212,6 +203,16 @@ kr_change_fib(struct kroute_node *kr, struct kroute *kroute, int action)
rtlabel_unref(kr->r.rtlabel); /* for RTM_CHANGE */
kr->r.rtlabel = kroute->rtlabel;
+ /* send update */
+ if (send_rtmsg(kr_state.fd, action, &kr->r, AF_MPLS) == -1)
+ return (-1);
+
+ if (kr->r.nexthop.s_addr != INADDR_ANY &&
+ kr->r.remote_label != NO_LABEL) {
+ if (send_rtmsg(kr_state.fd, RTM_CHANGE, &kr->r, AF_INET) == -1)
+ return (-1);
+ }
+
return (0);
}
@@ -223,7 +224,8 @@ kr_change(struct kroute *kroute)
kroute->rtlabel = rtlabel_tag2id(kroute->ext_tag);
- kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen, RTP_ANY);
+ kr = kroute_find_fec(kroute->prefix.s_addr, kroute->prefixlen,
+ kroute->nexthop.s_addr);
if (kr == NULL) {
log_warnx("kr_change: lost FEC %s/%d",
@@ -263,8 +265,9 @@ kr_delete(struct kroute *kroute)
{
struct kroute_node *kr, *nkr;
- if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen,
- kroute->priority)) == NULL)
+ kr = kroute_find_fec(kroute->prefix.s_addr, kroute->prefixlen,
+ kroute->nexthop.s_addr);
+ if (kr == NULL)
return (0);
if (kr_delete_fib(kr) == -1)
@@ -566,6 +569,30 @@ kroute_find(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio)
}
struct kroute_node *
+kroute_find_fec(in_addr_t prefix, u_int8_t prefixlen, in_addr_t nexthop)
+{
+ struct kroute_node s;
+ struct kroute_node *kn;
+
+ s.r.prefix.s_addr = prefix;
+ s.r.prefixlen = prefixlen;
+ s.r.priority = 0; /* trick to use RB_NFIND */
+
+ kn = RB_NFIND(kroute_tree, &krt, &s);
+ while (kn) {
+ if (kn->r.nexthop.s_addr == nexthop)
+ break;
+ kn = RB_NEXT(kroute_tree, &krt, kn);
+ if (kn == NULL || kn->r.prefix.s_addr != prefix ||
+ kn->r.prefixlen != prefixlen) {
+ kn = NULL;
+ break;
+ }
+ }
+ return (kn);
+}
+
+struct kroute_node *
kroute_matchgw(struct kroute_node *kr, struct in_addr nh)
{
in_addr_t nexthop;