When sending IP packets to userland with divert-packet rules, the
authorbluhm <bluhm@openbsd.org>
Tue, 4 Apr 2023 10:12:03 +0000 (10:12 +0000)
committerbluhm <bluhm@openbsd.org>
Tue, 4 Apr 2023 10:12:03 +0000 (10:12 +0000)
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@

sys/netinet/ip_divert.c
sys/netinet6/ip6_divert.c

index 1ca49a1..77d7698 100644 (file)
@@ -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 <michele@openbsd.org>
@@ -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);
index c7539f6..aa7fc4c 100644 (file)
@@ -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 <michele@openbsd.org>
@@ -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);