123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- package layers
- import (
- "encoding/binary"
- "errors"
- "github.com/google/gopacket"
- )
- const mbapRecordSizeInBytes int = 7
- const modbusPDUMinimumRecordSizeInBytes int = 2
- const modbusPDUMaximumRecordSizeInBytes int = 253
- type ModbusProtocol uint16
- const (
- ModbusProtocolModbus ModbusProtocol = 0
- )
- func (mp ModbusProtocol) String() string {
- switch mp {
- default:
- return "Unknown"
- case ModbusProtocolModbus:
- return "Modbus"
- }
- }
- type ModbusTCP struct {
- BaseLayer
- TransactionIdentifier uint16
- ProtocolIdentifier ModbusProtocol
- Length uint16
- UnitIdentifier uint8
- }
- func (d *ModbusTCP) LayerType() gopacket.LayerType {
- return LayerTypeModbusTCP
- }
- func decodeModbusTCP(data []byte, p gopacket.PacketBuilder) error {
-
- d := &ModbusTCP{}
- err := d.DecodeFromBytes(data, p)
- if err != nil {
- return err
- }
-
-
- p.AddLayer(d)
- p.SetApplicationLayer(d)
- return p.NextDecoder(d.NextLayerType())
- }
- func (d *ModbusTCP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
-
- if len(data) < mbapRecordSizeInBytes+modbusPDUMinimumRecordSizeInBytes {
- df.SetTruncated()
- return errors.New("ModbusTCP packet too short")
- }
- if len(data) > mbapRecordSizeInBytes+modbusPDUMaximumRecordSizeInBytes {
- df.SetTruncated()
- return errors.New("ModbusTCP packet too long")
- }
-
-
-
- d.BaseLayer = BaseLayer{Contents: data[:mbapRecordSizeInBytes], Payload: data[mbapRecordSizeInBytes:len(data)]}
-
-
- d.TransactionIdentifier = binary.BigEndian.Uint16(data[:2])
- d.ProtocolIdentifier = ModbusProtocol(binary.BigEndian.Uint16(data[2:4]))
- d.Length = binary.BigEndian.Uint16(data[4:6])
-
- if d.Length != uint16(len(d.BaseLayer.Payload)+1) {
- df.SetTruncated()
- return errors.New("ModbusTCP packet with wrong field value (Length)")
- }
- d.UnitIdentifier = uint8(data[6])
- return nil
- }
- func (d *ModbusTCP) NextLayerType() gopacket.LayerType {
- return gopacket.LayerTypePayload
- }
- func (d *ModbusTCP) Payload() []byte {
- return d.BaseLayer.Payload
- }
|