diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2012-03-15 16:37:12 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2012-03-15 16:37:12 +0000 |
commit | f691a48ee80ba746816d740ae0db5392c17d24c9 (patch) | |
tree | 052795a75d64c1dc64bc1912609e4031721ce304 /sys/netinet/ip_ipip.c | |
parent | e4afdbb46f47650f9cc49d61eb48ad859fbaf606 (diff) |
improve IPsec/ENC interaction:
- ipip_input() recalculate the IP header checksum if the tos bits
are changed after decapsulation. Otherwise these packets are
dropped later in the stack.
- ip_ecn_egress(): do not drop packets for IPsec if the outter
packet of a Tunnel has the ECN-CE bit set (Congestion Experienced)
and the inner packet does not indicate support ECN.
- remove unused ip6_ecn_ingress(), ip6_ecn_egress() code
ok mikeb@
Diffstat (limited to 'sys/netinet/ip_ipip.c')
-rw-r--r-- | sys/netinet/ip_ipip.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/sys/netinet/ip_ipip.c b/sys/netinet/ip_ipip.c index 6a48e52bb0b..24e89044b67 100644 --- a/sys/netinet/ip_ipip.c +++ b/sys/netinet/ip_ipip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipip.c,v 1.47 2010/05/11 09:36:07 claudio Exp $ */ +/* $OpenBSD: ip_ipip.c,v 1.48 2012/03/15 16:37:11 markus Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -156,11 +156,10 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp, int proto) #ifdef INET6 struct sockaddr_in6 *sin6; struct ip6_hdr *ip6; - u_int8_t itos; #endif int isr; - int hlen, s; - u_int8_t otos; + int mode, hlen, s; + u_int8_t itos, otos; u_int8_t v; sa_family_t af; @@ -266,10 +265,23 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp, int proto) #ifdef INET6 ip6 = NULL; #endif - if (!ip_ecn_egress(ECN_ALLOWED, &otos, &ipo->ip_tos)) { + itos = ipo->ip_tos; + mode = m->m_flags & (M_AUTH|M_CONF) ? + ECN_ALLOWED_IPSEC : ECN_ALLOWED; + if (!ip_ecn_egress(mode, &otos, &ipo->ip_tos)) { + DPRINTF(("ipip_input(): ip_ecn_egress() failed")); + ipipstat.ipips_pdrops++; m_freem(m); return; } + /* re-calculate the checksum if ip_tos was changed */ + if (itos != ipo->ip_tos) { + hlen = ipo->ip_hl << 2; + if (m->m_pkthdr.len >= hlen) { + ipo->ip_sum = 0; + ipo->ip_sum = in_cksum(m, hlen); + } + } break; #endif /* INET */ #ifdef INET6 @@ -280,6 +292,8 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp, int proto) ip6 = mtod(m, struct ip6_hdr *); itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; if (!ip_ecn_egress(ECN_ALLOWED, &otos, &itos)) { + DPRINTF(("ipip_input(): ip_ecn_egress() failed")); + ipipstat.ipips_pdrops++; m_freem(m); return; } |