diff options
-rw-r--r-- | sys/net/if_gif.c | 19 | ||||
-rw-r--r-- | sys/netinet/in_gif.c | 43 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 2 |
4 files changed, 61 insertions, 5 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 06a3469..0b32657 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -83,7 +83,7 @@ void gifattach __P((void *)); /* * gif global variable definitions */ -int ngif = NGIF; /* number of interfaces */ +int ngif = NGIF + 1; /* number of interfaces. +1 for stf. */ struct gif_softc *gif = 0; void @@ -95,7 +95,7 @@ gifattach(dummy) gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT); bzero(sc, ngif * sizeof(struct gif_softc)); - for (i = 0; i < ngif; sc++, i++) { + for (i = 0; i < ngif - 1; sc++, i++) { /* leave last one for stf */ sc->gif_if.if_name = "gif"; sc->gif_if.if_unit = i; sc->gif_if.if_mtu = GIF_MTU; @@ -107,6 +107,16 @@ gifattach(dummy) if_attach(&sc->gif_if); bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int)); } + sc->gif_if.if_name = "stf"; + sc->gif_if.if_unit = 0; + sc->gif_if.if_mtu = GIF_MTU; + sc->gif_if.if_flags = IFF_MULTICAST; + sc->gif_if.if_ioctl = gif_ioctl; + sc->gif_if.if_output = gif_output; + sc->gif_if.if_type = IFT_GIF; + sc->gif_if.if_snd.ifq_maxlen = ifqmaxlen; + if_attach(&sc->gif_if); + bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int)); } PSEUDO_SET(gifattach, if_gif); @@ -323,6 +333,11 @@ gif_ioctl(ifp, cmd, data) /* only one gif can have dst = INADDR_ANY */ #define satosaddr(sa) (((struct sockaddr_in *)(sa))->sin_addr.s_addr) +#ifdef INET6 + if (bcmp(ifp->if_name, "stf", 3) == 0) + satosaddr(dst) = INADDR_BROADCAST; +#endif + if (satosaddr(dst) == INADDR_ANY) { int i; struct gif_softc *sc2; 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) { diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index b802880..1d2d8c3 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -643,7 +643,7 @@ findpcb: #ifdef INET6 /* save packet options if user wanted */ - if (inp->in6p_flags & INP_CONTROLOPTS) { + if (isipv6 && inp->in6p_flags & INP_CONTROLOPTS) { if (inp->in6p_options) { m_freem(inp->in6p_options); inp->in6p_options = 0; diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index b802880..1d2d8c3 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -643,7 +643,7 @@ findpcb: #ifdef INET6 /* save packet options if user wanted */ - if (inp->in6p_flags & INP_CONTROLOPTS) { + if (isipv6 && inp->in6p_flags & INP_CONTROLOPTS) { if (inp->in6p_options) { m_freem(inp->in6p_options); inp->in6p_options = 0; |