diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2016-10-18 11:20:43 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2016-10-18 11:20:43 +0000 |
commit | c0edf1d09650bff29054261f1bad27931590c156 (patch) | |
tree | 27a5b304241e667f455648dad96cd8b456d69729 /sys/net | |
parent | 2febd3c4ff6e2a5cc67ea4a7965a0f6448466069 (diff) |
The checksum of a ICMP "need to frag" packet for TCP was wrong when
created from a ICMP6 "too big" packet. The function pf_change_icmp_af()
has code to adjust the pseudo-header checksum in the ICMP6 case,
but pf_test_state_icmp() changed the proto before the case was
entered.
So call pf_change_icmp_af() before the pd->proto is converted in
the TCP and UDP payload case like it was already done for ICMP and
ICMP6 payload.
Found by sys/net/pf_forward regress test; OK henning@
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/pf.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c index 340a8f695b6..aa7b9f33b8a 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.989 2016/10/09 18:01:57 henning Exp $ */ +/* $OpenBSD: pf.c,v 1.990 2016/10/18 11:20:42 bluhm Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -5104,6 +5104,10 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state, m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), pd->hdr.icmp6, M_NOWAIT); + if (pf_change_icmp_af(pd->m, ipoff2, + pd, &pd2, &nk->addr[sidx], + &nk->addr[didx], pd->af, nk->af)) + return (PF_DROP); if (nk->af == AF_INET) pd->proto = IPPROTO_ICMP; else @@ -5117,11 +5121,6 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state, &nk->addr[pd2.didx], nk->af); pd->naf = nk->af; - if (pf_change_icmp_af(pd->m, ipoff2, - pd, &pd2, &nk->addr[sidx], - &nk->addr[didx], pd->af, nk->af)) - return (PF_DROP); - pf_patch_16(pd, &th.th_sport, nk->port[sidx]); pf_patch_16(pd, @@ -5220,6 +5219,10 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state, m_copyback(pd->m, pd->off, sizeof(struct icmp6_hdr), pd->hdr.icmp6, M_NOWAIT); + if (pf_change_icmp_af(pd->m, ipoff2, + pd, &pd2, &nk->addr[sidx], + &nk->addr[didx], pd->af, nk->af)) + return (PF_DROP); if (nk->af == AF_INET) pd->proto = IPPROTO_ICMP; else @@ -5233,11 +5236,6 @@ pf_test_state_icmp(struct pf_pdesc *pd, struct pf_state **state, &nk->addr[pd2.didx], nk->af); pd->naf = nk->af; - if (pf_change_icmp_af(pd->m, ipoff2, - pd, &pd2, &nk->addr[sidx], - &nk->addr[didx], pd->af, nk->af)) - return (PF_DROP); - pf_patch_16(pd, &uh.uh_sport, nk->port[sidx]); pf_patch_16(pd, |