DNP3

December 17, 2025 ยท View on GitHub

The DNP3 plugin for Caldera provides adversary emulation abilities specific to the DNP3 control systems protocol.

v2.0 released 05 Dec 2024

Overview

The DNP3 plugin provides 11 unique abilities specific to the DNP3 protocol offered for both serial and TCP connections (22 total abilities). This is accomplished not through exploitation, but rather by leveraging native functionality within the protocol.

The following table outlines MITRE ATT&CK for ICS coverage provided by the DNP3 plugin.

CollectionInhibit Response FunctionImpair Process Control
Automated CollectionDevice Restart/ShutdownUnauthorized Command Message
Point & Tag IdentificationBlock Reporting MessageModify Parameter
Denial of Service

Ability Overview Tables

The following table(s) list each plugin ability by their corresponding tactic.

Collection Abilities

AbilityTechniqueTechnique Id
DNP3 - ReadPoint & Tag IdentificationT0861
DNP3 - Read AllPoint & Tag IdentificationT0861
DNP3 - Integrity PollAutomated CollectionT0802
DNP3 - Enable Unsolicited MessagesAutomated CollectionT0802

Inhibit Response Function Abilities

AbilityTechniqueTechnique Id
DNP3 - Cold RestartDevice Restart/ShutdownT0816
DNP3 - Warm RestartDevice Restart/ShutdownT0816
DNP3 - Disable Unsolicited MessagesBlock Reporting MessageT0804

Impair Process Control Abilities

AbilityTechniqueTechnique Id
DNP3 - OperateUnauthorized Command MessageT0855
DNP3 - Toggle (Two-Output Model)Unauthorized Command MessageT0855
DNP3 - Toggle (Activation Model)Unauthorized Command MessageT0855
DNP3 - Set AnalogModify ParameterT0836

Architecture

This section describes the main components of the plugin and how they interface.

Block Diagram

block diagram

The DNP3 plugin exposes several new protocol specific abilities to your Caldera instance. The abilities are executed from a host running a Caldera agent via the corresponding payload. Abilities must target devices that support the DNP3 protocol to achieve described effects.

Payloads

The DNP3 plugin includes one payload that implements the abilities, compiled for three different host architectures:

  • dnp3-actions.exe (Windows)
  • dnp3-actions (Linux)
  • dnp3-actions_darwin (Mac)

Libraries

The following libraries were used to build the DNP3 payloads:

LibraryVersionLicense
OpenDNP3v3.1.2Apache 2.0
CLI11v2.4.2License

Usage

This section describes how to initially deploy and execute the abilities present within the DNP3 Plugin.

Deployment

  1. Identify the target system you would like to communicate with via the DNP3 protocol.
  2. Identify a viable host for the Caldera agent that will be sending DNP3 messages to the target system. A viable host has a network connection to the target system and has an architecture that is compatible with one of the plugin's payloads.
  3. Deploy the Caldera agent to the viable host.
  4. Run a combination of the DNP3 plugin abilities to achieve the desired effect.

If you don't know where to begin, try using DNP3 - Integrity Poll to read all of the data on a device.

Reference the Caldera training plugin for a step-by-step tutorial on how to deploy an agent and run abilities via an operation.

Test Server (Outstation) Usage

This plugin includes a test server (known in DNP3 parlance as an outstation) in the plugins/ directory that can be used to create a test environment for the plugin.

  1. Start the Caldera server and deploy a Caldera agent.
  2. On the device where the agent is running, start the DNP3 server using the following commands:
Windows (psh)
.\dnp3-outstation.exe --tui
Linux (sh)
./dnp3-outstation --tui
Darwin (sh)
./dnp3-outstation_darwin --tui

  1. Execute a DNP3 ability from your agent using the Caldera server. "DNP3 (TCP) - Integrity Poll" is a good first test. To target the DNP3 test server, ensure you select the following facts:
  • dnp3.server.ip: 127.0.0.1
  • dnp3.link.local: 1
  • dnp3.link.remote: 1024
  1. The outstation is designed to demonstrate the different features and concepts in the DNP3 protocol and is not intended to be an authentic replica of any specific device. Try discovering data on the device, reading and writing analog values, and operating points with different operation types and trip control codes.

Network Connection

