diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2006-11-28 16:39:35 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2006-11-28 16:39:35 +0000 |
commit | 7e5f9e3805cae5d88127896b6c930fded4293638 (patch) | |
tree | eb3e429882f1780a2b9fac417a32e5b0f8720af9 /usr.sbin/bgpd/kroute.c | |
parent | ad9b38f7b39476f6dc3637954afe88c789eef783 (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.c | 55 |
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); } - |