summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2004-08-03 11:22:16 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2004-08-03 11:22:16 +0000
commit4db9c1a02eeb9a2f2cab3f9d37ff1c15ce1b91dd (patch)
tree886d0b81496ebec1a778d257f7db7e5768c8399e
parentb337bae270d603117da35f981f247b3da7e438c2 (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.c101
-rw-r--r--sys/net/route.h17
-rw-r--r--sys/net/rtsock.c16
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) &&