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 Caculate 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  TAILQ_INIT(&tx->objects);
503  TAILQ_INSERT_TAIL(&dnp3->tx_list, tx, next);
504 
505  /* Check for flood state. */
507  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_FLOODED);
508  dnp3->flooded = 1;
509  }
510 
511  return tx;
512 }
513 
514 /**
515  * \brief Calculate the length of a link frame with CRCs.
516  *
517  * This is required as the length parameter in the DNP3 header does not
518  * include the added CRCs.
519  *
520  * \param length The length from the DNP3 link header.
521  *
522  * \retval The length of the frame with CRCs included or 0 if the length isn't
523  * long enough to be a valid DNP3 frame.
524  */
525 static uint32_t DNP3CalculateLinkLength(uint8_t length)
526 {
527  uint32_t frame_len = 0;
528  int rem;
529 
530  /* Fail early if the length is less than the minimum size. */
531  if (length < DNP3_LINK_HDR_LEN) {
532  return 0;
533  }
534 
535  /* Subtract the 5 bytes of the header that are included in the
536  * length. */
537  length -= DNP3_LINK_HDR_LEN;
538 
539  rem = length % DNP3_BLOCK_SIZE;
540  frame_len = (length / DNP3_BLOCK_SIZE) * (DNP3_BLOCK_SIZE + DNP3_CRC_LEN);
541  if (rem) {
542  frame_len += rem + DNP3_CRC_LEN;
543  }
544 
545  return frame_len + sizeof(DNP3LinkHeader);
546 }
547 
548 /**
549  * \brief Check if the link function code specifies user data.
550  *
551  * \param header Point to link header.
552  *
553  * \retval 1 if frame contains user data, otherwise 0.
554  */
555 static int DNP3IsUserData(const DNP3LinkHeader *header)
556 {
557  switch (DNP3_LINK_FC(header->control)) {
560  return 1;
561  default:
562  return 0;
563  }
564 }
565 
566 /**
567  * \brief Check if the frame has user data.
568  *
569  * Check if the DNP3 frame actually has user data by checking if data
570  * exists after the headers.
571  *
572  * \retval 1 if user data exists, otherwise 0.
573  */
574 static int DNP3HasUserData(const DNP3LinkHeader *header, uint8_t direction)
575 {
576  if (direction == STREAM_TOSERVER) {
577  return header->len >= DNP3_LINK_HDR_LEN + sizeof(DNP3TransportHeader) +
578  sizeof(DNP3ApplicationHeader);
579  }
580  else {
581  return header->len >= DNP3_LINK_HDR_LEN + sizeof(DNP3TransportHeader) +
582  sizeof(DNP3ApplicationHeader) + sizeof(DNP3InternalInd);
583  }
584 }
585 
586 /**
587  * \brief Reset a DNP3Buffer.
588  */
589 static void DNP3BufferReset(DNP3Buffer *buffer)
590 {
591  buffer->offset = 0;
592  buffer->len = 0;
593 }
594 
595 /**
596  * \brief Add data to a DNP3 buffer, enlarging the buffer if required.
597  *
598  * \param buffer Buffer to add data data.
599  * \param data Data to be added to buffer.
600  * \param len Size of data to be added to buffer.
601  *
602  * \param 1 if data was added successful, otherwise 0.
603  */
604 static int DNP3BufferAdd(DNP3Buffer *buffer, const uint8_t *data, uint32_t len)
605 {
606  if (buffer->size == 0) {
607  buffer->buffer = SCCalloc(1, len);
608  if (unlikely(buffer->buffer == NULL)) {
609  return 0;
610  }
611  buffer->size = len;
612  }
613  else if (buffer->len + len > buffer->size) {
614  uint8_t *tmp = SCRealloc(buffer->buffer, buffer->len + len);
615  if (unlikely(tmp == NULL)) {
616  return 0;
617  }
618  buffer->buffer = tmp;
619  buffer->size = buffer->len + len;
620  }
621  memcpy(buffer->buffer + buffer->len, data, len);
622  buffer->len += len;
623 
624  return 1;
625 }
626 
627 /**
628  * \brief Trim a DNP3 buffer.
629  *
630  * Trimming a buffer moves the data in the buffer up to the front of
631  * the buffer freeing up room at the end for more incoming data.
632  *
633  * \param buffer The buffer to trim.
634  */
635 static void DNP3BufferTrim(DNP3Buffer *buffer)
636 {
637  if (buffer->offset == buffer->len) {
638  DNP3BufferReset(buffer);
639  }
640  else if (buffer->offset > 0) {
641  memmove(buffer->buffer, buffer->buffer + buffer->offset,
642  buffer->len - buffer->offset);
643  buffer->len = buffer->len - buffer->offset;
644  buffer->offset = 0;
645  }
646 }
647 
648 /**
649  * \brief Free a DNP3 object.
650  */
651 static void DNP3ObjectFree(DNP3Object *object)
652 {
653  if (object->points != NULL) {
654  DNP3FreeObjectPointList(object->group, object->variation,
655  object->points);
656  }
657  SCFree(object);
658 }
659 
660 /**
661  * \breif Allocate a DNP3 object.
662  */
663 static DNP3Object *DNP3ObjectAlloc(void)
664 {
665  DNP3Object *object = SCCalloc(1, sizeof(*object));
666  if (unlikely(object == NULL)) {
667  return NULL;
668  }
669  object->points = DNP3PointListAlloc();
670  if (object->points == NULL) {
671  DNP3ObjectFree(object);
672  return NULL;
673  }
674  return object;
675 }
676 
677 /**
678  * \brief Decode DNP3 application objects.
679  *
680  * This function decoded known DNP3 application objects. As the
681  * protocol isn't self describing, we can only decode the buffer while
682  * the application objects are known. As soon as an unknown
683  * group/variation is hit, we must stop processing.
684  *
685  * \param buf the input buffer
686  * \param len length of the input buffer
687  * \param objects pointer to list where decoded objects will be stored.
688  *
689  * \retval 1 if all objects decoded, 0 if all objects could not be decoded (
690  * unknown group/variations)
691  */
692 static int DNP3DecodeApplicationObjects(DNP3Transaction *tx, const uint8_t *buf,
693  uint32_t len, DNP3ObjectList *objects)
694 {
695  int retval = 0;
696 
697  if (buf == NULL || len == 0) {
698  return 1;
699  }
700 
701  while (len) {
702  uint32_t offset = 0;
703 
704  if (len < sizeof(DNP3ObjHeader)) {
705  goto done;
706  }
707  DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
708  offset += sizeof(DNP3ObjHeader);
709 
710  DNP3Object *object = DNP3ObjectAlloc();
711  if (unlikely(object == NULL)) {
712  goto done;
713  }
714  TAILQ_INSERT_TAIL(objects, object, next);
715 
716  object->group = header->group;
717  object->variation = header->variation;
718  object->qualifier = header->qualifier;
719  object->prefix_code = DNP3_OBJ_PREFIX(header->qualifier);
720  object->range_code = DNP3_OBJ_RANGE(header->qualifier);
721 
722  /* IEEE 1815-2012, Table 4-5. */
723  switch (object->range_code) {
724  case 0x00:
725  case 0x03: {
726  /* 1 octet start and stop indexes OR 1 octet start and
727  * stop virtual addresses. */
728  if (offset + (sizeof(uint8_t) * 2) > len) {
729  /* Not enough data. */
730  SCLogDebug("Not enough data.");
731  goto not_enough_data;
732  }
733  object->start = buf[offset++];
734  object->stop = buf[offset++];
735  object->count = object->stop - object->start + 1;
736  break;
737  }
738  case 0x01:
739  case 0x04: {
740  /* 2 octet start and stop indexes OR 2 octect start
741  * and stop virtual addresses. */
742  if (offset + (sizeof(uint16_t) * 2) > len) {
743  /* Not enough data. */
744  SCLogDebug("Not enough data.");
745  goto not_enough_data;
746  }
747  object->start = DNP3_SWAP16(*(uint16_t *)(buf + offset));
748  offset += sizeof(uint16_t);
749  object->stop = DNP3_SWAP16(*(uint16_t *)(buf + offset));
750  offset += sizeof(uint16_t);
751  object->count = object->stop - object->start + 1;
752  break;
753  }
754  case 0x02:
755  case 0x05: {
756  /* 4 octet start and stop indexes OR 4 octect start
757  * and stop virtual addresses. */
758  if (offset + (sizeof(uint32_t) * 2) > len) {
759  /* Not enough data. */
760  SCLogDebug("Not enough data.");
761  goto not_enough_data;
762  }
763  object->start = DNP3_SWAP32(*(uint32_t *)(buf + offset));
764  offset += sizeof(uint32_t);
765  object->stop = DNP3_SWAP32(*(uint32_t *)(buf + offset));
766  offset += sizeof(uint32_t);
767  object->count = object->stop - object->start + 1;
768  break;
769  }
770  case 0x06:
771  /* No range field. */
772  object->count = 0;
773  break;
774  case 0x07:
775  /* 1 octet count of objects. */
776  if (offset + sizeof(uint8_t) > len) {
777  SCLogDebug("Not enough data.");
778  goto not_enough_data;
779  }
780  object->count = buf[offset];
781  offset += sizeof(uint8_t);
782  break;
783  case 0x08: {
784  /* 2 octet count of objects. */
785  if (offset + sizeof(uint16_t) > len) {
786  SCLogDebug("Not enough data.");
787  goto not_enough_data;
788  }
789  object->count = DNP3_SWAP16(*(uint16_t *)(buf + offset));
790  offset += sizeof(uint16_t);
791  break;
792  }
793  case 0x09: {
794  /* 4 octet count of objects. */
795  if (offset + sizeof(uint32_t) > len) {
796  SCLogDebug("Not enough data.");
797  goto not_enough_data;
798  }
799  object->count = DNP3_SWAP32(*(uint32_t *)(buf + offset));
800  offset += sizeof(uint32_t);
801  break;
802  }
803  case 0x0b: {
804  if (offset + sizeof(uint8_t) > len) {
805  /* Not enough data. */
806  SCLogDebug("Not enough data.");
807  goto not_enough_data;
808  }
809  object->count = *(uint8_t *)(buf + offset);
810  offset += sizeof(uint8_t);
811  break;
812  }
813  default:
814  SCLogDebug("Range code 0x%02x is reserved.",
815  object->range_code);
816  goto done;
817  }
818 
819  buf += offset;
820  len -= offset;
821 
822  if (object->variation == 0 || object->count == 0) {
823  goto next;
824  }
825 
826  int event = DNP3DecodeObject(header->group, header->variation, &buf,
827  &len, object->prefix_code, object->start, object->count,
828  object->points);
829  if (event) {
830  DNP3SetEventTx(tx, DNP3_DECODER_EVENT_UNKNOWN_OBJECT);
831  goto done;
832  }
833 
834  next:
835  continue;
836  }
837 
838  /* All objects were decoded. */
839  retval = 1;
840 
841 not_enough_data:
842 done:
843  return retval;
844 }
845 
846 /**
847  * \brief Handle DNP3 request user data.
848  *
849  * \param dnp3 the current DNP3State
850  * \param input pointer to the DNP3 frame (starting with link header)
851  * \param input_len length of the input frame
852  */
853 static void DNP3HandleUserDataRequest(DNP3State *dnp3, const uint8_t *input,
854  uint32_t input_len)
855 {
856  DNP3LinkHeader *lh;
858  DNP3ApplicationHeader *ah;
859  DNP3Transaction *tx = NULL, *ttx;
860 
861  lh = (DNP3LinkHeader *)input;
862 
863  if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
864  input_len - sizeof(DNP3LinkHeader))) {
865  return;
866  }
867 
868  th = input[sizeof(DNP3LinkHeader)];
869 
870  if (!DNP3_TH_FIR(th)) {
871  TAILQ_FOREACH(ttx, &dnp3->tx_list, next) {
872  if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
873  NEXT_TH_SEQNO(DNP3_TH_SEQ(ttx->th)) == DNP3_TH_SEQ(th)) {
874  tx = ttx;
875  break;
876  }
877  }
878 
879  if (tx == NULL) {
880  return;
881  }
882 
883  /* Update the saved transport header so subsequent segments
884  * will be matched to this sequence number. */
885  tx->th = th;
886  }
887  else {
888  ah = (DNP3ApplicationHeader *)(input + sizeof(DNP3LinkHeader) +
889  sizeof(DNP3TransportHeader));
890 
891  /* Ignore confirms - for now. */
892  if (ah->function_code == DNP3_APP_FC_CONFIRM) {
893  return;
894  }
895 
896  /* Create a transaction. */
897  tx = DNP3TxAlloc(dnp3, true);
898  if (unlikely(tx == NULL)) {
899  return;
900  }
901  tx->lh = *lh;
902  tx->th = th;
903  tx->ah = *ah;
904  }
905 
906  if (!DNP3ReassembleApplicationLayer(input + sizeof(DNP3LinkHeader),
907  input_len - sizeof(DNP3LinkHeader), &tx->buffer, &tx->buffer_len)) {
908 
909  /* Malformed, set event and mark as done. */
910  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_MALFORMED);
911  tx->done = 1;
912  return;
913  }
914 
915  /* If this is not the final segment, just return. */
916  if (!DNP3_TH_FIN(th)) {
917  return;
918  }
919 
920  tx->done = 1;
921 
922  if (DNP3DecodeApplicationObjects(tx, tx->buffer + sizeof(DNP3ApplicationHeader),
923  tx->buffer_len - sizeof(DNP3ApplicationHeader), &tx->objects)) {
924  tx->complete = 1;
925  }
926 }
927 
928 static void DNP3HandleUserDataResponse(DNP3State *dnp3, const uint8_t *input,
929  uint32_t input_len)
930 {
931  DNP3LinkHeader *lh;
933  DNP3ApplicationHeader *ah;
934  DNP3InternalInd *iin;
935  DNP3Transaction *tx = NULL, *ttx;
936  uint32_t offset = 0;
937 
938  lh = (DNP3LinkHeader *)input;
939  offset += sizeof(DNP3LinkHeader);
940 
941  if (!DNP3CheckUserDataCRCs(input + offset, input_len - offset)) {
942  return;
943  }
944 
945  th = input[offset++];
946 
947  if (!DNP3_TH_FIR(th)) {
948  TAILQ_FOREACH(ttx, &dnp3->tx_list, next) {
949  if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
950  !ttx->done && NEXT_TH_SEQNO(DNP3_TH_SEQ(ttx->th)) == DNP3_TH_SEQ(th)) {
951  tx = ttx;
952  break;
953  }
954  }
955 
956  if (tx == NULL) {
957  return;
958  }
959 
960  /* Replace the transport header in the transaction with this
961  * one in case there are more frames. */
962  tx->th = th;
963  }
964  else {
965  ah = (DNP3ApplicationHeader *)(input + offset);
966  offset += sizeof(DNP3ApplicationHeader);
967  iin = (DNP3InternalInd *)(input + offset);
968 
969  tx = DNP3TxAlloc(dnp3, false);
970  if (unlikely(tx == NULL)) {
971  return;
972  }
973  tx->lh = *lh;
974  tx->th = th;
975  tx->ah = *ah;
976  tx->iin = *iin;
977  }
978 
979  BUG_ON(tx->is_request);
980 
981  if (!DNP3ReassembleApplicationLayer(input + sizeof(DNP3LinkHeader),
982  input_len - sizeof(DNP3LinkHeader), &tx->buffer, &tx->buffer_len)) {
983  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_MALFORMED);
984  return;
985  }
986 
987  if (!DNP3_TH_FIN(th)) {
988  return;
989  }
990 
991  tx->done = 1;
992 
993  offset = sizeof(DNP3ApplicationHeader) + sizeof(DNP3InternalInd);
994  if (DNP3DecodeApplicationObjects(
995  tx, tx->buffer + offset, tx->buffer_len - offset, &tx->objects)) {
996  tx->complete = 1;
997  }
998 }
999 
1000 /**
1001  * \brief Decode the DNP3 request link layer.
1002  *
1003  * \retval number of bytes processed or -1 if the data stream does not look
1004  * like DNP3.
1005  */
1006 static int DNP3HandleRequestLinkLayer(DNP3State *dnp3, const uint8_t *input,
1007  uint32_t input_len)
1008 {
1009  SCEnter();
1010  uint32_t processed = 0;
1011 
1012  while (input_len) {
1013 
1014  /* Need at least enough bytes for a DNP3 header. */
1015  if (input_len < sizeof(DNP3LinkHeader)) {
1016  break;
1017  }
1018 
1019  DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1020 
1021  if (!DNP3CheckStartBytes(header)) {
1022  goto error;
1023  }
1024 
1025  if (!DNP3CheckLinkHeaderCRC(header)) {
1026  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_LINK_CRC);
1027  goto error;
1028  }
1029 
1030  uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1031  if (frame_len == 0) {
1032  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1033  goto error;
1034  }
1035  if (input_len < frame_len) {
1036  /* Insufficient data, just break - will wait for more data. */
1037  break;
1038  }
1039 
1040  /* Ignore non-user data for now. */
1041  if (!DNP3IsUserData(header)) {
1042  goto next;
1043  }
1044 
1045  /* Make sure the header length is large enough for transport and
1046  * application headers. */
1047  if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1048  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1049  goto next;
1050  }
1051 
1052  if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
1053  frame_len - sizeof(DNP3LinkHeader))) {
1054  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC);
1055  goto next;
1056  }
1057 
1058  DNP3HandleUserDataRequest(dnp3, input, frame_len);
1059 
1060  next:
1061  /* Advance the input buffer. */
1062  input += frame_len;
1063  input_len -= frame_len;
1064  processed += frame_len;
1065  }
1066 
1067  SCReturnInt(processed);
1068 error:
1069  /* Error out. Should only happen if this doesn't look like a DNP3
1070  * frame. */
1071  SCReturnInt(-1);
1072 }
1073 
1074 /**
1075  * \brief Handle incoming request data.
1076  *
1077  * The actual request PDU parsing is done in
1078  * DNP3HandleRequestLinkLayer. This function takes care of buffering TCP
1079  * date if a segment does not contain a complete frame (or contains
1080  * multiple frames, but not the complete final frame).
1081  */
1082 static AppLayerResult DNP3ParseRequest(Flow *f, void *state, AppLayerParserState *pstate,
1083  StreamSlice stream_slice, void *local_data)
1084 {
1085  SCEnter();
1086  DNP3State *dnp3 = (DNP3State *)state;
1087  DNP3Buffer *buffer = &dnp3->request_buffer;
1088  int processed = 0;
1089 
1090  const uint8_t *input = StreamSliceGetData(&stream_slice);
1091  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1092 
1093  if (input_len == 0) {
1095  }
1096 
1097  if (buffer->len) {
1098  if (!DNP3BufferAdd(buffer, input, input_len)) {
1099  goto error;
1100  }
1101  processed = DNP3HandleRequestLinkLayer(dnp3,
1102  buffer->buffer + buffer->offset,
1103  buffer->len - buffer->offset);
1104  if (processed < 0) {
1105  goto error;
1106  }
1107  buffer->offset += processed;
1108  DNP3BufferTrim(buffer);
1109  }
1110  else {
1111  processed = DNP3HandleRequestLinkLayer(dnp3, input, input_len);
1112  if (processed < 0) {
1113  SCLogDebug("Failed to process request link layer.");
1114  goto error;
1115  }
1116 
1117  input += processed;
1118  input_len -= processed;
1119 
1120  /* Not all data was processed, buffer it. */
1121  if (input_len) {
1122  if (!DNP3BufferAdd(buffer, input, input_len)) {
1123  goto error;
1124  }
1125  }
1126  }
1127 
1129 
1130 error:
1131  /* Reset the buffer. */
1132  DNP3BufferReset(buffer);
1134 }
1135 
1136 /**
1137  * \brief Decode the DNP3 response link layer.
1138  *
1139  * \retval number of bytes processed or -1 if the data stream does not
1140  * like look DNP3.
1141  */
1142 static int DNP3HandleResponseLinkLayer(DNP3State *dnp3, const uint8_t *input,
1143  uint32_t input_len)
1144 {
1145  SCEnter();
1146  uint32_t processed = 0;
1147 
1148  while (input_len) {
1149 
1150  /* Need at least enough bytes for a DNP3 header. */
1151  if (input_len < sizeof(DNP3LinkHeader)) {
1152  break;
1153  }
1154 
1155  DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1156 
1157  if (!DNP3CheckStartBytes(header)) {
1158  goto error;
1159  }
1160 
1161  if (!DNP3CheckLinkHeaderCRC(header)) {
1162  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_LINK_CRC);
1163  goto error;
1164  }
1165 
1166  /* Calculate the number of bytes needed to for this frame. */
1167  uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1168  if (frame_len == 0) {
1169  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1170  goto error;
1171  }
1172  if (input_len < frame_len) {
1173  /* Insufficient data, just break - will wait for more data. */
1174  break;
1175  }
1176 
1177  /* Only handle user data frames for now. */
1178  if (!DNP3IsUserData(header)) {
1179  goto next;
1180  }
1181 
1182  /* Make sure the header length is large enough for transport and
1183  * application headers. */
1184  if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1185  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1186  goto error;
1187  }
1188 
1189  if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
1190  frame_len - sizeof(DNP3LinkHeader))) {
1191  DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC);
1192  goto next;
1193  }
1194 
1195  DNP3HandleUserDataResponse(dnp3, input, frame_len);
1196 
1197  next:
1198  /* Advance the input buffer. */
1199  input += frame_len;
1200  input_len -= frame_len;
1201  processed += frame_len;
1202  }
1203 
1204  SCReturnInt(processed);
1205 error:
1206  /* Error out. Should only happen if the data stream no longer
1207  * looks like DNP3. */
1208  SCReturnInt(-1);
1209 }
1210 
1211 /**
1212  * \brief Parse incoming data.
1213  *
1214  * This is the entry function for DNP3 application layer data. Its
1215  * main responsibility is buffering incoming data that cannot be
1216  * processed.
1217  *
1218  * See DNP3ParseResponsePDUs for DNP3 frame handling.
1219  */
1220 static AppLayerResult DNP3ParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
1221  StreamSlice stream_slice, void *local_data)
1222 {
1223  SCEnter();
1224 
1225  DNP3State *dnp3 = (DNP3State *)state;
1226  DNP3Buffer *buffer = &dnp3->response_buffer;
1227  int processed;
1228 
1229  const uint8_t *input = StreamSliceGetData(&stream_slice);
1230  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1231 
1232  if (buffer->len) {
1233  if (!DNP3BufferAdd(buffer, input, input_len)) {
1234  goto error;
1235  }
1236  processed = DNP3HandleResponseLinkLayer(dnp3,
1237  buffer->buffer + buffer->offset,
1238  buffer->len - buffer->offset);
1239  if (processed < 0) {
1240  goto error;
1241  }
1242  buffer->offset += processed;
1243  DNP3BufferTrim(buffer);
1244  }
1245  else {
1246 
1247  /* Check if this is a banner, ignore if it is. */
1248  if (DNP3ContainsBanner(input, input_len)) {
1249  goto done;
1250  }
1251 
1252  processed = DNP3HandleResponseLinkLayer(dnp3, input, input_len);
1253  if (processed < 0) {
1254  goto error;
1255  }
1256  input += processed;
1257  input_len -= processed;
1258 
1259  /* Not all data was processed, buffer it. */
1260  if (input_len) {
1261  if (!DNP3BufferAdd(buffer, input, input_len)) {
1262  goto error;
1263  }
1264  }
1265  }
1266 
1267 done:
1269 
1270 error:
1271  /* An error occurred while processing DNP3 frames. Dump the
1272  * buffer as we can't be assured that they are valid anymore. */
1273  DNP3BufferReset(buffer);
1275 }
1276 
1277 static void *DNP3GetTx(void *alstate, uint64_t tx_id)
1278 {
1279  SCEnter();
1280  DNP3State *dnp3 = (DNP3State *)alstate;
1281  DNP3Transaction *tx = NULL;
1282  uint64_t tx_num = tx_id + 1;
1283 
1284  if (dnp3->curr && dnp3->curr->tx_num == (tx_num)) {
1285  SCReturnPtr(dnp3->curr, "void");
1286  }
1287 
1288  TAILQ_FOREACH(tx, &dnp3->tx_list, next) {
1289  if (tx_num != tx->tx_num) {
1290  continue;
1291  }
1292  SCReturnPtr(tx, "void");
1293  }
1294 
1295  SCReturnPtr(NULL, "void");
1296 }
1297 
1298 static uint64_t DNP3GetTxCnt(void *state)
1299 {
1300  SCEnter();
1301  uint64_t count = ((uint64_t)((DNP3State *)state)->transaction_max);
1302  SCReturnUInt(count);
1303 }
1304 
1305 /**
1306  * \brief Free all the objects in a DNP3ObjectList.
1307  */
1308 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1309 {
1310  DNP3Object *object;
1311 
1312  while ((object = TAILQ_FIRST(objects)) != NULL) {
1313  TAILQ_REMOVE(objects, object, next);
1314  DNP3ObjectFree(object);
1315  }
1316 }
1317 
1318 /**
1319  * \brief Free a DNP3 transaction.
1320  */
1321 static void DNP3TxFree(DNP3Transaction *tx)
1322 {
1323  SCEnter();
1324 
1325  if (tx->buffer != NULL) {
1326  SCFree(tx->buffer);
1327  }
1328 
1330 
1331  if (tx->tx_data.de_state != NULL) {
1332  DetectEngineStateFree(tx->tx_data.de_state);
1333  }
1334 
1335  DNP3TxFreeObjectList(&tx->objects);
1336 
1337  SCFree(tx);
1338  SCReturn;
1339 }
1340 
1341 /**
1342  * \brief Free a transaction by ID on a specific DNP3 state.
1343  *
1344  * This function is called by the app-layer to free a transaction on a
1345  * specific DNP3 state object.
1346  */
1347 static void DNP3StateTxFree(void *state, uint64_t tx_id)
1348 {
1349  SCEnter();
1350  DNP3State *dnp3 = state;
1351  DNP3Transaction *tx = NULL, *ttx;
1352  uint64_t tx_num = tx_id + 1;
1353 
1354  TAILQ_FOREACH_SAFE(tx, &dnp3->tx_list, next, ttx) {
1355 
1356  if (tx->tx_num != tx_num) {
1357  continue;
1358  }
1359 
1360  if (tx == dnp3->curr) {
1361  dnp3->curr = NULL;
1362  }
1363 
1364  if (tx->tx_data.events != NULL) {
1365  if (tx->tx_data.events->cnt <= dnp3->events) {
1366  dnp3->events -= tx->tx_data.events->cnt;
1367  } else {
1368  dnp3->events = 0;
1369  }
1370  }
1371  dnp3->unreplied--;
1372 
1373  /* Check flood state. */
1374  if (dnp3->flooded && dnp3->unreplied < DNP3_DEFAULT_REQ_FLOOD_COUNT) {
1375  dnp3->flooded = 0;
1376  }
1377 
1378  TAILQ_REMOVE(&dnp3->tx_list, tx, next);
1379  DNP3TxFree(tx);
1380  break;
1381  }
1382 
1383  SCReturn;
1384 }
1385 
1386 /**
1387  * \brief Free a DNP3 state.
1388  */
1389 static void DNP3StateFree(void *state)
1390 {
1391  SCEnter();
1392  DNP3State *dnp3 = state;
1393  DNP3Transaction *tx;
1394  if (state != NULL) {
1395  while ((tx = TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1396  TAILQ_REMOVE(&dnp3->tx_list, tx, next);
1397  DNP3TxFree(tx);
1398  }
1399  if (dnp3->request_buffer.buffer != NULL) {
1400  SCFree(dnp3->request_buffer.buffer);
1401  }
1402  if (dnp3->response_buffer.buffer != NULL) {
1403  SCFree(dnp3->response_buffer.buffer);
1404  }
1405  SCFree(dnp3);
1406  }
1407  SCReturn;
1408 }
1409 
1410 /**
1411  * \brief Called by the app-layer to get the state progress.
1412  */
1413 static int DNP3GetAlstateProgress(void *tx, uint8_t direction)
1414 {
1415  DNP3Transaction *dnp3tx = (DNP3Transaction *)tx;
1416  DNP3State *dnp3 = dnp3tx->dnp3;
1417  int retval = 0;
1418 
1419  /* If flooded, "ack" old transactions. */
1420  if (dnp3->flooded && (dnp3->transaction_max -
1421  dnp3tx->tx_num >= DNP3_DEFAULT_REQ_FLOOD_COUNT)) {
1422  SCLogDebug("flooded: returning tx as done.");
1423  SCReturnInt(1);
1424  }
1425 
1426  /* This is a unidirectional protocol.
1427  *
1428  * If progress is being checked in the TOSERVER (request)
1429  * direction, always return complete if the message is not a
1430  * request, as there will never be replies on transactions created
1431  * in the TOSERVER direction.
1432  *
1433  * Like wise, if progress is being checked in the TOCLIENT
1434  * direction, requests will never be seen. So always return
1435  * complete if the transaction is not a reply.
1436  *
1437  * Otherwise, if TOSERVER and transaction is a request, return
1438  * complete if the transaction is complete. And if TOCLIENT and
1439  * transaction is a response, return complete if the transaction
1440  * is complete.
1441  */
1442  if (direction & STREAM_TOSERVER) {
1443  if (!dnp3tx->is_request || dnp3tx->complete) {
1444  retval = 1;
1445  }
1446  } else if (direction & STREAM_TOCLIENT) {
1447  if (dnp3tx->is_request || dnp3tx->complete) {
1448  retval = 1;
1449  }
1450  }
1451 
1452  SCReturnInt(retval);
1453 }
1454 
1455 /**
1456  * \brief App-layer support.
1457  */
1458 static int DNP3StateGetEventInfo(const char *event_name, int *event_id,
1459  AppLayerEventType *event_type)
1460 {
1461  *event_id = SCMapEnumNameToValue(event_name, dnp3_decoder_event_table);
1462  if (*event_id == -1) {
1463  SCLogError("Event \"%s\" not present in "
1464  "the DNP3 enum event map table.",
1465  event_name);
1466  return -1;
1467  }
1468 
1469  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1470 
1471  return 0;
1472 }
1473 
1474 /**
1475  * \brief App-layer support.
1476  */
1477 static int DNP3StateGetEventInfoById(int event_id, const char **event_name,
1478  AppLayerEventType *event_type)
1479 {
1480  *event_name = SCMapEnumValueToName(event_id, dnp3_decoder_event_table);
1481  if (*event_name == NULL) {
1482  SCLogError("Event \"%d\" not present in "
1483  "the DNP3 enum event map table.",
1484  event_id);
1485  return -1;
1486  }
1487 
1488  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1489 
1490  return 0;
1491 }
1492 
1493 static AppLayerTxData *DNP3GetTxData(void *vtx)
1494 {
1495  DNP3Transaction *tx = (DNP3Transaction *)vtx;
1496  return &tx->tx_data;
1497 }
1498 
1499 static AppLayerStateData *DNP3GetStateData(void *vstate)
1500 {
1501  DNP3State *state = (DNP3State *)vstate;
1502  return &state->state_data;
1503 }
1504 
1505 /**
1506  * \brief Check if the prefix code is a size prefix.
1507  *
1508  * \retval 1 if the prefix_code specifies a size prefix, 0 if not.
1509  */
1510 int DNP3PrefixIsSize(uint8_t prefix_code)
1511 {
1512  switch (prefix_code) {
1513  case 0x04:
1514  case 0x05:
1515  case 0x06:
1516  return 1;
1517  break;
1518  default:
1519  return 0;
1520  }
1521 }
1522 
1523 /**
1524  * \brief Register the DNP3 application protocol parser.
1525  */
1527 {
1528  SCEnter();
1529 
1530  const char *proto_name = "dnp3";
1531 
1532  if (AppLayerProtoDetectConfProtoDetectionEnabledDefault("tcp", proto_name, false)) {
1534 
1535  if (RunmodeIsUnittests()) {
1537  ALPROTO_DNP3, 0, sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1538  DNP3ProbingParser, DNP3ProbingParser);
1539  }
1540  else {
1541  if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
1542  proto_name, ALPROTO_DNP3, 0, sizeof(DNP3LinkHeader),
1543  DNP3ProbingParser, DNP3ProbingParser)) {
1544  return;
1545  }
1546  }
1547 
1548  } else {
1549  SCLogConfig("Protocol detection and parser disabled for DNP3.");
1550  SCReturn;
1551  }
1552 
1553  if (AppLayerParserConfParserEnabled("tcp", proto_name))
1554  {
1555  SCLogConfig("Registering DNP3/tcp parsers.");
1556 
1557  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DNP3, STREAM_TOSERVER,
1558  DNP3ParseRequest);
1559  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DNP3, STREAM_TOCLIENT,
1560  DNP3ParseResponse);
1561 
1563  DNP3StateAlloc, DNP3StateFree);
1564 
1565  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTx);
1566  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxCnt);
1568  DNP3StateTxFree);
1569 
1571  DNP3GetAlstateProgress);
1573 
1575  DNP3StateGetEventInfo);
1577  DNP3StateGetEventInfoById);
1578 
1580  DNP3GetTxData);
1581  AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetStateData);
1582 #if 0
1583  /* While this parser is now fully unidirectional. setting this
1584  * flag breaks detection at this time. */
1587 #endif
1588  }
1589  else {
1590  SCLogConfig("Parser disabled for protocol %s. "
1591  "Protocol detection still on.", proto_name);
1592  }
1593 
1594 #ifdef UNITTESTS
1597 #endif
1598 
1599  SCReturn;
1600 }
1601 
1602 #ifdef UNITTESTS
1603 
1604 #include "flow-util.h"
1605 #include "stream-tcp.h"
1606 
1607 /**
1608  * \brief Utility function to fix CRCs when mangling a frame.
1609  */
1610 static void DNP3FixCrc(uint8_t *data, uint32_t len)
1611 {
1612  uint32_t block_size;
1613 
1614  while (len) {
1615  if (len >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
1616  block_size = DNP3_BLOCK_SIZE;
1617  } else {
1618  block_size = len - DNP3_CRC_LEN;
1619  }
1620  uint16_t crc = DNP3ComputeCRC(data, block_size);
1621  data[block_size + 1] = (crc >> 8) & 0xff;
1622  data[block_size] = crc & 0xff;
1623  data += block_size + DNP3_CRC_LEN;
1624  len -= block_size + DNP3_CRC_LEN;
1625  }
1626 }
1627 
1628 /**
1629  * \test Test CRC checking on partial and full blocks.
1630  */
1631 static int DNP3ParserTestCheckCRC(void)
1632 {
1633  uint8_t request[] = {
1634  /* DNP3 start. */
1635  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1636  0xa5, 0xe9,
1637 
1638  /* Transport header. */
1639  0xff,
1640 
1641  /* Application layer - segment 1. */
1642  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1643  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1644  0xef,
1645 
1646  /* Application layer - segment 2. */
1647  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1648  };
1649 
1650  /* Check link header CRC. */
1651  FAIL_IF(!DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1652 
1653  /* Check first application layer segment. */
1654  FAIL_IF(!DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1656 
1657 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1658  /* Change a byte in link header, should fail now. */
1659  request[2]++;
1660  FAIL_IF(DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1661 
1662  /* Change a byte in the first application segment, should fail
1663  * now. */
1664  request[sizeof(DNP3LinkHeader) + 3]++;
1665  FAIL_IF(DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1667 #endif
1668 
1669  PASS;
1670 }
1671 
1672 /**
1673  * \test Test validation of all CRCs in user data.
1674  */
1675 static int DNP3CheckUserDataCRCsTest(void)
1676 {
1677  /* Multi-block data with valid CRCs. */
1678  uint8_t data_valid[] = {
1679  0xff, 0xc9, 0x05, 0x0c,
1680  0x01, 0x28, 0x01, 0x00,
1681  0x00, 0x00, 0x01, 0x01,
1682  0x01, 0x00, 0x00, 0x00,
1683  0x72, 0xef, /* CRC. */
1684 
1685  0xff, 0xc9, 0x05, 0x0c,
1686  0x01, 0x28, 0x01, 0x00,
1687  0x00, 0x00, 0x01, 0x01,
1688  0x01, 0x00, 0x00, 0x00,
1689  0x72, 0xef, /* CRC. */
1690 
1691  0xff, 0xc9, 0x05, 0x0c,
1692  0x01, 0x28, 0x01, 0x00,
1693  0x00, 0x00, 0x01, 0x01,
1694  0x01, 0x00, 0x00, 0x00,
1695  0x72, 0xef, /* CRC. */
1696 
1697  0x00, 0x00, 0x00, 0x00,
1698  0x00,
1699  0xff, 0xff, /* CRC. */
1700  };
1701  FAIL_IF(!DNP3CheckUserDataCRCs(data_valid, sizeof(data_valid)));
1702 
1703 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1704  /* Multi-block data with one non-crc byte altered. */
1705  uint8_t data_invalid[] = {
1706  0xff, 0xc9, 0x05, 0x0c,
1707  0x01, 0x28, 0x01, 0x00,
1708  0x00, 0x00, 0x01, 0x01,
1709  0x01, 0x00, 0x00, 0x00,
1710  0x72, 0xef, /* CRC. */
1711 
1712  0xff, 0xc9, 0x05, 0x0c,
1713  0x01, 0x28, 0x01, 0x00,
1714  0x00, 0x00, 0x01, 0x01,
1715  0x01, 0x00, 0x00, 0x00,
1716  0x72, 0xef, /* CRC. */
1717 
1718  0xff, 0xc9, 0x05, 0x0c,
1719  0x01, 0x28, 0x01, 0x00,
1720  0x00, 0x00, 0x01, 0x01,
1721  0x01, 0x00, 0x00, 0x00,
1722  0x72, 0xef, /* CRC. */
1723 
1724  0x00, 0x00, 0x00, 0x00,
1725  0x01, /* Invalid byte. */
1726  0xff, 0xff, /* CRC. */
1727  };
1728  FAIL_IF(DNP3CheckUserDataCRCs(data_invalid, sizeof(data_invalid)));
1729 
1730  /* 1 byte - need at least 3. */
1731  uint8_t one_byte_nocrc[] = { 0x01 };
1732  FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc, sizeof(one_byte_nocrc)));
1733 
1734  /* 2 bytes - need at least 3. */
1735  uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1736  FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc, sizeof(two_byte_nocrc)));
1737 #endif
1738 
1739  /* 3 bytes, valid CRC. */
1740  uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1741  *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1742  three_bytes_good_crc, 1);
1743  FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1744  sizeof(three_bytes_good_crc)));
1745 
1746  PASS;
1747 }
1748 
1749 /**
1750  * \test Test the link layer length calculation.
1751  *
1752  * Test the calculation that converts the link provided in the DNP3
1753  * header to the actual length of the frame. That is the length with
1754  * CRCs as the length in the header does not include CRCs.
1755  */
1756 static int DNP3CalculateLinkLengthTest(void)
1757 {
1758  /* These are invalid. */
1759  FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1760  FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1761  FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1762  FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1763  FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1764 
1765  /* This is the minimum size. */
1766  FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1767 
1768  /* 1 full user data blocks of data. */
1769  FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1770 
1771  /* 2 full user data blocks of data. */
1772  FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1773 
1774  /* 2 full user data blocks, plus one more byte. */
1775  /* 2 full user data blocks of data. */
1776  FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1777 
1778  /* The maximum size. */
1779  FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1780 
1781  PASS;
1782 }
1783 
1784 /**
1785  * \test The conversion of length with CRCs to the length without
1786  * CRCs.
1787  */
1788 static int DNP3CalculateTransportLengthWithoutCRCsTest(void)
1789 {
1790  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1791  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1792  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1793  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1794  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1795  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1796  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1797 
1798  /* 19 bytes is not enough for a second block. */
1799  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1800 
1801  /* 20 bytes really isn't enough either, but is large enough to
1802  * satisfy the CRC on the second block. */
1803  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1804 
1805  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1806 
1807  PASS;
1808 }
1809 
1810 /**
1811  * \test Test the validation of the link header CRC.
1812  */
1813 static int DNP3ParserCheckLinkHeaderCRC(void)
1814 {
1815  /* DNP3 frame with valid headers and CRCs. */
1816  uint8_t request[] = {
1817  /* DNP3 start. */
1818  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1819  0xa5, 0xe9,
1820 
1821  /* Transport header. */
1822  0xff,
1823 
1824  /* Application layer. */
1825  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1826  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1827  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1828  };
1829 
1830  DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1831  FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1832 
1833 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1834  /* Alter a byte in the header. */
1835  request[4] = 0;
1836  FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1837 #endif
1838 
1839  PASS;
1840 }
1841 
1842 /**
1843  * \test Test removal of CRCs from user data.
1844  */
1845 static int DNP3ReassembleApplicationLayerTest01(void)
1846 {
1847  uint32_t reassembled_len = 0;
1848  uint8_t *output = NULL;
1849 
1850  uint8_t payload[] = {
1851 
1852  0xff, 0xc9, 0x05, 0x0c,
1853  0x01, 0x28, 0x01, 0x00,
1854  0x00, 0x00, 0x01, 0x01,
1855  0x01, 0x00, 0x00, 0x00,
1856  0x72, 0xef, /* CRC. */
1857 
1858  0xff, 0xc9, 0x05, 0x0c,
1859  0x01, 0x28, 0x01, 0x00,
1860  0x00, 0x00, 0x01, 0x01,
1861  0x01, 0x00, 0x00, 0x00,
1862  0x72, 0xef, /* CRC. */
1863 
1864  0xff, 0xc9, 0x05, 0x0c,
1865  0x01, 0x28, 0x01, 0x00,
1866  0x00, 0x00, 0x01, 0x01,
1867  0x01, 0x00, 0x00, 0x00,
1868  0x72, 0xef, /* CRC. */
1869 
1870  0x00, 0x00, 0x00, 0x00,
1871  0x00,
1872  0xff, 0xff, /* CRC. */
1873  };
1874 
1875  uint8_t expected[] = {
1876  0xc9, 0x05, 0x0c,
1877  0x01, 0x28, 0x01, 0x00,
1878  0x00, 0x00, 0x01, 0x01,
1879  0x01, 0x00, 0x00, 0x00,
1880  /* CRC removed. */
1881  0xff, 0xc9, 0x05, 0x0c,
1882  0x01, 0x28, 0x01, 0x00,
1883  0x00, 0x00, 0x01, 0x01,
1884  0x01, 0x00, 0x00, 0x00,
1885  /* CRC removed. */
1886  0xff, 0xc9, 0x05, 0x0c,
1887  0x01, 0x28, 0x01, 0x00,
1888  0x00, 0x00, 0x01, 0x01,
1889  0x01, 0x00, 0x00, 0x00,
1890  /* CRC removed. */
1891  0x00, 0x00, 0x00, 0x00,
1892  0x00
1893  /* CRC removed. */
1894  };
1895 
1896  /* Valid frame. */
1897  FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1898  sizeof(payload), &output, &reassembled_len));
1899  FAIL_IF(output == NULL);
1900  FAIL_IF(reassembled_len != sizeof(expected));
1901  FAIL_IF(memcmp(expected, output, reassembled_len));
1902  SCFree(output);
1903 
1904  /* 1 byte, invalid. */
1905  reassembled_len = 0;
1906  output = NULL;
1907  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1908  &reassembled_len));
1909  FAIL_IF(output != NULL);
1910  FAIL_IF(reassembled_len != 0);
1911 
1912  /* 2 bytes, invalid. */
1913  reassembled_len = 0;
1914  output = NULL;
1915  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1916  &reassembled_len));
1917  FAIL_IF(output != NULL);
1918  FAIL_IF(reassembled_len != 0);
1919 
1920  /* 3 bytes, minimum - but that would only be the transport header
1921  * which isn't included in the output. */
1922  reassembled_len = 0;
1923  output = NULL;
1924  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1925  &reassembled_len));
1926  FAIL_IF(output != NULL);
1927  FAIL_IF(reassembled_len != 0);
1928 
1929  /* 4 bytes is the minimum to get any reassembled data. */
1930  reassembled_len = 0;
1931  output = NULL;
1932  FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1933  &reassembled_len));
1934  FAIL_IF(output == NULL);
1935  FAIL_IF(reassembled_len != 1);
1936 
1937  /* Last block too short (by 1 byte) for data + CRC. */
1938  uint8_t short_payload1[] = {
1939 
1940  0xff, 0xc9, 0x05, 0x0c,
1941  0x01, 0x28, 0x01, 0x00,
1942  0x00, 0x00, 0x01, 0x01,
1943  0x01, 0x00, 0x00, 0x00,
1944  0x72, 0xef, /* CRC. */
1945 
1946  0xff, 0xc9, 0x05, 0x0c,
1947  0x01, 0x28, 0x01, 0x00,
1948  0x00, 0x00, 0x01, 0x01,
1949  0x01, 0x00, 0x00, 0x00,
1950  0x72, 0xef, /* CRC. */
1951 
1952  0xff, 0xc9, 0x05, 0x0c,
1953  0x01, 0x28, 0x01, 0x00,
1954  0x00, 0x00, 0x01, 0x01,
1955  0x01, 0x00, 0x00, 0x00,
1956  0x72, 0xef, /* CRC. */
1957 
1958  0x00, 0x00
1959  };
1960  reassembled_len = 0;
1961  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1962  sizeof(short_payload1), &output, &reassembled_len));
1963 
1964  /* Last block too short (by 2 bytes) for data + CRC. */
1965  uint8_t short_payload2[] = {
1966 
1967  0xff, 0xc9, 0x05, 0x0c,
1968  0x01, 0x28, 0x01, 0x00,
1969  0x00, 0x00, 0x01, 0x01,
1970  0x01, 0x00, 0x00, 0x00,
1971  0x72, 0xef, /* CRC. */
1972 
1973  0xff, 0xc9, 0x05, 0x0c,
1974  0x01, 0x28, 0x01, 0x00,
1975  0x00, 0x00, 0x01, 0x01,
1976  0x01, 0x00, 0x00, 0x00,
1977  0x72, 0xef, /* CRC. */
1978 
1979  0xff, 0xc9, 0x05, 0x0c,
1980  0x01, 0x28, 0x01, 0x00,
1981  0x00, 0x00, 0x01, 0x01,
1982  0x01, 0x00, 0x00, 0x00,
1983  0x72, 0xef, /* CRC. */
1984 
1985  0x00,
1986  };
1987  reassembled_len = 0;
1988  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
1989  sizeof(short_payload2), &output, &reassembled_len));
1990 
1991  PASS;
1992 }
1993 
1994 /**
1995  * \test Test the probing parser.
1996  */
1997 static int DNP3ProbingParserTest(void)
1998 {
1999  uint8_t pkt[] = {
2000  0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2001  0xbd, 0x71
2002  };
2003  uint8_t rdir = 0;
2004 
2005  /* Valid frame. */
2006  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_DNP3);
2007 
2008  /* Send too little bytes. */
2009  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(DNP3LinkHeader) - 1, &rdir) != ALPROTO_UNKNOWN);
2010 
2011  /* Bad start bytes. */
2012  pkt[0] = 0x06;
2013  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2014 
2015  /* Restore start byte. */
2016  pkt[0] = 0x05;
2017 
2018  /* Set the length to a value less than the minimum length of 5. */
2019  pkt[2] = 0x03;
2020  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2021 
2022  /* Send a banner. */
2023  char mybanner[] = "Welcome to DNP3 SCADA.";
2024  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner, sizeof(mybanner) - 1,
2025  &rdir) != ALPROTO_DNP3);
2026  FAIL_IF(rdir != STREAM_TOCLIENT);
2027 
2028  PASS;
2029 }
2030 
2031 /**
2032  * \test Test a basic request/response.
2033  */
2034 static int DNP3ParserTestRequestResponse(void)
2035 {
2036  DNP3State *state = NULL;
2037 
2038  uint8_t request[] = {
2039  /* DNP3 start. */
2040  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2041  0xa5, 0xe9,
2042 
2043  /* Transport header. */
2044  0xff,
2045 
2046  /* Application layer. */
2047  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2048  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2049  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2050  };
2051 
2052  uint8_t response[] = {
2053  /* DNP3 start. */
2054  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2055  0xe2, 0x59,
2056 
2057  /* Transport header. */
2058  0xc3,
2059 
2060  /* Application layer. */
2061  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2062  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2063  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2064  0xff, 0xff
2065  };
2066 
2068  Flow flow;
2069  TcpSession ssn;
2070 
2071  memset(&flow, 0, sizeof(flow));
2072  memset(&ssn, 0, sizeof(ssn));
2073 
2074  flow.protoctx = (void *)&ssn;
2075  flow.proto = IPPROTO_TCP;
2076  flow.alproto = ALPROTO_DNP3;
2077 
2078  StreamTcpInitConfig(true);
2079 
2080  SCMutexLock(&flow.m);
2082  STREAM_TOSERVER, request, sizeof(request)));
2083  SCMutexUnlock(&flow.m);
2084 
2085  state = flow.alstate;
2086  FAIL_IF(state == NULL);
2087 
2088  DNP3Transaction *tx = DNP3GetTx(state, 0);
2089  FAIL_IF(tx == NULL);
2090  FAIL_IF(tx->tx_num != 1);
2091  FAIL_IF(tx != state->curr);
2092  FAIL_IF(tx->buffer == NULL);
2093  FAIL_IF(tx->buffer_len != 20);
2094  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2095 
2096  SCMutexLock(&flow.m);
2098  STREAM_TOCLIENT, response, sizeof(response)));
2099  SCMutexUnlock(&flow.m);
2100  DNP3Transaction *tx0 = DNP3GetTx(state, 1);
2101  FAIL_IF(tx0 == NULL);
2102  FAIL_IF(tx0 == tx);
2103  FAIL_IF(!tx0->done);
2104  FAIL_IF(tx0->buffer == NULL);
2105 
2107  StreamTcpFreeConfig(true);
2108  FLOW_DESTROY(&flow);
2109  PASS;
2110 }
2111 
2112 /**
2113  * \test Test an unsolicited response from an outstation.
2114  *
2115  * This is kind of like a request initiated from the "server".
2116  */
2117 static int DNP3ParserTestUnsolicitedResponseConfirm(void)
2118 {
2119  DNP3State *state = NULL;
2120 
2121  /* Unsolicited response with confirm bit set. */
2122  uint8_t response[] = {
2123  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2124  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2125  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2126  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2127  };
2128 
2129  /* Confirm. */
2130  uint8_t confirm[] = {
2131  0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2132  0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2133  0x3d
2134  };
2135 
2137  Flow flow;
2138  TcpSession ssn;
2139 
2140  memset(&flow, 0, sizeof(flow));
2141  memset(&ssn, 0, sizeof(ssn));
2142 
2143  flow.protoctx = (void *)&ssn;
2144  flow.proto = IPPROTO_TCP;
2145  flow.alproto = ALPROTO_DNP3;
2146 
2147  StreamTcpInitConfig(true);
2148 
2149  SCMutexLock(&flow.m);
2151  STREAM_TOCLIENT, response, sizeof(response)));
2152  SCMutexUnlock(&flow.m);
2153 
2154  state = flow.alstate;
2155  FAIL_IF(state == NULL);
2156 
2157  DNP3Transaction *tx = DNP3GetTx(state, 0);
2158  FAIL_IF(tx == NULL);
2159  FAIL_IF(tx->tx_num != 1);
2160  FAIL_IF(tx != state->curr);
2161  FAIL_IF(!tx->done);
2162  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_UNSOLICITED_RESP);
2163 
2164  SCMutexLock(&flow.m);
2166  STREAM_TOSERVER, confirm, sizeof(confirm)));
2167  SCMutexUnlock(&flow.m);
2168 
2169  /* Confirms are ignored currently. With the move to
2170  unidirectional transactions it might be easy to support these
2171  now. */
2172  DNP3Transaction *resptx = DNP3GetTx(state, 1);
2173  FAIL_IF(resptx);
2174 
2176  StreamTcpFreeConfig(true);
2177  FLOW_DESTROY(&flow);
2178  PASS;
2179 }
2180 
2181 /**
2182  * \test Test flood state.
2183  *
2184  * Note that flood state needs to revisited with the modification to a
2185  * unidirectional protocol.
2186  */
2187 static int DNP3ParserTestFlooded(void)
2188 {
2189  DNP3State *state = NULL;
2190 
2191  uint8_t request[] = {
2192  /* DNP3 start. */
2193  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2194  0xa5, 0xe9,
2195 
2196  /* Transport header. */
2197  0xff,
2198 
2199  /* Application layer. */
2200  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2201  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2202  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2203  };
2204 
2206  Flow flow;
2207  TcpSession ssn;
2208 
2209  memset(&flow, 0, sizeof(flow));
2210  memset(&ssn, 0, sizeof(ssn));
2211 
2212  flow.protoctx = (void *)&ssn;
2213  flow.proto = IPPROTO_TCP;
2214  flow.alproto = ALPROTO_DNP3;
2215 
2216  StreamTcpInitConfig(true);
2217 
2218  SCMutexLock(&flow.m);
2220  STREAM_TOSERVER, request, sizeof(request)));
2221  SCMutexUnlock(&flow.m);
2222 
2223  state = flow.alstate;
2224  FAIL_IF(state == NULL);
2225 
2226  DNP3Transaction *tx = DNP3GetTx(state, 0);
2227  FAIL_IF(tx == NULL);
2228  FAIL_IF(tx->tx_num != 1);
2229  FAIL_IF(tx != state->curr);
2230  FAIL_IF(tx->buffer == NULL);
2231  FAIL_IF(tx->buffer_len != 20);
2232  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2233  FAIL_IF_NOT(tx->done);
2234  FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2235 
2236  for (int i = 0; i < DNP3_DEFAULT_REQ_FLOOD_COUNT - 1; i++) {
2237  SCMutexLock(&flow.m);
2239  STREAM_TOSERVER, request, sizeof(request)));
2240  SCMutexUnlock(&flow.m);
2241  }
2242  FAIL_IF(state->flooded);
2243  FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2244 
2245  /* One more request should trip us into flooded state. */
2246  SCMutexLock(&flow.m);
2248  STREAM_TOSERVER, request, sizeof(request)));
2249  SCMutexUnlock(&flow.m);
2250  FAIL_IF(!state->flooded);
2251 
2252  /* Progress for the oldest tx should return 1. */
2253  FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2254 
2256  StreamTcpFreeConfig(true);
2257  FLOW_DESTROY(&flow);
2258  PASS;
2259 }
2260 
2261 /**
2262  * \test Test parsing of partial frames.
2263  *
2264  * As DNP3 operates over TCP, it is possible that a partial DNP3 frame
2265  * is received. Test that the partial frame will be buffered until the
2266  * remainder is seen.
2267  */
2268 static int DNP3ParserTestPartialFrame(void)
2269 {
2270  DNP3State *state = NULL;
2271  DNP3Transaction *tx;
2272  int r;
2273 
2274  uint8_t request_partial1[] = {
2275  /* DNP3 start. */
2276  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2277  0xa5, 0xe9,
2278 
2279  /* Transport header. */
2280  0xff,
2281 
2282  /* Application layer. */
2283  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2284  };
2285 
2286  uint8_t request_partial2[] = {
2287  /* Remainder of application layer. */
2288  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2289  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2290  };
2291 
2292  uint8_t response_partial1[] = {
2293  /* DNP3 start. */
2294  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2295  0xe2, 0x59,
2296 
2297  /* Transport header. */
2298  0xc3,
2299 
2300  /* Application layer. */
2301  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2302  };
2303 
2304  uint8_t response_partial2[] = {
2305  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2306  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2307  0xff, 0xff
2308  };
2309 
2310  /* Boiler plate for app layer setup. */
2312  Flow flow;
2313  TcpSession ssn;
2314  memset(&flow, 0, sizeof(flow));
2315  memset(&ssn, 0, sizeof(ssn));
2316  flow.protoctx = (void *)&ssn;
2317  flow.proto = IPPROTO_TCP;
2318  flow.alproto = ALPROTO_DNP3;
2319  StreamTcpInitConfig(true);
2320 
2321  /* Pass in the first partial frame. */
2322 
2323  SCMutexLock(&flow.m);
2324  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2325  STREAM_TOSERVER, request_partial1, sizeof(request_partial1));
2326  SCMutexUnlock(&flow.m);
2327  FAIL_IF(r != 0);
2328 
2329  /* Frame should just be buffered, but not yet processed. */
2330  state = flow.alstate;
2331  FAIL_IF(state == NULL);
2332  FAIL_IF(state->request_buffer.len != sizeof(request_partial1));
2333  FAIL_IF(state->request_buffer.offset != 0);
2334  FAIL_IF(memcmp(state->request_buffer.buffer, request_partial1,
2335  sizeof(request_partial1)));
2336 
2337  /* There should not be a transaction yet. */
2338  FAIL_IF(state->transaction_max != 0);
2339  FAIL_IF(DNP3GetTx(state, 0) != NULL);
2340 
2341  /* Send the second partial. */
2342  SCMutexLock(&flow.m);
2343  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2344  STREAM_TOSERVER, request_partial2, sizeof(request_partial2));
2345  SCMutexUnlock(&flow.m);
2346  FAIL_IF(r != 0);
2347 
2348  /* The second partial completed the frame, the buffer should now
2349  * be clear. */
2350  FAIL_IF(state->request_buffer.len != 0);
2351  FAIL_IF(state->request_buffer.offset != 0);
2352 
2353  /* Should now have a complete transaction. */
2354  tx = DNP3GetTx(state, 0);
2355  FAIL_IF(tx == NULL);
2356  FAIL_IF(tx->tx_num != 1);
2357  FAIL_IF(tx != state->curr);
2358  FAIL_IF(tx->buffer == NULL);
2359  FAIL_IF(tx->buffer_len != 20);
2360  FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2361 
2362  /* Send partial response. */
2363  SCMutexLock(&flow.m);
2364  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2365  STREAM_TOCLIENT, response_partial1, sizeof(response_partial1));
2366  SCMutexUnlock(&flow.m);
2367  FAIL_IF(r != 0);
2368  FAIL_IF(state->response_buffer.len != sizeof(response_partial1));
2369  FAIL_IF(state->response_buffer.offset != 0);
2370  tx = DNP3GetTx(state, 1);
2371  FAIL_IF_NOT_NULL(tx);
2372 
2373  /* Send rest of response. */
2374  SCMutexLock(&flow.m);
2375  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2376  STREAM_TOCLIENT, response_partial2, sizeof(response_partial2));
2377  SCMutexUnlock(&flow.m);
2378  FAIL_IF(r != 0);
2379 
2380  /* Buffer should now be empty. */
2381  FAIL_IF(state->response_buffer.len != 0);
2382  FAIL_IF(state->response_buffer.offset != 0);
2383 
2384  /* There should now be a response transaction. */
2385  tx = DNP3GetTx(state, 1);
2386  FAIL_IF_NULL(tx);
2387  FAIL_IF(tx->buffer == NULL);
2388  FAIL_IF(tx->buffer_len == 0);
2389 
2391  StreamTcpFreeConfig(true);
2392  FLOW_DESTROY(&flow);
2393  PASS;
2394 }
2395 
2396 /**
2397  * \test Test multiple DNP3 frames in one TCP read.
2398  */
2399 static int DNP3ParserTestMultiFrame(void)
2400 {
2401  DNP3State *state = NULL;
2402 
2403  /* Unsolicited response 1. */
2404  uint8_t unsol_response1[] = {
2405  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2406  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2407  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2408  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2409  };
2410 
2411  /* Unsolicited response 2. */
2412  uint8_t unsol_response2[] = {
2413  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2414  0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2415  0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2416  0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2417  };
2418 
2419  uint8_t combined[sizeof(unsol_response1) + sizeof(unsol_response2)];
2420  memcpy(combined, unsol_response1, sizeof(unsol_response1));
2421  memcpy(combined + sizeof(unsol_response1), unsol_response2,
2422  sizeof(unsol_response2));
2423 
2424  /* Setup. */
2426  Flow flow;
2427  TcpSession ssn;
2428  int r;
2429  memset(&flow, 0, sizeof(flow));
2430  memset(&ssn, 0, sizeof(ssn));
2431  flow.protoctx = (void *)&ssn;
2432  flow.proto = IPPROTO_TCP;
2433  flow.alproto = ALPROTO_DNP3;
2434  StreamTcpInitConfig(true);
2435 
2436  SCMutexLock(&flow.m);
2437  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2438  STREAM_TOCLIENT, combined, sizeof(combined));
2439  SCMutexUnlock(&flow.m);
2440  FAIL_IF(r != 0);
2441 
2442  state = flow.alstate;
2443  FAIL_IF(state == NULL);
2444  FAIL_IF(state->transaction_max != 2);
2445 
2447  StreamTcpFreeConfig(true);
2448  FLOW_DESTROY(&flow);
2449  PASS;
2450 }
2451 
2452 /**
2453  * \test Test the parsing of a request PDU.
2454  *
2455  * The PDU under test contains a single read request object:
2456  * - Group: 1
2457  * - Variation: 0
2458  * - Count: 0
2459  */
2460 static int DNP3ParserTestParsePDU01(void)
2461 {
2462  /* Frame to be tested. This frame is a DNP3 request with one read
2463  * request data object, group 1, variation 0. */
2464  const uint8_t pkt[] = {
2465  0x05, 0x64,
2466  0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2467  0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2468  };
2469 
2470  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2471  int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt, sizeof(pkt));
2472  FAIL_IF(pdus < 1);
2473  DNP3Transaction *dnp3tx = DNP3GetTx(dnp3state, 0);
2474  FAIL_IF_NULL(dnp3tx);
2475  FAIL_IF(!dnp3tx->is_request);
2476  FAIL_IF(TAILQ_EMPTY(&dnp3tx->objects));
2477  DNP3Object *object = TAILQ_FIRST(&dnp3tx->objects);
2478  FAIL_IF(object->group != 1 || object->variation != 0);
2479  FAIL_IF(object->count != 0);
2480 
2481  DNP3StateFree(dnp3state);
2482  PASS;
2483 }
2484 
2485 /**
2486  * \test Test the decode of a DNP3 fragment with a single 70:3 object.
2487  */
2488 static int DNP3ParserDecodeG70V3Test(void)
2489 {
2490  const uint8_t pkt[] = {
2491  0x05, 0x64,
2492  0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2493  0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2494  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2495  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2496  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2497  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2498  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2499  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2500  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2501  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2502  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2503  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2504  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2505  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2506  0xc4, 0x8b
2507  };
2508 
2509  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2510  FAIL_IF_NULL(dnp3state);
2511  int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt, sizeof(pkt));
2512  FAIL_IF(bytes != sizeof(pkt));
2513  DNP3Transaction *tx = DNP3GetTx(dnp3state, 0);
2514  FAIL_IF_NULL(tx);
2515  FAIL_IF_NOT(tx->is_request);
2516  DNP3Object *obj = TAILQ_FIRST(&tx->objects);
2517  FAIL_IF_NULL(obj);
2518  FAIL_IF_NOT(obj->group == 70);
2519  FAIL_IF_NOT(obj->variation == 3);
2520  FAIL_IF_NOT(obj->prefix_code == 0x5);
2521  FAIL_IF_NOT(obj->range_code == 0xb);
2522  FAIL_IF_NOT(obj->count == 1);
2523  DNP3Point *point = TAILQ_FIRST(obj->points);
2524  FAIL_IF_NULL(point);
2525  FAIL_IF_NOT(point->prefix == 85);
2526  FAIL_IF_NOT(point->size == 85);
2527  FAIL_IF_NULL(point->data);
2528  DNP3ObjectG70V3 *data = point->data;
2529  FAIL_IF_NOT(strcmp(
2530  data->filename,
2531  "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2532  DNP3StateFree(dnp3state);
2533  PASS;
2534 }
2535 
2536 /**
2537  * \brief Test that an alert is raised on an unknown object.
2538  */
2539 static int DNP3ParserUnknownEventAlertTest(void)
2540 {
2541  /* Valid DNP3 frame with 70:3 object. */
2542  uint8_t pkt[] = {
2543  0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2544  0xc7, 0xee,
2545 
2546  0xc7, 0xc9, 0x1b,
2547 
2548  /* Object and variation. Originally 70:3, now 70:99, an
2549  * unknown object. */
2550  0x46, 0x63,
2551 
2552  0x5b, 0x01, 0x55,
2553  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2554  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2555  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2556  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2557  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2558  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2559  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2560  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2561  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2562  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2563  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2564  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2565  0xc4, 0x8b
2566  };
2567 
2568  DNP3FixCrc(pkt + 10, sizeof(pkt) - 10);
2569 
2570  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2571  FAIL_IF_NULL(dnp3state);
2572  int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt, sizeof(pkt));
2573  FAIL_IF(bytes != sizeof(pkt));
2574 
2575  DNP3StateFree(dnp3state);
2576  PASS;
2577 }
2578 
2579 /**
2580 * \brief Test that an alert is raised on incorrect data.
2581 */
2582 static int DNP3ParserIncorrectUserData(void)
2583 {
2584  uint8_t packet_bytes[] = {
2585  0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2586  0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2587  };
2588 
2590  Flow flow;
2591  TcpSession ssn;
2592  memset(&flow, 0, sizeof(flow));
2593  memset(&ssn, 0, sizeof(ssn));
2594  flow.protoctx = (void *)&ssn;
2595  flow.proto = IPPROTO_TCP;
2596  flow.alproto = ALPROTO_DNP3;
2597  StreamTcpInitConfig(true);
2598 
2599  int r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2600  STREAM_TOCLIENT, packet_bytes, sizeof(packet_bytes));
2601 
2602  FAIL_IF(r == 0);
2603 
2605  StreamTcpFreeConfig(true);
2606  FLOW_DESTROY(&flow);
2607  PASS;
2608 }
2609 
2610 #endif
2611 
2613 {
2614 #ifdef UNITTESTS
2615  UtRegisterTest("DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2616  UtRegisterTest("DNP3ParserCheckLinkHeaderCRC",
2617  DNP3ParserCheckLinkHeaderCRC);
2618  UtRegisterTest("DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2619  UtRegisterTest("DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2620  UtRegisterTest("DNP3CalculateTransportLengthWithoutCRCsTest",
2621  DNP3CalculateTransportLengthWithoutCRCsTest);
2622  UtRegisterTest("DNP3ReassembleApplicationLayerTest01",
2623  DNP3ReassembleApplicationLayerTest01);
2624  UtRegisterTest("DNP3ProbingParserTest", DNP3ProbingParserTest);
2625  UtRegisterTest("DNP3ParserTestRequestResponse",
2626  DNP3ParserTestRequestResponse);
2627  UtRegisterTest("DNP3ParserTestUnsolicitedResponseConfirm",
2628  DNP3ParserTestUnsolicitedResponseConfirm);
2629  UtRegisterTest("DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2630  UtRegisterTest("DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2631  UtRegisterTest("DNP3ParserTestFlooded", DNP3ParserTestFlooded);
2632  UtRegisterTest("DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2633  UtRegisterTest("DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2634  UtRegisterTest("DNP3ParserUnknownEventAlertTest",
2635  DNP3ParserUnknownEventAlertTest);
2636  UtRegisterTest("DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);
2637 #endif
2638 }
util-byte.h
DNP3Transaction_::complete
uint8_t complete
Definition: app-layer-dnp3.h:223
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:1731
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:213
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:151
DNP3_DECODER_EVENT_MALFORMED
@ DNP3_DECODER_EVENT_MALFORMED
Definition: app-layer-dnp3.h:106
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:34
AppLayerParserRegisterOptionFlags
void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto, uint32_t flags)
Definition: app-layer-parser.c:415
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:246
DNP3Transaction_::done
uint8_t done
Definition: app-layer-dnp3.h:222
DNP3Transaction_::th
DNP3TransportHeader th
Definition: app-layer-dnp3.h:219
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DNP3_DECODER_EVENT_FLOODED
@ DNP3_DECODER_EVENT_FLOODED
Definition: app-layer-dnp3.h:102
DNP3_SWAP32
#define DNP3_SWAP32(x)
Definition: app-layer-dnp3.h:92
Flow_::proto
uint8_t proto
Definition: flow.h:379
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:80
DNP3ParserRegisterTests
void DNP3ParserRegisterTests(void)
Definition: app-layer-dnp3.c:2612
DNP3Object_
Struct to hold the list of decoded objects.
Definition: app-layer-dnp3.h:188
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:357
DNP3State_::transaction_max
uint64_t transaction_max
Definition: app-layer-dnp3.h:238
AppLayerEventType
enum AppLayerEventType_ AppLayerEventType
DNP3_APP_FC_CONFIRM
#define DNP3_APP_FC_CONFIRM
Definition: app-layer-dnp3.h:29
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:241
DNP3Buffer_::offset
int offset
Definition: app-layer-dnp3.h:153
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
DNP3Transaction_::objects
DNP3ObjectList objects
Definition: app-layer-dnp3.h:217
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:1510
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:66
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:243
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:216
Flow_::protoctx
void * protoctx
Definition: flow.h:447
DNP3_TH_SEQ
#define DNP3_TH_SEQ(x)
Definition: app-layer-dnp3.h:79
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:179
util-unittest.h
APP_LAYER_EVENT_TYPE_TRANSACTION
@ APP_LAYER_EVENT_TYPE_TRANSACTION
Definition: app-layer-events.h:57
RegisterDNP3Parsers
void RegisterDNP3Parsers(void)
Register the DNP3 application protocol parser.
Definition: app-layer-dnp3.c:1526
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:152
DNP3_SWAP16
#define DNP3_SWAP16(x)
Definition: app-layer-dnp3.h:91
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:239
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:1692
DNP3Object_::points
DNP3PointList * points
Definition: app-layer-dnp3.h:197
DNP3_DECODER_EVENT_UNKNOWN_OBJECT
@ DNP3_DECODER_EVENT_UNKNOWN_OBJECT
Definition: app-layer-dnp3.h:107
app-layer-detect-proto.h
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:356
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:220
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:177
DNP3Transaction_::iin
DNP3InternalInd iin
Definition: app-layer-dnp3.h:221
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
APP_LAYER_PARSER_OPT_UNIDIR_TXS
#define APP_LAYER_PARSER_OPT_UNIDIR_TXS
Definition: app-layer-parser.h:48
Flow_::m
SCMutex m
Definition: flow.h:441
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
DNP3Buffer_::buffer
uint8_t * buffer
Definition: app-layer-dnp3.h:150
app-layer-parser.h
DNP3_TH_FIN
#define DNP3_TH_FIN(x)
Definition: app-layer-dnp3.h:77
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:289
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:48
AppLayerParserRegisterProtocolUnittests
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
Definition: app-layer-parser.c:1926
DNP3Object_::group
uint8_t group
Definition: app-layer-dnp3.h:189
SCReturnUInt
#define SCReturnUInt(x)
Definition: util-debug.h:277
DNP3_LINK_DIR
#define DNP3_LINK_DIR(control)
Definition: app-layer-dnp3.h:70
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:1909
DNP3Object_::start
uint32_t start
Definition: app-layer-dnp3.h:194
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:232
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:211
DNP3Object_::count
uint32_t count
Definition: app-layer-dnp3.h:196
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:88
AppLayerTxData
struct AppLayerTxData AppLayerTxData
Definition: detect.h:1303
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:237
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:668
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:1323
suricata-common.h
DNP3_DECODER_EVENT_BAD_LINK_CRC
@ DNP3_DECODER_EVENT_BAD_LINK_CRC
Definition: app-layer-dnp3.h:104
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:193
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
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:235
DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC
@ DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC
Definition: app-layer-dnp3.h:105
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:192
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:210
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:482
DNP3Object_::variation
uint8_t variation
Definition: app-layer-dnp3.h:190
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:78
app-layer-protos.h
DNP3State_
Per flow DNP3 state.
Definition: app-layer-dnp3.h:234
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:240
DNP3_LINK_FC
#define DNP3_LINK_FC(control)
Definition: app-layer-dnp3.h:74
app-layer-dnp3-objects.h
DNP3TransportHeader
uint8_t DNP3TransportHeader
DNP3 transport header.
Definition: app-layer-dnp3.h:126
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:66
DNP3Point_::prefix
uint32_t prefix
Definition: app-layer-dnp3.h:172
DNP3Transaction_::tx_data
AppLayerTxData tx_data
Definition: app-layer-dnp3.h:208
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:2014
TcpSession_
Definition: stream-tcp-private.h:272
DNP3Transaction_::lh
DNP3LinkHeader lh
Definition: app-layer-dnp3.h:218
DNP3_START_BYTE0
#define DNP3_START_BYTE0
Definition: app-layer-dnp3.c:43
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:456
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:129
DNP3Point_
DNP3 object point.
Definition: app-layer-dnp3.h:171
DNP3Transaction_
DNP3 transaction.
Definition: app-layer-dnp3.h:207
app-layer.h
DNP3Buffer_
A struct used for buffering incoming data prior to reassembly.
Definition: app-layer-dnp3.h:149
DNP3Transaction_::buffer
uint8_t * buffer
Definition: app-layer-dnp3.h:215
DNP3_DECODER_EVENT_LEN_TOO_SMALL
@ DNP3_DECODER_EVENT_LEN_TOO_SMALL
Definition: app-layer-dnp3.h:103