summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordhartmei <dhartmei@openbsd.org>2004-12-05 12:12:01 +0000
committerdhartmei <dhartmei@openbsd.org>2004-12-05 12:12:01 +0000
commit2d84e39b7ea51a9ee3e3cb9feeb91f31d1da089d (patch)
tree2285d3b076a924f45c95debb0a2b2920bd9dbbcf
parentafter attaching an overload table, set its active flag. otherwise, the (diff)
downloadwireguard-openbsd-2d84e39b7ea51a9ee3e3cb9feeb91f31d1da089d.tar.xz
wireguard-openbsd-2d84e39b7ea51a9ee3e3cb9feeb91f31d1da089d.zip
IPv6 packets can contain headers (like options) before the TCP/UDP/ICMP6
header. pf finds the first TCP/UDP/ICMP6 header to filter by traversing the header chain. In the case where headers are skipped, the protocol checksum verification used the wrong length (included the skipped headers), leading to incorrectly mismatching checksums. Such IPv6 packets with headers were silently dropped. Reported by Bernhard Schmidt. ok mcbride@
-rw-r--r--sys/net/pf.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 4f69b9afdb9..628b41cdf23 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.465 2004/12/04 07:49:48 mcbride Exp $ */
+/* $OpenBSD: pf.c,v 1.466 2004/12/05 12:12:01 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -5469,7 +5469,7 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
return (1);
if (m->m_pkthdr.len < off + len)
return (1);
- switch (af) {
+ switch (af) {
#ifdef INET
case AF_INET:
if (p == IPPROTO_ICMP) {
@@ -5947,7 +5947,8 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
goto done;
}
if (dir == PF_IN && pf_check_proto_cksum(m, off,
- ntohs(h->ip6_plen), IPPROTO_TCP, AF_INET6)) {
+ ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
+ IPPROTO_TCP, AF_INET6)) {
action = PF_DROP;
goto done;
}
@@ -5980,7 +5981,8 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
goto done;
}
if (dir == PF_IN && uh.uh_sum && pf_check_proto_cksum(m,
- off, ntohs(h->ip6_plen), IPPROTO_UDP, AF_INET6)) {
+ off, ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
+ IPPROTO_UDP, AF_INET6)) {
action = PF_DROP;
goto done;
}
@@ -6014,7 +6016,8 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
goto done;
}
if (dir == PF_IN && pf_check_proto_cksum(m, off,
- ntohs(h->ip6_plen), IPPROTO_ICMPV6, AF_INET6)) {
+ ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
+ IPPROTO_ICMPV6, AF_INET6)) {
action = PF_DROP;
goto done;
}