suricata
app-layer-dnp3.c
Go to the documentation of this file.
1 /* Copyright (C) 2015-2025 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * DNP3 protocol implementation
22  */
23 
24 #include "suricata-common.h"
25 #include "suricata.h"
26 #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 #include "app-layer-events.h"
36 
37 #include "app-layer-dnp3.h"
38 #include "app-layer-dnp3-objects.h"
39 
40 /* Default number of unreplied requests to be considered a flood. */
41 #define DNP3_DEFAULT_REQ_FLOOD_COUNT 500
42 
43 #define DNP3_DEFAULT_PORT "20000"
44 
45 /* Expected values for the start bytes. */
46 #define DNP3_START_BYTE0 0x05
47 #define DNP3_START_BYTE1 0x64
48 
49 /* Minimum length for a DNP3 frame. */
50 #define DNP3_MIN_LEN 5
51 
52 /* Length of each CRC. */
53 #define DNP3_CRC_LEN 2
54 
55 /* DNP3 block size. After the link header a CRC is inserted after
56  * after 16 bytes of data. */
57 #define DNP3_BLOCK_SIZE 16
58 
59 /* Maximum transport layer sequence number. */
60 #define DNP3_MAX_TRAN_SEQNO 64
61 
62 /* Maximum application layer sequence number. */
63 // unused #define DNP3_MAX_APP_SEQNO 16
64 
65 /* The number of bytes in the header that are counted as part of the
66  * header length field. */
67 #define DNP3_LINK_HDR_LEN 5
68 
69 /* Link function codes. */
70 enum {
73 };
74 
75 /* Reserved addresses. */
76 // unused #define DNP3_RESERVED_ADDR_MIN 0xfff0
77 // unused #define DNP3_RESERVED_ADDR_MAX 0xfffb
78 
79 /* Source addresses must be < 0xfff0. */
80 // unused #define DNP3_SRC_ADDR_MAX 0xfff0
81 
82 /* Extract the prefix code from the object qualifier. */
83 #define DNP3_OBJ_PREFIX(x) ((x >> 4) & 0x7)
84 
85 /* Extract the range code from the object qualifier. */
86 #define DNP3_OBJ_RANGE(x) (x & 0xf)
87 
88 /* Decoder event map. */
90  {"FLOODED", DNP3_DECODER_EVENT_FLOODED},
91  {"LEN_TOO_SMALL", DNP3_DECODER_EVENT_LEN_TOO_SMALL},
92  {"BAD_LINK_CRC", DNP3_DECODER_EVENT_BAD_LINK_CRC},
93  {"BAD_TRANSPORT_CRC", DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC},
94  {"MALFORMED", DNP3_DECODER_EVENT_MALFORMED},
95  {"UNKNOWN_OBJECT", DNP3_DECODER_EVENT_UNKNOWN_OBJECT},
96  {NULL, -1},
97 };
98 
99 /* Calculate the next transport sequence number. */
100 #define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
101 
102 /* CRC table generated by pycrc - http://github.com/tpircher/pycrc.
103  * - Polynomial: 0x3d65. */
104 static const uint16_t crc_table[256] = {
105  0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
106  0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
107  0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
108  0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
109  0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
110  0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
111  0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
112  0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
113  0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
114  0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
115  0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
116  0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
117  0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
118  0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
119  0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
120  0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
121  0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
122  0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
123  0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
124  0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
125  0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
126  0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
127  0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
128  0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
129  0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
130  0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
131  0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
132  0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
133  0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
134  0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
135  0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
136  0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
137 };
138 
139 /**
140  * \brief Compute the CRC for a buffer.
141  *
142  * \param buf Buffer to create CRC from.
143  * \param len Length of buffer (number of bytes to use for CRC).
144 
145  */
146 static uint16_t DNP3ComputeCRC(const uint8_t *buf, uint32_t len)
147 {
148  const uint8_t *byte = buf;
149  uint16_t crc = 0;
150  int idx;
151 
152  while (len--) {
153  idx = (crc ^ *byte) & 0xff;
154  crc = (crc_table[idx] ^ (crc >> 8)) & 0xffff;
155  byte++;
156  }
157 
158  return ~crc & 0xffff;
159 }
160 
161 /**
162  * \brief Check the CRC of a block.
163  *
164  * \param block The block of data with CRC to be checked.
165  * \param len The size of the data block.
166  *
167  * \retval 1 if CRC is OK, otherwise 0.
168  */
169 static int DNP3CheckCRC(const uint8_t *block, uint32_t len)
170 {
171 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
172  return 1;
173 #endif
174  uint32_t crc_offset;
175  uint16_t crc;
176 
177  /* Need at least one byte plus the CRC. */
178  if (len < DNP3_CRC_LEN + 1) {
179  return 0;
180  }
181 
182  crc_offset = len - DNP3_CRC_LEN;
183  crc = DNP3ComputeCRC(block, len - DNP3_CRC_LEN);
184  if (((crc & 0xff) == block[crc_offset]) &&
185  ((crc >> 8) == block[crc_offset + 1])) {
186  return 1;
187  }
188 
189  return 0;
190 }
191 
192 /**
193  * \brief Check the CRC of the link header.
194  *
195  * \param header Point to the link header.
196  *
197  * \retval 1 if header CRC is OK, otherwise 0.
198  */
199 static int DNP3CheckLinkHeaderCRC(const DNP3LinkHeader *header)
200 {
201  return DNP3CheckCRC((uint8_t *)header, sizeof(DNP3LinkHeader));
202 }
203 
204 /**
205  * \brief Check user data CRCs.
206  *
207  * \param data Pointer to user data.
208  * \param len Length of user data.
209  *
210  * \retval 1 if CRCs are OK, otherwise 0.
211  */
212 static int DNP3CheckUserDataCRCs(const uint8_t *data, uint32_t len)
213 {
214  uint32_t offset = 0;
215  uint32_t block_size;
216 
217  while (offset < len) {
218  if (len - offset >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
219  block_size = DNP3_BLOCK_SIZE + DNP3_CRC_LEN;
220  }
221  else {
222  block_size = len - offset;
223  }
224 
225  if (!DNP3CheckCRC(data + offset, block_size)) {
226  /* Once failed, may as well return immediately. */
227  return 0;
228  }
229 
230  offset += block_size;
231  }
232 
233  return 1;
234 }
235 
236 /**
237  * \brief Check the DNP3 frame start bytes.
238  *
239  * \retval 1 if valid, 0 if not.
240  */
241 static int DNP3CheckStartBytes(const DNP3LinkHeader *header)
242 {
243  return header->start_byte0 == DNP3_START_BYTE0 &&
244  header->start_byte1 == DNP3_START_BYTE1;
245 }
246 
247 /* Some DNP3 servers start with a banner. */
248 #define DNP3_BANNER "DNP3"
249 
250 /**
251  * \brief Check if a frame contains a banner.
252  *
253  * Some servers (outstations) appear to send back a banner that fails
254  * the normal frame checks. So first check for a banner.
255  *
256  * \retval 1 if a banner is found, 0 if not.
257  */
258 static int DNP3ContainsBanner(const uint8_t *input, uint32_t len)
259 {
260  return BasicSearch(input, len, (uint8_t *)DNP3_BANNER, strlen(DNP3_BANNER)) != NULL;
261 }
262 
263 /**
264  * \brief DNP3 probing parser.
265  */
266 static uint16_t DNP3ProbingParser(
267  const Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, 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) {
498  } else {
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(
853  Flow *f, DNP3State *dnp3, const uint8_t *input, 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->tx_data.updated_ts = true;
902  tx->lh = *lh;
903  tx->th = th;
904  tx->ah = *ah;
905  }
906 
907  if (!DNP3ReassembleApplicationLayer(input + sizeof(DNP3LinkHeader),
908  input_len - sizeof(DNP3LinkHeader), &tx->buffer, &tx->buffer_len)) {
909 
910  /* Malformed, set event and mark as done. */
911  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_MALFORMED);
912  tx->done = 1;
913  return;
914  }
915 
916  /* If this is not the final segment, just return. */
917  if (!DNP3_TH_FIN(th)) {
918  return;
919  }
920 
921  tx->done = 1;
922 
923  if (DNP3DecodeApplicationObjects(tx, tx->buffer + sizeof(DNP3ApplicationHeader),
924  tx->buffer_len - sizeof(DNP3ApplicationHeader), &tx->objects)) {
925  tx->complete = 1;
926  }
927  if (f != NULL) {
928  AppLayerParserTriggerRawStreamInspection(f, STREAM_TOSERVER);
929  }
930 }
931 
932 static void DNP3HandleUserDataResponse(
933  Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
934 {
935  DNP3LinkHeader *lh;
937  DNP3ApplicationHeader *ah;
938  DNP3InternalInd *iin;
939  DNP3Transaction *tx = NULL, *ttx;
940  uint32_t offset = 0;
941 
942  lh = (DNP3LinkHeader *)input;
943  offset += sizeof(DNP3LinkHeader);
944 
945  if (!DNP3CheckUserDataCRCs(input + offset, input_len - offset)) {
946  return;
947  }
948 
949  th = input[offset++];
950 
951  if (!DNP3_TH_FIR(th)) {
952  TAILQ_FOREACH(ttx, &dnp3->tx_list, next) {
953  if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
954  !ttx->done && NEXT_TH_SEQNO(DNP3_TH_SEQ(ttx->th)) == DNP3_TH_SEQ(th)) {
955  tx = ttx;
956  break;
957  }
958  }
959 
960  if (tx == NULL) {
961  return;
962  }
963 
964  /* Replace the transport header in the transaction with this
965  * one in case there are more frames. */
966  tx->th = th;
967  tx->tx_data.updated_tc = true;
968  }
969  else {
970  ah = (DNP3ApplicationHeader *)(input + offset);
971  offset += sizeof(DNP3ApplicationHeader);
972  iin = (DNP3InternalInd *)(input + offset);
973 
974  tx = DNP3TxAlloc(dnp3, false);
975  if (unlikely(tx == NULL)) {
976  return;
977  }
978  tx->tx_data.updated_tc = true;
979  tx->lh = *lh;
980  tx->th = th;
981  tx->ah = *ah;
982  tx->iin = *iin;
983  }
984 
985  BUG_ON(tx->is_request);
986 
987  if (!DNP3ReassembleApplicationLayer(input + sizeof(DNP3LinkHeader),
988  input_len - sizeof(DNP3LinkHeader), &tx->buffer, &tx->buffer_len)) {
989  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_MALFORMED);
990  return;
991  }
992 
993  if (!DNP3_TH_FIN(th)) {
994  return;
995  }
996 
997  tx->done = 1;
998 
999  offset = sizeof(DNP3ApplicationHeader) + sizeof(DNP3InternalInd);
1000  if (DNP3DecodeApplicationObjects(
1001  tx, tx->buffer + offset, tx->buffer_len - offset, &tx->objects)) {
1002  tx->complete = 1;
1003  }
1004  if (f != NULL) {
1005  AppLayerParserTriggerRawStreamInspection(f, STREAM_TOCLIENT);
1006  }
1007 }
1008 
1009 /**
1010  * \brief Decode the DNP3 request link layer.
1011  *
1012  * \retval number of bytes processed or -1 if the data stream does not look
1013  * like DNP3.
1014  */
1015 static int DNP3HandleRequestLinkLayer(
1016  Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
1017 {
1018  SCEnter();
1019  uint32_t processed = 0;
1020 
1021  while (input_len) {
1022 
1023  /* Need at least enough bytes for a DNP3 header. */
1024  if (input_len < sizeof(DNP3LinkHeader)) {
1025  break;
1026  }
1027 
1028  DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1029 
1030  if (!DNP3CheckStartBytes(header)) {
1031  goto error;
1032  }
1033 
1034  if (!DNP3CheckLinkHeaderCRC(header)) {
1035  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_LINK_CRC);
1036  goto error;
1037  }
1038 
1039  uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1040  if (frame_len == 0) {
1041  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1042  goto error;
1043  }
1044  if (input_len < frame_len) {
1045  /* Insufficient data, just break - will wait for more data. */
1046  break;
1047  }
1048 
1049  /* Ignore non-user data for now. */
1050  if (!DNP3IsUserData(header)) {
1051  goto next;
1052  }
1053 
1054  /* Make sure the header length is large enough for transport and
1055  * application headers. */
1056  if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1057  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1058  goto next;
1059  }
1060 
1061  if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
1062  frame_len - sizeof(DNP3LinkHeader))) {
1063  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC);
1064  goto next;
1065  }
1066 
1067  DNP3HandleUserDataRequest(f, dnp3, input, frame_len);
1068 
1069  next:
1070  /* Advance the input buffer. */
1071  input += frame_len;
1072  input_len -= frame_len;
1073  processed += frame_len;
1074  }
1075 
1076  SCReturnInt(processed);
1077 error:
1078  /* Error out. Should only happen if this doesn't look like a DNP3
1079  * frame. */
1080  SCReturnInt(-1);
1081 }
1082 
1083 /**
1084  * \brief Handle incoming request data.
1085  *
1086  * The actual request PDU parsing is done in
1087  * DNP3HandleRequestLinkLayer. This function takes care of buffering TCP
1088  * date if a segment does not contain a complete frame (or contains
1089  * multiple frames, but not the complete final frame).
1090  */
1091 static AppLayerResult DNP3ParseRequest(Flow *f, void *state, AppLayerParserState *pstate,
1092  StreamSlice stream_slice, void *local_data)
1093 {
1094  SCEnter();
1095  DNP3State *dnp3 = (DNP3State *)state;
1096  DNP3Buffer *buffer = &dnp3->request_buffer;
1097  int processed = 0;
1098 
1099  const uint8_t *input = StreamSliceGetData(&stream_slice);
1100  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1101 
1102  if (input_len == 0) {
1104  }
1105 
1106  if (buffer->len) {
1107  if (!DNP3BufferAdd(buffer, input, input_len)) {
1108  goto error;
1109  }
1110  processed = DNP3HandleRequestLinkLayer(
1111  f, dnp3, buffer->buffer + buffer->offset, buffer->len - buffer->offset);
1112  if (processed < 0) {
1113  goto error;
1114  }
1115  buffer->offset += processed;
1116  DNP3BufferTrim(buffer);
1117  }
1118  else {
1119  processed = DNP3HandleRequestLinkLayer(f, dnp3, input, input_len);
1120  if (processed < 0) {
1121  SCLogDebug("Failed to process request link layer.");
1122  goto error;
1123  }
1124 
1125  input += processed;
1126  input_len -= processed;
1127 
1128  /* Not all data was processed, buffer it. */
1129  if (input_len) {
1130  if (!DNP3BufferAdd(buffer, input, input_len)) {
1131  goto error;
1132  }
1133  }
1134  }
1135 
1137 
1138 error:
1139  /* Reset the buffer. */
1140  DNP3BufferReset(buffer);
1142 }
1143 
1144 /**
1145  * \brief Decode the DNP3 response link layer.
1146  *
1147  * \retval number of bytes processed or -1 if the data stream does not
1148  * like look DNP3.
1149  */
1150 static int DNP3HandleResponseLinkLayer(
1151  Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
1152 {
1153  SCEnter();
1154  uint32_t processed = 0;
1155 
1156  while (input_len) {
1157 
1158  /* Need at least enough bytes for a DNP3 header. */
1159  if (input_len < sizeof(DNP3LinkHeader)) {
1160  break;
1161  }
1162 
1163  DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1164 
1165  if (!DNP3CheckStartBytes(header)) {
1166  goto error;
1167  }
1168 
1169  if (!DNP3CheckLinkHeaderCRC(header)) {
1170  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_LINK_CRC);
1171  goto error;
1172  }
1173 
1174  /* Calculate the number of bytes needed to for this frame. */
1175  uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1176  if (frame_len == 0) {
1177  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1178  goto error;
1179  }
1180  if (input_len < frame_len) {
1181  /* Insufficient data, just break - will wait for more data. */
1182  break;
1183  }
1184 
1185  /* Only handle user data frames for now. */
1186  if (!DNP3IsUserData(header)) {
1187  goto next;
1188  }
1189 
1190  /* Make sure the header length is large enough for transport and
1191  * application headers. */
1192  if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1193  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1194  goto error;
1195  }
1196 
1197  if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
1198  frame_len - sizeof(DNP3LinkHeader))) {
1199  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC);
1200  goto next;
1201  }
1202 
1203  DNP3HandleUserDataResponse(f, dnp3, input, frame_len);
1204 
1205  next:
1206  /* Advance the input buffer. */
1207  input += frame_len;
1208  input_len -= frame_len;
1209  processed += frame_len;
1210  }
1211 
1212  SCReturnInt(processed);
1213 error:
1214  /* Error out. Should only happen if the data stream no longer
1215  * looks like DNP3. */
1216  SCReturnInt(-1);
1217 }
1218 
1219 /**
1220  * \brief Parse incoming data.
1221  *
1222  * This is the entry function for DNP3 application layer data. Its
1223  * main responsibility is buffering incoming data that cannot be
1224  * processed.
1225  *
1226  * See DNP3ParseResponsePDUs for DNP3 frame handling.
1227  */
1228 static AppLayerResult DNP3ParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
1229  StreamSlice stream_slice, void *local_data)
1230 {
1231  SCEnter();
1232 
1233  DNP3State *dnp3 = (DNP3State *)state;
1234  DNP3Buffer *buffer = &dnp3->response_buffer;
1235  int processed;
1236 
1237  const uint8_t *input = StreamSliceGetData(&stream_slice);
1238  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1239 
1240  if (buffer->len) {
1241  if (!DNP3BufferAdd(buffer, input, input_len)) {
1242  goto error;
1243  }
1244  processed = DNP3HandleResponseLinkLayer(
1245  f, dnp3, buffer->buffer + buffer->offset, buffer->len - buffer->offset);
1246  if (processed < 0) {
1247  goto error;
1248  }
1249  buffer->offset += processed;
1250  DNP3BufferTrim(buffer);
1251  }
1252  else {
1253 
1254  /* Check if this is a banner, ignore if it is. */
1255  if (DNP3ContainsBanner(input, input_len)) {
1256  goto done;
1257  }
1258 
1259  processed = DNP3HandleResponseLinkLayer(f, dnp3, input, input_len);
1260  if (processed < 0) {
1261  goto error;
1262  }
1263  input += processed;
1264  input_len -= processed;
1265 
1266  /* Not all data was processed, buffer it. */
1267  if (input_len) {
1268  if (!DNP3BufferAdd(buffer, input, input_len)) {
1269  goto error;
1270  }
1271  }
1272  }
1273 
1274 done:
1276 
1277 error:
1278  /* An error occurred while processing DNP3 frames. Dump the
1279  * buffer as we can't be assured that they are valid anymore. */
1280  DNP3BufferReset(buffer);
1282 }
1283 
1284 static void *DNP3GetTx(void *alstate, uint64_t tx_id)
1285 {
1286  SCEnter();
1287  DNP3State *dnp3 = (DNP3State *)alstate;
1288  DNP3Transaction *tx = NULL;
1289  uint64_t tx_num = tx_id + 1;
1290 
1291  if (dnp3->curr && dnp3->curr->tx_num == (tx_num)) {
1292  SCReturnPtr(dnp3->curr, "void");
1293  }
1294 
1295  TAILQ_FOREACH(tx, &dnp3->tx_list, next) {
1296  if (tx_num != tx->tx_num) {
1297  continue;
1298  }
1299  SCReturnPtr(tx, "void");
1300  }
1301 
1302  SCReturnPtr(NULL, "void");
1303 }
1304 
1305 static uint64_t DNP3GetTxCnt(void *state)
1306 {
1307  SCEnter();
1308  uint64_t count = ((uint64_t)((DNP3State *)state)->transaction_max);
1309  SCReturnUInt(count);
1310 }
1311 
1312 /**
1313  * \brief Free all the objects in a DNP3ObjectList.
1314  */
1315 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1316 {
1317  DNP3Object *object;
1318 
1319  while ((object = TAILQ_FIRST(objects)) != NULL) {
1320  TAILQ_REMOVE(objects, object, next);
1321  DNP3ObjectFree(object);
1322  }
1323 }
1324 
1325 /**
1326  * \brief Free a DNP3 transaction.
1327  */
1328 static void DNP3TxFree(DNP3Transaction *tx)
1329 {
1330  SCEnter();
1331 
1332  if (tx->buffer != NULL) {
1333  SCFree(tx->buffer);
1334  }
1335 
1336  SCAppLayerTxDataCleanup(&tx->tx_data);
1337 
1338  DNP3TxFreeObjectList(&tx->objects);
1339 
1340  SCFree(tx);
1341  SCReturn;
1342 }
1343 
1344 /**
1345  * \brief Free a transaction by ID on a specific DNP3 state.
1346  *
1347  * This function is called by the app-layer to free a transaction on a
1348  * specific DNP3 state object.
1349  */
1350 static void DNP3StateTxFree(void *state, uint64_t tx_id)
1351 {
1352  SCEnter();
1353  DNP3State *dnp3 = state;
1354  DNP3Transaction *tx = NULL, *ttx;
1355  uint64_t tx_num = tx_id + 1;
1356 
1357  TAILQ_FOREACH_SAFE(tx, &dnp3->tx_list, next, ttx) {
1358 
1359  if (tx->tx_num != tx_num) {
1360  continue;
1361  }
1362 
1363  if (tx == dnp3->curr) {
1364  dnp3->curr = NULL;
1365  }
1366 
1367  if (tx->tx_data.events != NULL) {
1368  if (tx->tx_data.events->cnt <= dnp3->events) {
1369  dnp3->events -= tx->tx_data.events->cnt;
1370  } else {
1371  dnp3->events = 0;
1372  }
1373  }
1374  dnp3->unreplied--;
1375 
1376  /* Check flood state. */
1377  if (dnp3->flooded && dnp3->unreplied < DNP3_DEFAULT_REQ_FLOOD_COUNT) {
1378  dnp3->flooded = 0;
1379  }
1380 
1381  TAILQ_REMOVE(&dnp3->tx_list, tx, next);
1382  DNP3TxFree(tx);
1383  break;
1384  }
1385 
1386  SCReturn;
1387 }
1388 
1389 /**
1390  * \brief Free a DNP3 state.
1391  */
1392 static void DNP3StateFree(void *state)
1393 {
1394  SCEnter();
1395  DNP3State *dnp3 = state;
1396  DNP3Transaction *tx;
1397  if (state != NULL) {
1398  while ((tx = TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1399  TAILQ_REMOVE(&dnp3->tx_list, tx, next);
1400  DNP3TxFree(tx);
1401  }
1402  if (dnp3->request_buffer.buffer != NULL) {
1403  SCFree(dnp3->request_buffer.buffer);
1404  }
1405  if (dnp3->response_buffer.buffer != NULL) {
1406  SCFree(dnp3->response_buffer.buffer);
1407  }
1408  SCFree(dnp3);
1409  }
1410  SCReturn;
1411 }
1412 
1413 /**
1414  * \brief Called by the app-layer to get the state progress.
1415  */
1416 static int DNP3GetAlstateProgress(void *tx, uint8_t direction)
1417 {
1418  DNP3Transaction *dnp3tx = (DNP3Transaction *)tx;
1419  DNP3State *dnp3 = dnp3tx->dnp3;
1420  int retval = 0;
1421 
1422  /* If flooded, "ack" old transactions. */
1423  if (dnp3->flooded && (dnp3->transaction_max -
1424  dnp3tx->tx_num >= DNP3_DEFAULT_REQ_FLOOD_COUNT)) {
1425  SCLogDebug("flooded: returning tx as done.");
1426  SCReturnInt(1);
1427  }
1428 
1429  if (dnp3tx->complete)
1430  retval = 1;
1431 
1432  SCReturnInt(retval);
1433 }
1434 
1435 /**
1436  * \brief App-layer support.
1437  */
1438 static int DNP3StateGetEventInfo(
1439  const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
1440 {
1441  if (SCAppLayerGetEventIdByName(event_name, dnp3_decoder_event_table, event_id) == 0) {
1442  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1443  return 0;
1444  }
1445  return -1;
1446 }
1447 
1448 /**
1449  * \brief App-layer support.
1450  */
1451 static int DNP3StateGetEventInfoById(
1452  uint8_t event_id, const char **event_name, AppLayerEventType *event_type)
1453 {
1454  *event_name = SCMapEnumValueToName(event_id, dnp3_decoder_event_table);
1455  if (*event_name == NULL) {
1456  SCLogError("Event \"%d\" not present in "
1457  "the DNP3 enum event map table.",
1458  event_id);
1459  return -1;
1460  }
1461 
1462  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1463 
1464  return 0;
1465 }
1466 
1467 static AppLayerTxData *DNP3GetTxData(void *vtx)
1468 {
1469  DNP3Transaction *tx = (DNP3Transaction *)vtx;
1470  return &tx->tx_data;
1471 }
1472 
1473 static AppLayerStateData *DNP3GetStateData(void *vstate)
1474 {
1475  DNP3State *state = (DNP3State *)vstate;
1476  return &state->state_data;
1477 }
1478 
1479 /**
1480  * \brief Check if the prefix code is a size prefix.
1481  *
1482  * \retval 1 if the prefix_code specifies a size prefix, 0 if not.
1483  */
1484 int DNP3PrefixIsSize(uint8_t prefix_code)
1485 {
1486  switch (prefix_code) {
1487  case 0x04:
1488  case 0x05:
1489  case 0x06:
1490  return 1;
1491  break;
1492  default:
1493  return 0;
1494  }
1495 }
1496 
1497 static AppLayerGetTxIterTuple DNP3GetTxIterator(const uint8_t ipproto, const AppProto alproto,
1498  void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *state)
1499 {
1500  DNP3State *dnp_state = (DNP3State *)alstate;
1501  AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
1502  if (dnp_state) {
1503  DNP3Transaction *tx_ptr;
1504  if (state->un.ptr == NULL) {
1505  tx_ptr = TAILQ_FIRST(&dnp_state->tx_list);
1506  } else {
1507  tx_ptr = (DNP3Transaction *)state->un.ptr;
1508  }
1509  if (tx_ptr) {
1510  while (tx_ptr->tx_num < min_tx_id + 1) {
1511  tx_ptr = TAILQ_NEXT(tx_ptr, next);
1512  if (!tx_ptr) {
1513  return no_tuple;
1514  }
1515  }
1516  if (tx_ptr->tx_num >= max_tx_id + 1) {
1517  return no_tuple;
1518  }
1519  state->un.ptr = TAILQ_NEXT(tx_ptr, next);
1520  AppLayerGetTxIterTuple tuple = {
1521  .tx_ptr = tx_ptr,
1522  .tx_id = tx_ptr->tx_num - 1,
1523  .has_next = (state->un.ptr != NULL),
1524  };
1525  return tuple;
1526  }
1527  }
1528  return no_tuple;
1529 }
1530 
1531 /**
1532  * \brief Register the DNP3 application protocol parser.
1533  */
1535 {
1536  SCEnter();
1537 
1538  const char *proto_name = "dnp3";
1539 
1540  if (SCAppLayerProtoDetectConfProtoDetectionEnabledDefault("tcp", proto_name, false)) {
1542 
1543  if (RunmodeIsUnittests()) {
1545  sizeof(DNP3LinkHeader), STREAM_TOSERVER, DNP3ProbingParser, DNP3ProbingParser);
1546  }
1547  else {
1548  if (!SCAppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP, proto_name, ALPROTO_DNP3,
1549  0, sizeof(DNP3LinkHeader), DNP3ProbingParser, DNP3ProbingParser)) {
1550  return;
1551  }
1552  }
1553 
1554  } else {
1555  SCLogConfig("Protocol detection and parser disabled for DNP3.");
1556  SCReturn;
1557  }
1558 
1559  if (SCAppLayerParserConfParserEnabled("tcp", proto_name)) {
1560  SCLogConfig("Registering DNP3/tcp parsers.");
1561 
1562  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DNP3, STREAM_TOSERVER,
1563  DNP3ParseRequest);
1564  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DNP3, STREAM_TOCLIENT,
1565  DNP3ParseResponse);
1566 
1568  DNP3StateAlloc, DNP3StateFree);
1569 
1570  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTx);
1571  AppLayerParserRegisterGetTxIterator(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxIterator);
1572  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxCnt);
1574  DNP3StateTxFree);
1575 
1577  DNP3GetAlstateProgress);
1579 
1581  DNP3StateGetEventInfo);
1583  DNP3StateGetEventInfoById);
1584 
1586  DNP3GetTxData);
1587  AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetStateData);
1588  } else {
1589  SCLogConfig("Parser disabled for protocol %s. "
1590  "Protocol detection still on.", proto_name);
1591  }
1592 
1593 #ifdef UNITTESTS
1596 #endif
1597 
1598  SCReturn;
1599 }
1600 
1601 #ifdef UNITTESTS
1602 
1603 #include "flow-util.h"
1604 #include "stream-tcp.h"
1605 
1606 /**
1607  * \brief Utility function to fix CRCs when mangling a frame.
1608  */
1609 static void DNP3FixCrc(uint8_t *data, uint32_t len)
1610 {
1611  uint32_t block_size;
1612 
1613  while (len) {
1614  if (len >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
1615  block_size = DNP3_BLOCK_SIZE;
1616  } else {
1617  block_size = len - DNP3_CRC_LEN;
1618  }
1619  uint16_t crc = DNP3ComputeCRC(data, block_size);
1620  data[block_size + 1] = (crc >> 8) & 0xff;
1621  data[block_size] = crc & 0xff;
1622  data += block_size + DNP3_CRC_LEN;
1623  len -= block_size + DNP3_CRC_LEN;
1624  }
1625 }
1626 
1627 /**
1628  * \test Test CRC checking on partial and full blocks.
1629  */
1630 static int DNP3ParserTestCheckCRC(void)
1631 {
1632  uint8_t request[] = {
1633  /* DNP3 start. */
1634  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1635  0xa5, 0xe9,
1636 
1637  /* Transport header. */
1638  0xff,
1639 
1640  /* Application layer - segment 1. */
1641  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1642  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1643  0xef,
1644 
1645  /* Application layer - segment 2. */
1646  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1647  };
1648 
1649  /* Check link header CRC. */
1650  FAIL_IF(!DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1651 
1652  /* Check first application layer segment. */
1653  FAIL_IF(!DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1655 
1656 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1657  /* Change a byte in link header, should fail now. */
1658  request[2]++;
1659  FAIL_IF(DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1660 
1661  /* Change a byte in the first application segment, should fail
1662  * now. */
1663  request[sizeof(DNP3LinkHeader) + 3]++;
1664  FAIL_IF(DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1666 #endif
1667 
1668  PASS;
1669 }
1670 
1671 /**
1672  * \test Test validation of all CRCs in user data.
1673  */
1674 static int DNP3CheckUserDataCRCsTest(void)
1675 {
1676  /* Multi-block data with valid CRCs. */
1677  uint8_t data_valid[] = {
1678  0xff, 0xc9, 0x05, 0x0c,
1679  0x01, 0x28, 0x01, 0x00,
1680  0x00, 0x00, 0x01, 0x01,
1681  0x01, 0x00, 0x00, 0x00,
1682  0x72, 0xef, /* CRC. */
1683 
1684  0xff, 0xc9, 0x05, 0x0c,
1685  0x01, 0x28, 0x01, 0x00,
1686  0x00, 0x00, 0x01, 0x01,
1687  0x01, 0x00, 0x00, 0x00,
1688  0x72, 0xef, /* CRC. */
1689 
1690  0xff, 0xc9, 0x05, 0x0c,
1691  0x01, 0x28, 0x01, 0x00,
1692  0x00, 0x00, 0x01, 0x01,
1693  0x01, 0x00, 0x00, 0x00,
1694  0x72, 0xef, /* CRC. */
1695 
1696  0x00, 0x00, 0x00, 0x00,
1697  0x00,
1698  0xff, 0xff, /* CRC. */
1699  };
1700  FAIL_IF(!DNP3CheckUserDataCRCs(data_valid, sizeof(data_valid)));
1701 
1702 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1703  /* Multi-block data with one non-crc byte altered. */
1704  uint8_t data_invalid[] = {
1705  0xff, 0xc9, 0x05, 0x0c,
1706  0x01, 0x28, 0x01, 0x00,
1707  0x00, 0x00, 0x01, 0x01,
1708  0x01, 0x00, 0x00, 0x00,
1709  0x72, 0xef, /* CRC. */
1710 
1711  0xff, 0xc9, 0x05, 0x0c,
1712  0x01, 0x28, 0x01, 0x00,
1713  0x00, 0x00, 0x01, 0x01,
1714  0x01, 0x00, 0x00, 0x00,
1715  0x72, 0xef, /* CRC. */
1716 
1717  0xff, 0xc9, 0x05, 0x0c,
1718  0x01, 0x28, 0x01, 0x00,
1719  0x00, 0x00, 0x01, 0x01,
1720  0x01, 0x00, 0x00, 0x00,
1721  0x72, 0xef, /* CRC. */
1722 
1723  0x00, 0x00, 0x00, 0x00,
1724  0x01, /* Invalid byte. */
1725  0xff, 0xff, /* CRC. */
1726  };
1727  FAIL_IF(DNP3CheckUserDataCRCs(data_invalid, sizeof(data_invalid)));
1728 
1729  /* 1 byte - need at least 3. */
1730  uint8_t one_byte_nocrc[] = { 0x01 };
1731  FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc, sizeof(one_byte_nocrc)));
1732 
1733  /* 2 bytes - need at least 3. */
1734  uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1735  FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc, sizeof(two_byte_nocrc)));
1736 #endif
1737 
1738  /* 3 bytes, valid CRC. */
1739  uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1740  *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1741  three_bytes_good_crc, 1);
1742  FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1743  sizeof(three_bytes_good_crc)));
1744 
1745  PASS;
1746 }
1747 
1748 /**
1749  * \test Test the link layer length calculation.
1750  *
1751  * Test the calculation that converts the link provided in the DNP3
1752  * header to the actual length of the frame. That is the length with
1753  * CRCs as the length in the header does not include CRCs.
1754  */
1755 static int DNP3CalculateLinkLengthTest(void)
1756 {
1757  /* These are invalid. */
1758  FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1759  FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1760  FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1761  FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1762  FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1763 
1764  /* This is the minimum size. */
1765  FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1766 
1767  /* 1 full user data blocks of data. */
1768  FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1769 
1770  /* 2 full user data blocks of data. */
1771  FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1772 
1773  /* 2 full user data blocks, plus one more byte. */
1774  /* 2 full user data blocks of data. */
1775  FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1776 
1777  /* The maximum size. */
1778  FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1779 
1780  PASS;
1781 }
1782 
1783 /**
1784  * \test The conversion of length with CRCs to the length without
1785  * CRCs.
1786  */
1787 static int DNP3CalculateTransportLengthWithoutCRCsTest(void)
1788 {
1789  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1790  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1791  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1792  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1793  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1794  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1795  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1796 
1797  /* 19 bytes is not enough for a second block. */
1798  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1799 
1800  /* 20 bytes really isn't enough either, but is large enough to
1801  * satisfy the CRC on the second block. */
1802  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1803 
1804  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1805 
1806  PASS;
1807 }
1808 
1809 /**
1810  * \test Test the validation of the link header CRC.
1811  */
1812 static int DNP3ParserCheckLinkHeaderCRC(void)
1813 {
1814  /* DNP3 frame with valid headers and CRCs. */
1815  uint8_t request[] = {
1816  /* DNP3 start. */
1817  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1818  0xa5, 0xe9,
1819 
1820  /* Transport header. */
1821  0xff,
1822 
1823  /* Application layer. */
1824  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1825  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1826  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1827  };
1828 
1829  DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1830  FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1831 
1832 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1833  /* Alter a byte in the header. */
1834  request[4] = 0;
1835  FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1836 #endif
1837 
1838  PASS;
1839 }
1840 
1841 /**
1842  * \test Test removal of CRCs from user data.
1843  */
1844 static int DNP3ReassembleApplicationLayerTest01(void)
1845 {
1846  uint32_t reassembled_len = 0;
1847  uint8_t *output = NULL;
1848 
1849  uint8_t payload[] = {
1850 
1851  0xff, 0xc9, 0x05, 0x0c,
1852  0x01, 0x28, 0x01, 0x00,
1853  0x00, 0x00, 0x01, 0x01,
1854  0x01, 0x00, 0x00, 0x00,
1855  0x72, 0xef, /* CRC. */
1856 
1857  0xff, 0xc9, 0x05, 0x0c,
1858  0x01, 0x28, 0x01, 0x00,
1859  0x00, 0x00, 0x01, 0x01,
1860  0x01, 0x00, 0x00, 0x00,
1861  0x72, 0xef, /* CRC. */
1862 
1863  0xff, 0xc9, 0x05, 0x0c,
1864  0x01, 0x28, 0x01, 0x00,
1865  0x00, 0x00, 0x01, 0x01,
1866  0x01, 0x00, 0x00, 0x00,
1867  0x72, 0xef, /* CRC. */
1868 
1869  0x00, 0x00, 0x00, 0x00,
1870  0x00,
1871  0xff, 0xff, /* CRC. */
1872  };
1873 
1874  uint8_t expected[] = {
1875  0xc9, 0x05, 0x0c,
1876  0x01, 0x28, 0x01, 0x00,
1877  0x00, 0x00, 0x01, 0x01,
1878  0x01, 0x00, 0x00, 0x00,
1879  /* CRC removed. */
1880  0xff, 0xc9, 0x05, 0x0c,
1881  0x01, 0x28, 0x01, 0x00,
1882  0x00, 0x00, 0x01, 0x01,
1883  0x01, 0x00, 0x00, 0x00,
1884  /* CRC removed. */
1885  0xff, 0xc9, 0x05, 0x0c,
1886  0x01, 0x28, 0x01, 0x00,
1887  0x00, 0x00, 0x01, 0x01,
1888  0x01, 0x00, 0x00, 0x00,
1889  /* CRC removed. */
1890  0x00, 0x00, 0x00, 0x00,
1891  0x00
1892  /* CRC removed. */
1893  };
1894 
1895  /* Valid frame. */
1896  FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1897  sizeof(payload), &output, &reassembled_len));
1898  FAIL_IF(output == NULL);
1899  FAIL_IF(reassembled_len != sizeof(expected));
1900  FAIL_IF(memcmp(expected, output, reassembled_len));
1901  SCFree(output);
1902 
1903  /* 1 byte, invalid. */
1904  reassembled_len = 0;
1905  output = NULL;
1906  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1907  &reassembled_len));
1908  FAIL_IF(output != NULL);
1909  FAIL_IF(reassembled_len != 0);
1910 
1911  /* 2 bytes, invalid. */
1912  reassembled_len = 0;
1913  output = NULL;
1914  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1915  &reassembled_len));
1916  FAIL_IF(output != NULL);
1917  FAIL_IF(reassembled_len != 0);
1918 
1919  /* 3 bytes, minimum - but that would only be the transport header
1920  * which isn't included in the output. */
1921  reassembled_len = 0;
1922  output = NULL;
1923  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1924  &reassembled_len));
1925  FAIL_IF(output != NULL);
1926  FAIL_IF(reassembled_len != 0);
1927 
1928  /* 4 bytes is the minimum to get any reassembled data. */
1929  reassembled_len = 0;
1930  output = NULL;
1931  FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1932  &reassembled_len));
1933  FAIL_IF(output == NULL);
1934  FAIL_IF(reassembled_len != 1);
1935 
1936  /* Last block too short (by 1 byte) for data + CRC. */
1937  uint8_t short_payload1[] = {
1938 
1939  0xff, 0xc9, 0x05, 0x0c,
1940  0x01, 0x28, 0x01, 0x00,
1941  0x00, 0x00, 0x01, 0x01,
1942  0x01, 0x00, 0x00, 0x00,
1943  0x72, 0xef, /* CRC. */
1944 
1945  0xff, 0xc9, 0x05, 0x0c,
1946  0x01, 0x28, 0x01, 0x00,
1947  0x00, 0x00, 0x01, 0x01,
1948  0x01, 0x00, 0x00, 0x00,
1949  0x72, 0xef, /* CRC. */
1950 
1951  0xff, 0xc9, 0x05, 0x0c,
1952  0x01, 0x28, 0x01, 0x00,
1953  0x00, 0x00, 0x01, 0x01,
1954  0x01, 0x00, 0x00, 0x00,
1955  0x72, 0xef, /* CRC. */
1956 
1957  0x00, 0x00
1958  };
1959  reassembled_len = 0;
1960  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1961  sizeof(short_payload1), &output, &reassembled_len));
1962 
1963  /* Last block too short (by 2 bytes) for data + CRC. */
1964  uint8_t short_payload2[] = {
1965 
1966  0xff, 0xc9, 0x05, 0x0c,
1967  0x01, 0x28, 0x01, 0x00,
1968  0x00, 0x00, 0x01, 0x01,
1969  0x01, 0x00, 0x00, 0x00,
1970  0x72, 0xef, /* CRC. */
1971 
1972  0xff, 0xc9, 0x05, 0x0c,
1973  0x01, 0x28, 0x01, 0x00,
1974  0x00, 0x00, 0x01, 0x01,
1975  0x01, 0x00, 0x00, 0x00,
1976  0x72, 0xef, /* CRC. */
1977 
1978  0xff, 0xc9, 0x05, 0x0c,
1979  0x01, 0x28, 0x01, 0x00,
1980  0x00, 0x00, 0x01, 0x01,
1981  0x01, 0x00, 0x00, 0x00,
1982  0x72, 0xef, /* CRC. */
1983 
1984  0x00,
1985  };
1986  reassembled_len = 0;
1987  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
1988  sizeof(short_payload2), &output, &reassembled_len));
1989 
1990  PASS;
1991 }
1992 
1993 /**
1994  * \test Test the probing parser.
1995  */
1996 static int DNP3ProbingParserTest(void)
1997 {
1998  uint8_t pkt[] = {
1999  0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2000  0xbd, 0x71
2001  };
2002  uint8_t rdir = 0;
2003 
2004  /* Valid frame. */
2005  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_DNP3);
2006 
2007  /* Send too little bytes. */
2008  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(DNP3LinkHeader) - 1, &rdir) != ALPROTO_UNKNOWN);
2009 
2010  /* Bad start bytes. */
2011  pkt[0] = 0x06;
2012  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2013 
2014  /* Restore start byte. */
2015  pkt[0] = 0x05;
2016 
2017  /* Set the length to a value less than the minimum length of 5. */
2018  pkt[2] = 0x03;
2019  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2020 
2021  /* Send a banner. */
2022  char mybanner[] = "Welcome to DNP3 SCADA.";
2023  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner, sizeof(mybanner) - 1,
2024  &rdir) != ALPROTO_DNP3);
2025  FAIL_IF(rdir != STREAM_TOCLIENT);
2026 
2027  PASS;
2028 }
2029 
2030 /**
2031  * \test Test a basic request/response.
2032  */
2033 static int DNP3ParserTestRequestResponse(void)
2034 {
2035  DNP3State *state = NULL;
2036 
2037  uint8_t request[] = {
2038  /* DNP3 start. */
2039  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2040  0xa5, 0xe9,
2041 
2042  /* Transport header. */
2043  0xff,
2044 
2045  /* Application layer. */
2046  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2047  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2048  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2049  };
2050 
2051  uint8_t response[] = {
2052  /* DNP3 start. */
2053  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2054  0xe2, 0x59,
2055 
2056  /* Transport header. */
2057  0xc3,
2058 
2059  /* Application layer. */
2060  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2061  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2062  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2063  0xff, 0xff
2064  };
2065 
2067  Flow flow;
2068  TcpSession ssn;
2069 
2070  memset(&flow, 0, sizeof(flow));
2071  memset(&ssn, 0, sizeof(ssn));
2072 
2073  flow.protoctx = (void *)&ssn;
2074  flow.proto = IPPROTO_TCP;
2075  flow.alproto = ALPROTO_DNP3;
2076 
2077  StreamTcpInitConfig(true);
2078 
2079  SCMutexLock(&flow.m);
2081  STREAM_TOSERVER, request, sizeof(request)));
2082  SCMutexUnlock(&flow.m);
2083 
2084  state = flow.alstate;
2085  FAIL_IF(state == NULL);
2086 
2087  DNP3Transaction *tx = DNP3GetTx(state, 0);
2088  FAIL_IF(tx == NULL);
2089  FAIL_IF(tx->tx_num != 1);
2090  FAIL_IF(tx != state->curr);
2091  FAIL_IF(tx->buffer == NULL);
2092  FAIL_IF(tx->buffer_len != 20);
2093  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2094 
2095  SCMutexLock(&flow.m);
2097  STREAM_TOCLIENT, response, sizeof(response)));
2098  SCMutexUnlock(&flow.m);
2099  DNP3Transaction *tx0 = DNP3GetTx(state, 1);
2100  FAIL_IF(tx0 == NULL);
2101  FAIL_IF(tx0 == tx);
2102  FAIL_IF(!tx0->done);
2103  FAIL_IF(tx0->buffer == NULL);
2104 
2106  StreamTcpFreeConfig(true);
2107  FLOW_DESTROY(&flow);
2108  PASS;
2109 }
2110 
2111 /**
2112  * \test Test an unsolicited response from an outstation.
2113  *
2114  * This is kind of like a request initiated from the "server".
2115  */
2116 static int DNP3ParserTestUnsolicitedResponseConfirm(void)
2117 {
2118  DNP3State *state = NULL;
2119 
2120  /* Unsolicited response with confirm bit set. */
2121  uint8_t response[] = {
2122  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2123  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2124  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2125  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2126  };
2127 
2128  /* Confirm. */
2129  uint8_t confirm[] = {
2130  0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2131  0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2132  0x3d
2133  };
2134 
2136  Flow flow;
2137  TcpSession ssn;
2138 
2139  memset(&flow, 0, sizeof(flow));
2140  memset(&ssn, 0, sizeof(ssn));
2141 
2142  flow.protoctx = (void *)&ssn;
2143  flow.proto = IPPROTO_TCP;
2144  flow.alproto = ALPROTO_DNP3;
2145 
2146  StreamTcpInitConfig(true);
2147 
2148  SCMutexLock(&flow.m);
2150  STREAM_TOCLIENT, response, sizeof(response)));
2151  SCMutexUnlock(&flow.m);
2152 
2153  state = flow.alstate;
2154  FAIL_IF(state == NULL);
2155 
2156  DNP3Transaction *tx = DNP3GetTx(state, 0);
2157  FAIL_IF(tx == NULL);
2158  FAIL_IF(tx->tx_num != 1);
2159  FAIL_IF(tx != state->curr);
2160  FAIL_IF(!tx->done);
2161  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_UNSOLICITED_RESP);
2162 
2163  SCMutexLock(&flow.m);
2165  STREAM_TOSERVER, confirm, sizeof(confirm)));
2166  SCMutexUnlock(&flow.m);
2167 
2168  /* Confirms are ignored currently. With the move to
2169  unidirectional transactions it might be easy to support these
2170  now. */
2171  DNP3Transaction *resptx = DNP3GetTx(state, 1);
2172  FAIL_IF(resptx);
2173 
2175  StreamTcpFreeConfig(true);
2176  FLOW_DESTROY(&flow);
2177  PASS;
2178 }
2179 
2180 /**
2181  * \test Test flood state.
2182  *
2183  * Note that flood state needs to revisited with the modification to a
2184  * unidirectional protocol.
2185  */
2186 static int DNP3ParserTestFlooded(void)
2187 {
2188  DNP3State *state = NULL;
2189 
2190  uint8_t request[] = {
2191  /* DNP3 start. */
2192  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2193  0xa5, 0xe9,
2194 
2195  /* Transport header. */
2196  0xff,
2197 
2198  /* Application layer. */
2199  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2200  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2201  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2202  };
2203 
2205  Flow flow;
2206  TcpSession ssn;
2207 
2208  memset(&flow, 0, sizeof(flow));
2209  memset(&ssn, 0, sizeof(ssn));
2210 
2211  flow.protoctx = (void *)&ssn;
2212  flow.proto = IPPROTO_TCP;
2213  flow.alproto = ALPROTO_DNP3;
2214 
2215  StreamTcpInitConfig(true);
2216 
2217  SCMutexLock(&flow.m);
2219  STREAM_TOSERVER, request, sizeof(request)));
2220  SCMutexUnlock(&flow.m);
2221 
2222  state = flow.alstate;
2223  FAIL_IF(state == NULL);
2224 
2225  DNP3Transaction *tx = DNP3GetTx(state, 0);
2226  FAIL_IF(tx == NULL);
2227  FAIL_IF(tx->tx_num != 1);
2228  FAIL_IF(tx != state->curr);
2229  FAIL_IF(tx->buffer == NULL);
2230  FAIL_IF(tx->buffer_len != 20);
2231  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2232  FAIL_IF_NOT(tx->done);
2233  FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2234 
2235  for (int i = 0; i < DNP3_DEFAULT_REQ_FLOOD_COUNT - 1; i++) {
2236  SCMutexLock(&flow.m);
2238  STREAM_TOSERVER, request, sizeof(request)));
2239  SCMutexUnlock(&flow.m);
2240  }
2241  FAIL_IF(state->flooded);
2242  FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2243 
2244  /* One more request should trip us into flooded state. */
2245  SCMutexLock(&flow.m);
2247  STREAM_TOSERVER, request, sizeof(request)));
2248  SCMutexUnlock(&flow.m);
2249  FAIL_IF(!state->flooded);
2250 
2251  /* Progress for the oldest tx should return 1. */
2252  FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2253 
2255  StreamTcpFreeConfig(true);
2256  FLOW_DESTROY(&flow);
2257  PASS;
2258 }
2259 
2260 /**
2261  * \test Test parsing of partial frames.
2262  *
2263  * As DNP3 operates over TCP, it is possible that a partial DNP3 frame
2264  * is received. Test that the partial frame will be buffered until the
2265  * remainder is seen.
2266  */
2267 static int DNP3ParserTestPartialFrame(void)
2268 {
2269  DNP3State *state = NULL;
2270  DNP3Transaction *tx;
2271  int r;
2272 
2273  uint8_t request_partial1[] = {
2274  /* DNP3 start. */
2275  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2276  0xa5, 0xe9,
2277 
2278  /* Transport header. */
2279  0xff,
2280 
2281  /* Application layer. */
2282  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2283  };
2284 
2285  uint8_t request_partial2[] = {
2286  /* Remainder of application layer. */
2287  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2288  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2289  };
2290 
2291  uint8_t response_partial1[] = {
2292  /* DNP3 start. */
2293  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2294  0xe2, 0x59,
2295 
2296  /* Transport header. */
2297  0xc3,
2298 
2299  /* Application layer. */
2300  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2301  };
2302 
2303  uint8_t response_partial2[] = {
2304  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2305  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2306  0xff, 0xff
2307  };
2308 
2309  /* Boiler plate for app layer setup. */
2311  Flow flow;
2312  TcpSession ssn;
2313  memset(&flow, 0, sizeof(flow));
2314  memset(&ssn, 0, sizeof(ssn));
2315  flow.protoctx = (void *)&ssn;
2316  flow.proto = IPPROTO_TCP;
2317  flow.alproto = ALPROTO_DNP3;
2318  StreamTcpInitConfig(true);
2319 
2320  /* Pass in the first partial frame. */
2321 
2322  SCMutexLock(&flow.m);
2323  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2324  STREAM_TOSERVER, request_partial1, sizeof(request_partial1));
2325  SCMutexUnlock(&flow.m);
2326  FAIL_IF(r != 0);
2327 
2328  /* Frame should just be buffered, but not yet processed. */
2329  state = flow.alstate;
2330  FAIL_IF(state == NULL);
2331  FAIL_IF(state->request_buffer.len != sizeof(request_partial1));
2332  FAIL_IF(state->request_buffer.offset != 0);
2333  FAIL_IF(memcmp(state->request_buffer.buffer, request_partial1,
2334  sizeof(request_partial1)));
2335 
2336  /* There should not be a transaction yet. */
2337  FAIL_IF(state->transaction_max != 0);
2338  FAIL_IF(DNP3GetTx(state, 0) != NULL);
2339 
2340  /* Send the second partial. */
2341  SCMutexLock(&flow.m);
2342  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2343  STREAM_TOSERVER, request_partial2, sizeof(request_partial2));
2344  SCMutexUnlock(&flow.m);
2345  FAIL_IF(r != 0);
2346 
2347  /* The second partial completed the frame, the buffer should now
2348  * be clear. */
2349  FAIL_IF(state->request_buffer.len != 0);
2350  FAIL_IF(state->request_buffer.offset != 0);
2351 
2352  /* Should now have a complete transaction. */
2353  tx = DNP3GetTx(state, 0);
2354  FAIL_IF(tx == NULL);
2355  FAIL_IF(tx->tx_num != 1);
2356  FAIL_IF(tx != state->curr);
2357  FAIL_IF(tx->buffer == NULL);
2358  FAIL_IF(tx->buffer_len != 20);
2359  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2360 
2361  /* Send partial response. */
2362  SCMutexLock(&flow.m);
2363  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2364  STREAM_TOCLIENT, response_partial1, sizeof(response_partial1));
2365  SCMutexUnlock(&flow.m);
2366  FAIL_IF(r != 0);
2367  FAIL_IF(state->response_buffer.len != sizeof(response_partial1));
2368  FAIL_IF(state->response_buffer.offset != 0);
2369  tx = DNP3GetTx(state, 1);
2370  FAIL_IF_NOT_NULL(tx);
2371 
2372  /* Send rest of response. */
2373  SCMutexLock(&flow.m);
2374  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2375  STREAM_TOCLIENT, response_partial2, sizeof(response_partial2));
2376  SCMutexUnlock(&flow.m);
2377  FAIL_IF(r != 0);
2378 
2379  /* Buffer should now be empty. */
2380  FAIL_IF(state->response_buffer.len != 0);
2381  FAIL_IF(state->response_buffer.offset != 0);
2382 
2383  /* There should now be a response transaction. */
2384  tx = DNP3GetTx(state, 1);
2385  FAIL_IF_NULL(tx);
2386  FAIL_IF(tx->buffer == NULL);
2387  FAIL_IF(tx->buffer_len == 0);
2388 
2390  StreamTcpFreeConfig(true);
2391  FLOW_DESTROY(&flow);
2392  PASS;
2393 }
2394 
2395 /**
2396  * \test Test multiple DNP3 frames in one TCP read.
2397  */
2398 static int DNP3ParserTestMultiFrame(void)
2399 {
2400  DNP3State *state = NULL;
2401 
2402  /* Unsolicited response 1. */
2403  uint8_t unsol_response1[] = {
2404  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2405  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2406  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2407  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2408  };
2409 
2410  /* Unsolicited response 2. */
2411  uint8_t unsol_response2[] = {
2412  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2413  0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2414  0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2415  0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2416  };
2417 
2418  uint8_t combined[sizeof(unsol_response1) + sizeof(unsol_response2)];
2419  memcpy(combined, unsol_response1, sizeof(unsol_response1));
2420  memcpy(combined + sizeof(unsol_response1), unsol_response2,
2421  sizeof(unsol_response2));
2422 
2423  /* Setup. */
2425  Flow flow;
2426  TcpSession ssn;
2427  int r;
2428  memset(&flow, 0, sizeof(flow));
2429  memset(&ssn, 0, sizeof(ssn));
2430  flow.protoctx = (void *)&ssn;
2431  flow.proto = IPPROTO_TCP;
2432  flow.alproto = ALPROTO_DNP3;
2433  StreamTcpInitConfig(true);
2434 
2435  SCMutexLock(&flow.m);
2436  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2437  STREAM_TOCLIENT, combined, sizeof(combined));
2438  SCMutexUnlock(&flow.m);
2439  FAIL_IF(r != 0);
2440 
2441  state = flow.alstate;
2442  FAIL_IF(state == NULL);
2443  FAIL_IF(state->transaction_max != 2);
2444 
2446  StreamTcpFreeConfig(true);
2447  FLOW_DESTROY(&flow);
2448  PASS;
2449 }
2450 
2451 /**
2452  * \test Test the parsing of a request PDU.
2453  *
2454  * The PDU under test contains a single read request object:
2455  * - Group: 1
2456  * - Variation: 0
2457  * - Count: 0
2458  */
2459 static int DNP3ParserTestParsePDU01(void)
2460 {
2461  /* Frame to be tested. This frame is a DNP3 request with one read
2462  * request data object, group 1, variation 0. */
2463  const uint8_t pkt[] = {
2464  0x05, 0x64,
2465  0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2466  0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2467  };
2468 
2469  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2470  int pdus = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2471  FAIL_IF(pdus < 1);
2472  DNP3Transaction *dnp3tx = DNP3GetTx(dnp3state, 0);
2473  FAIL_IF_NULL(dnp3tx);
2474  FAIL_IF(!dnp3tx->is_request);
2475  FAIL_IF(TAILQ_EMPTY(&dnp3tx->objects));
2476  DNP3Object *object = TAILQ_FIRST(&dnp3tx->objects);
2477  FAIL_IF(object->group != 1 || object->variation != 0);
2478  FAIL_IF(object->count != 0);
2479 
2480  DNP3StateFree(dnp3state);
2481  PASS;
2482 }
2483 
2484 /**
2485  * \test Test the decode of a DNP3 fragment with a single 70:3 object.
2486  */
2487 static int DNP3ParserDecodeG70V3Test(void)
2488 {
2489  const uint8_t pkt[] = {
2490  0x05, 0x64,
2491  0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2492  0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2493  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2494  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2495  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2496  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2497  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2498  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2499  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2500  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2501  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2502  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2503  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2504  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2505  0xc4, 0x8b
2506  };
2507 
2508  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2509  FAIL_IF_NULL(dnp3state);
2510  int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2511  FAIL_IF(bytes != sizeof(pkt));
2512  DNP3Transaction *tx = DNP3GetTx(dnp3state, 0);
2513  FAIL_IF_NULL(tx);
2514  FAIL_IF_NOT(tx->is_request);
2515  DNP3Object *obj = TAILQ_FIRST(&tx->objects);
2516  FAIL_IF_NULL(obj);
2517  FAIL_IF_NOT(obj->group == 70);
2518  FAIL_IF_NOT(obj->variation == 3);
2519  FAIL_IF_NOT(obj->prefix_code == 0x5);
2520  FAIL_IF_NOT(obj->range_code == 0xb);
2521  FAIL_IF_NOT(obj->count == 1);
2522  DNP3Point *point = TAILQ_FIRST(obj->points);
2523  FAIL_IF_NULL(point);
2524  FAIL_IF_NOT(point->prefix == 85);
2525  FAIL_IF_NOT(point->size == 85);
2526  FAIL_IF_NULL(point->data);
2527  DNP3ObjectG70V3 *data = point->data;
2528  FAIL_IF_NOT(strcmp(
2529  data->filename,
2530  "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2531  DNP3StateFree(dnp3state);
2532  PASS;
2533 }
2534 
2535 /**
2536  * \brief Test that an alert is raised on an unknown object.
2537  */
2538 static int DNP3ParserUnknownEventAlertTest(void)
2539 {
2540  /* Valid DNP3 frame with 70:3 object. */
2541  uint8_t pkt[] = {
2542  0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2543  0xc7, 0xee,
2544 
2545  0xc7, 0xc9, 0x1b,
2546 
2547  /* Object and variation. Originally 70:3, now 70:99, an
2548  * unknown object. */
2549  0x46, 0x63,
2550 
2551  0x5b, 0x01, 0x55,
2552  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2553  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2554  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2555  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2556  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2557  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2558  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2559  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2560  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2561  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2562  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2563  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2564  0xc4, 0x8b
2565  };
2566 
2567  DNP3FixCrc(pkt + 10, sizeof(pkt) - 10);
2568 
2569  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2570  FAIL_IF_NULL(dnp3state);
2571  int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2572  FAIL_IF(bytes != sizeof(pkt));
2573 
2574  DNP3StateFree(dnp3state);
2575  PASS;
2576 }
2577 
2578 /**
2579 * \brief Test that an alert is raised on incorrect data.
2580 */
2581 static int DNP3ParserIncorrectUserData(void)
2582 {
2583  uint8_t packet_bytes[] = {
2584  0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2585  0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2586  };
2587 
2589  Flow flow;
2590  TcpSession ssn;
2591  memset(&flow, 0, sizeof(flow));
2592  memset(&ssn, 0, sizeof(ssn));
2593  flow.protoctx = (void *)&ssn;
2594  flow.proto = IPPROTO_TCP;
2595  flow.alproto = ALPROTO_DNP3;
2596  StreamTcpInitConfig(true);
2597 
2598  int r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2599  STREAM_TOCLIENT, packet_bytes, sizeof(packet_bytes));
2600 
2601  FAIL_IF(r == 0);
2602 
2604  StreamTcpFreeConfig(true);
2605  FLOW_DESTROY(&flow);
2606  PASS;
2607 }
2608 
2609 #endif
2610 
2612 {
2613 #ifdef UNITTESTS
2614  UtRegisterTest("DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2615  UtRegisterTest("DNP3ParserCheckLinkHeaderCRC",
2616  DNP3ParserCheckLinkHeaderCRC);
2617  UtRegisterTest("DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2618  UtRegisterTest("DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2619  UtRegisterTest("DNP3CalculateTransportLengthWithoutCRCsTest",
2620  DNP3CalculateTransportLengthWithoutCRCsTest);
2621  UtRegisterTest("DNP3ReassembleApplicationLayerTest01",
2622  DNP3ReassembleApplicationLayerTest01);
2623  UtRegisterTest("DNP3ProbingParserTest", DNP3ProbingParserTest);
2624  UtRegisterTest("DNP3ParserTestRequestResponse",
2625  DNP3ParserTestRequestResponse);
2626  UtRegisterTest("DNP3ParserTestUnsolicitedResponseConfirm",
2627  DNP3ParserTestUnsolicitedResponseConfirm);
2628  UtRegisterTest("DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2629  UtRegisterTest("DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2630  UtRegisterTest("DNP3ParserTestFlooded", DNP3ParserTestFlooded);
2631  UtRegisterTest("DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2632  UtRegisterTest("DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2633  UtRegisterTest("DNP3ParserUnknownEventAlertTest",
2634  DNP3ParserUnknownEventAlertTest);
2635  UtRegisterTest("DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);
2636 #endif
2637 }
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:500
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:89
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:136
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
APP_LAYER_TX_SKIP_INSPECT_TC
#define APP_LAYER_TX_SKIP_INSPECT_TC
Definition: app-layer-parser.h:68
stream-tcp.h
StreamSlice
struct StreamSlice StreamSlice
Definition: app-layer-parser.h:38
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:275
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:86
DNP3ParserRegisterTests
void DNP3ParserRegisterTests(void)
Definition: app-layer-dnp3.c:2611
DNP3Object_
Struct to hold the list of decoded objects.
Definition: app-layer-dnp3.h:192
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:548
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:510
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:248
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
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:324
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:1484
AppLayerTxData
struct AppLayerTxData AppLayerTxData
Definition: app-layer-parser.h:42
DNP3ObjectG70V3_::filename
char filename[65535]
Definition: app-layer-dnp3-objects.h:1227
AppLayerEventType
enum AppLayerEventType AppLayerEventType
Definition: app-layer-parser.h:43
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:100
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:41
util-spm-bs.h
DNP3Transaction_::buffer_len
uint32_t buffer_len
Definition: app-layer-dnp3.h:220
Flow_::protoctx
void * protoctx
Definition: flow.h:441
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:72
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:1534
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
AppLayerParserTriggerRawStreamInspection
void AppLayerParserTriggerRawStreamInspection(Flow *f, int direction)
Definition: app-layer-parser.c:1557
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
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:488
AppLayerResult
struct AppLayerResult AppLayerResult
Definition: app-layer-parser.h:39
DNP3_BLOCK_SIZE
#define DNP3_BLOCK_SIZE
Definition: app-layer-dnp3.c:57
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:135
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
SCAppLayerParserConfParserEnabled
int SCAppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests
Definition: app-layer-parser.c:345
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:50
app-layer-dnp3.h
AppLayerGetTxIterTuple
struct AppLayerGetTxIterTuple AppLayerGetTxIterTuple
Definition: app-layer-parser.h:40
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
DNP3_CRC_LEN
#define DNP3_CRC_LEN
Definition: app-layer-dnp3.c:53
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:23
SCEnter
#define SCEnter(...)
Definition: util-debug.h:277
AppLayerParserRegisterStateFuncs
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
Definition: app-layer-parser.c:435
Flow_::m
SCMutex m
Definition: flow.h:435
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:255
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:317
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:595
DNP3_MIN_LEN
#define DNP3_MIN_LEN
Definition: app-layer-dnp3.c:50
SCReturn
#define SCReturn
Definition: util-debug.h:279
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:1840
AppLayerGetTxIterState
Definition: app-layer-parser.h:134
DNP3Object_::group
uint8_t group
Definition: app-layer-dnp3.h:193
SCReturnUInt
#define SCReturnUInt(x)
Definition: util-debug.h:283
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:67
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:293
DNP3_START_BYTE1
#define DNP3_START_BYTE1
Definition: app-layer-dnp3.c:47
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1742
DNP3Object_::start
uint32_t start
Definition: app-layer-dnp3.h:198
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:270
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:402
DNP3_BANNER
#define DNP3_BANNER
Definition: app-layer-dnp3.c:248
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
crc
uint16_t crc
Definition: app-layer-dnp3.h:6
SCAppLayerProtoDetectPPRegister
void SCAppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
Definition: app-layer-detect-proto.c:1527
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:297
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:530
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:77
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:297
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:859
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:1291
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:71
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:616
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:606
DNP3_OBJ_PREFIX
#define DNP3_OBJ_PREFIX(x)
Definition: app-layer-dnp3.c:83
DNP3Object_::prefix_code
uint8_t prefix_code
Definition: app-layer-dnp3.h:196
AppLayerStateData
struct AppLayerStateData AppLayerStateData
Definition: app-layer-parser.h:44
app-layer-events.h
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
DNP3Transaction_::tx_num
uint64_t tx_num
Definition: app-layer-dnp3.h:214
AppLayerParserRegisterGetTxIterator
void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto, AppLayerGetTxIteratorFunc Func)
Definition: app-layer-parser.c:540
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:267
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:479
SCAppLayerProtoDetectPPParseConfPorts
int SCAppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
Definition: app-layer-detect-proto.c:1563
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:33
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:43
AppLayerParserRegisterGetTxCnt
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
Definition: app-layer-parser.c:520
SCAppLayerProtoDetectConfProtoDetectionEnabledDefault
int SCAppLayerProtoDetectConfProtoDetectionEnabledDefault(const char *ipproto, const char *alproto, bool default_enabled)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:1872
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:81
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:563
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:60
DNP3Point_::prefix
uint32_t prefix
Definition: app-layer-dnp3.h:176
DNP3Transaction_::tx_data
AppLayerTxData tx_data
Definition: app-layer-dnp3.h:212
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:46
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-enum.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:281
DNP3_OBJ_RANGE
#define DNP3_OBJ_RANGE(x)
Definition: app-layer-dnp3.c:86
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
SCAppLayerGetEventIdByName
int SCAppLayerGetEventIdByName(const char *event_name, SCEnumCharMap *table, uint8_t *event_id)
Definition: app-layer-events.c:28
DNP3Point_
DNP3 object point.
Definition: app-layer-dnp3.h:175
DNP3Transaction_
DNP3 transaction.
Definition: app-layer-dnp3.h:211
AppLayerGetTxIterState::un
union AppLayerGetTxIterState::@7 un
APP_LAYER_TX_SKIP_INSPECT_TS
#define APP_LAYER_TX_SKIP_INSPECT_TS
Definition: app-layer-parser.h:67
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