remove redundnt codes; find a way to use the analyzer function, such as Weird; fix a small bug in ProcessData function in DNP3.cc; passed the test

This commit is contained in:
Hui Lin 2014-08-28 20:35:28 -05:00
parent 81606e7ff4
commit dd830db38a
2 changed files with 273 additions and 507 deletions

View file

@ -109,21 +109,242 @@ const unsigned int PSEUDO_APP_LAYER_INDEX = 11; // index of first DNP3 app-laye
const unsigned int PSEUDO_TRANSPORT_LEN = 1; // length of DNP3 Transport Layer
const unsigned int PSEUDO_LINK_LAYER_LEN = 8; // length of DNP3 Pseudo Link Layer
bool DNP3_TCP_Analyzer::crc_table_initialized = false;
unsigned int DNP3_TCP_Analyzer::crc_table[256];
bool DNP3_Analyzer::crc_table_initialized = false;
unsigned int DNP3_Analyzer::crc_table[256];
bool DNP3_UDP_Analyzer::crc_table_initialized = false;
unsigned int DNP3_UDP_Analyzer::crc_table[256];
DNP3_Analyzer::DNP3_Analyzer()
{
if ( ! crc_table_initialized )
PrecomputeCRCTable();
}
DNP3_Analyzer::~DNP3_Analyzer()
{
}
bool DNP3_Analyzer::ProcessData(analyzer::Analyzer* thisAnalyzer, binpac::DNP3::DNP3_Conn* thisInterp, int len, const u_char* data, bool orig)
{
Endpoint* endp = orig ? &orig_state : &resp_state;
while ( len )
{
if ( endp->in_hdr )
{
// We're parsing the DNP3 header and link layer, get that in full.
if ( ! AddToBuffer(endp, PSEUDO_APP_LAYER_INDEX, &data, &len) )
return true;
// The first two bytes must always be 0x0564.
if( endp->buffer[0] != 0x05 || endp->buffer[1] != 0x64 )
{
thisAnalyzer->Weird("dnp3_header_lacks_magic");
return false;
}
// Make sure header checksum is correct.
if ( ! CheckCRC(thisAnalyzer, PSEUDO_LINK_LAYER_LEN, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN, "header") )
{
thisAnalyzer->ProtocolViolation("broken_checksum");
return false;
}
// If the checksum works out, we're pretty certainly DNP3.
thisAnalyzer->ProtocolConfirmation();
// DNP3 packets without transport and application
// layers can happen, we ignore them.
if ( (endp->buffer[PSEUDO_LENGTH_INDEX] + 3) == (char)PSEUDO_LINK_LAYER_LEN )
{
//ClearEndpointState(orig);
ClearEndpointState(thisInterp, orig);
return true;
}
// Double check the direction in case the first
// received packet is a response.
u_char ctrl = endp->buffer[PSEUDO_CONTROL_FIELD_INDEX];
if ( orig != (bool)(ctrl & 0x80) )
thisAnalyzer->Weird("dnp3_unexpected_flow_direction");
// Update state.
endp->pkt_length = endp->buffer[PSEUDO_LENGTH_INDEX];
endp->tpflags = endp->buffer[PSEUDO_TRANSPORT_INDEX];
endp->in_hdr = false; // Now parsing application layer.
// For the first packet, we submit the header to
// BinPAC.
if ( ++endp->pkt_cnt == 1 )
//interp->NewData(orig, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN);
thisInterp->NewData(orig, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN);
}
if ( ! endp->in_hdr )
{
assert(endp->pkt_length);
// We're parsing the DNP3 application layer, get that
// in full now as well. We calculate the number of
// raw bytes the application layer consists of from
// the packet length by determining how much 16-byte
// chunks fit in there, and then add 2 bytes CRC for
// each.
int n = PSEUDO_APP_LAYER_INDEX + (endp->pkt_length - 5) + ((endp->pkt_length - 5) / 16) * 2
+ 2 * ( ((endp->pkt_length - 5) % 16 == 0) ? 0 : 1) - 1 ;
if ( ! AddToBuffer(endp, n, &data, &len) )
return true;
// Parse the the application layer data.
//if ( ! ParseAppLayer(endp) )
if ( ! ParseAppLayer(thisAnalyzer, thisInterp, endp) )
return false;
// Done with this packet, prepare for next.
endp->buffer_len = 0;
endp->in_hdr = true;
}
}
return true;
}
bool DNP3_Analyzer::AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len)
{
if ( ! target_len )
return true;
int to_copy = min(*len, target_len - endp->buffer_len);
memcpy(endp->buffer + endp->buffer_len, *data, to_copy);
*data += to_copy;
*len -= to_copy;
endp->buffer_len += to_copy;
return endp->buffer_len == target_len;
}
bool DNP3_Analyzer::ParseAppLayer(analyzer::Analyzer* thisAnalyzer, binpac::DNP3::DNP3_Conn* thisInterp, Endpoint* endp)
{
bool orig = (endp == &orig_state);
binpac::DNP3::DNP3_Flow* flow = orig ? thisInterp->upflow() : thisInterp->downflow();
u_char* data = endp->buffer + PSEUDO_TRANSPORT_INDEX; // The transport layer byte counts as app-layer it seems.
int len = endp->pkt_length - 5;
// DNP3 Packet : DNP3 Pseudo Link Layer | DNP3 Pseudo Transport Layer | DNP3 Pseudo Application Layer
// DNP3 Serial Transport Layer data is always 1 byte.
// Get FIN FIR seq field in transport header.
// FIR indicate whether the following DNP3 Serial Application Layer is first chunk of bytes or not.
// FIN indicate whether the following DNP3 Serial Application Layer is last chunk of bytes or not.
int is_first = (endp->tpflags & 0x40) >> 6; // Initial chunk of data in this packet.
int is_last = (endp->tpflags & 0x80) >> 7; // Last chunk of data in this packet.
int transport = PSEUDO_TRANSPORT_LEN;
int i = 0;
while ( len > 0 )
{
int n = min(len, 16);
// Make sure chunk has a correct checksum.
if ( ! CheckCRC(thisAnalyzer, n, data, data + n, "app_chunk") )
return false;
// Pass on to BinPAC.
assert(data + n < endp->buffer + endp->buffer_len);
flow->flow_buffer()->BufferData(data + transport, data + n);
transport = 0;
data += n + 2;
len -= n;
}
if ( is_first )
endp->encountered_first_chunk = true;
if ( ! is_first && ! endp->encountered_first_chunk )
{
// We lost the first chunk.
thisAnalyzer->Weird("dnp3_first_application_layer_chunk_missing");
return false;
}
if ( is_last )
{
flow->flow_buffer()->FinishBuffer();
flow->FlowEOF();
//ClearEndpointState(orig);
ClearEndpointState(thisInterp, orig);
}
return true;
}
void DNP3_Analyzer::ClearEndpointState(binpac::DNP3::DNP3_Conn* thisInterp, bool orig)
{
Endpoint* endp = orig ? &orig_state : &resp_state;
binpac::DNP3::DNP3_Flow* flow = orig ? thisInterp->upflow() : thisInterp->downflow(); //??
endp->in_hdr = true;
endp->encountered_first_chunk = false;
endp->buffer_len = 0;
endp->pkt_length = 0;
endp->tpflags = 0;
endp->pkt_cnt = 0;
}
bool DNP3_Analyzer::CheckCRC(analyzer::Analyzer* thisAnalyzer, int len, const u_char* data, const u_char* crc16, const char* where)
{
unsigned int crc = CalcCRC(len, data);
if ( crc16[0] == (crc & 0xff) && crc16[1] == (crc & 0xff00) >> 8 )
return true;
thisAnalyzer->Weird(fmt("dnp3_corrupt_%s_checksum", where));
return false;
}
void DNP3_Analyzer::PrecomputeCRCTable()
{
for( unsigned int i = 0; i < 256; i++)
{
unsigned int crc = i;
for ( unsigned int j = 0; j < 8; ++j )
{
if ( crc & 0x0001 )
crc = (crc >> 1) ^ 0xA6BC; // Generating polynomial.
else
crc >>= 1;
}
crc_table[i] = crc;
}
}
unsigned int DNP3_Analyzer::CalcCRC(int len, const u_char* data)
{
unsigned int crc = 0x0000;
for ( int i = 0; i < len; i++ )
{
unsigned int index = (crc ^ data[i]) & 0xFF;
crc = crc_table[index] ^ (crc >> 8);
}
return ~crc & 0xFFFF;
}
DNP3_TCP_Analyzer::DNP3_TCP_Analyzer(Connection* c) : TCP_ApplicationAnalyzer("DNP3_TCP", c)
{
interp = new binpac::DNP3::DNP3_Conn(this);
ClearEndpointState(true);
ClearEndpointState(false);
ClearEndpointState(interp, true);
ClearEndpointState(interp, false);
if ( ! crc_table_initialized )
PrecomputeCRCTable();
}
DNP3_TCP_Analyzer::~DNP3_TCP_Analyzer()
@ -145,7 +366,7 @@ void DNP3_TCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
try
{
if ( ! ProcessData(len, data, orig) )
if ( ! ProcessData(this, interp, len, data, orig) )
SetSkip(1);
}
@ -168,225 +389,13 @@ void DNP3_TCP_Analyzer::EndpointEOF(bool is_orig)
interp->FlowEOF(is_orig);
}
bool DNP3_TCP_Analyzer::ProcessData(int len, const u_char* data, bool orig)
{
Endpoint* endp = orig ? &orig_state : &resp_state;
while ( len )
{
if ( endp->in_hdr )
{
// We're parsing the DNP3 header and link layer, get that in full.
if ( ! AddToBuffer(endp, PSEUDO_APP_LAYER_INDEX, &data, &len) )
return true;
// The first two bytes must always be 0x0564.
if( endp->buffer[0] != 0x05 || endp->buffer[1] != 0x64 )
{
Weird("dnp3_header_lacks_magic");
return false;
}
// Make sure header checksum is correct.
if ( ! CheckCRC(PSEUDO_LINK_LAYER_LEN, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN, "header") )
{
ProtocolViolation("broken_checksum");
return false;
}
// If the checksum works out, we're pretty certainly DNP3.
ProtocolConfirmation();
// DNP3 packets without transport and application
// layers can happen, we ignore them.
if ( (endp->buffer[PSEUDO_LENGTH_INDEX] + 3) == (char)PSEUDO_LINK_LAYER_LEN )
{
ClearEndpointState(orig);
return true;
}
// Double check the direction in case the first
// received packet is a response.
u_char ctrl = endp->buffer[PSEUDO_CONTROL_FIELD_INDEX];
if ( orig != (bool)(ctrl & 0x80) )
Weird("dnp3_unexpected_flow_direction");
// Update state.
endp->pkt_length = endp->buffer[PSEUDO_LENGTH_INDEX];
endp->tpflags = endp->buffer[PSEUDO_TRANSPORT_INDEX];
endp->in_hdr = false; // Now parsing application layer.
// For the first packet, we submit the header to
// BinPAC.
if ( ++endp->pkt_cnt == 1 )
interp->NewData(orig, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN);
}
if ( ! endp->in_hdr )
{
assert(endp->pkt_length);
// We're parsing the DNP3 application layer, get that
// in full now as well. We calculate the number of
// raw bytes the application layer consists of from
// the packet length by determining how much 16-byte
// chunks fit in there, and then add 2 bytes CRC for
// each.
int n = PSEUDO_APP_LAYER_INDEX + (endp->pkt_length - 5) + ((endp->pkt_length - 5) / 16) * 2 + 2 - 1;
if ( ! AddToBuffer(endp, n, &data, &len) )
return true;
// Parse the the application layer data.
if ( ! ParseAppLayer(endp) )
return false;
// Done with this packet, prepare for next.
endp->buffer_len = 0;
endp->in_hdr = true;
}
}
return true;
}
bool DNP3_TCP_Analyzer::AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len)
{
if ( ! target_len )
return true;
int to_copy = min(*len, target_len - endp->buffer_len);
memcpy(endp->buffer + endp->buffer_len, *data, to_copy);
*data += to_copy;
*len -= to_copy;
endp->buffer_len += to_copy;
return endp->buffer_len == target_len;
}
bool DNP3_TCP_Analyzer::ParseAppLayer(Endpoint* endp)
{
bool orig = (endp == &orig_state);
binpac::DNP3::DNP3_Flow* flow = orig ? interp->upflow() : interp->downflow();
u_char* data = endp->buffer + PSEUDO_TRANSPORT_INDEX; // The transport layer byte counts as app-layer it seems.
int len = endp->pkt_length - 5;
// DNP3 Packet : DNP3 Pseudo Link Layer | DNP3 Pseudo Transport Layer | DNP3 Pseudo Application Layer
// DNP3 Serial Transport Layer data is always 1 byte.
// Get FIN FIR seq field in transport header.
// FIR indicate whether the following DNP3 Serial Application Layer is first chunk of bytes or not.
// FIN indicate whether the following DNP3 Serial Application Layer is last chunk of bytes or not.
int is_first = (endp->tpflags & 0x40) >> 6; // Initial chunk of data in this packet.
int is_last = (endp->tpflags & 0x80) >> 7; // Last chunk of data in this packet.
int transport = PSEUDO_TRANSPORT_LEN;
int i = 0;
while ( len > 0 )
{
int n = min(len, 16);
// Make sure chunk has a correct checksum.
if ( ! CheckCRC(n, data, data + n, "app_chunk") )
return false;
// Pass on to BinPAC.
assert(data + n < endp->buffer + endp->buffer_len);
flow->flow_buffer()->BufferData(data + transport, data + n);
transport = 0;
data += n + 2;
len -= n;
}
if ( is_first )
endp->encountered_first_chunk = true;
if ( ! is_first && ! endp->encountered_first_chunk )
{
// We lost the first chunk.
Weird("dnp3_first_application_layer_chunk_missing");
return false;
}
if ( is_last )
{
flow->flow_buffer()->FinishBuffer();
flow->FlowEOF();
ClearEndpointState(orig);
}
return true;
}
void DNP3_TCP_Analyzer::ClearEndpointState(bool orig)
{
Endpoint* endp = orig ? &orig_state : &resp_state;
binpac::DNP3::DNP3_Flow* flow = orig ? interp->upflow() : interp->downflow();
endp->in_hdr = true;
endp->encountered_first_chunk = false;
endp->buffer_len = 0;
endp->pkt_length = 0;
endp->tpflags = 0;
endp->pkt_cnt = 0;
}
bool DNP3_TCP_Analyzer::CheckCRC(int len, const u_char* data, const u_char* crc16, const char* where)
{
unsigned int crc = CalcCRC(len, data);
if ( crc16[0] == (crc & 0xff) && crc16[1] == (crc & 0xff00) >> 8 )
return true;
Weird(fmt("dnp3_corrupt_%s_checksum", where));
return false;
}
void DNP3_TCP_Analyzer::PrecomputeCRCTable()
{
for( unsigned int i = 0; i < 256; i++)
{
unsigned int crc = i;
for ( unsigned int j = 0; j < 8; ++j )
{
if ( crc & 0x0001 )
crc = (crc >> 1) ^ 0xA6BC; // Generating polynomial.
else
crc >>= 1;
}
crc_table[i] = crc;
}
}
unsigned int DNP3_TCP_Analyzer::CalcCRC(int len, const u_char* data)
{
unsigned int crc = 0x0000;
for ( int i = 0; i < len; i++ )
{
unsigned int index = (crc ^ data[i]) & 0xFF;
crc = crc_table[index] ^ (crc >> 8);
}
return ~crc & 0xFFFF;
}
// ?? For DNP3 over UDP analyzer. most of the codes are copied and pasted. Better way to reuse the code?
DNP3_UDP_Analyzer::DNP3_UDP_Analyzer(Connection* c) : Analyzer("DNP3_UDP", c)
{
interp = new binpac::DNP3::DNP3_Conn(this);
ClearEndpointState(true);
ClearEndpointState(false);
ClearEndpointState(interp, true);
ClearEndpointState(interp, false);
if ( ! crc_table_initialized )
PrecomputeCRCTable();
@ -410,7 +419,7 @@ void DNP3_UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, ui
try
{
if ( ! ProcessData(len, data, orig) )
if ( ! ProcessData(this, interp, len, data, orig) )
SetSkip(1);
}
@ -420,228 +429,4 @@ void DNP3_UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, ui
throw;
}
}
/*
void DNP3_UDP_Analyzer::Undelivered(uint64 seq, int len, bool orig)
{
Analyzer::Undelivered(seq, len, orig);
interp->NewGap(orig, len);
}
void DNP3_UDP_Analyzer::EndpointEOF(bool is_orig)
{
Analyzer::EndpointEOF(is_orig);
interp->FlowEOF(is_orig);
}
*/
bool DNP3_UDP_Analyzer::ProcessData(int len, const u_char* data, bool orig)
{
Endpoint* endp = orig ? &orig_state : &resp_state;
while ( len )
{
if ( endp->in_hdr )
{
// We're parsing the DNP3 header and link layer, get that in full.
if ( ! AddToBuffer(endp, PSEUDO_APP_LAYER_INDEX, &data, &len) )
return true;
// The first two bytes must always be 0x0564.
if( endp->buffer[0] != 0x05 || endp->buffer[1] != 0x64 )
{
Weird("dnp3_header_lacks_magic");
return false;
}
// Make sure header checksum is correct.
if ( ! CheckCRC(PSEUDO_LINK_LAYER_LEN, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN, "header") )
{
ProtocolViolation("broken_checksum");
return false;
}
// If the checksum works out, we're pretty certainly DNP3.
ProtocolConfirmation();
// DNP3 packets without transport and application
// layers can happen, we ignore them.
if ( (endp->buffer[PSEUDO_LENGTH_INDEX] + 3) == (char)PSEUDO_LINK_LAYER_LEN )
{
ClearEndpointState(orig);
return true;
}
// Double check the direction in case the first
// received packet is a response.
u_char ctrl = endp->buffer[PSEUDO_CONTROL_FIELD_INDEX];
if ( orig != (bool)(ctrl & 0x80) )
Weird("dnp3_unexpected_flow_direction");
// Update state.
endp->pkt_length = endp->buffer[PSEUDO_LENGTH_INDEX];
endp->tpflags = endp->buffer[PSEUDO_TRANSPORT_INDEX];
endp->in_hdr = false; // Now parsing application layer.
// For the first packet, we submit the header to
// BinPAC.
if ( ++endp->pkt_cnt == 1 )
interp->NewData(orig, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN);
}
if ( ! endp->in_hdr )
{
assert(endp->pkt_length);
// We're parsing the DNP3 application layer, get that
// in full now as well. We calculate the number of
// raw bytes the application layer consists of from
// the packet length by determining how much 16-byte
// chunks fit in there, and then add 2 bytes CRC for
// each.
int n = PSEUDO_APP_LAYER_INDEX + (endp->pkt_length - 5) + ((endp->pkt_length - 5) / 16) * 2 + 2 - 1;
if ( ! AddToBuffer(endp, n, &data, &len) )
return true;
// Parse the the application layer data.
if ( ! ParseAppLayer(endp) )
return false;
// Done with this packet, prepare for next.
endp->buffer_len = 0;
endp->in_hdr = true;
}
}
return true;
}
bool DNP3_UDP_Analyzer::AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len)
{
if ( ! target_len )
return true;
int to_copy = min(*len, target_len - endp->buffer_len);
memcpy(endp->buffer + endp->buffer_len, *data, to_copy);
*data += to_copy;
*len -= to_copy;
endp->buffer_len += to_copy;
return endp->buffer_len == target_len;
}
bool DNP3_UDP_Analyzer::ParseAppLayer(Endpoint* endp)
{
bool orig = (endp == &orig_state);
binpac::DNP3::DNP3_Flow* flow = orig ? interp->upflow() : interp->downflow();
u_char* data = endp->buffer + PSEUDO_TRANSPORT_INDEX; // The transport layer byte counts as app-layer it seems.
int len = endp->pkt_length - 5;
// DNP3 Packet : DNP3 Pseudo Link Layer | DNP3 Pseudo Transport Layer | DNP3 Pseudo Application Layer
// DNP3 Serial Transport Layer data is always 1 byte.
// Get FIN FIR seq field in transport header.
// FIR indicate whether the following DNP3 Serial Application Layer is first chunk of bytes or not.
// FIN indicate whether the following DNP3 Serial Application Layer is last chunk of bytes or not.
int is_first = (endp->tpflags & 0x40) >> 6; // Initial chunk of data in this packet.
int is_last = (endp->tpflags & 0x80) >> 7; // Last chunk of data in this packet.
int transport = PSEUDO_TRANSPORT_LEN;
int i = 0;
while ( len > 0 )
{
int n = min(len, 16);
// Make sure chunk has a correct checksum.
if ( ! CheckCRC(n, data, data + n, "app_chunk") )
return false;
// Pass on to BinPAC.
assert(data + n < endp->buffer + endp->buffer_len);
flow->flow_buffer()->BufferData(data + transport, data + n);
transport = 0;
data += n + 2;
len -= n;
}
if ( is_first )
endp->encountered_first_chunk = true;
if ( ! is_first && ! endp->encountered_first_chunk )
{
// We lost the first chunk.
Weird("dnp3_first_application_layer_chunk_missing");
return false;
}
if ( is_last )
{
flow->flow_buffer()->FinishBuffer();
flow->FlowEOF();
ClearEndpointState(orig);
}
return true;
}
void DNP3_UDP_Analyzer::ClearEndpointState(bool orig)
{
Endpoint* endp = orig ? &orig_state : &resp_state;
binpac::DNP3::DNP3_Flow* flow = orig ? interp->upflow() : interp->downflow();
endp->in_hdr = true;
endp->encountered_first_chunk = false;
endp->buffer_len = 0;
endp->pkt_length = 0;
endp->tpflags = 0;
endp->pkt_cnt = 0;
}
bool DNP3_UDP_Analyzer::CheckCRC(int len, const u_char* data, const u_char* crc16, const char* where)
{
unsigned int crc = CalcCRC(len, data);
if ( crc16[0] == (crc & 0xff) && crc16[1] == (crc & 0xff00) >> 8 )
return true;
Weird(fmt("dnp3_corrupt_%s_checksum", where));
return false;
}
void DNP3_UDP_Analyzer::PrecomputeCRCTable()
{
for( unsigned int i = 0; i < 256; i++)
{
unsigned int crc = i;
for ( unsigned int j = 0; j < 8; ++j )
{
if ( crc & 0x0001 )
crc = (crc >> 1) ^ 0xA6BC; // Generating polynomial.
else
crc >>= 1;
}
crc_table[i] = crc;
}
}
unsigned int DNP3_UDP_Analyzer::CalcCRC(int len, const u_char* data)
{
unsigned int crc = 0x0000;
for ( int i = 0; i < len; i++ )
{
unsigned int index = (crc ^ data[i]) & 0xFF;
crc = crc_table[index] ^ (crc >> 8);
}
return ~crc & 0xFFFF;
}