This plugin allows the agent to send DNP3 messages using a IP/TCP or serial connection. The first argument to the dnp3-actions payload selects the connection type. This must be followed by several additional arguments to establish the connection.

IP/TCP

Positional arguments (required):

NameDescriptionType
dnp3.server.ipIP address of the outstationstring
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint

Flags (optional):

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000

Serial

Positional arguments (required):

NameDescriptionType
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint

Flags (optional):

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500

Abilities

DNP3 - Read

Read the specified values from the outstation.

For more information, see the [Data Model](#data-model) section.
TCP

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} --start #{dnp3.data.start} --end #{dnp3.data.end}
Linux (sh)
./dnp3-actions tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} --start #{dnp3.data.start} --end #{dnp3.data.end}
Darwin (sh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} --start #{dnp3.data.start} --end #{dnp3.data.end}

Facts:

NameDescriptionType
dnp3.server.ipIP address of the outstationstring
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.data.groupDNP3 datatypeint
dnp3.data.startFirst index to read (inclusive)int
dnp3.data.endFinal index to read (inclusive)int

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
--variationvariation (format) to read the dataintNone
Serial

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} --start #{dnp3.data.start} --end #{dnp3.data.end}
Linux (sh)
./dnp3-actions serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} --start #{dnp3.data.start} --end #{dnp3.data.end}
Darwin (sh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} --start #{dnp3.data.start} --end #{dnp3.data.end}

Facts:

NameDescriptionType
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.data.groupDNP3 datatypeint
dnp3.data.startFirst index to read (inclusive)int
dnp3.data.endFinal index to read (inclusive)int

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500
--variationvariation (format) to read the dataintNone

DNP3 - Read All

Read the specified values from a certain group of the outstation.

For more information, see the [Data Model](#data-model) section.
TCP

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} 
Linux (sh)
./dnp3-actions tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} 
Darwin (sh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group}

Facts:

NameDescriptionType
dnp3.server.ipIP address of the outstationstring
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.data.groupDNP3 datatypeint
dnp3.data.variationVariation of the DNP3 datatype (group)int

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
--variationvariation (format) to read the dataintNone
Serial

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} 
Linux (sh)
./dnp3-actions serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group} 
Darwin (sh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} read #{dnp3.data.group}

Facts:

NameDescriptionType
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.data.groupDNP3 datatypeint
dnp3.data.variationVariation of the DNP3 datatype (group)int
dnp3.data.startFirst index to read (inclusive)int
dnp3.data.endFinal index to read (inclusive)int

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500
--variationvariation (format) to read the dataintNone

DNP3 - Integrity Poll

Read all data groups present on the outstation.

TCP

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} integrity-poll
Linux (sh)
./dnp3-actions tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} integrity-poll
Darwin (sh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} integrity-poll

Facts:

NameDescriptionType
dnp3.server.ipIP address of the outstationstring
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
Serial

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} integrity-poll
Linux (sh)
./dnp3-actions serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} integrity-poll
Darwin (sh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} integrity-poll

Facts:

NameDescriptionType
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500

DNP3 - Operate

Operate specified points utilizing SELECT_BEFORE_OPERATE (SBO) or DIRECT_OPERATE (DO)

For more information on operating points in DNP3 see the [Control Models](#control-models) section.
TCP

Ability Command:

Windows (cmd/psh)
./dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} #{dnp3.op.mode} --indices #{dnp3.operate.indices} --op-type #{dnp3.operate.type} --tcc #{dnp3.operate.tcc}
Linux (sh)
./dnp3-actions tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} #{dnp3.op.mode} --indices #{dnp3.operate.indices} --op-type #{dnp3.operate.type} --tcc #{dnp3.operate.tcc}
Darwin (sh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} #{dnp3.op.mode} --indices #{dnp3.operate.indices} --op-type #{dnp3.operate.type} --tcc #{dnp3.operate.tcc}

Facts:

NameDescriptionType
dnp3.server.ipIP address of the outstationstring
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.operate.modeChoose either SBO or DO Modestring
dnp3.operate.indicesIndices to send the CROB to (operate)comma separated list of int
dnp3.operate.typeOne of 'NUL', 'PULSE_ON', 'PULSE_OFF', 'LATCH_ON', 'LATCH_OFF'string
dnp3.operate.tccOne of 'NUL', 'CLOSE', 'TRIP'string

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
--onsignal on-time value in msint100
--offsignal off-time value in msint100
--counttimes to repeat signalint1
--clearset the control code clear bitstring
Serial

