summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1999-01-08 00:56:07 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1999-01-08 00:56:07 +0000
commitf2b23511b00acad5ac786927adf6ae9f92c43b54 (patch)
treebcbaacf3eb3bde80221e63ed4d8d89f6633b1d8e /sys
parente95bfef84140b990116d223ce4923feb2f593d86 (diff)
INET6 support; NRL/cmetz
Diffstat (limited to 'sys')
-rw-r--r--sys/net/route.c133
-rw-r--r--sys/net/route.h26
2 files changed, 151 insertions, 8 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index c2553f6d22d..e4809d205cf 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.8 1999/01/07 22:18:59 deraadt Exp $ */
+/* $OpenBSD: route.c,v 1.9 1999/01/08 00:56:06 deraadt Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -36,6 +36,18 @@
* @(#)route.c 8.2 (Berkeley) 11/15/93
*/
+/*
+%%% portions-copyright-nrl-95
+Portions of this software are Copyright 1995-1998 by Randall Atkinson,
+Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
+Reserved. All rights under this copyright have been assigned to the US
+Naval Research Laboratory (NRL). The NRL Copyright Notice and License
+Agreement Version 1.1 (January 17, 1995) applies to these portions of the
+software.
+You should have received a copy of the license with this software. If you
+didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
+*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
@@ -66,6 +78,8 @@
int rttrash; /* routes not in table but not freed */
struct sockaddr wildcard; /* zero valued cookie for wildcard searches */
+static int okaytoclone __P((u_int, int));
+
void
rtable_init(table)
void **table;
@@ -84,6 +98,70 @@ route_init()
rtable_init((void **)rt_tables);
}
+void
+rtalloc_noclone(ro, howstrict)
+ register struct route *ro;
+ int howstrict;
+{
+ if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
+ return; /* XXX */
+ ro->ro_rt = rtalloc2(&ro->ro_dst, 1, howstrict);
+}
+
+static int
+okaytoclone(flags, howstrict)
+ u_int flags;
+ int howstrict;
+{
+ if (howstrict == ALL_CLONING)
+ return 1;
+ if (howstrict == ONNET_CLONING && !(flags & (RTF_GATEWAY|RTF_TUNNEL)))
+ return 1;
+ return 0;
+}
+
+struct rtentry *
+rtalloc2(dst, report,howstrict)
+ register struct sockaddr *dst;
+ int report,howstrict;
+{
+ register struct radix_node_head *rnh = rt_tables[dst->sa_family];
+ register struct rtentry *rt;
+ register struct radix_node *rn;
+ struct rtentry *newrt = 0;
+ struct rt_addrinfo info;
+ int s = splnet(), err = 0, msgtype = RTM_MISS;
+
+ if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
+ ((rn->rn_flags & RNF_ROOT) == 0)) {
+ newrt = rt = (struct rtentry *)rn;
+ if (report && (rt->rt_flags & RTF_CLONING) &&
+ okaytoclone(rt->rt_flags, howstrict)) {
+ err = rtrequest(RTM_RESOLVE, dst, SA(0), SA(0), 0,
+ &newrt);
+ if (err) {
+ newrt = rt;
+ rt->rt_refcnt++;
+ goto miss;
+ }
+ if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
+ msgtype = RTM_RESOLVE;
+ goto miss;
+ }
+ } else
+ rt->rt_refcnt++;
+ } else {
+ rtstat.rts_unreach++;
+miss: if (report) {
+ bzero((caddr_t)&info, sizeof(info));
+ info.rti_info[RTAX_DST] = dst;
+ rt_missmsg(msgtype, &info, 0, err);
+ }
+ }
+ splx(s);
+ return (newrt);
+}
+
/*
* Packet routing routines.
*/
@@ -160,7 +238,8 @@ rtfree(rt)
return;
}
ifa = rt->rt_ifa;
- IFAFREE(ifa);
+ if (ifa)
+ IFAFREE(ifa);
Free(rt_key(rt));
Free(rt);
}
@@ -332,6 +411,10 @@ ifa_ifwithroute(flags, dst, gateway)
if (rt == NULL)
return (NULL);
rt->rt_refcnt--;
+ /* The gateway must be local if the same address family. */
+ if (!(flags & RTF_TUNNEL) && (rt->rt_flags & RTF_GATEWAY) &&
+ rt_key(rt)->sa_family == dst->sa_family)
+ return (0);
if ((ifa = rt->rt_ifa) == NULL)
return (NULL);
}
@@ -427,14 +510,36 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
ifa->ifa_refcnt++;
rt->rt_ifa = ifa;
rt->rt_ifp = ifa->ifa_ifp;
- if (req == RTM_RESOLVE)
+ if (req == RTM_RESOLVE) {
+ /*
+ * Copy both metrics and a back pointer to the cloned
+ * route's parent.
+ */
rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
+ rt->rt_parent = *ret_nrt; /* Back ptr. to parent. */
+ }
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : NULL));
if (ret_nrt) {
*ret_nrt = rt;
rt->rt_refcnt++;
}
+#ifdef INET6
+ /* If we have a v4_in_v4 or a v4_in_v6 tunnel route
+ * then do some tunnel state (e.g. security state)
+ * initialization.
+ *
+ * Since IPV6 packets flow down this path, we don't
+ * want it using ipv4_tunnelsetup(rt) (since they
+ * have their own ipv6_tunnel_parent/child()
+ * routines which are called ipv6_rtrequest().)
+ *
+ * Thus, we check to see if the packet is to a v4
+ * destination.
+ */
+ if (dst->sa_family == AF_INET && (rt->rt_flags & RTF_TUNNEL))
+ ipv4_tunnelsetup(rt);
+#endif /* INET6 */
break;
}
bad:
@@ -442,6 +547,17 @@ bad:
return (error);
}
+/*
+ * Set up any tunnel states (e.g. security) information
+ * for v4_in_v4 or v4_in_v6 tunnel routes.
+ */
+void
+ipv4_tunnelsetup(rt)
+ register struct rtentry *rt;
+{
+ /* XXX */
+}
+
int
rt_setgate(rt0, dst, gate)
struct rtentry *rt0;
@@ -545,17 +661,24 @@ rtinit(ifa, cmd, flags)
}
if (cmd == RTM_ADD && error == 0 && (rt = nrt) != NULL) {
rt->rt_refcnt--;
+#ifdef INET6
+ /* Initialize Path MTU for IPv6 interface route */
+ if (ifa->ifa_addr->sa_family == AF_INET6 &&
+ !rt->rt_rmx.rmx_mtu)
+ rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu;
+#endif /* INET6 */
if (rt->rt_ifa != ifa) {
printf("rtinit: wrong ifa (%p) was (%p)\n",
ifa, rt->rt_ifa);
if (rt->rt_ifa->ifa_rtrequest)
- rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(NULL));
+ rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt,
+ SA(NULL));
IFAFREE(rt->rt_ifa);
rt->rt_ifa = ifa;
rt->rt_ifp = ifa->ifa_ifp;
ifa->ifa_refcnt++;
if (ifa->ifa_rtrequest)
- ifa->ifa_rtrequest(RTM_ADD, rt, SA(NULL));
+ ifa->ifa_rtrequest(RTM_ADD, rt, SA(NULL));
}
rt_newaddrmsg(cmd, ifa, error, nrt);
}
diff --git a/sys/net/route.h b/sys/net/route.h
index fa0b3edfd97..39a222057f3 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.h,v 1.3 1998/02/22 01:23:29 niklas Exp $ */
+/* $OpenBSD: route.h,v 1.4 1999/01/08 00:56:06 deraadt Exp $ */
/* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */
/*
@@ -94,8 +94,9 @@ struct rtentry {
#define rt_key(r) ((struct sockaddr *)((r)->rt_nodes->rn_key))
#define rt_mask(r) ((struct sockaddr *)((r)->rt_nodes->rn_mask))
struct sockaddr *rt_gateway; /* value */
- short rt_flags; /* up/down?, host/net */
+ u_int rt_flags; /* up/down?, host/net */
short rt_refcnt; /* # held references */
+ short rt_filler; /* XXX */
u_long rt_use; /* raw # packets forwarded */
struct ifnet *rt_ifp; /* the answer: interface to use */
struct ifaddr *rt_ifa; /* the answer: interface to use */
@@ -103,7 +104,9 @@ struct rtentry {
caddr_t rt_llinfo; /* pointer to link level info cache */
struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */
struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
+ struct rtentry *rt_parent; /* If cloned, parent of this route. */
};
+#define rt_use rt_rmx.rmx_pksent
/*
* Following structure necessary for 4.3 compatibility;
@@ -115,7 +118,7 @@ struct ortentry {
struct sockaddr rt_gateway; /* value */
int16_t rt_flags; /* up/down?, host/net */
int16_t rt_refcnt; /* # held references */
- u_int32_t rt_use; /* raw # packets forwarded */
+ u_int32_t rt_ouse; /* raw # packets forwarded (was: rt_use) */
struct ifnet *rt_ifp; /* the answer: interface to use */
};
@@ -135,6 +138,12 @@ struct ortentry {
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
+/*
+ * New IPv6 routing flags.
+ *
+ * PROTO1 and PROTO2 are used, and defined in netinet6/ipv6_var.h.
+ */
+#define RTF_TUNNEL 0x100000 /* Tunnelling bit. */
/*
* Routing statistics.
@@ -235,6 +244,13 @@ struct route_cb {
(rt)->rt_refcnt--; \
} while (0)
+/*
+ * Values for additional argument to rtalloc_noclone() and rtalloc2()
+ */
+#define ALL_CLONING 0
+#define ONNET_CLONING 1
+#define NO_CLONING 2
+
struct route_cb route_cb;
struct rtstat rtstat;
struct radix_node_head *rt_tables[AF_MAX+1];
@@ -256,6 +272,9 @@ void rtable_init __P((void **));
void rtalloc __P((struct route *));
struct rtentry *
rtalloc1 __P((struct sockaddr *, int));
+void rtalloc_noclone __P((struct route *, int));
+struct rtentry *
+ rtalloc2 __P((struct sockaddr *, int, int));
void rtfree __P((struct rtentry *));
int rtinit __P((struct ifaddr *, int, int));
int rtioctl __P((u_long, caddr_t, struct proc *));
@@ -265,4 +284,5 @@ void rtredirect __P((struct sockaddr *, struct sockaddr *,
int rtrequest __P((int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int,
struct rtentry **));
+void ipv4_tunnelsetup __P((struct rtentry *));
#endif /* _KERNEL */