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,
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_ts = 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 */
607  if (type & MODBUS_TYP_BIT_ACCESS_MASK) {
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 */
852  if (type & MODBUS_TYP_BIT_ACCESS_MASK) {
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 1 when the command is parsed, 0 otherwise
1289  */
1290 static int 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)) {
1304  SCReturnInt(1);
1305  } else if (input == NULL || input_len == 0) {
1306  SCReturnInt(-1);
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))
1315  SCReturnInt(0);
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)
1320  SCReturnInt(0);
1321 
1322  /* Allocate a Transaction Context and add it to Transaction list */
1323  tx = ModbusTxAlloc(modbus);
1324  if (tx == NULL)
1325  SCReturnInt(0);
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 
1343  SCReturnInt(1);
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 1 when the command is parsed, 0 otherwise
1354  */
1355 static int 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)) {
1369  SCReturnInt(1);
1370  } else if (input == NULL || input_len == 0) {
1371  SCReturnInt(-1);
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))
1380  SCReturnInt(0);
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)
1385  SCReturnInt(0);
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)
1394  SCReturnInt(0);
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 
1417  SCReturnInt(1);
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 #ifndef AFLFUZZ_APPLAYER
1514  return;
1515 #endif
1516  }
1517  }
1518 
1519  ConfNode *p = NULL;
1520  p = ConfGetNode("app-layer.protocols.modbus.request-flood");
1521  if (p != NULL) {
1522  uint32_t value;
1523  if (ParseSizeStringU32(p->val, &value) < 0) {
1524  SCLogError(SC_ERR_MODBUS_CONFIG, "invalid value for request-flood %s", p->val);
1525  } else {
1526  request_flood = value;
1527  }
1528  }
1529  SCLogConfig("Modbus request flood protection level: %u", request_flood);
1530 
1531  p = ConfGetNode("app-layer.protocols.modbus.stream-depth");
1532  if (p != NULL) {
1533  uint32_t value;
1534  if (ParseSizeStringU32(p->val, &value) < 0) {
1535  SCLogError(SC_ERR_MODBUS_CONFIG, "invalid value for stream-depth %s", p->val);
1536  } else {
1537  stream_depth = value;
1538  }
1539  }
1540  SCLogConfig("Modbus stream depth: %u", stream_depth);
1541  } else {
1542 #ifndef AFLFUZZ_APPLAYER
1543  SCLogConfig("Protocol detection and parser disabled for %s protocol.", proto_name);
1544  return;
1545 #endif
1546  }
1547  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1548  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOSERVER, ModbusParseRequest);
1549  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOCLIENT, ModbusParseResponse);
1550  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateAlloc, ModbusStateFree);
1551 
1552  AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetEvents);
1554  ModbusGetTxDetectState, ModbusSetTxDetectState);
1555 
1556  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTx);
1557  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTxCnt);
1558  AppLayerParserRegisterLoggerFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTxLogged,
1559  ModbusSetTxLogged);
1560  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateTxFree);
1561 
1562  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetAlstateProgress);
1564  ModbusGetAlstateProgressCompletionStatus);
1565 
1566  AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateGetEventInfo);
1567  AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateGetEventInfoById);
1568 
1571  ModbusGetTxDetectFlags, ModbusSetTxDetectFlags);
1572 
1573  AppLayerParserSetStreamDepth(IPPROTO_TCP, ALPROTO_MODBUS, stream_depth);
1574  } else {
1575  SCLogConfig("Parsed disabled for %s protocol. Protocol detection" "still on.", proto_name);
1576  }
1577 #ifdef UNITTESTS
1579 #endif
1580 
1581  SCReturn;
1582 }
1583 
1584 /* UNITTESTS */
1585 #ifdef UNITTESTS
1586 #include "detect.h"
1587 #include "detect-engine.h"
1588 #include "detect-parse.h"
1589 
1590 #include "flow-util.h"
1591 
1592 #include "util-unittest.h"
1593 #include "util-unittest-helper.h"
1594 
1595 #include "stream-tcp.h"
1596 #include "stream-tcp-private.h"
1597 
1598 /* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
1599 static uint8_t invalidFunctionCode[] = {/* Transaction ID */ 0x00, 0x00,
1600  /* Protocol ID */ 0x00, 0x01,
1601  /* Length */ 0x00, 0x02,
1602  /* Unit ID */ 0x00,
1603  /* Function code */ 0x00};
1604 
1605 /* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
1606 /* Example of a request to read discrete outputs 20-38 */
1607 static uint8_t readCoilsReq[] = {/* Transaction ID */ 0x00, 0x00,
1608  /* Protocol ID */ 0x00, 0x00,
1609  /* Length */ 0x00, 0x06,
1610  /* Unit ID */ 0x00,
1611  /* Function code */ 0x01,
1612  /* Starting Address */ 0x78, 0x90,
1613  /* Quantity of coils */ 0x00, 0x13 };
1614 
1615 static uint8_t readCoilsRsp[] = {/* Transaction ID */ 0x00, 0x00,
1616  /* Protocol ID */ 0x00, 0x00,
1617  /* Length */ 0x00, 0x06,
1618  /* Unit ID */ 0x00,
1619  /* Function code */ 0x01,
1620  /* Byte count */ 0x03,
1621  /* Coil Status */ 0xCD, 0x6B, 0x05 };
1622 
1623 static uint8_t readCoilsErrorRsp[] = {/* Transaction ID */ 0x00, 0x00,
1624  /* Protocol ID */ 0x00, 0x00,
1625  /* Length */ 0x00, 0x03,
1626  /* Unit ID */ 0x00,
1627  /* Function code */ 0x81,
1628  /* Exception code */ 0x05};
1629 
1630 /* Modbus Application Protocol Specification V1.1b3 6.6: Write Single register */
1631 /* Example of a request to write register 2 to 00 03 hex */
1632 static uint8_t writeSingleRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1633  /* Protocol ID */ 0x00, 0x00,
1634  /* Length */ 0x00, 0x06,
1635  /* Unit ID */ 0x00,
1636  /* Function code */ 0x06,
1637  /* Register Address */ 0x00, 0x01,
1638  /* Register Value */ 0x00, 0x03};
1639 
1640 static uint8_t invalidWriteSingleRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1641  /* Protocol ID */ 0x00, 0x00,
1642  /* Length */ 0x00, 0x04,
1643  /* Unit ID */ 0x00,
1644  /* Function code */ 0x06,
1645  /* Register Address */ 0x00, 0x01};
1646 
1647 static uint8_t writeSingleRegisterRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1648  /* Protocol ID */ 0x00, 0x00,
1649  /* Length */ 0x00, 0x06,
1650  /* Unit ID */ 0x00,
1651  /* Function code */ 0x06,
1652  /* Register Address */ 0x00, 0x01,
1653  /* Register Value */ 0x00, 0x03};
1654 
1655 /* Modbus Application Protocol Specification V1.1b3 6.12: Write Multiple registers */
1656 /* Example of a request to write two registers starting at 2 to 00 0A and 01 02 hex */
1657 static uint8_t writeMultipleRegistersReq[] = {/* Transaction ID */ 0x00, 0x0A,
1658  /* Protocol ID */ 0x00, 0x00,
1659  /* Length */ 0x00, 0x0B,
1660  /* Unit ID */ 0x00,
1661  /* Function code */ 0x10,
1662  /* Starting Address */ 0x00, 0x01,
1663  /* Quantity of Registers */ 0x00, 0x02,
1664  /* Byte count */ 0x04,
1665  /* Registers Value */ 0x00, 0x0A,
1666  0x01, 0x02};
1667 
1668 static uint8_t writeMultipleRegistersRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1669  /* Protocol ID */ 0x00, 0x00,
1670  /* Length */ 0x00, 0x06,
1671  /* Unit ID */ 0x00,
1672  /* Function code */ 0x10,
1673  /* Starting Address */ 0x00, 0x01,
1674  /* Quantity of Registers */ 0x00, 0x02};
1675 
1676 /* Modbus Application Protocol Specification V1.1b3 6.16: Mask Write Register */
1677 /* Example of a request to mask write to register 5 */
1678 static uint8_t maskWriteRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1679  /* Protocol ID */ 0x00, 0x00,
1680  /* Length */ 0x00, 0x08,
1681  /* Unit ID */ 0x00,
1682  /* Function code */ 0x16,
1683  /* Reference Address */ 0x00, 0x04,
1684  /* And_Mask */ 0x00, 0xF2,
1685  /* Or_Mask */ 0x00, 0x25};
1686 
1687 static uint8_t invalidMaskWriteRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1688  /* Protocol ID */ 0x00, 0x00,
1689  /* Length */ 0x00, 0x06,
1690  /* Unit ID */ 0x00,
1691  /* Function code */ 0x16,
1692  /* Reference Address */ 0x00, 0x04,
1693  /* And_Mask */ 0x00, 0xF2};
1694 
1695 static uint8_t maskWriteRegisterRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1696  /* Protocol ID */ 0x00, 0x00,
1697  /* Length */ 0x00, 0x08,
1698  /* Unit ID */ 0x00,
1699  /* Function code */ 0x16,
1700  /* Reference Address */ 0x00, 0x04,
1701  /* And_Mask */ 0x00, 0xF2,
1702  /* Or_Mask */ 0x00, 0x25};
1703 
1704 /* Modbus Application Protocol Specification V1.1b3 6.17: Read/Write Multiple registers */
1705 /* Example of a request to read six registers starting at register 4, */
1706 /* and to write three registers starting at register 15 */
1707 static uint8_t readWriteMultipleRegistersReq[] = {/* Transaction ID */ 0x12, 0x34,
1708  /* Protocol ID */ 0x00, 0x00,
1709  /* Length */ 0x00, 0x11,
1710  /* Unit ID */ 0x00,
1711  /* Function code */ 0x17,
1712  /* Read Starting Address */ 0x00, 0x03,
1713  /* Quantity to Read */ 0x00, 0x06,
1714  /* Write Starting Address */ 0x00, 0x0E,
1715  /* Quantity to Write */ 0x00, 0x03,
1716  /* Write Byte count */ 0x06,
1717  /* Write Registers Value */ 0x12, 0x34,
1718  0x56, 0x78,
1719  0x9A, 0xBC};
1720 
1721 /* Mismatch value in Byte count 0x0B instead of 0x0C */
1722 static uint8_t readWriteMultipleRegistersRsp[] = {/* Transaction ID */ 0x12, 0x34,
1723  /* Protocol ID */ 0x00, 0x00,
1724  /* Length */ 0x00, 0x0E,
1725  /* Unit ID */ 0x00,
1726  /* Function code */ 0x17,
1727  /* Byte count */ 0x0B,
1728  /* Read Registers Value */ 0x00, 0xFE,
1729  0x0A, 0xCD,
1730  0x00, 0x01,
1731  0x00, 0x03,
1732  0x00, 0x0D,
1733  0x00};
1734 
1735 /* Modbus Application Protocol Specification V1.1b3 6.8.1: 04 Force Listen Only Mode */
1736 /* Example of a request to to remote device to its Listen Only MOde for Modbus Communications. */
1737 static uint8_t forceListenOnlyMode[] = {/* Transaction ID */ 0x0A, 0x00,
1738  /* Protocol ID */ 0x00, 0x00,
1739  /* Length */ 0x00, 0x06,
1740  /* Unit ID */ 0x00,
1741  /* Function code */ 0x08,
1742  /* Sub-function code */ 0x00, 0x04,
1743  /* Data */ 0x00, 0x00};
1744 
1745 static uint8_t invalidProtocolIdReq[] = {/* Transaction ID */ 0x00, 0x00,
1746  /* Protocol ID */ 0x00, 0x01,
1747  /* Length */ 0x00, 0x06,
1748  /* Unit ID */ 0x00,
1749  /* Function code */ 0x01,
1750  /* Starting Address */ 0x78, 0x90,
1751  /* Quantity of coils */ 0x00, 0x13 };
1752 
1753 static uint8_t invalidLengthWriteMultipleRegistersReq[] = {
1754  /* Transaction ID */ 0x00, 0x0A,
1755  /* Protocol ID */ 0x00, 0x00,
1756  /* Length */ 0x00, 0x09,
1757  /* Unit ID */ 0x00,
1758  /* Function code */ 0x10,
1759  /* Starting Address */ 0x00, 0x01,
1760  /* Quantity of Registers */ 0x00, 0x02,
1761  /* Byte count */ 0x04,
1762  /* Registers Value */ 0x00, 0x0A,
1763  0x01, 0x02};
1764 
1765 static uint8_t exceededLengthWriteMultipleRegistersReq[] = {
1766  /* Transaction ID */ 0x00, 0x0A,
1767  /* Protocol ID */ 0x00, 0x00,
1768  /* Length */ 0xff, 0xfa,
1769  /* Unit ID */ 0x00,
1770  /* Function code */ 0x10,
1771  /* Starting Address */ 0x00, 0x01,
1772  /* Quantity of Registers */ 0x7f, 0xf9,
1773  /* Byte count */ 0xff};
1774 
1775 static uint8_t invalidLengthPDUWriteMultipleRegistersReq[] = {
1776  /* Transaction ID */ 0x00, 0x0A,
1777  /* Protocol ID */ 0x00, 0x00,
1778  /* Length */ 0x00, 0x02,
1779  /* Unit ID */ 0x00,
1780  /* Function code */ 0x10};
1781 
1782 /** \test Send Modbus Read Coils request/response. */
1783 static int ModbusParserTest01(void) {
1785  Flow f;
1786  TcpSession ssn;
1787 
1788  FAIL_IF_NULL(alp_tctx);
1789 
1790  memset(&f, 0, sizeof(f));
1791  memset(&ssn, 0, sizeof(ssn));
1792 
1793  FLOW_INITIALIZE(&f);
1794  f.protoctx = (void *)&ssn;
1795  f.proto = IPPROTO_TCP;
1796  f.alproto = ALPROTO_MODBUS;
1797 
1799 
1800  FLOWLOCK_WRLOCK(&f);
1801  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1802  STREAM_TOSERVER, readCoilsReq,
1803  sizeof(readCoilsReq));
1804  FAIL_IF_NOT(r == 0);
1805  FLOWLOCK_UNLOCK(&f);
1806 
1807  ModbusState *modbus_state = f.alstate;
1808  FAIL_IF_NULL(modbus_state);
1809 
1810  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1811  FAIL_IF_NOT(tx->function == 1);
1812  FAIL_IF_NOT(tx->read.address == 0x7890);
1813  FAIL_IF_NOT(tx->read.quantity == 19);
1814 
1815  FLOWLOCK_WRLOCK(&f);
1816  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1817  STREAM_TOCLIENT, readCoilsRsp,
1818  sizeof(readCoilsRsp));
1819  FAIL_IF_NOT(r == 0);
1820  FLOWLOCK_UNLOCK(&f);
1821 
1822  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1823 
1824  AppLayerParserThreadCtxFree(alp_tctx);
1826  FLOW_DESTROY(&f);
1827  PASS;
1828 }
1829 
1830 /** \test Send Modbus Write Multiple registers request/response. */
1831 static int ModbusParserTest02(void) {
1833  Flow f;
1834  TcpSession ssn;
1835 
1836  FAIL_IF_NULL(alp_tctx);
1837 
1838  memset(&f, 0, sizeof(f));
1839  memset(&ssn, 0, sizeof(ssn));
1840 
1841  FLOW_INITIALIZE(&f);
1842  f.protoctx = (void *)&ssn;
1843  f.proto = IPPROTO_TCP;
1844  f.alproto = ALPROTO_MODBUS;
1845 
1847 
1848  FLOWLOCK_WRLOCK(&f);
1849  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1850  STREAM_TOSERVER, writeMultipleRegistersReq,
1851  sizeof(writeMultipleRegistersReq));
1852  FAIL_IF_NOT(r == 0);
1853  FLOWLOCK_UNLOCK(&f);
1854 
1855  ModbusState *modbus_state = f.alstate;
1856  FAIL_IF_NULL(modbus_state);
1857 
1858  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1859 
1860  FAIL_IF_NOT(tx->function == 16);
1861  FAIL_IF_NOT(tx->write.address == 0x01);
1862  FAIL_IF_NOT(tx->write.quantity == 2);
1863  FAIL_IF_NOT(tx->write.count == 4);
1864  FAIL_IF_NOT(tx->data[0] == 0x000A);
1865  FAIL_IF_NOT(tx->data[1] == 0x0102);
1866 
1867  FLOWLOCK_WRLOCK(&f);
1868  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1869  STREAM_TOCLIENT, writeMultipleRegistersRsp,
1870  sizeof(writeMultipleRegistersRsp));
1871  FAIL_IF_NOT(r == 0);
1872  FLOWLOCK_UNLOCK(&f);
1873 
1874  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1875 
1876  AppLayerParserThreadCtxFree(alp_tctx);
1878  FLOW_DESTROY(&f);
1879  PASS;
1880 }
1881 
1882 /** \test Send Modbus Read/Write Multiple registers request/response with mismatch value. */
1883 static int ModbusParserTest03(void) {
1885  DetectEngineThreadCtx *det_ctx = NULL;
1886  Flow f;
1887  Packet *p = NULL;
1888  Signature *s = NULL;
1889  TcpSession ssn;
1890  ThreadVars tv;
1891 
1892  FAIL_IF_NULL(alp_tctx);
1893 
1894  memset(&tv, 0, sizeof(ThreadVars));
1895  memset(&f, 0, sizeof(Flow));
1896  memset(&ssn, 0, sizeof(TcpSession));
1897 
1898  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1899 
1900  FLOW_INITIALIZE(&f);
1901  f.alproto = ALPROTO_MODBUS;
1902  f.protoctx = (void *)&ssn;
1903  f.proto = IPPROTO_TCP;
1904  f.alproto = ALPROTO_MODBUS;
1905  f.flags |= FLOW_IPV4;
1906 
1907  p->flow = &f;
1910 
1912 
1914  FAIL_IF_NULL(de_ctx);
1915 
1916  de_ctx->flags |= DE_QUIET;
1917  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
1918  "(msg:\"Modbus Data mismatch\"; "
1919  "app-layer-event: "
1920  "modbus.value_mismatch; "
1921  "sid:1;)");
1922  FAIL_IF_NULL(s);
1923 
1924  SigGroupBuild(de_ctx);
1925  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1926 
1927  FLOWLOCK_WRLOCK(&f);
1928  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1930  readWriteMultipleRegistersReq,
1931  sizeof(readWriteMultipleRegistersReq));
1932  FAIL_IF_NOT(r == 0);
1933  FLOWLOCK_UNLOCK(&f);
1934 
1935  ModbusState *modbus_state = f.alstate;
1936  FAIL_IF_NULL(modbus_state);
1937 
1938  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1939 
1940  FAIL_IF_NOT(tx->function == 23);
1941  FAIL_IF_NOT(tx->read.address == 0x03);
1942  FAIL_IF_NOT(tx->read.quantity == 6);
1943  FAIL_IF_NOT(tx->write.address == 0x0E);
1944  FAIL_IF_NOT(tx->write.quantity == 3);
1945  FAIL_IF_NOT(tx->write.count == 6);
1946  FAIL_IF_NOT(tx->data[0] == 0x1234);
1947  FAIL_IF_NOT(tx->data[1] == 0x5678);
1948  FAIL_IF_NOT(tx->data[2] == 0x9ABC);
1949 
1950  FLOWLOCK_WRLOCK(&f);
1951  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1952  STREAM_TOCLIENT, readWriteMultipleRegistersRsp,
1953  sizeof(readWriteMultipleRegistersRsp));
1954  FAIL_IF_NOT(r == 0);
1955  FLOWLOCK_UNLOCK(&f);
1956 
1957  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1958 
1959  /* do detect */
1960  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1961 
1963 
1964  SigGroupCleanup(de_ctx);
1965  SigCleanSignatures(de_ctx);
1966 
1967  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1968  DetectEngineCtxFree(de_ctx);
1969 
1970  AppLayerParserThreadCtxFree(alp_tctx);
1972  FLOW_DESTROY(&f);
1973  UTHFreePackets(&p, 1);
1974  PASS;
1975 }
1976 
1977 /** \test Send Modbus Force Listen Only Mode request. */
1978 static int ModbusParserTest04(void) {
1980  Flow f;
1981  TcpSession ssn;
1982 
1983  FAIL_IF_NULL(alp_tctx);
1984 
1985  memset(&f, 0, sizeof(f));
1986  memset(&ssn, 0, sizeof(ssn));
1987 
1988  FLOW_INITIALIZE(&f);
1989  f.protoctx = (void *)&ssn;
1990  f.proto = IPPROTO_TCP;
1991  f.alproto = ALPROTO_MODBUS;
1992 
1994 
1995  FLOWLOCK_WRLOCK(&f);
1996  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1997  STREAM_TOSERVER, forceListenOnlyMode,
1998  sizeof(forceListenOnlyMode));
1999  FAIL_IF_NOT(r == 0);
2000  FLOWLOCK_UNLOCK(&f);
2001 
2002  ModbusState *modbus_state = f.alstate;
2003  FAIL_IF_NULL(modbus_state);
2004 
2005  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2006 
2007  FAIL_IF_NOT(tx->function == 8);
2008  FAIL_IF_NOT(tx->subFunction == 4);
2009 
2010  AppLayerParserThreadCtxFree(alp_tctx);
2012  FLOW_DESTROY(&f);
2013  PASS;
2014 }
2015 
2016 /** \test Send Modbus invalid Protocol version in request. */
2017 static int ModbusParserTest05(void) {
2019  DetectEngineThreadCtx *det_ctx = NULL;
2020  Flow f;
2021  Packet *p = NULL;
2022  Signature *s = NULL;
2023  TcpSession ssn;
2024  ThreadVars tv;
2025 
2026  FAIL_IF_NULL(alp_tctx);
2027 
2028  memset(&tv, 0, sizeof(ThreadVars));
2029  memset(&f, 0, sizeof(Flow));
2030  memset(&ssn, 0, sizeof(TcpSession));
2031 
2032  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2033 
2034  FLOW_INITIALIZE(&f);
2035  f.alproto = ALPROTO_MODBUS;
2036  f.protoctx = (void *)&ssn;
2037  f.proto = IPPROTO_TCP;
2038  f.alproto = ALPROTO_MODBUS;
2039  f.flags |= FLOW_IPV4;
2040 
2041  p->flow = &f;
2044 
2046 
2048  FAIL_IF_NULL(de_ctx);
2049 
2050  de_ctx->flags |= DE_QUIET;
2051  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2052  "(msg:\"Modbus invalid Protocol version\"; "
2053  "app-layer-event: "
2054  "modbus.invalid_protocol_id; "
2055  "sid:1;)");
2056  FAIL_IF_NULL(s);
2057 
2058  SigGroupBuild(de_ctx);
2059  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2060 
2061  FLOWLOCK_WRLOCK(&f);
2062  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2063  STREAM_TOSERVER, invalidProtocolIdReq,
2064  sizeof(invalidProtocolIdReq));
2065  FAIL_IF_NOT(r == 0);
2066  FLOWLOCK_UNLOCK(&f);
2067 
2068  ModbusState *modbus_state = f.alstate;
2069  FAIL_IF_NULL(modbus_state);
2070 
2071  /* do detect */
2072  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2073 
2075 
2076  SigGroupCleanup(de_ctx);
2077  SigCleanSignatures(de_ctx);
2078 
2079  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2080  DetectEngineCtxFree(de_ctx);
2081 
2082  AppLayerParserThreadCtxFree(alp_tctx);
2084  FLOW_DESTROY(&f);
2085  UTHFreePackets(&p, 1);
2086  PASS;
2087 }
2088 
2089 /** \test Send Modbus unsolicited response. */
2090 static int ModbusParserTest06(void) {
2092  DetectEngineThreadCtx *det_ctx = NULL;
2093  Flow f;
2094  Packet *p = NULL;
2095  Signature *s = NULL;
2096  TcpSession ssn;
2097  ThreadVars tv;
2098 
2099  FAIL_IF_NULL(alp_tctx);
2100 
2101  memset(&tv, 0, sizeof(ThreadVars));
2102  memset(&f, 0, sizeof(Flow));
2103  memset(&ssn, 0, sizeof(TcpSession));
2104 
2105  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2106 
2107  FLOW_INITIALIZE(&f);
2108  f.alproto = ALPROTO_MODBUS;
2109  f.protoctx = (void *)&ssn;
2110  f.proto = IPPROTO_TCP;
2111  f.alproto = ALPROTO_MODBUS;
2112  f.flags |= FLOW_IPV4;
2113 
2114  p->flow = &f;
2117 
2119 
2121  FAIL_IF_NULL(de_ctx);
2122 
2123  de_ctx->flags |= DE_QUIET;
2124  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2125  "(msg:\"Modbus unsolicited response\"; "
2126  "app-layer-event: "
2127  "modbus.unsolicited_response; "
2128  "sid:1;)");
2129  FAIL_IF_NULL(s);
2130 
2131  SigGroupBuild(de_ctx);
2132  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2133 
2134  FLOWLOCK_WRLOCK(&f);
2135  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2136  STREAM_TOCLIENT, readCoilsRsp,
2137  sizeof(readCoilsRsp));
2138  FAIL_IF_NOT(r == 0);
2139  FLOWLOCK_UNLOCK(&f);
2140 
2141  ModbusState *modbus_state = f.alstate;
2142  FAIL_IF_NULL(modbus_state);
2143 
2144  /* do detect */
2145  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2146 
2148 
2149  SigGroupCleanup(de_ctx);
2150  SigCleanSignatures(de_ctx);
2151 
2152  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2153  DetectEngineCtxFree(de_ctx);
2154 
2155  AppLayerParserThreadCtxFree(alp_tctx);
2157  FLOW_DESTROY(&f);
2158  UTHFreePackets(&p, 1);
2159  PASS;
2160 }
2161 
2162 /** \test Send Modbus invalid Length request. */
2163 static int ModbusParserTest07(void) {
2165  DetectEngineThreadCtx *det_ctx = NULL;
2166  Flow f;
2167  Packet *p = NULL;
2168  Signature *s = NULL;
2169  TcpSession ssn;
2170  ThreadVars tv;
2171 
2172  FAIL_IF_NULL(alp_tctx);
2173 
2174  memset(&tv, 0, sizeof(ThreadVars));
2175  memset(&f, 0, sizeof(Flow));
2176  memset(&ssn, 0, sizeof(TcpSession));
2177 
2178  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2179 
2180  FLOW_INITIALIZE(&f);
2181  f.alproto = ALPROTO_MODBUS;
2182  f.protoctx = (void *)&ssn;
2183  f.proto = IPPROTO_TCP;
2184  f.alproto = ALPROTO_MODBUS;
2185  f.flags |= FLOW_IPV4;
2186 
2187  p->flow = &f;
2190 
2192 
2194  FAIL_IF_NULL(de_ctx);
2195 
2196  de_ctx->flags |= DE_QUIET;
2197  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2198  "(msg:\"Modbus invalid Length\"; "
2199  "app-layer-event: "
2200  "modbus.invalid_length; "
2201  "sid:1;)");
2202  FAIL_IF_NULL(s);
2203 
2204  SigGroupBuild(de_ctx);
2205  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2206 
2207  FLOWLOCK_WRLOCK(&f);
2208  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2210  invalidLengthWriteMultipleRegistersReq,
2211  sizeof(invalidLengthWriteMultipleRegistersReq));
2212  FAIL_IF_NOT(r == 0);
2213  FLOWLOCK_UNLOCK(&f);
2214 
2215  ModbusState *modbus_state = f.alstate;
2216  FAIL_IF_NULL(modbus_state);
2217 
2218  /* do detect */
2219  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2220 
2222 
2223  SigGroupCleanup(de_ctx);
2224  SigCleanSignatures(de_ctx);
2225 
2226  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2227  DetectEngineCtxFree(de_ctx);
2228 
2229  AppLayerParserThreadCtxFree(alp_tctx);
2231  FLOW_DESTROY(&f);
2232  UTHFreePackets(&p, 1);
2233  PASS;
2234 }
2235 
2236 /** \test Send Modbus Read Coils request and error response with Exception code invalid. */
2237 static int ModbusParserTest08(void) {
2239  DetectEngineThreadCtx *det_ctx = NULL;
2240  Flow f;
2241  Packet *p = NULL;
2242  Signature *s = NULL;
2243  TcpSession ssn;
2244  ThreadVars tv;
2245 
2246  FAIL_IF_NULL(alp_tctx);
2247 
2248  memset(&tv, 0, sizeof(ThreadVars));
2249  memset(&f, 0, sizeof(Flow));
2250  memset(&ssn, 0, sizeof(TcpSession));
2251 
2252  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2253 
2254  FLOW_INITIALIZE(&f);
2255  f.alproto = ALPROTO_MODBUS;
2256  f.protoctx = (void *)&ssn;
2257  f.proto = IPPROTO_TCP;
2258  f.alproto = ALPROTO_MODBUS;
2259  f.flags |= FLOW_IPV4;
2260 
2261  p->flow = &f;
2264 
2266 
2268  FAIL_IF_NULL(de_ctx);
2269 
2270  de_ctx->flags |= DE_QUIET;
2271  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2272  "(msg:\"Modbus Exception code invalid\"; "
2273  "app-layer-event: "
2274  "modbus.invalid_exception_code; "
2275  "sid:1;)");
2276  FAIL_IF_NULL(s);
2277 
2278  SigGroupBuild(de_ctx);
2279  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2280 
2281  FLOWLOCK_WRLOCK(&f);
2282  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2283  STREAM_TOSERVER, readCoilsReq,
2284  sizeof(readCoilsReq));
2285  FAIL_IF_NOT(r == 0);
2286  FLOWLOCK_UNLOCK(&f);
2287 
2288  ModbusState *modbus_state = f.alstate;
2289  FAIL_IF_NULL(modbus_state);
2290 
2291  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2292 
2293  FAIL_IF_NOT(tx->function == 1);
2294  FAIL_IF_NOT(tx->read.address == 0x7890);
2295  FAIL_IF_NOT(tx->read.quantity == 19);
2296 
2297  FLOWLOCK_WRLOCK(&f);
2298  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2299  STREAM_TOCLIENT, readCoilsErrorRsp,
2300  sizeof(readCoilsErrorRsp));
2301  FAIL_IF_NOT(r == 0);
2302  FLOWLOCK_UNLOCK(&f);
2303 
2304  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2305 
2306  /* do detect */
2307  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2308 
2310 
2311  SigGroupCleanup(de_ctx);
2312  SigCleanSignatures(de_ctx);
2313 
2314  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2315  DetectEngineCtxFree(de_ctx);
2316 
2317  AppLayerParserThreadCtxFree(alp_tctx);
2319  FLOW_DESTROY(&f);
2320  UTHFreePackets(&p, 1);
2321  PASS;
2322 }
2323 
2324 /** \test Modbus fragmentation - 1 ADU over 2 TCP packets. */
2325 static int ModbusParserTest09(void) {
2327  Flow f;
2328  TcpSession ssn;
2329 
2330  uint32_t input_len = sizeof(readCoilsReq), part2_len = 3;
2331  uint8_t *input = readCoilsReq;
2332 
2333  FAIL_IF_NULL(alp_tctx);
2334 
2335  memset(&f, 0, sizeof(f));
2336  memset(&ssn, 0, sizeof(ssn));
2337 
2338  FLOW_INITIALIZE(&f);
2339  f.protoctx = (void *)&ssn;
2340  f.proto = IPPROTO_TCP;
2341  f.alproto = ALPROTO_MODBUS;
2342 
2344 
2345  FLOWLOCK_WRLOCK(&f);
2346  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2347  STREAM_TOSERVER, input, input_len - part2_len);
2348  FAIL_IF_NOT(r == 0);
2349 
2350  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2351  STREAM_TOSERVER, input, input_len);
2352  FAIL_IF_NOT(r == 0);
2353  FLOWLOCK_UNLOCK(&f);
2354 
2355  ModbusState *modbus_state = f.alstate;
2356  FAIL_IF_NULL(modbus_state);
2357 
2358  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2359 
2360  FAIL_IF_NOT(tx->function == 1);
2361  FAIL_IF_NOT(tx->read.address == 0x7890);
2362  FAIL_IF_NOT(tx->read.quantity == 19);
2363 
2364  input_len = sizeof(readCoilsRsp);
2365  part2_len = 10;
2366  input = readCoilsRsp;
2367 
2368  FLOWLOCK_WRLOCK(&f);
2369  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2370  STREAM_TOCLIENT, input, input_len - part2_len);
2371  FAIL_IF_NOT(r == 0);
2372 
2373  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2374  STREAM_TOCLIENT, input, input_len);
2375  FAIL_IF_NOT(r == 0);
2376  FLOWLOCK_UNLOCK(&f);
2377 
2378  FAIL_IF_NOT(modbus_state->transaction_max ==1);
2379 
2380  AppLayerParserThreadCtxFree(alp_tctx);
2382  FLOW_DESTROY(&f);
2383  PASS;
2384 }
2385 
2386 /** \test Modbus fragmentation - 2 ADU in 1 TCP packet. */
2387 static int ModbusParserTest10(void) {
2388  uint32_t input_len = sizeof(readCoilsReq) + sizeof(writeMultipleRegistersReq);
2389  uint8_t *input, *ptr;
2390 
2392  Flow f;
2393  TcpSession ssn;
2394 
2395  FAIL_IF_NULL(alp_tctx);
2396 
2397  input = (uint8_t *) SCMalloc (input_len * sizeof(uint8_t));
2398  FAIL_IF_NULL(input);
2399 
2400  memcpy(input, readCoilsReq, sizeof(readCoilsReq));
2401  memcpy(input + sizeof(readCoilsReq), writeMultipleRegistersReq, sizeof(writeMultipleRegistersReq));
2402 
2403  memset(&f, 0, sizeof(f));
2404  memset(&ssn, 0, sizeof(ssn));
2405 
2406  FLOW_INITIALIZE(&f);
2407  f.protoctx = (void *)&ssn;
2408  f.proto = IPPROTO_TCP;
2409  f.alproto = ALPROTO_MODBUS;
2410 
2412 
2413  FLOWLOCK_WRLOCK(&f);
2414  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2415  STREAM_TOSERVER, input, input_len);
2416  FAIL_IF_NOT(r == 0);
2417  FLOWLOCK_UNLOCK(&f);
2418 
2419  ModbusState *modbus_state = f.alstate;
2420  FAIL_IF_NULL(modbus_state);
2421 
2422  FAIL_IF_NOT(modbus_state->transaction_max == 2);
2423 
2424  ModbusTransaction *tx = ModbusGetTx(modbus_state, 1);
2425 
2426  FAIL_IF_NOT(tx->function == 16);
2427  FAIL_IF_NOT(tx->write.address == 0x01);
2428  FAIL_IF_NOT(tx->write.quantity == 2);
2429  FAIL_IF_NOT(tx->write.count == 4);
2430  FAIL_IF_NOT(tx->data[0] == 0x000A);
2431  FAIL_IF_NOT(tx->data[1] == 0x0102);
2432 
2433  input_len = sizeof(readCoilsRsp) + sizeof(writeMultipleRegistersRsp);
2434 
2435  ptr = (uint8_t *) SCRealloc (input, input_len * sizeof(uint8_t));
2436  FAIL_IF_NULL(ptr);
2437  input = ptr;
2438 
2439  memcpy(input, readCoilsRsp, sizeof(readCoilsRsp));
2440  memcpy(input + sizeof(readCoilsRsp), writeMultipleRegistersRsp, sizeof(writeMultipleRegistersRsp));
2441 
2442  FLOWLOCK_WRLOCK(&f);
2443  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2444  STREAM_TOCLIENT, input, sizeof(input_len));
2445  FAIL_IF_NOT(r == 0);
2446  FLOWLOCK_UNLOCK(&f);
2447 
2448  SCFree(input);
2449  AppLayerParserThreadCtxFree(alp_tctx);
2451  FLOW_DESTROY(&f);
2452  PASS;
2453 }
2454 
2455 /** \test Send Modbus exceed Length request. */
2456 static int ModbusParserTest11(void) {
2458  DetectEngineThreadCtx *det_ctx = NULL;
2459  Flow f;
2460  Packet *p = NULL;
2461  Signature *s = NULL;
2462  TcpSession ssn;
2463  ThreadVars tv;
2464 
2465  FAIL_IF(alp_tctx == NULL);
2466 
2467  memset(&tv, 0, sizeof(ThreadVars));
2468  memset(&f, 0, sizeof(Flow));
2469  memset(&ssn, 0, sizeof(TcpSession));
2470 
2471  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2472 
2473  FLOW_INITIALIZE(&f);
2474  f.alproto = ALPROTO_MODBUS;
2475  f.protoctx = (void *)&ssn;
2476  f.proto = IPPROTO_TCP;
2477  f.alproto = ALPROTO_MODBUS;
2478  f.flags |= FLOW_IPV4;
2479 
2480  p->flow = &f;
2483 
2485 
2487  FAIL_IF_NULL(de_ctx);
2488 
2489  de_ctx->flags |= DE_QUIET;
2490  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2491  "(msg:\"Modbus invalid Length\"; "
2492  "app-layer-event: "
2493  "modbus.invalid_length; "
2494  "sid:1;)");
2495  FAIL_IF_NULL(s);
2496 
2497  SigGroupBuild(de_ctx);
2498  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2499 
2500  FLOWLOCK_WRLOCK(&f);
2501  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2503  exceededLengthWriteMultipleRegistersReq,
2504  sizeof(exceededLengthWriteMultipleRegistersReq) + 65523 * sizeof(uint8_t));
2505  FAIL_IF_NOT(r == 0);
2506  FLOWLOCK_UNLOCK(&f);
2507 
2508  ModbusState *modbus_state = f.alstate;
2509  FAIL_IF_NULL(modbus_state);
2510 
2511  /* do detect */
2512  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2513 
2515 
2516  SigGroupCleanup(de_ctx);
2517  SigCleanSignatures(de_ctx);
2518 
2519  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2520  DetectEngineCtxFree(de_ctx);
2521 
2522  AppLayerParserThreadCtxFree(alp_tctx);
2524  FLOW_DESTROY(&f);
2525  UTHFreePackets(&p, 1);
2526  PASS;
2527 }
2528 
2529 /** \test Send Modbus invalid PDU Length. */
2530 static int ModbusParserTest12(void) {
2532  DetectEngineThreadCtx *det_ctx = NULL;
2533  Flow f;
2534  Packet *p = NULL;
2535  Signature *s = NULL;
2536  TcpSession ssn;
2537  ThreadVars tv;
2538 
2539  FAIL_IF_NULL(alp_tctx);
2540 
2541  memset(&tv, 0, sizeof(ThreadVars));
2542  memset(&f, 0, sizeof(Flow));
2543  memset(&ssn, 0, sizeof(TcpSession));
2544 
2545  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2546 
2547  FLOW_INITIALIZE(&f);
2548  f.alproto = ALPROTO_MODBUS;
2549  f.protoctx = (void *)&ssn;
2550  f.proto = IPPROTO_TCP;
2551  f.alproto = ALPROTO_MODBUS;
2552  f.flags |= FLOW_IPV4;
2553 
2554  p->flow = &f;
2557 
2559 
2561  FAIL_IF_NULL(de_ctx);
2562 
2563  de_ctx->flags |= DE_QUIET;
2564  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2565  "(msg:\"Modbus invalid Length\"; "
2566  "app-layer-event: "
2567  "modbus.invalid_length; "
2568  "sid:1;)");
2569  FAIL_IF_NULL(s);
2570 
2571  SigGroupBuild(de_ctx);
2572  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2573 
2574  FLOWLOCK_WRLOCK(&f);
2575  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2577  invalidLengthPDUWriteMultipleRegistersReq,
2578  sizeof(invalidLengthPDUWriteMultipleRegistersReq));
2579  FAIL_IF_NOT(r == 0);
2580  FLOWLOCK_UNLOCK(&f);
2581 
2582  ModbusState *modbus_state = f.alstate;
2583  FAIL_IF_NULL(modbus_state);
2584 
2585  /* do detect */
2586  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2587 
2589 
2590  SigGroupCleanup(de_ctx);
2591  SigCleanSignatures(de_ctx);
2592 
2593  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2594  DetectEngineCtxFree(de_ctx);
2595 
2596  AppLayerParserThreadCtxFree(alp_tctx);
2598  FLOW_DESTROY(&f);
2599  UTHFreePackets(&p, 1);
2600  PASS;
2601 }
2602 
2603 /** \test Send Modbus Mask Write register request/response. */
2604 static int ModbusParserTest13(void) {
2606  Flow f;
2607  TcpSession ssn;
2608 
2609  FAIL_IF_NULL(alp_tctx);
2610 
2611  memset(&f, 0, sizeof(f));
2612  memset(&ssn, 0, sizeof(ssn));
2613 
2614  FLOW_INITIALIZE(&f);
2615  f.protoctx = (void *)&ssn;
2616  f.proto = IPPROTO_TCP;
2617  f.alproto = ALPROTO_MODBUS;
2618 
2620 
2621  FLOWLOCK_WRLOCK(&f);
2622  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2623  STREAM_TOSERVER, maskWriteRegisterReq,
2624  sizeof(maskWriteRegisterReq));
2625  FAIL_IF_NOT(r == 0);
2626  FLOWLOCK_UNLOCK(&f);
2627 
2628  ModbusState *modbus_state = f.alstate;
2629  FAIL_IF_NULL(modbus_state);
2630 
2631  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2632 
2633  FAIL_IF_NOT(tx->function == 22);
2634  FAIL_IF_NOT(tx->data[0] == 0x00F2);
2635  FAIL_IF_NOT(tx->data[1] == 0x0025);
2636 
2637  FLOWLOCK_WRLOCK(&f);
2638  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2639  STREAM_TOCLIENT, maskWriteRegisterRsp,
2640  sizeof(maskWriteRegisterRsp));
2641  FAIL_IF_NOT(r == 0);
2642  FLOWLOCK_UNLOCK(&f);
2643 
2644  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2645 
2646  AppLayerParserThreadCtxFree(alp_tctx);
2648  FLOW_DESTROY(&f);
2649  PASS;
2650 }
2651 
2652 /** \test Send Modbus Write single register request/response. */
2653 static int ModbusParserTest14(void) {
2655  Flow f;
2656  TcpSession ssn;
2657 
2658  FAIL_IF_NULL(alp_tctx);
2659 
2660  memset(&f, 0, sizeof(f));
2661  memset(&ssn, 0, sizeof(ssn));
2662 
2663  FLOW_INITIALIZE(&f);
2664  f.protoctx = (void *)&ssn;
2665  f.proto = IPPROTO_TCP;
2666  f.alproto = ALPROTO_MODBUS;
2667 
2669 
2670  FLOWLOCK_WRLOCK(&f);
2671  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2672  STREAM_TOSERVER, writeSingleRegisterReq,
2673  sizeof(writeSingleRegisterReq));
2674  FAIL_IF_NOT(r == 0);
2675  FLOWLOCK_UNLOCK(&f);
2676 
2677  ModbusState *modbus_state = f.alstate;
2678  FAIL_IF_NULL(modbus_state);
2679 
2680  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2681 
2682  FAIL_IF_NOT(tx->function == 6);
2683  FAIL_IF_NOT(tx->write.address == 0x0001);
2684  FAIL_IF_NOT(tx->data[0] == 0x0003);
2685 
2686  FLOWLOCK_WRLOCK(&f);
2687  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2688  STREAM_TOCLIENT, writeSingleRegisterRsp,
2689  sizeof(writeSingleRegisterRsp));
2690  FAIL_IF_NOT(r == 0);
2691  FLOWLOCK_UNLOCK(&f);
2692 
2693  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2694 
2695  AppLayerParserThreadCtxFree(alp_tctx);
2697  FLOW_DESTROY(&f);
2698  PASS;
2699 }
2700 
2701 /** \test Send invalid Modbus Mask Write register request. */
2702 static int ModbusParserTest15(void) {
2704  DetectEngineThreadCtx *det_ctx = NULL;
2705  Flow f;
2706  Packet *p = NULL;
2707  Signature *s = NULL;
2708  TcpSession ssn;
2709  ThreadVars tv;
2710 
2711  FAIL_IF_NULL(alp_tctx);
2712 
2713  memset(&tv, 0, sizeof(ThreadVars));
2714  memset(&f, 0, sizeof(f));
2715  memset(&ssn, 0, sizeof(ssn));
2716 
2717  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2718 
2719  FLOW_INITIALIZE(&f);
2720  f.alproto = ALPROTO_MODBUS;
2721  f.protoctx = (void *)&ssn;
2722  f.proto = IPPROTO_TCP;
2723  f.alproto = ALPROTO_MODBUS;
2724  f.flags |= FLOW_IPV4;
2725 
2726  p->flow = &f;
2729 
2731 
2733  FAIL_IF_NULL(de_ctx);
2734 
2735  de_ctx->flags |= DE_QUIET;
2736  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2737  "(msg:\"Modbus invalid Length\"; "
2738  "app-layer-event: "
2739  "modbus.invalid_length; "
2740  "sid:1;)");
2741  FAIL_IF_NULL(s);
2742 
2743  SigGroupBuild(de_ctx);
2744  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2745 
2746  FLOWLOCK_WRLOCK(&f);
2747  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2748  STREAM_TOSERVER, invalidMaskWriteRegisterReq,
2749  sizeof(invalidMaskWriteRegisterReq));
2750  FAIL_IF_NOT(r == 0);
2751  FLOWLOCK_UNLOCK(&f);
2752 
2753  ModbusState *modbus_state = f.alstate;
2754  FAIL_IF_NULL(modbus_state);
2755 
2756  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2757 
2758  FAIL_IF_NOT(tx->function == 22);
2759 
2760  /* do detect */
2761  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2762 
2764 
2765  FLOWLOCK_WRLOCK(&f);
2766  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2767  STREAM_TOCLIENT, maskWriteRegisterRsp,
2768  sizeof(maskWriteRegisterRsp));
2769  FAIL_IF_NOT(r == 0);
2770  FLOWLOCK_UNLOCK(&f);
2771 
2772  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2773 
2774  SigGroupCleanup(de_ctx);
2775  SigCleanSignatures(de_ctx);
2776 
2777  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2778  DetectEngineCtxFree(de_ctx);
2779 
2780  AppLayerParserThreadCtxFree(alp_tctx);
2782  FLOW_DESTROY(&f);
2783  UTHFreePackets(&p, 1);
2784  PASS;
2785 }
2786 
2787 /** \test Send invalid Modbus Mask Write register request. */
2788 static int ModbusParserTest16(void) {
2790  DetectEngineThreadCtx *det_ctx = NULL;
2791  Flow f;
2792  Packet *p = NULL;
2793  Signature *s = NULL;
2794  TcpSession ssn;
2795  ThreadVars tv;
2796 
2797  FAIL_IF_NULL(alp_tctx);
2798 
2799  memset(&tv, 0, sizeof(ThreadVars));
2800  memset(&f, 0, sizeof(f));
2801  memset(&ssn, 0, sizeof(ssn));
2802 
2803  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2804 
2805  FLOW_INITIALIZE(&f);
2806  f.alproto = ALPROTO_MODBUS;
2807  f.protoctx = (void *)&ssn;
2808  f.proto = IPPROTO_TCP;
2809  f.alproto = ALPROTO_MODBUS;
2810  f.flags |= FLOW_IPV4;
2811 
2812  p->flow = &f;
2815 
2817 
2819  FAIL_IF_NULL(de_ctx);
2820 
2821  de_ctx->flags |= DE_QUIET;
2822  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2823  "(msg:\"Modbus invalid Length\"; "
2824  "app-layer-event: "
2825  "modbus.invalid_length; "
2826  "sid:1;)");
2827  FAIL_IF_NULL(s);
2828 
2829  SigGroupBuild(de_ctx);
2830  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2831 
2832  FLOWLOCK_WRLOCK(&f);
2833  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2835  invalidWriteSingleRegisterReq,
2836  sizeof(invalidWriteSingleRegisterReq));
2837  FAIL_IF_NOT(r == 0);
2838  FLOWLOCK_UNLOCK(&f);
2839 
2840  ModbusState *modbus_state = f.alstate;
2841  FAIL_IF_NULL(modbus_state);
2842 
2843  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2844 
2845  FAIL_IF_NOT(tx->function == 6);
2846  FAIL_IF_NOT(tx->write.address == 0x0001);
2847 
2848  /* do detect */
2849  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2850 
2852 
2853  FLOWLOCK_WRLOCK(&f);
2854  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2855  STREAM_TOCLIENT, writeSingleRegisterRsp,
2856  sizeof(writeSingleRegisterRsp));
2857  FAIL_IF_NOT(r == 0);
2858  FLOWLOCK_UNLOCK(&f);
2859 
2860  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2861 
2862  SigGroupCleanup(de_ctx);
2863  SigCleanSignatures(de_ctx);
2864 
2865  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2866  DetectEngineCtxFree(de_ctx);
2867 
2868  AppLayerParserThreadCtxFree(alp_tctx);
2870  FLOW_DESTROY(&f);
2871  UTHFreePackets(&p, 1);
2872  PASS;}
2873 
2874 /** \test Checks if stream_depth is correct */
2875 static int ModbusParserTest17(void) {
2877  Flow f;
2878  TcpSession ssn;
2879 
2880  FAIL_IF_NULL(alp_tctx);
2881 
2882  memset(&f, 0, sizeof(f));
2883  memset(&ssn, 0, sizeof(ssn));
2884 
2885  FLOW_INITIALIZE(&f);
2886  f.protoctx = (void *)&ssn;
2887  f.proto = IPPROTO_TCP;
2888  f.alproto = ALPROTO_MODBUS;
2889 
2891 
2892  FLOWLOCK_WRLOCK(&f);
2893  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2894  readCoilsReq, sizeof(readCoilsReq));
2895  FAIL_IF(r != 0);
2896  FLOWLOCK_UNLOCK(&f);
2897 
2898  FAIL_IF(f.alstate == NULL);
2899 
2900  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2901 
2902  FLOWLOCK_WRLOCK(&f);
2903  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2904  readCoilsRsp, sizeof(readCoilsRsp));
2905  FAIL_IF(r != 0);
2906  FLOWLOCK_UNLOCK(&f);
2907 
2908  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2909 
2910  AppLayerParserThreadCtxFree(alp_tctx);
2912  FLOW_DESTROY(&f);
2913  PASS;
2914 }
2915 
2916 /*/ \test Checks if stream depth is correct over 2 TCP packets */
2917 static int ModbusParserTest18(void) {
2919  Flow f;
2920  TcpSession ssn;
2921 
2922  uint32_t input_len = sizeof(readCoilsReq), part2_len = 3;
2923  uint8_t *input = readCoilsReq;
2924 
2925  FAIL_IF_NULL(alp_tctx);
2926 
2927  memset(&f, 0, sizeof(f));
2928  memset(&ssn, 0, sizeof(ssn));
2929 
2930  FLOW_INITIALIZE(&f);
2931  f.protoctx = (void *)&ssn;
2932  f.proto = IPPROTO_TCP;
2933  f.alproto = ALPROTO_MODBUS;
2934 
2936 
2937  FLOWLOCK_WRLOCK(&f);
2938  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2939  input, input_len - part2_len);
2940  FAIL_IF(r != 0);
2941  FLOWLOCK_UNLOCK(&f);
2942 
2943  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2944 
2945  FLOWLOCK_WRLOCK(&f);
2946  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2947  input, input_len);
2948  FAIL_IF(r != 0);
2949  FLOWLOCK_UNLOCK(&f);
2950 
2951  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2952 
2953  FAIL_IF(f.alstate == NULL);
2954 
2955  input_len = sizeof(readCoilsRsp);
2956  part2_len = 10;
2957  input = readCoilsRsp;
2958 
2959  FLOWLOCK_WRLOCK(&f);
2960  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2961  input, input_len - part2_len);
2962  FAIL_IF(r != 0);
2963  FLOWLOCK_UNLOCK(&f);
2964 
2965  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2966 
2967  FLOWLOCK_WRLOCK(&f);
2968  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2969  input, input_len);
2970  FAIL_IF(r != 0);
2971  FLOWLOCK_UNLOCK(&f);
2972 
2973  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2974 
2975  AppLayerParserThreadCtxFree(alp_tctx);
2977  FLOW_DESTROY(&f);
2978  PASS;
2979 }
2980 
2981 /** \test Send Modbus invalid function. */
2982 static int ModbusParserTest19(void) {
2984  DetectEngineThreadCtx *det_ctx = NULL;
2985  Flow f;
2986  Packet *p = NULL;
2987  Signature *s = NULL;
2988  TcpSession ssn;
2989  ThreadVars tv;
2990 
2991  FAIL_IF_NULL(alp_tctx);
2992 
2993  memset(&tv, 0, sizeof(ThreadVars));
2994  memset(&f, 0, sizeof(Flow));
2995  memset(&ssn, 0, sizeof(TcpSession));
2996 
2997  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2998 
2999  FLOW_INITIALIZE(&f);
3000  f.alproto = ALPROTO_MODBUS;
3001  f.protoctx = (void *)&ssn;
3002  f.proto = IPPROTO_TCP;
3003  f.alproto = ALPROTO_MODBUS;
3004  f.flags |= FLOW_IPV4;
3005 
3006  p->flow = &f;
3009 
3011 
3013  FAIL_IF_NULL(de_ctx);
3014 
3015  de_ctx->flags |= DE_QUIET;
3016  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
3017  "(msg:\"Modbus invalid Function code\"; "
3018  "app-layer-event: "
3019  "modbus.invalid_function_code; "
3020  "sid:1;)");
3021  FAIL_IF_NULL(s);
3022 
3023  SigGroupBuild(de_ctx);
3024  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3025 
3026  FLOWLOCK_WRLOCK(&f);
3027  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
3029  invalidFunctionCode,
3030  sizeof(invalidFunctionCode));
3031  FAIL_IF_NOT(r == 0);
3032  FLOWLOCK_UNLOCK(&f);
3033 
3034  ModbusState *modbus_state = f.alstate;
3035  FAIL_IF_NULL(modbus_state);
3036 
3037  /* do detect */
3038  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3039 
3041 
3042  SigGroupCleanup(de_ctx);
3043  SigCleanSignatures(de_ctx);
3044 
3045  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
3046  DetectEngineCtxFree(de_ctx);
3047 
3048  AppLayerParserThreadCtxFree(alp_tctx);
3050  FLOW_DESTROY(&f);
3051  UTHFreePackets(&p, 1);
3052  PASS;
3053 }
3054 #endif /* UNITTESTS */
3055 
3057 #ifdef UNITTESTS
3058  UtRegisterTest("ModbusParserTest01 - Modbus Read Coils request",
3059  ModbusParserTest01);
3060  UtRegisterTest("ModbusParserTest02 - Modbus Write Multiple registers request",
3061  ModbusParserTest02);
3062  UtRegisterTest("ModbusParserTest03 - Modbus Read/Write Multiple registers request",
3063  ModbusParserTest03);
3064  UtRegisterTest("ModbusParserTest04 - Modbus Force Listen Only Mode request",
3065  ModbusParserTest04);
3066  UtRegisterTest("ModbusParserTest05 - Modbus invalid Protocol version",
3067  ModbusParserTest05);
3068  UtRegisterTest("ModbusParserTest06 - Modbus unsolicited response",
3069  ModbusParserTest06);
3070  UtRegisterTest("ModbusParserTest07 - Modbus invalid Length request",
3071  ModbusParserTest07);
3072  UtRegisterTest("ModbusParserTest08 - Modbus Exception code invalid",
3073  ModbusParserTest08);
3074  UtRegisterTest("ModbusParserTest09 - Modbus fragmentation - 1 ADU in 2 TCP packets",
3075  ModbusParserTest09);
3076  UtRegisterTest("ModbusParserTest10 - Modbus fragmentation - 2 ADU in 1 TCP packet",
3077  ModbusParserTest10);
3078  UtRegisterTest("ModbusParserTest11 - Modbus exceeded Length request",
3079  ModbusParserTest11);
3080  UtRegisterTest("ModbusParserTest12 - Modbus invalid PDU Length",
3081  ModbusParserTest12);
3082  UtRegisterTest("ModbusParserTest13 - Modbus Mask Write register request",
3083  ModbusParserTest13);
3084  UtRegisterTest("ModbusParserTest14 - Modbus Write single register request",
3085  ModbusParserTest14);
3086  UtRegisterTest("ModbusParserTest15 - Modbus invalid Mask Write register request",
3087  ModbusParserTest15);
3088  UtRegisterTest("ModbusParserTest16 - Modbus invalid Write single register request",
3089  ModbusParserTest16);
3090  UtRegisterTest("ModbusParserTest17 - Modbus stream depth",
3091  ModbusParserTest17);
3092  UtRegisterTest("ModbusParserTest18 - Modbus stream depth in 2 TCP packets",
3093  ModbusParserTest18);
3094  UtRegisterTest("ModbusParserTest19 - Modbus invalid Function code",
3095  ModbusParserTest19);
3096 #endif /* UNITTESTS */
3097 }
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
#define MODBUS_SUBFUNC_SERVER_BUSY_COUNT
void AppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
struct ModbusState_ * modbus
#define MODBUS_FUNC_ENCAPINTTRANS
enum AppLayerEventType_ AppLayerEventType
uint16_t flags
#define MODBUS_MIN_QUANTITY
#define SCLogDebug(...)
Definition: util-debug.h:335
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
struct Flow_ * flow
Definition: decode.h:446
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
struct ModbusTransaction_::@18::@20::@22 read
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
struct HtpBodyChunk_ * next
#define MODBUS_ERROR_CODE_ILLEGAL_FUNCTION
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
uint32_t event_type
uint8_t proto
Definition: flow.h:344
void ModbusParserRegisterTests(void)
#define FALSE
#define MODBUS_TYP_ACCESS_FUNCTION_MASK
LoggerId
#define MODBUS_SUBFUNC_DIAG_REGS
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:243
#define MODBUS_CAT_USER_DEFINED
uint64_t transaction_max
int logged
#define PASS
Pass the test.
#define unlikely(expr)
Definition: util-optimize.h:35
#define MODBUS_TYP_WRITE
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
void AppLayerParserRegisterDetectFlagsFuncs(uint8_t ipproto, AppProto alproto, uint64_t(*GetTxDetectFlags)(void *tx, uint8_t dir), void(*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t))
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
#define MODBUS_FUNC_WRITESINGLECOIL
#define MODBUS_MAX_COUNT
uint32_t unreplied_cnt
#define MODBUS_SUBFUNC_COM_ERR_COUNT
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:356
#define MODBUS_PROTOCOL_VER
uint64_t offset
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
#define MODBUS_FUNC_GETCOMEVTCOUNTER
#define MODBUS_FUNC_MASKWRITEREG
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:203
void SigCleanSignatures(DetectEngineCtx *de_ctx)
#define MODBUS_ERROR_CODE_MEMORY_PARITY_ERROR
AppLayerDecoderEvents * decoder_events
void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event)
Set an app layer decoder event.
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:668
#define MODBUS_FUNC_GETCOMEVTLOG
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:240
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *))
#define MODBUS_MEI_ENCAPINTTRANS_READ
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
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
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
char * val
Definition: conf.h:34
#define MODBUS_TYP_MULTIPLE
#define MODBUS_FUNC_READCOILS
Signature container.
Definition: detect.h:522
#define MODBUS_TYP_COILS
#define MODBUS_MIN_COUNT
#define TRUE
#define MODBUS_FUNC_READDISCINPUTS
void * protoctx
Definition: flow.h:400
#define MODBUS_SUBFUNC_SERVER_NO_RSP_COUNT
#define MODBUS_FUNC_WRITESINGLEREG
main detection engine ctx
Definition: detect.h:761
#define MODBUS_ERROR_CODE_ILLEGAL_DATA_VALUE
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
#define MODBUS_MAX_INVALID_UNIT_ID
#define MODBUS_TYP_BIT_ACCESS_MASK
void * alstate
Definition: flow.h:438
SCEnumCharMap modbus_decoder_event_table[]
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 and when...
#define DE_QUIET
Definition: detect.h:292
#define MODBUS_MIN_INVALID_UNIT_ID
#define SCCalloc(nm, a)
Definition: util-mem.h:253
Data structure to store app layer decoder events.
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
#define MODBUS_FUNC_WRITEFILERECORD
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
uint8_t flags
Definition: detect.h:762
#define MODBUS_FUNC_ERRORMASK
#define TAILQ_INIT(head)
Definition: queue.h:370
#define MODBUS_FUNC_WRITEMULTREGS
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)
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, int *event_id, AppLayerEventType *event_type))
uint8_t type
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_DESTROY(f)
Definition: flow-util.h:121
#define MODBUS_TYP_DISCRETES
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
#define MODBUS_TYP_SINGLE
#define MODBUS_FUNC_READFIFOQUEUE
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define MODBUS_CAT_PUBLIC_UNASSIGNED
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1670
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:412
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:364
#define MODBUS_MIN_ADU_LEN
uint8_t flowflags
Definition: decode.h:440
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.
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
#define BYTE_BIG_ENDIAN
Definition: util-byte.h:29
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
int SigGroupCleanup(DetectEngineCtx *de_ctx)
#define MODBUS_SUBFUNC_CLEAR_REGS
int RunmodeIsUnittests(void)
Definition: suricata.c:267
#define MODBUS_FUNC_READWRITEMULTREGS
#define SCReturnInt(x)
Definition: util-debug.h:341
void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfoById)(int event_id, const char **event_name, AppLayerEventType *event_type))
#define MODBUS_SUBFUNC_RESTART_COM
#define MODBUS_SUBFUNC_SERVER_CHAR_COUNT
#define MODBUS_MAX_QUANTITY_IN_WORD_ACCESS
#define MODBUS_TYP_HOLDING
#define SCRealloc(x, a)
Definition: util-mem.h:238
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:385
#define MODBUS_MEI_ENCAPINTTRANS_CAN
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
#define MODBUS_ERROR_CODE_ILLEGAL_DATA_ADDRESS
struct ModbusFunctionCodeRange_ ModbusFunctionCodeRange
Definition: conf.h:32
#define MODBUS_FUNC_READFILERECORD
DetectEngineState * de_state
#define SCMalloc(a)
Definition: util-mem.h:222
#define MODBUS_CAT_NONE
#define MODBUS_MAX_QUANTITY_IN_BIT_ACCESS
#define MODBUS_TYP_INPUT
#define MODBUS_FUNC_DIAGNOSTIC
#define MODBUS_TYP_WRITE_MULTIPLE
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
#define SCFree(a)
Definition: util-mem.h:322
PoolThreadReserved res
#define MODBUS_FUNC_MASK
uint8_t address
Definition: decode-ppp.h:312
uint16_t tx_id
#define MODBUS_MAX_ADU_LEN
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
#define MODBUS_TYP_WRITE_SINGLE
#define MODBUS_FUNC_WRITEMULTCOILS
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
#define MODBUS_FUNC_READEXCSTATUS
int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:164
void RegisterModbusParsers(void)
Function to register the Modbus protocol parsers and other functions.
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define STREAM_TOSERVER
Definition: stream.h:31
#define MODBUS_ERROR_CODE_SERVER_DEVICE_FAILURE
#define APP_LAYER_PARSER_EOF
#define MODBUS_SUBFUNC_BUS_MSG_COUNT
#define MODBUS_TYP_NONE
#define MODBUS_CONFIG_DEFAULT_REQUEST_FLOOD
#define MODBUS_SUBFUNC_QUERY_DATA
#define MODBUS_SUBFUNC_EXCEPT_ERR_COUNT
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
#define PKT_HAS_FLOW
Definition: decode.h:1094
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
struct ModbusTransaction_::@18::@20::@23 write
#define MODBUS_CONFIG_DEFAULT_STREAM_DEPTH
#define CEIL(quantity)
#define MODBUS_SUBFUNC_SERVER_NAK_COUNT
#define SCReturn
Definition: util-debug.h:339
#define MODBUS_CAT_PUBLIC_ASSIGNED
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
#define MODBUS_TYP_READ_WRITE_MULTIPLE
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
int ParseSizeStringU32(const char *size, uint32_t *res)
Definition: util-misc.c:186
#define MODBUS_FUNC_NONE
AppProto alproto
application level protocol
Definition: flow.h:409
#define MODBUS_CAT_RESERVED
#define MODBUS_SUBFUNC_CLEAR_COUNT
uint32_t flags
Definition: decode.h:444
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
#define MODBUS_SUBFUNC_SERVER_MSG_COUNT
#define MODBUS_SUBFUNC_CHANGE_DELIMITER
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
#define MODBUS_FUNC_REPORTSERVERID
#define MODBUS_FUNC_READINPUTREGS
uint16_t transactionId
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself...
Flow data structure.
Definition: flow.h:325
#define FLOW_IPV4
Definition: flow.h:94
#define MODBUS_FUNC_READHOLDREGS
uint32_t flags
Definition: flow.h:379
#define PKT_STREAM_EST
Definition: decode.h:1092
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
#define MODBUS_SUBFUNC_LISTEN_MODE
struct ModbusHeader_ __attribute__((__packed__))
DNP3 link header.
DetectEngineCtx * DetectEngineCtxInit(void)
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
#define MODBUS_TYP_READ
ModbusTransaction * curr