Enable the support for tracking FTP connections in the Connection tracker. This checks an incoming ftp control connection to extract the related data connection. When a matching data connection arrives, it would then update the connection entry to point to the original control connection.
Signed-off-by: Sairam Venugopal <[email protected]> --- datapath-windows/ovsext/Conntrack.c | 62 +++++++++++++++++++++++++++++++++++-- datapath-windows/ovsext/Conntrack.h | 8 +++++ datapath-windows/ovsext/Switch.c | 8 +++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c index d240c29..114c7b7 100644 --- a/datapath-windows/ovsext/Conntrack.c +++ b/datapath-windows/ovsext/Conntrack.c @@ -192,11 +192,21 @@ OvsCtEntryCreate(PNET_BUFFER_LIST curNbl, } state |= OVS_CS_F_NEW; + POVS_CT_ENTRY parentEntry = NULL; + parentEntry = OvsCtRelatedLookup(ctx->key, currentTime); + if (parentEntry != NULL) { + state |= OVS_CS_F_RELATED; + } + if (commit) { entry = OvsConntrackCreateTcpEntry(tcp, curNbl, currentTime); if (!entry) { return NULL; } + /* If this is related entry, then update parent */ + if (parentEntry != NULL) { + entry->parent = parentEntry; + } OvsCtAddEntry(entry, ctx, currentTime); } @@ -492,6 +502,13 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey, return NDIS_STATUS_SUCCESS; } +static __inline BOOLEAN +OvsDetectFtpPacket(OvsFlowKey *key) { + return (key->ipKey.nwProto == IPPROTO_TCP && + (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP || + ntohs(key->ipKey.l4.tpSrc) == IPPORT_FTP)); +} + /* *---------------------------------------------------------------------------- * OvsProcessConntrackEntry @@ -542,6 +559,21 @@ OvsProcessConntrackEntry(PNET_BUFFER_LIST curNbl, break; } } + + if (key->ipKey.nwProto == IPPROTO_TCP && entry) { + /* Update the related bit if there is a parent */ + if (entry->parent) { + state |= OVS_CS_F_RELATED; + } else { + POVS_CT_ENTRY parentEntry; + parentEntry = OvsCtRelatedLookup(ctx->key, currentTime); + if (parentEntry != NULL) { + entry->parent = parentEntry; + state |= OVS_CS_F_RELATED; + } + } + } + /* Copy mark and label from entry into flowKey. If actions specify different mark and label, update the flowKey. */ if (entry != NULL) { @@ -592,7 +624,8 @@ OvsCtExecute_(PNET_BUFFER_LIST curNbl, BOOLEAN commit, UINT16 zone, MD_MARK *mark, - MD_LABELS *labels) + MD_LABELS *labels, + char *helper) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; POVS_CT_ENTRY entry = NULL; @@ -629,6 +662,17 @@ OvsCtExecute_(PNET_BUFFER_LIST curNbl, OvsConntrackSetLabels(key, entry, &labels->value, &labels->mask); } + if (entry && OvsDetectFtpPacket(key)) { + /* FTP parser will always be loaded */ + UNREFERENCED_PARAMETER(helper); + + status = OvsCtHandleFtp(curNbl, key, layers, currentTime, entry, + (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP)); + if (status != NDIS_STATUS_SUCCESS) { + OVS_LOG_ERROR("Error while parsing the FTP packet"); + } + } + NdisReleaseRWLock(ovsConntrackLockObj, &lockState); return status; @@ -651,6 +695,8 @@ OvsExecuteConntrackAction(PNET_BUFFER_LIST curNbl, UINT16 zone = 0; MD_MARK *mark = NULL; MD_LABELS *labels = NULL; + char *helper = NULL; + NDIS_STATUS status; status = OvsDetectCtPacket(key); @@ -674,9 +720,21 @@ OvsExecuteConntrackAction(PNET_BUFFER_LIST curNbl, if (ctAttr) { labels = NlAttrGet(ctAttr); } + ctAttr = NlAttrFindNested(a, OVS_CT_ATTR_HELPER); + if (ctAttr) { + helper = NlAttrGet(ctAttr); + if (!memchr(helper, '\0', 16)) { + OVS_LOG_ERROR("Invalid CT_ATTR_HELPER:%s", helper); + return NDIS_STATUS_INVALID_PARAMETER; + } + if (strcmp("ftp", helper) != 0) { + /* Only support FTP */ + return NDIS_STATUS_NOT_SUPPORTED; + } + } status = OvsCtExecute_(curNbl, key, layers, - commit, zone, mark, labels); + commit, zone, mark, labels, helper); return status; } diff --git a/datapath-windows/ovsext/Conntrack.h b/datapath-windows/ovsext/Conntrack.h index 44fdfa0..d22b0c4 100644 --- a/datapath-windows/ovsext/Conntrack.h +++ b/datapath-windows/ovsext/Conntrack.h @@ -86,6 +86,7 @@ typedef struct OVS_CT_ENTRY { UINT32 mark; UINT64 timestampStart; struct ovs_key_ct_labels labels; + PVOID parent; /* Points to main connection */ } OVS_CT_ENTRY, *POVS_CT_ENTRY; typedef struct OVS_CT_REL_ENTRY { @@ -204,4 +205,11 @@ OvsCtRelatedEntryCreate(UINT8 ipProto, 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); + #endif /* __OVS_CONNTRACK_H_ */ diff --git a/datapath-windows/ovsext/Switch.c b/datapath-windows/ovsext/Switch.c index db023e9..138a656 100644 --- a/datapath-windows/ovsext/Switch.c +++ b/datapath-windows/ovsext/Switch.c @@ -225,6 +225,13 @@ OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle, goto create_switch_done; } + status = OvsInitCtRelated(switchContext); + if (status != STATUS_SUCCESS) { + OvsUninitSwitchContext(switchContext); + OVS_LOG_ERROR("Exit: Failed to initialize Connection tracking"); + goto create_switch_done; + } + *switchContextOut = switchContext; create_switch_done: @@ -257,6 +264,7 @@ OvsExtDetach(NDIS_HANDLE filterModuleContext) OvsCleanupIpHelper(); OvsCleanupSttDefragmentation(); OvsCleanupConntrack(); + OvsCleanupCtRelated(); /* This completes the cleanup, and a new attach can be handled now. */ OVS_LOG_TRACE("Exit: OvsDetach Successfully"); -- 2.9.0.windows.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
