summaryrefslogtreecommitdiff
path: root/datapath-windows
diff options
context:
space:
mode:
Diffstat (limited to 'datapath-windows')
-rw-r--r--datapath-windows/ovsext/Actions.c1
-rw-r--r--datapath-windows/ovsext/Conntrack-ftp.c109
-rw-r--r--datapath-windows/ovsext/Conntrack-related.c30
-rw-r--r--datapath-windows/ovsext/Conntrack-tcp.c53
-rw-r--r--datapath-windows/ovsext/Conntrack.c77
-rw-r--r--datapath-windows/ovsext/Conntrack.h19
6 files changed, 211 insertions, 78 deletions
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c
index 20de4db4c..3100532e1 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -2378,7 +2378,6 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,
}
OvsExecuteHash(key, (const PNL_ATTR)a);
-
break;
}
diff --git a/datapath-windows/ovsext/Conntrack-ftp.c b/datapath-windows/ovsext/Conntrack-ftp.c
index 066723685..6775496cf 100644
--- a/datapath-windows/ovsext/Conntrack-ftp.c
+++ b/datapath-windows/ovsext/Conntrack-ftp.c
@@ -122,12 +122,9 @@ OvsCtExtractNumbers(char *buf,
*----------------------------------------------------------------------------
*/
NDIS_STATUS
-OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
- OvsFlowKey *key,
- OVS_PACKET_HDR_INFO *layers,
- UINT64 currentTime,
- POVS_CT_ENTRY entry,
- BOOLEAN request)
+OvsCtHandleFtp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,
+ OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,
+ POVS_CT_ENTRY entry)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
FTP_TYPE ftpType = 0;
@@ -157,52 +154,51 @@ OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
OvsStrlcpy((char *)ftpMsg, (char *)buf, min(len, sizeof(ftpMsg)));
char *req = NULL;
- if (request) {
- if ((len >= 5) && (OvsStrncmp("PORT", ftpMsg, 4) == 0)) {
- ftpType = FTP_TYPE_ACTIVE;
- req = ftpMsg + 4;
- } else if ((len >= 5) && (OvsStrncmp("EPRT", ftpMsg, 4) == 0)) {
- ftpType = FTP_EXTEND_TYPE_ACTIVE;
- req = ftpMsg + 4;
+ if ((len >= 5) && (OvsStrncmp("PORT", ftpMsg, 4) == 0)) {
+ ftpType = FTP_TYPE_ACTIVE;
+ req = ftpMsg + 4;
+ } else if ((len >= 5) && (OvsStrncmp("EPRT", ftpMsg, 4) == 0)) {
+ ftpType = FTP_EXTEND_TYPE_ACTIVE;
+ req = ftpMsg + 4;
+ }
+
+ if ((len >= 4) && (OvsStrncmp(FTP_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {
+ ftpType = FTP_TYPE_PASV;
+ /* There are various formats for PASV command. We try to support
+ * some of them. This has been addressed by RFC 2428 - EPSV.
+ * Eg:
+ * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
+ * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2
+ * 227 Entering Passive Mode. h1,h2,h3,h4,p1,p2
+ * 227 =h1,h2,h3,h4,p1,p2
+ */
+ char *paren;
+ paren = strchr(ftpMsg, '(');
+ if (paren) {
+ req = paren + 1;
+ } else {
+ /* PASV command without ( */
+ req = ftpMsg + 3;
+ }
+ } else if ((len >= 4) && (
+ OvsStrncmp(FTP_EXTEND_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {
+ ftpType = FTP_EXTEND_TYPE_PASV;
+ /* The ftp extended passive mode only contain port info, ip address
+ * is same with the network protocol used by control connection.
+ * 229 Entering Extended Passive Mode (|||port|)
+ * */
+ char *paren;
+ paren = strchr(ftpMsg, '|');
+ if (paren) {
+ req = paren + 3;
+ } else {
+ /* Not a valid EPSV packet. */
+ return NDIS_STATUS_INVALID_PACKET;
}
- } else {
- if ((len >= 4) && (OvsStrncmp(FTP_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {
- ftpType = FTP_TYPE_PASV;
- /* There are various formats for PASV command. We try to support
- * some of them. This has been addressed by RFC 2428 - EPSV.
- * Eg:
- * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
- * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2
- * 227 Entering Passive Mode. h1,h2,h3,h4,p1,p2
- * 227 =h1,h2,h3,h4,p1,p2
- */
- char *paren;
- paren = strchr(ftpMsg, '(');
- if (paren) {
- req = paren + 1;
- } else {
- /* PASV command without ( */
- req = ftpMsg + 3;
- }
- } else if ((len >= 4) && (OvsStrncmp(FTP_EXTEND_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {
- ftpType = FTP_EXTEND_TYPE_PASV;
- /* The ftp extended passive mode only contain port info, ip address
- * is same with the network protocol used by control connection.
- * 229 Entering Extended Passive Mode (|||port|)
- * */
- char *paren;
- paren = strchr(ftpMsg, '|');
- if (paren) {
- req = paren + 3;
- } else {
- /* Not a valid EPSV packet. */
- return NDIS_STATUS_INVALID_PACKET;
- }
- if (!(*req > '0' && * req < '9')) {
- /* Not a valid port number. */
- return NDIS_STATUS_INVALID_PACKET;
- }
+ if (!(*req > '0' && * req < '9')) {
+ /* Not a valid port number. */
+ return NDIS_STATUS_INVALID_PACKET;
}
}
@@ -226,8 +222,15 @@ OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
(arr[2] << 8) | arr[3]);
port = ntohs(((arr[4] << 8) | arr[5]));
- serverIp.ipv4 = ip;
- clientIp.ipv4 = key->ipKey.nwDst;
+ if (ftpType == FTP_TYPE_ACTIVE) {
+ serverIp.ipv4 = key->ipKey.nwDst;
+ clientIp.ipv4 = ip;
+ }
+
+ if (ftpType == FTP_TYPE_PASV) {
+ serverIp.ipv4 = ip;
+ clientIp.ipv4 = key->ipKey.nwDst;
+ }
} else {
if (ftpType == FTP_EXTEND_TYPE_ACTIVE) {
/** In ftp active mode, we need to parse string like below:
@@ -239,7 +242,7 @@ OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
char *nextHdr = NULL;
int index = 0;
int isIpv6AddressFamily = 0;
- char ftpStr[1024] = {0x00};
+ char ftpStr[512] = {0x00};
RtlCopyMemory(ftpStr, req, strlen(req));
for (curHdr = ftpStr; *curHdr != '|'; curHdr++);
diff --git a/datapath-windows/ovsext/Conntrack-related.c b/datapath-windows/ovsext/Conntrack-related.c
index f985c7631..99b1553da 100644
--- a/datapath-windows/ovsext/Conntrack-related.c
+++ b/datapath-windows/ovsext/Conntrack-related.c
@@ -40,6 +40,7 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
/* FTP PASV - Client initiates the connection from unknown port */
if ((incomingKey.dl_type == entryKey.dl_type) &&
(incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&
+ (incomingKey.nw_proto == IPPROTO_TCP) &&
(incomingKey.dst.addr.ipv4 == entryKey.src.addr.ipv4) &&
(incomingKey.dst.port == entryKey.src.port) &&
(incomingKey.src.addr.ipv4 == entryKey.dst.addr.ipv4) &&
@@ -49,6 +50,7 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
if ((incomingKey.dl_type == entryKey.dl_type) &&
(incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&
+ (incomingKey.nw_proto == IPPROTO_TCP) &&
!memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.src.addr.ipv6),
sizeof(incomingKey.dst.addr.ipv6)) &&
(incomingKey.dst.port == entryKey.src.port) &&
@@ -65,6 +67,7 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
*/
if ((incomingKey.dl_type == entryKey.dl_type) &&
(incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&
+ (incomingKey.nw_proto == IPPROTO_TCP) &&
(incomingKey.src.addr.ipv4 == entryKey.src.addr.ipv4) &&
(incomingKey.dst.addr.ipv4 == entryKey.dst.addr.ipv4) &&
(incomingKey.dst.port == entryKey.dst.port) &&
@@ -74,6 +77,7 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
if ((incomingKey.dl_type == entryKey.dl_type) &&
(incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&
+ (incomingKey.nw_proto == IPPROTO_TCP) &&
!memcmp(&(incomingKey.src.addr.ipv6), &(entryKey.src.addr.ipv6),
sizeof(incomingKey.src.addr.ipv6)) &&
!memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.dst.addr.ipv6),
@@ -83,6 +87,31 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
return TRUE;
}
+ /* Tftp protocol */
+ if ((incomingKey.dl_type == entryKey.dl_type) &&
+ (incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&
+ (incomingKey.nw_proto == IPPROTO_UDP) &&
+ !memcmp(&(incomingKey.src.addr.ipv4), &(entryKey.src.addr.ipv4),
+ sizeof(incomingKey.src.addr.ipv4)) &&
+ !memcmp(&(incomingKey.dst.addr.ipv4), &(entryKey.dst.addr.ipv4),
+ sizeof(incomingKey.dst.addr.ipv4)) &&
+ (incomingKey.dst.port == entryKey.dst.port) &&
+ (incomingKey.nw_proto == entryKey.nw_proto)) {
+ return TRUE;
+ }
+
+ if ((incomingKey.dl_type == entryKey.dl_type) &&
+ (incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&
+ (incomingKey.nw_proto == IPPROTO_UDP) &&
+ !memcmp(&(incomingKey.src.addr.ipv6), &(entryKey.src.addr.ipv6),
+ sizeof(incomingKey.src.addr.ipv6)) &&
+ !memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.dst.addr.ipv6),
+ sizeof(incomingKey.dst.addr.ipv6)) &&
+ (incomingKey.dst.port == entryKey.dst.port) &&
+ (incomingKey.nw_proto == entryKey.nw_proto)) {
+ return TRUE;
+ }
+
return FALSE;
}
@@ -165,7 +194,6 @@ OvsCtRelatedEntryCreate(UINT8 ipProto,
}
UINT32 hash = OvsExtractCtRelatedKeyHash(&entry->key);
-
NdisAcquireRWLockWrite(ovsCtRelatedLockObj, &lockState, 0);
InsertHeadList(&ovsCtRelatedTable[hash & CT_HASH_TABLE_MASK],
&entry->link);
diff --git a/datapath-windows/ovsext/Conntrack-tcp.c b/datapath-windows/ovsext/Conntrack-tcp.c
index a468c3e6b..77370531c 100644
--- a/datapath-windows/ovsext/Conntrack-tcp.c
+++ b/datapath-windows/ovsext/Conntrack-tcp.c
@@ -37,6 +37,8 @@
*/
#include "Conntrack.h"
+#include "NetProto.h"
+#include "PacketParser.h"
#include <stddef.h>
struct tcp_peer {
@@ -577,3 +579,54 @@ done:
NlMsgEndNested(nlBuf, offset);
return status;
}
+
+NDIS_STATUS
+OvsCtHandleTftp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,
+ OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,
+ POVS_CT_ENTRY entry)
+{
+ UDPHdr udpStorage;
+ const UDPHdr *udp = NULL;
+ struct ct_addr serverIp;
+ struct ct_addr clientIp;
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+
+ udp = OvsGetUdp(curNbl, layers->l4Offset, &udpStorage);
+ if (!udp) {
+ return NDIS_STATUS_INVALID_PACKET;
+ }
+
+ RtlZeroMemory(&serverIp, sizeof(serverIp));
+ RtlZeroMemory(&clientIp, sizeof(clientIp));
+
+ if (OvsCtRelatedLookup(entry->key, currentTime)) {
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ if (layers->isIPv4) {
+ serverIp.ipv4 = key->ipKey.nwDst;
+ clientIp.ipv4 = key->ipKey.nwSrc;
+ status = OvsCtRelatedEntryCreate(key->ipKey.nwProto,
+ key->l2.dlType,
+ serverIp,
+ clientIp,
+ 0,
+ udp->source,
+ currentTime,
+ entry);
+ } else {
+ serverIp.ipv6 = key->ipv6Key.ipv6Dst;
+ clientIp.ipv6 = key->ipv6Key.ipv6Src;
+ status = OvsCtRelatedEntryCreate(key->ipv6Key.nwProto,
+ key->l2.dlType,
+ serverIp,
+ clientIp,
+ 0,
+ udp->source,
+ currentTime,
+ entry);
+ }
+
+ return status;
+}
+
diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c
index 471bf961b..1f3929894 100644
--- a/datapath-windows/ovsext/Conntrack.c
+++ b/datapath-windows/ovsext/Conntrack.c
@@ -874,13 +874,25 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
return NDIS_STATUS_INVALID_PACKET;
}
+ /* It's only designed for unNat traffic, when reverse traffic comes,
+ * find the unNat table, if found the nat entry, based on the nat entry
+ * restore the conntrack, it will be stored in the ctx->key and then use the
+ * ctx->key lookup the conntrack table to find the corresponded
+ * entry with the traffic.*/
natEntry = OvsNatLookup(&ctx->key, TRUE);
if (natEntry) {
- /* Translate address first for reverse NAT */
+ /* initial direction 20::1 -> 20::9, reverse direction 21::3 -> 20::1
+ * 20::9 could be regarded as nat ip, before convert, ctx->key value
+ * is "21::3 -> 20::1", after convert, ctx->key value is
+ * "20::9->20::1" */
ctx->key = natEntry->ctEntry->key;
OvsCtKeyReverse(&ctx->key);
} else {
- if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) {
+ if (OvsNatLookup(&ctx->key, FALSE)) {
+ /* Do nothing here, this branch here used to exclude traffic
+ * described in https://github.com/openvswitch/ovs-issues/issues/237
+ * */
+ } else if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) {
OvsPickupCtTupleAsLookupKey(&(ctx->key), zone, flowKey);
}
}
@@ -903,6 +915,18 @@ OvsDetectFtp6Packet(OvsFlowKey *key) {
ntohs(key->ipv6Key.l4.tpSrc) == IPPORT_FTP));
}
+static __inline BOOLEAN
+OvsDetectTftpPacket(OvsFlowKey *key) {
+ return (key->ipKey.nwProto == IPPROTO_UDP &&
+ (ntohs(key->ipKey.l4.tpDst) == IPPORT_TFTP));
+}
+
+static __inline BOOLEAN
+OvsDetectTftp6Packet(OvsFlowKey *key) {
+ return (key->ipv6Key.nwProto == IPPROTO_UDP &&
+ (ntohs(key->ipv6Key.l4.tpDst) == IPPORT_TFTP));
+}
+
/*
*----------------------------------------------------------------------------
* OvsProcessConntrackEntry
@@ -989,7 +1013,9 @@ OvsProcessConntrackEntry(OvsForwardingContext *fwdCtx,
if (entry) {
NdisAcquireSpinLock(&(entry->lock));
if ((layers->isIPv6 && key->ipv6Key.nwProto == IPPROTO_TCP) ||
- (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_TCP)) {
+ (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_TCP) ||
+ (layers->isIPv6 && key->ipv6Key.nwProto == IPPROTO_UDP) ||
+ (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_UDP)) {
/* Update the related bit if there is a parent */
if (entry->parent) {
state |= OVS_CS_F_RELATED;
@@ -1156,12 +1182,11 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
BOOLEAN triggerUpdateEvent = FALSE;
BOOLEAN entryCreated = FALSE;
- BOOLEAN isFtpPacket = FALSE;
- BOOLEAN isFtpRequestDirection = FALSE;
POVS_CT_ENTRY entry = NULL;
POVS_CT_ENTRY parent = NULL;
PNET_BUFFER_LIST curNbl = fwdCtx->curNbl;
OvsConntrackKeyLookupCtx ctx = { 0 };
+ CT_HELPER_METHOD helpMethod = CT_HELPER_NONE;
LOCK_STATE_EX lockStateTable;
UINT64 currentTime;
NdisGetCurrentSystemTime((LARGE_INTEGER *) &currentTime);
@@ -1241,32 +1266,52 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
OvsCtSetMarkLabel(key, entry, mark, labels, &triggerUpdateEvent);
+ if (helper && RtlEqualMemory(helper, "ftp", sizeof("ftp"))) {
+ helpMethod = CT_HELPER_FTP;
+ } else if (helper && RtlEqualMemory(helper, "tftp", sizeof("tftp"))) {
+ helpMethod = CT_HELPER_TFTP;
+ }
+
+ /* This code section was added to compatible with the old version,
+ * because old version regard all traffic to port 21 as ftp traffic,
+ * no need to add alg field in ct. Thus, the code was added to keep the
+ * same behavior for ftp and tftp.*/
if (layers->isIPv6) {
- isFtpPacket = OvsDetectFtp6Packet(key);
- if (ntohs(key->ipv6Key.l4.tpDst) == IPPORT_FTP) {
- isFtpRequestDirection = TRUE;
+ if (OvsDetectFtp6Packet(key)) {
+ helpMethod = CT_HELPER_FTP;
+ }
+
+ if (OvsDetectTftp6Packet(key)) {
+ helpMethod = CT_HELPER_TFTP;
}
} else {
- isFtpPacket = OvsDetectFtpPacket(key);
- if (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP) {
- isFtpRequestDirection = TRUE;
+ if (OvsDetectFtpPacket(key)) {
+ helpMethod = CT_HELPER_FTP;
+ }
+
+ if (OvsDetectTftpPacket(key)) {
+ helpMethod = CT_HELPER_TFTP;
}
}
- if (isFtpPacket) {
- /* FTP parser will always be loaded */
- status = OvsCtHandleFtp(curNbl, key, layers, currentTime, entry,
- isFtpRequestDirection);
+ if (helpMethod == CT_HELPER_FTP) {
+ status = OvsCtHandleFtp(curNbl, key, layers, currentTime, entry);
if (status != NDIS_STATUS_SUCCESS) {
OVS_LOG_ERROR("Error while parsing the FTP packet");
}
}
+ if (helpMethod == CT_HELPER_TFTP) {
+ status = OvsCtHandleTftp(curNbl, key, layers, currentTime, entry);
+ if (status != NDIS_STATUS_SUCCESS) {
+ OVS_LOG_ERROR("Error while parsing the TFTP packet");
+ }
+ }
+
parent = entry->parent;
/* The entry should have the same helper name with parent's */
if (!entry->helper_name &&
(helper || (parent && parent->helper_name))) {
-
helper = helper ? helper : parent->helper_name;
entry->helper_name = OvsAllocateMemoryWithTag(strlen(helper) + 1,
OVS_CT_POOL_TAG);
diff --git a/datapath-windows/ovsext/Conntrack.h b/datapath-windows/ovsext/Conntrack.h
index b68a54f30..deb51c0bc 100644
--- a/datapath-windows/ovsext/Conntrack.h
+++ b/datapath-windows/ovsext/Conntrack.h
@@ -80,6 +80,12 @@ typedef enum _NAT_ACTION {
NAT_ACTION_DST_PORT = 1 << 4,
} NAT_ACTION;
+typedef enum _CT_HELPER_METHOD {
+ CT_HELPER_NONE = 0,
+ CT_HELPER_FTP = 1,
+ CT_HELPER_TFTP = 2,
+} CT_HELPER_METHOD;
+
typedef struct _OVS_CT_KEY {
struct ct_endpoint src;
struct ct_endpoint dst;
@@ -218,11 +224,10 @@ NDIS_STATUS OvsCtRelatedEntryCreate(UINT8 ipProto,
UINT64 currentTime,
POVS_CT_ENTRY parent);
POVS_CT_ENTRY OvsCtRelatedLookup(OVS_CT_KEY key, UINT64 currentTime);
-
-NDIS_STATUS OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
- OvsFlowKey *key,
- OVS_PACKET_HDR_INFO *layers,
- UINT64 currentTime,
- POVS_CT_ENTRY entry,
- BOOLEAN request);
+NDIS_STATUS OvsCtHandleFtp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,
+ OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,
+ POVS_CT_ENTRY entry);
+NDIS_STATUS OvsCtHandleTftp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,
+ OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,
+ POVS_CT_ENTRY entry);
#endif /* __OVS_CONNTRACK_H_ */