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