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