summaryrefslogtreecommitdiff
path: root/sys
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 /sys
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
Diffstat (limited to 'sys')
-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) &&