1 | #include "IpDissector.h" |
---|
2 | #ifdef WIN32 |
---|
3 | #include <Winsock2.h> |
---|
4 | #else |
---|
5 | #include <netinet/in.h> |
---|
6 | #endif |
---|
7 | |
---|
8 | IpDissector::IpDissector() : |
---|
9 | m_ipHdr(0) |
---|
10 | { |
---|
11 | } |
---|
12 | |
---|
13 | IpDissector::~IpDissector() { |
---|
14 | delete m_ipHdr; |
---|
15 | } |
---|
16 | |
---|
17 | IpDissector * IpDissector::Clone() const { |
---|
18 | return new IpDissector(); |
---|
19 | } |
---|
20 | |
---|
21 | bool IpDissector::Dissect(const unsigned char * pData, ssize_t nDataLen) { |
---|
22 | if (!m_ipHdr) |
---|
23 | m_ipHdr = new IpHeader; |
---|
24 | memcpy(m_ipHdr, pData, sizeof(IpHeader)); |
---|
25 | pData += sizeof(IpHeader); |
---|
26 | #if BYTE_ORDER == LITTLE_ENDIAN |
---|
27 | m_ipHdr->totalLength = ntohs(m_ipHdr->totalLength); |
---|
28 | #endif |
---|
29 | SavePayload(pData, m_ipHdr->totalLength - m_ipHdr->headerLength*4); |
---|
30 | SaveLayerInfo(); |
---|
31 | return true; |
---|
32 | } |
---|
33 | |
---|
34 | bool IpDissector::NeedReassembly() const { |
---|
35 | if(m_ipHdr->moreFragment || m_ipHdr->fragOffset || m_ipHdr->fragOffset1) |
---|
36 | return true; |
---|
37 | return false; |
---|
38 | } |
---|
39 | |
---|
40 | bool IpDissector::Reassemble(Dissector * pDissector, ProtocolInfo * pProtocolInfo) { |
---|
41 | if(!NeedReassembly()) |
---|
42 | return false; |
---|
43 | |
---|
44 | if(m_holes.size() == 0) |
---|
45 | { |
---|
46 | // No hole defined even thougth reassembly is needed |
---|
47 | // It means that Reassemble is called for first time |
---|
48 | // Initialize reassembly structure and add self |
---|
49 | m_holes.push_back(std::pair<unsigned short, unsigned short>(0, (unsigned short)(- 1))); |
---|
50 | Reassemble(this, pProtocolInfo); |
---|
51 | } |
---|
52 | |
---|
53 | // Inspect potential fragment |
---|
54 | IpDissector * pIpDissector = dynamic_cast<IpDissector *>(pDissector); |
---|
55 | if((pIpDissector->m_ipHdr) && (pIpDissector->m_ipHdr->id == m_ipHdr->id)) |
---|
56 | { |
---|
57 | // Build First and Last values |
---|
58 | unsigned short nFirstFragmentByte = pIpDissector->m_ipHdr->fragOffset; |
---|
59 | nFirstFragmentByte = nFirstFragmentByte << 8; |
---|
60 | nFirstFragmentByte += pIpDissector->m_ipHdr->fragOffset1; |
---|
61 | nFirstFragmentByte *= 8; |
---|
62 | |
---|
63 | unsigned short nLastFragmentByte = nFirstFragmentByte |
---|
64 | + pIpDissector->m_ipHdr->totalLength |
---|
65 | - pIpDissector->m_ipHdr->headerLength * 4; |
---|
66 | |
---|
67 | // Compare to missing data |
---|
68 | std::list<std::pair<unsigned short, unsigned short> >::iterator it; |
---|
69 | int nPayloadSize = GetPayloadSize(); |
---|
70 | for(it = m_holes.begin(); it != m_holes.end(); ++it) |
---|
71 | { |
---|
72 | if(nFirstFragmentByte > (*it).second) |
---|
73 | continue; |
---|
74 | if(nLastFragmentByte < (*it).first) |
---|
75 | continue; |
---|
76 | if(!pIpDissector->m_ipHdr->moreFragment) |
---|
77 | { |
---|
78 | // Last fragment received |
---|
79 | (*it).second = nLastFragmentByte; |
---|
80 | nPayloadSize = nLastFragmentByte; |
---|
81 | } |
---|
82 | |
---|
83 | if(nFirstFragmentByte > (*it).first) |
---|
84 | m_holes.push_back(std::pair<unsigned short, unsigned short>((*it).first, nFirstFragmentByte - 1)); |
---|
85 | if(nLastFragmentByte < (*it).second) |
---|
86 | m_holes.push_back(std::pair<unsigned short, unsigned short>(nLastFragmentByte + 1, (*it).second)); |
---|
87 | m_holes.erase(it); |
---|
88 | std::pair<const unsigned char *, const ssize_t> data = pIpDissector->DetachData(); |
---|
89 | m_fragments[nFirstFragmentByte] = data.first; |
---|
90 | m_fragmentSizes[nFirstFragmentByte] = data.second; |
---|
91 | |
---|
92 | // received fragment is not needed anymore |
---|
93 | if(pIpDissector != this) |
---|
94 | delete pIpDissector; |
---|
95 | |
---|
96 | // check if packet is now complete |
---|
97 | if(m_holes.size() == 0) |
---|
98 | { |
---|
99 | m_ipHdr->moreFragment = 0; |
---|
100 | m_ipHdr->fragOffset = 0; |
---|
101 | m_ipHdr->fragOffset1 = 0; |
---|
102 | |
---|
103 | // Reassembly ! |
---|
104 | ssize_t nOffset = 0; |
---|
105 | AllocPayload(nPayloadSize); // payloadSize is valid since last fragment has been received |
---|
106 | while((nOffset != nPayloadSize) && (m_fragments.find(nOffset) != m_fragments.end())) |
---|
107 | { |
---|
108 | SetPayloadAt(m_fragments[nOffset], m_fragmentSizes[nOffset], nOffset); |
---|
109 | // Clean up |
---|
110 | delete m_fragments[nOffset]; |
---|
111 | nOffset += m_fragmentSizes[nOffset]; |
---|
112 | } |
---|
113 | m_fragments.clear(); |
---|
114 | m_fragmentSizes.clear(); |
---|
115 | } |
---|
116 | return true; |
---|
117 | } |
---|
118 | } |
---|
119 | return false; |
---|
120 | } |
---|
121 | |
---|
122 | const EProtocolType IpDissector::GetUpperLayerType() const |
---|
123 | { |
---|
124 | EProtocolType res = EProtocolType_Unknown; |
---|
125 | switch(m_ipHdr->protocol) |
---|
126 | { |
---|
127 | case 6: |
---|
128 | res = EProtocolType_Tcp; |
---|
129 | break; |
---|
130 | case 17: |
---|
131 | res = EProtocolType_Udp; |
---|
132 | break; |
---|
133 | } |
---|
134 | return res; |
---|
135 | } |
---|
136 | |
---|
137 | ProtocolInfoElement * IpDissector::CreateLayerInfo() |
---|
138 | { |
---|
139 | IPv4Info * pRes = new IPv4Info(); |
---|
140 | unsigned int nSrcAddr, nDstAddr; |
---|
141 | memcpy(&nSrcAddr, m_ipHdr->srcAddr, sizeof(int)); |
---|
142 | memcpy(&nDstAddr, m_ipHdr->destAddr, sizeof(int)); |
---|
143 | pRes->SetSourceAddress(nSrcAddr); |
---|
144 | pRes->SetDestinationAddress(nDstAddr); |
---|
145 | return pRes; |
---|
146 | } |
---|