View file

@ -9,7 +9,44 @@
namespace analyzer { namespace dnp3 {
class DNP3_TCP_Analyzer : public tcp::TCP_ApplicationAnalyzer {
class DNP3_Analyzer {
public:
DNP3_Analyzer();
virtual ~DNP3_Analyzer();
protected:
static const int MAX_BUFFER_SIZE = 300;
struct Endpoint {
u_char buffer[MAX_BUFFER_SIZE];
int buffer_len;
bool in_hdr;
int tpflags;
int pkt_length;
int pkt_cnt;
bool encountered_first_chunk;
};
bool ProcessData(analyzer::Analyzer* thisAnalyzer, binpac::DNP3::DNP3_Conn* thisInterp, int len, const u_char* data, bool orig);
void ClearEndpointState(binpac::DNP3::DNP3_Conn* localInterp, bool orig);
bool AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len);
bool ParseAppLayer(analyzer::Analyzer* thisAnalyzer, binpac::DNP3::DNP3_Conn* thisInterp, Endpoint* endp);
bool CheckCRC(analyzer::Analyzer* thisAnalyzer, int len, const u_char* data, const u_char* crc16, const char* where);
unsigned int CalcCRC(int len, const u_char* data);
static void PrecomputeCRCTable();
static bool crc_table_initialized;
static unsigned int crc_table[256];
Endpoint orig_state;
Endpoint resp_state;
};
class DNP3_TCP_Analyzer : public DNP3_Analyzer, public tcp::TCP_ApplicationAnalyzer {
public:
DNP3_TCP_Analyzer(Connection* conn);
virtual ~DNP3_TCP_Analyzer();
@ -23,38 +60,11 @@ public:
{ return new DNP3_TCP_Analyzer(conn); }
private:
static const int MAX_BUFFER_SIZE = 300;
struct Endpoint {
u_char buffer[MAX_BUFFER_SIZE];
int buffer_len;
bool in_hdr;
int tpflags;
int pkt_length;
int pkt_cnt;
bool encountered_first_chunk;
};
bool ProcessData(int len, const u_char* data, bool orig);
void ClearEndpointState(bool orig);
bool AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len);
bool ParseAppLayer(Endpoint* endp);
bool CheckCRC(int len, const u_char* data, const u_char* crc16, const char* where);
unsigned int CalcCRC(int len, const u_char* data);
binpac::DNP3::DNP3_Conn* interp;
Endpoint orig_state;
Endpoint resp_state;
static void PrecomputeCRCTable();
static bool crc_table_initialized;
static unsigned int crc_table[256];
};
class DNP3_UDP_Analyzer : public analyzer::Analyzer {
class DNP3_UDP_Analyzer : public DNP3_Analyzer, public analyzer::Analyzer {
public:
DNP3_UDP_Analyzer(Connection* conn);
virtual ~DNP3_UDP_Analyzer();
@ -62,41 +72,12 @@ public:
virtual void Done();
virtual void DeliverPacket(int len, const u_char* data, bool orig,
uint64 seq, const IP_Hdr* ip, int caplen);
//virtual void Undelivered(uint64 seq, int len, bool orig);
//virtual void EndpointEOF(bool is_orig);
static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new DNP3_UDP_Analyzer(conn); }
private:
static const int MAX_BUFFER_SIZE = 300;
struct Endpoint {
u_char buffer[MAX_BUFFER_SIZE];
int buffer_len;
bool in_hdr;
int tpflags;
int pkt_length;
int pkt_cnt;
bool encountered_first_chunk;
};
bool ProcessData(int len, const u_char* data, bool orig);
void ClearEndpointState(bool orig);
bool AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len);
bool ParseAppLayer(Endpoint* endp);
bool CheckCRC(int len, const u_char* data, const u_char* crc16, const char* where);
unsigned int CalcCRC(int len, const u_char* data);
binpac::DNP3::DNP3_Conn* interp;
Endpoint orig_state;
Endpoint resp_state;
static void PrecomputeCRCTable();
static bool crc_table_initialized;
static unsigned int crc_table[256];
binpac::DNP3::DNP3_Conn* interp;
};