diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-08-03 11:22:16 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-08-03 11:22:16 +0000 |
commit | 4db9c1a02eeb9a2f2cab3f9d37ff1c15ce1b91dd (patch) | |
tree | 886d0b81496ebec1a778d257f7db7e5768c8399e | |
parent | b337bae270d603117da35f981f247b3da7e438c2 (diff) |
introduce route labels, allowing for up to 32 bytes of info to be attached
to a route.
the label is sent over the routing socket wrapped into a new
struct sockaddr_rtlabel, allowing for handling it like any other sockaddr.
struct rtentry only contains a (16 bit) label-ID, with the actual labels
kept outside the routing table.
ID allocator code inspired by my own code for altq and pf tags.
mostly hacked at the c2k4 hackathon, markus ok
-rw-r--r-- | sys/net/route.c | 101 | ||||
-rw-r--r-- | sys/net/route.h | 17 | ||||
-rw-r--r-- | sys/net/rtsock.c | 16 |
3 files changed, 130 insertions, 4 deletions
diff --git a/sys/net/route.c b/sys/net/route.c index 00d94f9bfea..d96e42183a2 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.46 2004/07/28 13:13:41 markus Exp $ */ +/* $OpenBSD: route.c,v 1.47 2004/08/03 11:22:15 henning Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -111,6 +111,7 @@ #include <sys/protosw.h> #include <sys/ioctl.h> #include <sys/kernel.h> +#include <sys/queue.h> #include <sys/pool.h> #include <net/if.h> @@ -147,6 +148,20 @@ static int rtdeletemsg(struct rtentry *); static int rtflushclone1(struct radix_node *, void *); static void rtflushclone(struct radix_node_head *, struct rtentry *); +#define LABELID_MAX 50000 + +struct rt_label { + TAILQ_ENTRY(rt_label) rtl_entry; + char rtl_name[RTLABEL_LEN]; + u_int16_t rtl_id; + int rtl_ref; +}; + +TAILQ_HEAD(rt_labels, rt_label) rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels); + +static u_int16_t rtlabel_name2id(char *); +static void rtlabel_unref(u_int16_t); + #ifdef IPSEC static struct ifaddr * @@ -332,6 +347,7 @@ rtfree(rt) ifa = rt->rt_ifa; if (ifa) IFAFREE(ifa); + rtlabel_unref(rt->rt_labelid); Free(rt_key(rt)); pool_put(&rtentry_pool, rt); } @@ -670,6 +686,7 @@ rtrequest1(req, info, ret_nrt) struct radix_node_head *rnh; struct ifaddr *ifa; struct sockaddr *ndst; + struct sockaddr_rtlabel *sa_rl; #define senderr(x) { error = x ; goto bad; } if ((rnh = rt_tables[dst->sa_family]) == 0) @@ -767,6 +784,13 @@ rtrequest1(req, info, ret_nrt) senderr(EEXIST); } #endif + + if (info->rti_info[RTAX_LABEL] != NULL) { + sa_rl = (struct sockaddr_rtlabel *) + info->rti_info[RTAX_LABEL]; + rt->rt_labelid = rtlabel_name2id(sa_rl->sr_label); + } + ifa->ifa_refcnt++; rt->rt_ifa = ifa; rt->rt_ifp = ifa->ifa_ifp; @@ -1172,3 +1196,78 @@ rt_timer_timer(arg) timeout_add(to, hz); /* every second */ } + +static u_int16_t +rtlabel_name2id(char *name) +{ + struct rt_label *label, *p = NULL; + u_int16_t new_id = 1; + + TAILQ_FOREACH(label, &rt_labels, rtl_entry) + if (strcmp(name, label->rtl_name) == 0) { + label->rtl_ref++; + return (label->rtl_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->rtl_id == new_id; p = TAILQ_NEXT(p, rtl_entry)) + new_id = p->rtl_id + 1; + + if (new_id > LABELID_MAX) + return (0); + + label = (struct rt_label *)malloc(sizeof(struct rt_label), + M_TEMP, M_NOWAIT); + if (label == NULL) + return (0); + bzero(label, sizeof(struct rt_label)); + strlcpy(label->rtl_name, name, sizeof(label->rtl_name)); + label->rtl_id = new_id; + label->rtl_ref++; + + if (p != NULL) /* insert new entry before p */ + TAILQ_INSERT_BEFORE(p, label, rtl_entry); + else /* either list empty or no free slot in between */ + TAILQ_INSERT_TAIL(&rt_labels, label, rtl_entry); + + return (label->rtl_id); +} + +const char * +rtlabel_id2name(u_int16_t id) +{ + struct rt_label *label; + + TAILQ_FOREACH(label, &rt_labels, rtl_entry) + if (label->rtl_id == id) + return (label->rtl_name); + + return (NULL); +} + +static 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, rtl_entry); + if (id == p->rtl_id) { + if (--p->rtl_ref == 0) { + TAILQ_REMOVE(&rt_labels, p, rtl_entry); + free(p, M_TEMP); + } + break; + } + } +} diff --git a/sys/net/route.h b/sys/net/route.h index 31a25a0e73e..1b167704d53 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -1,4 +1,4 @@ -/* $OpenBSD: route.h,v 1.23 2004/06/19 19:55:53 cedric Exp $ */ +/* $OpenBSD: route.h,v 1.24 2004/08/03 11:22:15 henning Exp $ */ /* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */ /* @@ -116,6 +116,7 @@ struct rtentry { struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */ struct rtentry *rt_parent; /* If cloned, parent of this route. */ LIST_HEAD(, rttimer) rt_timer; /* queue of timeouts for misc funcs */ + u_int16_t rt_labelid; /* route label ID */ }; #define rt_use rt_rmx.rmx_pksent @@ -227,6 +228,7 @@ struct rt_msghdr { #define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */ #define RTA_SRC 0x100 /* source sockaddr present */ #define RTA_SRCMASK 0x200 /* source netmask present */ +#define RTA_LABEL 0x400 /* route label present */ /* * Index offsets for sockaddr array for alternate internal encoding. @@ -241,7 +243,8 @@ struct rt_msghdr { #define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */ #define RTAX_SRC 8 /* source sockaddr present */ #define RTAX_SRCMASK 9 /* source netmask present */ -#define RTAX_MAX 10 /* size of array to allocate */ +#define RTAX_LABEL 10 /* route label present */ +#define RTAX_MAX 11 /* size of array to allocate */ struct rt_addrinfo { int rti_addrs; @@ -283,6 +286,16 @@ struct rttimer_queue { LIST_ENTRY(rttimer_queue) rtq_link; }; +#define RTLABEL_LEN 32 + +struct sockaddr_rtlabel { + u_int8_t sr_len; /* total length */ + sa_family_t sr_family; /* address family */ + char sr_label[RTLABEL_LEN]; +}; + +const char *rtlabel_id2name(u_int16_t); + #ifdef _KERNEL #define RTFREE(rt) do { \ if ((rt)->rt_refcnt <= 1) \ diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 9280cb1c994..41962950d62 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.41 2004/06/24 22:25:25 henning Exp $ */ +/* $OpenBSD: rtsock.c,v 1.42 2004/08/03 11:22:15 henning Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -180,6 +180,8 @@ route_output(struct mbuf *m, ...) struct ifaddr *ifa = NULL; struct socket *so; struct rawcb *rp = NULL; + struct sockaddr_rtlabel sa_rt; + const char *label; va_list ap; va_start(ap, m); @@ -320,6 +322,18 @@ report: gate = rt->rt_gateway; netmask = rt_mask(rt); genmask = rt->rt_genmask; + + if (rt->rt_labelid) { + bzero(&sa_rt, sizeof(sa_rt)); + sa_rt.sr_len = sizeof(sa_rt); + label = rtlabel_id2name(rt->rt_labelid); + if (label != NULL) + strlcpy(sa_rt.sr_label, label, + sizeof(sa_rt.sr_label)); + info.rti_info[RTAX_LABEL] = + (struct sockaddr *)&sa_rt; + } + ifpaddr = 0; ifaaddr = 0; if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA) && |