summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_ipip.c
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2012-03-15 16:37:12 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2012-03-15 16:37:12 +0000
commitf691a48ee80ba746816d740ae0db5392c17d24c9 (patch)
tree052795a75d64c1dc64bc1912609e4031721ce304 /sys/netinet/ip_ipip.c
parente4afdbb46f47650f9cc49d61eb48ad859fbaf606 (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.c24
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;
}