diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2003-12-24 19:23:27 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2003-12-24 19:23:27 +0000 |
commit | 148c694f42da4be029930951951962fe9511d977 (patch) | |
tree | 048edad1f96736953520bf9dcc61d0eca033e032 /usr.sbin | |
parent | 3b89508c7731a21d167739fab4c678d4651589da (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.c | 102 |
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); } |