Ability Command:

Windows (cmd/psh)
./dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} #{dnp3.op.mode} --indices #{dnp3.operate.indices} --op-type #{dnp3.operate.type} --tcc #{dnp3.operate.tcc}
Linux (sh)
./dnp3-actions serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} #{dnp3.op.mode} --indices #{dnp3.operate.indices} --op-type #{dnp3.operate.type} --tcc #{dnp3.operate.tcc}
Darwin (sh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} #{dnp3.op.mode} --indices #{dnp3.operate.indices} --op-type #{dnp3.operate.type} --tcc #{dnp3.operate.tcc}

Facts:

NameDescriptionType
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.operate.modeChoose either SBO or DO Modestring
dnp3.operate.indicesIndices to send the CROB to (operate)comma separated list of int
dnp3.operate.typeOne of 'NUL', 'PULSE_ON', 'PULSE_OFF', 'LATCH_ON', 'LATCH_OFF'string
dnp3.operate.tccOne of 'NUL', 'CLOSE', 'TRIP'string

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500
--onsignal on-time value in msint100
--offsignal off-time value in msint100
--counttimes to repeat signalint1
--clearset the control code clear bitstring

DNP3 - Toggle (Activation Model)

Toggle breakers using the activation model (Utilizing trip-indices and close-indices)

For more information on operating points in DNP3 see the [Control Models](#control-models) section.
TCP

Ability Command:

Windows (cmd/psh)
./dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} toggle-activation #{dnp3.op.mode} --trip-indices #{dnp3.trip.indices} --close-indices #{dnp3.close.indices}
Linux (psh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} toggle-activation #{dnp3.op.mode} --trip-indices #{dnp3.trip.indices} --close-indices #{dnp3.close.indices}
Darwin (psh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} toggle-activation #{dnp3.op.mode} --trip-indices #{dnp3.trip.indices} --close-indices #{dnp3.close.indices}

Facts:

NameDescriptionType
dnp3.server.ipIP address of the outstationstring
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.operate.modeChoose either SBO or DO Modestring
dnp3.trip.indicesTrip-indices to send the CROB to (operate)comma separated list of int
dnp3.close.indicesClose-indices to send the CROB to (operate)comma separated list of int
dnp3.operate.typeOne of 'NUL', 'PULSE_ON', 'PULSE_OFF', 'LATCH_ON', 'LATCH_OFF'string
dnp3.operate.tccOne of 'NUL', 'CLOSE', 'TRIP'string

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
--onsignal on-time value in msint100
--offsignal off-time value in msint100
--iterationstimes to repeat signalint1
--delaydelay between trip and close operations in msint30000
Serial

Ability Command:

Windows (cmd/psh)
./dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} toggle-activation #{dnp3.op.mode} --trip-indices #{dnp3.trip.indices} --close-indices #{dnp3.close.indices}
Linux (psh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} toggle-activation #{dnp3.op.mode} --trip-indices #{dnp3.trip.indices} --close-indices #{dnp3.close.indices}
Darwin (psh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} toggle-activation #{dnp3.op.mode} --trip-indices #{dnp3.trip.indices} --close-indices #{dnp3.close.indices}

Facts:

NameDescriptionType
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.operate.modeChoose either SBO or DO Modestring
dnp3.trip.indicesTrip-indices to send the CROB to (operate)comma separated list of int
dnp3.close.indicesClose-indices to send the CROB to (operate)comma separated list of int
dnp3.operate.typeOne of 'NUL', 'PULSE_ON', 'PULSE_OFF', 'LATCH_ON', 'LATCH_OFF'string
dnp3.operate.tccOne of 'NUL', 'CLOSE', 'TRIP'string

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500
--onsignal on-time value in msint100
--offsignal off-time value in msint100
--iterationstimes to repeat signalint1
--delaydelay between trip and close operations in msint30000

DNP3 - Toggle (Two Output Model)

Toggle breakers using the complementary two-output model (Utilizing TRIP/CLOSE on the same index)

For more information on operating points in DNP3 see the [Control Models](#control-models) section.
TCP

Ability Command:

Windows (cmd/psh)
./dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} toggle-two-output #{dnp3.op.mode} --indices #{dnp3.operate.indices}
Linux (psh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} toggle-two-output #{dnp3.op.mode} --indices #{dnp3.operate.indices}
Darwin (psh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} toggle-two-output #{dnp3.op.mode} --indices #{dnp3.operate.indices}

Facts:

NameDescriptionType
dnp3.server.ipIP address of the outstationstring
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.operate.modeChoose either SBO or DO Modestring
dnp3.operate.indicesIndices to send the CROB to (operate)comma separated list of int
dnp3.operate.typeOne of 'NUL', 'PULSE_ON', 'PULSE_OFF', 'LATCH_ON', 'LATCH_OFF'string
dnp3.operate.tccOne of 'NUL', 'CLOSE', 'TRIP'string

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
--onsignal on-time value in msint100
--offsignal off-time value in msint100
--iterationstimes to repeat signalint1
--delaydelay between trip and close operations in msint30000
Serial

Ability Command:

Windows (cmd/psh)
./dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} toggle-two-output #{dnp3.op.mode} --indices #{dnp3.operate.indices}
Linux (psh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} toggle-two-output #{dnp3.op.mode} --indices #{dnp3.operate.indices}
Darwin (psh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} toggle-two-output #{dnp3.op.mode} --indices #{dnp3.operate.indices}

Facts:

NameDescriptionType
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.operate.modeChoose either SBO or DO Modestring
dnp3.operate.indicesIndices to send the CROB to (operate)comma separated list of int
dnp3.operate.typeOne of 'NUL', 'PULSE_ON', 'PULSE_OFF', 'LATCH_ON', 'LATCH_OFF'string
dnp3.operate.tccOne of 'NUL', 'CLOSE', 'TRIP'string

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500
--onsignal on-time value in msint100
--offsignal off-time value in msint100
--iterationstimes to repeat signalint1
--delaydelay between trip and close operations in msint30000

DNP3 - Set Analog

Change the values of specified points

TCP

Ability Command:

Windows (cmd/psh)
./dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} set-analog --indices #{dnp3.operate.indices} --values {dnp3.set.values}
Linux (psh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} set-analog --indices #{dnp3.operate.indices} --values {dnp3.set.values}
Darwin (psh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} set-analog --indices #{dnp3.operate.indices} --values {dnp3.set.values}

Facts:

NameDescriptionType
dnp3.server.ipIP address of the outstationstring
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.set.analogSet analog output values commandstring
dnp3.operate.indicesIndices to send the CROB to (operate)comma separated list of int
dnp3.set.valuesSet values to output on specified pointcomma separated list of int

Optional Flags:

FlagDescriptionTypeDefault
-p, --portPort number of the outstationint20000
--dtypeDatatype of valuesstring'DOUBLE64'
Serial

Ability Command:

Windows (cmd/psh)
./dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} set-analog --indices #{dnp3.operate.indices} --values {dnp3.set.values}
Linux (psh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} set-analog --indices #{dnp3.operate.indices} --values {dnp3.set.values}
Darwin (psh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} set-analog --indices #{dnp3.operate.indices} --values {dnp3.set.values}

Facts:

NameDescriptionType
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceint
dnp3.remote.linkDNP3 link layer address of the remote deviceint
dnp3.set.analogSet analog output values commandstring
dnp3.operate.indicesIndices to send the CROB to (operate)comma separated list of int
dnp3.set.valuesSet values to output on specified pointcomma separated list of int

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500
--dtypeDatatype of valuesstring'DOUBLE64'

DNP3 - Cold Restart

Perform a full restart (cold restart) of the outstation.

May leave the outstation in an unknown or invalid state
TCP

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} cold-restart
Linux (sh)
./dnp3-actions tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} cold-restart
Darwin (sh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} cold-restart

Facts:

NameDescriptionTypeDefault
dnp3.server.ipIP address of the outstationstringNone
dnp3.local.linkDNP3 link layer address of the local deviceintNone
dnp3.remote.linkDNP3 link layer address of the remote deviceintNone

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
Serial

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} cold-restart
Linux (sh)
./dnp3-actions serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} cold-restart
Darwin (sh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} cold-restart

Facts:

NameDescriptionTypeDefault
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceintNone
dnp3.remote.linkDNP3 link layer address of the remote deviceintNone

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500

DNP3 - Warm Restart

Perform a partial restart (warm restart) of the outstation. DNP3 applications will be reset but not affect other processes. Sometimes, this may revert values to defaults or reset to a known configuration.

May leave the outstation in an unknown or invalid state
TCP

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} warm-restart
Linux (sh)
./dnp3-actions tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} warm-restart
Darwin (sh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} warm-restart

Facts:

NameDescriptionTypeDefault
dnp3.server.ipIP address of the outstationstringNone
dnp3.local.linkDNP3 link layer address of the local deviceintNone
dnp3.remote.linkDNP3 link layer address of the remote deviceintNone

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
Serial

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} warm-restart
Linux (sh)
./dnp3-actions serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} warm-restart
Darwin (sh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} warm-restart

Facts:

NameDescriptionTypeDefault
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceintNone
dnp3.remote.linkDNP3 link layer address of the remote deviceintNone

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500

DNP3 - Disable Unsolicited Messages

Disable unsolicited messages on the outstation. May prevent clients connected to the outstation from receiving event data that would otherwise be self-reported by the outstation.

[Enable Unsolicited Messages](#dnp3---enable-unsolicited-messages) Ability 
TCP

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} disable-unsolicited
Linux (sh)
./dnp3-actions tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} disable-unsolicited
Darwin (sh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} disable-unsolicited

Facts:

NameDescriptionTypeDefault
dnp3.server.ipIP address of the outstationstringNone
dnp3.local.linkDNP3 link layer address of the local deviceintNone
dnp3.remote.linkDNP3 link layer address of the remote deviceintNone

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
--classesspace separated list of classes to disablestring'1,2,3'
Serial

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} disable-unsolicited
Linux (sh)
./dnp3-actions serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} disable-unsolicited
Darwin (sh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} disable-unsolicited

Facts:

NameDescriptionTypeDefault
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceintNone
dnp3.remote.linkDNP3 link layer address of the remote deviceintNone

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500
--classesspace separated list of classes to disablestring'1,2,3'

DNP3 - Enable Unsolicited Messages

Enable unsolicited messages on the outstation.

[Disable Unsolicited Messages](#dnp3---disable-unsolicited-messages) Ability 
TCP

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} enable-unsolicited
Linux (sh)
./dnp3-actions tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} enable-unsolicited
Darwin (sh)
./dnp3-actions_darwin tcp #{dnp3.server.ip} #{dnp3.local.link} #{dnp3.remote.link} enable-unsolicited

Facts:

NameDescriptionTypeDefault
dnp3.server.ipIP address of the outstationstringNone
dnp3.local.linkDNP3 link layer address of the local deviceintNone
dnp3.remote.linkDNP3 link layer address of the remote deviceintNone

Optional Flags:

FlagDescriptionTypeDefault
-p, --portport number of the outstationint20000
--classesspace separated list of classes to disablestring'1,2,3'
Serial

Ability Command:

Windows (cmd/psh)
.\dnp3-actions.exe serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} enable-unsolicited
Linux (sh)
./dnp3-actions serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} enable-unsolicited
Darwin (sh)
./dnp3-actions_darwin serial #{dnp3.server.serial_device} #{dnp3.local.link} #{dnp3.remote.link} enable-unsolicited

Facts:

NameDescriptionTypeDefault
dnp3.server.serial_deviceSerial device name (e.g. COM1, /dev/ttyS0)string
dnp3.local.linkDNP3 link layer address of the local deviceintNone
dnp3.remote.linkDNP3 link layer address of the remote deviceintNone

Optional Flags:

FlagDescriptionTypeDefault
-b,--baudbaud rate of the serial deviceint9600
--databitsdata bitsint8
--stopbitsstop bits, one of: 'One', 'OnePointFive', 'Two', 'None'string'One'
--parityparity, one of: 'Even', 'Odd', 'None'string'None'
--flowtypeflow control setting, one of 'Hardware', 'XONXOFF', 'None'string'None'
--delaydelay time in milliseconds before first txint500
--classesspace separated list of classes to disablestring'1,2,3'

