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