summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd/kroute.c
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2006-11-28 16:39:35 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2006-11-28 16:39:35 +0000
commit7e5f9e3805cae5d88127896b6c930fded4293638 (patch)
treeeb3e429882f1780a2b9fac417a32e5b0f8720af9 /usr.sbin/bgpd/kroute.c
parentad9b38f7b39476f6dc3637954afe88c789eef783 (diff)
allow bgpd to work on alternate routing tables, claudio ok, jmc manpage help
Diffstat (limited to 'usr.sbin/bgpd/kroute.c')
-rw-r--r--usr.sbin/bgpd/kroute.c55
1 files changed, 39 insertions, 16 deletions
diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c
index a417f0f7e6b..f92e5ffcc59 100644
--- a/usr.sbin/bgpd/kroute.c
+++ b/usr.sbin/bgpd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.149 2006/11/28 16:36:58 henning Exp $ */
+/* $OpenBSD: kroute.c,v 1.150 2006/11/28 16:39:34 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -39,6 +39,7 @@
struct {
u_int32_t rtseq;
pid_t pid;
+ u_int rtableid;
int fib_sync;
int fd;
} kr_state;
@@ -131,10 +132,10 @@ void if_announce(void *);
int send_rtmsg(int, int, struct kroute *);
int send_rt6msg(int, int, struct kroute6 *);
int dispatch_rtmsg(void);
-int fetchtable(void);
+int fetchtable(u_int, int);
int fetchifs(int);
int dispatch_rtmsg_addr(struct rt_msghdr *,
- struct sockaddr *[RTAX_MAX]);
+ struct sockaddr *[RTAX_MAX], int);
RB_HEAD(kroute_tree, kroute_node) krt;
RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare)
@@ -157,12 +158,13 @@ RB_GENERATE(kif_tree, kif_node, entry, kif_compare)
*/
int
-kr_init(int fs)
+kr_init(int fs, u_int rtableid)
{
int opt = 0, rcvbuf, default_rcvbuf;
socklen_t optlen;
kr_state.fib_sync = fs;
+ kr_state.rtableid = rtableid;
if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
log_warn("kr_init: socket");
@@ -198,8 +200,11 @@ kr_init(int fs)
if (fetchifs(0) == -1)
return (-1);
- if (fetchtable() == -1)
+ if (fetchtable(kr_state.rtableid, 0) == -1)
return (-1);
+ if (kr_state.rtableid != 0)
+ if (fetchtable(0, 1) == -1)
+ return (-1);
if (protect_lo() == -1)
return (-1);
@@ -1742,6 +1747,7 @@ send_rtmsg(int fd, int action, struct kroute *kroute)
r.hdr.rtm_msglen = sizeof(r);
r.hdr.rtm_version = RTM_VERSION;
r.hdr.rtm_type = action;
+ r.hdr.rtm_tableid = kr_state.rtableid;
r.hdr.rtm_flags = RTF_PROTO1;
if (kroute->flags & F_BLACKHOLE)
r.hdr.rtm_flags |= RTF_BLACKHOLE;
@@ -1818,6 +1824,7 @@ send_rt6msg(int fd, int action, struct kroute6 *kroute)
r.hdr.rtm_msglen = sizeof(r);
r.hdr.rtm_version = RTM_VERSION;
r.hdr.rtm_type = action;
+ r.hdr.rtm_tableid = kr_state.rtableid;
r.hdr.rtm_flags = RTF_PROTO1;
if (kroute->flags & F_BLACKHOLE)
r.hdr.rtm_flags |= RTF_BLACKHOLE;
@@ -1877,7 +1884,7 @@ retry:
}
int
-fetchtable(void)
+fetchtable(u_int rtableid, int connected_only)
{
size_t len;
int mib[7];
@@ -1895,9 +1902,11 @@ fetchtable(void)
mib[3] = 0;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
- mib[6] = 0; /* rtableid */
+ mib[6] = rtableid;
if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) {
+ if (rtableid != 0 && errno == EINVAL) /* table nonexistant */
+ return (0);
log_warn("sysctl");
return (-1);
}
@@ -2020,19 +2029,24 @@ fetchtable(void)
}
if (sa->sa_family == AF_INET) {
+log_debug("fetchtable id %u, %s/%u, %s", rtableid, inet_ntoa(kr->r.prefix), kr->r.prefixlen,
+kr->r.flags & F_CONNECTED ? "connected" : "");
if (rtm->rtm_flags & RTF_PROTO1) {
send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r);
free(kr);
- } else
+ } else if (connected_only && !(kr->r.flags & F_CONNECTED))
+ free(kr);
+ else
kroute_insert(kr);
} else if (sa->sa_family == AF_INET6) {
if (rtm->rtm_flags & RTF_PROTO1) {
send_rt6msg(kr_state.fd, RTM_DELETE, &kr6->r);
free(kr6);
- } else
+ } else if (connected_only && !(kr6->r.flags & F_CONNECTED))
+ free(kr6);
+ else
kroute6_insert(kr6);
}
-
}
free(buf);
return (0);
@@ -2119,6 +2133,7 @@ dispatch_rtmsg(void)
struct rt_msghdr *rtm;
struct if_msghdr ifm;
struct sockaddr *sa, *rti_info[RTAX_MAX];
+ int connected_only;
if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
log_warn("dispatch_rtmsg: read error");
@@ -2134,9 +2149,6 @@ dispatch_rtmsg(void)
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
- if (rtm->rtm_tableid != 0)
- continue;
-
switch (rtm->rtm_type) {
case RTM_ADD:
case RTM_CHANGE:
@@ -2153,7 +2165,15 @@ dispatch_rtmsg(void)
if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
continue;
- if (dispatch_rtmsg_addr(rtm, rti_info) == -1)
+ connected_only = 0;
+ if (rtm->rtm_tableid != kr_state.rtableid) {
+ if (rtm->rtm_tableid == 0)
+ connected_only = 1;
+ else
+ continue;
+ }
+
+ if (dispatch_rtmsg_addr(rtm, rti_info, connected_only) == -1)
return (-1);
break;
case RTM_IFINFO:
@@ -2173,7 +2193,8 @@ dispatch_rtmsg(void)
}
int
-dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX])
+dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX],
+ int connected_only)
{
struct sockaddr *sa;
struct sockaddr_in *sa_in;
@@ -2265,6 +2286,9 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX])
break;
}
+ if (connected_only && !(flags & F_CONNECTED))
+ return (0);
+
if (sa == NULL && !(flags & F_CONNECTED)) {
log_warnx("dispatch_rtmsg no nexthop for %s/%u",
log_addr(&prefix), prefixlen);
@@ -2380,4 +2404,3 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX])
return (0);
}
-