suricata
app-layer-dnp3.c
Go to the documentation of this file.
1 /* Copyright (C) 2015-2025 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * DNP3 protocol implementation
22  */
23 
24 #include "suricata-common.h"
25 #include "suricata.h"
26 
27 #include "util-spm-bs.h"
28 #include "util-enum.h"
29 
30 #include "app-layer-protos.h"
31 #include "app-layer-parser.h"
32 #include "app-layer-detect-proto.h"
33 #include "app-layer-events.h"
34 
35 #include "app-layer-dnp3.h"
36 #include "app-layer-dnp3-objects.h"
37 #include "conf.h"
38 #include "rust.h"
39 #include "util-debug.h"
40 #include "util-validate.h"
41 
42 #define DNP3_DEFAULT_PORT "20000"
43 
44 /* Expected values for the start bytes. */
45 #define DNP3_START_BYTE0 0x05
46 #define DNP3_START_BYTE1 0x64
47 
48 /* Minimum length for a DNP3 frame. */
49 #define DNP3_MIN_LEN 5
50 
51 /* Length of each CRC. */
52 #define DNP3_CRC_LEN 2
53 
54 /* DNP3 block size. After the link header a CRC is inserted after
55  * after 16 bytes of data. */
56 #define DNP3_BLOCK_SIZE 16
57 
58 /* Maximum transport layer sequence number. */
59 #define DNP3_MAX_TRAN_SEQNO 64
60 
61 /* Maximum application layer sequence number. */
62 // unused #define DNP3_MAX_APP_SEQNO 16
63 
64 /* The number of bytes in the header that are counted as part of the
65  * header length field. */
66 #define DNP3_LINK_HDR_LEN 5
67 
68 /* Link function codes. */
69 enum {
72 };
73 
74 /* Reserved addresses. */
75 // unused #define DNP3_RESERVED_ADDR_MIN 0xfff0
76 // unused #define DNP3_RESERVED_ADDR_MAX 0xfffb
77 
78 /* Source addresses must be < 0xfff0. */
79 // unused #define DNP3_SRC_ADDR_MAX 0xfff0
80 
81 /* Extract the prefix code from the object qualifier. */
82 #define DNP3_OBJ_PREFIX(x) ((x >> 4) & 0x7)
83 
84 /* Extract the range code from the object qualifier. */
85 #define DNP3_OBJ_RANGE(x) (x & 0xf)
86 
87 /* Default number of unreplied requests to be considered a flood.
88  *
89  * DNP3 is a request/response SCADA protocol with typically only 1-2
90  * transactions in flight. But set a limit high enough to allow for
91  * some pipelining but reduce the chance of memory exhaustion
92  * attacks. */
93 static uint64_t dnp3_max_tx = 32;
94 
95 /* The maximum number of points allowed per message (configurable). */
96 static uint64_t max_points = 16384;
97 
98 /* The maximum number of objects allowed per message (configurable). */
99 static uint64_t dnp3_max_objects = 2048;
100 
101 /* Decoder event map. */
103  { "FLOODED", DNP3_DECODER_EVENT_FLOODED },
104  { "LEN_TOO_SMALL", DNP3_DECODER_EVENT_LEN_TOO_SMALL },
105  { "BAD_LINK_CRC", DNP3_DECODER_EVENT_BAD_LINK_CRC },
106  { "BAD_TRANSPORT_CRC", DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC },
107  { "MALFORMED", DNP3_DECODER_EVENT_MALFORMED },
108  { "UNKNOWN_OBJECT", DNP3_DECODER_EVENT_UNKNOWN_OBJECT },
109  { "TOO_MANY_POINTS", DNP3_DECODER_EVENT_TOO_MANY_POINTS },
110  { "TOO_MANY_OBJECTS", DNP3_DECODER_EVENT_TOO_MANY_OBJECTS },
111  { "TOO_LONG_REASSEMBLY", DNP3_DECODER_EVENT_TOO_LONG_REASS },
112  { NULL, -1 },
113 };
114 
115 /* Calculate the next transport sequence number. */
116 #define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
117 
118 /* CRC table generated by pycrc - http://github.com/tpircher/pycrc.
119  * - Polynomial: 0x3d65. */
120 static const uint16_t crc_table[256] = {
121  0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
122  0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
123  0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
124  0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
125  0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
126  0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
127  0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
128  0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
129  0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
130  0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
131  0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
132  0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
133  0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
134  0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
135  0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
136  0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
137  0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
138  0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
139  0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
140  0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
141  0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
142  0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
143  0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
144  0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
145  0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
146  0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
147  0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
148  0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
149  0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
150  0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
151  0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
152  0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
153 };
154 
155 static DNP3Transaction *DNP3TxAlloc(DNP3State *dnp3, bool request);
156 
157 /**
158  * \brief Compute the CRC for a buffer.
159  *
160  * \param buf Buffer to create CRC from.
161  * \param len Length of buffer (number of bytes to use for CRC).
162  */
163 static uint16_t DNP3ComputeCRC(const uint8_t *buf, uint32_t len)
164 {
165  const uint8_t *byte = buf;
166  uint16_t crc = 0;
167  int idx;
168 
169  while (len--) {
170  idx = (crc ^ *byte) & 0xff;
171  crc = (crc_table[idx] ^ (crc >> 8)) & 0xffff;
172  byte++;
173  }
174 
175  return ~crc & 0xffff;
176 }
177 
178 /**
179  * \brief Check the CRC of a block.
180  *
181  * \param block The block of data with CRC to be checked.
182  * \param len The size of the data block.
183  *
184  * \retval 1 if CRC is OK, otherwise 0.
185  */
186 static int DNP3CheckCRC(const uint8_t *block, uint16_t len)
187 {
188 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
189  return 1;
190 #endif
191  uint16_t crc_offset;
192  uint16_t crc;
193 
194  /* Need at least one byte plus the CRC. */
195  if (len < DNP3_CRC_LEN + 1) {
196  return 0;
197  }
198 
199  crc_offset = len - DNP3_CRC_LEN;
200  crc = DNP3ComputeCRC(block, len - DNP3_CRC_LEN);
201  if (((crc & 0xff) == block[crc_offset]) &&
202  ((crc >> 8) == block[crc_offset + 1])) {
203  return 1;
204  }
205 
206  return 0;
207 }
208 
209 /**
210  * \brief Check the CRC of the link header.
211  *
212  * \param header Point to the link header.
213  *
214  * \retval 1 if header CRC is OK, otherwise 0.
215  */
216 static int DNP3CheckLinkHeaderCRC(const DNP3LinkHeader *header)
217 {
218  return DNP3CheckCRC((uint8_t *)header, sizeof(DNP3LinkHeader));
219 }
220 
221 /**
222  * \brief Check user data CRCs.
223  *
224  * \param data Pointer to user data.
225  * \param len Length of user data.
226  *
227  * \retval 1 if CRCs are OK, otherwise 0.
228  */
229 static int DNP3CheckUserDataCRCs(const uint8_t *data, uint16_t len)
230 {
231  uint16_t offset = 0;
232  uint16_t block_size;
233 
234  while (offset < len) {
235  if (len - offset >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
236  block_size = DNP3_BLOCK_SIZE + DNP3_CRC_LEN;
237  }
238  else {
239  block_size = len - offset;
240  }
241 
242  if (!DNP3CheckCRC(data + offset, block_size)) {
243  /* Once failed, may as well return immediately. */
244  return 0;
245  }
246 
247  offset += block_size;
248  }
249 
250  return 1;
251 }
252 
253 /**
254  * \brief Check the DNP3 frame start bytes.
255  *
256  * \retval 1 if valid, 0 if not.
257  */
258 static int DNP3CheckStartBytes(const DNP3LinkHeader *header)
259 {
260  return header->start_byte0 == DNP3_START_BYTE0 &&
261  header->start_byte1 == DNP3_START_BYTE1;
262 }
263 
264 /* Some DNP3 servers start with a banner. */
265 #define DNP3_BANNER "DNP3"
266 
267 /**
268  * \brief Check if a frame contains a banner.
269  *
270  * Some servers (outstations) appear to send back a banner that fails
271  * the normal frame checks. So first check for a banner.
272  *
273  * \retval 1 if a banner is found, 0 if not.
274  */
275 static int DNP3ContainsBanner(const uint8_t *input, uint32_t len)
276 {
277  return BasicSearch(input, len, (uint8_t *)DNP3_BANNER, strlen(DNP3_BANNER)) != NULL;
278 }
279 
280 /**
281  * \brief DNP3 probing parser.
282  */
283 static uint16_t DNP3ProbingParser(
284  const Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir)
285 {
286  const DNP3LinkHeader *const hdr = (const DNP3LinkHeader *)input;
287  const bool toserver = (direction & STREAM_TOSERVER) != 0;
288 
289  /* May be a banner. */
290  if (DNP3ContainsBanner(input, len)) {
291  SCLogDebug("Packet contains a DNP3 banner.");
292  bool is_banner = true;
293  // magic 0x100 = 256 seems good enough
294  for (uint32_t i = 0; i < len && i < 0x100; i++) {
295  if (!isprint(input[i])) {
296  is_banner = false;
297  break;
298  }
299  }
300  if (is_banner) {
301  if (toserver) {
302  *rdir = STREAM_TOCLIENT;
303  }
304  return ALPROTO_DNP3;
305  }
306  }
307 
308  /* Check that we have the minimum amount of bytes. */
309  if (len < sizeof(DNP3LinkHeader)) {
310  SCLogDebug("Length too small to be a DNP3 header.");
311  return ALPROTO_UNKNOWN;
312  }
313 
314  /* Verify start value (from AN2013-004b). */
315  if (!DNP3CheckStartBytes(hdr)) {
316  SCLogDebug("Invalid start bytes.");
317  return ALPROTO_FAILED;
318  }
319 
320  /* Verify minimum length. */
321  if (hdr->len < DNP3_MIN_LEN) {
322  SCLogDebug("Packet too small to be a valid DNP3 fragment.");
323  return ALPROTO_FAILED;
324  }
325 
326  // Test compatibility between direction and dnp3.ctl.direction
327  if ((DNP3_LINK_DIR(hdr->control) != 0) != toserver) {
328  *rdir = toserver ? STREAM_TOCLIENT : STREAM_TOSERVER;
329  }
330  SCLogDebug("Detected DNP3.");
331  return ALPROTO_DNP3;
332 }
333 
334 /**
335  * \brief Calculate the length of the transport layer with CRCs removed.
336  *
337  * \param input_len The length of the transport layer buffer.
338  *
339  * \retval The length of the buffer after CRCs are removed.
340  */
341 static int DNP3CalculateTransportLengthWithoutCRCs(uint16_t input_len)
342 {
343  /* Too small. */
344  if (input_len < DNP3_CRC_LEN) {
345  return -1;
346  }
347 
348  /* Get the number of complete blocks. */
349  int blocks = input_len / (DNP3_BLOCK_SIZE + DNP3_CRC_LEN);
350 
351  /* And the number of bytes in the last block. */
352  int rem = input_len - (blocks * (DNP3_BLOCK_SIZE + DNP3_CRC_LEN));
353 
354  if (rem) {
355  if (rem < DNP3_CRC_LEN) {
356  return -1;
357  }
358  return (blocks * DNP3_BLOCK_SIZE) + (rem - DNP3_CRC_LEN);
359  }
360  else {
361  return (blocks * DNP3_BLOCK_SIZE);
362  }
363 }
364 
365 /**
366  * \brief Reassemble the application layer by stripping the CRCs.
367  *
368  * Remove the CRCs from the user data blocks. The output is the user
369  * data with the CRCs removed as well as the transport header removed,
370  * but the input data still needs to include the transport header as
371  * its part of the first user data block.
372  *
373  * If the output length passed in is non-null, the new input data will
374  * be appended, and the output length pointer incremented as needed.
375  *
376  * \param input Input buffer starting at the transport header (which
377  * will be removed from the output).
378  * \param input_len Length of the input buffer.
379  * \param output Pointer to output buffer (may be realloc'd).
380  * \param output_len Pointer to output length.
381  *
382  * \retval 1 if reassembly was successful, otherwise 0.
383  */
384 static int DNP3ReassembleApplicationLayer(
385  const uint8_t *input, uint16_t input_len, uint8_t **output, uint16_t *output_len)
386 {
387  int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
388 
389  if (len <= 0) {
390  return 0;
391  }
392 
393  /* Remove one byte for the transport header and make sure we have
394  * at least one byte of user data. */
395  if (--len < 1) {
396  return 0;
397  }
398 
399  if (*output == NULL) {
400  *output = SCCalloc(1, len);
401  if (unlikely(*output == NULL)) {
402  return 0;
403  }
404  }
405  else {
406  uint8_t *ptr = SCRealloc(*output, (size_t)(*output_len + len));
407  if (unlikely(ptr == NULL)) {
408  return 0;
409  }
410  *output = ptr;
411  }
412 
413  uint16_t offset = 0, block_size;
414  while (offset < input_len) {
415  if (input_len - offset > DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
416  block_size = DNP3_BLOCK_SIZE + DNP3_CRC_LEN;
417  }
418  else {
419  block_size = input_len - offset;
420  }
421 
422  /* If handling the first block (offset is 0), trim off the
423  * first byte which is the transport header, and not part of
424  * the application data. */
425  if (offset == 0) {
426  offset++;
427  block_size--;
428  }
429 
430  /* Need at least 3 bytes to continue. One for application
431  * data, and 2 for the CRC. If not, return failure for
432  * malformed frame. */
433  if (block_size < DNP3_CRC_LEN + 1) {
434  SCLogDebug("Not enough data to continue.");
435  return 0;
436  }
437 
438  /* Make sure there is enough space to write into. */
439  if (block_size - DNP3_CRC_LEN > len) {
440  SCLogDebug("Not enough data to continue.");
441  return 0;
442  }
443 
444  memcpy(*output + *output_len, input + offset,
445  block_size - DNP3_CRC_LEN);
446  *output_len += block_size - DNP3_CRC_LEN;
447  offset += block_size;
448  len -= block_size - DNP3_CRC_LEN;
449  }
450 
451  return 1;
452 }
453 
454 /**
455  * \brief Allocate a DNP3 state object.
456  *
457  * The DNP3 state object represents a single DNP3 TCP session.
458  */
459 static void *DNP3StateAlloc(void *orig_state, AppProto proto_orig)
460 {
461  SCEnter();
462  DNP3State *dnp3;
463 
464  dnp3 = (DNP3State *)SCCalloc(1, sizeof(DNP3State));
465  if (unlikely(dnp3 == NULL)) {
466  return NULL;
467  }
468  TAILQ_INIT(&dnp3->tx_list);
469 
470  SCReturnPtr(dnp3, "void");
471 }
472 
473 /**
474  * \brief Set a DNP3 application layer event on a transaction.
475  */
476 static void DNP3SetEventTx(DNP3Transaction *tx, uint8_t event)
477 {
479  tx->dnp3->events++;
480 }
481 
482 /**
483  * \brief Set a DNP3 application layer event.
484  *
485  * Sets an event on the current transaction object, allocating an event carrier
486  * transaction if necessary.
487  */
488 static void DNP3SetEvent(DNP3State *dnp3, bool request, uint8_t event)
489 {
490  if (dnp3 != NULL && dnp3->curr == NULL) {
491  DNP3Transaction *tx = DNP3TxAlloc(dnp3, request);
492  if (tx != NULL) {
493  tx->done = 1;
494  }
495  }
496  if (dnp3 && dnp3->curr) {
497  DNP3SetEventTx(dnp3->curr, event);
498  }
499  else {
500  SCLogWarning("Failed to set event, state or tx pointer was NULL.");
501  }
502 }
503 
504 /**
505  * \brief Allocation a DNP3 transaction.
506  */
507 static DNP3Transaction *DNP3TxAlloc(DNP3State *dnp3, bool request)
508 {
509  DNP3Transaction *tx = SCCalloc(1, sizeof(DNP3Transaction));
510  if (unlikely(tx == NULL)) {
511  return NULL;
512  }
513  dnp3->transaction_max++;
514  dnp3->unreplied++;
515  dnp3->curr = tx;
516  tx->dnp3 = dnp3;
517  tx->tx_num = dnp3->transaction_max;
518  tx->is_request = request;
519  if (tx->is_request) {
520  tx->tx_data.flags = APP_LAYER_TX_SKIP_INSPECT_TC;
521  } else {
522  tx->tx_data.flags = APP_LAYER_TX_SKIP_INSPECT_TS;
523  }
524  TAILQ_INIT(&tx->objects);
525  TAILQ_INSERT_TAIL(&dnp3->tx_list, tx, next);
526 
527  /* Check for flood state. */
528  if (dnp3->unreplied > dnp3_max_tx && !dnp3->flooded) {
529  DNP3SetEvent(dnp3, request, DNP3_DECODER_EVENT_FLOODED);
530  dnp3->flooded = 1;
531  }
532 
533  return tx;
534 }
535 
536 /**
537  * \brief Calculate the length of a link frame with CRCs.
538  *
539  * This is required as the length parameter in the DNP3 header does not
540  * include the added CRCs.
541  *
542  * \param length The length from the DNP3 link header.
543  *
544  * \retval The length of the frame with CRCs included or 0 if the length isn't
545  * long enough to be a valid DNP3 frame.
546  */
547 static uint16_t DNP3CalculateLinkLength(uint8_t length)
548 {
549  uint16_t frame_len = 0;
550  int rem;
551 
552  /* Fail early if the length is less than the minimum size. */
553  if (length < DNP3_LINK_HDR_LEN) {
554  return 0;
555  }
556 
557  /* Subtract the 5 bytes of the header that are included in the
558  * length. */
560 
561  rem = length % DNP3_BLOCK_SIZE;
562  frame_len = (length / DNP3_BLOCK_SIZE) * (DNP3_BLOCK_SIZE + DNP3_CRC_LEN);
563  if (rem) {
564  frame_len += rem + DNP3_CRC_LEN;
565  }
566 
567  return frame_len + sizeof(DNP3LinkHeader);
568 }
569 
570 /**
571  * \brief Check if the link function code specifies user data.
572  *
573  * \param header Point to link header.
574  *
575  * \retval 1 if frame contains user data, otherwise 0.
576  */
577 static int DNP3IsUserData(const DNP3LinkHeader *header)
578 {
579  switch (DNP3_LINK_FC(header->control)) {
582  return 1;
583  default:
584  return 0;
585  }
586 }
587 
588 /**
589  * \brief Check if the frame has user data.
590  *
591  * Check if the DNP3 frame actually has user data by checking if data
592  * exists after the headers.
593  *
594  * \retval 1 if user data exists, otherwise 0.
595  */
596 static int DNP3HasUserData(const DNP3LinkHeader *header, uint8_t direction)
597 {
598  if (direction == STREAM_TOSERVER) {
599  return header->len >= DNP3_LINK_HDR_LEN + sizeof(DNP3TransportHeader) +
600  sizeof(DNP3ApplicationHeader);
601  }
602  else {
603  return header->len >= DNP3_LINK_HDR_LEN + sizeof(DNP3TransportHeader) +
604  sizeof(DNP3ApplicationHeader) + sizeof(DNP3InternalInd);
605  }
606 }
607 
608 /**
609  * \brief Advance past invalid input to the next possible DNP3 frame.
610  */
611 static void DNP3Resync(const uint8_t **input, uint32_t *input_len, uint32_t *processed)
612 {
613  uint32_t skip = 1;
614 
615  while (skip + 1 < *input_len) {
616  if ((*input)[skip] == DNP3_START_BYTE0 && (*input)[skip + 1] == DNP3_START_BYTE1) {
617  break;
618  }
619  skip++;
620  }
621 
622  /* Consume the final byte unless the next TCP slice could complete its start marker. */
623  if (skip < *input_len && (*input)[skip] != DNP3_START_BYTE0) {
624  skip++;
625  }
626 
627  *input += skip;
628  *input_len -= skip;
629  *processed += skip;
630 }
631 
632 /**
633  * \brief Reset a DNP3Buffer.
634  */
635 static void DNP3BufferReset(DNP3Buffer *buffer)
636 {
637  buffer->offset = 0;
638  buffer->len = 0;
639 }
640 
641 /**
642  * \brief Add data to a DNP3 buffer, enlarging the buffer if required.
643  *
644  * \param buffer Buffer to add data data.
645  * \param data Data to be added to buffer.
646  * \param len Size of data to be added to buffer.
647  *
648  * \param 1 if data was added successful, otherwise 0.
649  */
650 static int DNP3BufferAdd(DNP3Buffer *buffer, const uint8_t *data, uint32_t len)
651 {
652  if (buffer->size == 0) {
653  buffer->buffer = SCCalloc(1, len);
654  if (unlikely(buffer->buffer == NULL)) {
655  return 0;
656  }
657  buffer->size = len;
658  }
659  else if (buffer->len + len > buffer->size) {
660  uint8_t *tmp = SCRealloc(buffer->buffer, buffer->len + len);
661  if (unlikely(tmp == NULL)) {
662  return 0;
663  }
664  buffer->buffer = tmp;
665  buffer->size = buffer->len + len;
666  }
667  memcpy(buffer->buffer + buffer->len, data, len);
668  buffer->len += len;
669 
670  return 1;
671 }
672 
673 /**
674  * \brief Trim a DNP3 buffer.
675  *
676  * Trimming a buffer moves the data in the buffer up to the front of
677  * the buffer freeing up room at the end for more incoming data.
678  *
679  * \param buffer The buffer to trim.
680  */
681 static void DNP3BufferTrim(DNP3Buffer *buffer)
682 {
683  if (buffer->offset == buffer->len) {
684  DNP3BufferReset(buffer);
685  }
686  else if (buffer->offset > 0) {
687  SCMemmove(buffer->buffer, buffer->size, buffer->buffer + buffer->offset,
688  buffer->len - buffer->offset);
689  buffer->len = buffer->len - buffer->offset;
690  buffer->offset = 0;
691  }
692 }
693 
694 /**
695  * \brief Free a DNP3 object.
696  */
697 static void DNP3ObjectFree(DNP3Object *object)
698 {
699  if (object->points != NULL) {
700  DNP3FreeObjectPointList(object->group, object->variation,
701  object->points);
702  }
703  SCFree(object);
704 }
705 
706 /**
707  * \brief Allocate a DNP3 object.
708  */
709 static DNP3Object *DNP3ObjectAlloc(void)
710 {
711  DNP3Object *object = SCCalloc(1, sizeof(*object));
712  if (unlikely(object == NULL)) {
713  return NULL;
714  }
715  object->points = DNP3PointListAlloc();
716  if (object->points == NULL) {
717  DNP3ObjectFree(object);
718  return NULL;
719  }
720  return object;
721 }
722 
723 /**
724  * \brief Decode DNP3 application objects.
725  *
726  * This function decoded known DNP3 application objects. As the
727  * protocol isn't self describing, we can only decode the buffer while
728  * the application objects are known. As soon as an unknown
729  * group/variation is hit, we must stop processing.
730  *
731  * \param buf the input buffer
732  * \param len length of the input buffer
733  * \param objects pointer to list where decoded objects will be stored.
734  *
735  * \retval 1 if all objects decoded, 0 if all objects could not be decoded (
736  * unknown group/variations)
737  */
738 static int DNP3DecodeApplicationObjects(
739  DNP3Transaction *tx, const uint8_t *buf, uint16_t len, DNP3ObjectList *objects)
740 {
741  int retval = 0;
742  uint64_t point_count = 0;
743  uint64_t object_count = 0;
744 
745  if (buf == NULL || len == 0) {
746  return 1;
747  }
748 
749  while (len) {
750  uint16_t offset = 0;
751 
752  if (len < sizeof(DNP3ObjHeader)) {
753  goto done;
754  }
755  DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
756  offset += sizeof(DNP3ObjHeader);
757 
758  /* Check if we've exceeded the maximum number of objects. */
759  if (++object_count > dnp3_max_objects) {
760  DNP3SetEventTx(tx, DNP3_DECODER_EVENT_TOO_MANY_OBJECTS);
761  goto done;
762  }
763 
764  DNP3Object *object = DNP3ObjectAlloc();
765  if (unlikely(object == NULL)) {
766  goto done;
767  }
768  TAILQ_INSERT_TAIL(objects, object, next);
769 
770  object->group = header->group;
771  object->variation = header->variation;
772  object->qualifier = header->qualifier;
773  object->prefix_code = DNP3_OBJ_PREFIX(header->qualifier);
774  object->range_code = DNP3_OBJ_RANGE(header->qualifier);
775 
776  /* IEEE 1815-2012, Table 4-5. */
777  switch (object->range_code) {
778  case 0x00:
779  case 0x03: {
780  /* 1 octet start and stop indexes OR 1 octet start and
781  * stop virtual addresses. */
782  if (offset + (sizeof(uint8_t) * 2) > len) {
783  /* Not enough data. */
784  SCLogDebug("Not enough data.");
785  goto not_enough_data;
786  }
787  object->start = buf[offset++];
788  object->stop = buf[offset++];
789  object->count = object->stop - object->start + 1;
790  break;
791  }
792  case 0x01:
793  case 0x04: {
794  /* 2 octet start and stop indexes OR 2 octect start
795  * and stop virtual addresses. */
796  if (offset + (sizeof(uint16_t) * 2) > len) {
797  /* Not enough data. */
798  SCLogDebug("Not enough data.");
799  goto not_enough_data;
800  }
801  object->start = DNP3_SWAP16(*(uint16_t *)(buf + offset));
802  offset += sizeof(uint16_t);
803  object->stop = DNP3_SWAP16(*(uint16_t *)(buf + offset));
804  offset += sizeof(uint16_t);
805  object->count = object->stop - object->start + 1;
806  break;
807  }
808  case 0x02:
809  case 0x05: {
810  /* 4 octet start and stop indexes OR 4 octect start
811  * and stop virtual addresses. */
812  if (offset + (sizeof(uint32_t) * 2) > len) {
813  /* Not enough data. */
814  SCLogDebug("Not enough data.");
815  goto not_enough_data;
816  }
817  object->start = DNP3_SWAP32(*(uint32_t *)(buf + offset));
818  offset += sizeof(uint32_t);
819  object->stop = DNP3_SWAP32(*(uint32_t *)(buf + offset));
820  offset += sizeof(uint32_t);
821  object->count = object->stop - object->start + 1;
822  break;
823  }
824  case 0x06:
825  /* No range field. */
826  object->count = 0;
827  break;
828  case 0x07:
829  /* 1 octet count of objects. */
830  if (offset + sizeof(uint8_t) > len) {
831  SCLogDebug("Not enough data.");
832  goto not_enough_data;
833  }
834  object->count = buf[offset];
835  offset += sizeof(uint8_t);
836  break;
837  case 0x08: {
838  /* 2 octet count of objects. */
839  if (offset + sizeof(uint16_t) > len) {
840  SCLogDebug("Not enough data.");
841  goto not_enough_data;
842  }
843  object->count = DNP3_SWAP16(*(uint16_t *)(buf + offset));
844  offset += sizeof(uint16_t);
845  break;
846  }
847  case 0x09: {
848  /* 4 octet count of objects. */
849  if (offset + sizeof(uint32_t) > len) {
850  SCLogDebug("Not enough data.");
851  goto not_enough_data;
852  }
853  object->count = DNP3_SWAP32(*(uint32_t *)(buf + offset));
854  offset += sizeof(uint32_t);
855  break;
856  }
857  case 0x0b: {
858  if (offset + sizeof(uint8_t) > len) {
859  /* Not enough data. */
860  SCLogDebug("Not enough data.");
861  goto not_enough_data;
862  }
863  object->count = *(uint8_t *)(buf + offset);
864  offset += sizeof(uint8_t);
865  break;
866  }
867  default:
868  SCLogDebug("Range code 0x%02x is reserved.",
869  object->range_code);
870  goto done;
871  }
872 
873  buf += offset;
874  len -= offset;
875 
876  if (object->variation == 0 || object->count == 0) {
877  goto next;
878  }
879 
880  /* Check if we've exceeded the maximum number of points per message. */
881  point_count += object->count;
882  if (point_count > max_points) {
883  DNP3SetEventTx(tx, DNP3_DECODER_EVENT_TOO_MANY_POINTS);
884  goto done;
885  }
886 
887  int event = DNP3DecodeObject(header->group, header->variation, &buf,
888  &len, object->prefix_code, object->start, object->count,
889  object->points);
890  if (event) {
891  DNP3SetEventTx(tx, DNP3_DECODER_EVENT_UNKNOWN_OBJECT);
892  goto done;
893  }
894 
895  next:
896  continue;
897  }
898 
899  /* All objects were decoded. */
900  retval = 1;
901 
902 not_enough_data:
903 done:
904  return retval;
905 }
906 
907 /**
908  * \brief Handle DNP3 request user data.
909  *
910  * \param dnp3 the current DNP3State
911  * \param input pointer to the DNP3 frame (starting with link header)
912  * \param input_len length of the input frame
913  */
914 static void DNP3HandleUserDataRequest(
915  Flow *f, DNP3State *dnp3, const uint8_t *input, uint16_t input_len)
916 {
917  DNP3LinkHeader *lh;
919  DNP3ApplicationHeader *ah;
920  DNP3Transaction *tx = NULL, *ttx;
921 
922  lh = (DNP3LinkHeader *)input;
923 
924  if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
925  input_len - sizeof(DNP3LinkHeader))) {
926  return;
927  }
928 
929  th = input[sizeof(DNP3LinkHeader)];
930 
931  if (!DNP3_TH_FIR(th)) {
932  TAILQ_FOREACH(ttx, &dnp3->tx_list, next) {
933  if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
934  NEXT_TH_SEQNO(DNP3_TH_SEQ(ttx->th)) == DNP3_TH_SEQ(th)) {
935  tx = ttx;
936  break;
937  }
938  }
939 
940  if (tx == NULL) {
941  return;
942  }
943 
944  /* Update the saved transport header so subsequent segments
945  * will be matched to this sequence number. */
946  tx->th = th;
947  tx->tx_data.updated_ts = true;
948  }
949  else {
950  ah = (DNP3ApplicationHeader *)(input + sizeof(DNP3LinkHeader) +
951  sizeof(DNP3TransportHeader));
952 
953  /* Ignore confirms - for now. */
954  if (ah->function_code == DNP3_APP_FC_CONFIRM) {
955  return;
956  }
957 
958  /* Create a transaction. */
959  tx = DNP3TxAlloc(dnp3, true);
960  if (unlikely(tx == NULL)) {
961  return;
962  }
963  tx->tx_data.updated_ts = true;
964  tx->lh = *lh;
965  tx->th = th;
966  tx->ah = *ah;
967  }
968 
969  if (!DNP3ReassembleApplicationLayer(input + sizeof(DNP3LinkHeader),
970  input_len - sizeof(DNP3LinkHeader), &tx->buffer, &tx->buffer_len)) {
971 
972  /* Malformed, set event and mark as done. */
973  DNP3SetEvent(dnp3, true, DNP3_DECODER_EVENT_MALFORMED);
974  tx->done = 1;
975  return;
976  }
977  // a data link frame has its size on one byte,
978  // and transport layer has sequence in 0-63
979  if (tx->buffer_len > 63 * 0xff) {
980  DNP3SetEvent(dnp3, true, DNP3_DECODER_EVENT_TOO_LONG_REASS);
981  tx->done = 1;
982  return;
983  }
984 
985  /* If this is not the final segment, just return. */
986  if (!DNP3_TH_FIN(th)) {
987  return;
988  }
989 
990  tx->done = 1;
991 
992  if (DNP3DecodeApplicationObjects(tx, tx->buffer + sizeof(DNP3ApplicationHeader),
993  tx->buffer_len - sizeof(DNP3ApplicationHeader), &tx->objects)) {
994  tx->complete = 1;
995  }
996  if (f != NULL) {
998  }
999 }
1000 
1001 static void DNP3HandleUserDataResponse(
1002  Flow *f, DNP3State *dnp3, const uint8_t *input, uint16_t input_len)
1003 {
1004  DNP3LinkHeader *lh;
1006  DNP3ApplicationHeader *ah;
1007  DNP3InternalInd *iin;
1008  DNP3Transaction *tx = NULL, *ttx;
1009  uint16_t offset = 0;
1010 
1011  lh = (DNP3LinkHeader *)input;
1012  offset += sizeof(DNP3LinkHeader);
1013 
1014  if (!DNP3CheckUserDataCRCs(input + offset, input_len - offset)) {
1015  return;
1016  }
1017 
1018  th = input[offset++];
1019 
1020  if (!DNP3_TH_FIR(th)) {
1021  TAILQ_FOREACH(ttx, &dnp3->tx_list, next) {
1022  if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
1023  !ttx->done && NEXT_TH_SEQNO(DNP3_TH_SEQ(ttx->th)) == DNP3_TH_SEQ(th)) {
1024  tx = ttx;
1025  break;
1026  }
1027  }
1028 
1029  if (tx == NULL) {
1030  return;
1031  }
1032 
1033  /* Replace the transport header in the transaction with this
1034  * one in case there are more frames. */
1035  tx->th = th;
1036  tx->tx_data.updated_tc = true;
1037  }
1038  else {
1039  ah = (DNP3ApplicationHeader *)(input + offset);
1040  offset += sizeof(DNP3ApplicationHeader);
1041  iin = (DNP3InternalInd *)(input + offset);
1042 
1043  tx = DNP3TxAlloc(dnp3, false);
1044  if (unlikely(tx == NULL)) {
1045  return;
1046  }
1047  tx->tx_data.updated_tc = true;
1048  tx->lh = *lh;
1049  tx->th = th;
1050  tx->ah = *ah;
1051  tx->iin = *iin;
1052  }
1053 
1055 
1056  if (!DNP3ReassembleApplicationLayer(input + sizeof(DNP3LinkHeader),
1057  input_len - sizeof(DNP3LinkHeader), &tx->buffer, &tx->buffer_len)) {
1058  DNP3SetEvent(dnp3, false, DNP3_DECODER_EVENT_MALFORMED);
1059  return;
1060  }
1061  // a data link frame has its size on one byte,
1062  // and transport layer has sequence in 0-63
1063  if (tx->buffer_len > 63 * 0xff) {
1064  DNP3SetEvent(dnp3, false, DNP3_DECODER_EVENT_TOO_LONG_REASS);
1065  tx->done = 1;
1066  return;
1067  }
1068 
1069  if (!DNP3_TH_FIN(th)) {
1070  return;
1071  }
1072 
1073  tx->done = 1;
1074 
1075  offset = sizeof(DNP3ApplicationHeader) + sizeof(DNP3InternalInd);
1076  if (DNP3DecodeApplicationObjects(
1077  tx, tx->buffer + offset, tx->buffer_len - offset, &tx->objects)) {
1078  tx->complete = 1;
1079  }
1080  if (f != NULL) {
1082  }
1083 }
1084 
1085 /**
1086  * \brief Decode the DNP3 request link layer.
1087  *
1088  * \retval number of bytes processed or -1 if the data stream does not look
1089  * like DNP3.
1090  */
1091 static int DNP3HandleRequestLinkLayer(
1092  Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
1093 {
1094  SCEnter();
1095  uint32_t processed = 0;
1096 
1097  while (input_len) {
1098 
1099  /* Need at least enough bytes for a DNP3 header. */
1100  if (input_len < sizeof(DNP3LinkHeader)) {
1101  break;
1102  }
1103 
1104  DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1105 
1106  if (!DNP3CheckStartBytes(header)) {
1107  /* Terminal error condition. */
1108  SCReturnInt(-1);
1109  }
1110 
1111  if (!DNP3CheckLinkHeaderCRC(header)) {
1112  DNP3SetEvent(dnp3, true, DNP3_DECODER_EVENT_BAD_LINK_CRC);
1113  DNP3Resync(&input, &input_len, &processed);
1114  continue;
1115  }
1116 
1117  uint16_t frame_len = DNP3CalculateLinkLength(header->len);
1118  if (frame_len == 0) {
1119  DNP3SetEvent(dnp3, true, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1120  DNP3Resync(&input, &input_len, &processed);
1121  continue;
1122  }
1123  if (input_len < frame_len) {
1124  /* Insufficient data, just break - will wait for more data. */
1125  break;
1126  }
1127 
1128  /* Ignore non-user data for now. */
1129  if (!DNP3IsUserData(header)) {
1130  goto next;
1131  }
1132 
1133  /* Make sure the header length is large enough for transport and
1134  * application headers. */
1135  if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1136  DNP3SetEvent(dnp3, true, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1137  goto next;
1138  }
1139 
1140  if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
1141  frame_len - sizeof(DNP3LinkHeader))) {
1142  DNP3SetEvent(dnp3, true, DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC);
1143  goto next;
1144  }
1145 
1146  DNP3HandleUserDataRequest(f, dnp3, input, frame_len);
1147 
1148  next:
1149  /* Advance the input buffer. */
1150  input += frame_len;
1151  input_len -= frame_len;
1152  processed += frame_len;
1153  }
1154 
1155  SCReturnInt(processed);
1156 }
1157 
1158 /**
1159  * \brief Handle incoming request data.
1160  *
1161  * The actual request PDU parsing is done in
1162  * DNP3HandleRequestLinkLayer. This function takes care of buffering TCP
1163  * date if a segment does not contain a complete frame (or contains
1164  * multiple frames, but not the complete final frame).
1165  */
1166 static AppLayerResult DNP3ParseRequest(Flow *f, void *state, AppLayerParserState *pstate,
1167  StreamSlice stream_slice, void *local_data)
1168 {
1169  SCEnter();
1170  DNP3State *dnp3 = (DNP3State *)state;
1171  DNP3Buffer *buffer = &dnp3->request_buffer;
1172  int processed = 0;
1173 
1174  const uint8_t *input = StreamSliceGetData(&stream_slice);
1175  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1176 
1177  if (input_len == 0) {
1179  }
1180 
1181  if (buffer->len) {
1182  if (!DNP3BufferAdd(buffer, input, input_len)) {
1183  goto error;
1184  }
1185  processed = DNP3HandleRequestLinkLayer(
1186  f, dnp3, buffer->buffer + buffer->offset, buffer->len - buffer->offset);
1187  if (processed < 0) {
1188  goto error;
1189  }
1190  buffer->offset += processed;
1191  DNP3BufferTrim(buffer);
1192  }
1193  else {
1194  processed = DNP3HandleRequestLinkLayer(f, dnp3, input, input_len);
1195  if (processed < 0) {
1196  SCLogDebug("Failed to process request link layer.");
1197  goto error;
1198  }
1199 
1200  input += processed;
1201  input_len -= processed;
1202 
1203  /* Not all data was processed, buffer it. */
1204  if (input_len) {
1205  if (!DNP3BufferAdd(buffer, input, input_len)) {
1206  goto error;
1207  }
1208  }
1209  }
1210 
1212 
1213 error:
1214  /* Reset the buffer. */
1215  DNP3BufferReset(buffer);
1217 }
1218 
1219 /**
1220  * \brief Decode the DNP3 response link layer.
1221  *
1222  * \retval number of bytes processed or -1 if the data stream does not
1223  * like look DNP3.
1224  */
1225 static int DNP3HandleResponseLinkLayer(
1226  Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
1227 {
1228  SCEnter();
1229  uint32_t processed = 0;
1230 
1231  while (input_len) {
1232 
1233  /* Need at least enough bytes for a DNP3 header. */
1234  if (input_len < sizeof(DNP3LinkHeader)) {
1235  break;
1236  }
1237 
1238  DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1239 
1240  if (!DNP3CheckStartBytes(header)) {
1241  /* Terminal error condition. */
1242  SCReturnInt(-1);
1243  }
1244 
1245  if (!DNP3CheckLinkHeaderCRC(header)) {
1246  DNP3SetEvent(dnp3, false, DNP3_DECODER_EVENT_BAD_LINK_CRC);
1247  DNP3Resync(&input, &input_len, &processed);
1248  continue;
1249  }
1250 
1251  /* Calculate the number of bytes needed to for this frame. */
1252  uint16_t frame_len = DNP3CalculateLinkLength(header->len);
1253  if (frame_len == 0) {
1254  DNP3SetEvent(dnp3, false, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1255  DNP3Resync(&input, &input_len, &processed);
1256  continue;
1257  }
1258  if (input_len < frame_len) {
1259  /* Insufficient data, just break - will wait for more data. */
1260  break;
1261  }
1262 
1263  /* Only handle user data frames for now. */
1264  if (!DNP3IsUserData(header)) {
1265  goto next;
1266  }
1267 
1268  /* Make sure the header length is large enough for transport and
1269  * application headers. */
1270  if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1271  DNP3SetEvent(dnp3, false, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1272  goto next;
1273  }
1274 
1275  if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
1276  frame_len - sizeof(DNP3LinkHeader))) {
1277  DNP3SetEvent(dnp3, false, DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC);
1278  goto next;
1279  }
1280 
1281  DNP3HandleUserDataResponse(f, dnp3, input, frame_len);
1282 
1283  next:
1284  /* Advance the input buffer. */
1285  input += frame_len;
1286  input_len -= frame_len;
1287  processed += frame_len;
1288  }
1289 
1290  SCReturnInt(processed);
1291 }
1292 
1293 /**
1294  * \brief Parse incoming data.
1295  *
1296  * This is the entry function for DNP3 application layer data. Its
1297  * main responsibility is buffering incoming data that cannot be
1298  * processed.
1299  *
1300  * See DNP3ParseResponsePDUs for DNP3 frame handling.
1301  */
1302 static AppLayerResult DNP3ParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
1303  StreamSlice stream_slice, void *local_data)
1304 {
1305  SCEnter();
1306 
1307  DNP3State *dnp3 = (DNP3State *)state;
1308  DNP3Buffer *buffer = &dnp3->response_buffer;
1309  int processed;
1310 
1311  const uint8_t *input = StreamSliceGetData(&stream_slice);
1312  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1313 
1314  if (buffer->len) {
1315  if (!DNP3BufferAdd(buffer, input, input_len)) {
1316  goto error;
1317  }
1318  processed = DNP3HandleResponseLinkLayer(
1319  f, dnp3, buffer->buffer + buffer->offset, buffer->len - buffer->offset);
1320  if (processed < 0) {
1321  goto error;
1322  }
1323  buffer->offset += processed;
1324  DNP3BufferTrim(buffer);
1325  }
1326  else {
1327 
1328  /* Check if this is a banner, ignore if it is. */
1329  if (DNP3ContainsBanner(input, input_len)) {
1330  goto done;
1331  }
1332 
1333  processed = DNP3HandleResponseLinkLayer(f, dnp3, input, input_len);
1334  if (processed < 0) {
1335  goto error;
1336  }
1337  input += processed;
1338  input_len -= processed;
1339 
1340  /* Not all data was processed, buffer it. */
1341  if (input_len) {
1342  if (!DNP3BufferAdd(buffer, input, input_len)) {
1343  goto error;
1344  }
1345  }
1346  }
1347 
1348 done:
1350 
1351 error:
1352  /* An error occurred while processing DNP3 frames. Dump the
1353  * buffer as we can't be assured that they are valid anymore. */
1354  DNP3BufferReset(buffer);
1356 }
1357 
1358 static void *DNP3GetTx(void *alstate, uint64_t tx_id)
1359 {
1360  SCEnter();
1361  DNP3State *dnp3 = (DNP3State *)alstate;
1362  DNP3Transaction *tx = NULL;
1363  uint64_t tx_num = tx_id + 1;
1364 
1365  if (dnp3->curr && dnp3->curr->tx_num == (tx_num)) {
1366  SCReturnPtr(dnp3->curr, "void");
1367  }
1368 
1369  TAILQ_FOREACH(tx, &dnp3->tx_list, next) {
1370  if (tx_num != tx->tx_num) {
1371  continue;
1372  }
1373  SCReturnPtr(tx, "void");
1374  }
1375 
1376  SCReturnPtr(NULL, "void");
1377 }
1378 
1379 static uint64_t DNP3GetTxCnt(void *state)
1380 {
1381  SCEnter();
1382  uint64_t count = ((uint64_t)((DNP3State *)state)->transaction_max);
1383  SCReturnUInt(count);
1384 }
1385 
1386 /**
1387  * \brief Free all the objects in a DNP3ObjectList.
1388  */
1389 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1390 {
1391  DNP3Object *object;
1392 
1393  while ((object = TAILQ_FIRST(objects)) != NULL) {
1394  TAILQ_REMOVE(objects, object, next);
1395  DNP3ObjectFree(object);
1396  }
1397 }
1398 
1399 /**
1400  * \brief Free a DNP3 transaction.
1401  */
1402 static void DNP3TxFree(DNP3Transaction *tx)
1403 {
1404  SCEnter();
1405 
1406  if (tx->buffer != NULL) {
1407  SCFree(tx->buffer);
1408  }
1409 
1411 
1412  DNP3TxFreeObjectList(&tx->objects);
1413 
1414  SCFree(tx);
1415  SCReturn;
1416 }
1417 
1418 /**
1419  * \brief Free a transaction by ID on a specific DNP3 state.
1420  *
1421  * This function is called by the app-layer to free a transaction on a
1422  * specific DNP3 state object.
1423  */
1424 static void DNP3StateTxFree(void *state, uint64_t tx_id)
1425 {
1426  SCEnter();
1427  DNP3State *dnp3 = state;
1428  DNP3Transaction *tx = NULL, *ttx;
1429  uint64_t tx_num = tx_id + 1;
1430 
1431  TAILQ_FOREACH_SAFE(tx, &dnp3->tx_list, next, ttx) {
1432 
1433  if (tx->tx_num != tx_num) {
1434  continue;
1435  }
1436 
1437  if (tx == dnp3->curr) {
1438  dnp3->curr = NULL;
1439  }
1440 
1441  if (tx->tx_data.events != NULL) {
1442  if (tx->tx_data.events->cnt <= dnp3->events) {
1443  dnp3->events -= tx->tx_data.events->cnt;
1444  } else {
1445  dnp3->events = 0;
1446  }
1447  }
1448  dnp3->unreplied--;
1449 
1450  /* Check flood state. */
1451  if (dnp3->flooded && dnp3->unreplied < dnp3_max_tx) {
1452  dnp3->flooded = 0;
1453  }
1454 
1455  TAILQ_REMOVE(&dnp3->tx_list, tx, next);
1456  DNP3TxFree(tx);
1457  break;
1458  }
1459 
1460  SCReturn;
1461 }
1462 
1463 /**
1464  * \brief Free a DNP3 state.
1465  */
1466 static void DNP3StateFree(void *state)
1467 {
1468  SCEnter();
1469  DNP3State *dnp3 = state;
1470  DNP3Transaction *tx;
1471  if (state != NULL) {
1472  while ((tx = TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1473  TAILQ_REMOVE(&dnp3->tx_list, tx, next);
1474  DNP3TxFree(tx);
1475  }
1476  if (dnp3->request_buffer.buffer != NULL) {
1477  SCFree(dnp3->request_buffer.buffer);
1478  }
1479  if (dnp3->response_buffer.buffer != NULL) {
1480  SCFree(dnp3->response_buffer.buffer);
1481  }
1482  SCFree(dnp3);
1483  }
1484  SCReturn;
1485 }
1486 
1487 /**
1488  * \brief Called by the app-layer to get the state progress.
1489  */
1490 static int DNP3GetAlstateProgress(void *tx, uint8_t direction)
1491 {
1492  DNP3Transaction *dnp3tx = (DNP3Transaction *)tx;
1493  DNP3State *dnp3 = dnp3tx->dnp3;
1494  int retval = 0;
1495 
1496  /* If flooded, "ack" old transactions. */
1497  if (dnp3->flooded && (dnp3->transaction_max - dnp3tx->tx_num >= dnp3_max_tx)) {
1498  SCLogDebug("flooded: returning tx as done.");
1499  SCReturnInt(1);
1500  }
1501 
1502  if (dnp3tx->done)
1503  retval = 1;
1504 
1505  SCReturnInt(retval);
1506 }
1507 
1508 /**
1509  * \brief App-layer support.
1510  */
1511 static int DNP3StateGetEventInfo(
1512  const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
1513 {
1514  if (SCAppLayerGetEventIdByName(event_name, dnp3_decoder_event_table, event_id) == 0) {
1515  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1516  return 0;
1517  }
1518  return -1;
1519 }
1520 
1521 /**
1522  * \brief App-layer support.
1523  */
1524 static int DNP3StateGetEventInfoById(
1525  uint8_t event_id, const char **event_name, AppLayerEventType *event_type)
1526 {
1527  *event_name = SCMapEnumValueToName(event_id, dnp3_decoder_event_table);
1528  if (*event_name == NULL) {
1529  SCLogError("Event \"%d\" not present in "
1530  "the DNP3 enum event map table.",
1531  event_id);
1532  return -1;
1533  }
1534 
1535  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1536 
1537  return 0;
1538 }
1539 
1540 static AppLayerTxData *DNP3GetTxData(void *vtx)
1541 {
1542  DNP3Transaction *tx = (DNP3Transaction *)vtx;
1543  return &tx->tx_data;
1544 }
1545 
1546 static AppLayerStateData *DNP3GetStateData(void *vstate)
1547 {
1548  DNP3State *state = (DNP3State *)vstate;
1549  return &state->state_data;
1550 }
1551 
1552 /**
1553  * \brief Check if the prefix code is a size prefix.
1554  *
1555  * \retval 1 if the prefix_code specifies a size prefix, 0 if not.
1556  */
1557 int DNP3PrefixIsSize(uint8_t prefix_code)
1558 {
1559  switch (prefix_code) {
1560  case 0x04:
1561  case 0x05:
1562  case 0x06:
1563  return 1;
1564  break;
1565  default:
1566  return 0;
1567  }
1568 }
1569 
1570 static AppLayerGetTxIterTuple DNP3GetTxIterator(const uint8_t ipproto, const AppProto alproto,
1571  void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *state)
1572 {
1573  DNP3State *dnp_state = (DNP3State *)alstate;
1574  AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
1575  if (dnp_state) {
1576  DNP3Transaction *tx_ptr;
1577  if (state->un.ptr == NULL) {
1578  tx_ptr = TAILQ_FIRST(&dnp_state->tx_list);
1579  } else {
1580  tx_ptr = (DNP3Transaction *)state->un.ptr;
1581  }
1582  if (tx_ptr) {
1583  while (tx_ptr->tx_num < min_tx_id + 1) {
1584  tx_ptr = TAILQ_NEXT(tx_ptr, next);
1585  if (!tx_ptr) {
1586  return no_tuple;
1587  }
1588  }
1589  if (tx_ptr->tx_num >= max_tx_id + 1) {
1590  return no_tuple;
1591  }
1592  state->un.ptr = TAILQ_NEXT(tx_ptr, next);
1593  AppLayerGetTxIterTuple tuple = {
1594  .tx_ptr = tx_ptr,
1595  .tx_id = tx_ptr->tx_num - 1,
1596  .has_next = (state->un.ptr != NULL),
1597  };
1598  return tuple;
1599  }
1600  }
1601  return no_tuple;
1602 }
1603 
1604 /**
1605  * \brief Register the DNP3 application protocol parser.
1606  */
1608 {
1609  SCEnter();
1610 
1611  const char *proto_name = "dnp3";
1612 
1613  if (SCAppLayerProtoDetectConfProtoDetectionEnabledDefault("tcp", proto_name, false)) {
1615 
1616  if (RunmodeIsUnittests()) {
1618  sizeof(DNP3LinkHeader), STREAM_TOSERVER, DNP3ProbingParser, DNP3ProbingParser);
1619  }
1620  else {
1621  if (!SCAppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP, proto_name, ALPROTO_DNP3,
1622  0, sizeof(DNP3LinkHeader), DNP3ProbingParser, DNP3ProbingParser)) {
1623  return;
1624  }
1625  }
1626 
1627  } else {
1628  SCLogConfig("Protocol detection and parser disabled for DNP3.");
1629  SCReturn;
1630  }
1631 
1632  if (SCAppLayerParserConfParserEnabled("tcp", proto_name)) {
1633  SCLogConfig("Registering DNP3/tcp parsers.");
1634 
1635  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DNP3, STREAM_TOSERVER,
1636  DNP3ParseRequest);
1637  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DNP3, STREAM_TOCLIENT,
1638  DNP3ParseResponse);
1639 
1641  DNP3StateAlloc, DNP3StateFree);
1642 
1643  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTx);
1644  AppLayerParserRegisterGetTxIterator(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxIterator);
1645  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxCnt);
1647  DNP3StateTxFree);
1648 
1650  DNP3GetAlstateProgress);
1652 
1654  DNP3StateGetEventInfo);
1656  DNP3StateGetEventInfoById);
1657 
1659  DNP3GetTxData);
1660  AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetStateData);
1661 
1662  /* Parse max-tx configuration. */
1663  intmax_t value = 0;
1664  if (SCConfGetInt("app-layer.protocols.dnp3.max-tx", &value)) {
1665  dnp3_max_tx = (uint64_t)value;
1666  }
1667 
1668  /* Parse max-points configuration. */
1669  if (SCConfGetInt("app-layer.protocols.dnp3.max-points", &value)) {
1670  if (value > 0) {
1671  max_points = (uint64_t)value;
1672  }
1673  }
1674 
1675  /* Parse max-objects configuration. */
1676  if (SCConfGetInt("app-layer.protocols.dnp3.max-objects", &value)) {
1677  if (value > 0) {
1678  dnp3_max_objects = (uint64_t)value;
1679  }
1680  }
1681  } else {
1682  SCLogConfig("Parser disabled for protocol %s. "
1683  "Protocol detection still on.", proto_name);
1684  }
1685 
1686 #ifdef UNITTESTS
1689 #endif
1690 
1691  SCReturn;
1692 }
1693 
1694 #ifdef UNITTESTS
1695 
1696 #include "flow-util.h"
1697 #include "stream-tcp.h"
1698 #include "util-unittest.h"
1699 #include "threads.h"
1700 
1701 /**
1702  * \brief Utility function to fix CRCs when mangling a frame.
1703  */
1704 static void DNP3FixCrc(uint8_t *data, uint32_t len)
1705 {
1706  uint32_t block_size;
1707 
1708  while (len) {
1709  if (len >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
1710  block_size = DNP3_BLOCK_SIZE;
1711  } else {
1712  block_size = len - DNP3_CRC_LEN;
1713  }
1714  uint16_t crc = DNP3ComputeCRC(data, block_size);
1715  data[block_size + 1] = (crc >> 8) & 0xff;
1716  data[block_size] = crc & 0xff;
1717  data += block_size + DNP3_CRC_LEN;
1718  len -= block_size + DNP3_CRC_LEN;
1719  }
1720 }
1721 
1722 /**
1723  * \test Test CRC checking on partial and full blocks.
1724  */
1725 static int DNP3ParserTestCheckCRC(void)
1726 {
1727  uint8_t request[] = {
1728  /* DNP3 start. */
1729  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1730  0xa5, 0xe9,
1731 
1732  /* Transport header. */
1733  0xff,
1734 
1735  /* Application layer - segment 1. */
1736  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1737  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1738  0xef,
1739 
1740  /* Application layer - segment 2. */
1741  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1742  };
1743 
1744  /* Check link header CRC. */
1745  FAIL_IF(!DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1746 
1747  /* Check first application layer segment. */
1748  FAIL_IF(!DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1750 
1751 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1752  /* Change a byte in link header, should fail now. */
1753  request[2]++;
1754  FAIL_IF(DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1755 
1756  /* Change a byte in the first application segment, should fail
1757  * now. */
1758  request[sizeof(DNP3LinkHeader) + 3]++;
1759  FAIL_IF(DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1761 #endif
1762 
1763  PASS;
1764 }
1765 
1766 /**
1767  * \test Test validation of all CRCs in user data.
1768  */
1769 static int DNP3CheckUserDataCRCsTest(void)
1770 {
1771  /* Multi-block data with valid CRCs. */
1772  uint8_t data_valid[] = {
1773  0xff, 0xc9, 0x05, 0x0c,
1774  0x01, 0x28, 0x01, 0x00,
1775  0x00, 0x00, 0x01, 0x01,
1776  0x01, 0x00, 0x00, 0x00,
1777  0x72, 0xef, /* CRC. */
1778 
1779  0xff, 0xc9, 0x05, 0x0c,
1780  0x01, 0x28, 0x01, 0x00,
1781  0x00, 0x00, 0x01, 0x01,
1782  0x01, 0x00, 0x00, 0x00,
1783  0x72, 0xef, /* CRC. */
1784 
1785  0xff, 0xc9, 0x05, 0x0c,
1786  0x01, 0x28, 0x01, 0x00,
1787  0x00, 0x00, 0x01, 0x01,
1788  0x01, 0x00, 0x00, 0x00,
1789  0x72, 0xef, /* CRC. */
1790 
1791  0x00, 0x00, 0x00, 0x00,
1792  0x00,
1793  0xff, 0xff, /* CRC. */
1794  };
1795  FAIL_IF(!DNP3CheckUserDataCRCs(data_valid, sizeof(data_valid)));
1796 
1797 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1798  /* Multi-block data with one non-crc byte altered. */
1799  uint8_t data_invalid[] = {
1800  0xff, 0xc9, 0x05, 0x0c,
1801  0x01, 0x28, 0x01, 0x00,
1802  0x00, 0x00, 0x01, 0x01,
1803  0x01, 0x00, 0x00, 0x00,
1804  0x72, 0xef, /* CRC. */
1805 
1806  0xff, 0xc9, 0x05, 0x0c,
1807  0x01, 0x28, 0x01, 0x00,
1808  0x00, 0x00, 0x01, 0x01,
1809  0x01, 0x00, 0x00, 0x00,
1810  0x72, 0xef, /* CRC. */
1811 
1812  0xff, 0xc9, 0x05, 0x0c,
1813  0x01, 0x28, 0x01, 0x00,
1814  0x00, 0x00, 0x01, 0x01,
1815  0x01, 0x00, 0x00, 0x00,
1816  0x72, 0xef, /* CRC. */
1817 
1818  0x00, 0x00, 0x00, 0x00,
1819  0x01, /* Invalid byte. */
1820  0xff, 0xff, /* CRC. */
1821  };
1822  FAIL_IF(DNP3CheckUserDataCRCs(data_invalid, sizeof(data_invalid)));
1823 
1824  /* 1 byte - need at least 3. */
1825  uint8_t one_byte_nocrc[] = { 0x01 };
1826  FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc, sizeof(one_byte_nocrc)));
1827 
1828  /* 2 bytes - need at least 3. */
1829  uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1830  FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc, sizeof(two_byte_nocrc)));
1831 #endif
1832 
1833  /* 3 bytes, valid CRC. */
1834  uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1835  *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1836  three_bytes_good_crc, 1);
1837  FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1838  sizeof(three_bytes_good_crc)));
1839 
1840  PASS;
1841 }
1842 
1843 /**
1844  * \test Test the link layer length calculation.
1845  *
1846  * Test the calculation that converts the link provided in the DNP3
1847  * header to the actual length of the frame. That is the length with
1848  * CRCs as the length in the header does not include CRCs.
1849  */
1850 static int DNP3CalculateLinkLengthTest(void)
1851 {
1852  /* These are invalid. */
1853  FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1854  FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1855  FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1856  FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1857  FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1858 
1859  /* This is the minimum size. */
1860  FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1861 
1862  /* 1 full user data blocks of data. */
1863  FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1864 
1865  /* 2 full user data blocks of data. */
1866  FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1867 
1868  /* 2 full user data blocks, plus one more byte. */
1869  /* 2 full user data blocks of data. */
1870  FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1871 
1872  /* The maximum size. */
1873  FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1874 
1875  PASS;
1876 }
1877 
1878 /**
1879  * \test The conversion of length with CRCs to the length without
1880  * CRCs.
1881  */
1882 static int DNP3CalculateTransportLengthWithoutCRCsTest(void)
1883 {
1884  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1885  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1886  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1887  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1888  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1889  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1890  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1891 
1892  /* 19 bytes is not enough for a second block. */
1893  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1894 
1895  /* 20 bytes really isn't enough either, but is large enough to
1896  * satisfy the CRC on the second block. */
1897  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1898 
1899  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1900 
1901  PASS;
1902 }
1903 
1904 /**
1905  * \test Test the validation of the link header CRC.
1906  */
1907 static int DNP3ParserCheckLinkHeaderCRC(void)
1908 {
1909  /* DNP3 frame with valid headers and CRCs. */
1910  uint8_t request[] = {
1911  /* DNP3 start. */
1912  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1913  0xa5, 0xe9,
1914 
1915  /* Transport header. */
1916  0xff,
1917 
1918  /* Application layer. */
1919  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1920  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1921  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1922  };
1923 
1924  DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1925  FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1926 
1927 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1928  /* Alter a byte in the header. */
1929  request[4] = 0;
1930  FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1931 #endif
1932 
1933  PASS;
1934 }
1935 
1936 /**
1937  * \test Test removal of CRCs from user data.
1938  */
1939 static int DNP3ReassembleApplicationLayerTest01(void)
1940 {
1941  uint16_t reassembled_len = 0;
1942  uint8_t *output = NULL;
1943 
1944  uint8_t payload[] = {
1945 
1946  0xff, 0xc9, 0x05, 0x0c,
1947  0x01, 0x28, 0x01, 0x00,
1948  0x00, 0x00, 0x01, 0x01,
1949  0x01, 0x00, 0x00, 0x00,
1950  0x72, 0xef, /* CRC. */
1951 
1952  0xff, 0xc9, 0x05, 0x0c,
1953  0x01, 0x28, 0x01, 0x00,
1954  0x00, 0x00, 0x01, 0x01,
1955  0x01, 0x00, 0x00, 0x00,
1956  0x72, 0xef, /* CRC. */
1957 
1958  0xff, 0xc9, 0x05, 0x0c,
1959  0x01, 0x28, 0x01, 0x00,
1960  0x00, 0x00, 0x01, 0x01,
1961  0x01, 0x00, 0x00, 0x00,
1962  0x72, 0xef, /* CRC. */
1963 
1964  0x00, 0x00, 0x00, 0x00,
1965  0x00,
1966  0xff, 0xff, /* CRC. */
1967  };
1968 
1969  uint8_t expected[] = {
1970  0xc9, 0x05, 0x0c,
1971  0x01, 0x28, 0x01, 0x00,
1972  0x00, 0x00, 0x01, 0x01,
1973  0x01, 0x00, 0x00, 0x00,
1974  /* CRC removed. */
1975  0xff, 0xc9, 0x05, 0x0c,
1976  0x01, 0x28, 0x01, 0x00,
1977  0x00, 0x00, 0x01, 0x01,
1978  0x01, 0x00, 0x00, 0x00,
1979  /* CRC removed. */
1980  0xff, 0xc9, 0x05, 0x0c,
1981  0x01, 0x28, 0x01, 0x00,
1982  0x00, 0x00, 0x01, 0x01,
1983  0x01, 0x00, 0x00, 0x00,
1984  /* CRC removed. */
1985  0x00, 0x00, 0x00, 0x00,
1986  0x00
1987  /* CRC removed. */
1988  };
1989 
1990  /* Valid frame. */
1991  FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1992  sizeof(payload), &output, &reassembled_len));
1993  FAIL_IF(output == NULL);
1994  FAIL_IF(reassembled_len != sizeof(expected));
1995  FAIL_IF(memcmp(expected, output, reassembled_len));
1996  SCFree(output);
1997 
1998  /* 1 byte, invalid. */
1999  reassembled_len = 0;
2000  output = NULL;
2001  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
2002  &reassembled_len));
2003  FAIL_IF(output != NULL);
2004  FAIL_IF(reassembled_len != 0);
2005 
2006  /* 2 bytes, invalid. */
2007  reassembled_len = 0;
2008  output = NULL;
2009  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
2010  &reassembled_len));
2011  FAIL_IF(output != NULL);
2012  FAIL_IF(reassembled_len != 0);
2013 
2014  /* 3 bytes, minimum - but that would only be the transport header
2015  * which isn't included in the output. */
2016  reassembled_len = 0;
2017  output = NULL;
2018  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
2019  &reassembled_len));
2020  FAIL_IF(output != NULL);
2021  FAIL_IF(reassembled_len != 0);
2022 
2023  /* 4 bytes is the minimum to get any reassembled data. */
2024  reassembled_len = 0;
2025  output = NULL;
2026  FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
2027  &reassembled_len));
2028  FAIL_IF(output == NULL);
2029  FAIL_IF(reassembled_len != 1);
2030 
2031  /* Last block too short (by 1 byte) for data + CRC. */
2032  uint8_t short_payload1[] = {
2033 
2034  0xff, 0xc9, 0x05, 0x0c,
2035  0x01, 0x28, 0x01, 0x00,
2036  0x00, 0x00, 0x01, 0x01,
2037  0x01, 0x00, 0x00, 0x00,
2038  0x72, 0xef, /* CRC. */
2039 
2040  0xff, 0xc9, 0x05, 0x0c,
2041  0x01, 0x28, 0x01, 0x00,
2042  0x00, 0x00, 0x01, 0x01,
2043  0x01, 0x00, 0x00, 0x00,
2044  0x72, 0xef, /* CRC. */
2045 
2046  0xff, 0xc9, 0x05, 0x0c,
2047  0x01, 0x28, 0x01, 0x00,
2048  0x00, 0x00, 0x01, 0x01,
2049  0x01, 0x00, 0x00, 0x00,
2050  0x72, 0xef, /* CRC. */
2051 
2052  0x00, 0x00
2053  };
2054  reassembled_len = 0;
2055  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
2056  sizeof(short_payload1), &output, &reassembled_len));
2057 
2058  /* Last block too short (by 2 bytes) for data + CRC. */
2059  uint8_t short_payload2[] = {
2060 
2061  0xff, 0xc9, 0x05, 0x0c,
2062  0x01, 0x28, 0x01, 0x00,
2063  0x00, 0x00, 0x01, 0x01,
2064  0x01, 0x00, 0x00, 0x00,
2065  0x72, 0xef, /* CRC. */
2066 
2067  0xff, 0xc9, 0x05, 0x0c,
2068  0x01, 0x28, 0x01, 0x00,
2069  0x00, 0x00, 0x01, 0x01,
2070  0x01, 0x00, 0x00, 0x00,
2071  0x72, 0xef, /* CRC. */
2072 
2073  0xff, 0xc9, 0x05, 0x0c,
2074  0x01, 0x28, 0x01, 0x00,
2075  0x00, 0x00, 0x01, 0x01,
2076  0x01, 0x00, 0x00, 0x00,
2077  0x72, 0xef, /* CRC. */
2078 
2079  0x00,
2080  };
2081  reassembled_len = 0;
2082  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
2083  sizeof(short_payload2), &output, &reassembled_len));
2084  SCFree(output);
2085  output = NULL;
2086 
2087  PASS;
2088 }
2089 
2090 /**
2091  * \test Test the probing parser.
2092  */
2093 static int DNP3ProbingParserTest(void)
2094 {
2095  uint8_t pkt[] = {
2096  0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2097  0xbd, 0x71
2098  };
2099  uint8_t rdir = 0;
2100 
2101  /* Valid frame. */
2102  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_DNP3);
2103 
2104  /* Send too little bytes. */
2105  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(DNP3LinkHeader) - 1, &rdir) != ALPROTO_UNKNOWN);
2106 
2107  /* Bad start bytes. */
2108  pkt[0] = 0x06;
2109  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2110 
2111  /* Restore start byte. */
2112  pkt[0] = 0x05;
2113 
2114  /* Set the length to a value less than the minimum length of 5. */
2115  pkt[2] = 0x03;
2116  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2117 
2118  /* Send a banner. */
2119  char mybanner[] = "Welcome to DNP3 SCADA.";
2120  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner, sizeof(mybanner) - 1,
2121  &rdir) != ALPROTO_DNP3);
2122  FAIL_IF(rdir != STREAM_TOCLIENT);
2123 
2124  PASS;
2125 }
2126 
2127 /**
2128  * \test Test a basic request/response.
2129  */
2130 static int DNP3ParserTestRequestResponse(void)
2131 {
2132  DNP3State *state = NULL;
2133 
2134  uint8_t request[] = {
2135  /* DNP3 start. */
2136  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2137  0xa5, 0xe9,
2138 
2139  /* Transport header. */
2140  0xff,
2141 
2142  /* Application layer. */
2143  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2144  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2145  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2146  };
2147 
2148  uint8_t response[] = {
2149  /* DNP3 start. */
2150  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2151  0xe2, 0x59,
2152 
2153  /* Transport header. */
2154  0xc3,
2155 
2156  /* Application layer. */
2157  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2158  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2159  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2160  0xff, 0xff
2161  };
2162 
2164  Flow flow;
2165  TcpSession ssn;
2166 
2167  memset(&flow, 0, sizeof(flow));
2168  memset(&ssn, 0, sizeof(ssn));
2169 
2170  flow.protoctx = (void *)&ssn;
2171  flow.proto = IPPROTO_TCP;
2172  flow.alproto = ALPROTO_DNP3;
2173 
2174  StreamTcpInitConfig(true);
2175 
2176  SCMutexLock(&flow.m);
2178  STREAM_TOSERVER, request, sizeof(request)));
2179  SCMutexUnlock(&flow.m);
2180 
2181  state = flow.alstate;
2182  FAIL_IF(state == NULL);
2183 
2184  DNP3Transaction *tx = DNP3GetTx(state, 0);
2185  FAIL_IF(tx == NULL);
2186  FAIL_IF(tx->tx_num != 1);
2187  FAIL_IF(tx != state->curr);
2188  FAIL_IF(tx->buffer == NULL);
2189  FAIL_IF(tx->buffer_len != 20);
2190  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2191 
2192  SCMutexLock(&flow.m);
2194  STREAM_TOCLIENT, response, sizeof(response)));
2195  SCMutexUnlock(&flow.m);
2196  DNP3Transaction *tx0 = DNP3GetTx(state, 1);
2197  FAIL_IF(tx0 == NULL);
2198  FAIL_IF(tx0 == tx);
2199  FAIL_IF(!tx0->done);
2200  FAIL_IF(tx0->buffer == NULL);
2201 
2203  StreamTcpFreeConfig(true);
2204  FLOW_DESTROY(&flow);
2205  PASS;
2206 }
2207 
2208 /**
2209  * \test Test an unsolicited response from an outstation.
2210  *
2211  * This is kind of like a request initiated from the "server".
2212  */
2213 static int DNP3ParserTestUnsolicitedResponseConfirm(void)
2214 {
2215  DNP3State *state = NULL;
2216 
2217  /* Unsolicited response with confirm bit set. */
2218  uint8_t response[] = {
2219  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2220  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2221  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2222  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2223  };
2224 
2225  /* Confirm. */
2226  uint8_t confirm[] = {
2227  0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2228  0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2229  0x3d
2230  };
2231 
2233  Flow flow;
2234  TcpSession ssn;
2235 
2236  memset(&flow, 0, sizeof(flow));
2237  memset(&ssn, 0, sizeof(ssn));
2238 
2239  flow.protoctx = (void *)&ssn;
2240  flow.proto = IPPROTO_TCP;
2241  flow.alproto = ALPROTO_DNP3;
2242 
2243  StreamTcpInitConfig(true);
2244 
2245  SCMutexLock(&flow.m);
2247  STREAM_TOCLIENT, response, sizeof(response)));
2248  SCMutexUnlock(&flow.m);
2249 
2250  state = flow.alstate;
2251  FAIL_IF(state == NULL);
2252 
2253  DNP3Transaction *tx = DNP3GetTx(state, 0);
2254  FAIL_IF(tx == NULL);
2255  FAIL_IF(tx->tx_num != 1);
2256  FAIL_IF(tx != state->curr);
2257  FAIL_IF(!tx->done);
2258  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_UNSOLICITED_RESP);
2259 
2260  SCMutexLock(&flow.m);
2262  STREAM_TOSERVER, confirm, sizeof(confirm)));
2263  SCMutexUnlock(&flow.m);
2264 
2265  /* Confirms are ignored currently. With the move to
2266  unidirectional transactions it might be easy to support these
2267  now. */
2268  DNP3Transaction *resptx = DNP3GetTx(state, 1);
2269  FAIL_IF(resptx);
2270 
2272  StreamTcpFreeConfig(true);
2273  FLOW_DESTROY(&flow);
2274  PASS;
2275 }
2276 
2277 /**
2278  * \test Test flood state.
2279  *
2280  * Note that flood state needs to revisited with the modification to a
2281  * unidirectional protocol.
2282  */
2283 static int DNP3ParserTestFlooded(void)
2284 {
2285  DNP3State *state = NULL;
2286 
2287  uint8_t request[] = {
2288  /* DNP3 start. */
2289  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2290  0xa5, 0xe9,
2291 
2292  /* Transport header. */
2293  0xff,
2294 
2295  /* Application layer. */
2296  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2297  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2298  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2299  };
2300 
2302  Flow flow;
2303  TcpSession ssn;
2304 
2305  memset(&flow, 0, sizeof(flow));
2306  memset(&ssn, 0, sizeof(ssn));
2307 
2308  flow.protoctx = (void *)&ssn;
2309  flow.proto = IPPROTO_TCP;
2310  flow.alproto = ALPROTO_DNP3;
2311 
2312  StreamTcpInitConfig(true);
2313 
2314  SCMutexLock(&flow.m);
2316  STREAM_TOSERVER, request, sizeof(request)));
2317  SCMutexUnlock(&flow.m);
2318 
2319  state = flow.alstate;
2320  FAIL_IF(state == NULL);
2321 
2322  DNP3Transaction *tx = DNP3GetTx(state, 0);
2323  FAIL_IF(tx == NULL);
2324  FAIL_IF(tx->tx_num != 1);
2325  FAIL_IF(tx != state->curr);
2326  FAIL_IF(tx->buffer == NULL);
2327  FAIL_IF(tx->buffer_len != 20);
2328  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2329  FAIL_IF_NOT(tx->done);
2330  FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2331 
2332  for (uint64_t i = 0; i < dnp3_max_tx - 1; i++) {
2333  SCMutexLock(&flow.m);
2335  STREAM_TOSERVER, request, sizeof(request)));
2336  SCMutexUnlock(&flow.m);
2337  }
2338  FAIL_IF(state->flooded);
2339  FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2340 
2341  /* One more request should trip us into flooded state. */
2342  SCMutexLock(&flow.m);
2344  STREAM_TOSERVER, request, sizeof(request)));
2345  SCMutexUnlock(&flow.m);
2346  FAIL_IF(!state->flooded);
2347 
2348  /* Progress for the oldest tx should return 1. */
2349  FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2350 
2352  StreamTcpFreeConfig(true);
2353  FLOW_DESTROY(&flow);
2354  PASS;
2355 }
2356 
2357 /**
2358  * \test Test parsing of partial frames.
2359  *
2360  * As DNP3 operates over TCP, it is possible that a partial DNP3 frame
2361  * is received. Test that the partial frame will be buffered until the
2362  * remainder is seen.
2363  */
2364 static int DNP3ParserTestPartialFrame(void)
2365 {
2366  DNP3State *state = NULL;
2367  DNP3Transaction *tx;
2368  int r;
2369 
2370  uint8_t request_partial1[] = {
2371  /* DNP3 start. */
2372  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2373  0xa5, 0xe9,
2374 
2375  /* Transport header. */
2376  0xff,
2377 
2378  /* Application layer. */
2379  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2380  };
2381 
2382  uint8_t request_partial2[] = {
2383  /* Remainder of application layer. */
2384  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2385  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2386  };
2387 
2388  uint8_t response_partial1[] = {
2389  /* DNP3 start. */
2390  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2391  0xe2, 0x59,
2392 
2393  /* Transport header. */
2394  0xc3,
2395 
2396  /* Application layer. */
2397  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2398  };
2399 
2400  uint8_t response_partial2[] = {
2401  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2402  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2403  0xff, 0xff
2404  };
2405 
2406  /* Boiler plate for app layer setup. */
2408  Flow flow;
2409  TcpSession ssn;
2410  memset(&flow, 0, sizeof(flow));
2411  memset(&ssn, 0, sizeof(ssn));
2412  flow.protoctx = (void *)&ssn;
2413  flow.proto = IPPROTO_TCP;
2414  flow.alproto = ALPROTO_DNP3;
2415  StreamTcpInitConfig(true);
2416 
2417  /* Pass in the first partial frame. */
2418 
2419  SCMutexLock(&flow.m);
2420  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2421  STREAM_TOSERVER, request_partial1, sizeof(request_partial1));
2422  SCMutexUnlock(&flow.m);
2423  FAIL_IF(r != 0);
2424 
2425  /* Frame should just be buffered, but not yet processed. */
2426  state = flow.alstate;
2427  FAIL_IF(state == NULL);
2428  FAIL_IF(state->request_buffer.len != sizeof(request_partial1));
2429  FAIL_IF(state->request_buffer.offset != 0);
2430  FAIL_IF(memcmp(state->request_buffer.buffer, request_partial1,
2431  sizeof(request_partial1)));
2432 
2433  /* There should not be a transaction yet. */
2434  FAIL_IF(state->transaction_max != 0);
2435  FAIL_IF(DNP3GetTx(state, 0) != NULL);
2436 
2437  /* Send the second partial. */
2438  SCMutexLock(&flow.m);
2439  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2440  STREAM_TOSERVER, request_partial2, sizeof(request_partial2));
2441  SCMutexUnlock(&flow.m);
2442  FAIL_IF(r != 0);
2443 
2444  /* The second partial completed the frame, the buffer should now
2445  * be clear. */
2446  FAIL_IF(state->request_buffer.len != 0);
2447  FAIL_IF(state->request_buffer.offset != 0);
2448 
2449  /* Should now have a complete transaction. */
2450  tx = DNP3GetTx(state, 0);
2451  FAIL_IF(tx == NULL);
2452  FAIL_IF(tx->tx_num != 1);
2453  FAIL_IF(tx != state->curr);
2454  FAIL_IF(tx->buffer == NULL);
2455  FAIL_IF(tx->buffer_len != 20);
2456  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2457 
2458  /* Send partial response. */
2459  SCMutexLock(&flow.m);
2460  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2461  STREAM_TOCLIENT, response_partial1, sizeof(response_partial1));
2462  SCMutexUnlock(&flow.m);
2463  FAIL_IF(r != 0);
2464  FAIL_IF(state->response_buffer.len != sizeof(response_partial1));
2465  FAIL_IF(state->response_buffer.offset != 0);
2466  tx = DNP3GetTx(state, 1);
2467  FAIL_IF_NOT_NULL(tx);
2468 
2469  /* Send rest of response. */
2470  SCMutexLock(&flow.m);
2471  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2472  STREAM_TOCLIENT, response_partial2, sizeof(response_partial2));
2473  SCMutexUnlock(&flow.m);
2474  FAIL_IF(r != 0);
2475 
2476  /* Buffer should now be empty. */
2477  FAIL_IF(state->response_buffer.len != 0);
2478  FAIL_IF(state->response_buffer.offset != 0);
2479 
2480  /* There should now be a response transaction. */
2481  tx = DNP3GetTx(state, 1);
2482  FAIL_IF_NULL(tx);
2483  FAIL_IF(tx->buffer == NULL);
2484  FAIL_IF(tx->buffer_len == 0);
2485 
2487  StreamTcpFreeConfig(true);
2488  FLOW_DESTROY(&flow);
2489  PASS;
2490 }
2491 
2492 /**
2493  * \test Test multiple DNP3 frames in one TCP read.
2494  */
2495 static int DNP3ParserTestMultiFrame(void)
2496 {
2497  DNP3State *state = NULL;
2498 
2499  /* Unsolicited response 1. */
2500  uint8_t unsol_response1[] = {
2501  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2502  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2503  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2504  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2505  };
2506 
2507  /* Unsolicited response 2. */
2508  uint8_t unsol_response2[] = {
2509  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2510  0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2511  0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2512  0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2513  };
2514 
2515  uint8_t combined[sizeof(unsol_response1) + sizeof(unsol_response2)];
2516  memcpy(combined, unsol_response1, sizeof(unsol_response1));
2517  memcpy(combined + sizeof(unsol_response1), unsol_response2,
2518  sizeof(unsol_response2));
2519 
2520  /* Setup. */
2522  Flow flow;
2523  TcpSession ssn;
2524  int r;
2525  memset(&flow, 0, sizeof(flow));
2526  memset(&ssn, 0, sizeof(ssn));
2527  flow.protoctx = (void *)&ssn;
2528  flow.proto = IPPROTO_TCP;
2529  flow.alproto = ALPROTO_DNP3;
2530  StreamTcpInitConfig(true);
2531 
2532  SCMutexLock(&flow.m);
2533  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2534  STREAM_TOCLIENT, combined, sizeof(combined));
2535  SCMutexUnlock(&flow.m);
2536  FAIL_IF(r != 0);
2537 
2538  state = flow.alstate;
2539  FAIL_IF(state == NULL);
2540  FAIL_IF(state->transaction_max != 2);
2541 
2543  StreamTcpFreeConfig(true);
2544  FLOW_DESTROY(&flow);
2545  PASS;
2546 }
2547 
2548 /**
2549  * \test Test the parsing of a request PDU.
2550  *
2551  * The PDU under test contains a single read request object:
2552  * - Group: 1
2553  * - Variation: 0
2554  * - Count: 0
2555  */
2556 static int DNP3ParserTestParsePDU01(void)
2557 {
2558  /* Frame to be tested. This frame is a DNP3 request with one read
2559  * request data object, group 1, variation 0. */
2560  const uint8_t pkt[] = {
2561  0x05, 0x64,
2562  0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2563  0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2564  };
2565 
2566  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2567  int pdus = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2568  FAIL_IF(pdus < 1);
2569  DNP3Transaction *dnp3tx = DNP3GetTx(dnp3state, 0);
2570  FAIL_IF_NULL(dnp3tx);
2571  FAIL_IF(!dnp3tx->is_request);
2572  FAIL_IF(TAILQ_EMPTY(&dnp3tx->objects));
2573  DNP3Object *object = TAILQ_FIRST(&dnp3tx->objects);
2574  FAIL_IF(object->group != 1 || object->variation != 0);
2575  FAIL_IF(object->count != 0);
2576 
2577  DNP3StateFree(dnp3state);
2578  PASS;
2579 }
2580 
2581 /**
2582  * \test Ensure variable-length DNP3 objects do not embed maximum-sized buffers.
2583  */
2584 static int DNP3ParserObjectStructSizeTest(void)
2585 {
2586  const size_t max_point_size = 1024;
2587 
2588  FAIL_IF(sizeof(DNP3ObjectG70V1) >= max_point_size);
2589  FAIL_IF(sizeof(DNP3ObjectG70V2) >= max_point_size);
2590  FAIL_IF(sizeof(DNP3ObjectG70V3) >= max_point_size);
2591  FAIL_IF(sizeof(DNP3ObjectG70V7) >= max_point_size);
2592  FAIL_IF(sizeof(DNP3ObjectG70V8) >= max_point_size);
2593  FAIL_IF(sizeof(DNP3ObjectG120V7) >= max_point_size);
2594  FAIL_IF(sizeof(DNP3ObjectG120V10) >= max_point_size);
2595  FAIL_IF(sizeof(DNP3ObjectG120V11) >= max_point_size);
2596 
2597  PASS;
2598 }
2599 
2600 /**
2601  * \test Decode non-empty dynamically allocated G70V2 strings.
2602  */
2603 static int DNP3ParserDecodeG70V2Test(void)
2604 {
2605  const uint8_t input[] = {
2606  0x00,
2607  0x00,
2608  0x03,
2609  0x00,
2610  0x00,
2611  0x00,
2612  0x06,
2613  0x00,
2614  0x78,
2615  0x56,
2616  0x34,
2617  0x12,
2618  'b',
2619  'o',
2620  'b',
2621  's',
2622  'e',
2623  'c',
2624  'r',
2625  'e',
2626  't',
2627  };
2628  const uint8_t *buf = input;
2629  uint16_t len = sizeof(input);
2630  DNP3PointList *points = DNP3PointListAlloc();
2631  FAIL_IF_NULL(points);
2632 
2633  int event = DNP3DecodeObject(70, 2, &buf, &len, 0, 0, 1, points);
2634  FAIL_IF(event != 0);
2635  FAIL_IF(len != 0);
2636  DNP3Point *point = TAILQ_FIRST(points);
2637  FAIL_IF_NULL(point);
2638  DNP3ObjectG70V2 *data = point->data;
2639  FAIL_IF_NULL(data);
2640  FAIL_IF(strcmp(data->username, "bob") != 0);
2641  FAIL_IF(strcmp(data->password, "secret") != 0);
2642  FAIL_IF(data->authentication_key != 0x12345678);
2643 
2644  DNP3FreeObjectPointList(70, 2, points);
2645  PASS;
2646 }
2647 
2648 /**
2649  * \test Clean up an allocated G70V2 username when the password is truncated.
2650  */
2651 static int DNP3ParserDecodeG70V2TruncatedTest(void)
2652 {
2653  const uint8_t input[] = {
2654  0x00,
2655  0x00,
2656  0x03,
2657  0x00,
2658  0x00,
2659  0x00,
2660  0x06,
2661  0x00,
2662  0x78,
2663  0x56,
2664  0x34,
2665  0x12,
2666  'b',
2667  'o',
2668  'b',
2669  's',
2670  'e',
2671  'c',
2672  };
2673  const uint8_t *buf = input;
2674  uint16_t len = sizeof(input);
2675  DNP3PointList *points = DNP3PointListAlloc();
2676  FAIL_IF_NULL(points);
2677 
2678  int event = DNP3DecodeObject(70, 2, &buf, &len, 0, 0, 1, points);
2680  FAIL_IF_NOT(TAILQ_EMPTY(points));
2681 
2682  DNP3FreeObjectPointList(70, 2, points);
2683  PASS;
2684 }
2685 
2686 /**
2687  * \test Test the decode of a DNP3 fragment with a single 70:3 object.
2688  */
2689 static int DNP3ParserDecodeG70V3Test(void)
2690 {
2691  const uint8_t pkt[] = {
2692  0x05, 0x64,
2693  0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2694  0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2695  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2696  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2697  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2698  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2699  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2700  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2701  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2702  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2703  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2704  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2705  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2706  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2707  0xc4, 0x8b
2708  };
2709 
2710  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2711  FAIL_IF_NULL(dnp3state);
2712  int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2713  FAIL_IF(bytes != sizeof(pkt));
2714  DNP3Transaction *tx = DNP3GetTx(dnp3state, 0);
2715  FAIL_IF_NULL(tx);
2716  FAIL_IF_NOT(tx->is_request);
2717  DNP3Object *obj = TAILQ_FIRST(&tx->objects);
2718  FAIL_IF_NULL(obj);
2719  FAIL_IF_NOT(obj->group == 70);
2720  FAIL_IF_NOT(obj->variation == 3);
2721  FAIL_IF_NOT(obj->prefix_code == 0x5);
2722  FAIL_IF_NOT(obj->range_code == 0xb);
2723  FAIL_IF_NOT(obj->count == 1);
2724  DNP3Point *point = TAILQ_FIRST(obj->points);
2725  FAIL_IF_NULL(point);
2726  FAIL_IF_NOT(point->prefix == 85);
2727  FAIL_IF_NOT(point->size == 85);
2728  FAIL_IF_NULL(point->data);
2729  DNP3ObjectG70V3 *data = point->data;
2730  FAIL_IF_NOT(strcmp(
2731  data->filename,
2732  "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2733  DNP3StateFree(dnp3state);
2734  PASS;
2735 }
2736 
2737 /**
2738  * \brief Test that an alert is raised on an unknown object.
2739  */
2740 static int DNP3ParserUnknownEventAlertTest(void)
2741 {
2742  /* Valid DNP3 frame with 70:3 object. */
2743  uint8_t pkt[] = {
2744  0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2745  0xc7, 0xee,
2746 
2747  0xc7, 0xc9, 0x1b,
2748 
2749  /* Object and variation. Originally 70:3, now 70:99, an
2750  * unknown object. */
2751  0x46, 0x63,
2752 
2753  0x5b, 0x01, 0x55,
2754  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2755  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2756  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2757  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2758  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2759  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2760  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2761  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2762  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2763  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2764  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2765  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2766  0xc4, 0x8b
2767  };
2768 
2769  DNP3FixCrc(pkt + 10, sizeof(pkt) - 10);
2770 
2771  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2772  FAIL_IF_NULL(dnp3state);
2773  int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2774  FAIL_IF(bytes != sizeof(pkt));
2775 
2776  DNP3StateFree(dnp3state);
2777  PASS;
2778 }
2779 
2780 /**
2781 * \brief Test that an alert is raised on incorrect data.
2782 */
2783 static int DNP3ParserIncorrectUserData(void)
2784 {
2785  uint8_t packet_bytes[] = {
2786  0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2787  0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2788  };
2789 
2791  Flow flow;
2792  TcpSession ssn;
2793  memset(&flow, 0, sizeof(flow));
2794  memset(&ssn, 0, sizeof(ssn));
2795  flow.protoctx = (void *)&ssn;
2796  flow.proto = IPPROTO_TCP;
2797  flow.alproto = ALPROTO_DNP3;
2798  StreamTcpInitConfig(true);
2799 
2800  int r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2801  STREAM_TOCLIENT, packet_bytes, sizeof(packet_bytes));
2802 
2803  FAIL_IF(r != 0);
2804 
2806  StreamTcpFreeConfig(true);
2807  FLOW_DESTROY(&flow);
2808  PASS;
2809 }
2810 
2811 #endif
2812 
2814 {
2815 #ifdef UNITTESTS
2816  UtRegisterTest("DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2817  UtRegisterTest("DNP3ParserCheckLinkHeaderCRC",
2818  DNP3ParserCheckLinkHeaderCRC);
2819  UtRegisterTest("DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2820  UtRegisterTest("DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2821  UtRegisterTest("DNP3CalculateTransportLengthWithoutCRCsTest",
2822  DNP3CalculateTransportLengthWithoutCRCsTest);
2823  UtRegisterTest("DNP3ReassembleApplicationLayerTest01",
2824  DNP3ReassembleApplicationLayerTest01);
2825  UtRegisterTest("DNP3ProbingParserTest", DNP3ProbingParserTest);
2826  UtRegisterTest("DNP3ParserTestRequestResponse",
2827  DNP3ParserTestRequestResponse);
2828  UtRegisterTest("DNP3ParserTestUnsolicitedResponseConfirm",
2829  DNP3ParserTestUnsolicitedResponseConfirm);
2830  UtRegisterTest("DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2831  UtRegisterTest("DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2832  UtRegisterTest("DNP3ParserTestFlooded", DNP3ParserTestFlooded);
2833  UtRegisterTest("DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2834  UtRegisterTest("DNP3ParserObjectStructSizeTest", DNP3ParserObjectStructSizeTest);
2835  UtRegisterTest("DNP3ParserDecodeG70V2Test", DNP3ParserDecodeG70V2Test);
2836  UtRegisterTest("DNP3ParserDecodeG70V2TruncatedTest", DNP3ParserDecodeG70V2TruncatedTest);
2837  UtRegisterTest("DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2838  UtRegisterTest("DNP3ParserUnknownEventAlertTest",
2839  DNP3ParserUnknownEventAlertTest);
2840  UtRegisterTest("DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);
2841 #endif
2842 }
StreamSlice
Definition: app-layer-parser.h:126
DNP3Transaction_::complete
uint8_t complete
Definition: app-layer-dnp3.h:231
AppLayerParserRegisterGetStateProgressFunc
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
Definition: app-layer-parser.c:544
len
uint8_t len
Definition: app-layer-dnp3.h:2
AppLayerTxData::flags
uint8_t flags
Definition: app-layer-parser.h:182
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
DNP3Transaction_::dnp3
struct DNP3State_ * dnp3
Definition: app-layer-dnp3.h:221
DNP3_DECODER_EVENT_TOO_MANY_POINTS
@ DNP3_DECODER_EVENT_TOO_MANY_POINTS
Definition: app-layer-dnp3.h:113
dnp3_decoder_event_table
SCEnumCharMap dnp3_decoder_event_table[]
Definition: app-layer-dnp3.c:102
DNP3Buffer_::size
size_t size
Definition: app-layer-dnp3.h:159
DNP3_DECODER_EVENT_MALFORMED
@ DNP3_DECODER_EVENT_MALFORMED
Definition: app-layer-dnp3.h:111
AppLayerGetTxIterState::ptr
void * ptr
Definition: app-layer-parser.h:150
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
DNP3_APP_FC_DIR_OPERATE
#define DNP3_APP_FC_DIR_OPERATE
Definition: app-layer-dnp3.h:39
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:262
flow-util.h
stream-tcp.h
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
DNP3State_::response_buffer
DNP3Buffer response_buffer
Definition: app-layer-dnp3.h:254
SCAppLayerTxDataCleanup
void SCAppLayerTxDataCleanup(AppLayerTxData *txd)
Definition: app-layer-parser.c:831
DNP3Transaction_::done
uint8_t done
Definition: app-layer-dnp3.h:230
DNP3Transaction_::th
DNP3TransportHeader th
Definition: app-layer-dnp3.h:227
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DNP3_DECODER_EVENT_FLOODED
@ DNP3_DECODER_EVENT_FLOODED
Definition: app-layer-dnp3.h:107
DNP3_SWAP32
#define DNP3_SWAP32(x)
Definition: app-layer-dnp3.h:97
Flow_::proto
uint8_t proto
Definition: flow.h:382
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:87
DNP3ParserRegisterTests
void DNP3ParserRegisterTests(void)
Definition: app-layer-dnp3.c:2813
DNP3Object_
Struct to hold the list of decoded objects.
Definition: app-layer-dnp3.h:196
ssn
TcpSession ssn
Definition: fuzz_dataset.c:31
threads.h
AppLayerStateData
Definition: app-layer-parser.h:155
Flow_
Flow data structure.
Definition: flow.h:360
DNP3State_::transaction_max
uint64_t transaction_max
Definition: app-layer-dnp3.h:246
DNP3_APP_FC_CONFIRM
#define DNP3_APP_FC_CONFIRM
Definition: app-layer-dnp3.h:34
AppLayerParserRegisterStateProgressCompletionStatus
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
Definition: app-layer-parser.c:592
DNP3State_::flooded
uint8_t flooded
Definition: app-layer-dnp3.h:249
DNP3Buffer_::offset
int offset
Definition: app-layer-dnp3.h:161
AppLayerParserRegisterTxFreeFunc
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
Definition: app-layer-parser.c:554
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:248
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
DNP3ObjectG70V2_::authentication_key
uint32_t authentication_key
Definition: app-layer-dnp3-objects.h:1212
DNP3Transaction_::objects
DNP3ObjectList objects
Definition: app-layer-dnp3.h:225
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:364
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
DNP3PrefixIsSize
int DNP3PrefixIsSize(uint8_t prefix_code)
Check if the prefix code is a size prefix.
Definition: app-layer-dnp3.c:1557
rust.h
DNP3ObjectG120V10_
Definition: app-layer-dnp3-objects.h:1370
DNP3ObjectG120V11_
Definition: app-layer-dnp3-objects.h:1384
DNP3_APP_FC_UNSOLICITED_RESP
#define DNP3_APP_FC_UNSOLICITED_RESP
Definition: app-layer-dnp3.h:71
NEXT_TH_SEQNO
#define NEXT_TH_SEQNO(current)
Definition: app-layer-dnp3.c:116
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:294
DNP3State_::request_buffer
DNP3Buffer request_buffer
Definition: app-layer-dnp3.h:251
util-spm-bs.h
Flow_::protoctx
void * protoctx
Definition: flow.h:439
DNP3_TH_SEQ
#define DNP3_TH_SEQ(x)
Definition: app-layer-dnp3.h:84
AppLayerGetTxIterTuple::tx_ptr
void * tx_ptr
Definition: app-layer-parser.h:160
DNP3_LINK_FC_UNCONFIRMED_USER_DATA
@ DNP3_LINK_FC_UNCONFIRMED_USER_DATA
Definition: app-layer-dnp3.c:71
DNP3Point_::data
void * data
Definition: app-layer-dnp3.h:187
util-unittest.h
RegisterDNP3Parsers
void RegisterDNP3Parsers(void)
Register the DNP3 application protocol parser.
Definition: app-layer-dnp3.c:1607
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DNP3Buffer_::len
int len
Definition: app-layer-dnp3.h:160
SCAppLayerDecoderEventsSetEventRaw
void SCAppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event)
Set an app layer decoder event.
Definition: app-layer-events.c:97
DNP3_SWAP16
#define DNP3_SWAP16(x)
Definition: app-layer-dnp3.h:96
DNP3FreeObjectPointList
void DNP3FreeObjectPointList(int group, int variation, DNP3PointList *list)
Free a DNP3PointList.
Definition: app-layer-dnp3-objects.c:58
DNP3State_::events
uint16_t events
Definition: app-layer-dnp3.h:247
DNP3Object_::points
DNP3PointList * points
Definition: app-layer-dnp3.h:205
AppLayerResult
Definition: app-layer-parser.h:120
DNP3_DECODER_EVENT_UNKNOWN_OBJECT
@ DNP3_DECODER_EVENT_UNKNOWN_OBJECT
Definition: app-layer-dnp3.h:112
SCAppLayerParserTriggerRawStreamInspection
void SCAppLayerParserTriggerRawStreamInspection(Flow *f, int direction)
Definition: app-layer-parser.c:1787
DNP3Transaction_::buffer_len
uint16_t buffer_len
Definition: app-layer-dnp3.h:224
app-layer-detect-proto.h
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:498
DNP3_DECODER_EVENT_TOO_LONG_REASS
@ DNP3_DECODER_EVENT_TOO_LONG_REASS
Definition: app-layer-dnp3.h:115
DNP3ObjectG70V1_
Definition: app-layer-dnp3-objects.h:1188
DNP3_BLOCK_SIZE
#define DNP3_BLOCK_SIZE
Definition: app-layer-dnp3.c:56
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:312
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
DNP3ObjectG70V3_
Definition: app-layer-dnp3-objects.h:1217
util-debug.h
DNP3ObjectG70V2_
Definition: app-layer-dnp3-objects.h:1207
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:250
DNP3Transaction_::ah
DNP3ApplicationHeader ah
Definition: app-layer-dnp3.h:228
DNP3ObjectG70V8_
Definition: app-layer-dnp3-objects.h:1266
DNP3ObjectG70V7_
Definition: app-layer-dnp3-objects.h:1255
AppLayerParserState_
Definition: app-layer-parser.c:160
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
AppLayerTxData
Definition: app-layer-parser.h:172
SCAppLayerParserConfParserEnabled
int SCAppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests
Definition: app-layer-parser.c:385
DNP3Point_::size
uint32_t size
Definition: app-layer-dnp3.h:185
DNP3Transaction_::iin
DNP3InternalInd iin
Definition: app-layer-dnp3.h:229
ALPROTO_DNP3
@ ALPROTO_DNP3
Definition: app-layer-protos.h:50
app-layer-dnp3.h
APP_LAYER_EVENT_TYPE_TRANSACTION
@ APP_LAYER_EVENT_TYPE_TRANSACTION
Definition: app-layer-events.h:55
length
uint16_t length
Definition: decode-sctp.h:2
AppLayerEventType
AppLayerEventType
Definition: app-layer-events.h:54
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
DNP3_CRC_LEN
#define DNP3_CRC_LEN
Definition: app-layer-dnp3.c:52
SCConfGetInt
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:441
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:24
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
AppLayerParserRegisterStateFuncs
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
Definition: app-layer-parser.c:493
Flow_::m
SCMutex m
Definition: flow.h:444
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
DNP3Buffer_::buffer
uint8_t * buffer
Definition: app-layer-dnp3.h:158
app-layer-parser.h
DNP3_TH_FIN
#define DNP3_TH_FIN(x)
Definition: app-layer-dnp3.h:82
AppLayerDecoderEvents_::cnt
uint8_t cnt
Definition: app-layer-events.h:37
AppLayerParserRegisterGetEventInfo
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, uint8_t *event_id, AppLayerEventType *event_type))
Definition: app-layer-parser.c:671
DNP3_MIN_LEN
#define DNP3_MIN_LEN
Definition: app-layer-dnp3.c:49
SCReturn
#define SCReturn
Definition: util-debug.h:286
BasicSearch
uint8_t * BasicSearch(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, uint16_t needle_len)
Basic search improved. Limits are better handled, so it doesn't start searches that wont fit in the r...
Definition: util-spm-bs.c:49
AppLayerParserRegisterProtocolUnittests
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
Definition: app-layer-parser.c:2090
AppLayerGetTxIterState
Definition: app-layer-parser.h:148
DNP3DecodeObject
int DNP3DecodeObject(int group, int variation, const uint8_t **buf, uint16_t *len, uint8_t prefix_code, uint32_t start, uint32_t count, DNP3PointList *points)
Decode a DNP3 object.
Definition: app-layer-dnp3-objects.c:9071
DNP3Object_::group
uint8_t group
Definition: app-layer-dnp3.h:197
DNP3ObjectG70V3_::filename
char * filename
Definition: app-layer-dnp3-objects.h:1227
SCReturnUInt
#define SCReturnUInt(x)
Definition: util-debug.h:290
conf.h
DNP3_LINK_DIR
#define DNP3_LINK_DIR(control)
Definition: app-layer-dnp3.h:75
DNP3_LINK_HDR_LEN
#define DNP3_LINK_HDR_LEN
Definition: app-layer-dnp3.c:66
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:300
DNP3ObjectG70V2_::username
char * username
Definition: app-layer-dnp3-objects.h:1213
DNP3_START_BYTE1
#define DNP3_START_BYTE1
Definition: app-layer-dnp3.c:46
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1769
DNP3Object_::start
uint32_t start
Definition: app-layer-dnp3.h:202
AppLayerGetTxIterTuple
Definition: app-layer-parser.h:159
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:292
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:329
AppLayerParserRegisterParser
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
Definition: app-layer-parser.c:460
DNP3_BANNER
#define DNP3_BANNER
Definition: app-layer-dnp3.c:265
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
crc
uint16_t crc
Definition: app-layer-dnp3.h:6
SCAppLayerProtoDetectPPRegister
void SCAppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
Definition: app-layer-detect-proto.c:1528
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:337
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:574
DNP3_DECODER_EVENT_TOO_MANY_OBJECTS
@ DNP3_DECODER_EVENT_TOO_MANY_OBJECTS
Definition: app-layer-dnp3.h:114
DNP3Transaction_::is_request
bool is_request
Definition: app-layer-dnp3.h:219
DNP3Object_::count
uint32_t count
Definition: app-layer-dnp3.h:204
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:58
SCMapEnumValueToName
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
Definition: util-enum.c:68
SCReturnStruct
#define SCReturnStruct(x)
Definition: util-debug.h:304
DNP3PointListAlloc
DNP3PointList * DNP3PointListAlloc(void)
Allocate a list for DNP3 points.
Definition: app-layer-dnp3-objects.c:45
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
DNP3State_::curr
DNP3Transaction * curr
Definition: app-layer-dnp3.h:245
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:866
DNP3ObjectG70V2_::password
char * password
Definition: app-layer-dnp3-objects.h:1214
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1528
suricata-common.h
DNP3ObjectG120V7_
Definition: app-layer-dnp3-objects.h:1348
DNP3_DECODER_EVENT_BAD_LINK_CRC
@ DNP3_DECODER_EVENT_BAD_LINK_CRC
Definition: app-layer-dnp3.h:109
DNP3_LINK_FC_CONFIRMED_USER_DATA
@ DNP3_LINK_FC_CONFIRMED_USER_DATA
Definition: app-layer-dnp3.c:70
AppLayerTxData::updated_tc
bool updated_tc
Definition: app-layer-parser.h:179
DNP3Object_::range_code
uint8_t range_code
Definition: app-layer-dnp3.h:201
SCEnumCharMap_
Definition: util-enum.h:27
TAILQ_NEXT
#define TAILQ_NEXT(elm, field)
Definition: queue.h:307
AppLayerParserRegisterStateDataFunc
void AppLayerParserRegisterStateDataFunc(uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
Definition: app-layer-parser.c:692
DNP3State_::state_data
AppLayerStateData state_data
Definition: app-layer-dnp3.h:243
DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC
@ DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC
Definition: app-layer-dnp3.h:110
AppLayerParserRegisterTxDataFunc
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
Definition: app-layer-parser.c:682
DNP3_OBJ_PREFIX
#define DNP3_OBJ_PREFIX(x)
Definition: app-layer-dnp3.c:82
DNP3Object_::prefix_code
uint8_t prefix_code
Definition: app-layer-dnp3.h:200
app-layer-events.h
util-validate.h
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
DNP3Transaction_::tx_num
uint64_t tx_num
Definition: app-layer-dnp3.h:218
AppLayerParserRegisterGetTxIterator
void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto, AppLayerGetTxIteratorFunc Func)
Definition: app-layer-parser.c:584
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:485
SCAppLayerProtoDetectPPParseConfPorts
int SCAppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
Definition: app-layer-detect-proto.c:1564
DNP3Object_::variation
uint8_t variation
Definition: app-layer-dnp3.h:198
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:33
DNP3_TH_FIR
#define DNP3_TH_FIR(x)
Definition: app-layer-dnp3.h:83
app-layer-protos.h
DNP3State_
Per flow DNP3 state.
Definition: app-layer-dnp3.h:242
suricata.h
DNP3_DEFAULT_PORT
#define DNP3_DEFAULT_PORT
Definition: app-layer-dnp3.c:42
AppLayerParserRegisterGetTxCnt
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
Definition: app-layer-parser.c:564
SCAppLayerProtoDetectConfProtoDetectionEnabledDefault
int SCAppLayerProtoDetectConfProtoDetectionEnabledDefault(const char *ipproto, const char *alproto, bool default_enabled)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:1906
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:62
AppLayerTxData::events
AppLayerDecoderEvents * events
Definition: app-layer-parser.h:224
DNP3State_::unreplied
uint32_t unreplied
Definition: app-layer-dnp3.h:248
AppLayerParserRegisterGetEventInfoById
void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfoById)(uint8_t event_id, const char **event_name, AppLayerEventType *event_type))
Definition: app-layer-parser.c:607
DNP3_LINK_FC
#define DNP3_LINK_FC(control)
Definition: app-layer-dnp3.h:79
app-layer-dnp3-objects.h
DNP3TransportHeader
uint8_t DNP3TransportHeader
DNP3 transport header.
Definition: app-layer-dnp3.h:134
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:72
DNP3Point_::prefix
uint32_t prefix
Definition: app-layer-dnp3.h:180
DNP3Transaction_::tx_data
AppLayerTxData tx_data
Definition: app-layer-dnp3.h:216
TcpSession_
Definition: stream-tcp-private.h:283
DNP3Transaction_::lh
DNP3LinkHeader lh
Definition: app-layer-dnp3.h:226
DNP3_START_BYTE0
#define DNP3_START_BYTE0
Definition: app-layer-dnp3.c:45
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:456
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-enum.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
DNP3_OBJ_RANGE
#define DNP3_OBJ_RANGE(x)
Definition: app-layer-dnp3.c:85
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
SCAppLayerGetEventIdByName
int SCAppLayerGetEventIdByName(const char *event_name, SCEnumCharMap *table, uint8_t *event_id)
Definition: app-layer-events.c:31
DNP3Point_
DNP3 object point.
Definition: app-layer-dnp3.h:179
DNP3Transaction_
DNP3 transaction.
Definition: app-layer-dnp3.h:215
AppLayerGetTxIterState::un
union AppLayerGetTxIterState::@7 un
AppLayerTxData::updated_ts
bool updated_ts
Definition: app-layer-parser.h:180
f
Flow f
Definition: fuzz_dataset.c:32
DNP3Buffer_
A struct used for buffering incoming data prior to reassembly.
Definition: app-layer-dnp3.h:157
DNP3Transaction_::buffer
uint8_t * buffer
Definition: app-layer-dnp3.h:223
DNP3_DECODER_EVENT_LEN_TOO_SMALL
@ DNP3_DECODER_EVENT_LEN_TOO_SMALL
Definition: app-layer-dnp3.h:108