From: bluhm Date: Tue, 4 Apr 2023 10:12:03 +0000 (+0000) Subject: When sending IP packets to userland with divert-packet rules, the X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=6a006fd4a3095d74aff2cfe0f12b4b6c6261882a;p=openbsd When sending IP packets to userland with divert-packet rules, the checksum may be wrong. Locally generated packets diverted by pf out rules may have no checksum due to to hardware offloading. Calculate the checksum in that case. OK mvs@ sashan@ --- diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 1ca49a1738f..77d7698076a 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_divert.c,v 1.89 2022/10/17 14:49:02 mvs Exp $ */ +/* $OpenBSD: ip_divert.c,v 1.90 2023/04/04 10:12:03 bluhm Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -190,6 +190,8 @@ divert_packet(struct mbuf *m, int dir, u_int16_t divert_port) struct inpcb *inp = NULL; struct socket *so; struct sockaddr_in sin; + struct ip *ip; + int off; divstat_inc(divs_ipackets); @@ -232,6 +234,17 @@ divert_packet(struct mbuf *m, int dir, u_int16_t divert_port) break; } if_put(ifp); + } else { + /* + * Calculate IP and protocol checksums for outbound packet + * diverted to userland. pf rule diverts before cksum offload. + */ + ip = mtod(m, struct ip *); + off = ip->ip_hl << 2; + + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m, off); + in_proto_cksum_out(m, NULL); } mtx_enter(&inp->inp_mtx); diff --git a/sys/netinet6/ip6_divert.c b/sys/netinet6/ip6_divert.c index c7539f64a26..aa7fc4ccdcc 100644 --- a/sys/netinet6/ip6_divert.c +++ b/sys/netinet6/ip6_divert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_divert.c,v 1.88 2022/10/17 14:49:02 mvs Exp $ */ +/* $OpenBSD: ip6_divert.c,v 1.89 2023/04/04 10:12:03 bluhm Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -238,6 +238,12 @@ divert6_packet(struct mbuf *m, int dir, u_int16_t divert_port) break; } if_put(ifp); + } else { + /* + * Calculate protocol checksum for outbound packet diverted + * to userland. pf out rule diverts before cksum offload. + */ + in6_proto_cksum_out(m, NULL); } mtx_enter(&inp->inp_mtx);