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 void ModbusSetEvent(ModbusState *modbus, uint8_t e)
190 {
191  if (modbus && modbus->curr) {
192  SCLogDebug("modbus->curr->decoder_events %p", modbus->curr->decoder_events);
194  SCLogDebug("modbus->curr->decoder_events %p", modbus->curr->decoder_events);
195  modbus->events++;
196  } else
197  SCLogDebug("couldn't set event %u", e);
198 }
199 
200 static AppLayerDecoderEvents *ModbusGetEvents(void *state, uint64_t id)
201 {
202  ModbusState *modbus = (ModbusState *) state;
203  ModbusTransaction *tx;
204 
205  if (modbus->curr && modbus->curr->tx_num == (id + 1))
206  return modbus->curr->decoder_events;
207 
208  TAILQ_FOREACH(tx, &modbus->tx_list, next) {
209  if (tx->tx_num == (id+1))
210  return tx->decoder_events;
211  }
212 
213  return NULL;
214 }
215 
216 static int ModbusGetAlstateProgress(void *modbus_tx, uint8_t direction)
217 {
218  ModbusTransaction *tx = (ModbusTransaction *) modbus_tx;
219  ModbusState *modbus = tx->modbus;
220 
221  if (tx->replied == 1)
222  return 1;
223 
224  /* Check flood limit */
225  if ((modbus->givenup == 1) &&
226  ((modbus->transaction_max - tx->tx_num) > request_flood))
227  return 1;
228 
229  return 0;
230 }
231 
232 /** \brief Get value for 'complete' status in Modbus
233  */
234 static int ModbusGetAlstateProgressCompletionStatus(uint8_t direction)
235 {
236  return 1;
237 }
238 
239 static void *ModbusGetTx(void *alstate, uint64_t tx_id)
240 {
241  ModbusState *modbus = (ModbusState *) alstate;
242  ModbusTransaction *tx = NULL;
243 
244  if (modbus->curr && modbus->curr->tx_num == tx_id + 1)
245  return modbus->curr;
246 
247  TAILQ_FOREACH(tx, &modbus->tx_list, next) {
248  SCLogDebug("tx->tx_num %"PRIu64", tx_id %"PRIu64, tx->tx_num, (tx_id+1));
249  if (tx->tx_num != (tx_id+1))
250  continue;
251 
252  SCLogDebug("returning tx %p", tx);
253  return tx;
254  }
255 
256  return NULL;
257 }
258 
259 static void ModbusSetTxLogged(void *alstate, void *vtx, LoggerId logged)
260 {
262  tx->logged = logged;
263 }
264 
265 static LoggerId ModbusGetTxLogged(void *alstate, void *vtx)
266 {
268  return tx->logged;
269 }
270 
271 static uint64_t ModbusGetTxCnt(void *alstate)
272 {
273  return ((uint64_t) ((ModbusState *) alstate)->transaction_max);
274 }
275 
276 /** \internal
277  * \brief Find the Modbus Transaction in the state based on Transaction ID.
278  *
279  * \param modbus Pointer to Modbus state structure
280  * \param transactionId Transaction ID of the transaction
281  *
282  * \retval tx or NULL if not found
283  */
284 static ModbusTransaction *ModbusTxFindByTransaction(const ModbusState *modbus,
285  const uint16_t transactionId)
286 {
287  ModbusTransaction *tx = NULL;
288 
289  if (modbus->curr == NULL)
290  return NULL;
291 
292  /* fast path */
293  if ((modbus->curr->transactionId == transactionId) &&
294  !(modbus->curr->replied)) {
295  return modbus->curr;
296  /* slow path, iterate list */
297  } else {
298  TAILQ_FOREACH(tx, &modbus->tx_list, next) {
299  if ((tx->transactionId == transactionId) &&
300  !(modbus->curr->replied))
301  return tx;
302  }
303  }
304  /* not found */
305  return NULL;
306 }
307 
308 /** \internal
309  * \brief Allocate a Modbus Transaction and
310  * add it into Transaction list of Modbus State
311  *
312  * \param modbus Pointer to Modbus state structure
313  *
314  * \retval Pointer to Transaction or NULL pointer
315  */
316 static ModbusTransaction *ModbusTxAlloc(ModbusState *modbus) {
317  ModbusTransaction *tx;
318 
319  tx = (ModbusTransaction *) SCCalloc(1, sizeof(ModbusTransaction));
320  if (unlikely(tx == NULL))
321  return NULL;
322 
323  modbus->transaction_max++;
324  modbus->unreplied_cnt++;
325 
326  /* Check flood limit */
327  if ((request_flood != 0) && (modbus->unreplied_cnt > request_flood)) {
328  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_FLOODED);
329  modbus->givenup = 1;
330  }
331 
332  modbus->curr = tx;
333 
334  SCLogDebug("modbus->transaction_max updated to %"PRIu64, modbus->transaction_max);
335 
336  TAILQ_INSERT_TAIL(&modbus->tx_list, tx, next);
337 
338  tx->modbus = modbus;
339  tx->tx_num = modbus->transaction_max;
340 
341  return tx;
342 }
343 
344 /** \internal
345  * \brief Free a Modbus Transaction
346  *
347  * \retval Pointer to Transaction or NULL pointer
348  */
349 static void ModbusTxFree(ModbusTransaction *tx) {
350  SCEnter();
351  if (tx->data != NULL)
352  SCFree(tx->data);
353 
355 
356  if (tx->de_state != NULL)
358 
359  SCFree(tx);
360  SCReturn;
361 }
362 
363 /**
364  * \brief Modbus transaction cleanup callback
365  */
366 static void ModbusStateTxFree(void *state, uint64_t tx_id)
367 {
368  SCEnter();
369  ModbusState *modbus = (ModbusState *) state;
370  ModbusTransaction *tx = NULL, *ttx;
371 
372  SCLogDebug("state %p, id %"PRIu64, modbus, tx_id);
373 
374  TAILQ_FOREACH_SAFE(tx, &modbus->tx_list, next, ttx) {
375  SCLogDebug("tx %p tx->tx_num %"PRIu64", tx_id %"PRIu64, tx, tx->tx_num, (tx_id+1));
376 
377  if (tx->tx_num != (tx_id+1))
378  continue;
379 
380  if (tx == modbus->curr)
381  modbus->curr = NULL;
382 
383  if (tx->decoder_events != NULL) {
384  if (tx->decoder_events->cnt <= modbus->events)
385  modbus->events -= tx->decoder_events->cnt;
386  else
387  modbus->events = 0;
388  }
389 
390  modbus->unreplied_cnt--;
391 
392  /* Check flood limit */
393  if ((modbus->givenup == 1) &&
394  (request_flood != 0) &&
395  (modbus->unreplied_cnt < request_flood) )
396  modbus->givenup = 0;
397 
398  TAILQ_REMOVE(&modbus->tx_list, tx, next);
399  ModbusTxFree(tx);
400  break;
401  }
402  SCReturn;
403 }
404 
405 /** \internal
406  * \brief Extract 8bits data from pointer the received input data
407  *
408  * \param res Pointer to the result
409  * \param input Pointer the received input data
410  * \param input_len Length of the received input data
411  * \param offset Offset of the received input data pointer
412  */
413 static int ModbusExtractUint8(ModbusState *modbus,
414  uint8_t *res,
415  uint8_t *input,
416  uint32_t input_len,
417  uint16_t *offset) {
418  SCEnter();
419  if (input_len < (uint32_t) (*offset + sizeof(uint8_t))) {
420  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_LENGTH);
421  SCReturnInt(-1);
422  }
423 
424  *res = *(input + *offset);
425  *offset += sizeof(uint8_t);
426  SCReturnInt(0);
427 }
428 
429 /** \internal
430  * \brief Extract 16bits data from pointer the received input data
431  *
432  * \param res Pointer to the result
433  * \param input Pointer the received input data
434  * \param input_len Length of the received input data
435  * \param offset Offset of the received input data pointer
436  */
437 static int ModbusExtractUint16(ModbusState *modbus,
438  uint16_t *res,
439  uint8_t *input,
440  uint32_t input_len,
441  uint16_t *offset) {
442  SCEnter();
443  if (input_len < (uint32_t) (*offset + sizeof(uint16_t))) {
444  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_LENGTH);
445  SCReturnInt(-1);
446  }
447 
448  ByteExtractUint16(res, BYTE_BIG_ENDIAN, sizeof(uint16_t), (const uint8_t *) (input + *offset));
449  *offset += sizeof(uint16_t);
450  SCReturnInt(0);
451 }
452 
453 /** \internal
454  * \brief Check length field in Modbus header according to code function
455  *
456  * \param modbus Pointer to Modbus state structure
457  * \param length Length field in Modbus Header
458  * \param len Length according to code functio
459  */
460 static int ModbusCheckHeaderLength(ModbusState *modbus,
461  uint16_t length,
462  uint16_t len) {
463  SCEnter();
464  if (length != len) {
465  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_LENGTH);
466  SCReturnInt(-1);
467  }
468  SCReturnInt(0);
469 }
470 
471 /** \internal
472  * \brief Check Modbus header
473  *
474  * \param tx Pointer to Modbus Transaction structure
475  * \param modbus Pointer to Modbus state structure
476  * \param header Pointer to Modbus header state in which the value to be stored
477  */
478 static void ModbusCheckHeader(ModbusState *modbus,
479  ModbusHeader *header)
480 {
481  SCEnter();
482  /* MODBUS protocol is identified by the value 0. */
483  if (header->protocolId != MODBUS_PROTOCOL_VER)
484  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_PROTOCOL_ID);
485 
486  /* Check Length field that is a byte count of the following fields */
487  if ((header->length < MODBUS_MIN_ADU_LEN) ||
488  (header->length > MODBUS_MAX_ADU_LEN) )
489  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_LENGTH);
490 
491  /* Check Unit Identifier field that is not in invalid range */
492  if ((header->unitId > MODBUS_MIN_INVALID_UNIT_ID) &&
493  (header->unitId < MODBUS_MAX_INVALID_UNIT_ID) )
494  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_UNIT_IDENTIFIER);
495 
496  SCReturn;
497 }
498 
499 /** \internal
500  * \brief Parse Exception Response and verify protocol compliance.
501  *
502  * \param tx Pointer to Modbus Transaction structure
503  * \param modbus Pointer to Modbus state structure
504  * \param input Pointer the received input data
505  * \param input_len Length of the received input data
506  * \param offset Offset of the received input data pointer
507  */
508 static void ModbusExceptionResponse(ModbusTransaction *tx,
509  ModbusState *modbus,
510  uint8_t *input,
511  uint32_t input_len,
512  uint16_t *offset)
513 {
514  SCEnter();
515  uint8_t exception = 0;
516 
517  /* Exception code (1 byte) */
518  if (ModbusExtractUint8(modbus, &exception, input, input_len, offset))
519  SCReturn;
520 
521  switch (exception) {
524  break;
526  if (tx->function == MODBUS_FUNC_DIAGNOSTIC) {
527  break;
528  }
529  /* Fallthrough */
531  if ( (tx->type & MODBUS_TYP_ACCESS_FUNCTION_MASK) ||
534  break;
535  }
536  /* Fallthrough */
538  if ( (tx->function == MODBUS_FUNC_READFILERECORD) ||
540  break;
541  }
542  /* Fallthrough */
543  default:
544  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_EXCEPTION_CODE);
545  break;
546  }
547 
548  SCReturn;
549 }
550 
551 /** \internal
552  * \brief Parse Read data Request, complete Transaction structure
553  * and verify protocol compliance.
554  *
555  * \param tx Pointer to Modbus Transaction structure
556  * \param modbus Pointer to Modbus state structure
557  * \param input Pointer the received input data
558  * \param input_len Length of the received input data
559  * \param offset Offset of the received input data pointer
560  */
561 static void ModbusParseReadRequest(ModbusTransaction *tx,
562  ModbusState *modbus,
563  uint8_t *input,
564  uint32_t input_len,
565  uint16_t *offset)
566 {
567  SCEnter();
568  uint16_t quantity;
569  uint8_t type = tx->type;
570 
571  /* Starting Address (2 bytes) */
572  if (ModbusExtractUint16(modbus, &(tx->read.address), input, input_len, offset))
573  goto end;
574 
575  /* Quantity (2 bytes) */
576  if (ModbusExtractUint16(modbus, &(tx->read.quantity), input, input_len, offset))
577  goto end;
578  quantity = tx->read.quantity;
579 
580  /* Check Quantity range */
581  if (type & MODBUS_TYP_BIT_ACCESS_MASK) {
582  if ((quantity == MODBUS_MIN_QUANTITY) ||
584  goto error;
585  } else {
586  if ((quantity == MODBUS_MIN_QUANTITY) ||
588  goto error;
589  }
590 
591  if (~type & MODBUS_TYP_WRITE)
592  /* Except from Read/Write Multiple Registers function (code 23) */
593  /* The length of all Read Data function requests is 6 bytes */
594  /* Modbus Application Protocol Specification V1.1b3 from 6.1 to 6.4 */
595  ModbusCheckHeaderLength(modbus, tx->length, 6);
596 
597  goto end;
598 
599 error:
600  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_VALUE);
601 end:
602  SCReturn;
603 }
604 
605 /** \internal
606  * \brief Parse Read data Response and verify protocol compliance
607  *
608  * \param tx Pointer to Modbus Transaction structure
609  * \param modbus Pointer to Modbus state structure
610  * \param input Pointer the received input data
611  * \param input_len Length of the received input data
612  * \param offset Offset of the received input data pointer
613  */
614 static void ModbusParseReadResponse(ModbusTransaction *tx,
615  ModbusState *modbus,
616  uint8_t *input,
617  uint32_t input_len,
618  uint16_t *offset)
619 {
620  SCEnter();
621  uint8_t count = 0;
622 
623  /* Count (1 bytes) */
624  if (ModbusExtractUint8(modbus, &count, input, input_len, offset))
625  goto end;
626 
627  /* Check Count range and value according to the request */
628  if ((tx->type) & MODBUS_TYP_BIT_ACCESS_MASK) {
629  if ( (count < MODBUS_MIN_COUNT) ||
630  (count > MODBUS_MAX_COUNT) ||
631  (count != CEIL(tx->read.quantity)))
632  goto error;
633  } else {
634  if ( (count == MODBUS_MIN_COUNT) ||
635  (count > MODBUS_MAX_COUNT) ||
636  (count != (2 * (tx->read.quantity))))
637  goto error;
638  }
639 
640  /* Except from Read/Write Multiple Registers function (code 23) */
641  /* The length of all Read Data function responses is (3 bytes + count) */
642  /* Modbus Application Protocol Specification V1.1b3 from 6.1 to 6.4 */
643  ModbusCheckHeaderLength(modbus, tx->length, 3 + count);
644  goto end;
645 
646 error:
647  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_VALUE_MISMATCH);
648 end:
649  SCReturn;
650 }
651 
652 /** \internal
653  * \brief Parse Write data Request, complete Transaction structure
654  * and verify protocol compliance.
655  *
656  * \param tx Pointer to Modbus Transaction structure
657  * \param modbus Pointer to Modbus state structure
658  * \param input Pointer the received input data
659  * \param input_len Length of the received input data
660  * \param offset Offset of the received input data pointer
661  *
662  * \retval On success returns 0 or on failure returns -1.
663  */
664 static int ModbusParseWriteRequest(ModbusTransaction *tx,
665  ModbusState *modbus,
666  uint8_t *input,
667  uint32_t input_len,
668  uint16_t *offset)
669 {
670  SCEnter();
671  uint16_t quantity = 1, word = 0;
672  uint8_t byte = 0, count = 1, type = tx->type;
673 
674  int i = 0;
675 
676  /* Starting/Output/Register Address (2 bytes) */
677  if (ModbusExtractUint16(modbus, &(tx->write.address), input, input_len, offset))
678  goto end;
679 
680  if (type & MODBUS_TYP_SINGLE) {
681  /* The length of Write Single Coil (code 5) and */
682  /* Write Single Register (code 6) requests is 6 bytes */
683  /* Modbus Application Protocol Specification V1.1b3 6.5 and 6.6 */
684  if (ModbusCheckHeaderLength(modbus, tx->length, 6))
685  goto end;
686  } else if (type & MODBUS_TYP_MULTIPLE) {
687  /* Quantity (2 bytes) */
688  if (ModbusExtractUint16(modbus, &quantity, input, input_len, offset))
689  goto end;
690  tx->write.quantity = quantity;
691 
692  /* Count (1 bytes) */
693  if (ModbusExtractUint8(modbus, &count, input, input_len, offset))
694  goto end;
695  tx->write.count = count;
696 
698  /* Check Quantity range and conversion in byte (count) */
699  if ((quantity == MODBUS_MIN_QUANTITY) ||
700  (quantity > MODBUS_MAX_QUANTITY_IN_BIT_ACCESS) ||
701  (quantity != CEIL(count)))
702  goto error;
703 
704  /* The length of Write Multiple Coils (code 15) request is (7 + count) */
705  /* Modbus Application Protocol Specification V1.1b3 6.11 */
706  if (ModbusCheckHeaderLength(modbus, tx->length, 7 + count))
707  goto end;
708  } else {
709  /* Check Quantity range and conversion in byte (count) */
710  if ((quantity == MODBUS_MIN_QUANTITY) ||
711  (quantity > MODBUS_MAX_QUANTITY_IN_WORD_ACCESS) ||
712  (count != (2 * quantity)))
713  goto error;
714 
715  if (type & MODBUS_TYP_READ) {
716  /* The length of Read/Write Multiple Registers function (code 23) */
717  /* request is (11 bytes + count) */
718  /* Modbus Application Protocol Specification V1.1b3 6.17 */
719  if (ModbusCheckHeaderLength(modbus, tx->length, 11 + count))
720  goto end;
721  } else {
722  /* The length of Write Multiple Coils (code 15) and */
723  /* Write Multiple Registers (code 16) functions requests is (7 bytes + count) */
724  /* Modbus Application Protocol Specification V1.1b3 from 6.11 and 6.12 */
725  if (ModbusCheckHeaderLength(modbus, tx->length, 7 + count))
726  goto end;
727  }
728  }
729  } else {
730  /* Mask Write Register function (And_Mask and Or_Mask) */
731  quantity = 2;
732 
733  /* The length of Mask Write Register (code 22) function request is 8 */
734  /* Modbus Application Protocol Specification V1.1b3 6.16 */
735  if (ModbusCheckHeaderLength(modbus, tx->length, 8))
736  goto end;
737  }
738 
739  if (type & MODBUS_TYP_COILS) {
740  /* Output value (data block) unit is count */
741  tx->data = (uint16_t *) SCCalloc(1, count * sizeof(uint16_t));
742  if (unlikely(tx->data == NULL))
743  SCReturnInt(-1);
744 
745  if (type & MODBUS_TYP_SINGLE) {
746  /* Outputs value (2 bytes) */
747  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
748  goto end;
749  tx->data[i] = word;
750 
751  if ((word != 0x00) && (word != 0xFF00))
752  goto error;
753  } else {
754  for (i = 0; i < count; i++) {
755  /* Outputs value (1 byte) */
756  if (ModbusExtractUint8(modbus, &byte, input, input_len, offset))
757  goto end;
758  tx->data[i] = (uint16_t) byte;
759  }
760  }
761  } else {
762  /* Registers value (data block) unit is quantity */
763  tx->data = (uint16_t *) SCCalloc(1, quantity * sizeof(uint16_t));
764  if (unlikely(tx->data == NULL))
765  SCReturnInt(-1);
766 
767  for (i = 0; i < quantity; i++) {
768  /* Outputs/Registers value (2 bytes) */
769  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
770  goto end;
771  tx->data[i] = word;
772  }
773  }
774  goto end;
775 
776 error:
777  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_VALUE);
778 end:
779  SCReturnInt(0);
780 }
781 
782 /** \internal
783  * \brief Parse Write data Response and verify protocol compliance
784  *
785  * \param tx Pointer to Modbus Transaction structure
786  * \param modbus Pointer to Modbus state structure
787  * \param input Pointer the received input data
788  * \param input_len Length of the received input data
789  * \param offset Offset of the received input data pointer
790  */
791 static void ModbusParseWriteResponse(ModbusTransaction *tx,
792  ModbusState *modbus,
793  uint8_t *input,
794  uint32_t input_len,
795  uint16_t *offset)
796 {
797  SCEnter();
798  uint16_t address = 0, quantity = 0, word = 0;
799  uint8_t type = tx->type;
800 
801  /* Starting Address (2 bytes) */
802  if (ModbusExtractUint16(modbus, &address, input, input_len, offset))
803  goto end;
804 
805  if (address != tx->write.address)
806  goto error;
807 
808  if (type & MODBUS_TYP_SINGLE) {
809  /* Check if Outputs/Registers value has been stored */
810  if (tx->data != NULL)
811  {
812  /* Outputs/Registers value (2 bytes) */
813  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
814  goto end;
815 
816  /* Check with Outputs/Registers from request */
817  if (word != tx->data[0])
818  goto error;
819  }
820  } else if (type & MODBUS_TYP_MULTIPLE) {
821  /* Quantity (2 bytes) */
822  if (ModbusExtractUint16(modbus, &quantity, input, input_len, offset))
823  goto end;
824 
825  /* Check Quantity range */
826  if (type & MODBUS_TYP_BIT_ACCESS_MASK) {
827  if ((quantity == MODBUS_MIN_QUANTITY) ||
829  goto error;
830  } else {
831  if ((quantity == MODBUS_MIN_QUANTITY) ||
833  goto error;
834  }
835 
836  /* Check Quantity value according to the request */
837  if (quantity != tx->write.quantity)
838  goto error;
839  } else {
840  /* Check if And_Mask and Or_Mask values have been stored */
841  if (tx->data != NULL)
842  {
843  /* And_Mask value (2 bytes) */
844  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
845  goto end;
846 
847  /* Check And_Mask value according to the request */
848  if (word != tx->data[0])
849  goto error;
850 
851  /* And_Or_Mask value (2 bytes) */
852  if (ModbusExtractUint16(modbus, &word, input, input_len, offset))
853  goto end;
854 
855  /* Check Or_Mask value according to the request */
856  if (word != tx->data[1])
857  goto error;
858  }
859 
860  /* The length of Mask Write Register (code 22) function response is 8 */
861  /* Modbus Application Protocol Specification V1.1b3 6.16 */
862  ModbusCheckHeaderLength(modbus, tx->length, 8);
863  goto end;
864  }
865 
866  /* Except from Mask Write Register (code 22) */
867  /* The length of all Write Data function responses is 6 */
868  /* Modbus Application Protocol Specification V1.1b3 6.5, 6.6, 6.11, 6.12 and 6.17 */
869  ModbusCheckHeaderLength(modbus, tx->length, 6);
870  goto end;
871 
872 error:
873  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_VALUE_MISMATCH);
874 end:
875  SCReturn;
876 }
877 
878 /** \internal
879  * \brief Parse Diagnostic Request, complete Transaction
880  * structure (Category) and verify protocol compliance.
881  *
882  * \param tx Pointer to Modbus Transaction structure
883  * \param modbus Pointer to Modbus state structure
884  * \param input Pointer the received input data
885  * \param input_len Length of the received input data
886  * \param offset Offset of the received input data pointer
887  *
888  * \retval Reserved category function returns 1 otherwise returns 0.
889  */
890 static int ModbusParseDiagnosticRequest(ModbusTransaction *tx,
891  ModbusState *modbus,
892  uint8_t *input,
893  uint32_t input_len,
894  uint16_t *offset)
895 {
896  SCEnter();
897  uint16_t data = 0;
898 
899  /* Sub-function (2 bytes) */
900  if (ModbusExtractUint16(modbus, &(tx->subFunction), input, input_len, offset))
901  goto end;
902 
903  /* Data (2 bytes) */
904  if (ModbusExtractUint16(modbus, &data, input, input_len, offset))
905  goto end;
906 
908  switch (tx->subFunction) {
910  if ((data != 0x00) && (data != 0xFF00))
911  goto error;
912  break;
913 
915  if ((data & 0xFF) != 0x00)
916  goto error;
917  break;
918 
920  /* No answer is expected then mark tx as completed. */
921  tx->replied = 1;
922  /* Fallthrough */
934  if (data != 0x00)
935  goto error;
936  break;
937 
938  default:
939  /* Set function code category */
941  SCReturnInt(1);
942  }
943 
944  /* The length of all Diagnostic Requests is 6 */
945  /* Modbus Application Protocol Specification V1.1b3 6.8 */
946  ModbusCheckHeaderLength(modbus, tx->length, 6);
947  }
948 
949  goto end;
950 
951 error:
952  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_VALUE);
953 end:
954  SCReturnInt(0);
955 }
956 
957 /* Modbus Function Code Categories structure. */
958 typedef struct ModbusFunctionCodeRange_ {
959  uint8_t function;
960  uint8_t category;
962 
963 /* Modbus Function Code Categories table. */
964 static ModbusFunctionCodeRange modbusFunctionCodeRanges[] = {
966  { 9, MODBUS_CAT_RESERVED },
968  { 41, MODBUS_CAT_RESERVED },
970  { 65, MODBUS_CAT_USER_DEFINED },
972  { 90, MODBUS_CAT_RESERVED },
974  { 100, MODBUS_CAT_USER_DEFINED },
976  { 125, MODBUS_CAT_RESERVED },
977  { 128, MODBUS_CAT_NONE }
978 };
979 
980 /** \internal
981  * \brief Parse the Modbus Protocol Data Unit (PDU) Request
982  *
983  * \param tx Pointer to Modbus Transaction structure
984  * \param ModbusPdu Pointer the Modbus PDU state in which the value to be stored
985  * \param input Pointer the received input data
986  * \param input_len Length of the received input data
987  */
988 static void ModbusParseRequestPDU(ModbusTransaction *tx,
989  ModbusState *modbus,
990  uint8_t *input,
991  uint32_t input_len)
992 {
993  SCEnter();
994  uint16_t offset = (uint16_t) sizeof(ModbusHeader);
995  uint8_t count = 0;
996 
997  int i = 0;
998 
999  /* Standard function codes used on MODBUS application layer protocol (1 byte) */
1000  if (ModbusExtractUint8(modbus, &(tx->function), input, input_len, &offset))
1001  goto end;
1002 
1003  /* Set default function code category */
1004  tx->category = MODBUS_CAT_NONE;
1005 
1006  /* Set default function primary table */
1007  tx->type = MODBUS_TYP_NONE;
1008 
1009  switch (tx->function) {
1010  case MODBUS_FUNC_NONE:
1011  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_FUNCTION_CODE);
1012  break;
1013 
1014  case MODBUS_FUNC_READCOILS:
1015  /* Set function type */
1017  break;
1018 
1020  /* Set function type */
1022  break;
1023 
1025  /* Set function type */
1027  break;
1028 
1030  /* Set function type */
1032  break;
1033 
1035  /* Set function type */
1037  break;
1038 
1040  /* Set function type */
1042  break;
1043 
1045  /* Set function type */
1047  break;
1048 
1050  /* Set function type */
1052  break;
1053 
1055  /* Set function type */
1057  break;
1058 
1060  /* Set function type */
1062  break;
1063 
1066  /* Count/length (1 bytes) */
1067  if (ModbusExtractUint8(modbus, &count, input, input_len, &offset))
1068  goto end;
1069 
1070  /* Modbus Application Protocol Specification V1.1b3 6.14 and 6.15 */
1071  ModbusCheckHeaderLength(modbus, tx->length, 2 + count);
1072  break;
1073 
1075  if(ModbusParseDiagnosticRequest(tx, modbus, input, input_len, &offset))
1076  goto end;
1077  break;
1078 
1083  /* Modbus Application Protocol Specification V1.1b3 6.7, 6.9, 6.10 and 6.13 */
1084  ModbusCheckHeaderLength(modbus, tx->length, 2);
1085  break;
1086 
1088  /* Modbus Application Protocol Specification V1.1b3 6.18 */
1089  ModbusCheckHeaderLength(modbus, tx->length, 4);
1090  break;
1091 
1093  /* MEI type (1 byte) */
1094  if (ModbusExtractUint8(modbus, &(tx->mei), input, input_len, &offset))
1095  goto end;
1096 
1097  if (tx->mei == MODBUS_MEI_ENCAPINTTRANS_READ) {
1098  /* Modbus Application Protocol Specification V1.1b3 6.21 */
1099  ModbusCheckHeaderLength(modbus, tx->length, 5);
1100  } else if (tx->mei != MODBUS_MEI_ENCAPINTTRANS_CAN) {
1101  /* Set function code category */
1103  goto end;
1104  }
1105  break;
1106 
1107  default:
1108  /* Check if request is error. */
1109  if (tx->function & MODBUS_FUNC_ERRORMASK) {
1110  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_INVALID_FUNCTION_CODE);
1111  goto end;
1112  }
1113 
1114  /* Get and store function code category */
1115  for (i = 0; modbusFunctionCodeRanges[i].category != MODBUS_CAT_NONE; i++) {
1116  if (tx->function <= modbusFunctionCodeRanges[i].function)
1117  break;
1118  tx->category = modbusFunctionCodeRanges[i].category;
1119  }
1120  goto end;
1121  }
1122 
1123  /* Set function code category */
1125 
1126  if (tx->type & MODBUS_TYP_READ)
1127  ModbusParseReadRequest(tx, modbus, input, input_len, &offset);
1128 
1129  if (tx->type & MODBUS_TYP_WRITE)
1130  ModbusParseWriteRequest(tx, modbus, input, input_len, &offset);
1131 
1132 end:
1133  SCReturn;
1134 }
1135 
1136 /** \internal
1137  * \brief Parse the Modbus Protocol Data Unit (PDU) Response
1138  *
1139  * \param tx Pointer to Modbus Transaction structure
1140  * \param modbus Pointer the Modbus PDU state in which the value to be stored
1141  * \param input Pointer the received input data
1142  * \param input_len Length of the received input data
1143  * \param offset Offset of the received input data pointer
1144  */
1145 static void ModbusParseResponsePDU(ModbusTransaction *tx,
1146  ModbusState *modbus,
1147  uint8_t *input,
1148  uint32_t input_len)
1149 {
1150  SCEnter();
1151  uint16_t offset = (uint16_t) sizeof(ModbusHeader);
1152  uint8_t count = 0, error = FALSE, function = 0, mei = 0;
1153 
1154  /* Standard function codes used on MODBUS application layer protocol (1 byte) */
1155  if (ModbusExtractUint8(modbus, &function, input, input_len, &offset))
1156  goto end;
1157 
1158  /* Check if response is error */
1159  if(function & MODBUS_FUNC_ERRORMASK) {
1160  function &= MODBUS_FUNC_MASK;
1161  error = TRUE;
1162  }
1163 
1164  if (tx->category == MODBUS_CAT_PUBLIC_ASSIGNED) {
1165  /* Check if response is error. */
1166  if (error) {
1167  ModbusExceptionResponse(tx, modbus, input, input_len, &offset);
1168  } else {
1169  switch(function) {
1171  /* Modbus Application Protocol Specification V1.1b3 6.7 */
1172  ModbusCheckHeaderLength(modbus, tx->length, 3);
1173  goto end;
1174 
1176  /* Modbus Application Protocol Specification V1.1b3 6.9 */
1177  ModbusCheckHeaderLength(modbus, tx->length, 6);
1178  goto end;
1179 
1182  /* Count/length (1 bytes) */
1183  if (ModbusExtractUint8(modbus, &count, input, input_len, &offset))
1184  goto end;
1185 
1186  /* Modbus Application Protocol Specification V1.1b3 6.14 and 6.15 */
1187  ModbusCheckHeaderLength(modbus, tx->length, 2 + count);
1188  goto end;
1189 
1191  /* MEI type (1 byte) */
1192  if (ModbusExtractUint8(modbus, &mei, input, input_len, &offset))
1193  goto end;
1194 
1195  if (mei != tx->mei)
1196  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_VALUE_MISMATCH);
1197  goto end;
1198  }
1199 
1200  if (tx->type & MODBUS_TYP_READ)
1201  ModbusParseReadResponse(tx, modbus, input, input_len, &offset);
1202  /* Read/Write response contents none write response part */
1203  else if (tx->type & MODBUS_TYP_WRITE)
1204  ModbusParseWriteResponse(tx, modbus, input, input_len, &offset);
1205  }
1206  }
1207 
1208 end:
1209  SCReturn;
1210 }
1211 
1212 /** \internal
1213  * \brief Parse the Modbus Application Protocol (MBAP) header
1214  *
1215  * \param header Pointer the Modbus header state in which the value to be stored
1216  * \param input Pointer the received input data
1217  */
1218 static int ModbusParseHeader(ModbusState *modbus,
1219  ModbusHeader *header,
1220  uint8_t *input,
1221  uint32_t input_len)
1222 {
1223  SCEnter();
1224  uint16_t offset = 0;
1225 
1226  int r = 0;
1227 
1228  /* can't pass the header fields directly due to alignment (Bug 2088) */
1229  uint16_t transaction_id = 0;
1230  uint16_t protocol_id = 0;
1231  uint16_t length = 0;
1232  uint8_t unit_id = 0;
1233 
1234  /* Transaction Identifier (2 bytes) */
1235  r = ModbusExtractUint16(modbus, &transaction_id, input, input_len, &offset);
1236  /* Protocol Identifier (2 bytes) */
1237  r |= ModbusExtractUint16(modbus, &protocol_id, input, input_len, &offset);
1238  /* Length (2 bytes) */
1239  r |= ModbusExtractUint16(modbus, &length, input, input_len, &offset);
1240  /* Unit Identifier (1 byte) */
1241  r |= ModbusExtractUint8(modbus, &unit_id, input, input_len, &offset);
1242 
1243  if (r != 0) {
1244  SCReturnInt(-1);
1245  }
1246  header->transactionId = transaction_id;
1247  header->protocolId = protocol_id;
1248  header->length = length;
1249  header->unitId = unit_id;
1250 
1251  SCReturnInt(0);
1252 }
1253 
1254 /** \internal
1255  *
1256  * \brief This function is called to retrieve a Modbus Request
1257  *
1258  * \param state Modbus state structure for the parser
1259  * \param input Input line of the command
1260  * \param input_len Length of the request
1261  *
1262  * \retval 1 when the command is parsed, 0 otherwise
1263  */
1264 static int ModbusParseRequest(Flow *f,
1265  void *state,
1266  AppLayerParserState *pstate,
1267  uint8_t *input,
1268  uint32_t input_len,
1269  void *local_data,
1270  const uint8_t flags)
1271 {
1272  SCEnter();
1273  ModbusState *modbus = (ModbusState *) state;
1274  ModbusTransaction *tx;
1275  ModbusHeader header;
1276 
1277  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
1278  SCReturnInt(1);
1279  } else if (input == NULL || input_len == 0) {
1280  SCReturnInt(-1);
1281  }
1282 
1283  while (input_len > 0) {
1284  uint32_t adu_len = input_len;
1285  uint8_t *adu = input;
1286 
1287  /* Extract MODBUS Header */
1288  if (ModbusParseHeader(modbus, &header, adu, adu_len))
1289  SCReturnInt(0);
1290 
1291  /* Update ADU length with length in Modbus header. */
1292  adu_len = (uint32_t) sizeof(ModbusHeader) + (uint32_t) header.length - 1;
1293  if (adu_len > input_len)
1294  SCReturnInt(0);
1295 
1296  /* Allocate a Transaction Context and add it to Transaction list */
1297  tx = ModbusTxAlloc(modbus);
1298  if (tx == NULL)
1299  SCReturnInt(0);
1300 
1301  /* Check MODBUS Header */
1302  ModbusCheckHeader(modbus, &header);
1303 
1304  /* Store Unit ID, Transaction ID & PDU length */
1305  tx->unit_id = header.unitId;
1306  tx->transactionId = header.transactionId;
1307  tx->length = header.length;
1308 
1309  /* Extract MODBUS PDU and fill Transaction Context */
1310  ModbusParseRequestPDU(tx, modbus, adu, adu_len);
1311 
1312  /* Update input line and remaining input length of the command */
1313  input += adu_len;
1314  input_len -= adu_len;
1315  }
1316 
1317  SCReturnInt(1);
1318 }
1319 
1320 /** \internal
1321  * \brief This function is called to retrieve a Modbus response
1322  *
1323  * \param state Pointer to Modbus state structure for the parser
1324  * \param input Input line of the command
1325  * \param input_len Length of the request
1326  *
1327  * \retval 1 when the command is parsed, 0 otherwise
1328  */
1329 static int ModbusParseResponse(Flow *f,
1330  void *state,
1331  AppLayerParserState *pstate,
1332  uint8_t *input,
1333  uint32_t input_len,
1334  void *local_data,
1335  const uint8_t flags)
1336 {
1337  SCEnter();
1338  ModbusHeader header;
1339  ModbusState *modbus = (ModbusState *) state;
1340  ModbusTransaction *tx;
1341 
1342  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
1343  SCReturnInt(1);
1344  } else if (input == NULL || input_len == 0) {
1345  SCReturnInt(-1);
1346  }
1347 
1348  while (input_len > 0) {
1349  uint32_t adu_len = input_len;
1350  uint8_t *adu = input;
1351 
1352  /* Extract MODBUS Header */
1353  if (ModbusParseHeader(modbus, &header, adu, adu_len))
1354  SCReturnInt(0);
1355 
1356  /* Update ADU length with length in Modbus header. */
1357  adu_len = (uint32_t) sizeof(ModbusHeader) + (uint32_t) header.length - 1;
1358  if (adu_len > input_len)
1359  SCReturnInt(0);
1360 
1361  /* Find the transaction context thanks to transaction ID (and function code) */
1362  tx = ModbusTxFindByTransaction(modbus, header.transactionId);
1363  if (tx == NULL) {
1364  /* Allocate a Transaction Context if not previous request */
1365  /* and add it to Transaction list */
1366  tx = ModbusTxAlloc(modbus);
1367  if (tx == NULL)
1368  SCReturnInt(0);
1369 
1370  SCLogDebug("MODBUS_DECODER_EVENT_UNSOLICITED_RESPONSE");
1371  ModbusSetEvent(modbus, MODBUS_DECODER_EVENT_UNSOLICITED_RESPONSE);
1372  } else {
1373  /* Store PDU length */
1374  tx->length = header.length;
1375 
1376  /* Extract MODBUS PDU and fill Transaction Context */
1377  ModbusParseResponsePDU(tx, modbus, adu, adu_len);
1378  }
1379 
1380  /* Check and store MODBUS Header */
1381  ModbusCheckHeader(modbus, &header);
1382 
1383  /* Mark as completed */
1384  tx->replied = 1;
1385 
1386  /* Update input line and remaining input length of the command */
1387  input += adu_len;
1388  input_len -= adu_len;
1389  }
1390 
1391  SCReturnInt(1);
1392 }
1393 
1394 /** \internal
1395  * \brief Function to allocate the Modbus state memory
1396  */
1397 static void *ModbusStateAlloc(void)
1398 {
1399  ModbusState *modbus;
1400 
1401  modbus = (ModbusState *) SCCalloc(1, sizeof(ModbusState));
1402  if (unlikely(modbus == NULL))
1403  return NULL;
1404 
1405  TAILQ_INIT(&modbus->tx_list);
1406 
1407  return (void *) modbus;
1408 }
1409 
1410 /** \internal
1411  * \brief Function to free the Modbus state memory
1412  */
1413 static void ModbusStateFree(void *state)
1414 {
1415  SCEnter();
1416  ModbusState *modbus = (ModbusState *) state;
1417  ModbusTransaction *tx = NULL, *ttx;
1418 
1419  if (state) {
1420  TAILQ_FOREACH_SAFE(tx, &modbus->tx_list, next, ttx) {
1421  ModbusTxFree(tx);
1422  }
1423 
1424  SCFree(state);
1425  }
1426  SCReturn;
1427 }
1428 
1429 static uint16_t ModbusProbingParser(Flow *f,
1430  uint8_t *input,
1431  uint32_t input_len)
1432 {
1433  ModbusHeader *header = (ModbusHeader *) input;
1434 
1435  /* Modbus header is 7 bytes long */
1436  if (input_len < sizeof(ModbusHeader))
1437  return ALPROTO_UNKNOWN;
1438 
1439  /* MODBUS protocol is identified by the value 0. */
1440  if (header->protocolId != 0)
1441  return ALPROTO_FAILED;
1442 
1443  return ALPROTO_MODBUS;
1444 }
1445 
1446 static DetectEngineState *ModbusGetTxDetectState(void *vtx)
1447 {
1448  ModbusTransaction *tx = (ModbusTransaction *)vtx;
1449  return tx->de_state;
1450 }
1451 
1452 static int ModbusSetTxDetectState(void *vtx, DetectEngineState *s)
1453 {
1454  ModbusTransaction *tx = (ModbusTransaction *)vtx;
1455  tx->de_state = s;
1456  return 0;
1457 }
1458 
1459 /**
1460  * \brief Function to register the Modbus protocol parsers and other functions
1461  */
1463 {
1464  SCEnter();
1465  const char *proto_name = "modbus";
1466 
1467  /* Modbus application protocol V1.1b3 */
1468  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
1470 
1471  if (RunmodeIsUnittests()) {
1472  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
1473  "502",
1475  0, sizeof(ModbusHeader),
1477  ModbusProbingParser, NULL);
1478  } else {
1479  /* If there is no app-layer section for Modbus, silently
1480  * leave it disabled. */
1481  if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
1482  proto_name, ALPROTO_MODBUS,
1483  0, sizeof(ModbusHeader),
1484  ModbusProbingParser, NULL)) {
1485 #ifndef AFLFUZZ_APPLAYER
1486  return;
1487 #endif
1488  }
1489  }
1490 
1491  ConfNode *p = NULL;
1492  p = ConfGetNode("app-layer.protocols.modbus.request-flood");
1493  if (p != NULL) {
1494  uint32_t value;
1495  if (ParseSizeStringU32(p->val, &value) < 0) {
1496  SCLogError(SC_ERR_MODBUS_CONFIG, "invalid value for request-flood %s", p->val);
1497  } else {
1498  request_flood = value;
1499  }
1500  }
1501  SCLogConfig("Modbus request flood protection level: %u", request_flood);
1502 
1503  p = ConfGetNode("app-layer.protocols.modbus.stream-depth");
1504  if (p != NULL) {
1505  uint32_t value;
1506  if (ParseSizeStringU32(p->val, &value) < 0) {
1507  SCLogError(SC_ERR_MODBUS_CONFIG, "invalid value for stream-depth %s", p->val);
1508  } else {
1509  stream_depth = value;
1510  }
1511  }
1512  SCLogConfig("Modbus stream depth: %u", stream_depth);
1513  } else {
1514 #ifndef AFLFUZZ_APPLAYER
1515  SCLogConfig("Protocol detection and parser disabled for %s protocol.", proto_name);
1516  return;
1517 #endif
1518  }
1519  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1520  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOSERVER, ModbusParseRequest);
1521  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOCLIENT, ModbusParseResponse);
1522  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateAlloc, ModbusStateFree);
1523 
1524  AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetEvents);
1526  ModbusGetTxDetectState, ModbusSetTxDetectState);
1527 
1528  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTx);
1529  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTxCnt);
1530  AppLayerParserRegisterLoggerFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTxLogged,
1531  ModbusSetTxLogged);
1532  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateTxFree);
1533 
1534  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetAlstateProgress);
1536  ModbusGetAlstateProgressCompletionStatus);
1537 
1538  AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateGetEventInfo);
1539 
1541 
1542  AppLayerParserSetStreamDepth(IPPROTO_TCP, ALPROTO_MODBUS, stream_depth);
1543  } else {
1544  SCLogConfig("Parsed disabled for %s protocol. Protocol detection" "still on.", proto_name);
1545  }
1546 #ifdef UNITTESTS
1548 #endif
1549 
1550  SCReturn;
1551 }
1552 
1553 /* UNITTESTS */
1554 #ifdef UNITTESTS
1555 #include "detect.h"
1556 #include "detect-engine.h"
1557 #include "detect-parse.h"
1558 
1559 #include "flow-util.h"
1560 
1561 #include "util-unittest.h"
1562 #include "util-unittest-helper.h"
1563 
1564 #include "stream-tcp.h"
1565 #include "stream-tcp-private.h"
1566 
1567 /* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
1568 static uint8_t invalidFunctionCode[] = {/* Transaction ID */ 0x00, 0x00,
1569  /* Protocol ID */ 0x00, 0x01,
1570  /* Length */ 0x00, 0x02,
1571  /* Unit ID */ 0x00,
1572  /* Function code */ 0x00};
1573 
1574 /* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
1575 /* Example of a request to read discrete outputs 20-38 */
1576 static uint8_t readCoilsReq[] = {/* Transaction ID */ 0x00, 0x00,
1577  /* Protocol ID */ 0x00, 0x00,
1578  /* Length */ 0x00, 0x06,
1579  /* Unit ID */ 0x00,
1580  /* Function code */ 0x01,
1581  /* Starting Address */ 0x78, 0x90,
1582  /* Quantity of coils */ 0x00, 0x13 };
1583 
1584 static uint8_t readCoilsRsp[] = {/* Transaction ID */ 0x00, 0x00,
1585  /* Protocol ID */ 0x00, 0x00,
1586  /* Length */ 0x00, 0x06,
1587  /* Unit ID */ 0x00,
1588  /* Function code */ 0x01,
1589  /* Byte count */ 0x03,
1590  /* Coil Status */ 0xCD, 0x6B, 0x05 };
1591 
1592 static uint8_t readCoilsErrorRsp[] = {/* Transaction ID */ 0x00, 0x00,
1593  /* Protocol ID */ 0x00, 0x00,
1594  /* Length */ 0x00, 0x03,
1595  /* Unit ID */ 0x00,
1596  /* Function code */ 0x81,
1597  /* Exception code */ 0x05};
1598 
1599 /* Modbus Application Protocol Specification V1.1b3 6.6: Write Single register */
1600 /* Example of a request to write register 2 to 00 03 hex */
1601 static uint8_t writeSingleRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1602  /* Protocol ID */ 0x00, 0x00,
1603  /* Length */ 0x00, 0x06,
1604  /* Unit ID */ 0x00,
1605  /* Function code */ 0x06,
1606  /* Register Address */ 0x00, 0x01,
1607  /* Register Value */ 0x00, 0x03};
1608 
1609 static uint8_t invalidWriteSingleRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1610  /* Protocol ID */ 0x00, 0x00,
1611  /* Length */ 0x00, 0x04,
1612  /* Unit ID */ 0x00,
1613  /* Function code */ 0x06,
1614  /* Register Address */ 0x00, 0x01};
1615 
1616 static uint8_t writeSingleRegisterRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1617  /* Protocol ID */ 0x00, 0x00,
1618  /* Length */ 0x00, 0x06,
1619  /* Unit ID */ 0x00,
1620  /* Function code */ 0x06,
1621  /* Register Address */ 0x00, 0x01,
1622  /* Register Value */ 0x00, 0x03};
1623 
1624 /* Modbus Application Protocol Specification V1.1b3 6.12: Write Multiple registers */
1625 /* Example of a request to write two registers starting at 2 to 00 0A and 01 02 hex */
1626 static uint8_t writeMultipleRegistersReq[] = {/* Transaction ID */ 0x00, 0x0A,
1627  /* Protocol ID */ 0x00, 0x00,
1628  /* Length */ 0x00, 0x0B,
1629  /* Unit ID */ 0x00,
1630  /* Function code */ 0x10,
1631  /* Starting Address */ 0x00, 0x01,
1632  /* Quantity of Registers */ 0x00, 0x02,
1633  /* Byte count */ 0x04,
1634  /* Registers Value */ 0x00, 0x0A,
1635  0x01, 0x02};
1636 
1637 static uint8_t writeMultipleRegistersRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1638  /* Protocol ID */ 0x00, 0x00,
1639  /* Length */ 0x00, 0x06,
1640  /* Unit ID */ 0x00,
1641  /* Function code */ 0x10,
1642  /* Starting Address */ 0x00, 0x01,
1643  /* Quantity of Registers */ 0x00, 0x02};
1644 
1645 /* Modbus Application Protocol Specification V1.1b3 6.16: Mask Write Register */
1646 /* Example of a request to mask write to register 5 */
1647 static uint8_t maskWriteRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1648  /* Protocol ID */ 0x00, 0x00,
1649  /* Length */ 0x00, 0x08,
1650  /* Unit ID */ 0x00,
1651  /* Function code */ 0x16,
1652  /* Reference Address */ 0x00, 0x04,
1653  /* And_Mask */ 0x00, 0xF2,
1654  /* Or_Mask */ 0x00, 0x25};
1655 
1656 static uint8_t invalidMaskWriteRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1657  /* Protocol ID */ 0x00, 0x00,
1658  /* Length */ 0x00, 0x06,
1659  /* Unit ID */ 0x00,
1660  /* Function code */ 0x16,
1661  /* Reference Address */ 0x00, 0x04,
1662  /* And_Mask */ 0x00, 0xF2};
1663 
1664 static uint8_t maskWriteRegisterRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1665  /* Protocol ID */ 0x00, 0x00,
1666  /* Length */ 0x00, 0x08,
1667  /* Unit ID */ 0x00,
1668  /* Function code */ 0x16,
1669  /* Reference Address */ 0x00, 0x04,
1670  /* And_Mask */ 0x00, 0xF2,
1671  /* Or_Mask */ 0x00, 0x25};
1672 
1673 /* Modbus Application Protocol Specification V1.1b3 6.17: Read/Write Multiple registers */
1674 /* Example of a request to read six registers starting at register 4, */
1675 /* and to write three registers starting at register 15 */
1676 static uint8_t readWriteMultipleRegistersReq[] = {/* Transaction ID */ 0x12, 0x34,
1677  /* Protocol ID */ 0x00, 0x00,
1678  /* Length */ 0x00, 0x11,
1679  /* Unit ID */ 0x00,
1680  /* Function code */ 0x17,
1681  /* Read Starting Address */ 0x00, 0x03,
1682  /* Quantity to Read */ 0x00, 0x06,
1683  /* Write Starting Address */ 0x00, 0x0E,
1684  /* Quantity to Write */ 0x00, 0x03,
1685  /* Write Byte count */ 0x06,
1686  /* Write Registers Value */ 0x12, 0x34,
1687  0x56, 0x78,
1688  0x9A, 0xBC};
1689 
1690 /* Mismatch value in Byte count 0x0B instead of 0x0C */
1691 static uint8_t readWriteMultipleRegistersRsp[] = {/* Transaction ID */ 0x12, 0x34,
1692  /* Protocol ID */ 0x00, 0x00,
1693  /* Length */ 0x00, 0x0E,
1694  /* Unit ID */ 0x00,
1695  /* Function code */ 0x17,
1696  /* Byte count */ 0x0B,
1697  /* Read Registers Value */ 0x00, 0xFE,
1698  0x0A, 0xCD,
1699  0x00, 0x01,
1700  0x00, 0x03,
1701  0x00, 0x0D,
1702  0x00};
1703 
1704 /* Modbus Application Protocol Specification V1.1b3 6.8.1: 04 Force Listen Only Mode */
1705 /* Example of a request to to remote device to its Listen Only MOde for Modbus Communications. */
1706 static uint8_t forceListenOnlyMode[] = {/* Transaction ID */ 0x0A, 0x00,
1707  /* Protocol ID */ 0x00, 0x00,
1708  /* Length */ 0x00, 0x06,
1709  /* Unit ID */ 0x00,
1710  /* Function code */ 0x08,
1711  /* Sub-function code */ 0x00, 0x04,
1712  /* Data */ 0x00, 0x00};
1713 
1714 static uint8_t invalidProtocolIdReq[] = {/* Transaction ID */ 0x00, 0x00,
1715  /* Protocol ID */ 0x00, 0x01,
1716  /* Length */ 0x00, 0x06,
1717  /* Unit ID */ 0x00,
1718  /* Function code */ 0x01,
1719  /* Starting Address */ 0x78, 0x90,
1720  /* Quantity of coils */ 0x00, 0x13 };
1721 
1722 static uint8_t invalidLengthWriteMultipleRegistersReq[] = {
1723  /* Transaction ID */ 0x00, 0x0A,
1724  /* Protocol ID */ 0x00, 0x00,
1725  /* Length */ 0x00, 0x09,
1726  /* Unit ID */ 0x00,
1727  /* Function code */ 0x10,
1728  /* Starting Address */ 0x00, 0x01,
1729  /* Quantity of Registers */ 0x00, 0x02,
1730  /* Byte count */ 0x04,
1731  /* Registers Value */ 0x00, 0x0A,
1732  0x01, 0x02};
1733 
1734 static uint8_t exceededLengthWriteMultipleRegistersReq[] = {
1735  /* Transaction ID */ 0x00, 0x0A,
1736  /* Protocol ID */ 0x00, 0x00,
1737  /* Length */ 0xff, 0xfa,
1738  /* Unit ID */ 0x00,
1739  /* Function code */ 0x10,
1740  /* Starting Address */ 0x00, 0x01,
1741  /* Quantity of Registers */ 0x7f, 0xf9,
1742  /* Byte count */ 0xff};
1743 
1744 static uint8_t invalidLengthPDUWriteMultipleRegistersReq[] = {
1745  /* Transaction ID */ 0x00, 0x0A,
1746  /* Protocol ID */ 0x00, 0x00,
1747  /* Length */ 0x00, 0x02,
1748  /* Unit ID */ 0x00,
1749  /* Function code */ 0x10};
1750 
1751 /** \test Send Modbus Read Coils request/response. */
1752 static int ModbusParserTest01(void) {
1754  Flow f;
1755  TcpSession ssn;
1756 
1757  FAIL_IF_NULL(alp_tctx);
1758 
1759  memset(&f, 0, sizeof(f));
1760  memset(&ssn, 0, sizeof(ssn));
1761 
1762  FLOW_INITIALIZE(&f);
1763  f.protoctx = (void *)&ssn;
1764  f.proto = IPPROTO_TCP;
1765  f.alproto = ALPROTO_MODBUS;
1766 
1768 
1769  FLOWLOCK_WRLOCK(&f);
1770  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1771  STREAM_TOSERVER, readCoilsReq,
1772  sizeof(readCoilsReq));
1773  FAIL_IF_NOT(r == 0);
1774  FLOWLOCK_UNLOCK(&f);
1775 
1776  ModbusState *modbus_state = f.alstate;
1777  FAIL_IF_NULL(modbus_state);
1778 
1779  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1780  FAIL_IF_NOT(tx->function == 1);
1781  FAIL_IF_NOT(tx->read.address == 0x7890);
1782  FAIL_IF_NOT(tx->read.quantity == 19);
1783 
1784  FLOWLOCK_WRLOCK(&f);
1785  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1786  STREAM_TOCLIENT, readCoilsRsp,
1787  sizeof(readCoilsRsp));
1788  FAIL_IF_NOT(r == 0);
1789  FLOWLOCK_UNLOCK(&f);
1790 
1791  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1792 
1793  AppLayerParserThreadCtxFree(alp_tctx);
1795  FLOW_DESTROY(&f);
1796  PASS;
1797 }
1798 
1799 /** \test Send Modbus Write Multiple registers request/response. */
1800 static int ModbusParserTest02(void) {
1802  Flow f;
1803  TcpSession ssn;
1804 
1805  FAIL_IF_NULL(alp_tctx);
1806 
1807  memset(&f, 0, sizeof(f));
1808  memset(&ssn, 0, sizeof(ssn));
1809 
1810  FLOW_INITIALIZE(&f);
1811  f.protoctx = (void *)&ssn;
1812  f.proto = IPPROTO_TCP;
1813  f.alproto = ALPROTO_MODBUS;
1814 
1816 
1817  FLOWLOCK_WRLOCK(&f);
1818  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1819  STREAM_TOSERVER, writeMultipleRegistersReq,
1820  sizeof(writeMultipleRegistersReq));
1821  FAIL_IF_NOT(r == 0);
1822  FLOWLOCK_UNLOCK(&f);
1823 
1824  ModbusState *modbus_state = f.alstate;
1825  FAIL_IF_NULL(modbus_state);
1826 
1827  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1828 
1829  FAIL_IF_NOT(tx->function == 16);
1830  FAIL_IF_NOT(tx->write.address == 0x01);
1831  FAIL_IF_NOT(tx->write.quantity == 2);
1832  FAIL_IF_NOT(tx->write.count == 4);
1833  FAIL_IF_NOT(tx->data[0] == 0x000A);
1834  FAIL_IF_NOT(tx->data[1] == 0x0102);
1835 
1836  FLOWLOCK_WRLOCK(&f);
1837  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1838  STREAM_TOCLIENT, writeMultipleRegistersRsp,
1839  sizeof(writeMultipleRegistersRsp));
1840  FAIL_IF_NOT(r == 0);
1841  FLOWLOCK_UNLOCK(&f);
1842 
1843  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1844 
1845  AppLayerParserThreadCtxFree(alp_tctx);
1847  FLOW_DESTROY(&f);
1848  PASS;
1849 }
1850 
1851 /** \test Send Modbus Read/Write Multiple registers request/response with mismatch value. */
1852 static int ModbusParserTest03(void) {
1854  DetectEngineThreadCtx *det_ctx = NULL;
1855  Flow f;
1856  Packet *p = NULL;
1857  Signature *s = NULL;
1858  TcpSession ssn;
1859  ThreadVars tv;
1860 
1861  FAIL_IF_NULL(alp_tctx);
1862 
1863  memset(&tv, 0, sizeof(ThreadVars));
1864  memset(&f, 0, sizeof(Flow));
1865  memset(&ssn, 0, sizeof(TcpSession));
1866 
1867  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1868 
1869  FLOW_INITIALIZE(&f);
1870  f.alproto = ALPROTO_MODBUS;
1871  f.protoctx = (void *)&ssn;
1872  f.proto = IPPROTO_TCP;
1873  f.alproto = ALPROTO_MODBUS;
1874  f.flags |= FLOW_IPV4;
1875 
1876  p->flow = &f;
1879 
1881 
1883  FAIL_IF_NULL(de_ctx);
1884 
1885  de_ctx->flags |= DE_QUIET;
1886  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
1887  "(msg:\"Modbus Data mismatch\"; "
1888  "app-layer-event: "
1889  "modbus.value_mismatch; "
1890  "sid:1;)");
1891  FAIL_IF_NULL(s);
1892 
1893  SigGroupBuild(de_ctx);
1894  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1895 
1896  FLOWLOCK_WRLOCK(&f);
1897  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1899  readWriteMultipleRegistersReq,
1900  sizeof(readWriteMultipleRegistersReq));
1901  FAIL_IF_NOT(r == 0);
1902  FLOWLOCK_UNLOCK(&f);
1903 
1904  ModbusState *modbus_state = f.alstate;
1905  FAIL_IF_NULL(modbus_state);
1906 
1907  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1908 
1909  FAIL_IF_NOT(tx->function == 23);
1910  FAIL_IF_NOT(tx->read.address == 0x03);
1911  FAIL_IF_NOT(tx->read.quantity == 6);
1912  FAIL_IF_NOT(tx->write.address == 0x0E);
1913  FAIL_IF_NOT(tx->write.quantity == 3);
1914  FAIL_IF_NOT(tx->write.count == 6);
1915  FAIL_IF_NOT(tx->data[0] == 0x1234);
1916  FAIL_IF_NOT(tx->data[1] == 0x5678);
1917  FAIL_IF_NOT(tx->data[2] == 0x9ABC);
1918 
1919  FLOWLOCK_WRLOCK(&f);
1920  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1921  STREAM_TOCLIENT, readWriteMultipleRegistersRsp,
1922  sizeof(readWriteMultipleRegistersRsp));
1923  FAIL_IF_NOT(r == 0);
1924  FLOWLOCK_UNLOCK(&f);
1925 
1926  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1927 
1928  /* do detect */
1929  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1930 
1932 
1933  SigGroupCleanup(de_ctx);
1934  SigCleanSignatures(de_ctx);
1935 
1936  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1937  DetectEngineCtxFree(de_ctx);
1938 
1939  AppLayerParserThreadCtxFree(alp_tctx);
1941  FLOW_DESTROY(&f);
1942  UTHFreePackets(&p, 1);
1943  PASS;
1944 }
1945 
1946 /** \test Send Modbus Force Listen Only Mode request. */
1947 static int ModbusParserTest04(void) {
1949  Flow f;
1950  TcpSession ssn;
1951 
1952  FAIL_IF_NULL(alp_tctx);
1953 
1954  memset(&f, 0, sizeof(f));
1955  memset(&ssn, 0, sizeof(ssn));
1956 
1957  FLOW_INITIALIZE(&f);
1958  f.protoctx = (void *)&ssn;
1959  f.proto = IPPROTO_TCP;
1960  f.alproto = ALPROTO_MODBUS;
1961 
1963 
1964  FLOWLOCK_WRLOCK(&f);
1965  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1966  STREAM_TOSERVER, forceListenOnlyMode,
1967  sizeof(forceListenOnlyMode));
1968  FAIL_IF_NOT(r == 0);
1969  FLOWLOCK_UNLOCK(&f);
1970 
1971  ModbusState *modbus_state = f.alstate;
1972  FAIL_IF_NULL(modbus_state);
1973 
1974  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1975 
1976  FAIL_IF_NOT(tx->function == 8);
1977  FAIL_IF_NOT(tx->subFunction == 4);
1978 
1979  AppLayerParserThreadCtxFree(alp_tctx);
1981  FLOW_DESTROY(&f);
1982  PASS;
1983 }
1984 
1985 /** \test Send Modbus invalid Protocol version in request. */
1986 static int ModbusParserTest05(void) {
1988  DetectEngineThreadCtx *det_ctx = NULL;
1989  Flow f;
1990  Packet *p = NULL;
1991  Signature *s = NULL;
1992  TcpSession ssn;
1993  ThreadVars tv;
1994 
1995  FAIL_IF_NULL(alp_tctx);
1996 
1997  memset(&tv, 0, sizeof(ThreadVars));
1998  memset(&f, 0, sizeof(Flow));
1999  memset(&ssn, 0, sizeof(TcpSession));
2000 
2001  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2002 
2003  FLOW_INITIALIZE(&f);
2004  f.alproto = ALPROTO_MODBUS;
2005  f.protoctx = (void *)&ssn;
2006  f.proto = IPPROTO_TCP;
2007  f.alproto = ALPROTO_MODBUS;
2008  f.flags |= FLOW_IPV4;
2009 
2010  p->flow = &f;
2013 
2015 
2017  FAIL_IF_NULL(de_ctx);
2018 
2019  de_ctx->flags |= DE_QUIET;
2020  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2021  "(msg:\"Modbus invalid Protocol version\"; "
2022  "app-layer-event: "
2023  "modbus.invalid_protocol_id; "
2024  "sid:1;)");
2025  FAIL_IF_NULL(s);
2026 
2027  SigGroupBuild(de_ctx);
2028  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2029 
2030  FLOWLOCK_WRLOCK(&f);
2031  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2032  STREAM_TOSERVER, invalidProtocolIdReq,
2033  sizeof(invalidProtocolIdReq));
2034  FAIL_IF_NOT(r == 0);
2035  FLOWLOCK_UNLOCK(&f);
2036 
2037  ModbusState *modbus_state = f.alstate;
2038  FAIL_IF_NULL(modbus_state);
2039 
2040  /* do detect */
2041  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2042 
2044 
2045  SigGroupCleanup(de_ctx);
2046  SigCleanSignatures(de_ctx);
2047 
2048  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2049  DetectEngineCtxFree(de_ctx);
2050 
2051  AppLayerParserThreadCtxFree(alp_tctx);
2053  FLOW_DESTROY(&f);
2054  UTHFreePackets(&p, 1);
2055  PASS;
2056 }
2057 
2058 /** \test Send Modbus unsolicited response. */
2059 static int ModbusParserTest06(void) {
2061  DetectEngineThreadCtx *det_ctx = NULL;
2062  Flow f;
2063  Packet *p = NULL;
2064  Signature *s = NULL;
2065  TcpSession ssn;
2066  ThreadVars tv;
2067 
2068  FAIL_IF_NULL(alp_tctx);
2069 
2070  memset(&tv, 0, sizeof(ThreadVars));
2071  memset(&f, 0, sizeof(Flow));
2072  memset(&ssn, 0, sizeof(TcpSession));
2073 
2074  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2075 
2076  FLOW_INITIALIZE(&f);
2077  f.alproto = ALPROTO_MODBUS;
2078  f.protoctx = (void *)&ssn;
2079  f.proto = IPPROTO_TCP;
2080  f.alproto = ALPROTO_MODBUS;
2081  f.flags |= FLOW_IPV4;
2082 
2083  p->flow = &f;
2086 
2088 
2090  FAIL_IF_NULL(de_ctx);
2091 
2092  de_ctx->flags |= DE_QUIET;
2093  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2094  "(msg:\"Modbus unsolicited response\"; "
2095  "app-layer-event: "
2096  "modbus.unsolicited_response; "
2097  "sid:1;)");
2098  FAIL_IF_NULL(s);
2099 
2100  SigGroupBuild(de_ctx);
2101  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2102 
2103  FLOWLOCK_WRLOCK(&f);
2104  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2105  STREAM_TOCLIENT, readCoilsRsp,
2106  sizeof(readCoilsRsp));
2107  FAIL_IF_NOT(r == 0);
2108  FLOWLOCK_UNLOCK(&f);
2109 
2110  ModbusState *modbus_state = f.alstate;
2111  FAIL_IF_NULL(modbus_state);
2112 
2113  /* do detect */
2114  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2115 
2117 
2118  SigGroupCleanup(de_ctx);
2119  SigCleanSignatures(de_ctx);
2120 
2121  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2122  DetectEngineCtxFree(de_ctx);
2123 
2124  AppLayerParserThreadCtxFree(alp_tctx);
2126  FLOW_DESTROY(&f);
2127  UTHFreePackets(&p, 1);
2128  PASS;
2129 }
2130 
2131 /** \test Send Modbus invalid Length request. */
2132 static int ModbusParserTest07(void) {
2134  DetectEngineThreadCtx *det_ctx = NULL;
2135  Flow f;
2136  Packet *p = NULL;
2137  Signature *s = NULL;
2138  TcpSession ssn;
2139  ThreadVars tv;
2140 
2141  FAIL_IF_NULL(alp_tctx);
2142 
2143  memset(&tv, 0, sizeof(ThreadVars));
2144  memset(&f, 0, sizeof(Flow));
2145  memset(&ssn, 0, sizeof(TcpSession));
2146 
2147  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2148 
2149  FLOW_INITIALIZE(&f);
2150  f.alproto = ALPROTO_MODBUS;
2151  f.protoctx = (void *)&ssn;
2152  f.proto = IPPROTO_TCP;
2153  f.alproto = ALPROTO_MODBUS;
2154  f.flags |= FLOW_IPV4;
2155 
2156  p->flow = &f;
2159 
2161 
2163  FAIL_IF_NULL(de_ctx);
2164 
2165  de_ctx->flags |= DE_QUIET;
2166  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2167  "(msg:\"Modbus invalid Length\"; "
2168  "app-layer-event: "
2169  "modbus.invalid_length; "
2170  "sid:1;)");
2171  FAIL_IF_NULL(s);
2172 
2173  SigGroupBuild(de_ctx);
2174  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2175 
2176  FLOWLOCK_WRLOCK(&f);
2177  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2179  invalidLengthWriteMultipleRegistersReq,
2180  sizeof(invalidLengthWriteMultipleRegistersReq));
2181  FAIL_IF_NOT(r == 0);
2182  FLOWLOCK_UNLOCK(&f);
2183 
2184  ModbusState *modbus_state = f.alstate;
2185  FAIL_IF_NULL(modbus_state);
2186 
2187  /* do detect */
2188  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2189 
2191 
2192  SigGroupCleanup(de_ctx);
2193  SigCleanSignatures(de_ctx);
2194 
2195  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2196  DetectEngineCtxFree(de_ctx);
2197 
2198  AppLayerParserThreadCtxFree(alp_tctx);
2200  FLOW_DESTROY(&f);
2201  UTHFreePackets(&p, 1);
2202  PASS;
2203 }
2204 
2205 /** \test Send Modbus Read Coils request and error response with Exception code invalid. */
2206 static int ModbusParserTest08(void) {
2208  DetectEngineThreadCtx *det_ctx = NULL;
2209  Flow f;
2210  Packet *p = NULL;
2211  Signature *s = NULL;
2212  TcpSession ssn;
2213  ThreadVars tv;
2214 
2215  FAIL_IF_NULL(alp_tctx);
2216 
2217  memset(&tv, 0, sizeof(ThreadVars));
2218  memset(&f, 0, sizeof(Flow));
2219  memset(&ssn, 0, sizeof(TcpSession));
2220 
2221  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2222 
2223  FLOW_INITIALIZE(&f);
2224  f.alproto = ALPROTO_MODBUS;
2225  f.protoctx = (void *)&ssn;
2226  f.proto = IPPROTO_TCP;
2227  f.alproto = ALPROTO_MODBUS;
2228  f.flags |= FLOW_IPV4;
2229 
2230  p->flow = &f;
2233 
2235 
2237  FAIL_IF_NULL(de_ctx);
2238 
2239  de_ctx->flags |= DE_QUIET;
2240  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2241  "(msg:\"Modbus Exception code invalid\"; "
2242  "app-layer-event: "
2243  "modbus.invalid_exception_code; "
2244  "sid:1;)");
2245  FAIL_IF_NULL(s);
2246 
2247  SigGroupBuild(de_ctx);
2248  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2249 
2250  FLOWLOCK_WRLOCK(&f);
2251  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2252  STREAM_TOSERVER, readCoilsReq,
2253  sizeof(readCoilsReq));
2254  FAIL_IF_NOT(r == 0);
2255  FLOWLOCK_UNLOCK(&f);
2256 
2257  ModbusState *modbus_state = f.alstate;
2258  FAIL_IF_NULL(modbus_state);
2259 
2260  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2261 
2262  FAIL_IF_NOT(tx->function == 1);
2263  FAIL_IF_NOT(tx->read.address == 0x7890);
2264  FAIL_IF_NOT(tx->read.quantity == 19);
2265 
2266  FLOWLOCK_WRLOCK(&f);
2267  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2268  STREAM_TOCLIENT, readCoilsErrorRsp,
2269  sizeof(readCoilsErrorRsp));
2270  FAIL_IF_NOT(r == 0);
2271  FLOWLOCK_UNLOCK(&f);
2272 
2273  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2274 
2275  /* do detect */
2276  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2277 
2279 
2280  SigGroupCleanup(de_ctx);
2281  SigCleanSignatures(de_ctx);
2282 
2283  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2284  DetectEngineCtxFree(de_ctx);
2285 
2286  AppLayerParserThreadCtxFree(alp_tctx);
2288  FLOW_DESTROY(&f);
2289  UTHFreePackets(&p, 1);
2290  PASS;
2291 }
2292 
2293 /** \test Modbus fragmentation - 1 ADU over 2 TCP packets. */
2294 static int ModbusParserTest09(void) {
2296  Flow f;
2297  TcpSession ssn;
2298 
2299  uint32_t input_len = sizeof(readCoilsReq), part2_len = 3;
2300  uint8_t *input = readCoilsReq;
2301 
2302  FAIL_IF_NULL(alp_tctx);
2303 
2304  memset(&f, 0, sizeof(f));
2305  memset(&ssn, 0, sizeof(ssn));
2306 
2307  FLOW_INITIALIZE(&f);
2308  f.protoctx = (void *)&ssn;
2309  f.proto = IPPROTO_TCP;
2310  f.alproto = ALPROTO_MODBUS;
2311 
2313 
2314  FLOWLOCK_WRLOCK(&f);
2315  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2316  STREAM_TOSERVER, input, input_len - part2_len);
2317  FAIL_IF_NOT(r == 0);
2318 
2319  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2320  STREAM_TOSERVER, input, input_len);
2321  FAIL_IF_NOT(r == 0);
2322  FLOWLOCK_UNLOCK(&f);
2323 
2324  ModbusState *modbus_state = f.alstate;
2325  FAIL_IF_NULL(modbus_state);
2326 
2327  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2328 
2329  FAIL_IF_NOT(tx->function == 1);
2330  FAIL_IF_NOT(tx->read.address == 0x7890);
2331  FAIL_IF_NOT(tx->read.quantity == 19);
2332 
2333  input_len = sizeof(readCoilsRsp);
2334  part2_len = 10;
2335  input = readCoilsRsp;
2336 
2337  FLOWLOCK_WRLOCK(&f);
2338  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2339  STREAM_TOCLIENT, input, input_len - part2_len);
2340  FAIL_IF_NOT(r == 0);
2341 
2342  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2343  STREAM_TOCLIENT, input, input_len);
2344  FAIL_IF_NOT(r == 0);
2345  FLOWLOCK_UNLOCK(&f);
2346 
2347  FAIL_IF_NOT(modbus_state->transaction_max ==1);
2348 
2349  AppLayerParserThreadCtxFree(alp_tctx);
2351  FLOW_DESTROY(&f);
2352  PASS;
2353 }
2354 
2355 /** \test Modbus fragmentation - 2 ADU in 1 TCP packet. */
2356 static int ModbusParserTest10(void) {
2357  uint32_t input_len = sizeof(readCoilsReq) + sizeof(writeMultipleRegistersReq);
2358  uint8_t *input, *ptr;
2359 
2361  Flow f;
2362  TcpSession ssn;
2363 
2364  FAIL_IF_NULL(alp_tctx);
2365 
2366  input = (uint8_t *) SCMalloc (input_len * sizeof(uint8_t));
2367  FAIL_IF_NULL(input);
2368 
2369  memcpy(input, readCoilsReq, sizeof(readCoilsReq));
2370  memcpy(input + sizeof(readCoilsReq), writeMultipleRegistersReq, sizeof(writeMultipleRegistersReq));
2371 
2372  memset(&f, 0, sizeof(f));
2373  memset(&ssn, 0, sizeof(ssn));
2374 
2375  FLOW_INITIALIZE(&f);
2376  f.protoctx = (void *)&ssn;
2377  f.proto = IPPROTO_TCP;
2378  f.alproto = ALPROTO_MODBUS;
2379 
2381 
2382  FLOWLOCK_WRLOCK(&f);
2383  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2384  STREAM_TOSERVER, input, input_len);
2385  FAIL_IF_NOT(r == 0);
2386  FLOWLOCK_UNLOCK(&f);
2387 
2388  ModbusState *modbus_state = f.alstate;
2389  FAIL_IF_NULL(modbus_state);
2390 
2391  FAIL_IF_NOT(modbus_state->transaction_max == 2);
2392 
2393  ModbusTransaction *tx = ModbusGetTx(modbus_state, 1);
2394 
2395  FAIL_IF_NOT(tx->function == 16);
2396  FAIL_IF_NOT(tx->write.address == 0x01);
2397  FAIL_IF_NOT(tx->write.quantity == 2);
2398  FAIL_IF_NOT(tx->write.count == 4);
2399  FAIL_IF_NOT(tx->data[0] == 0x000A);
2400  FAIL_IF_NOT(tx->data[1] == 0x0102);
2401 
2402  input_len = sizeof(readCoilsRsp) + sizeof(writeMultipleRegistersRsp);
2403 
2404  ptr = (uint8_t *) SCRealloc (input, input_len * sizeof(uint8_t));
2405  FAIL_IF_NULL(ptr);
2406  input = ptr;
2407 
2408  memcpy(input, readCoilsRsp, sizeof(readCoilsRsp));
2409  memcpy(input + sizeof(readCoilsRsp), writeMultipleRegistersRsp, sizeof(writeMultipleRegistersRsp));
2410 
2411  FLOWLOCK_WRLOCK(&f);
2412  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2413  STREAM_TOCLIENT, input, sizeof(input_len));
2414  FAIL_IF_NOT(r == 0);
2415  FLOWLOCK_UNLOCK(&f);
2416 
2417  SCFree(input);
2418  AppLayerParserThreadCtxFree(alp_tctx);
2420  FLOW_DESTROY(&f);
2421  PASS;
2422 }
2423 
2424 /** \test Send Modbus exceed Length request. */
2425 static int ModbusParserTest11(void) {
2427  DetectEngineThreadCtx *det_ctx = NULL;
2428  Flow f;
2429  Packet *p = NULL;
2430  Signature *s = NULL;
2431  TcpSession ssn;
2432  ThreadVars tv;
2433 
2434  FAIL_IF(alp_tctx == NULL);
2435 
2436  memset(&tv, 0, sizeof(ThreadVars));
2437  memset(&f, 0, sizeof(Flow));
2438  memset(&ssn, 0, sizeof(TcpSession));
2439 
2440  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2441 
2442  FLOW_INITIALIZE(&f);
2443  f.alproto = ALPROTO_MODBUS;
2444  f.protoctx = (void *)&ssn;
2445  f.proto = IPPROTO_TCP;
2446  f.alproto = ALPROTO_MODBUS;
2447  f.flags |= FLOW_IPV4;
2448 
2449  p->flow = &f;
2452 
2454 
2456  FAIL_IF_NULL(de_ctx);
2457 
2458  de_ctx->flags |= DE_QUIET;
2459  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2460  "(msg:\"Modbus invalid Length\"; "
2461  "app-layer-event: "
2462  "modbus.invalid_length; "
2463  "sid:1;)");
2464  FAIL_IF_NULL(s);
2465 
2466  SigGroupBuild(de_ctx);
2467  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2468 
2469  FLOWLOCK_WRLOCK(&f);
2470  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2472  exceededLengthWriteMultipleRegistersReq,
2473  sizeof(exceededLengthWriteMultipleRegistersReq) + 65523 * sizeof(uint8_t));
2474  FAIL_IF_NOT(r == 0);
2475  FLOWLOCK_UNLOCK(&f);
2476 
2477  ModbusState *modbus_state = f.alstate;
2478  FAIL_IF_NULL(modbus_state);
2479 
2480  /* do detect */
2481  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2482 
2484 
2485  SigGroupCleanup(de_ctx);
2486  SigCleanSignatures(de_ctx);
2487 
2488  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2489  DetectEngineCtxFree(de_ctx);
2490 
2491  AppLayerParserThreadCtxFree(alp_tctx);
2493  FLOW_DESTROY(&f);
2494  UTHFreePackets(&p, 1);
2495  PASS;
2496 }
2497 
2498 /** \test Send Modbus invalid PDU Length. */
2499 static int ModbusParserTest12(void) {
2501  DetectEngineThreadCtx *det_ctx = NULL;
2502  Flow f;
2503  Packet *p = NULL;
2504  Signature *s = NULL;
2505  TcpSession ssn;
2506  ThreadVars tv;
2507 
2508  FAIL_IF_NULL(alp_tctx);
2509 
2510  memset(&tv, 0, sizeof(ThreadVars));
2511  memset(&f, 0, sizeof(Flow));
2512  memset(&ssn, 0, sizeof(TcpSession));
2513 
2514  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2515 
2516  FLOW_INITIALIZE(&f);
2517  f.alproto = ALPROTO_MODBUS;
2518  f.protoctx = (void *)&ssn;
2519  f.proto = IPPROTO_TCP;
2520  f.alproto = ALPROTO_MODBUS;
2521  f.flags |= FLOW_IPV4;
2522 
2523  p->flow = &f;
2526 
2528 
2530  FAIL_IF_NULL(de_ctx);
2531 
2532  de_ctx->flags |= DE_QUIET;
2533  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2534  "(msg:\"Modbus invalid Length\"; "
2535  "app-layer-event: "
2536  "modbus.invalid_length; "
2537  "sid:1;)");
2538  FAIL_IF_NULL(s);
2539 
2540  SigGroupBuild(de_ctx);
2541  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2542 
2543  FLOWLOCK_WRLOCK(&f);
2544  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2546  invalidLengthPDUWriteMultipleRegistersReq,
2547  sizeof(invalidLengthPDUWriteMultipleRegistersReq));
2548  FAIL_IF_NOT(r == 0);
2549  FLOWLOCK_UNLOCK(&f);
2550 
2551  ModbusState *modbus_state = f.alstate;
2552  FAIL_IF_NULL(modbus_state);
2553 
2554  /* do detect */
2555  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2556 
2558 
2559  SigGroupCleanup(de_ctx);
2560  SigCleanSignatures(de_ctx);
2561 
2562  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2563  DetectEngineCtxFree(de_ctx);
2564 
2565  AppLayerParserThreadCtxFree(alp_tctx);
2567  FLOW_DESTROY(&f);
2568  UTHFreePackets(&p, 1);
2569  PASS;
2570 }
2571 
2572 /** \test Send Modbus Mask Write register request/response. */
2573 static int ModbusParserTest13(void) {
2575  Flow f;
2576  TcpSession ssn;
2577 
2578  FAIL_IF_NULL(alp_tctx);
2579 
2580  memset(&f, 0, sizeof(f));
2581  memset(&ssn, 0, sizeof(ssn));
2582 
2583  FLOW_INITIALIZE(&f);
2584  f.protoctx = (void *)&ssn;
2585  f.proto = IPPROTO_TCP;
2586  f.alproto = ALPROTO_MODBUS;
2587 
2589 
2590  FLOWLOCK_WRLOCK(&f);
2591  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2592  STREAM_TOSERVER, maskWriteRegisterReq,
2593  sizeof(maskWriteRegisterReq));
2594  FAIL_IF_NOT(r == 0);
2595  FLOWLOCK_UNLOCK(&f);
2596 
2597  ModbusState *modbus_state = f.alstate;
2598  FAIL_IF_NULL(modbus_state);
2599 
2600  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2601 
2602  FAIL_IF_NOT(tx->function == 22);
2603  FAIL_IF_NOT(tx->data[0] == 0x00F2);
2604  FAIL_IF_NOT(tx->data[1] == 0x0025);
2605 
2606  FLOWLOCK_WRLOCK(&f);
2607  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2608  STREAM_TOCLIENT, maskWriteRegisterRsp,
2609  sizeof(maskWriteRegisterRsp));
2610  FAIL_IF_NOT(r == 0);
2611  FLOWLOCK_UNLOCK(&f);
2612 
2613  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2614 
2615  AppLayerParserThreadCtxFree(alp_tctx);
2617  FLOW_DESTROY(&f);
2618  PASS;
2619 }
2620 
2621 /** \test Send Modbus Write single register request/response. */
2622 static int ModbusParserTest14(void) {
2624  Flow f;
2625  TcpSession ssn;
2626 
2627  FAIL_IF_NULL(alp_tctx);
2628 
2629  memset(&f, 0, sizeof(f));
2630  memset(&ssn, 0, sizeof(ssn));
2631 
2632  FLOW_INITIALIZE(&f);
2633  f.protoctx = (void *)&ssn;
2634  f.proto = IPPROTO_TCP;
2635  f.alproto = ALPROTO_MODBUS;
2636 
2638 
2639  FLOWLOCK_WRLOCK(&f);
2640  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2641  STREAM_TOSERVER, writeSingleRegisterReq,
2642  sizeof(writeSingleRegisterReq));
2643  FAIL_IF_NOT(r == 0);
2644  FLOWLOCK_UNLOCK(&f);
2645 
2646  ModbusState *modbus_state = f.alstate;
2647  FAIL_IF_NULL(modbus_state);
2648 
2649  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2650 
2651  FAIL_IF_NOT(tx->function == 6);
2652  FAIL_IF_NOT(tx->write.address == 0x0001);
2653  FAIL_IF_NOT(tx->data[0] == 0x0003);
2654 
2655  FLOWLOCK_WRLOCK(&f);
2656  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2657  STREAM_TOCLIENT, writeSingleRegisterRsp,
2658  sizeof(writeSingleRegisterRsp));
2659  FAIL_IF_NOT(r == 0);
2660  FLOWLOCK_UNLOCK(&f);
2661 
2662  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2663 
2664  AppLayerParserThreadCtxFree(alp_tctx);
2666  FLOW_DESTROY(&f);
2667  PASS;
2668 }
2669 
2670 /** \test Send invalid Modbus Mask Write register request. */
2671 static int ModbusParserTest15(void) {
2673  DetectEngineThreadCtx *det_ctx = NULL;
2674  Flow f;
2675  Packet *p = NULL;
2676  Signature *s = NULL;
2677  TcpSession ssn;
2678  ThreadVars tv;
2679 
2680  FAIL_IF_NULL(alp_tctx);
2681 
2682  memset(&tv, 0, sizeof(ThreadVars));
2683  memset(&f, 0, sizeof(f));
2684  memset(&ssn, 0, sizeof(ssn));
2685 
2686  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2687 
2688  FLOW_INITIALIZE(&f);
2689  f.alproto = ALPROTO_MODBUS;
2690  f.protoctx = (void *)&ssn;
2691  f.proto = IPPROTO_TCP;
2692  f.alproto = ALPROTO_MODBUS;
2693  f.flags |= FLOW_IPV4;
2694 
2695  p->flow = &f;
2698 
2700 
2702  FAIL_IF_NULL(de_ctx);
2703 
2704  de_ctx->flags |= DE_QUIET;
2705  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2706  "(msg:\"Modbus invalid Length\"; "
2707  "app-layer-event: "
2708  "modbus.invalid_length; "
2709  "sid:1;)");
2710  FAIL_IF_NULL(s);
2711 
2712  SigGroupBuild(de_ctx);
2713  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2714 
2715  FLOWLOCK_WRLOCK(&f);
2716  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2717  STREAM_TOSERVER, invalidMaskWriteRegisterReq,
2718  sizeof(invalidMaskWriteRegisterReq));
2719  FAIL_IF_NOT(r == 0);
2720  FLOWLOCK_UNLOCK(&f);
2721 
2722  ModbusState *modbus_state = f.alstate;
2723  FAIL_IF_NULL(modbus_state);
2724 
2725  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2726 
2727  FAIL_IF_NOT(tx->function == 22);
2728 
2729  /* do detect */
2730  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2731 
2733 
2734  FLOWLOCK_WRLOCK(&f);
2735  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2736  STREAM_TOCLIENT, maskWriteRegisterRsp,
2737  sizeof(maskWriteRegisterRsp));
2738  FAIL_IF_NOT(r == 0);
2739  FLOWLOCK_UNLOCK(&f);
2740 
2741  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2742 
2743  SigGroupCleanup(de_ctx);
2744  SigCleanSignatures(de_ctx);
2745 
2746  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2747  DetectEngineCtxFree(de_ctx);
2748 
2749  AppLayerParserThreadCtxFree(alp_tctx);
2751  FLOW_DESTROY(&f);
2752  UTHFreePackets(&p, 1);
2753  PASS;
2754 }
2755 
2756 /** \test Send invalid Modbus Mask Write register request. */
2757 static int ModbusParserTest16(void) {
2759  DetectEngineThreadCtx *det_ctx = NULL;
2760  Flow f;
2761  Packet *p = NULL;
2762  Signature *s = NULL;
2763  TcpSession ssn;
2764  ThreadVars tv;
2765 
2766  FAIL_IF_NULL(alp_tctx);
2767 
2768  memset(&tv, 0, sizeof(ThreadVars));
2769  memset(&f, 0, sizeof(f));
2770  memset(&ssn, 0, sizeof(ssn));
2771 
2772  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2773 
2774  FLOW_INITIALIZE(&f);
2775  f.alproto = ALPROTO_MODBUS;
2776  f.protoctx = (void *)&ssn;
2777  f.proto = IPPROTO_TCP;
2778  f.alproto = ALPROTO_MODBUS;
2779  f.flags |= FLOW_IPV4;
2780 
2781  p->flow = &f;
2784 
2786 
2788  FAIL_IF_NULL(de_ctx);
2789 
2790  de_ctx->flags |= DE_QUIET;
2791  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2792  "(msg:\"Modbus invalid Length\"; "
2793  "app-layer-event: "
2794  "modbus.invalid_length; "
2795  "sid:1;)");
2796  FAIL_IF_NULL(s);
2797 
2798  SigGroupBuild(de_ctx);
2799  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2800 
2801  FLOWLOCK_WRLOCK(&f);
2802  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2804  invalidWriteSingleRegisterReq,
2805  sizeof(invalidWriteSingleRegisterReq));
2806  FAIL_IF_NOT(r == 0);
2807  FLOWLOCK_UNLOCK(&f);
2808 
2809  ModbusState *modbus_state = f.alstate;
2810  FAIL_IF_NULL(modbus_state);
2811 
2812  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2813 
2814  FAIL_IF_NOT(tx->function == 6);
2815  FAIL_IF_NOT(tx->write.address == 0x0001);
2816 
2817  /* do detect */
2818  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2819 
2821 
2822  FLOWLOCK_WRLOCK(&f);
2823  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2824  STREAM_TOCLIENT, writeSingleRegisterRsp,
2825  sizeof(writeSingleRegisterRsp));
2826  FAIL_IF_NOT(r == 0);
2827  FLOWLOCK_UNLOCK(&f);
2828 
2829  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2830 
2831  SigGroupCleanup(de_ctx);
2832  SigCleanSignatures(de_ctx);
2833 
2834  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2835  DetectEngineCtxFree(de_ctx);
2836 
2837  AppLayerParserThreadCtxFree(alp_tctx);
2839  FLOW_DESTROY(&f);
2840  UTHFreePackets(&p, 1);
2841  PASS;}
2842 
2843 /** \test Checks if stream_depth is correct */
2844 static int ModbusParserTest17(void) {
2846  Flow f;
2847  TcpSession ssn;
2848 
2849  FAIL_IF_NULL(alp_tctx);
2850 
2851  memset(&f, 0, sizeof(f));
2852  memset(&ssn, 0, sizeof(ssn));
2853 
2854  FLOW_INITIALIZE(&f);
2855  f.protoctx = (void *)&ssn;
2856  f.proto = IPPROTO_TCP;
2857  f.alproto = ALPROTO_MODBUS;
2858 
2860 
2861  FLOWLOCK_WRLOCK(&f);
2862  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2863  readCoilsReq, sizeof(readCoilsReq));
2864  FAIL_IF(r != 0);
2865  FLOWLOCK_UNLOCK(&f);
2866 
2867  FAIL_IF(f.alstate == NULL);
2868 
2869  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2870 
2871  FLOWLOCK_WRLOCK(&f);
2872  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2873  readCoilsRsp, sizeof(readCoilsRsp));
2874  FAIL_IF(r != 0);
2875  FLOWLOCK_UNLOCK(&f);
2876 
2877  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2878 
2879  AppLayerParserThreadCtxFree(alp_tctx);
2881  FLOW_DESTROY(&f);
2882  PASS;
2883 }
2884 
2885 /*/ \test Checks if stream depth is correct over 2 TCP packets */
2886 static int ModbusParserTest18(void) {
2888  Flow f;
2889  TcpSession ssn;
2890 
2891  uint32_t input_len = sizeof(readCoilsReq), part2_len = 3;
2892  uint8_t *input = readCoilsReq;
2893 
2894  FAIL_IF_NULL(alp_tctx);
2895 
2896  memset(&f, 0, sizeof(f));
2897  memset(&ssn, 0, sizeof(ssn));
2898 
2899  FLOW_INITIALIZE(&f);
2900  f.protoctx = (void *)&ssn;
2901  f.proto = IPPROTO_TCP;
2902  f.alproto = ALPROTO_MODBUS;
2903 
2905 
2906  FLOWLOCK_WRLOCK(&f);
2907  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2908  input, input_len - part2_len);
2909  FAIL_IF(r != 0);
2910  FLOWLOCK_UNLOCK(&f);
2911 
2912  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2913 
2914  FLOWLOCK_WRLOCK(&f);
2915  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2916  input, input_len);
2917  FAIL_IF(r != 0);
2918  FLOWLOCK_UNLOCK(&f);
2919 
2920  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2921 
2922  FAIL_IF(f.alstate == NULL);
2923 
2924  input_len = sizeof(readCoilsRsp);
2925  part2_len = 10;
2926  input = readCoilsRsp;
2927 
2928  FLOWLOCK_WRLOCK(&f);
2929  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2930  input, input_len - part2_len);
2931  FAIL_IF(r != 0);
2932  FLOWLOCK_UNLOCK(&f);
2933 
2934  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2935 
2936  FLOWLOCK_WRLOCK(&f);
2937  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2938  input, input_len);
2939  FAIL_IF(r != 0);
2940  FLOWLOCK_UNLOCK(&f);
2941 
2942  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2943 
2944  AppLayerParserThreadCtxFree(alp_tctx);
2946  FLOW_DESTROY(&f);
2947  PASS;
2948 }
2949 
2950 /** \test Send Modbus invalid function. */
2951 static int ModbusParserTest19(void) {
2953  DetectEngineThreadCtx *det_ctx = NULL;
2954  Flow f;
2955  Packet *p = NULL;
2956  Signature *s = NULL;
2957  TcpSession ssn;
2958  ThreadVars tv;
2959 
2960  FAIL_IF_NULL(alp_tctx);
2961 
2962  memset(&tv, 0, sizeof(ThreadVars));
2963  memset(&f, 0, sizeof(Flow));
2964  memset(&ssn, 0, sizeof(TcpSession));
2965 
2966  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2967 
2968  FLOW_INITIALIZE(&f);
2969  f.alproto = ALPROTO_MODBUS;
2970  f.protoctx = (void *)&ssn;
2971  f.proto = IPPROTO_TCP;
2972  f.alproto = ALPROTO_MODBUS;
2973  f.flags |= FLOW_IPV4;
2974 
2975  p->flow = &f;
2978 
2980 
2982  FAIL_IF_NULL(de_ctx);
2983 
2984  de_ctx->flags |= DE_QUIET;
2985  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2986  "(msg:\"Modbus invalid Function code\"; "
2987  "app-layer-event: "
2988  "modbus.invalid_function_code; "
2989  "sid:1;)");
2990  FAIL_IF_NULL(s);
2991 
2992  SigGroupBuild(de_ctx);
2993  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2994 
2995  FLOWLOCK_WRLOCK(&f);
2996  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2998  invalidFunctionCode,
2999  sizeof(invalidFunctionCode));
3000  FAIL_IF_NOT(r == 0);
3001  FLOWLOCK_UNLOCK(&f);
3002 
3003  ModbusState *modbus_state = f.alstate;
3004  FAIL_IF_NULL(modbus_state);
3005 
3006  /* do detect */
3007  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3008 
3010 
3011  SigGroupCleanup(de_ctx);
3012  SigCleanSignatures(de_ctx);
3013 
3014  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
3015  DetectEngineCtxFree(de_ctx);
3016 
3017  AppLayerParserThreadCtxFree(alp_tctx);
3019  FLOW_DESTROY(&f);
3020  UTHFreePackets(&p, 1);
3021  PASS;
3022 }
3023 #endif /* UNITTESTS */
3024 
3026 #ifdef UNITTESTS
3027  UtRegisterTest("ModbusParserTest01 - Modbus Read Coils request",
3028  ModbusParserTest01);
3029  UtRegisterTest("ModbusParserTest02 - Modbus Write Multiple registers request",
3030  ModbusParserTest02);
3031  UtRegisterTest("ModbusParserTest03 - Modbus Read/Write Multiple registers request",
3032  ModbusParserTest03);
3033  UtRegisterTest("ModbusParserTest04 - Modbus Force Listen Only Mode request",
3034  ModbusParserTest04);
3035  UtRegisterTest("ModbusParserTest05 - Modbus invalid Protocol version",
3036  ModbusParserTest05);
3037  UtRegisterTest("ModbusParserTest06 - Modbus unsolicited response",
3038  ModbusParserTest06);
3039  UtRegisterTest("ModbusParserTest07 - Modbus invalid Length request",
3040  ModbusParserTest07);
3041  UtRegisterTest("ModbusParserTest08 - Modbus Exception code invalid",
3042  ModbusParserTest08);
3043  UtRegisterTest("ModbusParserTest09 - Modbus fragmentation - 1 ADU in 2 TCP packets",
3044  ModbusParserTest09);
3045  UtRegisterTest("ModbusParserTest10 - Modbus fragmentation - 2 ADU in 1 TCP packet",
3046  ModbusParserTest10);
3047  UtRegisterTest("ModbusParserTest11 - Modbus exceeded Length request",
3048  ModbusParserTest11);
3049  UtRegisterTest("ModbusParserTest12 - Modbus invalid PDU Length",
3050  ModbusParserTest12);
3051  UtRegisterTest("ModbusParserTest13 - Modbus Mask Write register request",
3052  ModbusParserTest13);
3053  UtRegisterTest("ModbusParserTest14 - Modbus Write single register request",
3054  ModbusParserTest14);
3055  UtRegisterTest("ModbusParserTest15 - Modbus invalid Mask Write register request",
3056  ModbusParserTest15);
3057  UtRegisterTest("ModbusParserTest16 - Modbus invalid Write single register request",
3058  ModbusParserTest16);
3059  UtRegisterTest("ModbusParserTest17 - Modbus stream depth",
3060  ModbusParserTest17);
3061  UtRegisterTest("ModbusParserTest18 - Modbus stream depth in 2 TCP packets",
3062  ModbusParserTest18);
3063  UtRegisterTest("ModbusParserTest19 - Modbus invalid Function code",
3064  ModbusParserTest19);
3065 #endif /* UNITTESTS */
3066 }
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
struct Flow_ * flow
Definition: decode.h:444
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:346
void ModbusParserRegisterTests(void)
#define FALSE
#define MODBUS_TYP_ACCESS_FUNCTION_MASK
LoggerId
#define MODBUS_SUBFUNC_DIAG_REGS
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:235
#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.
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:195
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:669
#define MODBUS_FUNC_GETCOMEVTLOG
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:232
#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:492
#define MODBUS_TYP_COILS
#define MODBUS_MIN_COUNT
#define TRUE
#define MODBUS_FUNC_READDISCINPUTS
void * protoctx
Definition: flow.h:398
#define MODBUS_SUBFUNC_SERVER_NO_RSP_COUNT
#define MODBUS_FUNC_WRITESINGLEREG
main detection engine ctx
Definition: detect.h:720
#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:436
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:298
#define MODBUS_MIN_INVALID_UNIT_ID
#define SCCalloc(nm, a)
Definition: util-mem.h:205
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))
uint16_t type
uint8_t flags
Definition: detect.h:721
#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))
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_DESTROY(f)
Definition: flow-util.h:115
#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:1752
#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:365
#define MODBUS_MIN_ADU_LEN
uint8_t flowflags
Definition: decode.h:438
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:193
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:261
#define MODBUS_FUNC_READWRITEMULTREGS
#define SCReturnInt(x)
Definition: util-debug.h:341
#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:190
#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:174
#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:236
PoolThreadReserved res
#define MODBUS_FUNC_MASK
uint8_t address
Definition: decode-ppp.h:311
uint16_t tx_id
#define MODBUS_MAX_ADU_LEN
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
#define MODBUS_TYP_WRITE_SINGLE
#define MODBUS_FUNC_WRITEMULTCOILS
#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:1101
#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:407
#define MODBUS_CAT_RESERVED
#define MODBUS_SUBFUNC_CLEAR_COUNT
uint32_t flags
Definition: decode.h:442
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:327
#define FLOW_IPV4
Definition: flow.h:93
#define MODBUS_FUNC_READHOLDREGS
uint32_t flags
Definition: flow.h:377
#define PKT_STREAM_EST
Definition: decode.h:1099
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
#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