DNP3 Protocol Notes

Data Model

When reading data from a DNP3 outstation, the user must specify the 'Group' and 'Variation' to read. The 'Group' can be thought of as similar to a datatype (see the table below for examples). Each Group has several 'Variations', which are different ways in which a Group can be read. For example, Group 2 is 'Binary Input Events', Variation 1 reads the data without a time value, while Variation 1 reads the data with absolute time. By default, this plugin requests all reads with variation 0, indicating no preference of read type. The optional --variation flag can be used to specify a particular variation.

GroupName
1Binary Input
2Binary Input Event
3Double-bit Binary Input
4Double-bit Binary Input Event
10Binary Output
11Binary Output Event
12Binary Command
13Binary Command Event
20Counter
21Frozen Counter
22Counter Event
23Frozen Counter Event
30Analog Input
32Analog Input Event
40Analog Output Status
41Analog Output
42Analog Output Event
43Analog Command Event
50Time and Date
51Time and Date CTO
52Time Delay
60Class Data
70File-control
80Internal Indications
110Octet String
111Octet String Event
112Virtual Terminal Output Block
113Virtual Terminal Event Data

Control Models

There are two control philosophies in DNP3 (and this plugin): select-before-operate and direct operate. Using the select-before-operate procedure, the controlling station (the Caldera payload) must first send a SELECT message, indicating the intention to operate a point. This is followed by an OPERATE message to actually execute the operation. If the outstation is set for select-before-operate mode and receives an unexpected OPERATE message (one not preceded by a SELECT message), it will ignore the command. In the direct operate mode, the preceding SELECT message is not required.

The action of an OPERATE command is defined by its control relay output block (CROB). Control abilities in this plugin contain the necessary fact templates (arguments) to build a CROB. There are three control models that a outstation may implement and the CROB must be constructed according to the appropriate model. The models are:

  • Activation model
  • Complementary latch model
  • Complementary two-output model

The activation model functions like a push-button, where a single virtual or physical output is linked to a specific event, such as "trip breaker" or "acknowledge alarm." Pressing the button triggers the associated event. These outputs are usually configured in pairs, with separate indices for actions like "trip breaker" and "close breaker." In this model, Control Relay Output Blocks (CROBs) typically use the 'PULSE_ON' operation type and the 'NUL' trip close code. Using the push-button analogy, 'PULSE_ON' represents the act of pressing the button, not the action itself. To trip a breaker, the operator sends a (NUL, PULSE_ON) CROB to the trip breaker index, and to close the breaker, a (NUL, PULSE_ON) CROB is sent to the close breaker index.

The complementary latch model operates like a light switch, where a single virtual or physical output remains in the on (active) or off (inactive) state based on the command it receives. This allows a single index to manage both on-off or enable-disable functions. This model is configured for the 'NUL' trip close code and uses 'LATCH_ON' and 'LATCH_OFF' operation types to activate or deactivate the output, respectively. It is generally used for simple controls, such as turning an indicator light on or off, rather than for controlling breakers.

The complementary two-output model consists of two virtual or physical outputs: a close and a trip output. Depending on the command received, one of these outputs is momentarily activated, allowing a breaker to be controlled from a single index. This model is configured for the 'TRIP' and 'CLOSE' trip close codes and uses the 'PULSE_ON' operation type. To trip a breaker, the operator sends a (TRIP, PULSE_ON) CROB to the breaker index, and to close the breaker, a (CLOSE, PULSE_ON) CROB is sent to the breaker index.

The CROB also contains on-time and off-time fields to set the time durations of the signal. These values are suggestions and may be overridden by the outstation.

As of September 2nd, 2022, the OpenDNP3 project was archived by the project owner. The latest and final release is 3.1.2 on April 22nd, 2022. The source may still be found on GitHub.

OpenDNP3 is (c) to Green Energy Corp (2010, 2011), Step Function I/O LLC (2013-2022, 2020-2022), and various contributors (2010-2022). Note that Automatak rebranded as Step Function I/O.

It is licensed under the terms of the Apache License 2.0, whose main condition requires "preservation of copyright and license notices."

The Caldera plugin is named "DNP3" as that is a short identifier of is purpose/scope. The plugin is not produced by Step Function I/O LLC.