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 direction,
1431  uint8_t *input,
1432  uint32_t input_len,
1433  uint8_t *rdir)
1434 {
1435  ModbusHeader *header = (ModbusHeader *) input;
1436 
1437  /* Modbus header is 7 bytes long */
1438  if (input_len < sizeof(ModbusHeader))
1439  return ALPROTO_UNKNOWN;
1440 
1441  /* MODBUS protocol is identified by the value 0. */
1442  if (header->protocolId != 0)
1443  return ALPROTO_FAILED;
1444 
1445  return ALPROTO_MODBUS;
1446 }
1447 
1448 static DetectEngineState *ModbusGetTxDetectState(void *vtx)
1449 {
1450  ModbusTransaction *tx = (ModbusTransaction *)vtx;
1451  return tx->de_state;
1452 }
1453 
1454 static int ModbusSetTxDetectState(void *vtx, DetectEngineState *s)
1455 {
1456  ModbusTransaction *tx = (ModbusTransaction *)vtx;
1457  tx->de_state = s;
1458  return 0;
1459 }
1460 
1461 /**
1462  * \brief Function to register the Modbus protocol parsers and other functions
1463  */
1465 {
1466  SCEnter();
1467  const char *proto_name = "modbus";
1468 
1469  /* Modbus application protocol V1.1b3 */
1470  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
1472 
1473  if (RunmodeIsUnittests()) {
1474  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
1475  "502",
1477  0, sizeof(ModbusHeader),
1479  ModbusProbingParser, NULL);
1480  } else {
1481  /* If there is no app-layer section for Modbus, silently
1482  * leave it disabled. */
1483  if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
1484  proto_name, ALPROTO_MODBUS,
1485  0, sizeof(ModbusHeader),
1486  ModbusProbingParser, NULL)) {
1487 #ifndef AFLFUZZ_APPLAYER
1488  return;
1489 #endif
1490  }
1491  }
1492 
1493  ConfNode *p = NULL;
1494  p = ConfGetNode("app-layer.protocols.modbus.request-flood");
1495  if (p != NULL) {
1496  uint32_t value;
1497  if (ParseSizeStringU32(p->val, &value) < 0) {
1498  SCLogError(SC_ERR_MODBUS_CONFIG, "invalid value for request-flood %s", p->val);
1499  } else {
1500  request_flood = value;
1501  }
1502  }
1503  SCLogConfig("Modbus request flood protection level: %u", request_flood);
1504 
1505  p = ConfGetNode("app-layer.protocols.modbus.stream-depth");
1506  if (p != NULL) {
1507  uint32_t value;
1508  if (ParseSizeStringU32(p->val, &value) < 0) {
1509  SCLogError(SC_ERR_MODBUS_CONFIG, "invalid value for stream-depth %s", p->val);
1510  } else {
1511  stream_depth = value;
1512  }
1513  }
1514  SCLogConfig("Modbus stream depth: %u", stream_depth);
1515  } else {
1516 #ifndef AFLFUZZ_APPLAYER
1517  SCLogConfig("Protocol detection and parser disabled for %s protocol.", proto_name);
1518  return;
1519 #endif
1520  }
1521  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1522  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOSERVER, ModbusParseRequest);
1523  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOCLIENT, ModbusParseResponse);
1524  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateAlloc, ModbusStateFree);
1525 
1526  AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetEvents);
1528  ModbusGetTxDetectState, ModbusSetTxDetectState);
1529 
1530  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTx);
1531  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTxCnt);
1532  AppLayerParserRegisterLoggerFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTxLogged,
1533  ModbusSetTxLogged);
1534  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateTxFree);
1535 
1536  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetAlstateProgress);
1538  ModbusGetAlstateProgressCompletionStatus);
1539 
1540  AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateGetEventInfo);
1541 
1543 
1544  AppLayerParserSetStreamDepth(IPPROTO_TCP, ALPROTO_MODBUS, stream_depth);
1545  } else {
1546  SCLogConfig("Parsed disabled for %s protocol. Protocol detection" "still on.", proto_name);
1547  }
1548 #ifdef UNITTESTS
1550 #endif
1551 
1552  SCReturn;
1553 }
1554 
1555 /* UNITTESTS */
1556 #ifdef UNITTESTS
1557 #include "detect.h"
1558 #include "detect-engine.h"
1559 #include "detect-parse.h"
1560 
1561 #include "flow-util.h"
1562 
1563 #include "util-unittest.h"
1564 #include "util-unittest-helper.h"
1565 
1566 #include "stream-tcp.h"
1567 #include "stream-tcp-private.h"
1568 
1569 /* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
1570 static uint8_t invalidFunctionCode[] = {/* Transaction ID */ 0x00, 0x00,
1571  /* Protocol ID */ 0x00, 0x01,
1572  /* Length */ 0x00, 0x02,
1573  /* Unit ID */ 0x00,
1574  /* Function code */ 0x00};
1575 
1576 /* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
1577 /* Example of a request to read discrete outputs 20-38 */
1578 static uint8_t readCoilsReq[] = {/* Transaction ID */ 0x00, 0x00,
1579  /* Protocol ID */ 0x00, 0x00,
1580  /* Length */ 0x00, 0x06,
1581  /* Unit ID */ 0x00,
1582  /* Function code */ 0x01,
1583  /* Starting Address */ 0x78, 0x90,
1584  /* Quantity of coils */ 0x00, 0x13 };
1585 
1586 static uint8_t readCoilsRsp[] = {/* Transaction ID */ 0x00, 0x00,
1587  /* Protocol ID */ 0x00, 0x00,
1588  /* Length */ 0x00, 0x06,
1589  /* Unit ID */ 0x00,
1590  /* Function code */ 0x01,
1591  /* Byte count */ 0x03,
1592  /* Coil Status */ 0xCD, 0x6B, 0x05 };
1593 
1594 static uint8_t readCoilsErrorRsp[] = {/* Transaction ID */ 0x00, 0x00,
1595  /* Protocol ID */ 0x00, 0x00,
1596  /* Length */ 0x00, 0x03,
1597  /* Unit ID */ 0x00,
1598  /* Function code */ 0x81,
1599  /* Exception code */ 0x05};
1600 
1601 /* Modbus Application Protocol Specification V1.1b3 6.6: Write Single register */
1602 /* Example of a request to write register 2 to 00 03 hex */
1603 static uint8_t writeSingleRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1604  /* Protocol ID */ 0x00, 0x00,
1605  /* Length */ 0x00, 0x06,
1606  /* Unit ID */ 0x00,
1607  /* Function code */ 0x06,
1608  /* Register Address */ 0x00, 0x01,
1609  /* Register Value */ 0x00, 0x03};
1610 
1611 static uint8_t invalidWriteSingleRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1612  /* Protocol ID */ 0x00, 0x00,
1613  /* Length */ 0x00, 0x04,
1614  /* Unit ID */ 0x00,
1615  /* Function code */ 0x06,
1616  /* Register Address */ 0x00, 0x01};
1617 
1618 static uint8_t writeSingleRegisterRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1619  /* Protocol ID */ 0x00, 0x00,
1620  /* Length */ 0x00, 0x06,
1621  /* Unit ID */ 0x00,
1622  /* Function code */ 0x06,
1623  /* Register Address */ 0x00, 0x01,
1624  /* Register Value */ 0x00, 0x03};
1625 
1626 /* Modbus Application Protocol Specification V1.1b3 6.12: Write Multiple registers */
1627 /* Example of a request to write two registers starting at 2 to 00 0A and 01 02 hex */
1628 static uint8_t writeMultipleRegistersReq[] = {/* Transaction ID */ 0x00, 0x0A,
1629  /* Protocol ID */ 0x00, 0x00,
1630  /* Length */ 0x00, 0x0B,
1631  /* Unit ID */ 0x00,
1632  /* Function code */ 0x10,
1633  /* Starting Address */ 0x00, 0x01,
1634  /* Quantity of Registers */ 0x00, 0x02,
1635  /* Byte count */ 0x04,
1636  /* Registers Value */ 0x00, 0x0A,
1637  0x01, 0x02};
1638 
1639 static uint8_t writeMultipleRegistersRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1640  /* Protocol ID */ 0x00, 0x00,
1641  /* Length */ 0x00, 0x06,
1642  /* Unit ID */ 0x00,
1643  /* Function code */ 0x10,
1644  /* Starting Address */ 0x00, 0x01,
1645  /* Quantity of Registers */ 0x00, 0x02};
1646 
1647 /* Modbus Application Protocol Specification V1.1b3 6.16: Mask Write Register */
1648 /* Example of a request to mask write to register 5 */
1649 static uint8_t maskWriteRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1650  /* Protocol ID */ 0x00, 0x00,
1651  /* Length */ 0x00, 0x08,
1652  /* Unit ID */ 0x00,
1653  /* Function code */ 0x16,
1654  /* Reference Address */ 0x00, 0x04,
1655  /* And_Mask */ 0x00, 0xF2,
1656  /* Or_Mask */ 0x00, 0x25};
1657 
1658 static uint8_t invalidMaskWriteRegisterReq[] = {/* Transaction ID */ 0x00, 0x0A,
1659  /* Protocol ID */ 0x00, 0x00,
1660  /* Length */ 0x00, 0x06,
1661  /* Unit ID */ 0x00,
1662  /* Function code */ 0x16,
1663  /* Reference Address */ 0x00, 0x04,
1664  /* And_Mask */ 0x00, 0xF2};
1665 
1666 static uint8_t maskWriteRegisterRsp[] = {/* Transaction ID */ 0x00, 0x0A,
1667  /* Protocol ID */ 0x00, 0x00,
1668  /* Length */ 0x00, 0x08,
1669  /* Unit ID */ 0x00,
1670  /* Function code */ 0x16,
1671  /* Reference Address */ 0x00, 0x04,
1672  /* And_Mask */ 0x00, 0xF2,
1673  /* Or_Mask */ 0x00, 0x25};
1674 
1675 /* Modbus Application Protocol Specification V1.1b3 6.17: Read/Write Multiple registers */
1676 /* Example of a request to read six registers starting at register 4, */
1677 /* and to write three registers starting at register 15 */
1678 static uint8_t readWriteMultipleRegistersReq[] = {/* Transaction ID */ 0x12, 0x34,
1679  /* Protocol ID */ 0x00, 0x00,
1680  /* Length */ 0x00, 0x11,
1681  /* Unit ID */ 0x00,
1682  /* Function code */ 0x17,
1683  /* Read Starting Address */ 0x00, 0x03,
1684  /* Quantity to Read */ 0x00, 0x06,
1685  /* Write Starting Address */ 0x00, 0x0E,
1686  /* Quantity to Write */ 0x00, 0x03,
1687  /* Write Byte count */ 0x06,
1688  /* Write Registers Value */ 0x12, 0x34,
1689  0x56, 0x78,
1690  0x9A, 0xBC};
1691 
1692 /* Mismatch value in Byte count 0x0B instead of 0x0C */
1693 static uint8_t readWriteMultipleRegistersRsp[] = {/* Transaction ID */ 0x12, 0x34,
1694  /* Protocol ID */ 0x00, 0x00,
1695  /* Length */ 0x00, 0x0E,
1696  /* Unit ID */ 0x00,
1697  /* Function code */ 0x17,
1698  /* Byte count */ 0x0B,
1699  /* Read Registers Value */ 0x00, 0xFE,
1700  0x0A, 0xCD,
1701  0x00, 0x01,
1702  0x00, 0x03,
1703  0x00, 0x0D,
1704  0x00};
1705 
1706 /* Modbus Application Protocol Specification V1.1b3 6.8.1: 04 Force Listen Only Mode */
1707 /* Example of a request to to remote device to its Listen Only MOde for Modbus Communications. */
1708 static uint8_t forceListenOnlyMode[] = {/* Transaction ID */ 0x0A, 0x00,
1709  /* Protocol ID */ 0x00, 0x00,
1710  /* Length */ 0x00, 0x06,
1711  /* Unit ID */ 0x00,
1712  /* Function code */ 0x08,
1713  /* Sub-function code */ 0x00, 0x04,
1714  /* Data */ 0x00, 0x00};
1715 
1716 static uint8_t invalidProtocolIdReq[] = {/* Transaction ID */ 0x00, 0x00,
1717  /* Protocol ID */ 0x00, 0x01,
1718  /* Length */ 0x00, 0x06,
1719  /* Unit ID */ 0x00,
1720  /* Function code */ 0x01,
1721  /* Starting Address */ 0x78, 0x90,
1722  /* Quantity of coils */ 0x00, 0x13 };
1723 
1724 static uint8_t invalidLengthWriteMultipleRegistersReq[] = {
1725  /* Transaction ID */ 0x00, 0x0A,
1726  /* Protocol ID */ 0x00, 0x00,
1727  /* Length */ 0x00, 0x09,
1728  /* Unit ID */ 0x00,
1729  /* Function code */ 0x10,
1730  /* Starting Address */ 0x00, 0x01,
1731  /* Quantity of Registers */ 0x00, 0x02,
1732  /* Byte count */ 0x04,
1733  /* Registers Value */ 0x00, 0x0A,
1734  0x01, 0x02};
1735 
1736 static uint8_t exceededLengthWriteMultipleRegistersReq[] = {
1737  /* Transaction ID */ 0x00, 0x0A,
1738  /* Protocol ID */ 0x00, 0x00,
1739  /* Length */ 0xff, 0xfa,
1740  /* Unit ID */ 0x00,
1741  /* Function code */ 0x10,
1742  /* Starting Address */ 0x00, 0x01,
1743  /* Quantity of Registers */ 0x7f, 0xf9,
1744  /* Byte count */ 0xff};
1745 
1746 static uint8_t invalidLengthPDUWriteMultipleRegistersReq[] = {
1747  /* Transaction ID */ 0x00, 0x0A,
1748  /* Protocol ID */ 0x00, 0x00,
1749  /* Length */ 0x00, 0x02,
1750  /* Unit ID */ 0x00,
1751  /* Function code */ 0x10};
1752 
1753 /** \test Send Modbus Read Coils request/response. */
1754 static int ModbusParserTest01(void) {
1756  Flow f;
1757  TcpSession ssn;
1758 
1759  FAIL_IF_NULL(alp_tctx);
1760 
1761  memset(&f, 0, sizeof(f));
1762  memset(&ssn, 0, sizeof(ssn));
1763 
1764  FLOW_INITIALIZE(&f);
1765  f.protoctx = (void *)&ssn;
1766  f.proto = IPPROTO_TCP;
1767  f.alproto = ALPROTO_MODBUS;
1768 
1770 
1771  FLOWLOCK_WRLOCK(&f);
1772  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1773  STREAM_TOSERVER, readCoilsReq,
1774  sizeof(readCoilsReq));
1775  FAIL_IF_NOT(r == 0);
1776  FLOWLOCK_UNLOCK(&f);
1777 
1778  ModbusState *modbus_state = f.alstate;
1779  FAIL_IF_NULL(modbus_state);
1780 
1781  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1782  FAIL_IF_NOT(tx->function == 1);
1783  FAIL_IF_NOT(tx->read.address == 0x7890);
1784  FAIL_IF_NOT(tx->read.quantity == 19);
1785 
1786  FLOWLOCK_WRLOCK(&f);
1787  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1788  STREAM_TOCLIENT, readCoilsRsp,
1789  sizeof(readCoilsRsp));
1790  FAIL_IF_NOT(r == 0);
1791  FLOWLOCK_UNLOCK(&f);
1792 
1793  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1794 
1795  AppLayerParserThreadCtxFree(alp_tctx);
1797  FLOW_DESTROY(&f);
1798  PASS;
1799 }
1800 
1801 /** \test Send Modbus Write Multiple registers request/response. */
1802 static int ModbusParserTest02(void) {
1804  Flow f;
1805  TcpSession ssn;
1806 
1807  FAIL_IF_NULL(alp_tctx);
1808 
1809  memset(&f, 0, sizeof(f));
1810  memset(&ssn, 0, sizeof(ssn));
1811 
1812  FLOW_INITIALIZE(&f);
1813  f.protoctx = (void *)&ssn;
1814  f.proto = IPPROTO_TCP;
1815  f.alproto = ALPROTO_MODBUS;
1816 
1818 
1819  FLOWLOCK_WRLOCK(&f);
1820  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1821  STREAM_TOSERVER, writeMultipleRegistersReq,
1822  sizeof(writeMultipleRegistersReq));
1823  FAIL_IF_NOT(r == 0);
1824  FLOWLOCK_UNLOCK(&f);
1825 
1826  ModbusState *modbus_state = f.alstate;
1827  FAIL_IF_NULL(modbus_state);
1828 
1829  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1830 
1831  FAIL_IF_NOT(tx->function == 16);
1832  FAIL_IF_NOT(tx->write.address == 0x01);
1833  FAIL_IF_NOT(tx->write.quantity == 2);
1834  FAIL_IF_NOT(tx->write.count == 4);
1835  FAIL_IF_NOT(tx->data[0] == 0x000A);
1836  FAIL_IF_NOT(tx->data[1] == 0x0102);
1837 
1838  FLOWLOCK_WRLOCK(&f);
1839  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1840  STREAM_TOCLIENT, writeMultipleRegistersRsp,
1841  sizeof(writeMultipleRegistersRsp));
1842  FAIL_IF_NOT(r == 0);
1843  FLOWLOCK_UNLOCK(&f);
1844 
1845  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1846 
1847  AppLayerParserThreadCtxFree(alp_tctx);
1849  FLOW_DESTROY(&f);
1850  PASS;
1851 }
1852 
1853 /** \test Send Modbus Read/Write Multiple registers request/response with mismatch value. */
1854 static int ModbusParserTest03(void) {
1856  DetectEngineThreadCtx *det_ctx = NULL;
1857  Flow f;
1858  Packet *p = NULL;
1859  Signature *s = NULL;
1860  TcpSession ssn;
1861  ThreadVars tv;
1862 
1863  FAIL_IF_NULL(alp_tctx);
1864 
1865  memset(&tv, 0, sizeof(ThreadVars));
1866  memset(&f, 0, sizeof(Flow));
1867  memset(&ssn, 0, sizeof(TcpSession));
1868 
1869  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1870 
1871  FLOW_INITIALIZE(&f);
1872  f.alproto = ALPROTO_MODBUS;
1873  f.protoctx = (void *)&ssn;
1874  f.proto = IPPROTO_TCP;
1875  f.alproto = ALPROTO_MODBUS;
1876  f.flags |= FLOW_IPV4;
1877 
1878  p->flow = &f;
1881 
1883 
1885  FAIL_IF_NULL(de_ctx);
1886 
1887  de_ctx->flags |= DE_QUIET;
1888  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
1889  "(msg:\"Modbus Data mismatch\"; "
1890  "app-layer-event: "
1891  "modbus.value_mismatch; "
1892  "sid:1;)");
1893  FAIL_IF_NULL(s);
1894 
1895  SigGroupBuild(de_ctx);
1896  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1897 
1898  FLOWLOCK_WRLOCK(&f);
1899  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1901  readWriteMultipleRegistersReq,
1902  sizeof(readWriteMultipleRegistersReq));
1903  FAIL_IF_NOT(r == 0);
1904  FLOWLOCK_UNLOCK(&f);
1905 
1906  ModbusState *modbus_state = f.alstate;
1907  FAIL_IF_NULL(modbus_state);
1908 
1909  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1910 
1911  FAIL_IF_NOT(tx->function == 23);
1912  FAIL_IF_NOT(tx->read.address == 0x03);
1913  FAIL_IF_NOT(tx->read.quantity == 6);
1914  FAIL_IF_NOT(tx->write.address == 0x0E);
1915  FAIL_IF_NOT(tx->write.quantity == 3);
1916  FAIL_IF_NOT(tx->write.count == 6);
1917  FAIL_IF_NOT(tx->data[0] == 0x1234);
1918  FAIL_IF_NOT(tx->data[1] == 0x5678);
1919  FAIL_IF_NOT(tx->data[2] == 0x9ABC);
1920 
1921  FLOWLOCK_WRLOCK(&f);
1922  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1923  STREAM_TOCLIENT, readWriteMultipleRegistersRsp,
1924  sizeof(readWriteMultipleRegistersRsp));
1925  FAIL_IF_NOT(r == 0);
1926  FLOWLOCK_UNLOCK(&f);
1927 
1928  FAIL_IF_NOT(modbus_state->transaction_max == 1);
1929 
1930  /* do detect */
1931  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1932 
1934 
1935  SigGroupCleanup(de_ctx);
1936  SigCleanSignatures(de_ctx);
1937 
1938  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1939  DetectEngineCtxFree(de_ctx);
1940 
1941  AppLayerParserThreadCtxFree(alp_tctx);
1943  FLOW_DESTROY(&f);
1944  UTHFreePackets(&p, 1);
1945  PASS;
1946 }
1947 
1948 /** \test Send Modbus Force Listen Only Mode request. */
1949 static int ModbusParserTest04(void) {
1951  Flow f;
1952  TcpSession ssn;
1953 
1954  FAIL_IF_NULL(alp_tctx);
1955 
1956  memset(&f, 0, sizeof(f));
1957  memset(&ssn, 0, sizeof(ssn));
1958 
1959  FLOW_INITIALIZE(&f);
1960  f.protoctx = (void *)&ssn;
1961  f.proto = IPPROTO_TCP;
1962  f.alproto = ALPROTO_MODBUS;
1963 
1965 
1966  FLOWLOCK_WRLOCK(&f);
1967  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1968  STREAM_TOSERVER, forceListenOnlyMode,
1969  sizeof(forceListenOnlyMode));
1970  FAIL_IF_NOT(r == 0);
1971  FLOWLOCK_UNLOCK(&f);
1972 
1973  ModbusState *modbus_state = f.alstate;
1974  FAIL_IF_NULL(modbus_state);
1975 
1976  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
1977 
1978  FAIL_IF_NOT(tx->function == 8);
1979  FAIL_IF_NOT(tx->subFunction == 4);
1980 
1981  AppLayerParserThreadCtxFree(alp_tctx);
1983  FLOW_DESTROY(&f);
1984  PASS;
1985 }
1986 
1987 /** \test Send Modbus invalid Protocol version in request. */
1988 static int ModbusParserTest05(void) {
1990  DetectEngineThreadCtx *det_ctx = NULL;
1991  Flow f;
1992  Packet *p = NULL;
1993  Signature *s = NULL;
1994  TcpSession ssn;
1995  ThreadVars tv;
1996 
1997  FAIL_IF_NULL(alp_tctx);
1998 
1999  memset(&tv, 0, sizeof(ThreadVars));
2000  memset(&f, 0, sizeof(Flow));
2001  memset(&ssn, 0, sizeof(TcpSession));
2002 
2003  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2004 
2005  FLOW_INITIALIZE(&f);
2006  f.alproto = ALPROTO_MODBUS;
2007  f.protoctx = (void *)&ssn;
2008  f.proto = IPPROTO_TCP;
2009  f.alproto = ALPROTO_MODBUS;
2010  f.flags |= FLOW_IPV4;
2011 
2012  p->flow = &f;
2015 
2017 
2019  FAIL_IF_NULL(de_ctx);
2020 
2021  de_ctx->flags |= DE_QUIET;
2022  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2023  "(msg:\"Modbus invalid Protocol version\"; "
2024  "app-layer-event: "
2025  "modbus.invalid_protocol_id; "
2026  "sid:1;)");
2027  FAIL_IF_NULL(s);
2028 
2029  SigGroupBuild(de_ctx);
2030  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2031 
2032  FLOWLOCK_WRLOCK(&f);
2033  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2034  STREAM_TOSERVER, invalidProtocolIdReq,
2035  sizeof(invalidProtocolIdReq));
2036  FAIL_IF_NOT(r == 0);
2037  FLOWLOCK_UNLOCK(&f);
2038 
2039  ModbusState *modbus_state = f.alstate;
2040  FAIL_IF_NULL(modbus_state);
2041 
2042  /* do detect */
2043  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2044 
2046 
2047  SigGroupCleanup(de_ctx);
2048  SigCleanSignatures(de_ctx);
2049 
2050  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2051  DetectEngineCtxFree(de_ctx);
2052 
2053  AppLayerParserThreadCtxFree(alp_tctx);
2055  FLOW_DESTROY(&f);
2056  UTHFreePackets(&p, 1);
2057  PASS;
2058 }
2059 
2060 /** \test Send Modbus unsolicited response. */
2061 static int ModbusParserTest06(void) {
2063  DetectEngineThreadCtx *det_ctx = NULL;
2064  Flow f;
2065  Packet *p = NULL;
2066  Signature *s = NULL;
2067  TcpSession ssn;
2068  ThreadVars tv;
2069 
2070  FAIL_IF_NULL(alp_tctx);
2071 
2072  memset(&tv, 0, sizeof(ThreadVars));
2073  memset(&f, 0, sizeof(Flow));
2074  memset(&ssn, 0, sizeof(TcpSession));
2075 
2076  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2077 
2078  FLOW_INITIALIZE(&f);
2079  f.alproto = ALPROTO_MODBUS;
2080  f.protoctx = (void *)&ssn;
2081  f.proto = IPPROTO_TCP;
2082  f.alproto = ALPROTO_MODBUS;
2083  f.flags |= FLOW_IPV4;
2084 
2085  p->flow = &f;
2088 
2090 
2092  FAIL_IF_NULL(de_ctx);
2093 
2094  de_ctx->flags |= DE_QUIET;
2095  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2096  "(msg:\"Modbus unsolicited response\"; "
2097  "app-layer-event: "
2098  "modbus.unsolicited_response; "
2099  "sid:1;)");
2100  FAIL_IF_NULL(s);
2101 
2102  SigGroupBuild(de_ctx);
2103  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2104 
2105  FLOWLOCK_WRLOCK(&f);
2106  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2107  STREAM_TOCLIENT, readCoilsRsp,
2108  sizeof(readCoilsRsp));
2109  FAIL_IF_NOT(r == 0);
2110  FLOWLOCK_UNLOCK(&f);
2111 
2112  ModbusState *modbus_state = f.alstate;
2113  FAIL_IF_NULL(modbus_state);
2114 
2115  /* do detect */
2116  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2117 
2119 
2120  SigGroupCleanup(de_ctx);
2121  SigCleanSignatures(de_ctx);
2122 
2123  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2124  DetectEngineCtxFree(de_ctx);
2125 
2126  AppLayerParserThreadCtxFree(alp_tctx);
2128  FLOW_DESTROY(&f);
2129  UTHFreePackets(&p, 1);
2130  PASS;
2131 }
2132 
2133 /** \test Send Modbus invalid Length request. */
2134 static int ModbusParserTest07(void) {
2136  DetectEngineThreadCtx *det_ctx = NULL;
2137  Flow f;
2138  Packet *p = NULL;
2139  Signature *s = NULL;
2140  TcpSession ssn;
2141  ThreadVars tv;
2142 
2143  FAIL_IF_NULL(alp_tctx);
2144 
2145  memset(&tv, 0, sizeof(ThreadVars));
2146  memset(&f, 0, sizeof(Flow));
2147  memset(&ssn, 0, sizeof(TcpSession));
2148 
2149  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2150 
2151  FLOW_INITIALIZE(&f);
2152  f.alproto = ALPROTO_MODBUS;
2153  f.protoctx = (void *)&ssn;
2154  f.proto = IPPROTO_TCP;
2155  f.alproto = ALPROTO_MODBUS;
2156  f.flags |= FLOW_IPV4;
2157 
2158  p->flow = &f;
2161 
2163 
2165  FAIL_IF_NULL(de_ctx);
2166 
2167  de_ctx->flags |= DE_QUIET;
2168  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2169  "(msg:\"Modbus invalid Length\"; "
2170  "app-layer-event: "
2171  "modbus.invalid_length; "
2172  "sid:1;)");
2173  FAIL_IF_NULL(s);
2174 
2175  SigGroupBuild(de_ctx);
2176  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2177 
2178  FLOWLOCK_WRLOCK(&f);
2179  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2181  invalidLengthWriteMultipleRegistersReq,
2182  sizeof(invalidLengthWriteMultipleRegistersReq));
2183  FAIL_IF_NOT(r == 0);
2184  FLOWLOCK_UNLOCK(&f);
2185 
2186  ModbusState *modbus_state = f.alstate;
2187  FAIL_IF_NULL(modbus_state);
2188 
2189  /* do detect */
2190  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2191 
2193 
2194  SigGroupCleanup(de_ctx);
2195  SigCleanSignatures(de_ctx);
2196 
2197  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2198  DetectEngineCtxFree(de_ctx);
2199 
2200  AppLayerParserThreadCtxFree(alp_tctx);
2202  FLOW_DESTROY(&f);
2203  UTHFreePackets(&p, 1);
2204  PASS;
2205 }
2206 
2207 /** \test Send Modbus Read Coils request and error response with Exception code invalid. */
2208 static int ModbusParserTest08(void) {
2210  DetectEngineThreadCtx *det_ctx = NULL;
2211  Flow f;
2212  Packet *p = NULL;
2213  Signature *s = NULL;
2214  TcpSession ssn;
2215  ThreadVars tv;
2216 
2217  FAIL_IF_NULL(alp_tctx);
2218 
2219  memset(&tv, 0, sizeof(ThreadVars));
2220  memset(&f, 0, sizeof(Flow));
2221  memset(&ssn, 0, sizeof(TcpSession));
2222 
2223  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2224 
2225  FLOW_INITIALIZE(&f);
2226  f.alproto = ALPROTO_MODBUS;
2227  f.protoctx = (void *)&ssn;
2228  f.proto = IPPROTO_TCP;
2229  f.alproto = ALPROTO_MODBUS;
2230  f.flags |= FLOW_IPV4;
2231 
2232  p->flow = &f;
2235 
2237 
2239  FAIL_IF_NULL(de_ctx);
2240 
2241  de_ctx->flags |= DE_QUIET;
2242  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2243  "(msg:\"Modbus Exception code invalid\"; "
2244  "app-layer-event: "
2245  "modbus.invalid_exception_code; "
2246  "sid:1;)");
2247  FAIL_IF_NULL(s);
2248 
2249  SigGroupBuild(de_ctx);
2250  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2251 
2252  FLOWLOCK_WRLOCK(&f);
2253  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2254  STREAM_TOSERVER, readCoilsReq,
2255  sizeof(readCoilsReq));
2256  FAIL_IF_NOT(r == 0);
2257  FLOWLOCK_UNLOCK(&f);
2258 
2259  ModbusState *modbus_state = f.alstate;
2260  FAIL_IF_NULL(modbus_state);
2261 
2262  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2263 
2264  FAIL_IF_NOT(tx->function == 1);
2265  FAIL_IF_NOT(tx->read.address == 0x7890);
2266  FAIL_IF_NOT(tx->read.quantity == 19);
2267 
2268  FLOWLOCK_WRLOCK(&f);
2269  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2270  STREAM_TOCLIENT, readCoilsErrorRsp,
2271  sizeof(readCoilsErrorRsp));
2272  FAIL_IF_NOT(r == 0);
2273  FLOWLOCK_UNLOCK(&f);
2274 
2275  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2276 
2277  /* do detect */
2278  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2279 
2281 
2282  SigGroupCleanup(de_ctx);
2283  SigCleanSignatures(de_ctx);
2284 
2285  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2286  DetectEngineCtxFree(de_ctx);
2287 
2288  AppLayerParserThreadCtxFree(alp_tctx);
2290  FLOW_DESTROY(&f);
2291  UTHFreePackets(&p, 1);
2292  PASS;
2293 }
2294 
2295 /** \test Modbus fragmentation - 1 ADU over 2 TCP packets. */
2296 static int ModbusParserTest09(void) {
2298  Flow f;
2299  TcpSession ssn;
2300 
2301  uint32_t input_len = sizeof(readCoilsReq), part2_len = 3;
2302  uint8_t *input = readCoilsReq;
2303 
2304  FAIL_IF_NULL(alp_tctx);
2305 
2306  memset(&f, 0, sizeof(f));
2307  memset(&ssn, 0, sizeof(ssn));
2308 
2309  FLOW_INITIALIZE(&f);
2310  f.protoctx = (void *)&ssn;
2311  f.proto = IPPROTO_TCP;
2312  f.alproto = ALPROTO_MODBUS;
2313 
2315 
2316  FLOWLOCK_WRLOCK(&f);
2317  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2318  STREAM_TOSERVER, input, input_len - part2_len);
2319  FAIL_IF_NOT(r == 0);
2320 
2321  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2322  STREAM_TOSERVER, input, input_len);
2323  FAIL_IF_NOT(r == 0);
2324  FLOWLOCK_UNLOCK(&f);
2325 
2326  ModbusState *modbus_state = f.alstate;
2327  FAIL_IF_NULL(modbus_state);
2328 
2329  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2330 
2331  FAIL_IF_NOT(tx->function == 1);
2332  FAIL_IF_NOT(tx->read.address == 0x7890);
2333  FAIL_IF_NOT(tx->read.quantity == 19);
2334 
2335  input_len = sizeof(readCoilsRsp);
2336  part2_len = 10;
2337  input = readCoilsRsp;
2338 
2339  FLOWLOCK_WRLOCK(&f);
2340  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2341  STREAM_TOCLIENT, input, input_len - part2_len);
2342  FAIL_IF_NOT(r == 0);
2343 
2344  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2345  STREAM_TOCLIENT, input, input_len);
2346  FAIL_IF_NOT(r == 0);
2347  FLOWLOCK_UNLOCK(&f);
2348 
2349  FAIL_IF_NOT(modbus_state->transaction_max ==1);
2350 
2351  AppLayerParserThreadCtxFree(alp_tctx);
2353  FLOW_DESTROY(&f);
2354  PASS;
2355 }
2356 
2357 /** \test Modbus fragmentation - 2 ADU in 1 TCP packet. */
2358 static int ModbusParserTest10(void) {
2359  uint32_t input_len = sizeof(readCoilsReq) + sizeof(writeMultipleRegistersReq);
2360  uint8_t *input, *ptr;
2361 
2363  Flow f;
2364  TcpSession ssn;
2365 
2366  FAIL_IF_NULL(alp_tctx);
2367 
2368  input = (uint8_t *) SCMalloc (input_len * sizeof(uint8_t));
2369  FAIL_IF_NULL(input);
2370 
2371  memcpy(input, readCoilsReq, sizeof(readCoilsReq));
2372  memcpy(input + sizeof(readCoilsReq), writeMultipleRegistersReq, sizeof(writeMultipleRegistersReq));
2373 
2374  memset(&f, 0, sizeof(f));
2375  memset(&ssn, 0, sizeof(ssn));
2376 
2377  FLOW_INITIALIZE(&f);
2378  f.protoctx = (void *)&ssn;
2379  f.proto = IPPROTO_TCP;
2380  f.alproto = ALPROTO_MODBUS;
2381 
2383 
2384  FLOWLOCK_WRLOCK(&f);
2385  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2386  STREAM_TOSERVER, input, input_len);
2387  FAIL_IF_NOT(r == 0);
2388  FLOWLOCK_UNLOCK(&f);
2389 
2390  ModbusState *modbus_state = f.alstate;
2391  FAIL_IF_NULL(modbus_state);
2392 
2393  FAIL_IF_NOT(modbus_state->transaction_max == 2);
2394 
2395  ModbusTransaction *tx = ModbusGetTx(modbus_state, 1);
2396 
2397  FAIL_IF_NOT(tx->function == 16);
2398  FAIL_IF_NOT(tx->write.address == 0x01);
2399  FAIL_IF_NOT(tx->write.quantity == 2);
2400  FAIL_IF_NOT(tx->write.count == 4);
2401  FAIL_IF_NOT(tx->data[0] == 0x000A);
2402  FAIL_IF_NOT(tx->data[1] == 0x0102);
2403 
2404  input_len = sizeof(readCoilsRsp) + sizeof(writeMultipleRegistersRsp);
2405 
2406  ptr = (uint8_t *) SCRealloc (input, input_len * sizeof(uint8_t));
2407  FAIL_IF_NULL(ptr);
2408  input = ptr;
2409 
2410  memcpy(input, readCoilsRsp, sizeof(readCoilsRsp));
2411  memcpy(input + sizeof(readCoilsRsp), writeMultipleRegistersRsp, sizeof(writeMultipleRegistersRsp));
2412 
2413  FLOWLOCK_WRLOCK(&f);
2414  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2415  STREAM_TOCLIENT, input, sizeof(input_len));
2416  FAIL_IF_NOT(r == 0);
2417  FLOWLOCK_UNLOCK(&f);
2418 
2419  SCFree(input);
2420  AppLayerParserThreadCtxFree(alp_tctx);
2422  FLOW_DESTROY(&f);
2423  PASS;
2424 }
2425 
2426 /** \test Send Modbus exceed Length request. */
2427 static int ModbusParserTest11(void) {
2429  DetectEngineThreadCtx *det_ctx = NULL;
2430  Flow f;
2431  Packet *p = NULL;
2432  Signature *s = NULL;
2433  TcpSession ssn;
2434  ThreadVars tv;
2435 
2436  FAIL_IF(alp_tctx == NULL);
2437 
2438  memset(&tv, 0, sizeof(ThreadVars));
2439  memset(&f, 0, sizeof(Flow));
2440  memset(&ssn, 0, sizeof(TcpSession));
2441 
2442  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2443 
2444  FLOW_INITIALIZE(&f);
2445  f.alproto = ALPROTO_MODBUS;
2446  f.protoctx = (void *)&ssn;
2447  f.proto = IPPROTO_TCP;
2448  f.alproto = ALPROTO_MODBUS;
2449  f.flags |= FLOW_IPV4;
2450 
2451  p->flow = &f;
2454 
2456 
2458  FAIL_IF_NULL(de_ctx);
2459 
2460  de_ctx->flags |= DE_QUIET;
2461  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2462  "(msg:\"Modbus invalid Length\"; "
2463  "app-layer-event: "
2464  "modbus.invalid_length; "
2465  "sid:1;)");
2466  FAIL_IF_NULL(s);
2467 
2468  SigGroupBuild(de_ctx);
2469  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2470 
2471  FLOWLOCK_WRLOCK(&f);
2472  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2474  exceededLengthWriteMultipleRegistersReq,
2475  sizeof(exceededLengthWriteMultipleRegistersReq) + 65523 * sizeof(uint8_t));
2476  FAIL_IF_NOT(r == 0);
2477  FLOWLOCK_UNLOCK(&f);
2478 
2479  ModbusState *modbus_state = f.alstate;
2480  FAIL_IF_NULL(modbus_state);
2481 
2482  /* do detect */
2483  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2484 
2486 
2487  SigGroupCleanup(de_ctx);
2488  SigCleanSignatures(de_ctx);
2489 
2490  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2491  DetectEngineCtxFree(de_ctx);
2492 
2493  AppLayerParserThreadCtxFree(alp_tctx);
2495  FLOW_DESTROY(&f);
2496  UTHFreePackets(&p, 1);
2497  PASS;
2498 }
2499 
2500 /** \test Send Modbus invalid PDU Length. */
2501 static int ModbusParserTest12(void) {
2503  DetectEngineThreadCtx *det_ctx = NULL;
2504  Flow f;
2505  Packet *p = NULL;
2506  Signature *s = NULL;
2507  TcpSession ssn;
2508  ThreadVars tv;
2509 
2510  FAIL_IF_NULL(alp_tctx);
2511 
2512  memset(&tv, 0, sizeof(ThreadVars));
2513  memset(&f, 0, sizeof(Flow));
2514  memset(&ssn, 0, sizeof(TcpSession));
2515 
2516  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2517 
2518  FLOW_INITIALIZE(&f);
2519  f.alproto = ALPROTO_MODBUS;
2520  f.protoctx = (void *)&ssn;
2521  f.proto = IPPROTO_TCP;
2522  f.alproto = ALPROTO_MODBUS;
2523  f.flags |= FLOW_IPV4;
2524 
2525  p->flow = &f;
2528 
2530 
2532  FAIL_IF_NULL(de_ctx);
2533 
2534  de_ctx->flags |= DE_QUIET;
2535  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2536  "(msg:\"Modbus invalid Length\"; "
2537  "app-layer-event: "
2538  "modbus.invalid_length; "
2539  "sid:1;)");
2540  FAIL_IF_NULL(s);
2541 
2542  SigGroupBuild(de_ctx);
2543  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2544 
2545  FLOWLOCK_WRLOCK(&f);
2546  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2548  invalidLengthPDUWriteMultipleRegistersReq,
2549  sizeof(invalidLengthPDUWriteMultipleRegistersReq));
2550  FAIL_IF_NOT(r == 0);
2551  FLOWLOCK_UNLOCK(&f);
2552 
2553  ModbusState *modbus_state = f.alstate;
2554  FAIL_IF_NULL(modbus_state);
2555 
2556  /* do detect */
2557  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2558 
2560 
2561  SigGroupCleanup(de_ctx);
2562  SigCleanSignatures(de_ctx);
2563 
2564  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2565  DetectEngineCtxFree(de_ctx);
2566 
2567  AppLayerParserThreadCtxFree(alp_tctx);
2569  FLOW_DESTROY(&f);
2570  UTHFreePackets(&p, 1);
2571  PASS;
2572 }
2573 
2574 /** \test Send Modbus Mask Write register request/response. */
2575 static int ModbusParserTest13(void) {
2577  Flow f;
2578  TcpSession ssn;
2579 
2580  FAIL_IF_NULL(alp_tctx);
2581 
2582  memset(&f, 0, sizeof(f));
2583  memset(&ssn, 0, sizeof(ssn));
2584 
2585  FLOW_INITIALIZE(&f);
2586  f.protoctx = (void *)&ssn;
2587  f.proto = IPPROTO_TCP;
2588  f.alproto = ALPROTO_MODBUS;
2589 
2591 
2592  FLOWLOCK_WRLOCK(&f);
2593  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2594  STREAM_TOSERVER, maskWriteRegisterReq,
2595  sizeof(maskWriteRegisterReq));
2596  FAIL_IF_NOT(r == 0);
2597  FLOWLOCK_UNLOCK(&f);
2598 
2599  ModbusState *modbus_state = f.alstate;
2600  FAIL_IF_NULL(modbus_state);
2601 
2602  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2603 
2604  FAIL_IF_NOT(tx->function == 22);
2605  FAIL_IF_NOT(tx->data[0] == 0x00F2);
2606  FAIL_IF_NOT(tx->data[1] == 0x0025);
2607 
2608  FLOWLOCK_WRLOCK(&f);
2609  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2610  STREAM_TOCLIENT, maskWriteRegisterRsp,
2611  sizeof(maskWriteRegisterRsp));
2612  FAIL_IF_NOT(r == 0);
2613  FLOWLOCK_UNLOCK(&f);
2614 
2615  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2616 
2617  AppLayerParserThreadCtxFree(alp_tctx);
2619  FLOW_DESTROY(&f);
2620  PASS;
2621 }
2622 
2623 /** \test Send Modbus Write single register request/response. */
2624 static int ModbusParserTest14(void) {
2626  Flow f;
2627  TcpSession ssn;
2628 
2629  FAIL_IF_NULL(alp_tctx);
2630 
2631  memset(&f, 0, sizeof(f));
2632  memset(&ssn, 0, sizeof(ssn));
2633 
2634  FLOW_INITIALIZE(&f);
2635  f.protoctx = (void *)&ssn;
2636  f.proto = IPPROTO_TCP;
2637  f.alproto = ALPROTO_MODBUS;
2638 
2640 
2641  FLOWLOCK_WRLOCK(&f);
2642  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2643  STREAM_TOSERVER, writeSingleRegisterReq,
2644  sizeof(writeSingleRegisterReq));
2645  FAIL_IF_NOT(r == 0);
2646  FLOWLOCK_UNLOCK(&f);
2647 
2648  ModbusState *modbus_state = f.alstate;
2649  FAIL_IF_NULL(modbus_state);
2650 
2651  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2652 
2653  FAIL_IF_NOT(tx->function == 6);
2654  FAIL_IF_NOT(tx->write.address == 0x0001);
2655  FAIL_IF_NOT(tx->data[0] == 0x0003);
2656 
2657  FLOWLOCK_WRLOCK(&f);
2658  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2659  STREAM_TOCLIENT, writeSingleRegisterRsp,
2660  sizeof(writeSingleRegisterRsp));
2661  FAIL_IF_NOT(r == 0);
2662  FLOWLOCK_UNLOCK(&f);
2663 
2664  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2665 
2666  AppLayerParserThreadCtxFree(alp_tctx);
2668  FLOW_DESTROY(&f);
2669  PASS;
2670 }
2671 
2672 /** \test Send invalid Modbus Mask Write register request. */
2673 static int ModbusParserTest15(void) {
2675  DetectEngineThreadCtx *det_ctx = NULL;
2676  Flow f;
2677  Packet *p = NULL;
2678  Signature *s = NULL;
2679  TcpSession ssn;
2680  ThreadVars tv;
2681 
2682  FAIL_IF_NULL(alp_tctx);
2683 
2684  memset(&tv, 0, sizeof(ThreadVars));
2685  memset(&f, 0, sizeof(f));
2686  memset(&ssn, 0, sizeof(ssn));
2687 
2688  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2689 
2690  FLOW_INITIALIZE(&f);
2691  f.alproto = ALPROTO_MODBUS;
2692  f.protoctx = (void *)&ssn;
2693  f.proto = IPPROTO_TCP;
2694  f.alproto = ALPROTO_MODBUS;
2695  f.flags |= FLOW_IPV4;
2696 
2697  p->flow = &f;
2700 
2702 
2704  FAIL_IF_NULL(de_ctx);
2705 
2706  de_ctx->flags |= DE_QUIET;
2707  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2708  "(msg:\"Modbus invalid Length\"; "
2709  "app-layer-event: "
2710  "modbus.invalid_length; "
2711  "sid:1;)");
2712  FAIL_IF_NULL(s);
2713 
2714  SigGroupBuild(de_ctx);
2715  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2716 
2717  FLOWLOCK_WRLOCK(&f);
2718  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2719  STREAM_TOSERVER, invalidMaskWriteRegisterReq,
2720  sizeof(invalidMaskWriteRegisterReq));
2721  FAIL_IF_NOT(r == 0);
2722  FLOWLOCK_UNLOCK(&f);
2723 
2724  ModbusState *modbus_state = f.alstate;
2725  FAIL_IF_NULL(modbus_state);
2726 
2727  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2728 
2729  FAIL_IF_NOT(tx->function == 22);
2730 
2731  /* do detect */
2732  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2733 
2735 
2736  FLOWLOCK_WRLOCK(&f);
2737  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2738  STREAM_TOCLIENT, maskWriteRegisterRsp,
2739  sizeof(maskWriteRegisterRsp));
2740  FAIL_IF_NOT(r == 0);
2741  FLOWLOCK_UNLOCK(&f);
2742 
2743  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2744 
2745  SigGroupCleanup(de_ctx);
2746  SigCleanSignatures(de_ctx);
2747 
2748  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2749  DetectEngineCtxFree(de_ctx);
2750 
2751  AppLayerParserThreadCtxFree(alp_tctx);
2753  FLOW_DESTROY(&f);
2754  UTHFreePackets(&p, 1);
2755  PASS;
2756 }
2757 
2758 /** \test Send invalid Modbus Mask Write register request. */
2759 static int ModbusParserTest16(void) {
2761  DetectEngineThreadCtx *det_ctx = NULL;
2762  Flow f;
2763  Packet *p = NULL;
2764  Signature *s = NULL;
2765  TcpSession ssn;
2766  ThreadVars tv;
2767 
2768  FAIL_IF_NULL(alp_tctx);
2769 
2770  memset(&tv, 0, sizeof(ThreadVars));
2771  memset(&f, 0, sizeof(f));
2772  memset(&ssn, 0, sizeof(ssn));
2773 
2774  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2775 
2776  FLOW_INITIALIZE(&f);
2777  f.alproto = ALPROTO_MODBUS;
2778  f.protoctx = (void *)&ssn;
2779  f.proto = IPPROTO_TCP;
2780  f.alproto = ALPROTO_MODBUS;
2781  f.flags |= FLOW_IPV4;
2782 
2783  p->flow = &f;
2786 
2788 
2790  FAIL_IF_NULL(de_ctx);
2791 
2792  de_ctx->flags |= DE_QUIET;
2793  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2794  "(msg:\"Modbus invalid Length\"; "
2795  "app-layer-event: "
2796  "modbus.invalid_length; "
2797  "sid:1;)");
2798  FAIL_IF_NULL(s);
2799 
2800  SigGroupBuild(de_ctx);
2801  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2802 
2803  FLOWLOCK_WRLOCK(&f);
2804  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2806  invalidWriteSingleRegisterReq,
2807  sizeof(invalidWriteSingleRegisterReq));
2808  FAIL_IF_NOT(r == 0);
2809  FLOWLOCK_UNLOCK(&f);
2810 
2811  ModbusState *modbus_state = f.alstate;
2812  FAIL_IF_NULL(modbus_state);
2813 
2814  ModbusTransaction *tx = ModbusGetTx(modbus_state, 0);
2815 
2816  FAIL_IF_NOT(tx->function == 6);
2817  FAIL_IF_NOT(tx->write.address == 0x0001);
2818 
2819  /* do detect */
2820  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
2821 
2823 
2824  FLOWLOCK_WRLOCK(&f);
2825  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
2826  STREAM_TOCLIENT, writeSingleRegisterRsp,
2827  sizeof(writeSingleRegisterRsp));
2828  FAIL_IF_NOT(r == 0);
2829  FLOWLOCK_UNLOCK(&f);
2830 
2831  FAIL_IF_NOT(modbus_state->transaction_max == 1);
2832 
2833  SigGroupCleanup(de_ctx);
2834  SigCleanSignatures(de_ctx);
2835 
2836  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
2837  DetectEngineCtxFree(de_ctx);
2838 
2839  AppLayerParserThreadCtxFree(alp_tctx);
2841  FLOW_DESTROY(&f);
2842  UTHFreePackets(&p, 1);
2843  PASS;}
2844 
2845 /** \test Checks if stream_depth is correct */
2846 static int ModbusParserTest17(void) {
2848  Flow f;
2849  TcpSession ssn;
2850 
2851  FAIL_IF_NULL(alp_tctx);
2852 
2853  memset(&f, 0, sizeof(f));
2854  memset(&ssn, 0, sizeof(ssn));
2855 
2856  FLOW_INITIALIZE(&f);
2857  f.protoctx = (void *)&ssn;
2858  f.proto = IPPROTO_TCP;
2859  f.alproto = ALPROTO_MODBUS;
2860 
2862 
2863  FLOWLOCK_WRLOCK(&f);
2864  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2865  readCoilsReq, sizeof(readCoilsReq));
2866  FAIL_IF(r != 0);
2867  FLOWLOCK_UNLOCK(&f);
2868 
2869  FAIL_IF(f.alstate == NULL);
2870 
2871  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2872 
2873  FLOWLOCK_WRLOCK(&f);
2874  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2875  readCoilsRsp, sizeof(readCoilsRsp));
2876  FAIL_IF(r != 0);
2877  FLOWLOCK_UNLOCK(&f);
2878 
2879  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2880 
2881  AppLayerParserThreadCtxFree(alp_tctx);
2883  FLOW_DESTROY(&f);
2884  PASS;
2885 }
2886 
2887 /*/ \test Checks if stream depth is correct over 2 TCP packets */
2888 static int ModbusParserTest18(void) {
2890  Flow f;
2891  TcpSession ssn;
2892 
2893  uint32_t input_len = sizeof(readCoilsReq), part2_len = 3;
2894  uint8_t *input = readCoilsReq;
2895 
2896  FAIL_IF_NULL(alp_tctx);
2897 
2898  memset(&f, 0, sizeof(f));
2899  memset(&ssn, 0, sizeof(ssn));
2900 
2901  FLOW_INITIALIZE(&f);
2902  f.protoctx = (void *)&ssn;
2903  f.proto = IPPROTO_TCP;
2904  f.alproto = ALPROTO_MODBUS;
2905 
2907 
2908  FLOWLOCK_WRLOCK(&f);
2909  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2910  input, input_len - part2_len);
2911  FAIL_IF(r != 0);
2912  FLOWLOCK_UNLOCK(&f);
2913 
2914  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2915 
2916  FLOWLOCK_WRLOCK(&f);
2917  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
2918  input, input_len);
2919  FAIL_IF(r != 0);
2920  FLOWLOCK_UNLOCK(&f);
2921 
2922  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2923 
2924  FAIL_IF(f.alstate == NULL);
2925 
2926  input_len = sizeof(readCoilsRsp);
2927  part2_len = 10;
2928  input = readCoilsRsp;
2929 
2930  FLOWLOCK_WRLOCK(&f);
2931  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2932  input, input_len - part2_len);
2933  FAIL_IF(r != 0);
2934  FLOWLOCK_UNLOCK(&f);
2935 
2936  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2937 
2938  FLOWLOCK_WRLOCK(&f);
2939  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
2940  input, input_len);
2941  FAIL_IF(r != 0);
2942  FLOWLOCK_UNLOCK(&f);
2943 
2944  FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
2945 
2946  AppLayerParserThreadCtxFree(alp_tctx);
2948  FLOW_DESTROY(&f);
2949  PASS;
2950 }
2951 
2952 /** \test Send Modbus invalid function. */
2953 static int ModbusParserTest19(void) {
2955  DetectEngineThreadCtx *det_ctx = NULL;
2956  Flow f;
2957  Packet *p = NULL;
2958  Signature *s = NULL;
2959  TcpSession ssn;
2960  ThreadVars tv;
2961 
2962  FAIL_IF_NULL(alp_tctx);
2963 
2964  memset(&tv, 0, sizeof(ThreadVars));
2965  memset(&f, 0, sizeof(Flow));
2966  memset(&ssn, 0, sizeof(TcpSession));
2967 
2968  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2969 
2970  FLOW_INITIALIZE(&f);
2971  f.alproto = ALPROTO_MODBUS;
2972  f.protoctx = (void *)&ssn;
2973  f.proto = IPPROTO_TCP;
2974  f.alproto = ALPROTO_MODBUS;
2975  f.flags |= FLOW_IPV4;
2976 
2977  p->flow = &f;
2980 
2982 
2984  FAIL_IF_NULL(de_ctx);
2985 
2986  de_ctx->flags |= DE_QUIET;
2987  s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
2988  "(msg:\"Modbus invalid Function code\"; "
2989  "app-layer-event: "
2990  "modbus.invalid_function_code; "
2991  "sid:1;)");
2992  FAIL_IF_NULL(s);
2993 
2994  SigGroupBuild(de_ctx);
2995  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
2996 
2997  FLOWLOCK_WRLOCK(&f);
2998  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
3000  invalidFunctionCode,
3001  sizeof(invalidFunctionCode));
3002  FAIL_IF_NOT(r == 0);
3003  FLOWLOCK_UNLOCK(&f);
3004 
3005  ModbusState *modbus_state = f.alstate;
3006  FAIL_IF_NULL(modbus_state);
3007 
3008  /* do detect */
3009  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3010 
3012 
3013  SigGroupCleanup(de_ctx);
3014  SigCleanSignatures(de_ctx);
3015 
3016  DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
3017  DetectEngineCtxFree(de_ctx);
3018 
3019  AppLayerParserThreadCtxFree(alp_tctx);
3021  FLOW_DESTROY(&f);
3022  UTHFreePackets(&p, 1);
3023  PASS;
3024 }
3025 #endif /* UNITTESTS */
3026 
3028 #ifdef UNITTESTS
3029  UtRegisterTest("ModbusParserTest01 - Modbus Read Coils request",
3030  ModbusParserTest01);
3031  UtRegisterTest("ModbusParserTest02 - Modbus Write Multiple registers request",
3032  ModbusParserTest02);
3033  UtRegisterTest("ModbusParserTest03 - Modbus Read/Write Multiple registers request",
3034  ModbusParserTest03);
3035  UtRegisterTest("ModbusParserTest04 - Modbus Force Listen Only Mode request",
3036  ModbusParserTest04);
3037  UtRegisterTest("ModbusParserTest05 - Modbus invalid Protocol version",
3038  ModbusParserTest05);
3039  UtRegisterTest("ModbusParserTest06 - Modbus unsolicited response",
3040  ModbusParserTest06);
3041  UtRegisterTest("ModbusParserTest07 - Modbus invalid Length request",
3042  ModbusParserTest07);
3043  UtRegisterTest("ModbusParserTest08 - Modbus Exception code invalid",
3044  ModbusParserTest08);
3045  UtRegisterTest("ModbusParserTest09 - Modbus fragmentation - 1 ADU in 2 TCP packets",
3046  ModbusParserTest09);
3047  UtRegisterTest("ModbusParserTest10 - Modbus fragmentation - 2 ADU in 1 TCP packet",
3048  ModbusParserTest10);
3049  UtRegisterTest("ModbusParserTest11 - Modbus exceeded Length request",
3050  ModbusParserTest11);
3051  UtRegisterTest("ModbusParserTest12 - Modbus invalid PDU Length",
3052  ModbusParserTest12);
3053  UtRegisterTest("ModbusParserTest13 - Modbus Mask Write register request",
3054  ModbusParserTest13);
3055  UtRegisterTest("ModbusParserTest14 - Modbus Write single register request",
3056  ModbusParserTest14);
3057  UtRegisterTest("ModbusParserTest15 - Modbus invalid Mask Write register request",
3058  ModbusParserTest15);
3059  UtRegisterTest("ModbusParserTest16 - Modbus invalid Write single register request",
3060  ModbusParserTest16);
3061  UtRegisterTest("ModbusParserTest17 - Modbus stream depth",
3062  ModbusParserTest17);
3063  UtRegisterTest("ModbusParserTest18 - Modbus stream depth in 2 TCP packets",
3064  ModbusParserTest18);
3065  UtRegisterTest("ModbusParserTest19 - Modbus invalid Function code",
3066  ModbusParserTest19);
3067 #endif /* UNITTESTS */
3068 }
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:443
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:343
void ModbusParserRegisterTests(void)
#define FALSE
#define MODBUS_TYP_ACCESS_FUNCTION_MASK
LoggerId
#define MODBUS_SUBFUNC_DIAG_REGS
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:242
#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:202
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:239
#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:495
#define MODBUS_TYP_COILS
#define MODBUS_MIN_COUNT
#define TRUE
#define MODBUS_FUNC_READDISCINPUTS
void * protoctx
Definition: flow.h:395
#define MODBUS_SUBFUNC_SERVER_NO_RSP_COUNT
#define MODBUS_FUNC_WRITESINGLEREG
main detection engine ctx
Definition: detect.h:723
#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:433
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:296
#define MODBUS_MIN_INVALID_UNIT_ID
#define SCCalloc(nm, a)
Definition: util-mem.h:197
Data structure to store app layer decoder events.
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
#define MODBUS_FUNC_WRITEFILERECORD
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
uint8_t flags
Definition: detect.h:724
#define MODBUS_FUNC_ERRORMASK
#define TAILQ_INIT(head)
Definition: queue.h:370
#define MODBUS_FUNC_WRITEMULTREGS
int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, int *event_id, AppLayerEventType *event_type))
uint8_t type
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_DESTROY(f)
Definition: flow-util.h: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:1743
#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:437
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:200
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:259
#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:182
#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:166
#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:228
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:1092
#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:404
#define MODBUS_CAT_RESERVED
#define MODBUS_SUBFUNC_CLEAR_COUNT
uint32_t flags
Definition: decode.h:441
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:324
#define FLOW_IPV4
Definition: flow.h:93
#define MODBUS_FUNC_READHOLDREGS
uint32_t flags
Definition: flow.h:374
#define PKT_STREAM_EST
Definition: decode.h:1090
#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