summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2021-02-06 13:15:38 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2021-02-06 13:15:38 +0000
commit18832472191f327dbb28e24e61d7f2f27882de25 (patch)
treec503a3c926b80ebe23f2903e652cca6fcd1670c9 /sys
parent820a444e54da8488f0f2129a2d7f347d63967218 (diff)
Simplex interface sends packet back without hardware checksum
offloading. The checksum must be calculated in software. Use the same condition in ether_resolve() to send the broadcast packet back to the stack and in in_ifcap_cksum() to force software checksumming. This fixes regress/sys/kern/sosplice/loop. OK procter@
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_ethersubr.c8
-rw-r--r--sys/netinet/ip_output.c41
2 files changed, 34 insertions, 15 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 6a8c678c6bf..47d74957fdf 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ethersubr.c,v 1.269 2021/02/05 16:47:48 bluhm Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.270 2021/02/06 13:15:37 bluhm Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
@@ -227,7 +227,11 @@ ether_resolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
return (error);
eh->ether_type = htons(ETHERTYPE_IP);
- /* If broadcasting on a simplex interface, loopback a copy */
+ /*
+ * If broadcasting on a simplex interface, loopback a copy.
+ * The checksum must be calculated in software. Keep the
+ * condition in sync with in_ifcap_cksum().
+ */
if (ISSET(m->m_flags, M_BCAST) &&
ISSET(ifp->if_flags, IFF_SIMPLEX) &&
!m->m_pkthdr.pf.routed) {
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index cd84b3a0833..b32adb453fe 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.363 2021/02/02 17:47:42 claudio Exp $ */
+/* $OpenBSD: ip_output.c,v 1.364 2021/02/06 13:15:37 bluhm Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -79,6 +79,7 @@ void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *);
static __inline u_int16_t __attribute__((__unused__))
in_cksum_phdr(u_int32_t, u_int32_t, u_int32_t);
void in_delayed_cksum(struct mbuf *);
+int in_ifcap_cksum(struct mbuf *, struct ifnet *, int);
#ifdef IPSEC
struct tdb *
@@ -458,8 +459,7 @@ sendit:
*/
if (ntohs(ip->ip_len) <= mtu) {
ip->ip_sum = 0;
- if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
- (ifp->if_bridgeidx == 0))
+ if (in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4))
m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
else {
ipstat_inc(ips_outswcsum);
@@ -719,9 +719,7 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
m->m_pkthdr.ph_ifidx = 0;
mhip->ip_off = htons((u_int16_t)mhip->ip_off);
mhip->ip_sum = 0;
- if ((ifp != NULL) &&
- (ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
- (ifp->if_bridgeidx == 0))
+ if (in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4))
m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
else {
ipstat_inc(ips_outswcsum);
@@ -740,9 +738,7 @@ ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
ip->ip_len = htons((u_int16_t)m->m_pkthdr.len);
ip->ip_off |= htons(IP_MF);
ip->ip_sum = 0;
- if ((ifp != NULL) &&
- (ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
- (ifp->if_bridgeidx == 0))
+ if (in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4))
m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
else {
ipstat_inc(ips_outswcsum);
@@ -1855,15 +1851,15 @@ in_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
}
if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) {
- if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
- ip->ip_hl != 5 || ifp->if_bridgeidx != 0) {
+ if (!in_ifcap_cksum(m, ifp, IFCAP_CSUM_TCPv4) ||
+ ip->ip_hl != 5) {
tcpstat_inc(tcps_outswcsum);
in_delayed_cksum(m);
m->m_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT; /* Clear */
}
} else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
- if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
- ip->ip_hl != 5 || ifp->if_bridgeidx != 0) {
+ if (!in_ifcap_cksum(m, ifp, IFCAP_CSUM_UDPv4) ||
+ ip->ip_hl != 5) {
udpstat_inc(udps_outswcsum);
in_delayed_cksum(m);
m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */
@@ -1873,3 +1869,22 @@ in_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */
}
}
+
+int
+in_ifcap_cksum(struct mbuf *m, struct ifnet *ifp, int ifcap)
+{
+ if ((ifp == NULL) ||
+ !ISSET(ifp->if_capabilities, ifcap) ||
+ (ifp->if_bridgeidx != 0))
+ return (0);
+ /*
+ * Simplex interface sends packet back without hardware cksum.
+ * Keep this check in sync with the condition where ether_resolve()
+ * calls if_input_local().
+ */
+ if (ISSET(m->m_flags, M_BCAST) &&
+ ISSET(ifp->if_flags, IFF_SIMPLEX) &&
+ !m->m_pkthdr.pf.routed)
+ return (0);
+ return (1);
+}