aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_stf.c
diff options
context:
space:
mode:
authorHajimu UMEMOTO <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerHajimu UMEMOTO <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit33841545909f4a4ee94aa148b3a9cbcdc1abb02a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /sys/net/if_stf.c
parent52ebde4fbaab8a8b79de6b17892943783abec7be (diff)
downloadsrc-33841545909f4a4ee94aa148b3a9cbcdc1abb02a.tar.gz
src-33841545909f4a4ee94aa148b3a9cbcdc1abb02a.zip
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks
Notes
Notes: svn path=/head/; revision=78064
Diffstat (limited to 'sys/net/if_stf.c')
-rw-r--r--sys/net/if_stf.c93
1 files changed, 62 insertions, 31 deletions
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index d6a64958ee53..979e6c5ea778 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: if_stf.c,v 1.42 2000/08/15 07:24:23 itojun Exp $ */
+/* $KAME: if_stf.c,v 1.60 2001/05/03 14:51:47 itojun Exp $ */
/*
* Copyright (C) 2000 WIDE Project.
@@ -31,7 +31,7 @@
*/
/*
- * 6to4 interface, based on draft-ietf-ngtrans-6to4-06.txt.
+ * 6to4 interface, based on RFC3056.
*
* 6to4 interface is NOT capable of link-layer (I mean, IPv4) multicasting.
* There is no address mapping defined from IPv6 multicast address to IPv4
@@ -60,12 +60,13 @@
* ICMPv6:
* - Redirects cannot be used due to the lack of link-local address.
*
- * Starting from 04 draft, the specification suggests how to construct
- * link-local address for 6to4 interface.
- * However, it seems to have no real use and does not help the above symptom
- * much. Even if we assign link-locals to interface, we cannot really
- * use link-local unicast/multicast on top of 6to4 cloud, and the above
- * analysis does not change.
+ * stf interface does not have, and will not need, a link-local address.
+ * It seems to have no real benefit and does not help the above symptoms much.
+ * Even if we assign link-locals to interface, we cannot really
+ * use link-local unicast/multicast on top of 6to4 cloud (since there's no
+ * encapsulation defined for link-local address), and the above analysis does
+ * not change. RFC3056 does not mandate the assignment of link-local address
+ * either.
*
* 6to4 interface has security issues. Refer to
* http://playground.iijlab.net/i-d/draft-itojun-ipv6-transition-abuse-00.txt
@@ -159,8 +160,10 @@ static int stf_encapcheck __P((const struct mbuf *, int, int, void *));
static struct in6_ifaddr *stf_getsrcifa6 __P((struct ifnet *));
static int stf_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *));
-static int stf_checkaddr4 __P((struct in_addr *, struct ifnet *));
-static int stf_checkaddr6 __P((struct in6_addr *, struct ifnet *));
+static int stf_checkaddr4 __P((struct stf_softc *, struct in_addr *,
+ struct ifnet *));
+static int stf_checkaddr6 __P((struct stf_softc *, struct in6_addr *,
+ struct ifnet *));
static void stf_rtrequest __P((int, struct rtentry *, struct sockaddr *));
static int stf_ioctl __P((struct ifnet *, u_long, caddr_t));
@@ -197,6 +200,10 @@ stfattach(dummy)
sc->sc_if.if_ioctl = stf_ioctl;
sc->sc_if.if_output = stf_output;
sc->sc_if.if_type = IFT_STF;
+#if 0
+ /* turn off ingress filter */
+ sc->sc_if.if_flags |= IFF_LINK2;
+#endif
sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
if_attach(&sc->sc_if);
#if NBPFILTER > 0
@@ -230,6 +237,10 @@ stf_encapcheck(m, off, proto, arg)
if ((sc->sc_if.if_flags & IFF_UP) == 0)
return 0;
+ /* IFF_LINK0 means "no decapsulation" */
+ if ((sc->sc_if.if_flags & IFF_LINK0) != 0)
+ return 0;
+
if (proto != IPPROTO_IPV6)
return 0;
@@ -317,6 +328,7 @@ stf_output(ifp, m, dst, rt)
{
struct stf_softc *sc;
struct sockaddr_in6 *dst6;
+ struct in_addr *in4;
struct sockaddr_in *dst4;
u_int8_t tos;
struct ip *ip;
@@ -351,6 +363,19 @@ stf_output(ifp, m, dst, rt)
ip6 = mtod(m, struct ip6_hdr *);
tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+ /*
+ * Pickup the right outer dst addr from the list of candidates.
+ * ip6_dst has priority as it may be able to give us shorter IPv4 hops.
+ */
+ if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst))
+ in4 = GET_V4(&ip6->ip6_dst);
+ else if (IN6_IS_ADDR_6TO4(&dst6->sin6_addr))
+ in4 = GET_V4(&dst6->sin6_addr);
+ else {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+
M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
if (m && m->m_len < sizeof(struct ip))
m = m_pullup(m, sizeof(struct ip));
@@ -362,12 +387,14 @@ stf_output(ifp, m, dst, rt)
bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr),
&ip->ip_src, sizeof(ip->ip_src));
- bcopy(GET_V4(&dst6->sin6_addr), &ip->ip_dst, sizeof(ip->ip_dst));
+ bcopy(in4, &ip->ip_dst, sizeof(ip->ip_dst));
ip->ip_p = IPPROTO_IPV6;
ip->ip_ttl = ip_gif_ttl; /*XXX*/
ip->ip_len = m->m_pkthdr.len; /*host order*/
if (ifp->if_flags & IFF_LINK1)
ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos);
+ else
+ ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos);
dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst;
if (dst4->sin_family != AF_INET ||
@@ -394,9 +421,10 @@ stf_output(ifp, m, dst, rt)
}
static int
-stf_checkaddr4(in, ifp)
+stf_checkaddr4(sc, in, inifp)
+ struct stf_softc *sc;
struct in_addr *in;
- struct ifnet *ifp; /* incoming interface */
+ struct ifnet *inifp; /* incoming interface */
{
struct in_ifaddr *ia4;
@@ -427,7 +455,7 @@ stf_checkaddr4(in, ifp)
/*
* perform ingress filter
*/
- if (ifp) {
+ if (sc && (sc->sc_if.if_flags & IFF_LINK2) == 0 && inifp) {
struct sockaddr_in sin;
struct rtentry *rt;
@@ -436,10 +464,14 @@ stf_checkaddr4(in, ifp)
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_addr = *in;
rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
- if (!rt)
- return -1;
- if (rt->rt_ifp != ifp) {
- rtfree(rt);
+ if (!rt || rt->rt_ifp != inifp) {
+#if 0
+ log(LOG_WARNING, "%s: packet from 0x%x dropped "
+ "due to ingress filter\n", if_name(&sc->sc_if),
+ (u_int32_t)ntohl(sin.sin_addr.s_addr));
+#endif
+ if (rt)
+ rtfree(rt);
return -1;
}
rtfree(rt);
@@ -449,15 +481,16 @@ stf_checkaddr4(in, ifp)
}
static int
-stf_checkaddr6(in6, ifp)
+stf_checkaddr6(sc, in6, inifp)
+ struct stf_softc *sc;
struct in6_addr *in6;
- struct ifnet *ifp; /* incoming interface */
+ struct ifnet *inifp; /* incoming interface */
{
/*
* check 6to4 addresses
*/
if (IN6_IS_ADDR_6TO4(in6))
- return stf_checkaddr4(GET_V4(in6), ifp);
+ return stf_checkaddr4(sc, GET_V4(in6), inifp);
/*
* reject anything that look suspicious. the test is implemented
@@ -476,7 +509,7 @@ void
in_stf_input(struct mbuf *m, ...)
#else
in_stf_input(m, va_alist)
- register struct mbuf *m;
+ struct mbuf *m;
#endif
{
int off, proto;
@@ -514,8 +547,8 @@ in_stf_input(m, va_alist)
* perform sanity check against outer src/dst.
* for source, perform ingress filter as well.
*/
- if (stf_checkaddr4(&ip->ip_dst, NULL) < 0 ||
- stf_checkaddr4(&ip->ip_src, m->m_pkthdr.rcvif) < 0) {
+ if (stf_checkaddr4(sc, &ip->ip_dst, NULL) < 0 ||
+ stf_checkaddr4(sc, &ip->ip_src, m->m_pkthdr.rcvif) < 0) {
m_freem(m);
return;
}
@@ -534,8 +567,8 @@ in_stf_input(m, va_alist)
* perform sanity check against inner src/dst.
* for source, perform ingress filter as well.
*/
- if (stf_checkaddr6(&ip6->ip6_dst, NULL) < 0 ||
- stf_checkaddr6(&ip6->ip6_src, m->m_pkthdr.rcvif) < 0) {
+ if (stf_checkaddr6(sc, &ip6->ip6_dst, NULL) < 0 ||
+ stf_checkaddr6(sc, &ip6->ip6_src, m->m_pkthdr.rcvif) < 0) {
m_freem(m);
return;
}
@@ -543,6 +576,8 @@ in_stf_input(m, va_alist)
itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
if ((ifp->if_flags & IFF_LINK1) != 0)
ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
+ else
+ ip_ecn_egress(ECN_NOCARE, &otos, &itos);
ip6->ip6_flow &= ~htonl(0xff << 20);
ip6->ip6_flow |= htonl((u_int32_t)itos << 20);
@@ -558,7 +593,7 @@ in_stf_input(m, va_alist)
* try to free it or keep a pointer a to it).
*/
struct mbuf m0;
- u_int af = AF_INET6;
+ u_int32_t af = AF_INET6;
m0.m_next = m;
m0.m_len = 4;
@@ -594,11 +629,7 @@ static void
stf_rtrequest(cmd, rt, sa)
int cmd;
struct rtentry *rt;
-#if defined(__bsdi__) && _BSDI_VERSION >= 199802
- struct rt_addrinfo *sa;
-#else
struct sockaddr *sa;
-#endif
{
if (rt)