summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ospfd/kroute.c80
-rw-r--r--usr.sbin/ospfd/ospfd.h7
-rw-r--r--usr.sbin/ospfd/rde.c23
3 files changed, 75 insertions, 35 deletions
diff --git a/usr.sbin/ospfd/kroute.c b/usr.sbin/ospfd/kroute.c
index 486302902b5..d707a3d3e3a 100644
--- a/usr.sbin/ospfd/kroute.c
+++ b/usr.sbin/ospfd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.25 2006/01/23 22:29:15 claudio Exp $ */
+/* $OpenBSD: kroute.c,v 1.26 2006/03/08 13:49:07 claudio Exp $ */
/*
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -166,10 +166,23 @@ kr_change(struct kroute *kroute)
if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen)) !=
NULL) {
- if (kr->r.flags & F_OSPFD_INSERTED)
+ if (!(kr->r.flags & F_KERNEL))
action = RTM_CHANGE;
- else /* a non-ospf route already exists. not a problem */
- return (0);
+ else { /* a non-ospf route already exists. not a problem */
+ if (!(kr->r.flags & F_BGPD_INSERTED)) {
+ kr->r.flags |= F_OSPFD_INSERTED;
+ return (0);
+ }
+ /*
+ * ospf route has higher pref
+ * - reset flags to the ospf ones
+ * - use RTM_CHANGE
+ * - zero out ifindex (this is no longer relevant)
+ */
+ action = RTM_CHANGE;
+ kr->r.flags = kroute->flags | F_OSPFD_INSERTED;
+ kr->r.ifindex = 0;
+ }
}
/* nexthop within 127/8 -> ignore silently */
@@ -210,10 +223,12 @@ kr_delete(struct kroute *kroute)
if (!(kr->r.flags & F_OSPFD_INSERTED))
return (0);
- /* nexthop within 127/8 -> ignore silently */
- if ((kroute->nexthop.s_addr & htonl(IN_CLASSA_NET)) ==
- htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
+ if (kr->r.flags & F_KERNEL) {
+ /* remove F_OSPFD_INSERTED flag, route still exists in kernel */
+ kr->r.flags &= ~F_OSPFD_INSERTED;
+ kr->r.ifindex = 0; /* ifindex is no longer relevant */
return (0);
+ }
if (send_rtmsg(kr_state.fd, RTM_DELETE, kroute) == -1)
return (-1);
@@ -243,7 +258,7 @@ kr_fib_couple(void)
kr_state.fib_sync = 1;
RB_FOREACH(kr, kroute_tree, &krt)
- if ((kr->r.flags & F_OSPFD_INSERTED))
+ if (!(kr->r.flags & F_KERNEL))
send_rtmsg(kr_state.fd, RTM_ADD, &kr->r);
log_info("kernel routing table coupled");
@@ -258,7 +273,7 @@ kr_fib_decouple(void)
return;
RB_FOREACH(kr, kroute_tree, &krt)
- if ((kr->r.flags & F_OSPFD_INSERTED))
+ if (!(kr->r.flags & F_KERNEL))
send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r);
kr_state.fib_sync = 0;
@@ -345,7 +360,7 @@ kr_redistribute(int type, struct kroute *kr)
}
/* Only non-ospfd routes are considered for redistribution. */
- if (kr->flags & F_OSPFD_INSERTED)
+ if (!(kr->flags & F_KERNEL))
return;
/* Dynamic routes are not redistributable. */
@@ -422,7 +437,7 @@ kroute_insert(struct kroute_node *kr)
return (-1);
}
- if (kr->r.flags & F_OSPFD_INSERTED) {
+ if (!(kr->r.flags & F_KERNEL)) {
/* don't validate or redistribute ospf route */
kr->r.flags &= ~F_DOWN;
return (0);
@@ -712,6 +727,9 @@ send_rtmsg(int fd, int action, struct kroute *kroute)
r.hdr.rtm_version = RTM_VERSION;
r.hdr.rtm_type = action;
r.hdr.rtm_flags = RTF_PROTO2;
+ if (action == RTM_CHANGE) /* force PROTO2 reset the other flags */
+ r.hdr.rtm_fmask =
+ RTF_PROTO2|RTF_PROTO1|RTF_REJECT|RTF_BLACKHOLE;
r.hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */
r.hdr.rtm_addrs = RTA_DST|RTA_GATEWAY|RTA_NETMASK;
r.prefix.sin_len = sizeof(r.prefix);
@@ -825,6 +843,8 @@ fetchtable(void)
kr->r.flags |= F_STATIC;
if (rtm->rtm_flags & RTF_DYNAMIC)
kr->r.flags |= F_DYNAMIC;
+ if (rtm->rtm_flags & RTF_PROTO1)
+ kr->r.flags |= F_BGPD_INSERTED;
if (sa_in != NULL) {
if (sa_in->sin_len == 0)
break;
@@ -1005,6 +1025,8 @@ dispatch_rtmsg(void)
flags |= F_STATIC;
if (rtm->rtm_flags & RTF_DYNAMIC)
flags |= F_DYNAMIC;
+ if (rtm->rtm_flags & RTF_PROTO1)
+ flags |= F_BGPD_INSERTED;
break;
default:
continue;
@@ -1034,24 +1056,21 @@ dispatch_rtmsg(void)
if ((kr = kroute_find(prefix.s_addr, prefixlen)) !=
NULL) {
- if (kr->r.flags & F_KERNEL) {
- kr->r.nexthop.s_addr = nexthop.s_addr;
- kr->r.flags = flags;
-
- if (kif_validate(kr->r.ifindex))
- kr->r.flags &= ~F_DOWN;
- else
- kr->r.flags |= F_DOWN;
-
- /* just readd, the RDE will care */
- kr_redistribute(IMSG_NETWORK_ADD,
- &kr->r);
- }
- } else if (rtm->rtm_type == RTM_CHANGE) {
- log_warnx("change req for %s/%u: not "
- "in table", inet_ntoa(prefix),
- prefixlen);
- continue;
+ /* ospf route overridden by kernel */
+ /* pref is not checked because this is forced */
+ if (kr->r.flags & F_OSPFD_INSERTED)
+ flags |= F_OSPFD_INSERTED;
+ kr->r.nexthop.s_addr = nexthop.s_addr;
+ kr->r.flags = flags;
+ kr->r.ifindex = ifindex;
+
+ if (kif_validate(kr->r.ifindex))
+ kr->r.flags &= ~F_DOWN;
+ else
+ kr->r.flags |= F_DOWN;
+
+ /* just readd, the RDE will care */
+ kr_redistribute(IMSG_NETWORK_ADD, &kr->r);
} else {
if ((kr = calloc(1,
sizeof(struct kroute_node))) == NULL) {
@@ -1073,6 +1092,9 @@ dispatch_rtmsg(void)
continue;
if (!(kr->r.flags & F_KERNEL))
continue;
+ if (kr->r.flags & F_OSPFD_INSERTED)
+ main_imsg_compose_rde(IMSG_KROUTE_GET, 0,
+ &kr->r, sizeof(struct kroute));
if (kroute_remove(kr) == -1)
return (-1);
break;
diff --git a/usr.sbin/ospfd/ospfd.h b/usr.sbin/ospfd/ospfd.h
index 59d729fd377..e14cf91eb2a 100644
--- a/usr.sbin/ospfd/ospfd.h
+++ b/usr.sbin/ospfd/ospfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfd.h,v 1.46 2006/02/24 21:06:47 norby Exp $ */
+/* $OpenBSD: ospfd.h,v 1.47 2006/03/08 13:49:07 claudio Exp $ */
/*
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -48,11 +48,11 @@
#define F_OSPFD_INSERTED 0x0001
#define F_KERNEL 0x0002
-#define F_CONNECTED 0x0004
+#define F_BGPD_INSERTED 0x0004
+#define F_CONNECTED 0x0008
#define F_DOWN 0x0010
#define F_STATIC 0x0020
#define F_DYNAMIC 0x0040
-#define F_LONGER 0x0080
#define F_REDISTRIBUTED 0x0100
#define REDISTRIBUTE_STATIC 0x01
@@ -119,6 +119,7 @@ enum imsg_type {
IMSG_CTL_END,
IMSG_KROUTE_CHANGE,
IMSG_KROUTE_DELETE,
+ IMSG_KROUTE_GET,
IMSG_IFINFO,
IMSG_NEIGHBOR_UP,
IMSG_NEIGHBOR_DOWN,
diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c
index 8b78008544e..4970f1207dc 100644
--- a/usr.sbin/ospfd/rde.c
+++ b/usr.sbin/ospfd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.40 2006/02/21 13:02:59 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.41 2006/03/08 13:49:07 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -560,11 +560,12 @@ rde_dispatch_imsg(int fd, short event, void *bula)
void
rde_dispatch_parent(int fd, short event, void *bula)
{
- struct imsgbuf *ibuf = bula;
struct imsg imsg;
+ struct kroute kr;
+ struct imsgbuf *ibuf = bula;
struct lsa *lsa;
struct vertex *v;
- struct kroute kr;
+ struct rt_node *rn;
int n;
switch (event) {
@@ -618,6 +619,22 @@ rde_dispatch_parent(int fd, short event, void *bula)
lsa_merge(nbrself, lsa, v);
}
break;
+ case IMSG_KROUTE_GET:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) {
+ log_warnx("rde_dispatch: wrong imsg len");
+ break;
+ }
+ memcpy(&kr, imsg.data, sizeof(kr));
+
+ if ((rn = rt_find(kr.prefix.s_addr, kr.prefixlen,
+ DT_NET)) != NULL)
+ rde_send_change_kroute(rn);
+ else
+ /* should not happen */
+ imsg_compose(ibuf_main, IMSG_KROUTE_DELETE, 0,
+ 0, &kr, sizeof(kr));
+
+ break;
default:
log_debug("rde_dispatch_parent: unexpected imsg %d",
imsg.hdr.type);