diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2005-06-13 21:16:19 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2005-06-13 21:16:19 +0000 |
commit | b67d52447b7269e8a850cde9cd3d1d55bdbf43b0 (patch) | |
tree | 5a9cf9ea456458e9d7945642b0aa24309f91d123 /usr.sbin | |
parent | f5b0690d48b94e07abc90ee4f1e44565f941df53 (diff) |
route label support, kroute part and ID allocator as well as the internal
interface changes. support in the filter language and rde to come. claudio ok
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bgpd/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 23 | ||||
-rw-r--r-- | usr.sbin/bgpd/kroute.c | 94 | ||||
-rw-r--r-- | usr.sbin/bgpd/name2id.c | 117 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 27 |
5 files changed, 212 insertions, 53 deletions
diff --git a/usr.sbin/bgpd/Makefile b/usr.sbin/bgpd/Makefile index 6b515e411ec..e29cea78830 100644 --- a/usr.sbin/bgpd/Makefile +++ b/usr.sbin/bgpd/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.22 2005/03/28 15:16:45 henning Exp $ +# $OpenBSD: Makefile,v 1.23 2005/06/13 21:16:18 henning Exp $ .PATH: ${.CURDIR}/.. @@ -6,7 +6,7 @@ PROG= bgpd SRCS= bgpd.c buffer.c session.c log.c parse.y config.c imsg.c \ rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c \ control.c pfkey.c rde_update.c rde_attr.c printconf.c \ - rde_filter.c pftable.c + rde_filter.c pftable.c name2id.c CFLAGS+= -Wall -I${.CURDIR} CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CFLAGS+= -Wmissing-declarations diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 9a685c9e73e..aafad0280b1 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.167 2005/06/09 15:32:03 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.168 2005/06/13 21:16:18 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -21,6 +21,7 @@ #include <sys/types.h> #include <sys/socket.h> #include <sys/queue.h> +#include <net/route.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> @@ -369,6 +370,7 @@ struct kroute { struct in_addr prefix; struct in_addr nexthop; u_int16_t flags; + u_int16_t labelid; u_short ifindex; u_int8_t prefixlen; }; @@ -377,6 +379,7 @@ struct kroute6 { struct in6_addr prefix; struct in6_addr nexthop; u_int16_t flags; + u_int16_t labelid; u_short ifindex; u_int8_t prefixlen; }; @@ -427,6 +430,16 @@ struct ctl_neighbor { char descr[PEER_DESCR_LEN]; }; +struct kroute_label { + struct kroute kr; + char label[RTLABEL_LEN]; +}; + +struct kroute6_label { + struct kroute6 kr; + char label[RTLABEL_LEN]; +}; + #define F_RIB_ELIGIBLE 0x01 #define F_RIB_ACTIVE 0x02 #define F_RIB_INTERNAL 0x04 @@ -653,10 +666,10 @@ int imsg_get_fd(struct imsgbuf *); /* kroute.c */ int kr_init(int); -int kr_change(struct kroute *); -int kr_delete(struct kroute *); -int kr6_change(struct kroute6 *); -int kr6_delete(struct kroute6 *); +int kr_change(struct kroute_label *); +int kr_delete(struct kroute_label *); +int kr6_change(struct kroute6_label *); +int kr6_delete(struct kroute6_label *); void kr_shutdown(void); void kr_fib_couple(void); void kr_fib_decouple(void); diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c index dbfb8f27eca..5404086dfbd 100644 --- a/usr.sbin/bgpd/kroute.c +++ b/usr.sbin/bgpd/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.136 2005/06/07 18:56:51 claudio Exp $ */ +/* $OpenBSD: kroute.c,v 1.137 2005/06/13 21:16:18 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -208,12 +208,12 @@ kr_init(int fs) } int -kr_change(struct kroute *kroute) +kr_change(struct kroute_label *kl) { struct kroute_node *kr; int action = RTM_ADD; - if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen)) != + if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen)) != NULL) { if (kr->r.flags & F_BGPD_INSERTED) action = RTM_CHANGE; @@ -222,11 +222,15 @@ kr_change(struct kroute *kroute) } /* nexthop within 127/8 -> ignore silently */ - if ((kroute->nexthop.s_addr & htonl(IN_CLASSA_NET)) == + if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) == htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) return (0); - if (send_rtmsg(kr_state.fd, action, kroute) == -1) + if (kr) + rtlabel_unref(kr->r.labelid); + kl->kr.labelid = rtlabel_name2id(kl->label); + + if (send_rtmsg(kr_state.fd, action, &kl->kr) == -1) return (-1); if (action == RTM_ADD) { @@ -234,20 +238,22 @@ kr_change(struct kroute *kroute) log_warn("kr_change"); return (-1); } - kr->r.prefix.s_addr = kroute->prefix.s_addr; - kr->r.prefixlen = kroute->prefixlen; - kr->r.nexthop.s_addr = kroute->nexthop.s_addr; - kr->r.flags = kroute->flags | F_BGPD_INSERTED; + kr->r.prefix.s_addr = kl->kr.prefix.s_addr; + kr->r.prefixlen = kl->kr.prefixlen; + kr->r.nexthop.s_addr = kl->kr.nexthop.s_addr; + kr->r.flags = kl->kr.flags | F_BGPD_INSERTED; + kr->r.labelid = kl->kr.labelid; if (kroute_insert(kr) == -1) free(kr); } else { - kr->r.nexthop.s_addr = kroute->nexthop.s_addr; - if (kroute->flags & F_BLACKHOLE) + kr->r.nexthop.s_addr = kl->kr.nexthop.s_addr; + kr->r.labelid = kl->kr.labelid; + if (kl->kr.flags & F_BLACKHOLE) kr->r.flags |= F_BLACKHOLE; else kr->r.flags &= ~F_BLACKHOLE; - if (kroute->flags & F_REJECT) + if (kl->kr.flags & F_REJECT) kr->r.flags |= F_REJECT; else kr->r.flags &= ~F_REJECT; @@ -257,11 +263,11 @@ kr_change(struct kroute *kroute) } int -kr_delete(struct kroute *kroute) +kr_delete(struct kroute_label *kl) { struct kroute_node *kr; - if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen)) == + if ((kr = kroute_find(kl->kr.prefix.s_addr, kl->kr.prefixlen)) == NULL) return (0); @@ -269,11 +275,13 @@ kr_delete(struct kroute *kroute) return (0); /* nexthop within 127/8 -> ignore silently */ - if ((kroute->nexthop.s_addr & htonl(IN_CLASSA_NET)) == + if ((kl->kr.nexthop.s_addr & htonl(IN_CLASSA_NET)) == htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) return (0); - if (send_rtmsg(kr_state.fd, RTM_DELETE, kroute) == -1) + rtlabel_unref(kl->kr.labelid); + + if (send_rtmsg(kr_state.fd, RTM_DELETE, &kl->kr) == -1) return (-1); if (kroute_remove(kr) == -1) @@ -283,12 +291,12 @@ kr_delete(struct kroute *kroute) } int -kr6_change(struct kroute6 *kroute) +kr6_change(struct kroute6_label *kl) { struct kroute6_node *kr6; int action = RTM_ADD; - if ((kr6 = kroute6_find(&kroute->prefix, kroute->prefixlen)) != NULL) { + if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen)) != NULL) { if (kr6->r.flags & F_BGPD_INSERTED) action = RTM_CHANGE; else /* a non-bgp route already exists. not a problem */ @@ -296,10 +304,14 @@ kr6_change(struct kroute6 *kroute) } /* nexthop to loopback -> ignore silently */ - if (IN6_IS_ADDR_LOOPBACK(&kroute->nexthop)) + if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop)) return (0); - if (send_rt6msg(kr_state.fd, action, kroute) == -1) + if (kr6) + rtlabel_unref(kr6->r.labelid); + kl->kr.labelid = rtlabel_name2id(kl->label); + + if (send_rt6msg(kr_state.fd, action, &kl->kr) == -1) return (-1); if (action == RTM_ADD) { @@ -307,23 +319,25 @@ kr6_change(struct kroute6 *kroute) log_warn("kr_change"); return (-1); } - memcpy(&kr6->r.prefix, &kroute->prefix, + memcpy(&kr6->r.prefix, &kl->kr.prefix, sizeof(struct in6_addr)); - kr6->r.prefixlen = kroute->prefixlen; - memcpy(&kr6->r.nexthop, &kroute->nexthop, + kr6->r.prefixlen = kl->kr.prefixlen; + memcpy(&kr6->r.nexthop, &kl->kr.nexthop, sizeof(struct in6_addr)); - kr6->r.flags = kroute->flags | F_BGPD_INSERTED; + kr6->r.flags = kl->kr.flags | F_BGPD_INSERTED; + kr6->r.labelid = kl->kr.labelid; if (kroute6_insert(kr6) == -1) free(kr6); } else { - memcpy(&kr6->r.nexthop, &kroute->nexthop, + memcpy(&kr6->r.nexthop, &kl->kr.nexthop, sizeof(struct in6_addr)); - if (kroute->flags & F_BLACKHOLE) + kr6->r.labelid = kl->kr.labelid; + if (kl->kr.flags & F_BLACKHOLE) kr6->r.flags |= F_BLACKHOLE; else kr6->r.flags &= ~F_BLACKHOLE; - if (kroute->flags & F_REJECT) + if (kl->kr.flags & F_REJECT) kr6->r.flags |= F_REJECT; else kr6->r.flags &= ~F_REJECT; @@ -333,24 +347,26 @@ kr6_change(struct kroute6 *kroute) } int -kr6_delete(struct kroute6 *kroute) +kr6_delete(struct kroute6_label *kl) { struct kroute6_node *kr6; - if ((kr6 = kroute6_find(&kroute->prefix, kroute->prefixlen)) == NULL) + if ((kr6 = kroute6_find(&kl->kr.prefix, kl->kr.prefixlen)) == NULL) return (0); if (!(kr6->r.flags & F_BGPD_INSERTED)) return (0); /* nexthop to loopback -> ignore silently */ - if (IN6_IS_ADDR_LOOPBACK(&kroute->nexthop)) + if (IN6_IS_ADDR_LOOPBACK(&kl->kr.nexthop)) return (0); - if (send_rt6msg(kr_state.fd, RTM_DELETE, kroute) == -1) + if (send_rt6msg(kr_state.fd, RTM_DELETE, &kl->kr) == -1) return (-1); - if (kroute6_remove(kr6) == -1) + rtlabel_unref(kl->kr.labelid); + + if (kroute6_remove(kr6) == -1) return (-1); return (0); @@ -1693,6 +1709,7 @@ send_rtmsg(int fd, int action, struct kroute *kroute) struct sockaddr_in prefix; struct sockaddr_in nexthop; struct sockaddr_in mask; + struct sockaddr_rtlabel label; } r; if (kr_state.fib_sync == 0) @@ -1708,7 +1725,7 @@ send_rtmsg(int fd, int action, struct kroute *kroute) if (kroute->flags & F_REJECT) r.hdr.rtm_flags |= RTF_REJECT; r.hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ - r.hdr.rtm_addrs = RTA_DST|RTA_GATEWAY|RTA_NETMASK; + r.hdr.rtm_addrs = RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_LABEL; r.prefix.sin_len = sizeof(r.prefix); r.prefix.sin_family = AF_INET; r.prefix.sin_addr.s_addr = kroute->prefix.s_addr; @@ -1723,6 +1740,10 @@ send_rtmsg(int fd, int action, struct kroute *kroute) r.mask.sin_family = AF_INET; r.mask.sin_addr.s_addr = htonl(prefixlen2mask(kroute->prefixlen)); + r.label.sr_len = sizeof(r.label); + strlcpy(r.label.sr_label, rtlabel_id2name(kroute->labelid), + sizeof(r.label.sr_label)); + retry: if (write(fd, &r, sizeof(r)) == -1) { switch (errno) { @@ -1762,6 +1783,7 @@ send_rt6msg(int fd, int action, struct kroute6 *kroute) struct sockaddr_in6 prefix; struct sockaddr_in6 nexthop; struct sockaddr_in6 mask; + struct sockaddr_rtlabel label; } r; if (kr_state.fib_sync == 0) @@ -1777,7 +1799,7 @@ send_rt6msg(int fd, int action, struct kroute6 *kroute) if (kroute->flags & F_REJECT) r.hdr.rtm_flags |= RTF_REJECT; r.hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ - r.hdr.rtm_addrs = RTA_DST|RTA_GATEWAY|RTA_NETMASK; + r.hdr.rtm_addrs = RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_LABEL; r.prefix.sin6_len = sizeof(r.prefix); r.prefix.sin6_family = AF_INET6; memcpy(&r.prefix.sin6_addr, &kroute->prefix, sizeof(struct in6_addr)); @@ -1794,6 +1816,10 @@ send_rt6msg(int fd, int action, struct kroute6 *kroute) memcpy(&r.mask.sin6_addr, prefixlen2mask6(kroute->prefixlen), sizeof(struct in6_addr)); + r.label.sr_len = sizeof(r.label); + strlcpy(r.label.sr_label, rtlabel_id2name(kroute->labelid), + sizeof(r.label.sr_label)); + retry: if (write(fd, &r, sizeof(r)) == -1) { switch (errno) { diff --git a/usr.sbin/bgpd/name2id.c b/usr.sbin/bgpd/name2id.c new file mode 100644 index 00000000000..5916f221d44 --- /dev/null +++ b/usr.sbin/bgpd/name2id.c @@ -0,0 +1,117 @@ +/* $OpenBSD: name2id.c,v 1.1 2005/06/13 21:16:18 henning Exp $ */ + +/* + * Copyright (c) 2004, 2005 Henning Brauer <henning@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <net/route.h> + +#include <stdlib.h> +#include <string.h> + +#include "bgpd.h" + +#define IDVAL_MAX 50000 + +struct rt_label { + TAILQ_ENTRY(rt_label) entry; + char name[RTLABEL_LEN]; + u_int16_t id; + int ref; +}; + +TAILQ_HEAD(rt_labels, rt_label) rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels); + + +u_int16_t +rtlabel_name2id(char *name) +{ + struct rt_label *label, *p = NULL; + u_int16_t new_id = 1; + + if (!name[0]) + return (0); + + TAILQ_FOREACH(label, &rt_labels, entry) + if (strcmp(name, label->name) == 0) { + label->ref++; + return (label->id); + } + + /* + * to avoid fragmentation, we do a linear search from the beginning + * and take the first free slot we find. if there is none or the list + * is empty, append a new entry at the end. + */ + + if (!TAILQ_EMPTY(&rt_labels)) + for (p = TAILQ_FIRST(&rt_labels); p != NULL && + p->id == new_id; p = TAILQ_NEXT(p, entry)) + new_id = p->id + 1; + + if (new_id > IDVAL_MAX) + return (0); + + if ((label = calloc(1, sizeof(struct rt_label))) == NULL) + return (0); + strlcpy(label->name, name, sizeof(label->name)); + label->id = new_id; + label->ref++; + + if (p != NULL) /* insert new entry before p */ + TAILQ_INSERT_BEFORE(p, label, entry); + else /* either list empty or no free slot in between */ + TAILQ_INSERT_TAIL(&rt_labels, label, entry); + + return (label->id); +} + +const char * +rtlabel_id2name(u_int16_t id) +{ + struct rt_label *label; + + if (!id) + return(""); + + TAILQ_FOREACH(label, &rt_labels, entry) + if (label->id == id) + return (label->name); + + return (""); +} + +void +rtlabel_unref(u_int16_t id) +{ + struct rt_label *p, *next; + + if (id == 0) + return; + + for (p = TAILQ_FIRST(&rt_labels); p != NULL; p = next) { + next = TAILQ_NEXT(p, entry); + if (id == p->id) { + if (--p->ref == 0) { + TAILQ_REMOVE(&rt_labels, p, entry); + free(p); + } + break; + } + } +} diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index a484185e4bc..a2e485e0403 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.161 2005/06/10 08:28:50 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.162 2005/06/13 21:16:18 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -1611,10 +1611,10 @@ rde_dump_prefix(struct ctl_show_rib_prefix *pref, pid_t pid) void rde_send_kroute(struct prefix *new, struct prefix *old) { - struct kroute kr; - struct bgpd_addr addr; - struct prefix *p; - enum imsg_type type; + struct kroute_label kl; + struct bgpd_addr addr; + struct prefix *p; + enum imsg_type type; /* * If old is != NULL we know it was active and should be removed. @@ -1627,7 +1627,7 @@ rde_send_kroute(struct prefix *new, struct prefix *old) new->aspath->flags & F_PREFIX_ANNOUNCED)) return; - bzero(&kr, sizeof(kr)); + bzero(&kl, sizeof(kl)); if (new == NULL || new->aspath->nexthop == NULL || new->aspath->nexthop->state != NEXTHOP_REACH || @@ -1637,18 +1637,21 @@ rde_send_kroute(struct prefix *new, struct prefix *old) } else { type = IMSG_KROUTE_CHANGE; p = new; - kr.nexthop.s_addr = p->aspath->nexthop->true_nexthop.v4.s_addr; + kl.kr.nexthop.s_addr = + p->aspath->nexthop->true_nexthop.v4.s_addr; } pt_getaddr(p->prefix, &addr); - kr.prefix.s_addr = addr.v4.s_addr; - kr.prefixlen = p->prefix->prefixlen; + kl.kr.prefix.s_addr = addr.v4.s_addr; + kl.kr.prefixlen = p->prefix->prefixlen; if (p->aspath->flags & F_NEXTHOP_REJECT) - kr.flags |= F_REJECT; + kl.kr.flags |= F_REJECT; if (p->aspath->flags & F_NEXTHOP_BLACKHOLE) - kr.flags |= F_BLACKHOLE; + kl.kr.flags |= F_BLACKHOLE; + /* XXX */ + strlcpy(kl.label, rtlabel_id2name(0), sizeof(kl.label)); - if (imsg_compose(ibuf_main, type, 0, 0, -1, &kr, sizeof(kr)) == -1) + if (imsg_compose(ibuf_main, type, 0, 0, -1, &kl, sizeof(kl)) == -1) fatal("imsg_compose error"); } |