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 <vsai...@vmware.com> --- datapath-windows/ovsext/Conntrack.c | 61 ++++++++++++++++++++++++++++++- datapath-windows/ovsext/Conntrack.h | 8 ++++ datapath-windows/ovsext/Netlink/Netlink.c | 16 ++++++++ datapath-windows/ovsext/Netlink/Netlink.h | 1 + datapath-windows/ovsext/Switch.c | 8 ++++ 5 files changed, 92 insertions(+), 2 deletions(-) diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c index 1436431..1554916 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, + PCHAR 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; + PCHAR helper = NULL; + NDIS_STATUS status; status = OvsDetectCtPacket(key); @@ -674,9 +720,20 @@ OvsExecuteConntrackAction(PNET_BUFFER_LIST curNbl, if (ctAttr) { labels = NlAttrGet(ctAttr); } + ctAttr = NlAttrFindNested(a, OVS_CT_ATTR_HELPER); + if (ctAttr) { + helper = NlAttrGetString(ctAttr); + if (helper == NULL) { + 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 e93842d..124d2af 100644 --- a/datapath-windows/ovsext/Conntrack.h +++ b/datapath-windows/ovsext/Conntrack.h @@ -85,6 +85,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 { @@ -200,4 +201,11 @@ NDIS_STATUS OvsCtRelatedEntryCreate(UINT8 ipProto, 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); + #endif /* __OVS_CONNTRACK_H_ */ diff --git a/datapath-windows/ovsext/Netlink/Netlink.c b/datapath-windows/ovsext/Netlink/Netlink.c index 2432205..a63f066 100644 --- a/datapath-windows/ovsext/Netlink/Netlink.c +++ b/datapath-windows/ovsext/Netlink/Netlink.c @@ -992,6 +992,22 @@ NlAttrGetU64(const PNL_ATTR nla) /* * --------------------------------------------------------------------------- + * Returns the string value in 'nla''s payload. + * Returns NULL if it is not a proper '\0' terminated string. + * --------------------------------------------------------------------------- + */ +PCHAR +NlAttrGetString(const PNL_ATTR nla) +{ + ASSERT(nla->nlaLen >= NLA_HDRLEN); + if (!memchr(NlAttrGet(nla), '\0', nla->nlaLen - NLA_HDRLEN)) { + return NULL; + } + return NlAttrGet(nla); +} + +/* + * --------------------------------------------------------------------------- * Validate the netlink attribute against the policy * --------------------------------------------------------------------------- */ diff --git a/datapath-windows/ovsext/Netlink/Netlink.h b/datapath-windows/ovsext/Netlink/Netlink.h index 363f575..964c0e5 100644 --- a/datapath-windows/ovsext/Netlink/Netlink.h +++ b/datapath-windows/ovsext/Netlink/Netlink.h @@ -138,6 +138,7 @@ UINT8 NlAttrGetU8(const PNL_ATTR nla); UINT16 NlAttrGetU16(const PNL_ATTR nla); UINT32 NlAttrGetU32(const PNL_ATTR nla); UINT64 NlAttrGetU64(const PNL_ATTR nla); +PCHAR NlAttrGetString(const PNL_ATTR nla); const PNL_ATTR NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type); const PNL_ATTR NlAttrFindNested(const PNL_ATTR nla, 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 d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev