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