summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in_gif.c
diff options
context:
space:
mode:
authorshin <shin@FreeBSD.org>2000-03-11 11:17:24 +0000
committershin <shin@FreeBSD.org>2000-03-11 11:17:24 +0000
commit4897d4b884a45fa62be25d44438c46c8b795c36c (patch)
tree62045144ea41cdf658b5188ff11cd090c84f819d /sys/netinet/in_gif.c
parent843cb7cecfa2978f81dbd98715c6cd6f8bc90bcf (diff)
downloadFreeBSD-src-4897d4b884a45fa62be25d44438c46c8b795c36c.zip
FreeBSD-src-4897d4b884a45fa62be25d44438c46c8b795c36c.tar.gz
IPv6 6to4 support.
Now most big problem of IPv6 is getting IPv6 address assignment. 6to4 solve the problem. 6to4 addr is defined like below, 2002: 4byte v4 addr : 2byte SLA ID : 8byte interface ID The most important point of the address format is that an IPv4 addr is embeded in it. So any user who has IPv4 addr can get IPv6 address block with 2byte subnet space. Also, the IPv4 addr is used for semi-automatic IPv6 over IPv4 tunneling. With 6to4, getting IPv6 addr become dramatically easy. The attached patch enable 6to4 extension, and confirmed to work, between "Richard Seaman, Jr." <dick@tar.com> and me. Approved by: jkh Reviewed by: itojun
Diffstat (limited to 'sys/netinet/in_gif.c')
-rw-r--r--sys/netinet/in_gif.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index 021c800..9348a53 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -84,6 +84,9 @@ SYSCTL_DECL(_net_inet_ip);
SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
&ip_gif_ttl, 0, "");
+#define IN6_IS_ADDR_6TO4(x) (ntohs((x)->s6_addr16[0]) == 0x2002)
+#define GET_V4(x) ((struct in_addr *)(&(x)->s6_addr16[1]))
+
int
in_gif_output(ifp, family, m, rt)
struct ifnet *ifp;
@@ -98,6 +101,9 @@ in_gif_output(ifp, family, m, rt)
struct ip iphdr; /* capsule IP header, host byte ordered */
int proto, error;
u_int8_t tos;
+#ifdef INET6
+ struct ip6_hdr *ip6 = NULL;
+#endif
if (sin_src == NULL || sin_dst == NULL ||
sin_src->sin_family != AF_INET ||
@@ -124,7 +130,6 @@ in_gif_output(ifp, family, m, rt)
#ifdef INET6
case AF_INET6:
{
- struct ip6_hdr *ip6;
proto = IPPROTO_IPV6;
if (m->m_len < sizeof(*ip6)) {
m = m_pullup(m, sizeof(*ip6));
@@ -147,6 +152,28 @@ in_gif_output(ifp, family, m, rt)
bzero(&iphdr, sizeof(iphdr));
iphdr.ip_src = sin_src->sin_addr;
+#ifdef INET6
+ /* XXX: temporal stf support hack */
+ if (bcmp(ifp->if_name, "stf", 3) == 0 && ip6 != NULL) {
+ if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst))
+ iphdr.ip_dst = *GET_V4(&ip6->ip6_dst);
+ else if (rt && rt->rt_gateway->sa_family == AF_INET6) {
+ struct in6_addr *dst6;
+
+ dst6 = &((struct sockaddr_in6 *)
+ (rt->rt_gateway))->sin6_addr;
+ if (IN6_IS_ADDR_6TO4(dst6))
+ iphdr.ip_dst = *GET_V4(dst6);
+ else {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+ } else {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+ } else
+#endif
if (ifp->if_flags & IFF_LINK0) {
/* multi-destination mode */
if (sin_dst->sin_addr.s_addr != INADDR_ANY)
@@ -233,6 +260,20 @@ in_gif_input(struct mbuf *m, int off, int proto)
if ((sc->gif_if.if_flags & IFF_UP) == 0)
continue;
+#ifdef INET6
+ /* XXX: temporal stf support hack */
+ if (proto == IPPROTO_IPV6 &&
+ bcmp(sc->gif_if.if_name, "stf", 3) == 0 &&
+ (satosin(sc->gif_psrc)->sin_addr.s_addr ==
+ ip->ip_dst.s_addr ||
+ IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) &&
+ satosin(sc->gif_pdst)->sin_addr.s_addr ==
+ INADDR_BROADCAST) {
+ gifp = &sc->gif_if;
+ break;
+ }
+#endif
+
if ((sc->gif_if.if_flags & IFF_LINK0)
&& satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
&& satosin(sc->gif_pdst)->sin_addr.s_addr == INADDR_ANY) {
OpenPOWER on IntegriCloud