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 "threads.h"
1699 
1700 /**
1701  * \brief Utility function to fix CRCs when mangling a frame.
1702  */
1703 static void DNP3FixCrc(uint8_t *data, uint32_t len)
1704 {
1705  uint32_t block_size;
1706 
1707  while (len) {
1708  if (len >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
1709  block_size = DNP3_BLOCK_SIZE;
1710  } else {
1711  block_size = len - DNP3_CRC_LEN;
1712  }
1713  uint16_t crc = DNP3ComputeCRC(data, block_size);
1714  data[block_size + 1] = (crc >> 8) & 0xff;
1715  data[block_size] = crc & 0xff;
1716  data += block_size + DNP3_CRC_LEN;
1717  len -= block_size + DNP3_CRC_LEN;
1718  }
1719 }
1720 
1721 /**
1722  * \test Test CRC checking on partial and full blocks.
1723  */
1724 static int DNP3ParserTestCheckCRC(void)
1725 {
1726  uint8_t request[] = {
1727  /* DNP3 start. */
1728  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1729  0xa5, 0xe9,
1730 
1731  /* Transport header. */
1732  0xff,
1733 
1734  /* Application layer - segment 1. */
1735  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1736  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1737  0xef,
1738 
1739  /* Application layer - segment 2. */
1740  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1741  };
1742 
1743  /* Check link header CRC. */
1744  FAIL_IF(!DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1745 
1746  /* Check first application layer segment. */
1747  FAIL_IF(!DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1749 
1750 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1751  /* Change a byte in link header, should fail now. */
1752  request[2]++;
1753  FAIL_IF(DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1754 
1755  /* Change a byte in the first application segment, should fail
1756  * now. */
1757  request[sizeof(DNP3LinkHeader) + 3]++;
1758  FAIL_IF(DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1760 #endif
1761 
1762  PASS;
1763 }
1764 
1765 /**
1766  * \test Test validation of all CRCs in user data.
1767  */
1768 static int DNP3CheckUserDataCRCsTest(void)
1769 {
1770  /* Multi-block data with valid CRCs. */
1771  uint8_t data_valid[] = {
1772  0xff, 0xc9, 0x05, 0x0c,
1773  0x01, 0x28, 0x01, 0x00,
1774  0x00, 0x00, 0x01, 0x01,
1775  0x01, 0x00, 0x00, 0x00,
1776  0x72, 0xef, /* CRC. */
1777 
1778  0xff, 0xc9, 0x05, 0x0c,
1779  0x01, 0x28, 0x01, 0x00,
1780  0x00, 0x00, 0x01, 0x01,
1781  0x01, 0x00, 0x00, 0x00,
1782  0x72, 0xef, /* CRC. */
1783 
1784  0xff, 0xc9, 0x05, 0x0c,
1785  0x01, 0x28, 0x01, 0x00,
1786  0x00, 0x00, 0x01, 0x01,
1787  0x01, 0x00, 0x00, 0x00,
1788  0x72, 0xef, /* CRC. */
1789 
1790  0x00, 0x00, 0x00, 0x00,
1791  0x00,
1792  0xff, 0xff, /* CRC. */
1793  };
1794  FAIL_IF(!DNP3CheckUserDataCRCs(data_valid, sizeof(data_valid)));
1795 
1796 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1797  /* Multi-block data with one non-crc byte altered. */
1798  uint8_t data_invalid[] = {
1799  0xff, 0xc9, 0x05, 0x0c,
1800  0x01, 0x28, 0x01, 0x00,
1801  0x00, 0x00, 0x01, 0x01,
1802  0x01, 0x00, 0x00, 0x00,
1803  0x72, 0xef, /* CRC. */
1804 
1805  0xff, 0xc9, 0x05, 0x0c,
1806  0x01, 0x28, 0x01, 0x00,
1807  0x00, 0x00, 0x01, 0x01,
1808  0x01, 0x00, 0x00, 0x00,
1809  0x72, 0xef, /* CRC. */
1810 
1811  0xff, 0xc9, 0x05, 0x0c,
1812  0x01, 0x28, 0x01, 0x00,
1813  0x00, 0x00, 0x01, 0x01,
1814  0x01, 0x00, 0x00, 0x00,
1815  0x72, 0xef, /* CRC. */
1816 
1817  0x00, 0x00, 0x00, 0x00,
1818  0x01, /* Invalid byte. */
1819  0xff, 0xff, /* CRC. */
1820  };
1821  FAIL_IF(DNP3CheckUserDataCRCs(data_invalid, sizeof(data_invalid)));
1822 
1823  /* 1 byte - need at least 3. */
1824  uint8_t one_byte_nocrc[] = { 0x01 };
1825  FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc, sizeof(one_byte_nocrc)));
1826 
1827  /* 2 bytes - need at least 3. */
1828  uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1829  FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc, sizeof(two_byte_nocrc)));
1830 #endif
1831 
1832  /* 3 bytes, valid CRC. */
1833  uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1834  *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1835  three_bytes_good_crc, 1);
1836  FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1837  sizeof(three_bytes_good_crc)));
1838 
1839  PASS;
1840 }
1841 
1842 /**
1843  * \test Test the link layer length calculation.
1844  *
1845  * Test the calculation that converts the link provided in the DNP3
1846  * header to the actual length of the frame. That is the length with
1847  * CRCs as the length in the header does not include CRCs.
1848  */
1849 static int DNP3CalculateLinkLengthTest(void)
1850 {
1851  /* These are invalid. */
1852  FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1853  FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1854  FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1855  FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1856  FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1857 
1858  /* This is the minimum size. */
1859  FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1860 
1861  /* 1 full user data blocks of data. */
1862  FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1863 
1864  /* 2 full user data blocks of data. */
1865  FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1866 
1867  /* 2 full user data blocks, plus one more byte. */
1868  /* 2 full user data blocks of data. */
1869  FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1870 
1871  /* The maximum size. */
1872  FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1873 
1874  PASS;
1875 }
1876 
1877 /**
1878  * \test The conversion of length with CRCs to the length without
1879  * CRCs.
1880  */
1881 static int DNP3CalculateTransportLengthWithoutCRCsTest(void)
1882 {
1883  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1884  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1885  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1886  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1887  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1888  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1889  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1890 
1891  /* 19 bytes is not enough for a second block. */
1892  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1893 
1894  /* 20 bytes really isn't enough either, but is large enough to
1895  * satisfy the CRC on the second block. */
1896  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1897 
1898  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1899 
1900  PASS;
1901 }
1902 
1903 /**
1904  * \test Test the validation of the link header CRC.
1905  */
1906 static int DNP3ParserCheckLinkHeaderCRC(void)
1907 {
1908  /* DNP3 frame with valid headers and CRCs. */
1909  uint8_t request[] = {
1910  /* DNP3 start. */
1911  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1912  0xa5, 0xe9,
1913 
1914  /* Transport header. */
1915  0xff,
1916 
1917  /* Application layer. */
1918  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1919  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1920  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1921  };
1922 
1923  DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1924  FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1925 
1926 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1927  /* Alter a byte in the header. */
1928  request[4] = 0;
1929  FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1930 #endif
1931 
1932  PASS;
1933 }
1934 
1935 /**
1936  * \test Test removal of CRCs from user data.
1937  */
1938 static int DNP3ReassembleApplicationLayerTest01(void)
1939 {
1940  uint16_t reassembled_len = 0;
1941  uint8_t *output = NULL;
1942 
1943  uint8_t payload[] = {
1944 
1945  0xff, 0xc9, 0x05, 0x0c,
1946  0x01, 0x28, 0x01, 0x00,
1947  0x00, 0x00, 0x01, 0x01,
1948  0x01, 0x00, 0x00, 0x00,
1949  0x72, 0xef, /* CRC. */
1950 
1951  0xff, 0xc9, 0x05, 0x0c,
1952  0x01, 0x28, 0x01, 0x00,
1953  0x00, 0x00, 0x01, 0x01,
1954  0x01, 0x00, 0x00, 0x00,
1955  0x72, 0xef, /* CRC. */
1956 
1957  0xff, 0xc9, 0x05, 0x0c,
1958  0x01, 0x28, 0x01, 0x00,
1959  0x00, 0x00, 0x01, 0x01,
1960  0x01, 0x00, 0x00, 0x00,
1961  0x72, 0xef, /* CRC. */
1962 
1963  0x00, 0x00, 0x00, 0x00,
1964  0x00,
1965  0xff, 0xff, /* CRC. */
1966  };
1967 
1968  uint8_t expected[] = {
1969  0xc9, 0x05, 0x0c,
1970  0x01, 0x28, 0x01, 0x00,
1971  0x00, 0x00, 0x01, 0x01,
1972  0x01, 0x00, 0x00, 0x00,
1973  /* CRC removed. */
1974  0xff, 0xc9, 0x05, 0x0c,
1975  0x01, 0x28, 0x01, 0x00,
1976  0x00, 0x00, 0x01, 0x01,
1977  0x01, 0x00, 0x00, 0x00,
1978  /* CRC removed. */
1979  0xff, 0xc9, 0x05, 0x0c,
1980  0x01, 0x28, 0x01, 0x00,
1981  0x00, 0x00, 0x01, 0x01,
1982  0x01, 0x00, 0x00, 0x00,
1983  /* CRC removed. */
1984  0x00, 0x00, 0x00, 0x00,
1985  0x00
1986  /* CRC removed. */
1987  };
1988 
1989  /* Valid frame. */
1990  FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1991  sizeof(payload), &output, &reassembled_len));
1992  FAIL_IF(output == NULL);
1993  FAIL_IF(reassembled_len != sizeof(expected));
1994  FAIL_IF(memcmp(expected, output, reassembled_len));
1995  SCFree(output);
1996 
1997  /* 1 byte, invalid. */
1998  reassembled_len = 0;
1999  output = NULL;
2000  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
2001  &reassembled_len));
2002  FAIL_IF(output != NULL);
2003  FAIL_IF(reassembled_len != 0);
2004 
2005  /* 2 bytes, invalid. */
2006  reassembled_len = 0;
2007  output = NULL;
2008  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
2009  &reassembled_len));
2010  FAIL_IF(output != NULL);
2011  FAIL_IF(reassembled_len != 0);
2012 
2013  /* 3 bytes, minimum - but that would only be the transport header
2014  * which isn't included in the output. */
2015  reassembled_len = 0;
2016  output = NULL;
2017  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
2018  &reassembled_len));
2019  FAIL_IF(output != NULL);
2020  FAIL_IF(reassembled_len != 0);
2021 
2022  /* 4 bytes is the minimum to get any reassembled data. */
2023  reassembled_len = 0;
2024  output = NULL;
2025  FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
2026  &reassembled_len));
2027  FAIL_IF(output == NULL);
2028  FAIL_IF(reassembled_len != 1);
2029 
2030  /* Last block too short (by 1 byte) for data + CRC. */
2031  uint8_t short_payload1[] = {
2032 
2033  0xff, 0xc9, 0x05, 0x0c,
2034  0x01, 0x28, 0x01, 0x00,
2035  0x00, 0x00, 0x01, 0x01,
2036  0x01, 0x00, 0x00, 0x00,
2037  0x72, 0xef, /* CRC. */
2038 
2039  0xff, 0xc9, 0x05, 0x0c,
2040  0x01, 0x28, 0x01, 0x00,
2041  0x00, 0x00, 0x01, 0x01,
2042  0x01, 0x00, 0x00, 0x00,
2043  0x72, 0xef, /* CRC. */
2044 
2045  0xff, 0xc9, 0x05, 0x0c,
2046  0x01, 0x28, 0x01, 0x00,
2047  0x00, 0x00, 0x01, 0x01,
2048  0x01, 0x00, 0x00, 0x00,
2049  0x72, 0xef, /* CRC. */
2050 
2051  0x00, 0x00
2052  };
2053  reassembled_len = 0;
2054  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
2055  sizeof(short_payload1), &output, &reassembled_len));
2056 
2057  /* Last block too short (by 2 bytes) for data + CRC. */
2058  uint8_t short_payload2[] = {
2059 
2060  0xff, 0xc9, 0x05, 0x0c,
2061  0x01, 0x28, 0x01, 0x00,
2062  0x00, 0x00, 0x01, 0x01,
2063  0x01, 0x00, 0x00, 0x00,
2064  0x72, 0xef, /* CRC. */
2065 
2066  0xff, 0xc9, 0x05, 0x0c,
2067  0x01, 0x28, 0x01, 0x00,
2068  0x00, 0x00, 0x01, 0x01,
2069  0x01, 0x00, 0x00, 0x00,
2070  0x72, 0xef, /* CRC. */
2071 
2072  0xff, 0xc9, 0x05, 0x0c,
2073  0x01, 0x28, 0x01, 0x00,
2074  0x00, 0x00, 0x01, 0x01,
2075  0x01, 0x00, 0x00, 0x00,
2076  0x72, 0xef, /* CRC. */
2077 
2078  0x00,
2079  };
2080  reassembled_len = 0;
2081  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
2082  sizeof(short_payload2), &output, &reassembled_len));
2083  SCFree(output);
2084  output = NULL;
2085 
2086  PASS;
2087 }
2088 
2089 /**
2090  * \test Test the probing parser.
2091  */
2092 static int DNP3ProbingParserTest(void)
2093 {
2094  uint8_t pkt[] = {
2095  0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2096  0xbd, 0x71
2097  };
2098  uint8_t rdir = 0;
2099 
2100  /* Valid frame. */
2101  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_DNP3);
2102 
2103  /* Send too little bytes. */
2104  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(DNP3LinkHeader) - 1, &rdir) != ALPROTO_UNKNOWN);
2105 
2106  /* Bad start bytes. */
2107  pkt[0] = 0x06;
2108  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2109 
2110  /* Restore start byte. */
2111  pkt[0] = 0x05;
2112 
2113  /* Set the length to a value less than the minimum length of 5. */
2114  pkt[2] = 0x03;
2115  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2116 
2117  /* Send a banner. */
2118  char mybanner[] = "Welcome to DNP3 SCADA.";
2119  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner, sizeof(mybanner) - 1,
2120  &rdir) != ALPROTO_DNP3);
2121  FAIL_IF(rdir != STREAM_TOCLIENT);
2122 
2123  PASS;
2124 }
2125 
2126 /**
2127  * \test Test a basic request/response.
2128  */
2129 static int DNP3ParserTestRequestResponse(void)
2130 {
2131  DNP3State *state = NULL;
2132 
2133  uint8_t request[] = {
2134  /* DNP3 start. */
2135  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2136  0xa5, 0xe9,
2137 
2138  /* Transport header. */
2139  0xff,
2140 
2141  /* Application layer. */
2142  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2143  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2144  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2145  };
2146 
2147  uint8_t response[] = {
2148  /* DNP3 start. */
2149  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2150  0xe2, 0x59,
2151 
2152  /* Transport header. */
2153  0xc3,
2154 
2155  /* Application layer. */
2156  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2157  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2158  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2159  0xff, 0xff
2160  };
2161 
2163  Flow flow;
2164  TcpSession ssn;
2165 
2166  memset(&flow, 0, sizeof(flow));
2167  memset(&ssn, 0, sizeof(ssn));
2168 
2169  flow.protoctx = (void *)&ssn;
2170  flow.proto = IPPROTO_TCP;
2171  flow.alproto = ALPROTO_DNP3;
2172 
2173  StreamTcpInitConfig(true);
2174 
2175  SCMutexLock(&flow.m);
2177  STREAM_TOSERVER, request, sizeof(request)));
2178  SCMutexUnlock(&flow.m);
2179 
2180  state = flow.alstate;
2181  FAIL_IF(state == NULL);
2182 
2183  DNP3Transaction *tx = DNP3GetTx(state, 0);
2184  FAIL_IF(tx == NULL);
2185  FAIL_IF(tx->tx_num != 1);
2186  FAIL_IF(tx != state->curr);
2187  FAIL_IF(tx->buffer == NULL);
2188  FAIL_IF(tx->buffer_len != 20);
2189  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2190 
2191  SCMutexLock(&flow.m);
2193  STREAM_TOCLIENT, response, sizeof(response)));
2194  SCMutexUnlock(&flow.m);
2195  DNP3Transaction *tx0 = DNP3GetTx(state, 1);
2196  FAIL_IF(tx0 == NULL);
2197  FAIL_IF(tx0 == tx);
2198  FAIL_IF(!tx0->done);
2199  FAIL_IF(tx0->buffer == NULL);
2200 
2202  StreamTcpFreeConfig(true);
2203  FLOW_DESTROY(&flow);
2204  PASS;
2205 }
2206 
2207 /**
2208  * \test Test an unsolicited response from an outstation.
2209  *
2210  * This is kind of like a request initiated from the "server".
2211  */
2212 static int DNP3ParserTestUnsolicitedResponseConfirm(void)
2213 {
2214  DNP3State *state = NULL;
2215 
2216  /* Unsolicited response with confirm bit set. */
2217  uint8_t response[] = {
2218  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2219  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2220  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2221  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2222  };
2223 
2224  /* Confirm. */
2225  uint8_t confirm[] = {
2226  0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2227  0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2228  0x3d
2229  };
2230 
2232  Flow flow;
2233  TcpSession ssn;
2234 
2235  memset(&flow, 0, sizeof(flow));
2236  memset(&ssn, 0, sizeof(ssn));
2237 
2238  flow.protoctx = (void *)&ssn;
2239  flow.proto = IPPROTO_TCP;
2240  flow.alproto = ALPROTO_DNP3;
2241 
2242  StreamTcpInitConfig(true);
2243 
2244  SCMutexLock(&flow.m);
2246  STREAM_TOCLIENT, response, sizeof(response)));
2247  SCMutexUnlock(&flow.m);
2248 
2249  state = flow.alstate;
2250  FAIL_IF(state == NULL);
2251 
2252  DNP3Transaction *tx = DNP3GetTx(state, 0);
2253  FAIL_IF(tx == NULL);
2254  FAIL_IF(tx->tx_num != 1);
2255  FAIL_IF(tx != state->curr);
2256  FAIL_IF(!tx->done);
2257  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_UNSOLICITED_RESP);
2258 
2259  SCMutexLock(&flow.m);
2261  STREAM_TOSERVER, confirm, sizeof(confirm)));
2262  SCMutexUnlock(&flow.m);
2263 
2264  /* Confirms are ignored currently. With the move to
2265  unidirectional transactions it might be easy to support these
2266  now. */
2267  DNP3Transaction *resptx = DNP3GetTx(state, 1);
2268  FAIL_IF(resptx);
2269 
2271  StreamTcpFreeConfig(true);
2272  FLOW_DESTROY(&flow);
2273  PASS;
2274 }
2275 
2276 /**
2277  * \test Test flood state.
2278  *
2279  * Note that flood state needs to revisited with the modification to a
2280  * unidirectional protocol.
2281  */
2282 static int DNP3ParserTestFlooded(void)
2283 {
2284  DNP3State *state = NULL;
2285 
2286  uint8_t request[] = {
2287  /* DNP3 start. */
2288  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2289  0xa5, 0xe9,
2290 
2291  /* Transport header. */
2292  0xff,
2293 
2294  /* Application layer. */
2295  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2296  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2297  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2298  };
2299 
2301  Flow flow;
2302  TcpSession ssn;
2303 
2304  memset(&flow, 0, sizeof(flow));
2305  memset(&ssn, 0, sizeof(ssn));
2306 
2307  flow.protoctx = (void *)&ssn;
2308  flow.proto = IPPROTO_TCP;
2309  flow.alproto = ALPROTO_DNP3;
2310 
2311  StreamTcpInitConfig(true);
2312 
2313  SCMutexLock(&flow.m);
2315  STREAM_TOSERVER, request, sizeof(request)));
2316  SCMutexUnlock(&flow.m);
2317 
2318  state = flow.alstate;
2319  FAIL_IF(state == NULL);
2320 
2321  DNP3Transaction *tx = DNP3GetTx(state, 0);
2322  FAIL_IF(tx == NULL);
2323  FAIL_IF(tx->tx_num != 1);
2324  FAIL_IF(tx != state->curr);
2325  FAIL_IF(tx->buffer == NULL);
2326  FAIL_IF(tx->buffer_len != 20);
2327  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2328  FAIL_IF_NOT(tx->done);
2329  FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2330 
2331  for (uint64_t i = 0; i < dnp3_max_tx - 1; i++) {
2332  SCMutexLock(&flow.m);
2334  STREAM_TOSERVER, request, sizeof(request)));
2335  SCMutexUnlock(&flow.m);
2336  }
2337  FAIL_IF(state->flooded);
2338  FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2339 
2340  /* One more request should trip us into flooded state. */
2341  SCMutexLock(&flow.m);
2343  STREAM_TOSERVER, request, sizeof(request)));
2344  SCMutexUnlock(&flow.m);
2345  FAIL_IF(!state->flooded);
2346 
2347  /* Progress for the oldest tx should return 1. */
2348  FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2349 
2351  StreamTcpFreeConfig(true);
2352  FLOW_DESTROY(&flow);
2353  PASS;
2354 }
2355 
2356 /**
2357  * \test Test parsing of partial frames.
2358  *
2359  * As DNP3 operates over TCP, it is possible that a partial DNP3 frame
2360  * is received. Test that the partial frame will be buffered until the
2361  * remainder is seen.
2362  */
2363 static int DNP3ParserTestPartialFrame(void)
2364 {
2365  DNP3State *state = NULL;
2366  DNP3Transaction *tx;
2367  int r;
2368 
2369  uint8_t request_partial1[] = {
2370  /* DNP3 start. */
2371  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2372  0xa5, 0xe9,
2373 
2374  /* Transport header. */
2375  0xff,
2376 
2377  /* Application layer. */
2378  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2379  };
2380 
2381  uint8_t request_partial2[] = {
2382  /* Remainder of application layer. */
2383  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2384  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2385  };
2386 
2387  uint8_t response_partial1[] = {
2388  /* DNP3 start. */
2389  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2390  0xe2, 0x59,
2391 
2392  /* Transport header. */
2393  0xc3,
2394 
2395  /* Application layer. */
2396  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2397  };
2398 
2399  uint8_t response_partial2[] = {
2400  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2401  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2402  0xff, 0xff
2403  };
2404 
2405  /* Boiler plate for app layer setup. */
2407  Flow flow;
2408  TcpSession ssn;
2409  memset(&flow, 0, sizeof(flow));
2410  memset(&ssn, 0, sizeof(ssn));
2411  flow.protoctx = (void *)&ssn;
2412  flow.proto = IPPROTO_TCP;
2413  flow.alproto = ALPROTO_DNP3;
2414  StreamTcpInitConfig(true);
2415 
2416  /* Pass in the first partial frame. */
2417 
2418  SCMutexLock(&flow.m);
2419  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2420  STREAM_TOSERVER, request_partial1, sizeof(request_partial1));
2421  SCMutexUnlock(&flow.m);
2422  FAIL_IF(r != 0);
2423 
2424  /* Frame should just be buffered, but not yet processed. */
2425  state = flow.alstate;
2426  FAIL_IF(state == NULL);
2427  FAIL_IF(state->request_buffer.len != sizeof(request_partial1));
2428  FAIL_IF(state->request_buffer.offset != 0);
2429  FAIL_IF(memcmp(state->request_buffer.buffer, request_partial1,
2430  sizeof(request_partial1)));
2431 
2432  /* There should not be a transaction yet. */
2433  FAIL_IF(state->transaction_max != 0);
2434  FAIL_IF(DNP3GetTx(state, 0) != NULL);
2435 
2436  /* Send the second partial. */
2437  SCMutexLock(&flow.m);
2438  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2439  STREAM_TOSERVER, request_partial2, sizeof(request_partial2));
2440  SCMutexUnlock(&flow.m);
2441  FAIL_IF(r != 0);
2442 
2443  /* The second partial completed the frame, the buffer should now
2444  * be clear. */
2445  FAIL_IF(state->request_buffer.len != 0);
2446  FAIL_IF(state->request_buffer.offset != 0);
2447 
2448  /* Should now have a complete transaction. */
2449  tx = DNP3GetTx(state, 0);
2450  FAIL_IF(tx == NULL);
2451  FAIL_IF(tx->tx_num != 1);
2452  FAIL_IF(tx != state->curr);
2453  FAIL_IF(tx->buffer == NULL);
2454  FAIL_IF(tx->buffer_len != 20);
2455  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2456 
2457  /* Send partial response. */
2458  SCMutexLock(&flow.m);
2459  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2460  STREAM_TOCLIENT, response_partial1, sizeof(response_partial1));
2461  SCMutexUnlock(&flow.m);
2462  FAIL_IF(r != 0);
2463  FAIL_IF(state->response_buffer.len != sizeof(response_partial1));
2464  FAIL_IF(state->response_buffer.offset != 0);
2465  tx = DNP3GetTx(state, 1);
2466  FAIL_IF_NOT_NULL(tx);
2467 
2468  /* Send rest of response. */
2469  SCMutexLock(&flow.m);
2470  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2471  STREAM_TOCLIENT, response_partial2, sizeof(response_partial2));
2472  SCMutexUnlock(&flow.m);
2473  FAIL_IF(r != 0);
2474 
2475  /* Buffer should now be empty. */
2476  FAIL_IF(state->response_buffer.len != 0);
2477  FAIL_IF(state->response_buffer.offset != 0);
2478 
2479  /* There should now be a response transaction. */
2480  tx = DNP3GetTx(state, 1);
2481  FAIL_IF_NULL(tx);
2482  FAIL_IF(tx->buffer == NULL);
2483  FAIL_IF(tx->buffer_len == 0);
2484 
2486  StreamTcpFreeConfig(true);
2487  FLOW_DESTROY(&flow);
2488  PASS;
2489 }
2490 
2491 /**
2492  * \test Test multiple DNP3 frames in one TCP read.
2493  */
2494 static int DNP3ParserTestMultiFrame(void)
2495 {
2496  DNP3State *state = NULL;
2497 
2498  /* Unsolicited response 1. */
2499  uint8_t unsol_response1[] = {
2500  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2501  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2502  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2503  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2504  };
2505 
2506  /* Unsolicited response 2. */
2507  uint8_t unsol_response2[] = {
2508  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2509  0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2510  0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2511  0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2512  };
2513 
2514  uint8_t combined[sizeof(unsol_response1) + sizeof(unsol_response2)];
2515  memcpy(combined, unsol_response1, sizeof(unsol_response1));
2516  memcpy(combined + sizeof(unsol_response1), unsol_response2,
2517  sizeof(unsol_response2));
2518 
2519  /* Setup. */
2521  Flow flow;
2522  TcpSession ssn;
2523  int r;
2524  memset(&flow, 0, sizeof(flow));
2525  memset(&ssn, 0, sizeof(ssn));
2526  flow.protoctx = (void *)&ssn;
2527  flow.proto = IPPROTO_TCP;
2528  flow.alproto = ALPROTO_DNP3;
2529  StreamTcpInitConfig(true);
2530 
2531  SCMutexLock(&flow.m);
2532  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2533  STREAM_TOCLIENT, combined, sizeof(combined));
2534  SCMutexUnlock(&flow.m);
2535  FAIL_IF(r != 0);
2536 
2537  state = flow.alstate;
2538  FAIL_IF(state == NULL);
2539  FAIL_IF(state->transaction_max != 2);
2540 
2542  StreamTcpFreeConfig(true);
2543  FLOW_DESTROY(&flow);
2544  PASS;
2545 }
2546 
2547 /**
2548  * \test Test the parsing of a request PDU.
2549  *
2550  * The PDU under test contains a single read request object:
2551  * - Group: 1
2552  * - Variation: 0
2553  * - Count: 0
2554  */
2555 static int DNP3ParserTestParsePDU01(void)
2556 {
2557  /* Frame to be tested. This frame is a DNP3 request with one read
2558  * request data object, group 1, variation 0. */
2559  const uint8_t pkt[] = {
2560  0x05, 0x64,
2561  0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2562  0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2563  };
2564 
2565  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2566  int pdus = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2567  FAIL_IF(pdus < 1);
2568  DNP3Transaction *dnp3tx = DNP3GetTx(dnp3state, 0);
2569  FAIL_IF_NULL(dnp3tx);
2570  FAIL_IF(!dnp3tx->is_request);
2571  FAIL_IF(TAILQ_EMPTY(&dnp3tx->objects));
2572  DNP3Object *object = TAILQ_FIRST(&dnp3tx->objects);
2573  FAIL_IF(object->group != 1 || object->variation != 0);
2574  FAIL_IF(object->count != 0);
2575 
2576  DNP3StateFree(dnp3state);
2577  PASS;
2578 }
2579 
2580 /**
2581  * \test Ensure variable-length DNP3 objects do not embed maximum-sized buffers.
2582  */
2583 static int DNP3ParserObjectStructSizeTest(void)
2584 {
2585  const size_t max_point_size = 1024;
2586 
2587  FAIL_IF(sizeof(DNP3ObjectG70V1) >= max_point_size);
2588  FAIL_IF(sizeof(DNP3ObjectG70V2) >= max_point_size);
2589  FAIL_IF(sizeof(DNP3ObjectG70V3) >= max_point_size);
2590  FAIL_IF(sizeof(DNP3ObjectG70V7) >= max_point_size);
2591  FAIL_IF(sizeof(DNP3ObjectG70V8) >= max_point_size);
2592  FAIL_IF(sizeof(DNP3ObjectG120V7) >= max_point_size);
2593  FAIL_IF(sizeof(DNP3ObjectG120V10) >= max_point_size);
2594  FAIL_IF(sizeof(DNP3ObjectG120V11) >= max_point_size);
2595 
2596  PASS;
2597 }
2598 
2599 /**
2600  * \test Decode non-empty dynamically allocated G70V2 strings.
2601  */
2602 static int DNP3ParserDecodeG70V2Test(void)
2603 {
2604  const uint8_t input[] = {
2605  0x00,
2606  0x00,
2607  0x03,
2608  0x00,
2609  0x00,
2610  0x00,
2611  0x06,
2612  0x00,
2613  0x78,
2614  0x56,
2615  0x34,
2616  0x12,
2617  'b',
2618  'o',
2619  'b',
2620  's',
2621  'e',
2622  'c',
2623  'r',
2624  'e',
2625  't',
2626  };
2627  const uint8_t *buf = input;
2628  uint16_t len = sizeof(input);
2629  DNP3PointList *points = DNP3PointListAlloc();
2630  FAIL_IF_NULL(points);
2631 
2632  int event = DNP3DecodeObject(70, 2, &buf, &len, 0, 0, 1, points);
2633  FAIL_IF(event != 0);
2634  FAIL_IF(len != 0);
2635  DNP3Point *point = TAILQ_FIRST(points);
2636  FAIL_IF_NULL(point);
2637  DNP3ObjectG70V2 *data = point->data;
2638  FAIL_IF_NULL(data);
2639  FAIL_IF(strcmp(data->username, "bob") != 0);
2640  FAIL_IF(strcmp(data->password, "secret") != 0);
2641  FAIL_IF(data->authentication_key != 0x12345678);
2642 
2643  DNP3FreeObjectPointList(70, 2, points);
2644  PASS;
2645 }
2646 
2647 /**
2648  * \test Clean up an allocated G70V2 username when the password is truncated.
2649  */
2650 static int DNP3ParserDecodeG70V2TruncatedTest(void)
2651 {
2652  const uint8_t input[] = {
2653  0x00,
2654  0x00,
2655  0x03,
2656  0x00,
2657  0x00,
2658  0x00,
2659  0x06,
2660  0x00,
2661  0x78,
2662  0x56,
2663  0x34,
2664  0x12,
2665  'b',
2666  'o',
2667  'b',
2668  's',
2669  'e',
2670  'c',
2671  };
2672  const uint8_t *buf = input;
2673  uint16_t len = sizeof(input);
2674  DNP3PointList *points = DNP3PointListAlloc();
2675  FAIL_IF_NULL(points);
2676 
2677  int event = DNP3DecodeObject(70, 2, &buf, &len, 0, 0, 1, points);
2679  FAIL_IF_NOT(TAILQ_EMPTY(points));
2680 
2681  DNP3FreeObjectPointList(70, 2, points);
2682  PASS;
2683 }
2684 
2685 /**
2686  * \test Test the decode of a DNP3 fragment with a single 70:3 object.
2687  */
2688 static int DNP3ParserDecodeG70V3Test(void)
2689 {
2690  const uint8_t pkt[] = {
2691  0x05, 0x64,
2692  0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2693  0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2694  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2695  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2696  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2697  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2698  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2699  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2700  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2701  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2702  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2703  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2704  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2705  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2706  0xc4, 0x8b
2707  };
2708 
2709  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2710  FAIL_IF_NULL(dnp3state);
2711  int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2712  FAIL_IF(bytes != sizeof(pkt));
2713  DNP3Transaction *tx = DNP3GetTx(dnp3state, 0);
2714  FAIL_IF_NULL(tx);
2715  FAIL_IF_NOT(tx->is_request);
2716  DNP3Object *obj = TAILQ_FIRST(&tx->objects);
2717  FAIL_IF_NULL(obj);
2718  FAIL_IF_NOT(obj->group == 70);
2719  FAIL_IF_NOT(obj->variation == 3);
2720  FAIL_IF_NOT(obj->prefix_code == 0x5);
2721  FAIL_IF_NOT(obj->range_code == 0xb);
2722  FAIL_IF_NOT(obj->count == 1);
2723  DNP3Point *point = TAILQ_FIRST(obj->points);
2724  FAIL_IF_NULL(point);
2725  FAIL_IF_NOT(point->prefix == 85);
2726  FAIL_IF_NOT(point->size == 85);
2727  FAIL_IF_NULL(point->data);
2728  DNP3ObjectG70V3 *data = point->data;
2729  FAIL_IF_NOT(strcmp(
2730  data->filename,
2731  "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2732  DNP3StateFree(dnp3state);
2733  PASS;
2734 }
2735 
2736 /**
2737  * \brief Test that an alert is raised on an unknown object.
2738  */
2739 static int DNP3ParserUnknownEventAlertTest(void)
2740 {
2741  /* Valid DNP3 frame with 70:3 object. */
2742  uint8_t pkt[] = {
2743  0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2744  0xc7, 0xee,
2745 
2746  0xc7, 0xc9, 0x1b,
2747 
2748  /* Object and variation. Originally 70:3, now 70:99, an
2749  * unknown object. */
2750  0x46, 0x63,
2751 
2752  0x5b, 0x01, 0x55,
2753  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2754  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2755  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2756  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2757  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2758  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2759  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2760  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2761  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2762  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2763  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2764  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2765  0xc4, 0x8b
2766  };
2767 
2768  DNP3FixCrc(pkt + 10, sizeof(pkt) - 10);
2769 
2770  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2771  FAIL_IF_NULL(dnp3state);
2772  int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2773  FAIL_IF(bytes != sizeof(pkt));
2774 
2775  DNP3StateFree(dnp3state);
2776  PASS;
2777 }
2778 
2779 /**
2780 * \brief Test that an alert is raised on incorrect data.
2781 */
2782 static int DNP3ParserIncorrectUserData(void)
2783 {
2784  uint8_t packet_bytes[] = {
2785  0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2786  0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2787  };
2788 
2790  Flow flow;
2791  TcpSession ssn;
2792  memset(&flow, 0, sizeof(flow));
2793  memset(&ssn, 0, sizeof(ssn));
2794  flow.protoctx = (void *)&ssn;
2795  flow.proto = IPPROTO_TCP;
2796  flow.alproto = ALPROTO_DNP3;
2797  StreamTcpInitConfig(true);
2798 
2799  int r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2800  STREAM_TOCLIENT, packet_bytes, sizeof(packet_bytes));
2801 
2802  FAIL_IF(r != 0);
2803 
2805  StreamTcpFreeConfig(true);
2806  FLOW_DESTROY(&flow);
2807  PASS;
2808 }
2809 
2810 #endif
2811 
2813 {
2814 #ifdef UNITTESTS
2815  UtRegisterTest("DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2816  UtRegisterTest("DNP3ParserCheckLinkHeaderCRC",
2817  DNP3ParserCheckLinkHeaderCRC);
2818  UtRegisterTest("DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2819  UtRegisterTest("DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2820  UtRegisterTest("DNP3CalculateTransportLengthWithoutCRCsTest",
2821  DNP3CalculateTransportLengthWithoutCRCsTest);
2822  UtRegisterTest("DNP3ReassembleApplicationLayerTest01",
2823  DNP3ReassembleApplicationLayerTest01);
2824  UtRegisterTest("DNP3ProbingParserTest", DNP3ProbingParserTest);
2825  UtRegisterTest("DNP3ParserTestRequestResponse",
2826  DNP3ParserTestRequestResponse);
2827  UtRegisterTest("DNP3ParserTestUnsolicitedResponseConfirm",
2828  DNP3ParserTestUnsolicitedResponseConfirm);
2829  UtRegisterTest("DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2830  UtRegisterTest("DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2831  UtRegisterTest("DNP3ParserTestFlooded", DNP3ParserTestFlooded);
2832  UtRegisterTest("DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2833  UtRegisterTest("DNP3ParserObjectStructSizeTest", DNP3ParserObjectStructSizeTest);
2834  UtRegisterTest("DNP3ParserDecodeG70V2Test", DNP3ParserDecodeG70V2Test);
2835  UtRegisterTest("DNP3ParserDecodeG70V2TruncatedTest", DNP3ParserDecodeG70V2TruncatedTest);
2836  UtRegisterTest("DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2837  UtRegisterTest("DNP3ParserUnknownEventAlertTest",
2838  DNP3ParserUnknownEventAlertTest);
2839  UtRegisterTest("DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);
2840 #endif
2841 }
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:101
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:381
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:87
DNP3ParserRegisterTests
void DNP3ParserRegisterTests(void)
Definition: app-layer-dnp3.c:2812
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:359
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:438
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
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:496
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:440
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:443
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:293
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:864
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:484
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:455
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