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