diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_ecn.c | 23 | ||||
-rw-r--r-- | sys/netinet/ip_ecn.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_ipip.c | 10 |
3 files changed, 28 insertions, 8 deletions
diff --git a/sys/netinet/ip_ecn.c b/sys/netinet/ip_ecn.c index e5d6cf249bb..b4621a019f1 100644 --- a/sys/netinet/ip_ecn.c +++ b/sys/netinet/ip_ecn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ecn.c,v 1.8 2016/09/24 14:51:37 naddy Exp $ */ +/* $OpenBSD: ip_ecn.c,v 1.9 2018/11/14 23:55:04 dlg Exp $ */ /* $KAME: ip_ecn.c,v 1.9 2000/10/01 12:44:48 itojun Exp $ */ /* @@ -154,3 +154,24 @@ ip_ecn_egress(int mode, u_int8_t *outer, u_int8_t *inner) } return (1); } + +/* + * Patch the checksum with the difference between the old and new tos. + * The patching is based on what pf_patch_8() and pf_cksum_fixkup() do, + * but they're in pf, so we can't rely on them being available. + */ +void +ip_tos_patch(struct ip *ip, uint8_t tos) +{ + uint16_t old; + uint16_t new; + uint32_t x; + + old = htons(ip->ip_tos); + new = htons(tos); + + ip->ip_tos = tos; + + x = ip->ip_sum + old - new; + ip->ip_sum = (x) + (x >> 16); +} diff --git a/sys/netinet/ip_ecn.h b/sys/netinet/ip_ecn.h index d6a8b166f1a..6f3d552468f 100644 --- a/sys/netinet/ip_ecn.h +++ b/sys/netinet/ip_ecn.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ecn.h,v 1.6 2012/03/15 16:37:11 markus Exp $ */ +/* $OpenBSD: ip_ecn.h,v 1.7 2018/11/14 23:55:04 dlg Exp $ */ /* $KAME: ip_ecn.h,v 1.5 2000/03/27 04:58:38 sumikawa Exp $ */ /* @@ -47,5 +47,6 @@ #if defined(_KERNEL) extern void ip_ecn_ingress(int, u_int8_t *, u_int8_t *); extern int ip_ecn_egress(int, u_int8_t *, u_int8_t *); +void ip_tos_patch(struct ip *, uint8_t); #endif /* _KERNEL */ #endif /* _NETINET_IP_ECN_H_ */ diff --git a/sys/netinet/ip_ipip.c b/sys/netinet/ip_ipip.c index 60d6efdc284..b8c90fd702e 100644 --- a/sys/netinet/ip_ipip.c +++ b/sys/netinet/ip_ipip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipip.c,v 1.88 2018/08/28 15:15:02 mpi Exp $ */ +/* $OpenBSD: ip_ipip.c,v 1.89 2018/11/14 23:55:04 dlg Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -239,16 +239,14 @@ ipip_input_if(struct mbuf **mp, int *offp, int proto, int oaf, itos = ip->ip_tos; mode = m->m_flags & (M_AUTH|M_CONF) ? ECN_ALLOWED_IPSEC : ECN_ALLOWED; - if (!ip_ecn_egress(mode, &otos, &ip->ip_tos)) { + if (!ip_ecn_egress(mode, &otos, &itos)) { DPRINTF(("%s: ip_ecn_egress() failed\n", __func__)); ipipstat_inc(ipips_pdrops); goto bad; } /* re-calculate the checksum if ip_tos was changed */ - if (itos != ip->ip_tos) { - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m, hlen); - } + if (itos != ip->ip_tos) + ip_tos_patch(ip, itos); break; #ifdef INET6 case IPPROTO_IPV6: |