16.3.4. DNP3

The suricata.dnp3 module provides access to DNP3 (Distributed Network Protocol 3) transaction data in Suricata Lua rules.

It is only available in Suricata Lua rules, not output scripts.

16.3.4.1. Setup

local dnp3 = require("suricata.dnp3")

16.3.4.2. Module Functions

dnp3.get_tx()

Returns the current DNP3 transaction object containing request or response data.

Returns:

A table containing the DNP3 transaction data, or nil on error

Raises:
  • error -- If the protocol is not DNP3

  • error -- If no transaction is available

Example:

function match(args)
    local tx = dnp3.get_tx()
    if tx and tx.is_request then
        -- Process DNP3 request
    end
end

16.3.4.3. Transaction Object Structure

The transaction object returned by get_tx() contains the following fields:

tx_num

Transaction number (integer)

is_request

Boolean indicating if this is a request (true) or response (false)

request

Table containing request data (only present when is_request is true)

response

Table containing response data (only present when is_request is false)

16.3.4.4. Request/Response Structure

Both request and response tables contain:

done

Boolean indicating if the transaction is complete

complete

Boolean indicating if all data has been received

Table containing DNP3 link layer header fields:

  • len: Frame length

  • control: Control byte

  • dst: Destination address

  • src: Source address

  • crc: CRC value

transport_header

Transport layer header byte (integer)

application_header

Table containing DNP3 application layer header fields:

  • control: Application control byte

  • function_code: DNP3 function code

objects

Array of DNP3 objects in the message

Additionally, response tables contain:

indicators

Internal Indication (IIN) field as a 16-bit integer combining IIN1 and IIN2

16.3.4.5. Objects Structure

Each object in the objects array contains:

group

DNP3 object group number (integer)

variation

DNP3 object variation number (integer)

points

Array of data points for this object

16.3.4.6. Points Structure

Each point in the points array contains:

index

Point index (integer)

Additional point fields depend on the object group and variation. Common fields include:

  • state: Binary state value

  • online: Online status flag

  • restart: Restart flag

  • comm_lost: Communication lost flag

  • remote_forced: Remote forced flag

  • local_forced: Local forced flag

  • chatter_filter: Chatter filter flag

  • reserved: Reserved bits

  • value: Analog value (for analog objects)

  • timestamp: Timestamp value (for time-tagged objects)

For all available fields, see app-layer-dnp3-objects.h in the Suricata source code.

16.3.4.7. Example Usage

Complete example checking for specific DNP3 function codes:

local dnp3 = require("suricata.dnp3")

function init(args)
    return {}
end

function match(args)
    local tx = dnp3.get_tx()

    if not tx then
        return 0
    end

    -- Check for write function code in request
    if tx.is_request and tx.request then
        local func_code = tx.request.application_header.function_code
        if func_code == 2 then  -- WRITE function
            return 1
        end
    end

    -- Check for specific object types
    if tx.request and tx.request.objects then
        for _, obj in ipairs(tx.request.objects) do
            if obj.group == 12 and obj.variation == 1 then
                -- Control Relay Output Block
                return 1
            end
        end
    end

    return 0
end