--- a/src/flow-monitor/model/ipv4-flow-classifier.cc Tue Dec 03 17:06:35 2013 -0800
+++ b/src/flow-monitor/model/ipv4-flow-classifier.cc Mon Dec 02 23:05:14 2013 +0100
@@ -109,35 +109,49 @@
return false;
}
+ if (ipHeader.GetFragmentOffset () > 0 )
+ {
+ // Ignore fragments: they don't carry a valid L4 header
+ return false;
+ }
+
FiveTuple tuple;
tuple.sourceAddress = ipHeader.GetSource ();
tuple.destinationAddress = ipHeader.GetDestination ();
tuple.protocol = ipHeader.GetProtocol ();
- switch (tuple.protocol)
+ if ((tuple.protocol != UDP_PROT_NUMBER) && (tuple.protocol != TCP_PROT_NUMBER))
{
- case UDP_PROT_NUMBER:
- {
- UdpHeader udpHeader;
- ipPayload->PeekHeader (udpHeader);
- tuple.sourcePort = udpHeader.GetSourcePort ();
- tuple.destinationPort = udpHeader.GetDestinationPort ();
- }
- break;
+ return false;
+ }
- case TCP_PROT_NUMBER:
- {
- TcpHeader tcpHeader;
- ipPayload->PeekHeader (tcpHeader);
- tuple.sourcePort = tcpHeader.GetSourcePort ();
- tuple.destinationPort = tcpHeader.GetDestinationPort ();
- }
- break;
-
- default:
+ if (ipPayload->GetSize () < 4)
+ {
+ // the packet doesn't carry enough bytes
return false;
}
+ // we rely on the fact that for both TCP and UDP the ports are
+ // carried in the first 4 octects.
+ // This allows to read the ports even on fragmented packets
+ // not carrying a full TCP or UDP header.
+
+ uint8_t data[4];
+ ipPayload->CopyData (data, 4);
+
+ uint16_t srcPort = 0;
+ srcPort |= data[0];
+ srcPort <<= 8;
+ srcPort |= data[1];
+
+ uint16_t dstPort = 0;
+ dstPort |= data[2];
+ dstPort <<= 8;
+ dstPort |= data[3];
+
+ tuple.sourcePort = srcPort;
+ tuple.destinationPort = dstPort;
+
// try to insert the tuple, but check if it already exists
std::pair<std::map<FiveTuple, FlowId>::iterator, bool> insert
= m_flowMap.insert (std::pair<FiveTuple, FlowId> (tuple, 0));