Hi,

I noticed a missing checksum count in netstat tcp packets sent
software-checksummed.  Turns out that our syn cache does the checksum
calculation by hand, instead of the established mechanism in ip
output.

Just set the flag M_TCP_CSUM_OUT and let in_proto_cksum_out() do
the work later.

While there remove redundant code.  The unhandled af case is handled
in the first switch statement of the function.

ok?

bluhm

Index: netinet/tcp_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.387
diff -u -p -r1.387 tcp_input.c
--- netinet/tcp_input.c 14 Mar 2023 00:24:05 -0000      1.387
+++ netinet/tcp_input.c 22 May 2023 19:48:25 -0000
@@ -3990,14 +3990,11 @@ syn_cache_respond(struct syn_cache *sc, 
                ip6->ip6_dst = sc->sc_src.sin6.sin6_addr;
                ip6->ip6_src = sc->sc_dst.sin6.sin6_addr;
                ip6->ip6_nxt = IPPROTO_TCP;
-               /* ip6_plen will be updated in ip6_output() */
                th = (struct tcphdr *)(ip6 + 1);
                th->th_dport = sc->sc_src.sin6.sin6_port;
                th->th_sport = sc->sc_dst.sin6.sin6_port;
                break;
 #endif
-       default:
-               unhandled_af(sc->sc_src.sa.sa_family);
        }
 
        th->th_seq = htonl(sc->sc_iss);
@@ -4096,21 +4093,7 @@ syn_cache_respond(struct syn_cache *sc, 
        }
 #endif /* TCP_SIGNATURE */
 
-       /* Compute the packet's checksum. */
-       switch (sc->sc_src.sa.sa_family) {
-       case AF_INET:
-               ip->ip_len = htons(tlen - hlen);
-               th->th_sum = 0;
-               th->th_sum = in_cksum(m, tlen);
-               break;
-#ifdef INET6
-       case AF_INET6:
-               ip6->ip6_plen = htons(tlen - hlen);
-               th->th_sum = 0;
-               th->th_sum = in6_cksum(m, IPPROTO_TCP, hlen, tlen - hlen);
-               break;
-#endif
-       }
+       SET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT);
 
        /* use IPsec policy and ttl from listening socket, on SYN ACK */
        inp = sc->sc_tp ? sc->sc_tp->t_inpcb : NULL;
@@ -4125,34 +4108,22 @@ syn_cache_respond(struct syn_cache *sc, 
                ip->ip_ttl = inp ? inp->inp_ip.ip_ttl : ip_defttl;
                if (inp != NULL)
                        ip->ip_tos = inp->inp_ip.ip_tos;
-               break;
-#ifdef INET6
-       case AF_INET6:
-               ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
-               ip6->ip6_vfc |= IPV6_VERSION;
-               ip6->ip6_plen = htons(tlen - hlen);
-               /* ip6_hlim will be initialized afterwards */
-               /* leave flowlabel = 0, it is legal and require no state mgmt */
-               break;
-#endif
-       }
 
-       switch (sc->sc_src.sa.sa_family) {
-       case AF_INET:
                error = ip_output(m, sc->sc_ipopts, &sc->sc_route4,
                    (ip_mtudisc ? IP_MTUDISC : 0),  NULL, inp, 0);
                break;
 #ifdef INET6
        case AF_INET6:
+               ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
+               ip6->ip6_vfc |= IPV6_VERSION;
+               /* ip6_plen will be updated in ip6_output() */
                ip6->ip6_hlim = in6_selecthlim(inp);
+               /* leave flowlabel = 0, it is legal and require no state mgmt */
 
                error = ip6_output(m, NULL /*XXX*/, &sc->sc_route6, 0,
                    NULL, NULL);
                break;
 #endif
-       default:
-               error = EAFNOSUPPORT;
-               break;
        }
        return (error);
 }

Reply via email to