summaryrefslogtreecommitdiffstats
path: root/src/app-layer-dnp3.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/app-layer-dnp3.h')
-rw-r--r--src/app-layer-dnp3.h260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/app-layer-dnp3.h b/src/app-layer-dnp3.h
new file mode 100644
index 0000000..aae07f9
--- /dev/null
+++ b/src/app-layer-dnp3.h
@@ -0,0 +1,260 @@
+/* Copyright (C) 2015 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * DNP3 application layer protocol header file
+ */
+
+#ifndef __APP_LAYER_DNP3_H__
+#define __APP_LAYER_DNP3_H__
+
+#include "rust.h"
+#if __BYTE_ORDER == __BIG_ENDIAN
+#include "util-byte.h"
+#endif
+
+/* DNP3 application request function codes. */
+#define DNP3_APP_FC_CONFIRM 0x00
+#define DNP3_APP_FC_READ 0x01
+#define DNP3_APP_FC_WRITE 0x02
+#define DNP3_APP_FC_SELECT 0x03
+#define DNP3_APP_FC_OPERATE 0x04
+#define DNP3_APP_FC_DIR_OPERATE 0x05
+#define DNP3_APP_FC_DIR_OPERATE_NR 0x06
+#define DNP3_APP_FC_FREEZE 0x07
+#define DNP3_APP_FC_FREEZE_NR 0x08
+#define DNP3_APP_FC_FREEZE_CLEAR 0x09
+#define DNP3_APP_FC_FREEZE_CLEAR_NR 0x0a
+#define DNP3_APP_FC_FREEZE_AT_TIME 0x0b
+#define DNP3_APP_FC_FREEZE_AT_TIME_NR 0x0c
+#define DNP3_APP_FC_COLD_RESTART 0x0d
+#define DNP3_APP_FC_WARM_RESTART 0x0e
+#define DNP3_APP_FC_INITIALIZE_DATA 0x0f
+#define DNP3_APP_FC_INITIALIZE_APPLICATION 0x10
+#define DNP3_APP_FC_START_APPLICATION 0x11
+#define DNP3_APP_FC_STOP_APPLICATION 0x12
+#define DNP3_APP_FC_SAVE_CONFIGURATION 0x13
+#define DNP3_APP_FC_ENABLE_UNSOLICITED 0x14
+#define DNP3_APP_FC_DISABLE_UNSOLICITED 0x15
+#define DNP3_APP_FC_ASSIGN_CLASS 0x16
+#define DNP3_APP_FC_DELAY_MEASUREMENT 0x17
+#define DNP3_APP_FC_RECORD_CURRENT_TIME 0x18
+#define DNP3_APP_FC_OPEN_TIME 0x19
+#define DNP3_APP_FC_CLOSE_FILE 0x1a
+#define DNP3_APP_FC_DELETE_FILE 0x1b
+#define DNP3_APP_FC_GET_FILE_INFO 0x1c
+#define DNP3_APP_FC_AUTHENTICATE_FILE 0x1d
+#define DNP3_APP_FC_ABORT_FILE 0x1e
+#define DNP3_APP_FC_ACTIVATE_CONFIG 0x1f
+#define DNP3_APP_FC_AUTH_REQ 0x20
+#define DNP3_APP_FC_AUTH_REQ_NR 0x21
+
+/* DNP3 application response function codes. */
+#define DNP3_APP_FC_RESPONSE 0x81
+#define DNP3_APP_FC_UNSOLICITED_RESP 0x82
+#define DNP3_APP_FC_AUTH_RESP 0x83
+
+/* Extract fields from the link control octet. */
+#define DNP3_LINK_DIR(control) (control & 0x80)
+#define DNP3_LINK_PRI(control) (control & 0x40)
+#define DNP3_LINK_FCB(control) (control & 0x20)
+#define DNP3_LINK_FCV(control) (control & 0x10)
+#define DNP3_LINK_FC(control) (control & 0x0f)
+
+/* Extract fields from transport layer header octet. */
+#define DNP3_TH_FIN(x) (x & 0x80)
+#define DNP3_TH_FIR(x) (x & 0x40)
+#define DNP3_TH_SEQ(x) (x & 0x3f)
+
+/* Extract fields from the application control octet. */
+#define DNP3_APP_FIR(x) (x & 0x80)
+#define DNP3_APP_FIN(x) (x & 0x40)
+#define DNP3_APP_CON(x) (x & 0x20)
+#define DNP3_APP_UNS(x) (x & 0x10)
+#define DNP3_APP_SEQ(x) (x & 0x0f)
+
+/* DNP3 values are stored in little endian on the wire, so swapping will be
+ * needed on big endian architectures. */
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define DNP3_SWAP16(x) SCByteSwap16(x)
+#define DNP3_SWAP32(x) SCByteSwap32(x)
+#define DNP3_SWAP64(x) SCByteSwap64(x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define DNP3_SWAP16(x) x
+#define DNP3_SWAP32(x) x
+#define DNP3_SWAP64(x) x
+#endif
+
+/* DNP3 decoder events. */
+enum {
+ DNP3_DECODER_EVENT_FLOODED = 1,
+ DNP3_DECODER_EVENT_LEN_TOO_SMALL,
+ DNP3_DECODER_EVENT_BAD_LINK_CRC,
+ DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC,
+ DNP3_DECODER_EVENT_MALFORMED,
+ DNP3_DECODER_EVENT_UNKNOWN_OBJECT,
+};
+
+/**
+ * \brief DNP3 link header.
+ */
+typedef struct DNP3LinkHeader_ {
+ uint8_t start_byte0; /**< First check byte. */
+ uint8_t start_byte1; /**< Second check byte. */
+ uint8_t len; /**< Length of PDU without CRCs. */
+ uint8_t control; /**< Control flags. */
+ uint16_t dst; /**< DNP3 destination address. */
+ uint16_t src; /**< DNP3 source address. */
+ uint16_t crc; /**< Link header CRC. */
+} __attribute__((__packed__)) DNP3LinkHeader;
+
+/**
+ * \brief DNP3 transport header.
+ */
+typedef uint8_t DNP3TransportHeader;
+
+/**
+ * \brief DNP3 application header.
+ */
+typedef struct DNP3ApplicationHeader_ {
+ uint8_t control; /**< Control flags. */
+ uint8_t function_code; /**< Application function code. */
+} __attribute__((__packed__)) DNP3ApplicationHeader;
+
+/**
+ * \brief DNP3 internal indicators.
+ *
+ * Part of the application header for responses only.
+ */
+typedef struct DNP3InternalInd_ {
+ uint8_t iin1;
+ uint8_t iin2;
+} __attribute__((__packed__)) DNP3InternalInd;
+
+/**
+ * \brief A struct used for buffering incoming data prior to reassembly.
+ */
+typedef struct DNP3Buffer_ {
+ uint8_t *buffer;
+ size_t size;
+ int len;
+ int offset;
+} DNP3Buffer;
+
+/**
+ * \brief DNP3 application object header.
+ */
+typedef struct DNP3ObjHeader_ {
+ uint8_t group;
+ uint8_t variation;
+ uint8_t qualifier;
+} __attribute__((packed)) DNP3ObjHeader;
+
+/**
+ * \brief DNP3 object point.
+ *
+ * Each DNP3 object can have 0 or more points representing the values
+ * of the object.
+ */
+typedef struct DNP3Point_ {
+ uint32_t prefix; /**< Prefix value for point. */
+ uint32_t index; /**< Index of point. If the object is prefixed
+ * with an index then this will be that
+ * value. Otherwise this is the place the point
+ * was in the list of points (starting at 0). */
+ uint32_t size; /**< Size of point if the object prefix was a
+ * size. */
+ void *data; /**< Data for this point. */
+ TAILQ_ENTRY(DNP3Point_) next;
+} DNP3Point;
+
+typedef TAILQ_HEAD(DNP3PointList_, DNP3Point_) DNP3PointList;
+
+/**
+ * \brief Struct to hold the list of decoded objects.
+ */
+typedef struct DNP3Object_ {
+ uint8_t group;
+ uint8_t variation;
+ uint8_t qualifier;
+ uint8_t prefix_code;
+ uint8_t range_code;
+ uint32_t start;
+ uint32_t stop;
+ uint32_t count;
+ DNP3PointList *points; /**< List of points for this object. */
+
+ TAILQ_ENTRY(DNP3Object_) next;
+} DNP3Object;
+
+typedef TAILQ_HEAD(DNP3ObjectList_, DNP3Object_) DNP3ObjectList;
+
+/**
+ * \brief DNP3 transaction.
+ */
+typedef struct DNP3Transaction_ {
+ AppLayerTxData tx_data;
+
+ uint64_t tx_num; /**< Internal transaction ID. */
+ bool is_request; /**< Is this tx a request? */
+
+ struct DNP3State_ *dnp3;
+
+ uint8_t *buffer; /**< Reassembled request buffer. */
+ uint32_t buffer_len;
+ DNP3ObjectList objects;
+ DNP3LinkHeader lh;
+ DNP3TransportHeader th;
+ DNP3ApplicationHeader ah;
+ DNP3InternalInd iin;
+ uint8_t done;
+ uint8_t complete; /**< Was the decode complete. It will not be
+ complete if we hit objects we do not know. */
+
+ TAILQ_ENTRY(DNP3Transaction_) next;
+} DNP3Transaction;
+
+TAILQ_HEAD(TxListHead, DNP3Transaction_);
+
+/**
+ * \brief Per flow DNP3 state.
+ */
+typedef struct DNP3State_ {
+ AppLayerStateData state_data;
+ TAILQ_HEAD(, DNP3Transaction_) tx_list;
+ DNP3Transaction *curr; /**< Current transaction. */
+ uint64_t transaction_max;
+ uint16_t events;
+ uint32_t unreplied; /**< Number of unreplied requests. */
+ uint8_t flooded; /**< Flag indicating flood. */
+
+ DNP3Buffer request_buffer; /**< Request buffer for buffering
+ * incomplete request PDUs received
+ * over TCP. */
+ DNP3Buffer response_buffer; /**< Response buffer for buffering
+ * incomplete response PDUs received
+ * over TCP. */
+
+} DNP3State;
+
+void RegisterDNP3Parsers(void);
+void DNP3ParserRegisterTests(void);
+int DNP3PrefixIsSize(uint8_t);
+
+#endif /* __APP_LAYER_DNP3_H__ */