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