summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2003-12-24 19:23:27 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2003-12-24 19:23:27 +0000
commit148c694f42da4be029930951951962fe9511d977 (patch)
tree048edad1f96736953520bf9dcc61d0eca033e032 /usr.sbin
parent3b89508c7731a21d167739fab4c678d4651589da (diff)
keep track of the routes we inserted to the kernel
do only ever delete those, and no others
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/kroute.c102
1 files changed, 96 insertions, 6 deletions
diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c
index 893d46217f8..77de2cf9255 100644
--- a/usr.sbin/bgpd/kroute.c
+++ b/usr.sbin/bgpd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.5 2003/12/23 17:38:49 henning Exp $ */
+/* $OpenBSD: kroute.c,v 1.6 2003/12/24 19:23:26 henning Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -18,6 +18,7 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/tree.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/route.h>
@@ -31,9 +32,22 @@
#include "bgpd.h"
+struct kroute_node {
+ RB_ENTRY(kroute_node) entry;
+ struct kroute r;
+ int flags;
+};
+
int kroute_msg(int, int, struct kroute *);
+int kroute_compare(struct kroute_node *, struct kroute_node *);
+
+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);
+
+u_int32_t rtseq = 1;
-u_int32_t rtseq = 1;
+#define F_BGPD_INSERTED 0x0001
int
kroute_init(void)
@@ -50,6 +64,8 @@ kroute_init(void)
if (setsockopt(s, SOL_SOCKET, SO_USELOOPBACK, &opt, sizeof(opt)) == -1)
fatal("route setsockopt", errno);
+ RB_INIT(&krt);
+
return (s);
}
@@ -93,8 +109,8 @@ retry:
return (0);
}
break;
- case EEXIST: /* connected route. ignore */
- return (0);
+ case EEXIST: /* connected route */
+ return (-2);
default:
logit(LOG_INFO, "kroute_msg: %s", strerror(errno));
return (-1);
@@ -110,17 +126,91 @@ retry:
int
kroute_add(int fd, struct kroute *kroute)
{
- return (kroute_msg(fd, RTM_ADD, kroute));
+ struct kroute_node *kr;
+ int n;
+
+ if ((n = kroute_msg(fd, RTM_ADD, kroute)) == -2) /* connected route */
+ return (0);
+
+ if (n == -1)
+ return (-1);
+
+ if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL)
+ fatal(NULL, errno);
+
+ kr->r.prefix = kroute->prefix;
+ kr->r.prefixlen = kroute->prefixlen;
+ kr->r.nexthop = kroute->nexthop;
+ kr->flags = F_BGPD_INSERTED;
+
+ if (RB_INSERT(kroute_tree, &krt, kr) != NULL) {
+ logit(LOG_CRIT, "RB_INSERT failed!");
+ return (-1);
+ }
+
+ return (n);
}
int
kroute_change(int fd, struct kroute *kroute)
{
+ struct kroute_node *kr, s;
+
+ s.r.prefix = kroute->prefix;
+ s.r.prefixlen = kroute->prefixlen;
+
+ if ((kr = RB_FIND(kroute_tree, &krt, &s)) == NULL) {
+ log_kroute(LOG_CRIT, "kroute_change: no match for", kroute);
+ return (-1);
+ }
+
+ if (!(kr->flags & F_BGPD_INSERTED)) {
+ logit(LOG_CRIT, "trying to change route not inserted by bgpd");
+ return (0);
+ }
+
+ kr->r.nexthop = kroute->nexthop;
+
return (kroute_msg(fd, RTM_CHANGE, kroute));
}
int
kroute_delete(int fd, struct kroute *kroute)
{
- return (kroute_msg(fd, RTM_DELETE, kroute));
+ struct kroute_node *kr, s;
+ int n;
+
+ s.r.prefix = kroute->prefix;
+ s.r.prefixlen = kroute->prefixlen;
+
+ if ((kr = RB_FIND(kroute_tree, &krt, &s)) == NULL) {
+ /* at the moment this is totally valid... */
+ log_kroute(LOG_CRIT, "kroute_delete: no match for", kroute);
+ return (0);
+ }
+
+ if (!(kr->flags & F_BGPD_INSERTED))
+ return (0);
+
+ if ((n = kroute_msg(fd, RTM_DELETE, kroute)) == -1)
+ return (-1);
+
+ RB_REMOVE(kroute_tree, &krt, kr);
+ free(kr);
+
+ return (0);
+}
+
+int
+kroute_compare(struct kroute_node *a, struct kroute_node *b)
+{
+ if (a->r.prefix < b->r.prefix)
+ return (-1);
+ if (a->r.prefix > b->r.prefix)
+ return (1);
+ if (a->r.prefixlen < b->r.prefixlen)
+ return (-1);
+ if (a->r.prefixlen > b->r.prefixlen)
+ return (1);
+ return (0);
}