Skip to content

Commit 9323fd9

Browse files
igsilyaovsrobot
authored andcommitted
datapath-windows: Fix parsing of split buffers in OvsGetTcpHeader.
NdisGetDataBuffer() is called without providing a buffer to copy packet data in case it is not contiguous. So, it fails in some scenarios where the packet is handled by the general network stack before OVS and headers become split in multiple buffers. Use existing helpers to retrieve the headers instead, they are using OvsGetPacketBytes() which should be able to handle split data. It might be a bit slower than getting direct pointers that may be provided by NdisGetDataBuffer(), but it's better to optimize commonly used OvsGetPacketBytes() helper in the future instead of optimizing every single caller separately. And we're still copying the TCP header anyway. Fixes: 9726a01 ("datapath-windows: Implement locking in conntrack NAT.") Reported-at: openvswitch/ovs-issues#323 Signed-off-by: Ilya Maximets <i.maximets@ovn.org> Signed-off-by: 0-day Robot <robot@bytheb.org>
1 parent 792e8ee commit 9323fd9

File tree

1 file changed

+21
-24
lines changed

1 file changed

+21
-24
lines changed

datapath-windows/ovsext/Conntrack.c

+21-24
Original file line numberDiff line numberDiff line change
@@ -678,46 +678,43 @@ OvsGetTcpHeader(PNET_BUFFER_LIST nbl,
678678
VOID *storage,
679679
UINT32 *tcpPayloadLen)
680680
{
681-
IPHdr *ipHdr;
682-
IPv6Hdr *ipv6Hdr;
683-
TCPHdr *tcp;
681+
IPv6Hdr ipv6HdrStorage;
682+
IPHdr ipHdrStorage;
683+
const IPv6Hdr *ipv6Hdr;
684+
const IPHdr *ipHdr;
685+
const TCPHdr *tcp;
684686
VOID *dest = storage;
685687
uint16_t ipv6ExtLength = 0;
686688

687689
if (layers->isIPv6) {
688-
ipv6Hdr = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(nbl),
689-
layers->l4Offset + sizeof(TCPHdr),
690-
NULL, 1, 0);
690+
ipv6Hdr = OvsGetPacketBytes(nbl, sizeof *ipv6Hdr,
691+
layers->l3Offset, &ipv6HdrStorage);
691692
if (ipv6Hdr == NULL) {
692693
return NULL;
693694
}
694695

695-
tcp = (TCPHdr *)((PCHAR)ipv6Hdr + layers->l4Offset);
696-
ipv6Hdr = (IPv6Hdr *)((PCHAR)ipv6Hdr + layers->l3Offset);
697-
if (tcp->doff * 4 >= sizeof *tcp) {
698-
NdisMoveMemory(dest, tcp, sizeof(TCPHdr));
699-
ipv6ExtLength = layers->l4Offset - layers->l3Offset - sizeof(IPv6Hdr);
700-
*tcpPayloadLen = (ntohs(ipv6Hdr->payload_len) - ipv6ExtLength - TCP_HDR_LEN(tcp));
701-
return storage;
696+
tcp = OvsGetTcp(nbl, layers->l4Offset, dest);
697+
if (tcp == NULL) {
698+
return NULL;
702699
}
700+
701+
ipv6ExtLength = layers->l4Offset - layers->l3Offset - sizeof(IPv6Hdr);
702+
*tcpPayloadLen = (ntohs(ipv6Hdr->payload_len) - ipv6ExtLength - TCP_HDR_LEN(tcp));
703703
} else {
704-
ipHdr = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(nbl),
705-
layers->l4Offset + sizeof(TCPHdr),
706-
NULL, 1 /*no align*/, 0);
704+
ipHdr = OvsGetIp(nbl, layers->l3Offset, &ipHdrStorage);
707705
if (ipHdr == NULL) {
708706
return NULL;
709707
}
710708

711-
ipHdr = (IPHdr *)((PCHAR)ipHdr + layers->l3Offset);
712-
tcp = (TCPHdr *)((PCHAR)ipHdr + ipHdr->ihl * 4);
713-
714-
if (tcp->doff * 4 >= sizeof *tcp) {
715-
NdisMoveMemory(dest, tcp, sizeof(TCPHdr));
716-
*tcpPayloadLen = TCP_DATA_LENGTH(ipHdr, tcp);
717-
return storage;
709+
tcp = OvsGetTcp(nbl, layers->l4Offset, dest);
710+
if (tcp == NULL) {
711+
return NULL;
718712
}
713+
714+
*tcpPayloadLen = TCP_DATA_LENGTH(ipHdr, tcp);
719715
}
720-
return NULL;
716+
717+
return storage;
721718
}
722719

723720
static UINT8

0 commit comments

Comments
 (0)