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 (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name))
1591  {
1593 
1594  if (RunmodeIsUnittests()) {
1596  ALPROTO_DNP3, 0, sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1597  DNP3ProbingParser, DNP3ProbingParser);
1598  }
1599  else {
1600  if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
1601  proto_name, ALPROTO_DNP3, 0, sizeof(DNP3LinkHeader),
1602  DNP3ProbingParser, DNP3ProbingParser)) {
1603  return;
1604  }
1605  }
1606 
1607  }
1608  else {
1609  SCLogConfig("Protocol detection and parser disabled for DNP3.");
1610  SCReturn;
1611  }
1612 
1613  if (AppLayerParserConfParserEnabled("tcp", proto_name))
1614  {
1615  SCLogConfig("Registering DNP3/tcp parsers.");
1616 
1618  DNP3ParseRequest);
1620  DNP3ParseResponse);
1621 
1623  DNP3StateAlloc, DNP3StateFree);
1624 
1626  DNP3GetEvents);
1628  DNP3GetTxDetectState, DNP3SetTxDetectState);
1629 
1630  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTx);
1631  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxCnt);
1633  DNP3StateTxFree);
1634 
1636  DNP3GetAlstateProgress);
1638 
1640  DNP3StateGetEventInfo);
1642  DNP3StateGetEventInfoById);
1643 
1645  DNP3GetTxData);
1646  }
1647  else {
1648  SCLogConfig("Parser disabled for protocol %s. "
1649  "Protocol detection still on.", proto_name);
1650  }
1651 
1652 #ifdef UNITTESTS
1655 #endif
1656 
1657  SCReturn;
1658 }
1659 
1660 #ifdef UNITTESTS
1661 
1662 #include "flow-util.h"
1663 #include "stream-tcp.h"
1664 
1665 /**
1666  * \brief Utility function to fix CRCs when mangling a frame.
1667  */
1668 static void DNP3FixCrc(uint8_t *data, uint32_t len)
1669 {
1670  uint32_t block_size;
1671 
1672  while (len) {
1673  if (len >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
1674  block_size = DNP3_BLOCK_SIZE;
1675  } else {
1676  block_size = len - DNP3_CRC_LEN;
1677  }
1678  uint16_t crc = DNP3ComputeCRC(data, block_size);
1679  data[block_size + 1] = (crc >> 8) & 0xff;
1680  data[block_size] = crc & 0xff;
1681  data += block_size + DNP3_CRC_LEN;
1682  len -= block_size + DNP3_CRC_LEN;
1683  }
1684 }
1685 
1686 /**
1687  * \test Test CRC checking on partial and full blocks.
1688  */
1689 static int DNP3ParserTestCheckCRC(void)
1690 {
1691  uint8_t request[] = {
1692  /* DNP3 start. */
1693  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1694  0xa5, 0xe9,
1695 
1696  /* Transport header. */
1697  0xff,
1698 
1699  /* Application layer - segment 1. */
1700  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1701  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1702  0xef,
1703 
1704  /* Application layer - segment 2. */
1705  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1706  };
1707 
1708  /* Check link header CRC. */
1709  FAIL_IF(!DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1710 
1711  /* Check first application layer segment. */
1712  FAIL_IF(!DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1714 
1715 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1716  /* Change a byte in link header, should fail now. */
1717  request[2]++;
1718  FAIL_IF(DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1719 
1720  /* Change a byte in the first application segment, should fail
1721  * now. */
1722  request[sizeof(DNP3LinkHeader) + 3]++;
1723  FAIL_IF(DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1725 #endif
1726 
1727  PASS;
1728 }
1729 
1730 /**
1731  * \test Test validation of all CRCs in user data.
1732  */
1733 static int DNP3CheckUserDataCRCsTest(void)
1734 {
1735  /* Multi-block data with valid CRCs. */
1736  uint8_t data_valid[] = {
1737  0xff, 0xc9, 0x05, 0x0c,
1738  0x01, 0x28, 0x01, 0x00,
1739  0x00, 0x00, 0x01, 0x01,
1740  0x01, 0x00, 0x00, 0x00,
1741  0x72, 0xef, /* CRC. */
1742 
1743  0xff, 0xc9, 0x05, 0x0c,
1744  0x01, 0x28, 0x01, 0x00,
1745  0x00, 0x00, 0x01, 0x01,
1746  0x01, 0x00, 0x00, 0x00,
1747  0x72, 0xef, /* CRC. */
1748 
1749  0xff, 0xc9, 0x05, 0x0c,
1750  0x01, 0x28, 0x01, 0x00,
1751  0x00, 0x00, 0x01, 0x01,
1752  0x01, 0x00, 0x00, 0x00,
1753  0x72, 0xef, /* CRC. */
1754 
1755  0x00, 0x00, 0x00, 0x00,
1756  0x00,
1757  0xff, 0xff, /* CRC. */
1758  };
1759  FAIL_IF(!DNP3CheckUserDataCRCs(data_valid, sizeof(data_valid)));
1760 
1761 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1762  /* Multi-block data with one non-crc byte altered. */
1763  uint8_t data_invalid[] = {
1764  0xff, 0xc9, 0x05, 0x0c,
1765  0x01, 0x28, 0x01, 0x00,
1766  0x00, 0x00, 0x01, 0x01,
1767  0x01, 0x00, 0x00, 0x00,
1768  0x72, 0xef, /* CRC. */
1769 
1770  0xff, 0xc9, 0x05, 0x0c,
1771  0x01, 0x28, 0x01, 0x00,
1772  0x00, 0x00, 0x01, 0x01,
1773  0x01, 0x00, 0x00, 0x00,
1774  0x72, 0xef, /* CRC. */
1775 
1776  0xff, 0xc9, 0x05, 0x0c,
1777  0x01, 0x28, 0x01, 0x00,
1778  0x00, 0x00, 0x01, 0x01,
1779  0x01, 0x00, 0x00, 0x00,
1780  0x72, 0xef, /* CRC. */
1781 
1782  0x00, 0x00, 0x00, 0x00,
1783  0x01, /* Invalid byte. */
1784  0xff, 0xff, /* CRC. */
1785  };
1786  FAIL_IF(DNP3CheckUserDataCRCs(data_invalid, sizeof(data_invalid)));
1787 
1788  /* 1 byte - need at least 3. */
1789  uint8_t one_byte_nocrc[] = { 0x01 };
1790  FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc, sizeof(one_byte_nocrc)));
1791 
1792  /* 2 bytes - need at least 3. */
1793  uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1794  FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc, sizeof(two_byte_nocrc)));
1795 #endif
1796 
1797  /* 3 bytes, valid CRC. */
1798  uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1799  *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1800  three_bytes_good_crc, 1);
1801  FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1802  sizeof(three_bytes_good_crc)));
1803 
1804  PASS;
1805 }
1806 
1807 /**
1808  * \test Test the link layer length calculation.
1809  *
1810  * Test the calculation that converts the link provided in the DNP3
1811  * header to the actual length of the frame. That is the length with
1812  * CRCs as the length in the header does not include CRCs.
1813  */
1814 static int DNP3CalculateLinkLengthTest(void)
1815 {
1816  /* These are invalid. */
1817  FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1818  FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1819  FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1820  FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1821  FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1822 
1823  /* This is the minimum size. */
1824  FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1825 
1826  /* 1 full user data blocks of data. */
1827  FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1828 
1829  /* 2 full user data blocks of data. */
1830  FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1831 
1832  /* 2 full user data blocks, plus one more byte. */
1833  /* 2 full user data blocks of data. */
1834  FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1835 
1836  /* The maximum size. */
1837  FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1838 
1839  PASS;
1840 }
1841 
1842 /**
1843  * \test The conversion of length with CRCs to the length without
1844  * CRCs.
1845  */
1846 static int DNP3CalculateTransportLengthWithoutCRCsTest(void)
1847 {
1848  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1849  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1850  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1851  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1852  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1853  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1854  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1855 
1856  /* 19 bytes is not enough for a second block. */
1857  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1858 
1859  /* 20 bytes really isn't enough either, but is large enough to
1860  * satisfy the CRC on the second block. */
1861  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1862 
1863  FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1864 
1865  PASS;
1866 }
1867 
1868 /**
1869  * \test Test the validation of the link header CRC.
1870  */
1871 static int DNP3ParserCheckLinkHeaderCRC(void)
1872 {
1873  /* DNP3 frame with valid headers and CRCs. */
1874  uint8_t request[] = {
1875  /* DNP3 start. */
1876  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1877  0xa5, 0xe9,
1878 
1879  /* Transport header. */
1880  0xff,
1881 
1882  /* Application layer. */
1883  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1884  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1885  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1886  };
1887 
1888  DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1889  FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1890 
1891 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1892  /* Alter a byte in the header. */
1893  request[4] = 0;
1894  FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1895 #endif
1896 
1897  PASS;
1898 }
1899 
1900 /**
1901  * \test Test removal of CRCs from user data.
1902  */
1903 static int DNP3ReassembleApplicationLayerTest01(void)
1904 {
1905  uint32_t reassembled_len = 0;
1906  uint8_t *output = NULL;
1907 
1908  uint8_t payload[] = {
1909 
1910  0xff, 0xc9, 0x05, 0x0c,
1911  0x01, 0x28, 0x01, 0x00,
1912  0x00, 0x00, 0x01, 0x01,
1913  0x01, 0x00, 0x00, 0x00,
1914  0x72, 0xef, /* CRC. */
1915 
1916  0xff, 0xc9, 0x05, 0x0c,
1917  0x01, 0x28, 0x01, 0x00,
1918  0x00, 0x00, 0x01, 0x01,
1919  0x01, 0x00, 0x00, 0x00,
1920  0x72, 0xef, /* CRC. */
1921 
1922  0xff, 0xc9, 0x05, 0x0c,
1923  0x01, 0x28, 0x01, 0x00,
1924  0x00, 0x00, 0x01, 0x01,
1925  0x01, 0x00, 0x00, 0x00,
1926  0x72, 0xef, /* CRC. */
1927 
1928  0x00, 0x00, 0x00, 0x00,
1929  0x00,
1930  0xff, 0xff, /* CRC. */
1931  };
1932 
1933  uint8_t expected[] = {
1934  0xc9, 0x05, 0x0c,
1935  0x01, 0x28, 0x01, 0x00,
1936  0x00, 0x00, 0x01, 0x01,
1937  0x01, 0x00, 0x00, 0x00,
1938  /* CRC removed. */
1939  0xff, 0xc9, 0x05, 0x0c,
1940  0x01, 0x28, 0x01, 0x00,
1941  0x00, 0x00, 0x01, 0x01,
1942  0x01, 0x00, 0x00, 0x00,
1943  /* CRC removed. */
1944  0xff, 0xc9, 0x05, 0x0c,
1945  0x01, 0x28, 0x01, 0x00,
1946  0x00, 0x00, 0x01, 0x01,
1947  0x01, 0x00, 0x00, 0x00,
1948  /* CRC removed. */
1949  0x00, 0x00, 0x00, 0x00,
1950  0x00
1951  /* CRC removed. */
1952  };
1953 
1954  /* Valid frame. */
1955  FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1956  sizeof(payload), &output, &reassembled_len));
1957  FAIL_IF(output == NULL);
1958  FAIL_IF(reassembled_len != sizeof(expected));
1959  FAIL_IF(memcmp(expected, output, reassembled_len));
1960  SCFree(output);
1961 
1962  /* 1 byte, invalid. */
1963  reassembled_len = 0;
1964  output = NULL;
1965  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1966  &reassembled_len));
1967  FAIL_IF(output != NULL);
1968  FAIL_IF(reassembled_len != 0);
1969 
1970  /* 2 bytes, invalid. */
1971  reassembled_len = 0;
1972  output = NULL;
1973  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1974  &reassembled_len));
1975  FAIL_IF(output != NULL);
1976  FAIL_IF(reassembled_len != 0);
1977 
1978  /* 3 bytes, minimum - but that would only be the transport header
1979  * which isn't included in the output. */
1980  reassembled_len = 0;
1981  output = NULL;
1982  FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1983  &reassembled_len));
1984  FAIL_IF(output != NULL);
1985  FAIL_IF(reassembled_len != 0);
1986 
1987  /* 4 bytes is the minimum to get any reassembled data. */
1988  reassembled_len = 0;
1989  output = NULL;
1990  FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1991  &reassembled_len));
1992  FAIL_IF(output == NULL);
1993  FAIL_IF(reassembled_len != 1);
1994 
1995  /* Last block too short (by 1 byte) for data + CRC. */
1996  uint8_t short_payload1[] = {
1997 
1998  0xff, 0xc9, 0x05, 0x0c,
1999  0x01, 0x28, 0x01, 0x00,
2000  0x00, 0x00, 0x01, 0x01,
2001  0x01, 0x00, 0x00, 0x00,
2002  0x72, 0xef, /* CRC. */
2003 
2004  0xff, 0xc9, 0x05, 0x0c,
2005  0x01, 0x28, 0x01, 0x00,
2006  0x00, 0x00, 0x01, 0x01,
2007  0x01, 0x00, 0x00, 0x00,
2008  0x72, 0xef, /* CRC. */
2009 
2010  0xff, 0xc9, 0x05, 0x0c,
2011  0x01, 0x28, 0x01, 0x00,
2012  0x00, 0x00, 0x01, 0x01,
2013  0x01, 0x00, 0x00, 0x00,
2014  0x72, 0xef, /* CRC. */
2015 
2016  0x00, 0x00
2017  };
2018  reassembled_len = 0;
2019  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
2020  sizeof(short_payload1), &output, &reassembled_len));
2021 
2022  /* Last block too short (by 2 bytes) for data + CRC. */
2023  uint8_t short_payload2[] = {
2024 
2025  0xff, 0xc9, 0x05, 0x0c,
2026  0x01, 0x28, 0x01, 0x00,
2027  0x00, 0x00, 0x01, 0x01,
2028  0x01, 0x00, 0x00, 0x00,
2029  0x72, 0xef, /* CRC. */
2030 
2031  0xff, 0xc9, 0x05, 0x0c,
2032  0x01, 0x28, 0x01, 0x00,
2033  0x00, 0x00, 0x01, 0x01,
2034  0x01, 0x00, 0x00, 0x00,
2035  0x72, 0xef, /* CRC. */
2036 
2037  0xff, 0xc9, 0x05, 0x0c,
2038  0x01, 0x28, 0x01, 0x00,
2039  0x00, 0x00, 0x01, 0x01,
2040  0x01, 0x00, 0x00, 0x00,
2041  0x72, 0xef, /* CRC. */
2042 
2043  0x00,
2044  };
2045  reassembled_len = 0;
2046  FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
2047  sizeof(short_payload2), &output, &reassembled_len));
2048 
2049  PASS;
2050 }
2051 
2052 /**
2053  * \test Test the probing parser.
2054  */
2055 static int DNP3ProbingParserTest(void)
2056 {
2057  uint8_t pkt[] = {
2058  0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2059  0xbd, 0x71
2060  };
2061  uint8_t rdir = 0;
2062 
2063  /* Valid frame. */
2064  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_DNP3);
2065 
2066  /* Send too little bytes. */
2067  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(DNP3LinkHeader) - 1, &rdir) != ALPROTO_UNKNOWN);
2068 
2069  /* Bad start bytes. */
2070  pkt[0] = 0x06;
2071  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2072 
2073  /* Restore start byte. */
2074  pkt[0] = 0x05;
2075 
2076  /* Set the length to a value less than the minimum length of 5. */
2077  pkt[2] = 0x03;
2078  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2079 
2080  /* Send a banner. */
2081  char mybanner[] = "Welcome to DNP3 SCADA.";
2082  FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner, sizeof(mybanner) - 1,
2083  &rdir) != ALPROTO_DNP3);
2084  FAIL_IF(rdir != STREAM_TOCLIENT);
2085 
2086  PASS;
2087 }
2088 
2089 /**
2090  * \test Test a basic request/response.
2091  */
2092 static int DNP3ParserTestRequestResponse(void)
2093 {
2094  DNP3State *state = NULL;
2095 
2096  uint8_t request[] = {
2097  /* DNP3 start. */
2098  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2099  0xa5, 0xe9,
2100 
2101  /* Transport header. */
2102  0xff,
2103 
2104  /* Application layer. */
2105  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2106  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2107  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2108  };
2109 
2110  uint8_t response[] = {
2111  /* DNP3 start. */
2112  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2113  0xe2, 0x59,
2114 
2115  /* Transport header. */
2116  0xc3,
2117 
2118  /* Application layer. */
2119  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2120  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2121  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2122  0xff, 0xff
2123  };
2124 
2126  Flow flow;
2127  TcpSession ssn;
2128 
2129  memset(&flow, 0, sizeof(flow));
2130  memset(&ssn, 0, sizeof(ssn));
2131 
2132  flow.protoctx = (void *)&ssn;
2133  flow.proto = IPPROTO_TCP;
2134  flow.alproto = ALPROTO_DNP3;
2135 
2136  StreamTcpInitConfig(true);
2137 
2138  SCMutexLock(&flow.m);
2140  STREAM_TOSERVER, request, sizeof(request)));
2141  SCMutexUnlock(&flow.m);
2142 
2143  state = flow.alstate;
2144  FAIL_IF(state == NULL);
2145 
2146  DNP3Transaction *tx = DNP3GetTx(state, 0);
2147  FAIL_IF(tx == NULL);
2148  FAIL_IF(tx->tx_num != 1);
2149  FAIL_IF(tx != state->curr);
2150  FAIL_IF(tx->request_buffer == NULL);
2151  FAIL_IF(tx->request_buffer_len != 20);
2152  FAIL_IF(tx->request_ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2153 
2154  SCMutexLock(&flow.m);
2156  STREAM_TOCLIENT, response, sizeof(response)));
2157  SCMutexUnlock(&flow.m);
2158  FAIL_IF(DNP3GetTx(state, 0) != tx);
2159  FAIL_IF(!tx->response_done);
2160  FAIL_IF(tx->response_buffer == NULL);
2161 
2163  StreamTcpFreeConfig(true);
2164  FLOW_DESTROY(&flow);
2165  PASS;
2166 }
2167 
2168 /**
2169  * \test Test an unsolicited response from an outstation.
2170  *
2171  * This is kind of like a request initiated from the "server".
2172  */
2173 static int DNP3ParserTestUnsolicitedResponseConfirm(void)
2174 {
2175  DNP3State *state = NULL;
2176 
2177  /* Unsolicited response with confirm bit set. */
2178  uint8_t response[] = {
2179  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2180  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2181  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2182  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2183  };
2184 
2185  /* Confirm. */
2186  uint8_t confirm[] = {
2187  0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2188  0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2189  0x3d
2190  };
2191 
2193  Flow flow;
2194  TcpSession ssn;
2195 
2196  memset(&flow, 0, sizeof(flow));
2197  memset(&ssn, 0, sizeof(ssn));
2198 
2199  flow.protoctx = (void *)&ssn;
2200  flow.proto = IPPROTO_TCP;
2201  flow.alproto = ALPROTO_DNP3;
2202 
2203  StreamTcpInitConfig(true);
2204 
2205  SCMutexLock(&flow.m);
2207  STREAM_TOCLIENT, response, sizeof(response)));
2208  SCMutexUnlock(&flow.m);
2209 
2210  state = flow.alstate;
2211  FAIL_IF(state == NULL);
2212 
2213  DNP3Transaction *tx = DNP3GetTx(state, 0);
2214  FAIL_IF(tx == NULL);
2215  FAIL_IF(tx->tx_num != 1);
2216  FAIL_IF(tx != state->curr);
2217  FAIL_IF(tx->request_buffer != NULL);
2218  FAIL_IF(tx->response_buffer == NULL);
2219  FAIL_IF(!tx->response_done);
2220  FAIL_IF(tx->response_ah.function_code != DNP3_APP_FC_UNSOLICITED_RESP);
2221 
2222  SCMutexLock(&flow.m);
2224  STREAM_TOSERVER, confirm, sizeof(confirm)));
2225  SCMutexUnlock(&flow.m);
2226  FAIL_IF(DNP3GetTx(state, 0) != tx);
2227  FAIL_IF(!tx->response_done);
2228  FAIL_IF(tx->response_buffer == NULL);
2229  /* FAIL_IF(tx->iin1 != 0 || tx->iin2 != 0); */
2230 
2232  StreamTcpFreeConfig(true);
2233  FLOW_DESTROY(&flow);
2234  PASS;
2235 }
2236 
2237 /**
2238  * \test Test flood state.
2239  */
2240 static int DNP3ParserTestFlooded(void)
2241 {
2242  DNP3State *state = NULL;
2243 
2244  uint8_t request[] = {
2245  /* DNP3 start. */
2246  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2247  0xa5, 0xe9,
2248 
2249  /* Transport header. */
2250  0xff,
2251 
2252  /* Application layer. */
2253  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2254  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2255  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2256  };
2257 
2259  Flow flow;
2260  TcpSession ssn;
2261 
2262  memset(&flow, 0, sizeof(flow));
2263  memset(&ssn, 0, sizeof(ssn));
2264 
2265  flow.protoctx = (void *)&ssn;
2266  flow.proto = IPPROTO_TCP;
2267  flow.alproto = ALPROTO_DNP3;
2268 
2269  StreamTcpInitConfig(true);
2270 
2271  SCMutexLock(&flow.m);
2273  STREAM_TOSERVER, request, sizeof(request)));
2274  SCMutexUnlock(&flow.m);
2275 
2276  state = flow.alstate;
2277  FAIL_IF(state == NULL);
2278 
2279  DNP3Transaction *tx = DNP3GetTx(state, 0);
2280  FAIL_IF(tx == NULL);
2281  FAIL_IF(tx->tx_num != 1);
2282  FAIL_IF(tx != state->curr);
2283  FAIL_IF(tx->request_buffer == NULL);
2284  FAIL_IF(tx->request_buffer_len != 20);
2285  /* FAIL_IF(tx->app_function_code != DNP3_APP_FC_DIR_OPERATE); */
2286  FAIL_IF(tx->response_done);
2287 
2288  for (int i = 0; i < DNP3_DEFAULT_REQ_FLOOD_COUNT - 1; i++) {
2289  SCMutexLock(&flow.m);
2291  STREAM_TOSERVER, request, sizeof(request)));
2292  SCMutexUnlock(&flow.m);
2293  }
2294  FAIL_IF(state->flooded);
2295  FAIL_IF(DNP3GetAlstateProgress(tx, 0));
2296 
2297  /* One more request should trip us into flooded state. */
2298  SCMutexLock(&flow.m);
2300  STREAM_TOSERVER, request, sizeof(request)));
2301  SCMutexUnlock(&flow.m);
2302  FAIL_IF(!state->flooded);
2303 
2304  /* Progress for the oldest tx should return 1. */
2305  FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2306 
2307  /* But progress for the current state should still return 0. */
2308  FAIL_IF(DNP3GetAlstateProgress(state->curr, 0));
2309 
2311  StreamTcpFreeConfig(true);
2312  FLOW_DESTROY(&flow);
2313  PASS;
2314 }
2315 
2316 /**
2317  * \test Test parsing of partial frames.
2318  *
2319  * As DNP3 operates over TCP, it is possible that a partial DNP3 frame
2320  * is received. Test that the partial frame will be buffered until the
2321  * remainder is seen.
2322  */
2323 static int DNP3ParserTestPartialFrame(void)
2324 {
2325  DNP3State *state = NULL;
2326  DNP3Transaction *tx;
2327  int r;
2328 
2329  uint8_t request_partial1[] = {
2330  /* DNP3 start. */
2331  0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2332  0xa5, 0xe9,
2333 
2334  /* Transport header. */
2335  0xff,
2336 
2337  /* Application layer. */
2338  0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2339  };
2340 
2341  uint8_t request_partial2[] = {
2342  /* Remainder of application layer. */
2343  0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2344  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2345  };
2346 
2347  uint8_t response_partial1[] = {
2348  /* DNP3 start. */
2349  0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2350  0xe2, 0x59,
2351 
2352  /* Transport header. */
2353  0xc3,
2354 
2355  /* Application layer. */
2356  0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2357  };
2358 
2359  uint8_t response_partial2[] = {
2360  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2361  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2362  0xff, 0xff
2363  };
2364 
2365  /* Boiler plate for app layer setup. */
2367  Flow flow;
2368  TcpSession ssn;
2369  memset(&flow, 0, sizeof(flow));
2370  memset(&ssn, 0, sizeof(ssn));
2371  flow.protoctx = (void *)&ssn;
2372  flow.proto = IPPROTO_TCP;
2373  flow.alproto = ALPROTO_DNP3;
2374  StreamTcpInitConfig(true);
2375 
2376  /* Pass in the first partial frame. */
2377 
2378  SCMutexLock(&flow.m);
2379  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2380  STREAM_TOSERVER, request_partial1, sizeof(request_partial1));
2381  SCMutexUnlock(&flow.m);
2382  FAIL_IF(r != 0);
2383 
2384  /* Frame should just be buffered, but not yet processed. */
2385  state = flow.alstate;
2386  FAIL_IF(state == NULL);
2387  FAIL_IF(state->request_buffer.len != sizeof(request_partial1));
2388  FAIL_IF(state->request_buffer.offset != 0);
2389  FAIL_IF(memcmp(state->request_buffer.buffer, request_partial1,
2390  sizeof(request_partial1)));
2391 
2392  /* There should not be a transaction yet. */
2393  FAIL_IF(state->transaction_max != 0);
2394  FAIL_IF(DNP3GetTx(state, 0) != NULL);
2395 
2396  /* Send the second partial. */
2397  SCMutexLock(&flow.m);
2398  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2399  STREAM_TOSERVER, request_partial2, sizeof(request_partial2));
2400  SCMutexUnlock(&flow.m);
2401  FAIL_IF(r != 0);
2402 
2403  /* The second partial completed the frame, the buffer should now
2404  * be clear. */
2405  FAIL_IF(state->request_buffer.len != 0);
2406  FAIL_IF(state->request_buffer.offset != 0);
2407 
2408  /* Should now have a complete transaction. */
2409  tx = DNP3GetTx(state, 0);
2410  FAIL_IF(tx == NULL);
2411  FAIL_IF(tx->tx_num != 1);
2412  FAIL_IF(tx != state->curr);
2413  FAIL_IF(tx->request_buffer == NULL);
2414  FAIL_IF(tx->request_buffer_len != 20);
2415  FAIL_IF(tx->request_ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2416 
2417  /* Send partial response. */
2418  SCMutexLock(&flow.m);
2419  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2420  STREAM_TOCLIENT, response_partial1, sizeof(response_partial1));
2421  SCMutexUnlock(&flow.m);
2422  FAIL_IF(r != 0);
2423  FAIL_IF(state->response_buffer.len != sizeof(response_partial1));
2424  FAIL_IF(state->response_buffer.offset != 0);
2425  FAIL_IF(tx->response_done);
2426 
2427  /* Send rest of response. */
2428  SCMutexLock(&flow.m);
2429  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2430  STREAM_TOCLIENT, response_partial2, sizeof(response_partial2));
2431  SCMutexUnlock(&flow.m);
2432  FAIL_IF(r != 0);
2433 
2434  /* Buffer should now be empty. */
2435  FAIL_IF(state->response_buffer.len != 0);
2436  FAIL_IF(state->response_buffer.offset != 0);
2437 
2438  /* Transaction should be replied to now. */
2439  FAIL_IF(!tx->response_done);
2440  FAIL_IF(tx->response_buffer == NULL);
2441  FAIL_IF(tx->response_buffer_len == 0);
2442 
2444  StreamTcpFreeConfig(true);
2445  FLOW_DESTROY(&flow);
2446  PASS;
2447 }
2448 
2449 /**
2450  * \test Test multiple DNP3 frames in one TCP read.
2451  */
2452 static int DNP3ParserTestMultiFrame(void)
2453 {
2454  DNP3State *state = NULL;
2455 
2456  /* Unsolicited response 1. */
2457  uint8_t unsol_response1[] = {
2458  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2459  0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2460  0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2461  0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2462  };
2463 
2464  /* Unsolicited response 2. */
2465  uint8_t unsol_response2[] = {
2466  0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2467  0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2468  0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2469  0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2470  };
2471 
2472  uint8_t combined[sizeof(unsol_response1) + sizeof(unsol_response2)];
2473  memcpy(combined, unsol_response1, sizeof(unsol_response1));
2474  memcpy(combined + sizeof(unsol_response1), unsol_response2,
2475  sizeof(unsol_response2));
2476 
2477  /* Setup. */
2479  Flow flow;
2480  TcpSession ssn;
2481  int r;
2482  memset(&flow, 0, sizeof(flow));
2483  memset(&ssn, 0, sizeof(ssn));
2484  flow.protoctx = (void *)&ssn;
2485  flow.proto = IPPROTO_TCP;
2486  flow.alproto = ALPROTO_DNP3;
2487  StreamTcpInitConfig(true);
2488 
2489  SCMutexLock(&flow.m);
2490  r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2491  STREAM_TOCLIENT, combined, sizeof(combined));
2492  SCMutexUnlock(&flow.m);
2493  FAIL_IF(r != 0);
2494 
2495  state = flow.alstate;
2496  FAIL_IF(state == NULL);
2497  FAIL_IF(state->transaction_max != 2);
2498 
2500  StreamTcpFreeConfig(true);
2501  FLOW_DESTROY(&flow);
2502  PASS;
2503 }
2504 
2505 /**
2506  * \test Test the parsing of a request PDU.
2507  *
2508  * The PDU under test contains a single read request object:
2509  * - Group: 1
2510  * - Variation: 0
2511  * - Count: 0
2512  */
2513 static int DNP3ParserTestParsePDU01(void)
2514 {
2515  /* Frame to be tested. This frame is a DNP3 request with one read
2516  * request data object, group 1, variation 0. */
2517  const uint8_t pkt[] = {
2518  0x05, 0x64,
2519  0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2520  0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2521  };
2522 
2523  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2524  int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt, sizeof(pkt));
2525  FAIL_IF(pdus < 1);
2526  DNP3Transaction *dnp3tx = DNP3GetTx(dnp3state, 0);
2527  FAIL_IF_NULL(dnp3tx);
2528  FAIL_IF(!dnp3tx->has_request);
2529  FAIL_IF(TAILQ_EMPTY(&dnp3tx->request_objects));
2530  DNP3Object *object = TAILQ_FIRST(&dnp3tx->request_objects);
2531  FAIL_IF(object->group != 1 || object->variation != 0);
2532  FAIL_IF(object->count != 0);
2533 
2534  DNP3StateFree(dnp3state);
2535  PASS;
2536 }
2537 
2538 /**
2539  * \test Test the decode of a DNP3 fragment with a single 70:3 object.
2540  */
2541 static int DNP3ParserDecodeG70V3Test(void)
2542 {
2543  const uint8_t pkt[] = {
2544  0x05, 0x64,
2545  0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2546  0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2547  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2548  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2549  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2550  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2551  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2552  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2553  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2554  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2555  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2556  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2557  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2558  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2559  0xc4, 0x8b
2560  };
2561 
2562  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2563  FAIL_IF_NULL(dnp3state);
2564  int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt, sizeof(pkt));
2565  FAIL_IF(bytes != sizeof(pkt));
2566  DNP3Transaction *tx = DNP3GetTx(dnp3state, 0);
2567  FAIL_IF_NULL(tx);
2568  FAIL_IF_NOT(tx->has_request);
2569  DNP3Object *obj = TAILQ_FIRST(&tx->request_objects);
2570  FAIL_IF_NULL(obj);
2571  FAIL_IF_NOT(obj->group == 70);
2572  FAIL_IF_NOT(obj->variation == 3);
2573  FAIL_IF_NOT(obj->prefix_code == 0x5);
2574  FAIL_IF_NOT(obj->range_code == 0xb);
2575  FAIL_IF_NOT(obj->count == 1);
2576  DNP3Point *point = TAILQ_FIRST(obj->points);
2577  FAIL_IF_NULL(point);
2578  FAIL_IF_NOT(point->prefix == 85);
2579  FAIL_IF_NOT(point->size == 85);
2580  FAIL_IF_NULL(point->data);
2581  DNP3ObjectG70V3 *data = point->data;
2582  FAIL_IF_NOT(strcmp(
2583  data->filename,
2584  "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2585  DNP3StateFree(dnp3state);
2586  PASS;
2587 }
2588 
2589 /**
2590  * \brief Test that an alert is raised on an unknown object.
2591  */
2592 static int DNP3ParserUnknownEventAlertTest(void)
2593 {
2594  /* Valid DNP3 frame with 70:3 object. */
2595  uint8_t pkt[] = {
2596  0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2597  0xc7, 0xee,
2598 
2599  0xc7, 0xc9, 0x1b,
2600 
2601  /* Object and variation. Originally 70:3, now 70:99, an
2602  * unknown object. */
2603  0x46, 0x63,
2604 
2605  0x5b, 0x01, 0x55,
2606  0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2607  0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2608  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2609  0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2610  0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2611  0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2612  0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2613  0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2614  0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2615  0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2616  0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2617  0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2618  0xc4, 0x8b
2619  };
2620 
2621  DNP3FixCrc(pkt + 10, sizeof(pkt) - 10);
2622 
2623  DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2624  FAIL_IF_NULL(dnp3state);
2625  int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt, sizeof(pkt));
2626  FAIL_IF(bytes != sizeof(pkt));
2627 
2628  DNP3StateFree(dnp3state);
2629  PASS;
2630 }
2631 
2632 /**
2633 * \brief Test that an alert is raised on incorrect data.
2634 */
2635 static int DNP3ParserIncorrectUserData(void)
2636 {
2637  uint8_t packet_bytes[] = {
2638  0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2639  0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2640  };
2641 
2643  Flow flow;
2644  TcpSession ssn;
2645  memset(&flow, 0, sizeof(flow));
2646  memset(&ssn, 0, sizeof(ssn));
2647  flow.protoctx = (void *)&ssn;
2648  flow.proto = IPPROTO_TCP;
2649  flow.alproto = ALPROTO_DNP3;
2650  StreamTcpInitConfig(true);
2651 
2652  int r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2653  STREAM_TOCLIENT, packet_bytes, sizeof(packet_bytes));
2654 
2655  FAIL_IF(r == 0);
2656 
2658  StreamTcpFreeConfig(true);
2659  FLOW_DESTROY(&flow);
2660  PASS;
2661 }
2662 
2663 #endif
2664 
2666 {
2667 #ifdef UNITTESTS
2668  UtRegisterTest("DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2669  UtRegisterTest("DNP3ParserCheckLinkHeaderCRC",
2670  DNP3ParserCheckLinkHeaderCRC);
2671  UtRegisterTest("DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2672  UtRegisterTest("DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2673  UtRegisterTest("DNP3CalculateTransportLengthWithoutCRCsTest",
2674  DNP3CalculateTransportLengthWithoutCRCsTest);
2675  UtRegisterTest("DNP3ReassembleApplicationLayerTest01",
2676  DNP3ReassembleApplicationLayerTest01);
2677  UtRegisterTest("DNP3ProbingParserTest", DNP3ProbingParserTest);
2678  UtRegisterTest("DNP3ParserTestRequestResponse",
2679  DNP3ParserTestRequestResponse);
2680  UtRegisterTest("DNP3ParserTestUnsolicitedResponseConfirm",
2681  DNP3ParserTestUnsolicitedResponseConfirm);
2682  UtRegisterTest("DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2683  UtRegisterTest("DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2684  UtRegisterTest("DNP3ParserTestFlooded", DNP3ParserTestFlooded);
2685  UtRegisterTest("DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2686  UtRegisterTest("DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2687  UtRegisterTest("DNP3ParserUnknownEventAlertTest",
2688  DNP3ParserUnknownEventAlertTest);
2689  UtRegisterTest("DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);
2690 #endif
2691 }
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:370
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:372
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:77
DNP3ParserRegisterTests
void DNP3ParserRegisterTests(void)
Definition: app-layer-dnp3.c:2665
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:350
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:9071
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:347
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
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:385
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:448
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:412
DNP3ObjectG70V3_
Definition: app-layer-dnp3-objects.h:1217
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:339
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:442
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:1736
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:265
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:356
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:60
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:1195
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:483
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:64
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
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:457
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
AppLayerProtoDetectConfProtoDetectionEnabled
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:1987
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