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