1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-04 23:35:36 -08:00

Recalculate checksum of normalised packet

In 2011, henning@ removed fiddling with the ip checksum of normalised
packets in r1.131 of sys/net/pf_norm.c. Rationale was that the checksum
is always recalculated in all output paths anyway. In 2016, procter@
reintroduced checksum modification to preserve end-to-end checksums in
r1.189 of sys/net/pf_norm.c. Likely soomewhere in that timeslot checksum
recalculation of normalised packets was broken.

With input from bluhm@.

OK sashan@, bluhm@
This commit is contained in:
bket 2022-10-10 16:43:12 +00:00
parent 6e8568b906
commit 33c43c6d64
3 changed files with 28 additions and 9 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pf.c,v 1.1140 2022/09/03 19:22:19 bluhm Exp $ */
/* $OpenBSD: pf.c,v 1.1141 2022/10/10 16:43:12 bket Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@ -164,7 +164,7 @@ void pf_add_threshold(struct pf_threshold *);
int pf_check_threshold(struct pf_threshold *);
int pf_check_tcp_cksum(struct mbuf *, int, int,
sa_family_t);
static __inline void pf_cksum_fixup(u_int16_t *, u_int16_t, u_int16_t,
__inline void pf_cksum_fixup(u_int16_t *, u_int16_t, u_int16_t,
u_int8_t);
void pf_cksum_fixup_a(u_int16_t *, const struct pf_addr *,
const struct pf_addr *, sa_family_t, u_int8_t);
@ -1937,7 +1937,7 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
* Note: this serves also as a reduction step for at most one add (as the
* trailing mod 2^16 prevents further reductions by destroying carries).
*/
static __inline void
__inline void
pf_cksum_fixup(u_int16_t *cksum, u_int16_t was, u_int16_t now,
u_int8_t proto)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pf_norm.c,v 1.224 2022/08/22 20:35:39 bluhm Exp $ */
/* $OpenBSD: pf_norm.c,v 1.225 2022/10/10 16:43:12 bket Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@ -1646,14 +1646,21 @@ pf_scrub(struct mbuf *m, u_int16_t flags, sa_family_t af, u_int8_t min_ttl,
#ifdef INET6
struct ip6_hdr *h6 = mtod(m, struct ip6_hdr *);
#endif /* INET6 */
u_int16_t old;
/* Clear IP_DF if no-df was requested */
if (flags & PFSTATE_NODF && af == AF_INET && h->ip_off & htons(IP_DF))
if (flags & PFSTATE_NODF && af == AF_INET && h->ip_off & htons(IP_DF)) {
old = h->ip_off;
h->ip_off &= htons(~IP_DF);
pf_cksum_fixup(&h->ip_sum, old, h->ip_off, 0);
}
/* Enforce a minimum ttl, may cause endless packet loops */
if (min_ttl && af == AF_INET && h->ip_ttl < min_ttl)
if (min_ttl && af == AF_INET && h->ip_ttl < min_ttl) {
old = h->ip_ttl;
h->ip_ttl = min_ttl;
pf_cksum_fixup(&h->ip_sum, old, h->ip_ttl, 0);
}
#ifdef INET6
if (min_ttl && af == AF_INET6 && h6->ip6_hlim < min_ttl)
h6->ip6_hlim = min_ttl;
@ -1661,8 +1668,15 @@ pf_scrub(struct mbuf *m, u_int16_t flags, sa_family_t af, u_int8_t min_ttl,
/* Enforce tos */
if (flags & PFSTATE_SETTOS) {
if (af == AF_INET)
if (af == AF_INET) {
/*
* ip_tos is 8 bit field at offset 1. Use 16 bit value
* at offset 0.
*/
old = *(u_int16_t *)h;
h->ip_tos = tos | (h->ip_tos & IPTOS_ECN_MASK);
pf_cksum_fixup(&h->ip_sum, old, *(u_int16_t *)h, 0);
}
#ifdef INET6
if (af == AF_INET6) {
/* drugs are unable to explain such idiocy */
@ -1674,6 +1688,9 @@ pf_scrub(struct mbuf *m, u_int16_t flags, sa_family_t af, u_int8_t min_ttl,
/* random-id, but not for fragments */
if (flags & PFSTATE_RANDOMID && af == AF_INET &&
!(h->ip_off & ~htons(IP_DF)))
!(h->ip_off & ~htons(IP_DF))) {
old = h->ip_id;
h->ip_id = htons(ip_randomid());
pf_cksum_fixup(&h->ip_sum, old, h->ip_id, 0);
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pfvar.h,v 1.510 2022/09/03 14:57:54 yasuoka Exp $ */
/* $OpenBSD: pfvar.h,v 1.511 2022/10/10 16:43:12 bket Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@ -1745,6 +1745,8 @@ extern void pf_print_state(struct pf_state *);
extern void pf_print_flags(u_int8_t);
extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
sa_family_t);
extern void pf_cksum_fixup(u_int16_t *, u_int16_t,
u_int16_t, u_int8_t);
void pf_rm_rule(struct pf_rulequeue *,
struct pf_rule *);
void pf_purge_rule(struct pf_rule *);