summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.h11
-rw-r--r--usr.sbin/bgpd/kroute.c140
2 files changed, 144 insertions, 7 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index e5ec3141b9c..be7be7af8df 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.25 2003/12/25 17:07:24 henning Exp $ */
+/* $OpenBSD: bgpd.h,v 1.26 2003/12/25 23:15:58 henning Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -248,6 +248,13 @@ struct kroute {
in_addr_t nexthop;
};
+struct kroute_nexthop {
+ in_addr_t nexthop;
+ u_int8_t valid;
+ u_int8_t connected;
+ in_addr_t gateway;
+};
+
/* prototypes */
/* session.c */
int session_main(struct bgpd_config *, int[2], int[2]);
@@ -303,5 +310,7 @@ int kroute_change(int, struct kroute *);
int kroute_delete(int, struct kroute *);
void kroute_shutdown(int);
void kroute_dispatch_msg(int);
+void kroute_validate_nexthop(in_addr_t, struct kroute_nexthop *);
+void kroute_nexthop_check(in_addr_t);
#endif /* __BGPD_H__ */
diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c
index 42f76b39f62..8298302f89b 100644
--- a/usr.sbin/bgpd/kroute.c
+++ b/usr.sbin/bgpd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.20 2003/12/25 19:24:46 henning Exp $ */
+/* $OpenBSD: kroute.c,v 1.21 2003/12/25 23:15:58 henning Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -35,9 +35,15 @@
#include "bgpd.h"
struct kroute_node {
- RB_ENTRY(kroute_node) entry;
- struct kroute r;
- int flags;
+ RB_ENTRY(kroute_node) entry;
+ struct kroute r;
+ int flags;
+};
+
+struct knexthop_node {
+ RB_ENTRY(knexthop_node) entry;
+ struct kroute_nexthop nh;
+ struct kroute_node *kroute;
};
int kroute_msg(int, int, struct kroute *);
@@ -46,17 +52,27 @@ void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
u_int8_t prefixlen_classful(in_addr_t);
u_int8_t mask2prefixlen(in_addr_t);
int kroute_fetchtable(void);
+int knexthop_compare(struct knexthop_node *,
+ struct knexthop_node *);
+void kroute_remove(struct kroute_node *);
+
+struct kroute_node * kroute_match(in_addr_t);
RB_HEAD(kroute_tree, kroute_node) kroute_tree, krt;
RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare);
RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare);
+RB_HEAD(knexthop_tree, knexthop_node) knexthop_tree, knt;
+RB_PROTOTYPE(knexthop_tree, knexthop_node, entry, knexthop_compare);
+RB_GENERATE(knexthop_tree, knexthop_node, entry, knexthop_compare);
+
u_int32_t rtseq = 1;
pid_t pid;
#define F_BGPD_INSERTED 0x0001
#define F_KERNEL 0x0002
#define F_CONNECTED 0x0004
+#define F_NEXTHOP 0x0008
int
kroute_init(void)
@@ -393,6 +409,8 @@ kroute_dispatch_msg(int fd)
if ((kr = RB_FIND(kroute_tree, &krt, &s)) != NULL) {
if (kr->flags & F_KERNEL) {
kr->r.nexthop = nexthop;
+ if (kr->flags & F_NEXTHOP) /* XXX */
+ flags |= F_NEXTHOP;
kr->flags = flags;
}
} else {
@@ -415,8 +433,7 @@ kroute_dispatch_msg(int fd)
continue;
if (!(kr->flags & F_KERNEL))
continue;
- RB_REMOVE(kroute_tree, &krt, kr);
- free(kr);
+ kroute_remove(kr);
break;
default:
/* ingnore for now */
@@ -425,3 +442,114 @@ kroute_dispatch_msg(int fd)
}
}
+
+void
+kroute_remove(struct kroute_node *kr)
+{
+ struct knexthop_node *s;
+ struct kroute_nexthop nh;
+
+ /*
+ * the foreach is suboptimal, but:
+ * -routes disappering that have nexthops attached should not
+ * happen often; except for some ibgp and multihop that should
+ * be connected routes anyway
+ * -maintaining an SLIST per kroute_node is probably worse
+ * -it is easy to change if needed ;-)
+ */
+
+ RB_REMOVE(kroute_tree, &krt, kr);
+
+ if ((kr->flags & F_KERNEL) && (kr->flags & F_NEXTHOP))
+ RB_FOREACH(s, knexthop_tree, &knt)
+ if (s->kroute == kr) {
+ /*
+ * XXX check again wether there's another
+ * non-bgp route. if not, notify RDE
+ * that this nexthop is now invalid
+ */
+ bzero(&nh, sizeof(nh));
+ kroute_validate_nexthop(s->nh.nexthop, &nh);
+ if (nh.valid == 0) {
+ /* no alternate route */
+ /* imsg_ invalid blah blah */
+ }
+ }
+
+ free(kr);
+}
+
+struct kroute_node *
+kroute_match(in_addr_t key)
+{
+ int i;
+ struct kroute_node s, *kr;
+ in_addr_t ina;
+
+ ina = ntohl(key);
+
+ for (i = 32; i >= 0; i--) {
+ s.r.prefix = htonl(ina & (0xffffffff << (32 - i)));
+ s.r.prefixlen = i;
+ if ((kr = RB_FIND(kroute_tree, &krt, &s)) != NULL)
+ return (kr);
+ }
+
+ return (NULL);
+}
+
+void
+kroute_nexthop_check(in_addr_t key)
+{
+ struct kroute_nexthop nh;
+ struct knexthop_node *h, s;
+
+ s.nh.nexthop = key;
+
+ bzero(&nh, sizeof(nh));
+ nh.nexthop = key;
+
+ if ((h = RB_FIND(knexthop_tree, &knt, &s)) != NULL) {
+ if (h->kroute != NULL) {
+ nh.valid = 1;
+ nh.connected = h->kroute->flags & F_CONNECTED;
+ nh.gateway = h->kroute->r.nexthop;
+ }
+ } else
+ kroute_validate_nexthop(key, &nh);
+
+ /* imsg_compose via bgpd.c blah blah blah */
+}
+
+void
+kroute_validate_nexthop(in_addr_t key, struct kroute_nexthop *nh)
+{
+ struct kroute_node *kr;
+ struct knexthop_node *h;
+
+ if ((h = calloc(1, sizeof(struct knexthop_node))) == NULL)
+ fatal(NULL, errno);
+
+ nh->nexthop = key;
+
+ if ((kr = kroute_match(key)) != NULL)
+ if (kr->flags & F_KERNEL) { /* must be non-bgp! */
+ h->kroute = kr;
+ kr->flags |= F_NEXTHOP;
+ nh->valid = 1;
+ nh->connected = kr->flags & F_CONNECTED;
+ nh->gateway = kr->r.nexthop;
+ }
+
+ if (RB_INSERT(knexthop_tree, &knt, h) != NULL)
+ fatal("RB_INSERT(knexthop_tree, &knt, h) failed!", 0);
+
+ /* imsg_compose via bgpd.c bla bla bla */
+}
+
+int
+knexthop_compare(struct knexthop_node *a, struct knexthop_node *b)
+{
+ return (b->nh.nexthop - a->nh.nexthop);
+}
+