Clear h/w csum flags on mbuf handled by UDP.

When checksums of received IP and UDP header already checked, UDP uses
sbappendaddr_locked() to pass received data to the socket.
sbappendaddr_locked() uses given mbuf as is, and if NIC supports checksum
offloading, mbuf contains csum_data and csum_flags that were calculated
for already stripped headers. Some NICs support only limited checksums
offloading and do not use CSUM_PSEUDO_HDR flag, and csum_data contains
some value that UDP/TCP should use for pseudo header checksum calculation.

When L2TP is used for tunneling with mpd5, ng_ksocket receives mbuf with
filled csum_flags and csum_data, that were calculated for outer headers.
When L2TP header is stripped, a packet that was tunneled goes to the IP
layer and due to presence of csum_flags (without CSUM_PSEUDO_HDR) and
csum_data, the UDP/TCP checksum check fails for this packet.

Reported by:	Irina Liakh <spell at itl ua>
Tested by:	Irina Liakh <spell at itl ua>
MFC after:	1 week
This commit is contained in:
Andrey V. Elsukov 2017-04-13 17:03:57 +00:00
parent 71cb533e98
commit 8428914909
2 changed files with 6 additions and 0 deletions

View File

@ -372,6 +372,9 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
append_sa = (struct sockaddr *)&udp_in[0];
m_adj(n, off);
/* Clear any h/w csum flags as they are no longer valid. */
n->m_pkthdr.csum_flags &= ~(CSUM_DATA_VALID | CSUM_IP_VALID);
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_rcv);
if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) {

View File

@ -187,6 +187,9 @@ udp6_append(struct inpcb *inp, struct mbuf *n, int off,
}
m_adj(n, off + sizeof(struct udphdr));
/* Clear any h/w csum flags as they are no longer valid. */
n->m_pkthdr.csum_flags &= ~CSUM_DATA_VALID;
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_rcv);
if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)&fromsa[0], n,