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