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