diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-01-08 00:56:07 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-01-08 00:56:07 +0000 |
commit | f2b23511b00acad5ac786927adf6ae9f92c43b54 (patch) | |
tree | bcbaacf3eb3bde80221e63ed4d8d89f6633b1d8e /sys/net | |
parent | e95bfef84140b990116d223ce4923feb2f593d86 (diff) |
INET6 support; NRL/cmetz
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/route.c | 133 | ||||
-rw-r--r-- | sys/net/route.h | 26 |
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 */ |