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