summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2006-06-15 16:33:03 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2006-06-15 16:33:03 +0000
commit76df8e5b0f5b64f80edc3988c2c84757ae779f94 (patch)
treef9b21052eb8f07402acee94ef038c38ba36707e6 /sys/net
parent686c8cda73261a63e3f930ab893ed44830d5e938 (diff)
put the multiple routing tables support back in, fixed.
problem before: with this, we are no longer using the address family as array index directly, since only 3 of 31 address fanilies actually attach a table, but we're using an address family to array index translation (just another array). there, 0 meant "does not attach a table", thus rt_gettable has to return a null pointer. unfortunately we were using array index 0 for whatever af attaches first, and since the list is backwards,, that used to be ipsec - execpt on ipsec-less ramdisks, where it was inet6, and since route show blindly iterates over all address families, and all those without a table pointed to index 0, we got 28 or 29 copies of the v6 table. i had that right initally, and then i borked it later... re-spotted by claudio. ok norby hshoexer claudio
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/route.c96
-rw-r--r--sys/net/route.h7
2 files changed, 80 insertions, 23 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index 9b05ced60ce..c9ac3840b5a 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.77 2006/06/06 15:36:07 deraadt Exp $ */
+/* $OpenBSD: route.c,v 1.78 2006/06/15 16:33:02 henning Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -130,9 +130,12 @@ struct ifaddr *encap_findgwifa(struct sockaddr *);
#define SA(p) ((struct sockaddr *)(p))
-struct route_cb route_cb;
-struct rtstat rtstat;
-struct radix_node_head *rt_tables[AF_MAX+1];
+struct route_cb route_cb;
+struct rtstat rtstat;
+struct radix_node_head ***rt_tables;
+u_int8_t af2rtafidx[AF_MAX+1];
+u_int8_t rtafidx_max;
+u_int rtbl_id_max = 0;
int rttrash; /* routes not in table but not freed */
struct sockaddr wildcard; /* zero cookie for wildcard searches */
@@ -140,6 +143,8 @@ struct sockaddr wildcard; /* zero cookie for wildcard searches */
struct pool rtentry_pool; /* pool for rtentry structures */
struct pool rttimer_pool; /* pool for rttimer structures */
+int rtable_init(struct radix_node_head ***);
+int rtable_add(u_int);
int okaytoclone(u_int, int);
int rtdeletemsg(struct rtentry *);
int rtflushclone1(struct radix_node *, void *);
@@ -165,23 +170,74 @@ encap_findgwifa(struct sockaddr *gw)
}
#endif
-void
-rtable_init(void **table)
+int
+rtable_init(struct radix_node_head ***table)
{
- struct domain *dom;
+ void **p;
+ struct domain *dom;
+
+ if ((p = malloc(sizeof(void *) * (rtafidx_max + 1), M_RTABLE,
+ M_NOWAIT)) == NULL)
+ return (-1);
+ bzero(p, sizeof(void *) * (rtafidx_max + 1));
+
+ /* 2nd pass: attach */
for (dom = domains; dom != NULL; dom = dom->dom_next)
if (dom->dom_rtattach)
- dom->dom_rtattach(&table[dom->dom_family],
+ dom->dom_rtattach(&p[af2rtafidx[dom->dom_family]],
dom->dom_rtoffset);
+
+ *table = (struct radix_node_head **)p;
+ return (0);
}
void
route_init()
{
+ struct domain *dom;
+
pool_init(&rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl",
NULL);
rn_init(); /* initialize all zeroes, all ones, mask table */
- rtable_init((void **)rt_tables);
+
+ bzero(af2rtafidx, sizeof(af2rtafidx));
+ rtafidx_max = 1; /* must have NULL at index 0, so start at 1 */
+
+ /* find out how many tables to allocate */
+ for (dom = domains; dom != NULL; dom = dom->dom_next)
+ if (dom->dom_rtattach)
+ af2rtafidx[dom->dom_family] = rtafidx_max++;
+
+ if (rtable_add(0) == -1)
+ panic("route_init rtable_add");
+}
+
+int
+rtable_add(u_int id) /* must be called at splsoftnet */
+{
+ void *p;
+
+ if (id > RT_TABLEID_MAX)
+ return (-1);
+
+ if (id == 0 || id > rtbl_id_max) {
+ size_t newlen = sizeof(void *) * (id+1);
+
+ if ((p = malloc(newlen, M_RTABLE, M_NOWAIT)) == NULL)
+ return (-1);
+ bzero(p, newlen);
+ if (id > 0) {
+ bcopy(rt_tables, p, sizeof(void *) * (rtbl_id_max+1));
+ free(rt_tables, M_RTABLE);
+ }
+ rt_tables = p;
+ rtbl_id_max = id;
+ }
+
+ if (rt_tables[id] != NULL) /* already exists */
+ return (-1);
+
+ return (rtable_init(&rt_tables[id]));
}
void
@@ -205,13 +261,14 @@ okaytoclone(u_int flags, int howstrict)
struct rtentry *
rtalloc2(struct sockaddr *dst, int report, int howstrict)
{
- struct radix_node_head *rnh = rt_tables[dst->sa_family];
+ struct radix_node_head *rnh;
struct rtentry *rt;
struct radix_node *rn;
struct rtentry *newrt = 0;
struct rt_addrinfo info;
int s = splnet(), err = 0, msgtype = RTM_MISS;
+ rnh = rt_gettable(dst->sa_family, 0);
if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
((rn->rn_flags & RNF_ROOT) == 0)) {
newrt = rt = (struct rtentry *)rn;
@@ -257,13 +314,14 @@ rtalloc(struct route *ro)
struct rtentry *
rtalloc1(struct sockaddr *dst, int report)
{
- struct radix_node_head *rnh = rt_tables[dst->sa_family];
+ struct radix_node_head *rnh;
struct rtentry *rt;
struct radix_node *rn;
struct rtentry *newrt = 0;
struct rt_addrinfo info;
int s = splsoftnet(), err = 0, msgtype = RTM_MISS;
+ rnh = rt_gettable(dst->sa_family, 0);
if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
((rn->rn_flags & RNF_ROOT) == 0)) {
newrt = rt = (struct rtentry *)rn;
@@ -657,7 +715,7 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
struct sockaddr_rtlabel *sa_rl;
#define senderr(x) { error = x ; goto bad; }
- if ((rnh = rt_tables[info->rti_info[RTAX_DST]->sa_family]) == 0)
+ if ((rnh = rt_gettable(info->rti_info[RTAX_DST]->sa_family, 0)) == NULL)
senderr(EAFNOSUPPORT);
if (info->rti_flags & RTF_HOST)
info->rti_info[RTAX_NETMASK] = NULL;
@@ -1127,10 +1185,9 @@ rt_timer_add(struct rtentry *rt, void (*func)(struct rtentry *,
}
struct radix_node_head *
-rt_gettable(sa_family_t af, int id)
+rt_gettable(sa_family_t af, u_int id)
{
- /* ignore id for now */
- return (rt_tables[af]);
+ return (rt_tables[id][af2rtafidx[af]]);
}
struct radix_node *
@@ -1143,6 +1200,7 @@ rt_lookup(struct sockaddr *dst, struct sockaddr *mask, int tableid)
return (rnh->rnh_lookup(dst, mask, rnh));
}
+
/* ARGSUSED */
void
rt_timer_timer(void *arg)
@@ -1259,13 +1317,11 @@ rt_if_remove(struct ifnet *ifp)
int i;
struct radix_node_head *rnh;
- for (i = 1; i <= AF_MAX; i++) {
- rnh = rt_tables[i];
- if (rnh)
+ for (i = 1; i <= AF_MAX; i++)
+ if ((rnh = rt_gettable(i, 0)) != NULL)
while ((*rnh->rnh_walktree)(rnh,
rt_if_remove_rtdelete, ifp) == EAGAIN)
- ;
- }
+ ; /* nothing */
}
/*
diff --git a/sys/net/route.h b/sys/net/route.h
index 9db16dbf54a..6534ddf1057 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.h,v 1.42 2006/06/06 15:36:07 deraadt Exp $ */
+/* $OpenBSD: route.h,v 1.43 2006/06/15 16:33:02 henning Exp $ */
/* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */
/*
@@ -304,6 +304,8 @@ void rtlabel_unref(u_int16_t);
#define ONNET_CLONING 1
#define NO_CLONING 2
+#define RT_TABLEID_MAX 255
+
extern struct route_cb route_cb;
extern struct rtstat rtstat;
extern const struct sockaddr_rtin rt_defmask4;
@@ -334,7 +336,6 @@ void rt_timer_queue_destroy(struct rttimer_queue *, int);
void rt_timer_remove_all(struct rtentry *);
unsigned long rt_timer_count(struct rttimer_queue *);
void rt_timer_timer(void *);
-void rtable_init(void **);
void rtalloc(struct route *);
struct rtentry *
rtalloc1(struct sockaddr *, int);
@@ -354,7 +355,7 @@ int rtrequest(int, struct sockaddr *,
int rtrequest1(int, struct rt_addrinfo *, struct rtentry **);
void rt_if_remove(struct ifnet *);
-struct radix_node_head *rt_gettable(sa_family_t, int);
+struct radix_node_head *rt_gettable(sa_family_t, u_int);
struct radix_node *rt_lookup(struct sockaddr *, struct sockaddr *, int);
#endif /* _KERNEL */
#endif /* _NET_ROUTE_H_ */