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