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