mirror of
https://github.com/zeek/zeek.git
synced 2025-10-13 20:18:20 +00:00
Final touches to modbus analyzer for now.
- There are still some broken events in the modbus analyzer because I don't have traffic to test with (coil and record related events primarily). - There are a few example scripts in policy/protocols/modbus
This commit is contained in:
parent
009efbcb27
commit
a2f336cc72
6 changed files with 549 additions and 179 deletions
|
@ -14,13 +14,13 @@ enum function_codes {
|
|||
READ_INPUT_REGISTERS = 0x04,
|
||||
WRITE_SINGLE_COIL = 0x05,
|
||||
WRITE_SINGLE_REGISTER = 0x06,
|
||||
READ_EXCEPTION_STATUS = 0x07,
|
||||
DIAGNOSTICS = 0x08,
|
||||
GET_COMM_EVENT_COUNTER = 0x0B,
|
||||
GET_COMM_EVENT_LOG = 0x0C,
|
||||
# READ_EXCEPTION_STATUS = 0x07,
|
||||
# DIAGNOSTICS = 0x08,
|
||||
# GET_COMM_EVENT_COUNTER = 0x0B,
|
||||
# GET_COMM_EVENT_LOG = 0x0C,
|
||||
WRITE_MULTIPLE_COILS = 0x0F,
|
||||
WRITE_MULTIPLE_REGISTERS = 0x10,
|
||||
REPORT_SLAVE_ID = 0x11,
|
||||
# REPORT_SLAVE_ID = 0x11,
|
||||
READ_FILE_RECORD = 0x14,
|
||||
WRITE_FILE_RECORD = 0x15,
|
||||
MASK_WRITE_REGISTER = 0x16,
|
||||
|
@ -64,9 +64,7 @@ type ModbusTCP_PDU(is_orig: bool) = record {
|
|||
true -> request: ModbusTCP_Request(header);
|
||||
false -> response: ModbusTCP_Response(header);
|
||||
};
|
||||
} &length=header.len+6, &byteorder=bigendian, &let {
|
||||
deliver: bool = $context.flow.deliver_message(header);
|
||||
};
|
||||
} &length=header.len+6, &byteorder=bigendian;
|
||||
|
||||
type ModbusTCP_TransportHeader = record {
|
||||
tid: uint16; # Transaction identifier
|
||||
|
@ -74,6 +72,8 @@ type ModbusTCP_TransportHeader = record {
|
|||
len: uint16; # Length of everyting after this field
|
||||
uid: uint8; # Unit identifier (previously 'slave address')
|
||||
fc: uint8; # MODBUS function code (see function_codes enum)
|
||||
} &byteorder=bigendian, &let {
|
||||
deliver: bool = $context.flow.deliver_message(this);
|
||||
};
|
||||
|
||||
type ModbusTCP_Request(header: ModbusTCP_TransportHeader) = case header.fc of {
|
||||
|
@ -98,7 +98,7 @@ type ModbusTCP_Request(header: ModbusTCP_TransportHeader) = case header.fc of {
|
|||
#ENCAP_INTERFACE_TRANSPORT
|
||||
|
||||
# All the rest
|
||||
default -> unknown: empty &restofdata;
|
||||
default -> unknown: bytestring &restofdata;
|
||||
};
|
||||
|
||||
# Responses
|
||||
|
@ -140,7 +140,7 @@ type ModbusTCP_Response(header: ModbusTCP_TransportHeader) = case header.fc of {
|
|||
READ_FIFO_QUEUE_EXCEPTION -> readFIFOQueueException: Exception(header);
|
||||
|
||||
# All the rest
|
||||
default -> unknown: empty &restofdata;
|
||||
default -> unknown: bytestring &restofdata;
|
||||
};
|
||||
|
||||
type Exception(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -155,7 +155,7 @@ type ReadCoilsRequest(header: ModbusTCP_TransportHeader) = record {
|
|||
quantity: uint16 &check(quantity <= 2000);
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadCoilsRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=1
|
||||
type ReadCoilsResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -163,7 +163,7 @@ type ReadCoilsResponse(header: ModbusTCP_TransportHeader) = record {
|
|||
bits: bytestring &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadCoilsResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=2
|
||||
type ReadDiscreteInputsRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -171,7 +171,7 @@ type ReadDiscreteInputsRequest(header: ModbusTCP_TransportHeader) = record {
|
|||
quantity: uint16 &check(quantity <= 2000);
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadDiscreteInputsRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=2
|
||||
type ReadDiscreteInputsResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -179,7 +179,7 @@ type ReadDiscreteInputsResponse(header: ModbusTCP_TransportHeader) = record {
|
|||
bits: bytestring &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadDiscreteInputsResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=3
|
||||
type ReadHoldingRegistersRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -187,7 +187,7 @@ type ReadHoldingRegistersRequest(header: ModbusTCP_TransportHeader) = record {
|
|||
quantity: uint16 &check(1 <= quantity && quantity <= 125);
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadHoldingRegistersRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=3
|
||||
type ReadHoldingRegistersResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -195,7 +195,7 @@ type ReadHoldingRegistersResponse(header: ModbusTCP_TransportHeader) = record {
|
|||
registers: uint16[] &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadHoldingRegistersResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=4
|
||||
type ReadInputRegistersRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -203,7 +203,7 @@ type ReadInputRegistersRequest(header: ModbusTCP_TransportHeader) = record {
|
|||
quantity: uint16 &check(1 <= quantity && quantity <= 125);
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadInputRegistersRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=4
|
||||
type ReadInputRegistersResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -211,41 +211,39 @@ type ReadInputRegistersResponse(header: ModbusTCP_TransportHeader) = record {
|
|||
registers: uint16[] &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadInputRegistersResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=5
|
||||
type WriteSingleCoilRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
start_address: uint16;
|
||||
on_off: uint8 &check(on_off == 0x00 || on_off == 0xFF);
|
||||
other: uint8 &check(other == 0x00);
|
||||
address: uint16;
|
||||
value: uint16 &check(value == 0x0000 || value == 0xFF00);
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteSingleCoilRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=5
|
||||
type WriteSingleCoilResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
start_address: uint16;
|
||||
on_off: uint8 &check(on_off == 0x00 || on_off == 0xFF);
|
||||
other: uint8 &check(other == 0x00);
|
||||
address: uint16;
|
||||
value: uint16 &check(value == 0x0000 || value == 0xFF00);
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteSingleCoilResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=6
|
||||
type WriteSingleRegisterRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
start_address: uint16;
|
||||
value: uint16;
|
||||
address: uint16;
|
||||
value: uint16;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteSingleRegisterRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=6
|
||||
type WriteSingleRegisterResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
start_address: uint16;
|
||||
value: uint16;
|
||||
address: uint16;
|
||||
value: uint16;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteSingleRegisterResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=15
|
||||
type WriteMultipleCoilsRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -255,7 +253,7 @@ type WriteMultipleCoilsRequest(header: ModbusTCP_TransportHeader) = record {
|
|||
coils: bytestring &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteMultipleCoilsRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=15
|
||||
type WriteMultipleCoilsResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -263,7 +261,7 @@ type WriteMultipleCoilsResponse(header: ModbusTCP_TransportHeader) = record {
|
|||
quantity: uint16 &check(quantity <= 0x07B0);
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteMultipleCoilsResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=16
|
||||
type WriteMultipleRegistersRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -275,7 +273,7 @@ type WriteMultipleRegistersRequest(header: ModbusTCP_TransportHeader) = record {
|
|||
registers: uint16[quantity] &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteMultipleRegistersRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=16
|
||||
type WriteMultipleRegistersResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -283,39 +281,38 @@ type WriteMultipleRegistersResponse(header: ModbusTCP_TransportHeader) = record
|
|||
quantity: uint16;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteMultipleRegistersResponse(header, this);
|
||||
};
|
||||
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# Support data structure for following message type.
|
||||
type FileRecordRequest = record {
|
||||
ref_type: uint8;
|
||||
file_num: uint16;
|
||||
record_num: uint16;
|
||||
ref_type: uint8 &check(ref_type == 6);
|
||||
file_num: uint16 &check(file_num > 0);
|
||||
record_num: uint16 &check(record_num <= 0x270F);
|
||||
record_len: uint16;
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=20
|
||||
type ReadFileRecordRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
byte_count: uint8;
|
||||
byte_count: uint8 &check(byte_count >= 0x07 && byte_count <= 0xF5);
|
||||
references: FileRecordRequest[] &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadFileRecordRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# Support data structure for the following message type.
|
||||
type FileRecordResponse = record {
|
||||
file_len: uint8;
|
||||
ref_type: uint8;
|
||||
file_len: uint8 &check(file_len >= 0x07 && file_len <= 0xF5);
|
||||
ref_type: uint8 &check(ref_type == 6);
|
||||
record_data: uint16[] &length=file_len;
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=20
|
||||
type ReadFileRecordResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
byte_count: uint8;
|
||||
byte_count: uint8 &check(byte_count >= 0x07 && byte_count <= 0xF5);
|
||||
references: FileRecordResponse[] &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadFileRecordResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# Support data structure for the two following message types.
|
||||
type ReferenceWithData = record {
|
||||
|
@ -324,7 +321,7 @@ type ReferenceWithData = record {
|
|||
record_num: uint16;
|
||||
word_count: uint16;
|
||||
register_value: uint16[word_count];
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=21
|
||||
type WriteFileRecordRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -332,7 +329,7 @@ type WriteFileRecordRequest(header: ModbusTCP_TransportHeader) = record {
|
|||
references: ReferenceWithData[] &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteFileRecordRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=21
|
||||
type WriteFileRecordResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -340,27 +337,25 @@ type WriteFileRecordResponse(header: ModbusTCP_TransportHeader) = record {
|
|||
references: ReferenceWithData[] &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_WriteFileRecordResponse(header, this);
|
||||
};
|
||||
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=22
|
||||
type MaskWriteRegisterRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
start_address: uint16;
|
||||
and_mask: uint16;
|
||||
or_mask: uint16;
|
||||
address: uint16;
|
||||
and_mask: uint16;
|
||||
or_mask: uint16;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_MaskWriteRegisterRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=22
|
||||
type MaskWriteRegisterResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
start_address: uint16;
|
||||
and_mask: uint16;
|
||||
or_mask: uint16;
|
||||
address: uint16;
|
||||
and_mask: uint16;
|
||||
or_mask: uint16;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_MaskWriteRegisterResponse(header, this);
|
||||
};
|
||||
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=23
|
||||
type ReadWriteMultipleRegistersRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -372,7 +367,7 @@ type ReadWriteMultipleRegistersRequest(header: ModbusTCP_TransportHeader) = reco
|
|||
write_register_values: uint16[write_quantity] &length=write_byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadWriteMultipleRegistersRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=23
|
||||
type ReadWriteMultipleRegistersResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
|
@ -380,20 +375,20 @@ type ReadWriteMultipleRegistersResponse(header: ModbusTCP_TransportHeader) = rec
|
|||
registers: uint16[] &length=byte_count;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadWriteMultipleRegistersResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# REQUEST FC=24
|
||||
type ReadFIFOQueueRequest(header: ModbusTCP_TransportHeader) = record {
|
||||
start_address: uint16;
|
||||
} &let{
|
||||
deliver: bool = $context.flow.deliver_ReadFIFOQueueRequest(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
# RESPONSE FC=24
|
||||
type ReadFIFOQueueResponse(header: ModbusTCP_TransportHeader) = record {
|
||||
byte_count: uint16 &check(byte_count <= 62);
|
||||
fifo_count: uint16 &check(word_count <= 31);
|
||||
register_data: uint16[fifo_count];
|
||||
fifo_count: uint16 &check(fifo_count <= 31);
|
||||
register_data: uint16[fifo_count] &length=byte_count/2;
|
||||
} &let {
|
||||
deliver: bool = $context.flow.deliver_ReadFIFOQueueResponse(header, this);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue