suricata
app-layer-modbus.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 ANSSI
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /**
29  * \file
30  *
31  * \author David DIALLO <diallo@et.esiea.fr>
32  *
33  * App-layer parser for Modbus protocol
34  *
35  */
36 
37 #include "suricata-common.h"
38 
39 #include "util-debug.h"
40 #include "util-byte.h"
41 #include "util-enum.h"
42 #include "util-mem.h"
43 #include "util-misc.h"
44 
45 #include "stream.h"
46 #include "stream-tcp.h"
47 
48 #include "app-layer-protos.h"
49 #include "app-layer-parser.h"
50 #include "app-layer-modbus.h"
51 
52 #include "app-layer-detect-proto.h"
53 
54 #include "conf.h"
55 #include "conf-yaml-loader.h"
56 #include "decode.h"
57 
59  /* Modbus Application Data Unit messages - ADU Modbus */
60  { "INVALID_PROTOCOL_ID", MODBUS_DECODER_EVENT_INVALID_PROTOCOL_ID },
61  { "UNSOLICITED_RESPONSE", MODBUS_DECODER_EVENT_UNSOLICITED_RESPONSE },
62  { "INVALID_LENGTH", MODBUS_DECODER_EVENT_INVALID_LENGTH },
63  { "INVALID_UNIT_IDENTIFIER", MODBUS_DECODER_EVENT_INVALID_UNIT_IDENTIFIER},
64 
65  /* Modbus Protocol Data Unit messages - PDU Modbus */
66  { "INVALID_FUNCTION_CODE", MODBUS_DECODER_EVENT_INVALID_FUNCTION_CODE },
67  { "INVALID_VALUE", MODBUS_DECODER_EVENT_INVALID_VALUE },
68  { "INVALID_EXCEPTION_CODE", MODBUS_DECODER_EVENT_INVALID_EXCEPTION_CODE },
69  { "VALUE_MISMATCH", MODBUS_DECODER_EVENT_VALUE_MISMATCH },
70 
71  /* Modbus Decoder event */
72  { "FLOODED", MODBUS_DECODER_EVENT_FLOODED},
73  { NULL, -1 },
74 };
75 
76 /* Modbus Application Data Unit (ADU) length range. */
77 #define MODBUS_MIN_ADU_LEN 2
78 #define MODBUS_MAX_ADU_LEN 254
79 
80 /* Modbus Protocol version. */
81 #define MODBUS_PROTOCOL_VER 0
82 
83 /* Modbus Unit Identifier range. */
84 #define MODBUS_MIN_INVALID_UNIT_ID 247
85 #define MODBUS_MAX_INVALID_UNIT_ID 255
86 
87 /* Modbus Quantity range. */
88 #define MODBUS_MIN_QUANTITY 0
89 #define MODBUS_MAX_QUANTITY_IN_BIT_ACCESS 2000
90 #define MODBUS_MAX_QUANTITY_IN_WORD_ACCESS 125
91 
92 /* Modbus Count range. */
93 #define MODBUS_MIN_COUNT 1
94 #define MODBUS_MAX_COUNT 250
95 
96 /* Modbus Function Code. */
97 #define MODBUS_FUNC_READCOILS 0x01
98 #define MODBUS_FUNC_READDISCINPUTS 0x02
99 #define MODBUS_FUNC_READHOLDREGS 0x03
100 #define MODBUS_FUNC_READINPUTREGS 0x04
101 #define MODBUS_FUNC_WRITESINGLECOIL 0x05
102 #define MODBUS_FUNC_WRITESINGLEREG 0x06
103 #define MODBUS_FUNC_READEXCSTATUS 0x07
104 #define MODBUS_FUNC_DIAGNOSTIC 0x08
105 #define MODBUS_FUNC_GETCOMEVTCOUNTER 0x0b
106 #define MODBUS_FUNC_GETCOMEVTLOG 0x0c
107 #define MODBUS_FUNC_WRITEMULTCOILS 0x0f
108 #define MODBUS_FUNC_WRITEMULTREGS 0x10
109 #define MODBUS_FUNC_REPORTSERVERID 0x11
110 #define MODBUS_FUNC_READFILERECORD 0x14
111 #define MODBUS_FUNC_WRITEFILERECORD 0x15
112 #define MODBUS_FUNC_MASKWRITEREG 0x16
113 #define MODBUS_FUNC_READWRITEMULTREGS 0x17
114 #define MODBUS_FUNC_READFIFOQUEUE 0x18
115 #define MODBUS_FUNC_ENCAPINTTRANS 0x2b
116 #define MODBUS_FUNC_MASK 0x7f
117 #define MODBUS_FUNC_ERRORMASK 0x80
118 
119 /* Modbus Diagnostic functions: Subfunction Code. */
120 #define MODBUS_SUBFUNC_QUERY_DATA 0x00
121 #define MODBUS_SUBFUNC_RESTART_COM 0x01
122 #define MODBUS_SUBFUNC_DIAG_REGS 0x02
123 #define MODBUS_SUBFUNC_CHANGE_DELIMITER 0x03
124 #define MODBUS_SUBFUNC_LISTEN_MODE 0x04
125 #define MODBUS_SUBFUNC_CLEAR_REGS 0x0a
126 #define MODBUS_SUBFUNC_BUS_MSG_COUNT 0x0b
127 #define MODBUS_SUBFUNC_COM_ERR_COUNT 0x0c
128 #define MODBUS_SUBFUNC_EXCEPT_ERR_COUNT 0x0d
129 #define MODBUS_SUBFUNC_SERVER_MSG_COUNT 0x0e
130 #define MODBUS_SUBFUNC_SERVER_NO_RSP_COUNT 0x0f
131 #define MODBUS_SUBFUNC_SERVER_NAK_COUNT 0x10
132 #define MODBUS_SUBFUNC_SERVER_BUSY_COUNT 0x11
133 #define MODBUS_SUBFUNC_SERVER_CHAR_COUNT 0x12
134 #define MODBUS_SUBFUNC_CLEAR_COUNT 0x14
135 
136 /* Modbus Encapsulated Interface Transport function: MEI type. */
137 #define MODBUS_MEI_ENCAPINTTRANS_CAN 0x0d
138 #define MODBUS_MEI_ENCAPINTTRANS_READ 0x0e
139 
140 /* Modbus Exception Codes. */
141 #define MODBUS_ERROR_CODE_ILLEGAL_FUNCTION 0x01
142 #define MODBUS_ERROR_CODE_ILLEGAL_DATA_ADDRESS 0x02
143 #define MODBUS_ERROR_CODE_ILLEGAL_DATA_VALUE 0x03
144 #define MODBUS_ERROR_CODE_SERVER_DEVICE_FAILURE 0x04
145 #define MODBUS_ERROR_CODE_MEMORY_PARITY_ERROR 0x08
146 
147 /* Modbus Application Protocol (MBAP) header. */
149  uint16_t transactionId;
150  uint16_t protocolId;
151  uint16_t length;
152  uint8_t unitId;
153 } __attribute__((__packed__));
155 
156 /* Modbus Read/Write function and Access Types. */
157 #define MODBUS_TYP_WRITE_SINGLE (MODBUS_TYP_WRITE | MODBUS_TYP_SINGLE)
158 #define MODBUS_TYP_WRITE_MULTIPLE (MODBUS_TYP_WRITE | MODBUS_TYP_MULTIPLE)
159 #define MODBUS_TYP_READ_WRITE_MULTIPLE (MODBUS_TYP_READ | MODBUS_TYP_WRITE | MODBUS_TYP_MULTIPLE)
160 
161 /* Macro to convert quantity value (in bit) into count value (in word): count = Ceil(quantity/8) */
162 #define CEIL(quantity) (((quantity) + 7)>>3)
163 
164 /* Modbus Default unreplied Modbus requests are considered a flood */
165 #define MODBUS_CONFIG_DEFAULT_REQUEST_FLOOD 500
166 
167 /* Modbus default stream reassembly depth */
168 #define MODBUS_CONFIG_DEFAULT_STREAM_DEPTH 0
169 
170 static uint32_t request_flood = MODBUS_CONFIG_DEFAULT_REQUEST_FLOOD;
171 static uint32_t stream_depth = MODBUS_CONFIG_DEFAULT_STREAM_DEPTH;
172 
173 static int ModbusStateGetEventInfo(const char *event_name, int *event_id, AppLayerEventType *event_type)
174 {
175  *event_id = SCMapEnumNameToValue(event_name, modbus_decoder_event_table);
176 
177  if (*event_id == -1) {
178  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
179  "modbus's enum map table.", event_name);
180  /* yes this is fatal */
181  return -1;
182  }
183 
184  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
185 
186  return 0;
187 }
188 
189 static int ModbusStateGetEventInfoById(int event_id, const char **event_name,
190  AppLayerEventType *event_type)
191 {
192  *event_name = SCMapEnumValueToName(event_id, modbus_decoder_event_table);
193 
194  if (*event_name == NULL) {
195  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%d\" not present in "
196  "modbus's enum map table.", event_id);
197  /* yes this is fatal */
198  return -1;
199  }
200 
201  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
202 
203  return 0;
204 }
205 
206 static void ModbusSetEvent(ModbusState *modbus, uint8_t e)
207 {
208  if (modbus && modbus->curr) {
209  SCLogDebug("modbus->curr->decoder_events %p", modbus->curr->decoder_events);
211  SCLogDebug("modbus->curr->decoder_events %p", modbus->curr->decoder_events);
212  modbus->events++;
213  } else
214  SCLogDebug("couldn't set event %u", e);
215 }
216 
217 static AppLayerDecoderEvents *ModbusGetEvents(void *tx)
218 {
219  return ((ModbusTransaction *)tx)->decoder_events;
220 }
221 
222 static int ModbusGetAlstateProgress(void *modbus_tx, uint8_t direction)
223 {
224  ModbusTransaction *tx = (ModbusTransaction *) modbus_tx;
225  ModbusState *modbus = tx->modbus;
226 
227  if (tx->replied == 1)
228  return 1;
229 
230  /* Check flood limit */
231  if ((modbus->givenup == 1) &&
232  ((modbus->transaction_max - tx->tx_num) > request_flood))
233  return 1;
234 
235  return 0;
236 }
237 
238 /** \brief Get value for 'complete' status in Modbus
239  */
240 static int ModbusGetAlstateProgressCompletionStatus(uint8_t direction)
241 {
242  return 1;
243 }
244 
245 static void *ModbusGetTx(void *alstate, uint64_t tx_id)
246 {
247  ModbusState *modbus = (ModbusState *) alstate;
248  ModbusTransaction *tx = NULL;
249 
250  if (modbus->curr && modbus->curr->tx_num == tx_id + 1)
251  return modbus->curr;
252 
253  TAILQ_FOREACH(tx, &modbus->tx_list, next) {
254  SCLogDebug("tx->tx_num %"PRIu64", tx_id %"PRIu64, tx->tx_num, (tx_id+1));
255  if (tx->tx_num != (tx_id+1))
256  continue;
257 
258  SCLogDebug("returning tx %p", tx);
259  return tx;
260  }
261 
262  return NULL;
263 }
264 
265 static void ModbusSetTxLogged(void *alstate, void *vtx, LoggerId logged)
266 {
268  tx->logged = logged;
269 }
270 
271 static LoggerId ModbusGetTxLogged(void *alstate, void *vtx)
272 {
274  return tx->logged;
275 }
276 
277 static void ModbusSetTxDetectFlags(void *vtx, uint8_t dir, uint64_t flags)
278 {
280  if (dir & STREAM_TOSERVER) {
281  tx->detect_flags_ts = flags;
282  } else {
283  tx->detect_flags_tc = flags;
284  }
285 }
286 
287 static uint64_t ModbusGetTxDetectFlags(void *vtx, uint8_t dir)
288 {
290  if (dir & STREAM_TOSERVER) {
291  return tx->detect_flags_ts;
292  } else {
293  return tx->detect_flags_tc;
294  }
295 }
296 
297 static uint64_t ModbusGetTxCnt(void *alstate)
298 {
299  return ((uint64_t) ((ModbusState *) alstate)->transaction_max);
300 }
301 
302 /** \internal
303  * \brief Find the Modbus Transaction in the state based on Transaction ID.
304  *
305  * \param modbus Pointer to Modbus state structure
306  * \param transactionId Transaction ID of the transaction
307  *
308  * \retval tx or NULL if not found
309  */
310 static ModbusTransaction *ModbusTxFindByTransaction(const ModbusState *modbus,
311  const uint16_t transactionId)
312 {
313  ModbusTransaction *tx = NULL;
314 
315  if (modbus->curr == NULL)
316  return NULL;
317 
318  /* fast path */
319  if ((modbus->curr->transactionId == transactionId) &&
320  !(modbus->curr->replied)) {
321  return modbus->curr;
322  /* slow path, iterate list */
323  } else {
324  TAILQ_FOREACH(tx, &modbus->tx_list, next) {
325  if ((tx->transactionId == transactionId) &&
326  !(modbus->curr->replied))
327  return tx;
328  }
329  }
330  /* not found */
331  return NULL;
332 }
333 
334 /** \internal
335  * \brief Allocate a Modbus Transaction and
336  * add it into Transaction list of Modbus State
337  *
338  * \param modbus Pointer to Modbus state structure
339  *
340  * \retval Pointer to Transaction or NULL pointer
341  */
342 static ModbusTransaction *ModbusTxAlloc(ModbusState *modbus) {
343  ModbusTransaction *tx;
344 
345  tx = (ModbusTransaction *) SCCalloc(1, sizeof(ModbusTransaction));
346  if (unlikely(tx == NULL))
347  return NULL;
348 
349  modbus->transaction_max++;
350  modbus->unreplied_cnt++;
351 
352  /* Check flood limit */
353  if ((request_flood != 0) && (modbus->unreplied_cnt > request_flood)) {
354  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_FLOODED);
355  modbus->givenup = 1;
356  }
357 
358  modbus->curr = tx;
359 
360  SCLogDebug("modbus->transaction_max updated to %"PRIu64, modbus->transaction_max);
361 
362  TAILQ_INSERT_TAIL(&modbus->tx_list, tx, next);
363 
364  tx->modbus = modbus;
365  tx->tx_num = modbus->transaction_max;
366 
367  return tx;
368 }
369 
370 /** \internal
371  * \brief Free a Modbus Transaction
372  *
373  * \retval Pointer to Transaction or NULL pointer
374  */
375 static void ModbusTxFree(ModbusTransaction *tx) {
376  SCEnter();
377  if (tx->data != NULL)
378  SCFree(tx->data);
379 
381 
382  if (tx->de_state != NULL)
384 
385  SCFree(tx);
386  SCReturn;
387 }
388 
389 /**
390  * \brief Modbus transaction cleanup callback
391  */
392 static void ModbusStateTxFree(void *state, uint64_t tx_id)
393 {
394  SCEnter();
395  ModbusState *modbus = (ModbusState *) state;
396  ModbusTransaction *tx = NULL, *ttx;
397 
398  SCLogDebug("state %p, id %"PRIu64, modbus, tx_id);
399 
400  TAILQ_FOREACH_SAFE(tx, &modbus->tx_list, next, ttx) {
401  SCLogDebug("tx %p tx->tx_num %"PRIu64", tx_id %"PRIu64, tx, tx->tx_num, (tx_id+1));
402 
403  if (tx->tx_num != (tx_id+1))
404  continue;
405 
406  if (tx == modbus->curr)
407  modbus->curr = NULL;
408 
409  if (tx->decoder_events != NULL) {
410  if (tx->decoder_events->cnt <= modbus->events)
411  modbus->events -= tx->decoder_events->cnt;
412  else
413  modbus->events = 0;
414  }
415 
416  modbus->unreplied_cnt--;
417 
418  /* Check flood limit */
419  if ((modbus->givenup == 1) &&
420  (request_flood != 0) &&
421  (modbus->unreplied_cnt < request_flood) )
422  modbus->givenup = 0;
423 
424  TAILQ_REMOVE(&modbus->tx_list, tx, next);
425  ModbusTxFree(tx);
426  break;
427  }
428  SCReturn;
429 }
430 
431 /** \internal
432  * \brief Extract 8bits data from pointer the received input data
433  *
434  * \param res Pointer to the result
435  * \param input Pointer the received input data
436  * \param input_len Length of the received input data
437  * \param offset Offset of the received input data pointer
438  */
439 static int ModbusExtractUint8(ModbusState *modbus,
440  uint8_t *res,
441  const uint8_t *input,
442  uint32_t input_len,
443  uint16_t *offset) {
444  SCEnter();
445  if (input_len < (uint32_t) (*offset + sizeof(uint8_t))) {
446  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_LENGTH);
447  SCReturnInt(-1);
448  }
449 
450  *res = *(input + *offset);
451  *offset += sizeof(uint8_t);
452  SCReturnInt(0);
453 }
454 
455 /** \internal
456  * \brief Extract 16bits data from pointer the received input data
457  *
458  * \param res Pointer to the result
459  * \param input Pointer the received input data
460  * \param input_len Length of the received input data
461  * \param offset Offset of the received input data pointer
462  */
463 static int ModbusExtractUint16(ModbusState *modbus,
464  uint16_t *res,
465  const uint8_t *input,
466  uint32_t input_len,
467  uint16_t *offset) {
468  SCEnter();
469  if (input_len < (uint32_t) (*offset + sizeof(uint16_t))) {
470  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_LENGTH);
471  SCReturnInt(-1);
472  }
473 
474  ByteExtractUint16(res, BYTE_BIG_ENDIAN, sizeof(uint16_t), (const uint8_t *) (input + *offset));
475  *offset += sizeof(uint16_t);
476  SCReturnInt(0);
477 }
478 
479 /** \internal
480  * \brief Check length field in Modbus header according to code function
481  *
482  * \param modbus Pointer to Modbus state structure
483  * \param length Length field in Modbus Header
484  * \param len Length according to code functio
485  */
486 static int ModbusCheckHeaderLength(ModbusState *modbus,
487  uint16_t length,
488  uint16_t len) {
489  SCEnter();
490  if (length != len) {
491  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_LENGTH);
492  SCReturnInt(-1);
493  }
494  SCReturnInt(0);
495 }
496 
497 /** \internal
498  * \brief Check Modbus header
499  *
500  * \param tx Pointer to Modbus Transaction structure
501  * \param modbus Pointer to Modbus state structure
502  * \param header Pointer to Modbus header state in which the value to be stored
503  */
504 static void ModbusCheckHeader(ModbusState *modbus,
505  ModbusHeader *header)
506 {
507  SCEnter();
508  /* MODBUS protocol is identified by the value 0. */
509  if (header->protocolId != MODBUS_PROTOCOL_VER)
510  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_PROTOCOL_ID);
511 
512  /* Check Length field that is a byte count of the following fields */
513  if ((header->length < MODBUS_MIN_ADU_LEN) ||
514  (header->length > MODBUS_MAX_ADU_LEN) )
515  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_LENGTH);
516 
517  /* Check Unit Identifier field that is not in invalid range */
518  if ((header->unitId > MODBUS_MIN_INVALID_UNIT_ID) &&
519  (header->unitId < MODBUS_MAX_INVALID_UNIT_ID) )
520  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_UNIT_IDENTIFIER);
521 
522  SCReturn;
523 }
524 
525 /** \internal
526  * \brief Parse Exception Response and verify protocol compliance.
527  *
528  * \param tx Pointer to Modbus Transaction structure
529  * \param modbus Pointer to Modbus state structure
530  * \param input Pointer the received input data
531  * \param input_len Length of the received input data
532  * \param offset Offset of the received input data pointer
533  */
534 static void ModbusExceptionResponse(ModbusTransaction *tx,
535  ModbusState *modbus,
536  const uint8_t *input,
537  uint32_t input_len,
538  uint16_t *offset)
539 {
540  SCEnter();
541  uint8_t exception = 0;
542 
543  /* Exception code (1 byte) */
544  if (ModbusExtractUint8(modbus, &exception, input, input_len, offset))
545  SCReturn;
546 
547  switch (exception) {
550  break;
552  if (tx->function == MODBUS_FUNC_DIAGNOSTIC) {
553  break;
554  }
555  /* Fallthrough */
557  if ( (tx->type & MODBUS_TYP_ACCESS_FUNCTION_MASK) ||
560  break;
561  }
562  /* Fallthrough */
564  if ( (tx->function == MODBUS_FUNC_READFILERECORD) ||
566  break;
567  }
568  /* Fallthrough */
569  default:
570  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_EXCEPTION_CODE);
571  break;
572  }
573 
574  SCReturn;
575 }
576 
577 /** \internal
578  * \brief Parse Read data Request, complete Transaction structure
579  * and verify protocol compliance.
580  *
581  * \param tx Pointer to Modbus Transaction structure
582  * \param modbus Pointer to Modbus state structure
583  * \param input Pointer the received input data
584  * \param input_len Length of the received input data
585  * \param offset Offset of the received input data pointer
586  */
587 static void ModbusParseReadRequest(ModbusTransaction *tx,
588  ModbusState *modbus,
589  const uint8_t *input,
590  uint32_t input_len,
591  uint16_t *offset)
592 {
593  SCEnter();
594  uint16_t quantity;
595  uint8_t type = tx->type;
596 
597  /* Starting Address (2 bytes) */
598  if (ModbusExtractUint16(modbus, &(tx->read.address), input, input_len, offset))
599  goto end;
600 
601  /* Quantity (2 bytes) */
602  if (ModbusExtractUint16(modbus, &(tx->read.quantity), input, input_len, offset))
603  goto end;
604  quantity = tx->read.quantity;
605 
606  /* Check Quantity range */
608  if ((quantity == MODBUS_MIN_QUANTITY) ||
610  goto error;
611  } else {
612  if ((quantity == MODBUS_MIN_QUANTITY) ||
614  goto error;
615  }
616 
617  if (~type & MODBUS_TYP_WRITE)
618  /* Except from Read/Write Multiple Registers function (code 23) */
619  /* The length of all Read Data function requests is 6 bytes */
620  /* Modbus Application Protocol Specification V1.1b3 from 6.1 to 6.4 */
621  ModbusCheckHeaderLength(modbus, tx->length, 6);
622 
623  goto end;
624 
625 error:
626  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_VALUE);
627 end:
628  SCReturn;
629 }
630 
631 /** \internal
632  * \brief Parse Read data Response and verify protocol compliance
633  *
634  * \param tx Pointer to Modbus Transaction structure
635  * \param modbus Pointer to Modbus state structure
636  * \param input Pointer the received input data
637  * \param input_len Length of the received input data
638  * \param offset Offset of the received input data pointer
639  */
640 static void ModbusParseReadResponse(ModbusTransaction *tx,
641  ModbusState *modbus,
642  const uint8_t *input,
643  uint32_t input_len,
644  uint16_t *offset)
645 {
646  SCEnter();
647  uint8_t count = 0;
648 
649  /* Count (1 bytes) */
650  if (ModbusExtractUint8(modbus, &count, input, input_len, offset))
651  goto end;
652 
653  /* Check Count range and value according to the request */
654  if ((tx->type) & MODBUS_TYP_BIT_ACCESS_MASK) {
655  if ( (count < MODBUS_MIN_COUNT) ||
656  (count > MODBUS_MAX_COUNT) ||
657  (count != CEIL(tx->read.quantity)))
658  goto error;
659  } else {
660  if ( (count == MODBUS_MIN_COUNT) ||
661  (count > MODBUS_MAX_COUNT) ||
662  (count != (2 * (tx->read.quantity))))
663  goto error;
664  }
665 
666  /* Except from Read/Write Multiple Registers function (code 23) */
667  /* The length of all Read Data function responses is (3 bytes + count) */
668  /* Modbus Application Protocol Specification V1.1b3 from 6.1 to 6.4 */
669  ModbusCheckHeaderLength(modbus, tx->length, 3 + count);
670  goto end;
671 
672 error:
673  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_VALUE_MISMATCH);
674 end:
675  SCReturn;
676 }
677 
678 /** \internal
679  * \brief Parse Write data Request, complete Transaction structure
680  * and verify protocol compliance.
681  *
682  * \param tx Pointer to Modbus Transaction structure
683  * \param modbus Pointer to Modbus state structure
684  * \param input Pointer the received input data
685  * \param input_len Length of the received input data
686  * \param offset Offset of the received input data pointer
687  *
688  * \retval On success returns 0 or on failure returns -1.
689  */
690 static int ModbusParseWriteRequest(ModbusTransaction *tx,
691  ModbusState *modbus,
692  const uint8_t *input,
693  uint32_t input_len,
694  uint16_t *offset)
695 {
696  SCEnter();
697  uint16_t quantity = 1, word = 0;
698  uint8_t byte = 0, count = 1, type = tx->type;
699 
700  int i = 0;
701 
702  /* Starting/Output/Register Address (2 bytes) */
703  if (ModbusExtractUint16(modbus, &(tx->write.address), input, input_len, offset))
704  goto end;
705 
706  if (type & MODBUS_TYP_SINGLE) {
707  /* The length of Write Single Coil (code 5) and */
708  /* Write Single Register (code 6) requests is 6 bytes */
709  /* Modbus Application Protocol Specification V1.1b3 6.5 and 6.6 */
710  if (ModbusCheckHeaderLength(modbus, tx->length, 6))
711  goto end;
712  } else if (type & MODBUS_TYP_MULTIPLE) {
713  /* Quantity (2 bytes) */
714  if (ModbusExtractUint16(modbus, &quantity, input, input_len, offset))
715  goto end;
716  tx->write.quantity = quantity;
717 
718  /* Count (1 bytes) */
719  if (ModbusExtractUint8(modbus, &count, input, input_len, offset))
720  goto end;
721  tx->write.count = count;
722 
724  /* Check Quantity range and conversion in byte (count) */
725  if ((quantity == MODBUS_MIN_QUANTITY) ||
726  (quantity > MODBUS_MAX_QUANTITY_IN_BIT_ACCESS) ||
727  (quantity != CEIL(count)))
728  goto error;
729 
730  /* The length of Write Multiple Coils (code 15) request is (7 + count) */
731  /* Modbus Application Protocol Specification V1.1b3 6.11 */
732  if (ModbusCheckHeaderLength(modbus, tx->length, 7 + count))
733  goto end;
734  } else {
735  /* Check Quantity range and conversion in byte (count) */
736  if ((quantity == MODBUS_MIN_QUANTITY) ||
737  (quantity > MODBUS_MAX_QUANTITY_IN_WORD_ACCESS) ||
738  (count != (2 * quantity)))
739  goto error;
740 
741  if (type & MODBUS_TYP_READ) {
742  /* The length of Read/Write Multiple Registers function (code 23) */
743  /* request is (11 bytes + count) */
744  /* Modbus Application Protocol Specification V1.1b3 6.17 */
745  if (ModbusCheckHeaderLength(modbus, tx->length, 11 + count))
746  goto end;
747  } else {
748  /* The length of Write Multiple Coils (code 15) and */
749  /* Write Multiple Registers (code 16) functions requests is (7 bytes + count) */
750  /* Modbus Application Protocol Specification V1.1b3 from 6.11 and 6.12 */
751  if (ModbusCheckHeaderLength(modbus, tx->length, 7 + count))
752  goto end;
753  }
754  }
755  } else {
756  /* Mask Write Register function (And_Mask and Or_Mask) */
757  quantity = 2;
758 
759  /* The length of Mask Write Register (code 22) function request is 8 */
760  /* Modbus Application Protocol Specification V1.1b3 6.16 */
761  if (ModbusCheckHeaderLength(modbus, tx->length, 8))
762  goto end;
763  }
764 
765  if (type & MODBUS_TYP_COILS) {
766  /* Output value (data block) unit is count */
767  tx->data = (uint16_t *) SCCalloc(1, count * sizeof(uint16_t));
768  if (unlikely(tx->data == NULL))
769  SCReturnInt(-1);
770 
771  if (type & MODBUS_TYP_SINGLE) {
772  /* Outputs value (2 bytes) */
773  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
774  goto end;
775  tx->data[i] = word;
776 
777  if ((word != 0x00) && (word != 0xFF00))
778  goto error;
779  } else {
780  for (i = 0; i < count; i++) {
781  /* Outputs value (1 byte) */
782  if (ModbusExtractUint8(modbus, &byte, input, input_len, offset))
783  goto end;
784  tx->data[i] = (uint16_t) byte;
785  }
786  }
787  } else {
788  /* Registers value (data block) unit is quantity */
789  tx->data = (uint16_t *) SCCalloc(1, quantity * sizeof(uint16_t));
790  if (unlikely(tx->data == NULL))
791  SCReturnInt(-1);
792 
793  for (i = 0; i < quantity; i++) {
794  /* Outputs/Registers value (2 bytes) */
795  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
796  goto end;
797  tx->data[i] = word;
798  }
799  }
800  goto end;
801 
802 error:
803  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_VALUE);
804 end:
805  SCReturnInt(0);
806 }
807 
808 /** \internal
809  * \brief Parse Write data Response and verify protocol compliance
810  *
811  * \param tx Pointer to Modbus Transaction structure
812  * \param modbus Pointer to Modbus state structure
813  * \param input Pointer the received input data
814  * \param input_len Length of the received input data
815  * \param offset Offset of the received input data pointer
816  */
817 static void ModbusParseWriteResponse(ModbusTransaction *tx,
818  ModbusState *modbus,
819  const uint8_t *input,
820  uint32_t input_len,
821  uint16_t *offset)
822 {
823  SCEnter();
824  uint16_t address = 0, quantity = 0, word = 0;
825  uint8_t type = tx->type;
826 
827  /* Starting Address (2 bytes) */
828  if (ModbusExtractUint16(modbus, &address, input, input_len, offset))
829  goto end;
830 
831  if (address != tx->write.address)
832  goto error;
833 
834  if (type & MODBUS_TYP_SINGLE) {
835  /* Check if Outputs/Registers value has been stored */
836  if (tx->data != NULL)
837  {
838  /* Outputs/Registers value (2 bytes) */
839  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
840  goto end;
841 
842  /* Check with Outputs/Registers from request */
843  if (word != tx->data[0])
844  goto error;
845  }
846  } else if (type & MODBUS_TYP_MULTIPLE) {
847  /* Quantity (2 bytes) */
848  if (ModbusExtractUint16(modbus, &quantity, input, input_len, offset))
849  goto end;
850 
851  /* Check Quantity range */
853  if ((quantity == MODBUS_MIN_QUANTITY) ||
855  goto error;
856  } else {
857  if ((quantity == MODBUS_MIN_QUANTITY) ||
859  goto error;
860  }
861 
862  /* Check Quantity value according to the request */
863  if (quantity != tx->write.quantity)
864  goto error;
865  } else {
866  /* Check if And_Mask and Or_Mask values have been stored */
867  if (tx->data != NULL)
868  {
869  /* And_Mask value (2 bytes) */
870  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
871  goto end;
872 
873  /* Check And_Mask value according to the request */
874  if (word != tx->data[0])
875  goto error;
876 
877  /* And_Or_Mask value (2 bytes) */
878  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
879  goto end;
880 
881  /* Check Or_Mask value according to the request */
882  if (word != tx->data[1])
883  goto error;
884  }
885 
886  /* The length of Mask Write Register (code 22) function response is 8 */
887  /* Modbus Application Protocol Specification V1.1b3 6.16 */
888  ModbusCheckHeaderLength(modbus, tx->length, 8);
889  goto end;
890  }
891 
892  /* Except from Mask Write Register (code 22) */
893  /* The length of all Write Data function responses is 6 */
894  /* Modbus Application Protocol Specification V1.1b3 6.5, 6.6, 6.11, 6.12 and 6.17 */
895  ModbusCheckHeaderLength(modbus, tx->length, 6);
896  goto end;
897 
898 error:
899  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_VALUE_MISMATCH);
900 end:
901  SCReturn;
902 }
903 
904 /** \internal
905  * \brief Parse Diagnostic Request, complete Transaction
906  * structure (Category) and verify protocol compliance.
907  *
908  * \param tx Pointer to Modbus Transaction structure
909  * \param modbus Pointer to Modbus state structure
910  * \param input Pointer the received input data
911  * \param input_len Length of the received input data
912  * \param offset Offset of the received input data pointer
913  *
914  * \retval Reserved category function returns 1 otherwise returns 0.
915  */
916 static int ModbusParseDiagnosticRequest(ModbusTransaction *tx,
917  ModbusState *modbus,
918  const uint8_t *input,
919  uint32_t input_len,
920  uint16_t *offset)
921 {
922  SCEnter();
923  uint16_t data = 0;
924 
925  /* Sub-function (2 bytes) */
926  if (ModbusExtractUint16(modbus, &(tx->subFunction), input, input_len, offset))
927  goto end;
928 
929  /* Data (2 bytes) */
930  if (ModbusExtractUint16(modbus, &data, input, input_len, offset))
931  goto end;
932 
934  switch (tx->subFunction) {
936  if ((data != 0x00) && (data != 0xFF00))
937  goto error;
938  break;
939 
941  if ((data & 0xFF) != 0x00)
942  goto error;
943  break;
944 
946  /* No answer is expected then mark tx as completed. */
947  tx->replied = 1;
948  /* Fallthrough */
960  if (data != 0x00)
961  goto error;
962  break;
963 
964  default:
965  /* Set function code category */
967  SCReturnInt(1);
968  }
969 
970  /* The length of all Diagnostic Requests is 6 */
971  /* Modbus Application Protocol Specification V1.1b3 6.8 */
972  ModbusCheckHeaderLength(modbus, tx->length, 6);
973  }
974 
975  goto end;
976 
977 error:
978  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_VALUE);
979 end:
980  SCReturnInt(0);
981 }
982 
983 /* Modbus Function Code Categories structure. */
984 typedef struct ModbusFunctionCodeRange_ {
985  uint8_t function;
986  uint8_t category;
988 
989 /* Modbus Function Code Categories table. */
990 static ModbusFunctionCodeRange modbusFunctionCodeRanges[] = {
992  { 9, MODBUS_CAT_RESERVED },
994  { 41, MODBUS_CAT_RESERVED },
996  { 65, MODBUS_CAT_USER_DEFINED },
998  { 90, MODBUS_CAT_RESERVED },
1000  { 100, MODBUS_CAT_USER_DEFINED },
1002  { 125, MODBUS_CAT_RESERVED },
1003  { 128, MODBUS_CAT_NONE }
1004 };
1005 
1006 /** \internal
1007  * \brief Parse the Modbus Protocol Data Unit (PDU) Request
1008  *
1009  * \param tx Pointer to Modbus Transaction structure
1010  * \param ModbusPdu Pointer the Modbus PDU state in which the value to be stored
1011  * \param input Pointer the received input data
1012  * \param input_len Length of the received input data
1013  */
1014 static void ModbusParseRequestPDU(ModbusTransaction *tx,
1015  ModbusState *modbus,
1016  const uint8_t *input,
1017  uint32_t input_len)
1018 {
1019  SCEnter();
1020  uint16_t offset = (uint16_t) sizeof(ModbusHeader);
1021  uint8_t count = 0;
1022 
1023  int i = 0;
1024 
1025  /* Standard function codes used on MODBUS application layer protocol (1 byte) */
1026  if (ModbusExtractUint8(modbus, &(tx->function), input, input_len, &offset))
1027  goto end;
1028 
1029  /* Set default function code category */
1030  tx->category = MODBUS_CAT_NONE;
1031 
1032  /* Set default function primary table */
1033  tx->type = MODBUS_TYP_NONE;
1034 
1035  switch (tx->function) {
1036  case MODBUS_FUNC_NONE:
1037  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_FUNCTION_CODE);
1038  break;
1039 
1040  case MODBUS_FUNC_READCOILS:
1041  /* Set function type */
1043  break;
1044 
1046  /* Set function type */
1048  break;
1049 
1051  /* Set function type */
1053  break;
1054 
1056  /* Set function type */
1058  break;
1059 
1061  /* Set function type */
1063  break;
1064 
1066  /* Set function type */
1068  break;
1069 
1071  /* Set function type */
1073  break;
1074 
1076  /* Set function type */
1078  break;
1079 
1081  /* Set function type */
1083  break;
1084 
1086  /* Set function type */
1088  break;
1089 
1092  /* Count/length (1 bytes) */
1093  if (ModbusExtractUint8(modbus, &count, input, input_len, &offset))
1094  goto end;
1095 
1096  /* Modbus Application Protocol Specification V1.1b3 6.14 and 6.15 */
1097  ModbusCheckHeaderLength(modbus, tx->length, 2 + count);
1098  break;
1099 
1101  if(ModbusParseDiagnosticRequest(tx, modbus, input, input_len, &offset))
1102  goto end;
1103  break;
1104 
1109  /* Modbus Application Protocol Specification V1.1b3 6.7, 6.9, 6.10 and 6.13 */
1110  ModbusCheckHeaderLength(modbus, tx->length, 2);
1111  break;
1112 
1114  /* Modbus Application Protocol Specification V1.1b3 6.18 */
1115  ModbusCheckHeaderLength(modbus, tx->length, 4);
1116  break;
1117 
1119  /* MEI type (1 byte) */
1120  if (ModbusExtractUint8(modbus, &(tx->mei), input, input_len, &offset))
1121  goto end;
1122 
1123  if (tx->mei == MODBUS_MEI_ENCAPINTTRANS_READ) {
1124  /* Modbus Application Protocol Specification V1.1b3 6.21 */
1125  ModbusCheckHeaderLength(modbus, tx->length, 5);
1126  } else if (tx->mei != MODBUS_MEI_ENCAPINTTRANS_CAN) {
1127  /* Set function code category */
1129  goto end;
1130  }
1131  break;
1132 
1133  default:
1134  /* Check if request is error. */
1135  if (tx->function & MODBUS_FUNC_ERRORMASK) {
1136  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_FUNCTION_CODE);
1137  goto end;
1138  }
1139 
1140  /* Get and store function code category */
1141  for (i = 0; modbusFunctionCodeRanges[i].category != MODBUS_CAT_NONE; i++) {
1142  if (tx->function <= modbusFunctionCodeRanges[i].function)
1143  break;
1144  tx->category = modbusFunctionCodeRanges[i].category;
1145  }
1146  goto end;
1147  }
1148 
1149  /* Set function code category */
1151 
1152  if (tx->type & MODBUS_TYP_READ)
1153  ModbusParseReadRequest(tx, modbus, input, input_len, &offset);
1154 
1155  if (tx->type & MODBUS_TYP_WRITE)
1156  ModbusParseWriteRequest(tx, modbus, input, input_len, &offset);
1157 
1158 end:
1159  SCReturn;
1160 }
1161 
1162 /** \internal
1163  * \brief Parse the Modbus Protocol Data Unit (PDU) Response
1164  *
1165  * \param tx Pointer to Modbus Transaction structure
1166  * \param modbus Pointer the Modbus PDU state in which the value to be stored
1167  * \param input Pointer the received input data
1168  * \param input_len Length of the received input data
1169  * \param offset Offset of the received input data pointer
1170  */
1171 static void ModbusParseResponsePDU(ModbusTransaction *tx,
1172  ModbusState *modbus,
1173  const uint8_t *input,
1174  uint32_t input_len)
1175 {
1176  SCEnter();
1177  uint16_t offset = (uint16_t) sizeof(ModbusHeader);
1178  uint8_t count = 0, error = FALSE, function = 0, mei = 0;
1179 
1180  /* Standard function codes used on MODBUS application layer protocol (1 byte) */
1181  if (ModbusExtractUint8(modbus, &function, input, input_len, &offset))
1182  goto end;
1183 
1184  /* Check if response is error */
1185  if(function & MODBUS_FUNC_ERRORMASK) {
1186  function &= MODBUS_FUNC_MASK;
1187  error = TRUE;
1188  }
1189 
1190  if (tx->category == MODBUS_CAT_PUBLIC_ASSIGNED) {
1191  /* Check if response is error. */
1192  if (error) {
1193  ModbusExceptionResponse(tx, modbus, input, input_len, &offset);
1194  } else {
1195  switch(function) {
1197  /* Modbus Application Protocol Specification V1.1b3 6.7 */
1198  ModbusCheckHeaderLength(modbus, tx->length, 3);
1199  goto end;
1200 
1202  /* Modbus Application Protocol Specification V1.1b3 6.9 */
1203  ModbusCheckHeaderLength(modbus, tx->length, 6);
1204  goto end;
1205 
1208  /* Count/length (1 bytes) */
1209  if (ModbusExtractUint8(modbus, &count, input, input_len, &offset))
1210  goto end;
1211 
1212  /* Modbus Application Protocol Specification V1.1b3 6.14 and 6.15 */
1213  ModbusCheckHeaderLength(modbus, tx->length, 2 + count);
1214  goto end;
1215 
1217  /* MEI type (1 byte) */
1218  if (ModbusExtractUint8(modbus, &mei, input, input_len, &offset))
1219  goto end;
1220 
1221  if (mei != tx->mei)
1222  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_VALUE_MISMATCH);
1223  goto end;
1224  }
1225 
1226  if (tx->type & MODBUS_TYP_READ)
1227  ModbusParseReadResponse(tx, modbus, input, input_len, &offset);
1228  /* Read/Write response contents none write response part */
1229  else if (tx->type & MODBUS_TYP_WRITE)
1230  ModbusParseWriteResponse(tx, modbus, input, input_len, &offset);
1231  }
1232  }
1233 
1234 end:
1235  SCReturn;
1236 }
1237 
1238 /** \internal
1239  * \brief Parse the Modbus Application Protocol (MBAP) header
1240  *
1241  * \param header Pointer the Modbus header state in which the value to be stored
1242  * \param input Pointer the received input data
1243  */
1244 static int ModbusParseHeader(ModbusState *modbus,
1245  ModbusHeader *header,
1246  const uint8_t *input,
1247  uint32_t input_len)
1248 {
1249  SCEnter();
1250  uint16_t offset = 0;
1251 
1252  int r = 0;
1253 
1254  /* can't pass the header fields directly due to alignment (Bug 2088) */
1255  uint16_t transaction_id = 0;
1256  uint16_t protocol_id = 0;
1257  uint16_t length = 0;
1258  uint8_t unit_id = 0;
1259 
1260  /* Transaction Identifier (2 bytes) */
1261  r = ModbusExtractUint16(modbus, &transaction_id, input, input_len, &offset);
1262  /* Protocol Identifier (2 bytes) */
1263  r |= ModbusExtractUint16(modbus, &protocol_id, input, input_len, &offset);
1264  /* Length (2 bytes) */
1265  r |= ModbusExtractUint16(modbus, &length, input, input_len, &offset);
1266  /* Unit Identifier (1 byte) */
1267  r |= ModbusExtractUint8(modbus, &unit_id, input, input_len, &offset);
1268 
1269  if (r != 0) {
1270  SCReturnInt(-1);
1271  }
1272  header->transactionId = transaction_id;
1273  header->protocolId = protocol_id;
1274  header->length = length;
1275  header->unitId = unit_id;
1276 
1277  SCReturnInt(0);
1278 }
1279 
1280 /** \internal
1281  *
1282  * \brief This function is called to retrieve a Modbus Request
1283  *
1284  * \param state Modbus state structure for the parser
1285  * \param input Input line of the command
1286  * \param input_len Length of the request
1287  *
1288  * \retval AppLayerResult APP_LAYER_OK or APP_LAYER_ERROR
1289  */
1290 static AppLayerResult ModbusParseRequest(Flow *f,
1291  void *state,
1292  AppLayerParserState *pstate,
1293  const uint8_t *input,
1294  uint32_t input_len,
1295  void *local_data,
1296  const uint8_t flags)
1297 {
1298  SCEnter();
1299  ModbusState *modbus = (ModbusState *) state;
1300  ModbusTransaction *tx;
1301  ModbusHeader header;
1302 
1303  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
1305  } else if (input == NULL || input_len == 0) {
1307  }
1308 
1309  while (input_len > 0) {
1310  uint32_t adu_len = input_len;
1311  const uint8_t *adu = input;
1312 
1313  /* Extract MODBUS Header */
1314  if (ModbusParseHeader(modbus, &header, adu, adu_len))
1316 
1317  /* Update ADU length with length in Modbus header. */
1318  adu_len = (uint32_t) sizeof(ModbusHeader) + (uint32_t) header.length - 1;
1319  if (adu_len > input_len)
1321 
1322  /* Allocate a Transaction Context and add it to Transaction list */
1323  tx = ModbusTxAlloc(modbus);
1324  if (tx == NULL)
1326 
1327  /* Check MODBUS Header */
1328  ModbusCheckHeader(modbus, &header);
1329 
1330  /* Store Unit ID, Transaction ID & PDU length */
1331  tx->unit_id = header.unitId;
1332  tx->transactionId = header.transactionId;
1333  tx->length = header.length;
1334 
1335  /* Extract MODBUS PDU and fill Transaction Context */
1336  ModbusParseRequestPDU(tx, modbus, adu, adu_len);
1337 
1338  /* Update input line and remaining input length of the command */
1339  input += adu_len;
1340  input_len -= adu_len;
1341  }
1342 
1344 }
1345 
1346 /** \internal
1347  * \brief This function is called to retrieve a Modbus response
1348  *
1349  * \param state Pointer to Modbus state structure for the parser
1350  * \param input Input line of the command
1351  * \param input_len Length of the request
1352  *
1353  * \retval AppLayerResult APP_LAYER_OK or APP_LAYER_ERROR
1354  */
1355 static AppLayerResult ModbusParseResponse(Flow *f,
1356  void *state,
1357  AppLayerParserState *pstate,
1358  const uint8_t *input,
1359  uint32_t input_len,
1360  void *local_data,
1361  const uint8_t flags)
1362 {
1363  SCEnter();
1364  ModbusHeader header;
1365  ModbusState *modbus = (ModbusState *) state;
1366  ModbusTransaction *tx;
1367 
1368  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
1370  } else if (input == NULL || input_len == 0) {
1372  }
1373 
1374  while (input_len > 0) {
1375  uint32_t adu_len = input_len;
1376  const uint8_t *adu = input;
1377 
1378  /* Extract MODBUS Header */
1379  if (ModbusParseHeader(modbus, &header, adu, adu_len))
1381 
1382  /* Update ADU length with length in Modbus header. */
1383  adu_len = (uint32_t) sizeof(ModbusHeader) + (uint32_t) header.length - 1;
1384  if (adu_len > input_len)
1386 
1387  /* Find the transaction context thanks to transaction ID (and function code) */
1388  tx = ModbusTxFindByTransaction(modbus, header.transactionId);
1389  if (tx == NULL) {
1390  /* Allocate a Transaction Context if not previous request */
1391  /* and add it to Transaction list */
1392  tx = ModbusTxAlloc(modbus);
1393  if (tx == NULL)
1395 
1396  SCLogDebug("MODBUS_DECODER_EVENT_UNSOLICITED_RESPONSE");
1397  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_UNSOLICITED_RESPONSE);
1398  } else {
1399  /* Store PDU length */
1400  tx->length = header.length;
1401 
1402  /* Extract MODBUS PDU and fill Transaction Context */
1403  ModbusParseResponsePDU(tx, modbus, adu, adu_len);
1404  }
1405 
1406  /* Check and store MODBUS Header */
1407  ModbusCheckHeader(modbus, &header);
1408 
1409  /* Mark as completed */
1410  tx->replied = 1;
1411 
1412  /* Update input line and remaining input length of the command */
1413  input += adu_len;
1414  input_len -= adu_len;
1415  }
1416 
1418 }
1419 
1420 /** \internal
1421  * \brief Function to allocate the Modbus state memory
1422  */
1423 static void *ModbusStateAlloc(void)
1424 {
1425  ModbusState *modbus;
1426 
1427  modbus = (ModbusState *) SCCalloc(1, sizeof(ModbusState));
1428  if (unlikely(modbus == NULL))
1429  return NULL;
1430 
1431  TAILQ_INIT(&modbus->tx_list);
1432 
1433  return (void *) modbus;
1434 }
1435 
1436 /** \internal
1437  * \brief Function to free the Modbus state memory
1438  */
1439 static void ModbusStateFree(void *state)
1440 {
1441  SCEnter();
1442  ModbusState *modbus = (ModbusState *) state;
1443  ModbusTransaction *tx = NULL, *ttx;
1444 
1445  if (state) {
1446  TAILQ_FOREACH_SAFE(tx, &modbus->tx_list, next, ttx) {
1447  ModbusTxFree(tx);
1448  }
1449 
1450  SCFree(state);
1451  }
1452  SCReturn;
1453 }
1454 
1455 static uint16_t ModbusProbingParser(Flow *f,
1456  uint8_t direction,
1457  const uint8_t *input,
1458  uint32_t input_len,
1459  uint8_t *rdir)
1460 {
1461  ModbusHeader *header = (ModbusHeader *) input;
1462 
1463  /* Modbus header is 7 bytes long */
1464  if (input_len < sizeof(ModbusHeader))
1465  return ALPROTO_UNKNOWN;
1466 
1467  /* MODBUS protocol is identified by the value 0. */
1468  if (header->protocolId != 0)
1469  return ALPROTO_FAILED;
1470 
1471  return ALPROTO_MODBUS;
1472 }
1473 
1474 static DetectEngineState *ModbusGetTxDetectState(void *vtx)
1475 {
1476  ModbusTransaction *tx = (ModbusTransaction *)vtx;
1477  return tx->de_state;
1478 }
1479 
1480 static int ModbusSetTxDetectState(void *vtx, DetectEngineState *s)
1481 {
1482  ModbusTransaction *tx = (ModbusTransaction *)vtx;
1483  tx->de_state = s;
1484  return 0;
1485 }
1486 
1487 /**
1488  * \brief Function to register the Modbus protocol parsers and other functions
1489  */
1491 {
1492  SCEnter();
1493  const char *proto_name = "modbus";
1494 
1495  /* Modbus application protocol V1.1b3 */
1496  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
1498 
1499  if (RunmodeIsUnittests()) {
1500  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
1501  "502",
1503  0, sizeof(ModbusHeader),
1505  ModbusProbingParser, ModbusProbingParser);
1506  } else {
1507  /* If there is no app-layer section for Modbus, silently
1508  * leave it disabled. */
1509  if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
1510  proto_name, ALPROTO_MODBUS,
1511  0, sizeof(ModbusHeader),
1512  ModbusProbingParser, ModbusProbingParser)) {
1513  return;
1514  }
1515  }
1516 
1517  ConfNode *p = NULL;
1518  p = ConfGetNode("app-layer.protocols.modbus.request-flood");
1519  if (p != NULL) {
1520  uint32_t value;
1521  if (ParseSizeStringU32(p->val, &value) < 0) {
1522  SCLogError(SC_ERR_MODBUS_CONFIG, "invalid value for request-flood %s", p->val);
1523  } else {
1524  request_flood = value;
1525  }
1526  }
1527  SCLogConfig("Modbus request flood protection level: %u", request_flood);
1528 
1529  p = ConfGetNode("app-layer.protocols.modbus.stream-depth");
1530  if (p != NULL) {
1531  uint32_t value;
1532  if (ParseSizeStringU32(p->val, &value) < 0) {
1533  SCLogError(SC_ERR_MODBUS_CONFIG, "invalid value for stream-depth %s", p->val);
1534  } else {
1535  stream_depth = value;
1536  }
1537  }
1538  SCLogConfig("Modbus stream depth: %u", stream_depth);
1539  } else {
1540  SCLogConfig("Protocol detection and parser disabled for %s protocol.", proto_name);
1541  return;
1542  }
1543  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1544  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOSERVER, ModbusParseRequest);
1545  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOCLIENT, ModbusParseResponse);
1546  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateAlloc, ModbusStateFree);
1547 
1548  AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetEvents);
1550  ModbusGetTxDetectState, ModbusSetTxDetectState);
1551 
1552  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTx);
1553  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTxCnt);
1554  AppLayerParserRegisterLoggerFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTxLogged,
1555  ModbusSetTxLogged);
1556  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateTxFree);
1557 
1558  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetAlstateProgress);
1560  ModbusGetAlstateProgressCompletionStatus);
1561 
1562  AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateGetEventInfo);
1563  AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateGetEventInfoById);
1564 
1567  ModbusGetTxDetectFlags, ModbusSetTxDetectFlags);
1568 
1569  AppLayerParserSetStreamDepth(IPPROTO_TCP, ALPROTO_MODBUS, stream_depth);
1570  } else {
1571  SCLogConfig("Parsed disabled for %s protocol. Protocol detection" "still on.", proto_name);
1572  }
1573 #ifdef UNITTESTS
1575 #endif
1576 
1577  SCReturn;
1578 }
1579 
1580 /* UNITTESTS */
1581 #ifdef UNITTESTS
1582 #include "detect.h"
1583 #include "detect-engine.h"
1584 #include "detect-parse.h"
1585 
1586 #include "flow-util.h"
1587 
1588 #include "util-unittest.h"
1589 #include "util-unittest-helper.h"
1590 
1591 #include "stream-tcp.h"
1592 #include "stream-tcp-private.h"
1593 
1594 /* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
1595 static uint8_t invalidFunctionCode[] = {/* Transaction ID */ 0x00, 0x00,
1596  /* Protocol ID */ 0x00, 0x01,
1597  /* Length */ 0x00, 0x02,
1598  /* Unit ID */ 0x00,
1599  /* Function code */ 0x00};
1600 
1601 /* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
1602 /* Example of a request to read discrete outputs 20-38 */
1603 static uint8_t readCoilsReq[] = {/* Transaction ID */ 0x00, 0x00,
1604  /* Protocol ID */ 0x00, 0x00,
1605  /* Length */ 0x00, 0x06,
1606  /* Unit ID */ 0x00,
1607  /* Function code */ 0x01,
1608  /* Starting Address */ 0x78, 0x90,
1609  /* Quantity of coils */ 0x00, 0x13 };
1610 
1611 static uint8_t readCoilsRsp[] = {/* Transaction ID */ 0x00, 0x00,
1612  /* Protocol ID */ 0x00, 0x00,
1613  /* Length */ 0x00, 0x06,
1614  /* Unit ID */ 0x00,
1615  /* Function code */ 0x01,
1616  /* Byte count */ 0x03,
1617  /* Coil Status */ 0xCD, 0x6B, 0x05 };
1618 
1619 static uint8_t readCoilsErrorRsp[] = {/* Transaction ID */ 0x00, 0x00,
1620  /* Protocol ID */ 0x00, 0x00,
1621  /* Length */ 0x00, 0x03,
1622  /* Unit ID */ 0x00,
1623  /* Function code */ 0x81,
1624  /* Exception code */ 0x05};
1625 
1626 /* Modbus Application Protocol Specification V1.1b3 6.6: Write Single register */
1627 /* Example of a request to write register 2 to 00 03 hex */
1628 static uint8_t writeSingleRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1629  /* Protocol ID */ 0x00, 0x00,
1630  /* Length */ 0x00, 0x06,
1631  /* Unit ID */ 0x00,
1632  /* Function code */ 0x06,
1633  /* Register Address */ 0x00, 0x01,
1634  /* Register Value */ 0x00, 0x03};
1635 
1636 static uint8_t invalidWriteSingleRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1637  /* Protocol ID */ 0x00, 0x00,
1638  /* Length */ 0x00, 0x04,
1639  /* Unit ID */ 0x00,
1640  /* Function code */ 0x06,
1641  /* Register Address */ 0x00, 0x01};
1642 
1643 static uint8_t writeSingleRegisterRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1644  /* Protocol ID */ 0x00, 0x00,
1645  /* Length */ 0x00, 0x06,
1646  /* Unit ID */ 0x00,
1647  /* Function code */ 0x06,
1648  /* Register Address */ 0x00, 0x01,
1649  /* Register Value */ 0x00, 0x03};
1650 
1651 /* Modbus Application Protocol Specification V1.1b3 6.12: Write Multiple registers */
1652 /* Example of a request to write two registers starting at 2 to 00 0A and 01 02 hex */
1653 static uint8_t writeMultipleRegistersReq[] = {/* Transaction ID */ 0x00, 0x0A,
1654  /* Protocol ID */ 0x00, 0x00,
1655  /* Length */ 0x00, 0x0B,
1656  /* Unit ID */ 0x00,
1657  /* Function code */ 0x10,
1658  /* Starting Address */ 0x00, 0x01,
1659  /* Quantity of Registers */ 0x00, 0x02,
1660  /* Byte count */ 0x04,
1661  /* Registers Value */ 0x00, 0x0A,
1662  0x01, 0x02};
1663 
1664 static uint8_t writeMultipleRegistersRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1665  /* Protocol ID */ 0x00, 0x00,
1666  /* Length */ 0x00, 0x06,
1667  /* Unit ID */ 0x00,
1668  /* Function code */ 0x10,
1669  /* Starting Address */ 0x00, 0x01,
1670  /* Quantity of Registers */ 0x00, 0x02};
1671 
1672 /* Modbus Application Protocol Specification V1.1b3 6.16: Mask Write Register */
1673 /* Example of a request to mask write to register 5 */
1674 static uint8_t maskWriteRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1675  /* Protocol ID */ 0x00, 0x00,
1676  /* Length */ 0x00, 0x08,
1677  /* Unit ID */ 0x00,
1678  /* Function code */ 0x16,
1679  /* Reference Address */ 0x00, 0x04,
1680  /* And_Mask */ 0x00, 0xF2,
1681  /* Or_Mask */ 0x00, 0x25};
1682 
1683 static uint8_t invalidMaskWriteRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1684  /* Protocol ID */ 0x00, 0x00,
1685  /* Length */ 0x00, 0x06,
1686  /* Unit ID */ 0x00,
1687  /* Function code */ 0x16,
1688  /* Reference Address */ 0x00, 0x04,
1689  /* And_Mask */ 0x00, 0xF2};
1690 
1691 static uint8_t maskWriteRegisterRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1692  /* Protocol ID */ 0x00, 0x00,
1693  /* Length */ 0x00, 0x08,
1694  /* Unit ID */ 0x00,
1695  /* Function code */ 0x16,
1696  /* Reference Address */ 0x00, 0x04,
1697  /* And_Mask */ 0x00, 0xF2,
1698  /* Or_Mask */ 0x00, 0x25};
1699 
1700 /* Modbus Application Protocol Specification V1.1b3 6.17: Read/Write Multiple registers */
1701 /* Example of a request to read six registers starting at register 4, */
1702 /* and to write three registers starting at register 15 */
1703 static uint8_t readWriteMultipleRegistersReq[] = {/* Transaction ID */ 0x12, 0x34,
1704  /* Protocol ID */ 0x00, 0x00,
1705  /* Length */ 0x00, 0x11,
1706  /* Unit ID */ 0x00,
1707  /* Function code */ 0x17,
1708  /* Read Starting Address */ 0x00, 0x03,
1709  /* Quantity to Read */ 0x00, 0x06,
1710  /* Write Starting Address */ 0x00, 0x0E,
1711  /* Quantity to Write */ 0x00, 0x03,
1712  /* Write Byte count */ 0x06,
1713  /* Write Registers Value */ 0x12, 0x34,
1714  0x56, 0x78,
1715  0x9A, 0xBC};
1716 
1717 /* Mismatch value in Byte count 0x0B instead of 0x0C */
1718 static uint8_t readWriteMultipleRegistersRsp[] = {/* Transaction ID */ 0x12, 0x34,
1719  /* Protocol ID */ 0x00, 0x00,
1720  /* Length */ 0x00, 0x0E,
1721  /* Unit ID */ 0x00,
1722  /* Function code */ 0x17,
1723  /* Byte count */ 0x0B,
1724  /* Read Registers Value */ 0x00, 0xFE,
1725  0x0A, 0xCD,
1726  0x00, 0x01,
1727  0x00, 0x03,
1728  0x00, 0x0D,
1729  0x00};
1730 
1731 /* Modbus Application Protocol Specification V1.1b3 6.8.1: 04 Force Listen Only Mode */
1732 /* Example of a request to to remote device to its Listen Only Mode for Modbus Communications. */
1733 static uint8_t forceListenOnlyMode[] = {/* Transaction ID */ 0x0A, 0x00,
1734  /* Protocol ID */ 0x00, 0x00,
1735  /* Length */ 0x00, 0x06,
1736  /* Unit ID */ 0x00,
1737  /* Function code */ 0x08,
1738  /* Sub-function code */ 0x00, 0x04,
1739  /* Data */ 0x00, 0x00};
1740 
1741 static uint8_t invalidProtocolIdReq[] = {/* Transaction ID */ 0x00, 0x00,
1742  /* Protocol ID */ 0x00, 0x01,
1743  /* Length */ 0x00, 0x06,
1744  /* Unit ID */ 0x00,
1745  /* Function code */ 0x01,
1746  /* Starting Address */ 0x78, 0x90,
1747  /* Quantity of coils */ 0x00, 0x13 };
1748 
1749 static uint8_t invalidLengthWriteMultipleRegistersReq[] = {
1750  /* Transaction ID */ 0x00, 0x0A,
1751  /* Protocol ID */ 0x00, 0x00,
1752  /* Length */ 0x00, 0x09,
1753  /* Unit ID */ 0x00,
1754  /* Function code */ 0x10,
1755  /* Starting Address */ 0x00, 0x01,
1756  /* Quantity of Registers */ 0x00, 0x02,
1757  /* Byte count */ 0x04,
1758  /* Registers Value */ 0x00, 0x0A,
1759  0x01, 0x02};
1760 
1761 static uint8_t exceededLengthWriteMultipleRegistersReq[] = {
1762  /* Transaction ID */ 0x00, 0x0A,
1763  /* Protocol ID */ 0x00, 0x00,
1764  /* Length */ 0xff, 0xfa,
1765  /* Unit ID */ 0x00,
1766  /* Function code */ 0x10,
1767  /* Starting Address */ 0x00, 0x01,
1768  /* Quantity of Registers */ 0x7f, 0xf9,
1769  /* Byte count */ 0xff};
1770 
1771 static uint8_t invalidLengthPDUWriteMultipleRegistersReq[] = {
1772  /* Transaction ID */ 0x00, 0x0A,
1773  /* Protocol ID */ 0x00, 0x00,
1774  /* Length */ 0x00, 0x02,
1775  /* Unit ID */ 0x00,
1776  /* Function code */ 0x10};
1777 
1778 /** \test Send Modbus Read Coils request/response. */
1779 static int ModbusParserTest01(void) {
1781  Flow f;
1782  TcpSession ssn;
1783 
1785 
1786  memset(&f, 0, sizeof(f));
1787  memset(&ssn, 0, sizeof(ssn));
1788 
1789  FLOW_INITIALIZE(&f);
1790  f.protoctx = (void *)&ssn;
1791  f.proto = IPPROTO_TCP;
1792  f.alproto = ALPROTO_MODBUS;
1793 
1795 
1796  FLOWLOCK_WRLOCK(&f);
1797  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1798  STREAM_TOSERVER, readCoilsReq,
1799  sizeof(readCoilsReq));
1800  FAIL_IF_NOT(r == 0);
1801  FLOWLOCK_UNLOCK(&f);
1802 
1803  ModbusState *modbus_state = f.alstate;
1804  FAIL_IF_NULL(modbus_state);
1805 
1806  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1807  FAIL_IF_NOT(tx->function == 1);
1808  FAIL_IF_NOT(tx->read.address == 0x7890);
1809  FAIL_IF_NOT(tx->read.quantity == 19);
1810 
1811  FLOWLOCK_WRLOCK(&f);
1813  STREAM_TOCLIENT, readCoilsRsp,
1814  sizeof(readCoilsRsp));
1815  FAIL_IF_NOT(r == 0);
1816  FLOWLOCK_UNLOCK(&f);
1817 
1818  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1819 
1822  FLOW_DESTROY(&f);
1823  PASS;
1824 }
1825 
1826 /** \test Send Modbus Write Multiple registers request/response. */
1827 static int ModbusParserTest02(void) {
1829  Flow f;
1830  TcpSession ssn;
1831 
1833 
1834  memset(&f, 0, sizeof(f));
1835  memset(&ssn, 0, sizeof(ssn));
1836 
1837  FLOW_INITIALIZE(&f);
1838  f.protoctx = (void *)&ssn;
1839  f.proto = IPPROTO_TCP;
1840  f.alproto = ALPROTO_MODBUS;
1841 
1843 
1844  FLOWLOCK_WRLOCK(&f);
1845  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1846  STREAM_TOSERVER, writeMultipleRegistersReq,
1847  sizeof(writeMultipleRegistersReq));
1848  FAIL_IF_NOT(r == 0);
1849  FLOWLOCK_UNLOCK(&f);
1850 
1851  ModbusState *modbus_state = f.alstate;
1852  FAIL_IF_NULL(modbus_state);
1853 
1854  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1855 
1856  FAIL_IF_NOT(tx->function == 16);
1857  FAIL_IF_NOT(tx->write.address == 0x01);
1858  FAIL_IF_NOT(tx->write.quantity == 2);
1859  FAIL_IF_NOT(tx->write.count == 4);
1860  FAIL_IF_NOT(tx->data[0] == 0x000A);
1861  FAIL_IF_NOT(tx->data[1] == 0x0102);
1862 
1863  FLOWLOCK_WRLOCK(&f);
1865  STREAM_TOCLIENT, writeMultipleRegistersRsp,
1866  sizeof(writeMultipleRegistersRsp));
1867  FAIL_IF_NOT(r == 0);
1868  FLOWLOCK_UNLOCK(&f);
1869 
1870  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1871 
1874  FLOW_DESTROY(&f);
1875  PASS;
1876 }
1877 
1878 /** \test Send Modbus Read/Write Multiple registers request/response with mismatch value. */
1879 static int ModbusParserTest03(void) {
1881  DetectEngineThreadCtx *det_ctx = NULL;
1882  Flow f;
1883  Packet *p = NULL;
1884  Signature *s = NULL;
1885  TcpSession ssn;
1886  ThreadVars tv;
1887 
1889 
1890  memset(&tv, 0, sizeof(ThreadVars));
1891  memset(&f, 0, sizeof(Flow));
1892  memset(&ssn, 0, sizeof(TcpSession));
1893 
1894  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1895 
1896  FLOW_INITIALIZE(&f);
1897  f.alproto = ALPROTO_MODBUS;
1898  f.protoctx = (void *)&ssn;
1899  f.proto = IPPROTO_TCP;
1900  f.alproto = ALPROTO_MODBUS;
1901  f.flags |= FLOW_IPV4;
1902 
1903  p->flow = &f;
1906 
1908 
1911 
1912  de_ctx->flags |= DE_QUIET;
1913  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
1914  "(msg:\"Modbus Data mismatch\"; "
1915  "app-layer-event: "
1916  "modbus.value_mismatch; "
1917  "sid:1;)");
1918  FAIL_IF_NULL(s);
1919 
1921  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1922 
1923  FLOWLOCK_WRLOCK(&f);
1924  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1926  readWriteMultipleRegistersReq,
1927  sizeof(readWriteMultipleRegistersReq));
1928  FAIL_IF_NOT(r == 0);
1929  FLOWLOCK_UNLOCK(&f);
1930 
1931  ModbusState *modbus_state = f.alstate;
1932  FAIL_IF_NULL(modbus_state);
1933 
1934  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1935 
1936  FAIL_IF_NOT(tx->function == 23);
1937  FAIL_IF_NOT(tx->read.address == 0x03);
1938  FAIL_IF_NOT(tx->read.quantity == 6);
1939  FAIL_IF_NOT(tx->write.address == 0x0E);
1940  FAIL_IF_NOT(tx->write.quantity == 3);
1941  FAIL_IF_NOT(tx->write.count == 6);
1942  FAIL_IF_NOT(tx->data[0] == 0x1234);
1943  FAIL_IF_NOT(tx->data[1] == 0x5678);
1944  FAIL_IF_NOT(tx->data[2] == 0x9ABC);
1945 
1946  FLOWLOCK_WRLOCK(&f);
1948  STREAM_TOCLIENT, readWriteMultipleRegistersRsp,
1949  sizeof(readWriteMultipleRegistersRsp));
1950  FAIL_IF_NOT(r == 0);
1951  FLOWLOCK_UNLOCK(&f);
1952 
1953  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1954 
1955  /* do detect */
1956  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1957 
1959 
1962 
1963  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1965 
1968  FLOW_DESTROY(&f);
1969  UTHFreePackets(&p, 1);
1970  PASS;
1971 }
1972 
1973 /** \test Send Modbus Force Listen Only Mode request. */
1974 static int ModbusParserTest04(void) {
1976  Flow f;
1977  TcpSession ssn;
1978 
1980 
1981  memset(&f, 0, sizeof(f));
1982  memset(&ssn, 0, sizeof(ssn));
1983 
1984  FLOW_INITIALIZE(&f);
1985  f.protoctx = (void *)&ssn;
1986  f.proto = IPPROTO_TCP;
1987  f.alproto = ALPROTO_MODBUS;
1988 
1990 
1991  FLOWLOCK_WRLOCK(&f);
1992  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1993  STREAM_TOSERVER, forceListenOnlyMode,
1994  sizeof(forceListenOnlyMode));
1995  FAIL_IF_NOT(r == 0);
1996  FLOWLOCK_UNLOCK(&f);
1997 
1998  ModbusState *modbus_state = f.alstate;
1999  FAIL_IF_NULL(modbus_state);
2000 
2001  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2002 
2003  FAIL_IF_NOT(tx->function == 8);
2004  FAIL_IF_NOT(tx->subFunction == 4);
2005 
2008  FLOW_DESTROY(&f);
2009  PASS;
2010 }
2011 
2012 /** \test Send Modbus invalid Protocol version in request. */
2013 static int ModbusParserTest05(void) {
2015  DetectEngineThreadCtx *det_ctx = NULL;
2016  Flow f;
2017  Packet *p = NULL;
2018  Signature *s = NULL;
2019  TcpSession ssn;
2020  ThreadVars tv;
2021 
2023 
2024  memset(&tv, 0, sizeof(ThreadVars));
2025  memset(&f, 0, sizeof(Flow));
2026  memset(&ssn, 0, sizeof(TcpSession));
2027 
2028  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2029 
2030  FLOW_INITIALIZE(&f);
2031  f.alproto = ALPROTO_MODBUS;
2032  f.protoctx = (void *)&ssn;
2033  f.proto = IPPROTO_TCP;
2034  f.alproto = ALPROTO_MODBUS;
2035  f.flags |= FLOW_IPV4;
2036 
2037  p->flow = &f;
2040 
2042 
2045 
2046  de_ctx->flags |= DE_QUIET;
2047  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2048  "(msg:\"Modbus invalid Protocol version\"; "
2049  "app-layer-event: "
2050  "modbus.invalid_protocol_id; "
2051  "sid:1;)");
2052  FAIL_IF_NULL(s);
2053 
2055  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2056 
2057  FLOWLOCK_WRLOCK(&f);
2058  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2059  STREAM_TOSERVER, invalidProtocolIdReq,
2060  sizeof(invalidProtocolIdReq));
2061  FAIL_IF_NOT(r == 0);
2062  FLOWLOCK_UNLOCK(&f);
2063 
2064  ModbusState *modbus_state = f.alstate;
2065  FAIL_IF_NULL(modbus_state);
2066 
2067  /* do detect */
2068  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2069 
2071 
2074 
2075  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2077 
2080  FLOW_DESTROY(&f);
2081  UTHFreePackets(&p, 1);
2082  PASS;
2083 }
2084 
2085 /** \test Send Modbus unsolicited response. */
2086 static int ModbusParserTest06(void) {
2088  DetectEngineThreadCtx *det_ctx = NULL;
2089  Flow f;
2090  Packet *p = NULL;
2091  Signature *s = NULL;
2092  TcpSession ssn;
2093  ThreadVars tv;
2094 
2096 
2097  memset(&tv, 0, sizeof(ThreadVars));
2098  memset(&f, 0, sizeof(Flow));
2099  memset(&ssn, 0, sizeof(TcpSession));
2100 
2101  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2102 
2103  FLOW_INITIALIZE(&f);
2104  f.alproto = ALPROTO_MODBUS;
2105  f.protoctx = (void *)&ssn;
2106  f.proto = IPPROTO_TCP;
2107  f.alproto = ALPROTO_MODBUS;
2108  f.flags |= FLOW_IPV4;
2109 
2110  p->flow = &f;
2113 
2115 
2118 
2119  de_ctx->flags |= DE_QUIET;
2120  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2121  "(msg:\"Modbus unsolicited response\"; "
2122  "app-layer-event: "
2123  "modbus.unsolicited_response; "
2124  "sid:1;)");
2125  FAIL_IF_NULL(s);
2126 
2128  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2129 
2130  FLOWLOCK_WRLOCK(&f);
2131  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2132  STREAM_TOCLIENT, readCoilsRsp,
2133  sizeof(readCoilsRsp));
2134  FAIL_IF_NOT(r == 0);
2135  FLOWLOCK_UNLOCK(&f);
2136 
2137  ModbusState *modbus_state = f.alstate;
2138  FAIL_IF_NULL(modbus_state);
2139 
2140  /* do detect */
2141  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2142 
2144 
2147 
2148  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2150 
2153  FLOW_DESTROY(&f);
2154  UTHFreePackets(&p, 1);
2155  PASS;
2156 }
2157 
2158 /** \test Send Modbus invalid Length request. */
2159 static int ModbusParserTest07(void) {
2161  DetectEngineThreadCtx *det_ctx = NULL;
2162  Flow f;
2163  Packet *p = NULL;
2164  Signature *s = NULL;
2165  TcpSession ssn;
2166  ThreadVars tv;
2167 
2169 
2170  memset(&tv, 0, sizeof(ThreadVars));
2171  memset(&f, 0, sizeof(Flow));
2172  memset(&ssn, 0, sizeof(TcpSession));
2173 
2174  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2175 
2176  FLOW_INITIALIZE(&f);
2177  f.alproto = ALPROTO_MODBUS;
2178  f.protoctx = (void *)&ssn;
2179  f.proto = IPPROTO_TCP;
2180  f.alproto = ALPROTO_MODBUS;
2181  f.flags |= FLOW_IPV4;
2182 
2183  p->flow = &f;
2186 
2188 
2191 
2192  de_ctx->flags |= DE_QUIET;
2193  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2194  "(msg:\"Modbus invalid Length\"; "
2195  "app-layer-event: "
2196  "modbus.invalid_length; "
2197  "sid:1;)");
2198  FAIL_IF_NULL(s);
2199 
2201  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2202 
2203  FLOWLOCK_WRLOCK(&f);
2204  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2206  invalidLengthWriteMultipleRegistersReq,
2207  sizeof(invalidLengthWriteMultipleRegistersReq));
2208  FAIL_IF_NOT(r == 0);
2209  FLOWLOCK_UNLOCK(&f);
2210 
2211  ModbusState *modbus_state = f.alstate;
2212  FAIL_IF_NULL(modbus_state);
2213 
2214  /* do detect */
2215  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2216 
2218 
2221 
2222  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2224 
2227  FLOW_DESTROY(&f);
2228  UTHFreePackets(&p, 1);
2229  PASS;
2230 }
2231 
2232 /** \test Send Modbus Read Coils request and error response with Exception code invalid. */
2233 static int ModbusParserTest08(void) {
2235  DetectEngineThreadCtx *det_ctx = NULL;
2236  Flow f;
2237  Packet *p = NULL;
2238  Signature *s = NULL;
2239  TcpSession ssn;
2240  ThreadVars tv;
2241 
2243 
2244  memset(&tv, 0, sizeof(ThreadVars));
2245  memset(&f, 0, sizeof(Flow));
2246  memset(&ssn, 0, sizeof(TcpSession));
2247 
2248  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2249 
2250  FLOW_INITIALIZE(&f);
2251  f.alproto = ALPROTO_MODBUS;
2252  f.protoctx = (void *)&ssn;
2253  f.proto = IPPROTO_TCP;
2254  f.alproto = ALPROTO_MODBUS;
2255  f.flags |= FLOW_IPV4;
2256 
2257  p->flow = &f;
2260 
2262 
2265 
2266  de_ctx->flags |= DE_QUIET;
2267  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2268  "(msg:\"Modbus Exception code invalid\"; "
2269  "app-layer-event: "
2270  "modbus.invalid_exception_code; "
2271  "sid:1;)");
2272  FAIL_IF_NULL(s);
2273 
2275  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2276 
2277  FLOWLOCK_WRLOCK(&f);
2278  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2279  STREAM_TOSERVER, readCoilsReq,
2280  sizeof(readCoilsReq));
2281  FAIL_IF_NOT(r == 0);
2282  FLOWLOCK_UNLOCK(&f);
2283 
2284  ModbusState *modbus_state = f.alstate;
2285  FAIL_IF_NULL(modbus_state);
2286 
2287  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2288 
2289  FAIL_IF_NOT(tx->function == 1);
2290  FAIL_IF_NOT(tx->read.address == 0x7890);
2291  FAIL_IF_NOT(tx->read.quantity == 19);
2292 
2293  FLOWLOCK_WRLOCK(&f);
2295  STREAM_TOCLIENT, readCoilsErrorRsp,
2296  sizeof(readCoilsErrorRsp));
2297  FAIL_IF_NOT(r == 0);
2298  FLOWLOCK_UNLOCK(&f);
2299 
2300  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2301 
2302  /* do detect */
2303  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2304 
2306 
2309 
2310  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2312 
2315  FLOW_DESTROY(&f);
2316  UTHFreePackets(&p, 1);
2317  PASS;
2318 }
2319 
2320 /** \test Modbus fragmentation - 1 ADU over 2 TCP packets. */
2321 static int ModbusParserTest09(void) {
2323  Flow f;
2324  TcpSession ssn;
2325 
2326  uint32_t input_len = sizeof(readCoilsReq), part2_len = 3;
2327  uint8_t *input = readCoilsReq;
2328 
2330 
2331  memset(&f, 0, sizeof(f));
2332  memset(&ssn, 0, sizeof(ssn));
2333 
2334  FLOW_INITIALIZE(&f);
2335  f.protoctx = (void *)&ssn;
2336  f.proto = IPPROTO_TCP;
2337  f.alproto = ALPROTO_MODBUS;
2338 
2340 
2341  FLOWLOCK_WRLOCK(&f);
2342  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2343  STREAM_TOSERVER, input, input_len - part2_len);
2344  FAIL_IF_NOT(r == 0);
2345 
2347  STREAM_TOSERVER, input, input_len);
2348  FAIL_IF_NOT(r == 0);
2349  FLOWLOCK_UNLOCK(&f);
2350 
2351  ModbusState *modbus_state = f.alstate;
2352  FAIL_IF_NULL(modbus_state);
2353 
2354  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2355 
2356  FAIL_IF_NOT(tx->function == 1);
2357  FAIL_IF_NOT(tx->read.address == 0x7890);
2358  FAIL_IF_NOT(tx->read.quantity == 19);
2359 
2360  input_len = sizeof(readCoilsRsp);
2361  part2_len = 10;
2362  input = readCoilsRsp;
2363 
2364  FLOWLOCK_WRLOCK(&f);
2366  STREAM_TOCLIENT, input, input_len - part2_len);
2367  FAIL_IF_NOT(r == 0);
2368 
2370  STREAM_TOCLIENT, input, input_len);
2371  FAIL_IF_NOT(r == 0);
2372  FLOWLOCK_UNLOCK(&f);
2373 
2374  FAIL_IF_NOT(modbus_state->transaction_max ==1);
2375 
2378  FLOW_DESTROY(&f);
2379  PASS;
2380 }
2381 
2382 /** \test Modbus fragmentation - 2 ADU in 1 TCP packet. */
2383 static int ModbusParserTest10(void) {
2384  uint32_t input_len = sizeof(readCoilsReq) + sizeof(writeMultipleRegistersReq);
2385  uint8_t *input, *ptr;
2386 
2388  Flow f;
2389  TcpSession ssn;
2390 
2392 
2393  input = (uint8_t *) SCMalloc (input_len * sizeof(uint8_t));
2394  FAIL_IF_NULL(input);
2395 
2396  memcpy(input, readCoilsReq, sizeof(readCoilsReq));
2397  memcpy(input + sizeof(readCoilsReq), writeMultipleRegistersReq, sizeof(writeMultipleRegistersReq));
2398 
2399  memset(&f, 0, sizeof(f));
2400  memset(&ssn, 0, sizeof(ssn));
2401 
2402  FLOW_INITIALIZE(&f);
2403  f.protoctx = (void *)&ssn;
2404  f.proto = IPPROTO_TCP;
2405  f.alproto = ALPROTO_MODBUS;
2406 
2408 
2409  FLOWLOCK_WRLOCK(&f);
2410  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2411  STREAM_TOSERVER, input, input_len);
2412  FAIL_IF_NOT(r == 0);
2413  FLOWLOCK_UNLOCK(&f);
2414 
2415  ModbusState *modbus_state = f.alstate;
2416  FAIL_IF_NULL(modbus_state);
2417 
2418  FAIL_IF_NOT(modbus_state->transaction_max == 2);
2419 
2420  ModbusTransaction *tx = ModbusGetTx(modbus_state, 1);
2421 
2422  FAIL_IF_NOT(tx->function == 16);
2423  FAIL_IF_NOT(tx->write.address == 0x01);
2424  FAIL_IF_NOT(tx->write.quantity == 2);
2425  FAIL_IF_NOT(tx->write.count == 4);
2426  FAIL_IF_NOT(tx->data[0] == 0x000A);
2427  FAIL_IF_NOT(tx->data[1] == 0x0102);
2428 
2429  input_len = sizeof(readCoilsRsp) + sizeof(writeMultipleRegistersRsp);
2430 
2431  ptr = (uint8_t *) SCRealloc (input, input_len * sizeof(uint8_t));
2432  FAIL_IF_NULL(ptr);
2433  input = ptr;
2434 
2435  memcpy(input, readCoilsRsp, sizeof(readCoilsRsp));
2436  memcpy(input + sizeof(readCoilsRsp), writeMultipleRegistersRsp, sizeof(writeMultipleRegistersRsp));
2437 
2438  FLOWLOCK_WRLOCK(&f);
2440  STREAM_TOCLIENT, input, sizeof(input_len));
2441  FAIL_IF_NOT(r == 0);
2442  FLOWLOCK_UNLOCK(&f);
2443 
2444  SCFree(input);
2447  FLOW_DESTROY(&f);
2448  PASS;
2449 }
2450 
2451 /** \test Send Modbus exceed Length request. */
2452 static int ModbusParserTest11(void) {
2454  DetectEngineThreadCtx *det_ctx = NULL;
2455  Flow f;
2456  Packet *p = NULL;
2457  Signature *s = NULL;
2458  TcpSession ssn;
2459  ThreadVars tv;
2460 
2461  FAIL_IF(alp_tctx == NULL);
2462 
2463  memset(&tv, 0, sizeof(ThreadVars));
2464  memset(&f, 0, sizeof(Flow));
2465  memset(&ssn, 0, sizeof(TcpSession));
2466 
2467  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2468 
2469  FLOW_INITIALIZE(&f);
2470  f.alproto = ALPROTO_MODBUS;
2471  f.protoctx = (void *)&ssn;
2472  f.proto = IPPROTO_TCP;
2473  f.alproto = ALPROTO_MODBUS;
2474  f.flags |= FLOW_IPV4;
2475 
2476  p->flow = &f;
2479 
2481 
2484 
2485  de_ctx->flags |= DE_QUIET;
2486  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2487  "(msg:\"Modbus invalid Length\"; "
2488  "app-layer-event: "
2489  "modbus.invalid_length; "
2490  "sid:1;)");
2491  FAIL_IF_NULL(s);
2492 
2494  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2495 
2496  FLOWLOCK_WRLOCK(&f);
2497  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2499  exceededLengthWriteMultipleRegistersReq,
2500  sizeof(exceededLengthWriteMultipleRegistersReq) + 65523 * sizeof(uint8_t));
2501  FAIL_IF_NOT(r == 0);
2502  FLOWLOCK_UNLOCK(&f);
2503 
2504  ModbusState *modbus_state = f.alstate;
2505  FAIL_IF_NULL(modbus_state);
2506 
2507  /* do detect */
2508  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2509 
2511 
2514 
2515  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2517 
2520  FLOW_DESTROY(&f);
2521  UTHFreePackets(&p, 1);
2522  PASS;
2523 }
2524 
2525 /** \test Send Modbus invalid PDU Length. */
2526 static int ModbusParserTest12(void) {
2528  DetectEngineThreadCtx *det_ctx = NULL;
2529  Flow f;
2530  Packet *p = NULL;
2531  Signature *s = NULL;
2532  TcpSession ssn;
2533  ThreadVars tv;
2534 
2536 
2537  memset(&tv, 0, sizeof(ThreadVars));
2538  memset(&f, 0, sizeof(Flow));
2539  memset(&ssn, 0, sizeof(TcpSession));
2540 
2541  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2542 
2543  FLOW_INITIALIZE(&f);
2544  f.alproto = ALPROTO_MODBUS;
2545  f.protoctx = (void *)&ssn;
2546  f.proto = IPPROTO_TCP;
2547  f.alproto = ALPROTO_MODBUS;
2548  f.flags |= FLOW_IPV4;
2549 
2550  p->flow = &f;
2553 
2555 
2558 
2559  de_ctx->flags |= DE_QUIET;
2560  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2561  "(msg:\"Modbus invalid Length\"; "
2562  "app-layer-event: "
2563  "modbus.invalid_length; "
2564  "sid:1;)");
2565  FAIL_IF_NULL(s);
2566 
2568  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2569 
2570  FLOWLOCK_WRLOCK(&f);
2571  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2573  invalidLengthPDUWriteMultipleRegistersReq,
2574  sizeof(invalidLengthPDUWriteMultipleRegistersReq));
2575  FAIL_IF_NOT(r == 0);
2576  FLOWLOCK_UNLOCK(&f);
2577 
2578  ModbusState *modbus_state = f.alstate;
2579  FAIL_IF_NULL(modbus_state);
2580 
2581  /* do detect */
2582  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2583 
2585 
2588 
2589  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2591 
2594  FLOW_DESTROY(&f);
2595  UTHFreePackets(&p, 1);
2596  PASS;
2597 }
2598 
2599 /** \test Send Modbus Mask Write register request/response. */
2600 static int ModbusParserTest13(void) {
2602  Flow f;
2603  TcpSession ssn;
2604 
2606 
2607  memset(&f, 0, sizeof(f));
2608  memset(&ssn, 0, sizeof(ssn));
2609 
2610  FLOW_INITIALIZE(&f);
2611  f.protoctx = (void *)&ssn;
2612  f.proto = IPPROTO_TCP;
2613  f.alproto = ALPROTO_MODBUS;
2614 
2616 
2617  FLOWLOCK_WRLOCK(&f);
2618  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2619  STREAM_TOSERVER, maskWriteRegisterReq,
2620  sizeof(maskWriteRegisterReq));
2621  FAIL_IF_NOT(r == 0);
2622  FLOWLOCK_UNLOCK(&f);
2623 
2624  ModbusState *modbus_state = f.alstate;
2625  FAIL_IF_NULL(modbus_state);
2626 
2627  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2628 
2629  FAIL_IF_NOT(tx->function == 22);
2630  FAIL_IF_NOT(tx->data[0] == 0x00F2);
2631  FAIL_IF_NOT(tx->data[1] == 0x0025);
2632 
2633  FLOWLOCK_WRLOCK(&f);
2635  STREAM_TOCLIENT, maskWriteRegisterRsp,
2636  sizeof(maskWriteRegisterRsp));
2637  FAIL_IF_NOT(r == 0);
2638  FLOWLOCK_UNLOCK(&f);
2639 
2640  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2641 
2644  FLOW_DESTROY(&f);
2645  PASS;
2646 }
2647 
2648 /** \test Send Modbus Write single register request/response. */
2649 static int ModbusParserTest14(void) {
2651  Flow f;
2652  TcpSession ssn;
2653 
2655 
2656  memset(&f, 0, sizeof(f));
2657  memset(&ssn, 0, sizeof(ssn));
2658 
2659  FLOW_INITIALIZE(&f);
2660  f.protoctx = (void *)&ssn;
2661  f.proto = IPPROTO_TCP;
2662  f.alproto = ALPROTO_MODBUS;
2663 
2665 
2666  FLOWLOCK_WRLOCK(&f);
2667  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2668  STREAM_TOSERVER, writeSingleRegisterReq,
2669  sizeof(writeSingleRegisterReq));
2670  FAIL_IF_NOT(r == 0);
2671  FLOWLOCK_UNLOCK(&f);
2672 
2673  ModbusState *modbus_state = f.alstate;
2674  FAIL_IF_NULL(modbus_state);
2675 
2676  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2677 
2678  FAIL_IF_NOT(tx->function == 6);
2679  FAIL_IF_NOT(tx->write.address == 0x0001);
2680  FAIL_IF_NOT(tx->data[0] == 0x0003);
2681 
2682  FLOWLOCK_WRLOCK(&f);
2684  STREAM_TOCLIENT, writeSingleRegisterRsp,
2685  sizeof(writeSingleRegisterRsp));
2686  FAIL_IF_NOT(r == 0);
2687  FLOWLOCK_UNLOCK(&f);
2688 
2689  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2690 
2693  FLOW_DESTROY(&f);
2694  PASS;
2695 }
2696 
2697 /** \test Send invalid Modbus Mask Write register request. */
2698 static int ModbusParserTest15(void) {
2700  DetectEngineThreadCtx *det_ctx = NULL;
2701  Flow f;
2702  Packet *p = NULL;
2703  Signature *s = NULL;
2704  TcpSession ssn;
2705  ThreadVars tv;
2706 
2708 
2709  memset(&tv, 0, sizeof(ThreadVars));
2710  memset(&f, 0, sizeof(f));
2711  memset(&ssn, 0, sizeof(ssn));
2712 
2713  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2714 
2715  FLOW_INITIALIZE(&f);
2716  f.alproto = ALPROTO_MODBUS;
2717  f.protoctx = (void *)&ssn;
2718  f.proto = IPPROTO_TCP;
2719  f.alproto = ALPROTO_MODBUS;
2720  f.flags |= FLOW_IPV4;
2721 
2722  p->flow = &f;
2725 
2727 
2730 
2731  de_ctx->flags |= DE_QUIET;
2732  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2733  "(msg:\"Modbus invalid Length\"; "
2734  "app-layer-event: "
2735  "modbus.invalid_length; "
2736  "sid:1;)");
2737  FAIL_IF_NULL(s);
2738 
2740  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2741 
2742  FLOWLOCK_WRLOCK(&f);
2743  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2744  STREAM_TOSERVER, invalidMaskWriteRegisterReq,
2745  sizeof(invalidMaskWriteRegisterReq));
2746  FAIL_IF_NOT(r == 0);
2747  FLOWLOCK_UNLOCK(&f);
2748 
2749  ModbusState *modbus_state = f.alstate;
2750  FAIL_IF_NULL(modbus_state);
2751 
2752  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2753 
2754  FAIL_IF_NOT(tx->function == 22);
2755 
2756  /* do detect */
2757  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2758 
2760 
2761  FLOWLOCK_WRLOCK(&f);
2763  STREAM_TOCLIENT, maskWriteRegisterRsp,
2764  sizeof(maskWriteRegisterRsp));
2765  FAIL_IF_NOT(r == 0);
2766  FLOWLOCK_UNLOCK(&f);
2767 
2768  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2769 
2772 
2773  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2775 
2778  FLOW_DESTROY(&f);
2779  UTHFreePackets(&p, 1);
2780  PASS;
2781 }
2782 
2783 /** \test Send invalid Modbus Mask Write register request. */
2784 static int ModbusParserTest16(void) {
2786  DetectEngineThreadCtx *det_ctx = NULL;
2787  Flow f;
2788  Packet *p = NULL;
2789  Signature *s = NULL;
2790  TcpSession ssn;
2791  ThreadVars tv;
2792 
2794 
2795  memset(&tv, 0, sizeof(ThreadVars));
2796  memset(&f, 0, sizeof(f));
2797  memset(&ssn, 0, sizeof(ssn));
2798 
2799  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2800 
2801  FLOW_INITIALIZE(&f);
2802  f.alproto = ALPROTO_MODBUS;
2803  f.protoctx = (void *)&ssn;
2804  f.proto = IPPROTO_TCP;
2805  f.alproto = ALPROTO_MODBUS;
2806  f.flags |= FLOW_IPV4;
2807 
2808  p->flow = &f;
2811 
2813 
2816 
2817  de_ctx->flags |= DE_QUIET;
2818  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2819  "(msg:\"Modbus invalid Length\"; "
2820  "app-layer-event: "
2821  "modbus.invalid_length; "
2822  "sid:1;)");
2823  FAIL_IF_NULL(s);
2824 
2826  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2827 
2828  FLOWLOCK_WRLOCK(&f);
2829  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2831  invalidWriteSingleRegisterReq,
2832  sizeof(invalidWriteSingleRegisterReq));
2833  FAIL_IF_NOT(r == 0);
2834  FLOWLOCK_UNLOCK(&f);
2835 
2836  ModbusState *modbus_state = f.alstate;
2837  FAIL_IF_NULL(modbus_state);
2838 
2839  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2840 
2841  FAIL_IF_NOT(tx->function == 6);
2842  FAIL_IF_NOT(tx->write.address == 0x0001);
2843 
2844  /* do detect */
2845  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2846 
2848 
2849  FLOWLOCK_WRLOCK(&f);
2851  STREAM_TOCLIENT, writeSingleRegisterRsp,
2852  sizeof(writeSingleRegisterRsp));
2853  FAIL_IF_NOT(r == 0);
2854  FLOWLOCK_UNLOCK(&f);
2855 
2856  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2857 
2860 
2861  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2863 
2866  FLOW_DESTROY(&f);
2867  UTHFreePackets(&p, 1);
2868  PASS;}
2869 
2870 /** \test Checks if stream_depth is correct */
2871 static int ModbusParserTest17(void) {
2873  Flow f;
2874  TcpSession ssn;
2875 
2877 
2878  memset(&f, 0, sizeof(f));
2879  memset(&ssn, 0, sizeof(ssn));
2880 
2881  FLOW_INITIALIZE(&f);
2882  f.protoctx = (void *)&ssn;
2883  f.proto = IPPROTO_TCP;
2884  f.alproto = ALPROTO_MODBUS;
2885 
2887 
2888  FLOWLOCK_WRLOCK(&f);
2890  readCoilsReq, sizeof(readCoilsReq));
2891  FAIL_IF(r != 0);
2892  FLOWLOCK_UNLOCK(&f);
2893 
2894  FAIL_IF(f.alstate == NULL);
2895 
2896  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2897 
2898  FLOWLOCK_WRLOCK(&f);
2900  readCoilsRsp, sizeof(readCoilsRsp));
2901  FAIL_IF(r != 0);
2902  FLOWLOCK_UNLOCK(&f);
2903 
2904  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2905 
2908  FLOW_DESTROY(&f);
2909  PASS;
2910 }
2911 
2912 /*/ \test Checks if stream depth is correct over 2 TCP packets */
2913 static int ModbusParserTest18(void) {
2915  Flow f;
2916  TcpSession ssn;
2917 
2918  uint32_t input_len = sizeof(readCoilsReq), part2_len = 3;
2919  uint8_t *input = readCoilsReq;
2920 
2922 
2923  memset(&f, 0, sizeof(f));
2924  memset(&ssn, 0, sizeof(ssn));
2925 
2926  FLOW_INITIALIZE(&f);
2927  f.protoctx = (void *)&ssn;
2928  f.proto = IPPROTO_TCP;
2929  f.alproto = ALPROTO_MODBUS;
2930 
2932 
2933  FLOWLOCK_WRLOCK(&f);
2935  input, input_len - part2_len);
2936  FAIL_IF(r != 0);
2937  FLOWLOCK_UNLOCK(&f);
2938 
2939  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2940 
2941  FLOWLOCK_WRLOCK(&f);
2943  input, input_len);
2944  FAIL_IF(r != 0);
2945  FLOWLOCK_UNLOCK(&f);
2946 
2947  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2948 
2949  FAIL_IF(f.alstate == NULL);
2950 
2951  input_len = sizeof(readCoilsRsp);
2952  part2_len = 10;
2953  input = readCoilsRsp;
2954 
2955  FLOWLOCK_WRLOCK(&f);
2957  input, input_len - part2_len);
2958  FAIL_IF(r != 0);
2959  FLOWLOCK_UNLOCK(&f);
2960 
2961  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2962 
2963  FLOWLOCK_WRLOCK(&f);
2965  input, input_len);
2966  FAIL_IF(r != 0);
2967  FLOWLOCK_UNLOCK(&f);
2968 
2969  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2970 
2973  FLOW_DESTROY(&f);
2974  PASS;
2975 }
2976 
2977 /** \test Send Modbus invalid function. */
2978 static int ModbusParserTest19(void) {
2980  DetectEngineThreadCtx *det_ctx = NULL;
2981  Flow f;
2982  Packet *p = NULL;
2983  Signature *s = NULL;
2984  TcpSession ssn;
2985  ThreadVars tv;
2986 
2988 
2989  memset(&tv, 0, sizeof(ThreadVars));
2990  memset(&f, 0, sizeof(Flow));
2991  memset(&ssn, 0, sizeof(TcpSession));
2992 
2993  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2994 
2995  FLOW_INITIALIZE(&f);
2996  f.alproto = ALPROTO_MODBUS;
2997  f.protoctx = (void *)&ssn;
2998  f.proto = IPPROTO_TCP;
2999  f.alproto = ALPROTO_MODBUS;
3000  f.flags |= FLOW_IPV4;
3001 
3002  p->flow = &f;
3005 
3007 
3010 
3011  de_ctx->flags |= DE_QUIET;
3012  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
3013  "(msg:\"Modbus invalid Function code\"; "
3014  "app-layer-event: "
3015  "modbus.invalid_function_code; "
3016  "sid:1;)");
3017  FAIL_IF_NULL(s);
3018 
3020  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3021 
3022  FLOWLOCK_WRLOCK(&f);
3023  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
3025  invalidFunctionCode,
3026  sizeof(invalidFunctionCode));
3027  FAIL_IF_NOT(r == 0);
3028  FLOWLOCK_UNLOCK(&f);
3029 
3030  ModbusState *modbus_state = f.alstate;
3031  FAIL_IF_NULL(modbus_state);
3032 
3033  /* do detect */
3034  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3035 
3037 
3040 
3041  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
3043 
3046  FLOW_DESTROY(&f);
3047  UTHFreePackets(&p, 1);
3048  PASS;
3049 }
3050 #endif /* UNITTESTS */
3051 
3053 #ifdef UNITTESTS
3054  UtRegisterTest("ModbusParserTest01 - Modbus Read Coils request",
3055  ModbusParserTest01);
3056  UtRegisterTest("ModbusParserTest02 - Modbus Write Multiple registers request",
3057  ModbusParserTest02);
3058  UtRegisterTest("ModbusParserTest03 - Modbus Read/Write Multiple registers request",
3059  ModbusParserTest03);
3060  UtRegisterTest("ModbusParserTest04 - Modbus Force Listen Only Mode request",
3061  ModbusParserTest04);
3062  UtRegisterTest("ModbusParserTest05 - Modbus invalid Protocol version",
3063  ModbusParserTest05);
3064  UtRegisterTest("ModbusParserTest06 - Modbus unsolicited response",
3065  ModbusParserTest06);
3066  UtRegisterTest("ModbusParserTest07 - Modbus invalid Length request",
3067  ModbusParserTest07);
3068  UtRegisterTest("ModbusParserTest08 - Modbus Exception code invalid",
3069  ModbusParserTest08);
3070  UtRegisterTest("ModbusParserTest09 - Modbus fragmentation - 1 ADU in 2 TCP packets",
3071  ModbusParserTest09);
3072  UtRegisterTest("ModbusParserTest10 - Modbus fragmentation - 2 ADU in 1 TCP packet",
3073  ModbusParserTest10);
3074  UtRegisterTest("ModbusParserTest11 - Modbus exceeded Length request",
3075  ModbusParserTest11);
3076  UtRegisterTest("ModbusParserTest12 - Modbus invalid PDU Length",
3077  ModbusParserTest12);
3078  UtRegisterTest("ModbusParserTest13 - Modbus Mask Write register request",
3079  ModbusParserTest13);
3080  UtRegisterTest("ModbusParserTest14 - Modbus Write single register request",
3081  ModbusParserTest14);
3082  UtRegisterTest("ModbusParserTest15 - Modbus invalid Mask Write register request",
3083  ModbusParserTest15);
3084  UtRegisterTest("ModbusParserTest16 - Modbus invalid Write single register request",
3085  ModbusParserTest16);
3086  UtRegisterTest("ModbusParserTest17 - Modbus stream depth",
3087  ModbusParserTest17);
3088  UtRegisterTest("ModbusParserTest18 - Modbus stream depth in 2 TCP packets",
3089  ModbusParserTest18);
3090  UtRegisterTest("ModbusParserTest19 - Modbus invalid Function code",
3091  ModbusParserTest19);
3092 #endif /* UNITTESTS */
3093 }
MODBUS_FUNC_ERRORMASK
#define MODBUS_FUNC_ERRORMASK
Definition: app-layer-modbus.c:117
util-byte.h
ModbusTransaction_::type
uint8_t type
Definition: app-layer-modbus.h:95
MODBUS_CONFIG_DEFAULT_REQUEST_FLOOD
#define MODBUS_CONFIG_DEFAULT_REQUEST_FLOOD
Definition: app-layer-modbus.c:165
AppLayerParserRegisterGetStateProgressFunc
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
Definition: app-layer-parser.c:490
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:1647
len
uint8_t len
Definition: app-layer-dnp3.h:4
MODBUS_FUNC_WRITEMULTCOILS
#define MODBUS_FUNC_WRITEMULTCOILS
Definition: app-layer-modbus.c:107
detect-engine.h
MODBUS_FUNC_WRITEMULTREGS
#define MODBUS_FUNC_WRITEMULTREGS
Definition: app-layer-modbus.c:108
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
MODBUS_FUNC_MASKWRITEREG
#define MODBUS_FUNC_MASKWRITEREG
Definition: app-layer-modbus.c:112
ModbusTransaction_::category
uint8_t category
Definition: app-layer-modbus.h:94
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1077
offset
uint64_t offset
Definition: util-streaming-buffer.h:2
ModbusTransaction_::decoder_events
AppLayerDecoderEvents * decoder_events
Definition: app-layer-modbus.h:115
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:370
ByteExtractUint16
int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:164
flow-util.h
AppLayerParserRegisterStateFuncs
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
Definition: app-layer-parser.c:397
AppLayerParserSetStreamDepth
void AppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
Definition: app-layer-parser.c:1419
DetectEngineState_
Definition: detect-engine-state.h:92
MODBUS_CAT_PUBLIC_UNASSIGNED
#define MODBUS_CAT_PUBLIC_UNASSIGNED
Definition: app-layer-modbus.h:58
ConfNode_::val
char * val
Definition: conf.h:34
stream-tcp.h
MODBUS_TYP_HOLDING
#define MODBUS_TYP_HOLDING
Definition: app-layer-modbus.h:74
SCFree
#define SCFree(a)
Definition: util-mem.h:322
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
MODBUS_MIN_QUANTITY
#define MODBUS_MIN_QUANTITY
Definition: app-layer-modbus.c:88
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
MODBUS_FUNC_DIAGNOSTIC
#define MODBUS_FUNC_DIAGNOSTIC
Definition: app-layer-modbus.c:104
MODBUS_FUNC_READFILERECORD
#define MODBUS_FUNC_READFILERECORD
Definition: app-layer-modbus.c:110
MODBUS_SUBFUNC_SERVER_NAK_COUNT
#define MODBUS_SUBFUNC_SERVER_NAK_COUNT
Definition: app-layer-modbus.c:131
ModbusTransaction_::de_state
DetectEngineState * de_state
Definition: app-layer-modbus.h:116
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:335
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:2
AppLayerParserRegisterDetectFlagsFuncs
void AppLayerParserRegisterDetectFlagsFuncs(uint8_t ipproto, AppProto alproto, uint64_t(*GetTxDetectFlags)(void *tx, uint8_t dir), void(*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t))
Definition: app-layer-parser.c:589
RegisterModbusParsers
void RegisterModbusParsers(void)
Function to register the Modbus protocol parsers and other functions.
Definition: app-layer-modbus.c:1490
AppLayerParserRegisterLoggerFuncs
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
Definition: app-layer-parser.c:447
ALPROTO_MODBUS
@ ALPROTO_MODBUS
Definition: app-layer-protos.h:42
Flow_::proto
uint8_t proto
Definition: flow.h:359
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:302
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:138
Packet_::flags
uint32_t flags
Definition: decode.h:444
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
ModbusHeader_::protocolId
uint16_t protocolId
Definition: app-layer-modbus.c:150
Flow_
Flow data structure.
Definition: flow.h:340
AppLayerEventType
enum AppLayerEventType_ AppLayerEventType
AppLayerParserRegisterGetEventsFunc
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *))
Definition: app-layer-parser.c:436
LoggerId
LoggerId
Definition: suricata-common.h:416
logged
int logged
Definition: app-layer-htp.h:3
MODBUS_TYP_READ
#define MODBUS_TYP_READ
Definition: app-layer-modbus.h:66
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:761
AppLayerParserRegisterParserAcceptableDataDirection
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:376
ModbusHeader_::unitId
uint8_t unitId
Definition: app-layer-modbus.c:152
transactionId
uint16_t transactionId
Definition: app-layer-modbus.c:59
MODBUS_MAX_COUNT
#define MODBUS_MAX_COUNT
Definition: app-layer-modbus.c:94
AppLayerParserRegisterTxFreeFunc
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
Definition: app-layer-parser.c:501
MODBUS_TYP_SINGLE
#define MODBUS_TYP_SINGLE
Definition: app-layer-modbus.h:75
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2030
MODBUS_CONFIG_DEFAULT_STREAM_DEPTH
#define MODBUS_CONFIG_DEFAULT_STREAM_DEPTH
Definition: app-layer-modbus.c:168
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:279
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:216
MODBUS_FUNC_READEXCSTATUS
#define MODBUS_FUNC_READEXCSTATUS
Definition: app-layer-modbus.c:103
MODBUS_TYP_NONE
#define MODBUS_TYP_NONE
Definition: app-layer-modbus.h:64
AppLayerDecoderEventsFreeEvents
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
Definition: app-layer-events.c:148
MODBUS_SUBFUNC_EXCEPT_ERR_COUNT
#define MODBUS_SUBFUNC_EXCEPT_ERR_COUNT
Definition: app-layer-modbus.c:128
DE_QUIET
#define DE_QUIET
Definition: detect.h:292
MODBUS_FUNC_READWRITEMULTREGS
#define MODBUS_FUNC_READWRITEMULTREGS
Definition: app-layer-modbus.c:113
AppLayerParserRegisterDetectStateFuncs
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
Definition: app-layer-parser.c:577
MODBUS_SUBFUNC_RESTART_COM
#define MODBUS_SUBFUNC_RESTART_COM
Definition: app-layer-modbus.c:121
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:262
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:385
ModbusTransaction_::logged
uint32_t logged
Definition: app-layer-modbus.h:89
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:39
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:440
MODBUS_FUNC_GETCOMEVTCOUNTER
#define MODBUS_FUNC_GETCOMEVTCOUNTER
Definition: app-layer-modbus.c:105
Flow_::protoctx
void * protoctx
Definition: flow.h:414
MODBUS_ERROR_CODE_ILLEGAL_DATA_ADDRESS
#define MODBUS_ERROR_CODE_ILLEGAL_DATA_ADDRESS
Definition: app-layer-modbus.c:142
ModbusTransaction_::detect_flags_ts
uint64_t detect_flags_ts
Definition: app-layer-modbus.h:117
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:94
MODBUS_MIN_COUNT
#define MODBUS_MIN_COUNT
Definition: app-layer-modbus.c:93
AppLayerDecoderEvents_
Data structure to store app layer decoder events.
Definition: app-layer-events.h:34
util-unittest.h
MODBUS_MEI_ENCAPINTTRANS_READ
#define MODBUS_MEI_ENCAPINTTRANS_READ
Definition: app-layer-modbus.c:138
APP_LAYER_EVENT_TYPE_TRANSACTION
@ APP_LAYER_EVENT_TYPE_TRANSACTION
Definition: app-layer-events.h:57
MODBUS_MIN_INVALID_UNIT_ID
#define MODBUS_MIN_INVALID_UNIT_ID
Definition: app-layer-modbus.c:84
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
MODBUS_SUBFUNC_CHANGE_DELIMITER
#define MODBUS_SUBFUNC_CHANGE_DELIMITER
Definition: app-layer-modbus.c:123
FLOWLOCK_UNLOCK
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:258
MODBUS_SUBFUNC_DIAG_REGS
#define MODBUS_SUBFUNC_DIAG_REGS
Definition: app-layer-modbus.c:122
MODBUS_CAT_USER_DEFINED
#define MODBUS_CAT_USER_DEFINED
Definition: app-layer-modbus.h:59
__attribute__
struct ModbusHeader_ __attribute__((__packed__))
DNP3 link header.
Definition: decode-vlan.c:162
MODBUS_ERROR_CODE_ILLEGAL_DATA_VALUE
#define MODBUS_ERROR_CODE_ILLEGAL_DATA_VALUE
Definition: app-layer-modbus.c:143
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:1613
MODBUS_TYP_WRITE_MULTIPLE
#define MODBUS_TYP_WRITE_MULTIPLE
Definition: app-layer-modbus.c:158
MODBUS_PROTOCOL_VER
#define MODBUS_PROTOCOL_VER
Definition: app-layer-modbus.c:81
app-layer-detect-proto.h
ModbusHeader_::transactionId
uint16_t transactionId
Definition: app-layer-modbus.c:149
MODBUS_SUBFUNC_BUS_MSG_COUNT
#define MODBUS_SUBFUNC_BUS_MSG_COUNT
Definition: app-layer-modbus.c:126
MODBUS_FUNC_READINPUTREGS
#define MODBUS_FUNC_READINPUTREGS
Definition: app-layer-modbus.c:100
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
AppLayerParserStateIssetFlag
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
Definition: app-layer-parser.c:1619
MODBUS_SUBFUNC_SERVER_MSG_COUNT
#define MODBUS_SUBFUNC_SERVER_MSG_COUNT
Definition: app-layer-modbus.c:129
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:412
MODBUS_DECODER_EVENT_INVALID_PROTOCOL_ID
@ MODBUS_DECODER_EVENT_INVALID_PROTOCOL_ID
Definition: app-layer-modbus.h:44
decode.h
ModbusTransaction_::length
uint16_t length
Definition: app-layer-modbus.h:91
util-debug.h
MODBUS_FUNC_READCOILS
#define MODBUS_FUNC_READCOILS
Definition: app-layer-modbus.c:97
type
uint8_t type
Definition: decode-icmpv4.h:2
AppLayerParserState_
Definition: app-layer-parser.c:155
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:16
ModbusTransaction_::read
struct ModbusTransaction_::@17::@19::@21 read
MODBUS_CAT_RESERVED
#define MODBUS_CAT_RESERVED
Definition: app-layer-modbus.h:60
ModbusState_::transaction_max
uint64_t transaction_max
Definition: app-layer-modbus.h:127
DetectEngineThreadCtx_
Definition: detect.h:1004
MODBUS_TYP_ACCESS_FUNCTION_MASK
#define MODBUS_TYP_ACCESS_FUNCTION_MASK
Definition: app-layer-modbus.h:68
ModbusTransaction_::data
uint16_t * data
Definition: app-layer-modbus.h:113
ModbusTransaction_
Definition: app-layer-modbus.h:85
ModbusState_::events
uint16_t events
Definition: app-layer-modbus.h:129
MODBUS_DECODER_EVENT_INVALID_VALUE
@ MODBUS_DECODER_EVENT_INVALID_VALUE
Definition: app-layer-modbus.h:49
STREAM_TOSERVER
#define STREAM_TOSERVER
Definition: stream.h:31
res
PoolThreadReserved res
Definition: stream-tcp-private.h:60
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:19
FLOWLOCK_WRLOCK
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:255
MODBUS_FUNC_READFIFOQUEUE
#define MODBUS_FUNC_READFIFOQUEUE
Definition: app-layer-modbus.c:114
SCEnter
#define SCEnter(...)
Definition: util-debug.h:337
ModbusState_::givenup
uint8_t givenup
Definition: app-layer-modbus.h:130
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
MODBUS_ERROR_CODE_ILLEGAL_FUNCTION
#define MODBUS_ERROR_CODE_ILLEGAL_FUNCTION
Definition: app-layer-modbus.c:141
SCRealloc
#define SCRealloc(x, a)
Definition: util-mem.h:238
MODBUS_MAX_ADU_LEN
#define MODBUS_MAX_ADU_LEN
Definition: app-layer-modbus.c:78
MODBUS_TYP_DISCRETES
#define MODBUS_TYP_DISCRETES
Definition: app-layer-modbus.h:70
MODBUS_MIN_ADU_LEN
#define MODBUS_MIN_ADU_LEN
Definition: app-layer-modbus.c:77
ModbusHeader_::length
uint16_t length
Definition: app-layer-modbus.c:151
app-layer-parser.h
TRUE
#define TRUE
Definition: suricata-common.h:33
SCMalloc
#define SCMalloc(a)
Definition: util-mem.h:222
MODBUS_TYP_READ_WRITE_MULTIPLE
#define MODBUS_TYP_READ_WRITE_MULTIPLE
Definition: app-layer-modbus.c:159
BYTE_BIG_ENDIAN
#define BYTE_BIG_ENDIAN
Definition: util-byte.h:29
AppLayerDecoderEvents_::cnt
uint8_t cnt
Definition: app-layer-events.h:38
SigMatchSignatures
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1665
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1947
CEIL
#define CEIL(quantity)
Definition: app-layer-modbus.c:162
FALSE
#define FALSE
Definition: suricata-common.h:34
MODBUS_ERROR_CODE_MEMORY_PARITY_ERROR
#define MODBUS_ERROR_CODE_MEMORY_PARITY_ERROR
Definition: app-layer-modbus.c:145
SCReturn
#define SCReturn
Definition: util-debug.h:339
stream.h
MODBUS_SUBFUNC_CLEAR_COUNT
#define MODBUS_SUBFUNC_CLEAR_COUNT
Definition: app-layer-modbus.c:134
AppLayerParserRegisterProtocolUnittests
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
Definition: app-layer-parser.c:1717
Packet_
Definition: decode.h:408
ModbusTransaction_::replied
uint8_t replied
Definition: app-layer-modbus.h:96
SCCalloc
#define SCCalloc(nm, a)
Definition: util-mem.h:253
conf-yaml-loader.h
StreamTcpFreeConfig
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
stream-tcp-private.h
conf.h
MODBUS_SUBFUNC_QUERY_DATA
#define MODBUS_SUBFUNC_QUERY_DATA
Definition: app-layer-modbus.c:120
MODBUS_FUNC_READDISCINPUTS
#define MODBUS_FUNC_READDISCINPUTS
Definition: app-layer-modbus.c:98
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:565
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1828
MODBUS_CAT_NONE
#define MODBUS_CAT_NONE
Definition: app-layer-modbus.h:56
MODBUS_SUBFUNC_SERVER_CHAR_COUNT
#define MODBUS_SUBFUNC_SERVER_CHAR_COUNT
Definition: app-layer-modbus.c:133
MODBUS_ERROR_CODE_SERVER_DEVICE_FAILURE
#define MODBUS_ERROR_CODE_SERVER_DEVICE_FAILURE
Definition: app-layer-modbus.c:144
ModbusParserRegisterTests
void ModbusParserRegisterTests(void)
Definition: app-layer-modbus.c:3052
APP_LAYER_PARSER_EOF
#define APP_LAYER_PARSER_EOF
Definition: app-layer-parser.h:35
ModbusTransaction_::mei
uint8_t mei
Definition: app-layer-modbus.h:100
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:364
DetectEngineStateFree
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
Definition: detect-engine-state.c:175
MODBUS_SUBFUNC_SERVER_NO_RSP_COUNT
#define MODBUS_SUBFUNC_SERVER_NO_RSP_COUNT
Definition: app-layer-modbus.c:130
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1876
AppLayerParserRegisterGetStateProgressCompletionStatus
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
Definition: app-layer-parser.c:542
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:253
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:523
MODBUS_FUNC_ENCAPINTTRANS
#define MODBUS_FUNC_ENCAPINTTRANS
Definition: app-layer-modbus.c:115
MODBUS_TYP_INPUT
#define MODBUS_TYP_INPUT
Definition: app-layer-modbus.h:73
ModbusFunctionCodeRange_::category
uint8_t category
Definition: app-layer-modbus.c:986
ModbusTransaction_::function
uint8_t function
Definition: app-layer-modbus.h:93
MODBUS_DECODER_EVENT_INVALID_EXCEPTION_CODE
@ MODBUS_DECODER_EVENT_INVALID_EXCEPTION_CODE
Definition: app-layer-modbus.h:50
util-mem.h
length
uint16_t length
Definition: app-layer-modbus.c:61
app-layer-modbus.h
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:56
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2316
MODBUS_FUNC_WRITEFILERECORD
#define MODBUS_FUNC_WRITEFILERECORD
Definition: app-layer-modbus.c:111
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:69
Packet_::flow
struct Flow_ * flow
Definition: decode.h:446
SCReturnStruct
#define SCReturnStruct(x)
Definition: util-debug.h:357
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2726
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
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:41
flags
uint8_t flags
Definition: decode-gre.h:2
MODBUS_SUBFUNC_COM_ERR_COUNT
#define MODBUS_SUBFUNC_COM_ERR_COUNT
Definition: app-layer-modbus.c:127
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:1181
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:2934
MODBUS_CAT_PUBLIC_ASSIGNED
#define MODBUS_CAT_PUBLIC_ASSIGNED
Definition: app-layer-modbus.h:57
MODBUS_SUBFUNC_CLEAR_REGS
#define MODBUS_SUBFUNC_CLEAR_REGS
Definition: app-layer-modbus.c:125
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:294
ModbusHeader_
Definition: app-layer-modbus.c:148
MODBUS_TYP_BIT_ACCESS_MASK
#define MODBUS_TYP_BIT_ACCESS_MASK
Definition: app-layer-modbus.h:69
MODBUS_FUNC_GETCOMEVTLOG
#define MODBUS_FUNC_GETCOMEVTLOG
Definition: app-layer-modbus.c:106
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
MODBUS_FUNC_READHOLDREGS
#define MODBUS_FUNC_READHOLDREGS
Definition: app-layer-modbus.c:99
ParseSizeStringU32
int ParseSizeStringU32(const char *size, uint32_t *res)
Definition: util-misc.c:186
MODBUS_FUNC_REPORTSERVERID
#define MODBUS_FUNC_REPORTSERVERID
Definition: app-layer-modbus.c:109
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
MODBUS_SUBFUNC_LISTEN_MODE
#define MODBUS_SUBFUNC_LISTEN_MODE
Definition: app-layer-modbus.c:124
MODBUS_DECODER_EVENT_UNSOLICITED_RESPONSE
@ MODBUS_DECODER_EVENT_UNSOLICITED_RESPONSE
Definition: app-layer-modbus.h:45
MODBUS_FUNC_NONE
#define MODBUS_FUNC_NONE
Definition: app-layer-modbus.h:82
ModbusFunctionCodeRange_
Definition: app-layer-modbus.c:984
ModbusState_::curr
ModbusTransaction * curr
Definition: app-layer-modbus.h:126
MODBUS_MEI_ENCAPINTTRANS_CAN
#define MODBUS_MEI_ENCAPINTTRANS_CAN
Definition: app-layer-modbus.c:137
ModbusTransaction_::tx_num
uint64_t tx_num
Definition: app-layer-modbus.h:88
MODBUS_MAX_QUANTITY_IN_BIT_ACCESS
#define MODBUS_MAX_QUANTITY_IN_BIT_ACCESS
Definition: app-layer-modbus.c:89
ConfNode_
Definition: conf.h:32
MODBUS_DECODER_EVENT_VALUE_MISMATCH
@ MODBUS_DECODER_EVENT_VALUE_MISMATCH
Definition: app-layer-modbus.h:51
Flow_::alstate
void * alstate
Definition: flow.h:452
modbus_decoder_event_table
SCEnumCharMap modbus_decoder_event_table[]
Definition: app-layer-modbus.c:58
Flow_::flags
uint32_t flags
Definition: flow.h:394
ModbusState_::unreplied_cnt
uint32_t unreplied_cnt
Definition: app-layer-modbus.h:128
detect-parse.h
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:553
Signature_
Signature container.
Definition: detect.h:522
ModbusTransaction_::write
struct ModbusTransaction_::@17::@19::@22 write
MODBUS_FUNC_WRITESINGLEREG
#define MODBUS_FUNC_WRITESINGLEREG
Definition: app-layer-modbus.c:102
ModbusTransaction_::modbus
struct ModbusState_ * modbus
Definition: app-layer-modbus.h:86
address
uint8_t address
Definition: decode-ppp.h:2
SC_ERR_MODBUS_CONFIG
@ SC_ERR_MODBUS_CONFIG
Definition: util-error.h:273
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:61
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:218
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:1985
ModbusTransaction_::unit_id
uint8_t unit_id
Definition: app-layer-modbus.h:92
MODBUS_TYP_MULTIPLE
#define MODBUS_TYP_MULTIPLE
Definition: app-layer-modbus.h:76
app-layer-protos.h
MODBUS_SUBFUNC_SERVER_BUSY_COUNT
#define MODBUS_SUBFUNC_SERVER_BUSY_COUNT
Definition: app-layer-modbus.c:132
AppLayerParserRegisterGetTxCnt
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
Definition: app-layer-parser.c:512
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:60
SC_ERR_INVALID_ENUM_MAP
@ SC_ERR_INVALID_ENUM_MAP
Definition: util-error.h:45
MODBUS_DECODER_EVENT_INVALID_LENGTH
@ MODBUS_DECODER_EVENT_INVALID_LENGTH
Definition: app-layer-modbus.h:46
MODBUS_MAX_QUANTITY_IN_WORD_ACCESS
#define MODBUS_MAX_QUANTITY_IN_WORD_ACCESS
Definition: app-layer-modbus.c:90
MODBUS_MAX_INVALID_UNIT_ID
#define MODBUS_MAX_INVALID_UNIT_ID
Definition: app-layer-modbus.c:85
ModbusState_
Definition: app-layer-modbus.h:124
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:762
MODBUS_TYP_COILS
#define MODBUS_TYP_COILS
Definition: app-layer-modbus.h:71
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:85
MODBUS_DECODER_EVENT_INVALID_FUNCTION_CODE
@ MODBUS_DECODER_EVENT_INVALID_FUNCTION_CODE
Definition: app-layer-modbus.h:48
ModbusTransaction_::transactionId
uint16_t transactionId
Definition: app-layer-modbus.h:90
ModbusTransaction_::detect_flags_tc
uint64_t detect_flags_tc
Definition: app-layer-modbus.h:118
TcpSession_
Definition: stream-tcp-private.h:260
util-misc.h
ModbusFunctionCodeRange
struct ModbusFunctionCodeRange_ ModbusFunctionCodeRange
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:423
util-enum.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:341
MODBUS_DECODER_EVENT_INVALID_UNIT_IDENTIFIER
@ MODBUS_DECODER_EVENT_INVALID_UNIT_IDENTIFIER
Definition: app-layer-modbus.h:47
MODBUS_TYP_WRITE_SINGLE
#define MODBUS_TYP_WRITE_SINGLE
Definition: app-layer-modbus.c:157
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:1892
MODBUS_TYP_WRITE
#define MODBUS_TYP_WRITE
Definition: app-layer-modbus.h:67
MODBUS_DECODER_EVENT_FLOODED
@ MODBUS_DECODER_EVENT_FLOODED
Definition: app-layer-modbus.h:52
MODBUS_FUNC_WRITESINGLECOIL
#define MODBUS_FUNC_WRITESINGLECOIL
Definition: app-layer-modbus.c:101
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:121
ModbusTransaction_::subFunction
uint16_t subFunction
Definition: app-layer-modbus.h:99
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1075
MODBUS_FUNC_MASK
#define MODBUS_FUNC_MASK
Definition: app-layer-modbus.c:116
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:393