]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
lua: document the dnp3 lib 13683/head
authorJason Ish <jason.ish@oisf.net>
Wed, 30 Jul 2025 23:36:33 +0000 (17:36 -0600)
committerJason Ish <jason.ish@oisf.net>
Fri, 1 Aug 2025 16:54:19 +0000 (10:54 -0600)
Ticket: #7631

doc/userguide/lua/libs/dnp3.rst [new file with mode: 0644]
doc/userguide/lua/libs/index.rst

diff --git a/doc/userguide/lua/libs/dnp3.rst b/doc/userguide/lua/libs/dnp3.rst
new file mode 100644 (file)
index 0000000..202dd65
--- /dev/null
@@ -0,0 +1,184 @@
+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.
+
+Setup
+*****
+
+::
+
+    local dnp3 = require("suricata.dnp3")
+
+Module Functions
+****************
+
+.. function:: 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
+   :raises 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
+
+Transaction Object Structure
+****************************
+
+The transaction object returned by ``get_tx()`` contains the following fields:
+
+.. attribute:: tx_num
+
+   Transaction number (integer)
+
+.. attribute:: is_request
+
+   Boolean indicating if this is a request (true) or response (false)
+
+.. attribute:: request
+
+   Table containing request data (only present when ``is_request`` is true)
+
+.. attribute:: response
+
+   Table containing response data (only present when ``is_request`` is false)
+
+Request/Response Structure
+**************************
+
+Both request and response tables contain:
+
+.. attribute:: done
+
+   Boolean indicating if the transaction is complete
+
+.. attribute:: complete
+
+   Boolean indicating if all data has been received
+
+.. attribute:: link_header
+
+   Table containing DNP3 link layer header fields:
+
+   - ``len``: Frame length
+   - ``control``: Control byte
+   - ``dst``: Destination address
+   - ``src``: Source address
+   - ``crc``: CRC value
+
+.. attribute:: transport_header
+
+   Transport layer header byte (integer)
+
+.. attribute:: application_header
+
+   Table containing DNP3 application layer header fields:
+
+   - ``control``: Application control byte
+   - ``function_code``: DNP3 function code
+
+.. attribute:: objects
+
+   Array of DNP3 objects in the message
+
+Additionally, response tables contain:
+
+.. attribute:: indicators
+
+   Internal Indication (IIN) field as a 16-bit integer combining IIN1 and IIN2
+
+Objects Structure
+*****************
+
+Each object in the ``objects`` array contains:
+
+.. attribute:: group
+
+   DNP3 object group number (integer)
+
+.. attribute:: variation
+
+   DNP3 object variation number (integer)
+
+.. attribute:: points
+
+   Array of data points for this object
+
+Points Structure
+****************
+
+Each point in the ``points`` array contains:
+
+.. attribute:: 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.
+
+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
index 87e73fe09f336b9fab9a7a0f7273e4f9539e4d38..43448654db77969e3b67dba370e0cb3dc3df659d 100644 (file)
@@ -11,6 +11,7 @@ environment without access to additional modules.
    base64
    bytevar
    config
+   dnp3
    dns
    file
    flowlib