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