Coverage Report

Created: 2026-02-14 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/app-layer-modbus.c
Line
Count
Source
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
41
#include "app-layer-parser.h"
42
#include "app-layer-modbus.h"
43
44
void ModbusParserRegisterTests(void);
45
46
/**
47
 * \brief Function to register the Modbus protocol parser
48
 */
49
void RegisterModbusParsers(void)
50
74
{
51
74
    rs_modbus_register_parser();
52
#ifdef UNITTESTS
53
    AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_MODBUS, ModbusParserRegisterTests);
54
#endif
55
56
74
    SCReturn;
57
74
}
58
59
/* UNITTESTS */
60
#ifdef UNITTESTS
61
#include "detect.h"
62
#include "detect-engine.h"
63
#include "detect-parse.h"
64
#include "detect-engine-build.h"
65
#include "detect-engine-alert.h"
66
67
#include "flow-util.h"
68
69
#include "util-unittest.h"
70
#include "util-unittest-helper.h"
71
72
#include "stream-tcp.h"
73
#include "stream-tcp-private.h"
74
75
#include "rust.h"
76
77
/* Modbus default stream reassembly depth */
78
#define MODBUS_CONFIG_DEFAULT_STREAM_DEPTH 0
79
80
/* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
81
static uint8_t invalidFunctionCode[] = {
82
    /* Transaction ID */ 0x00, 0x00,
83
    /* Protocol ID */ 0x00, 0x00,
84
    /* Length */ 0x00, 0x02,
85
    /* Unit ID */ 0x00,
86
    /* Function code */ 0x00
87
};
88
89
/* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
90
/* Example of a request to read discrete outputs 20-38 */
91
static uint8_t readCoilsReq[] = {/* Transaction ID */    0x00, 0x00,
92
                                 /* Protocol ID */       0x00, 0x00,
93
                                 /* Length */            0x00, 0x06,
94
                                 /* Unit ID */           0x00,
95
                                 /* Function code */     0x01,
96
                                 /* Starting Address */  0x78, 0x90,
97
                                 /* Quantity of coils */ 0x00, 0x13 };
98
99
static uint8_t readCoilsRsp[] = {/* Transaction ID */    0x00, 0x00,
100
                                 /* Protocol ID */       0x00, 0x00,
101
                                 /* Length */            0x00, 0x06,
102
                                 /* Unit ID */           0x00,
103
                                 /* Function code */     0x01,
104
                                 /* Byte count */        0x03,
105
                                 /* Coil Status */       0xCD, 0x6B, 0x05 };
106
107
static uint8_t readCoilsErrorRsp[] = {
108
    /* Transaction ID */ 0x00, 0x00,
109
    /* Protocol ID */ 0x00, 0x00,
110
    /* Length */ 0x00, 0x03,
111
    /* Unit ID */ 0x00,
112
    /* Function code */ 0x81,
113
    /* Invalid Exception code: should trigger the InvalidExceptionCode ModbusEvent */
114
    0xFF
115
};
116
117
/* Modbus Application Protocol Specification V1.1b3 6.6: Write Single register */
118
/* Example of a request to write register 2 to 00 03 hex */
119
static uint8_t writeSingleRegisterReq[] = {/* Transaction ID */     0x00, 0x0A,
120
                                           /* Protocol ID */        0x00, 0x00,
121
                                           /* Length */             0x00, 0x06,
122
                                           /* Unit ID */            0x00,
123
                                           /* Function code */      0x06,
124
                                           /* Register Address */   0x00, 0x01,
125
                                           /* Register Value */     0x00, 0x03};
126
127
static uint8_t invalidWriteSingleRegisterReq[] = {/* Transaction ID */      0x00, 0x0A,
128
                                                  /* Protocol ID */         0x00, 0x00,
129
                                                  /* Length */              0x00, 0x04,
130
                                                  /* Unit ID */             0x00,
131
                                                  /* Function code */       0x06,
132
                                                  /* Register Address */    0x00, 0x01};
133
134
static uint8_t writeSingleRegisterRsp[] = {/* Transaction ID */         0x00, 0x0A,
135
                                           /* Protocol ID */            0x00, 0x00,
136
                                           /* Length */                 0x00, 0x06,
137
                                           /* Unit ID */                0x00,
138
                                           /* Function code */          0x06,
139
                                           /* Register Address */       0x00, 0x01,
140
                                           /* Register Value */         0x00, 0x03};
141
142
/* Modbus Application Protocol Specification V1.1b3 6.12: Write Multiple registers */
143
/* Example of a request to write two registers starting at 2 to 00 0A and 01 02 hex */
144
static uint8_t writeMultipleRegistersReq[] = {/* Transaction ID */          0x00, 0x0A,
145
                                              /* Protocol ID */             0x00, 0x00,
146
                                              /* Length */                  0x00, 0x0B,
147
                                              /* Unit ID */                 0x00,
148
                                              /* Function code */           0x10,
149
                                              /* Starting Address */        0x00, 0x01,
150
                                              /* Quantity of Registers */   0x00, 0x02,
151
                                              /* Byte count */              0x04,
152
                                              /* Registers Value */         0x00, 0x0A,
153
                                                                            0x01, 0x02};
154
155
static uint8_t writeMultipleRegistersRsp[] = {/* Transaction ID */          0x00, 0x0A,
156
                                              /* Protocol ID */             0x00, 0x00,
157
                                              /* Length */                  0x00, 0x06,
158
                                              /* Unit ID */                 0x00,
159
                                              /* Function code */           0x10,
160
                                              /* Starting Address */        0x00, 0x01,
161
                                              /* Quantity of Registers */   0x00, 0x02};
162
163
/* Modbus Application Protocol Specification V1.1b3 6.16: Mask Write Register */
164
/* Example of a request to mask write to register 5 */
165
static uint8_t maskWriteRegisterReq[] = {/* Transaction ID */       0x00, 0x0A,
166
                                         /* Protocol ID */          0x00, 0x00,
167
                                         /* Length */               0x00, 0x08,
168
                                         /* Unit ID */              0x00,
169
                                         /* Function code */        0x16,
170
                                         /* Reference Address */    0x00, 0x04,
171
                                         /* And_Mask */             0x00, 0xF2,
172
                                         /* Or_Mask */              0x00, 0x25};
173
174
static uint8_t invalidMaskWriteRegisterReq[] = {/* Transaction ID */    0x00, 0x0A,
175
                                                /* Protocol ID */       0x00, 0x00,
176
                                                /* Length */            0x00, 0x06,
177
                                                /* Unit ID */           0x00,
178
                                                /* Function code */     0x16,
179
                                                /* Reference Address */ 0x00, 0x04,
180
                                                /* And_Mask */          0x00, 0xF2};
181
182
static uint8_t maskWriteRegisterRsp[] = {/* Transaction ID */       0x00, 0x0A,
183
                                         /* Protocol ID */          0x00, 0x00,
184
                                         /* Length */               0x00, 0x08,
185
                                         /* Unit ID */              0x00,
186
                                         /* Function code */        0x16,
187
                                         /* Reference Address */    0x00, 0x04,
188
                                         /* And_Mask */             0x00, 0xF2,
189
                                         /* Or_Mask */              0x00, 0x25};
190
191
/* Modbus Application Protocol Specification V1.1b3 6.17: Read/Write Multiple registers */
192
/* Example of a request to read six registers starting at register 4, */
193
/* and to write three registers starting at register 15 */
194
static uint8_t readWriteMultipleRegistersReq[] = {/* Transaction ID */          0x12, 0x34,
195
                                                  /* Protocol ID */             0x00, 0x00,
196
                                                  /* Length */                  0x00, 0x11,
197
                                                  /* Unit ID */                 0x00,
198
                                                  /* Function code */           0x17,
199
                                                  /* Read Starting Address */   0x00, 0x03,
200
                                                  /* Quantity to Read */        0x00, 0x06,
201
                                                  /* Write Starting Address */  0x00, 0x0E,
202
                                                  /* Quantity to Write */       0x00, 0x03,
203
                                                  /* Write Byte count */        0x06,
204
                                                  /* Write Registers Value */   0x12, 0x34,
205
                                                                                0x56, 0x78,
206
                                                                                0x9A, 0xBC};
207
208
/* Mismatch value in Byte count 0x0B instead of 0x0C */
209
static uint8_t readWriteMultipleRegistersRsp[] = {/* Transaction ID */          0x12, 0x34,
210
                                                  /* Protocol ID */             0x00, 0x00,
211
                                                  /* Length */                  0x00, 0x0E,
212
                                                  /* Unit ID */                 0x00,
213
                                                  /* Function code */           0x17,
214
                                                  /* Byte count */              0x0B,
215
                                                  /* Read Registers Value */    0x00, 0xFE,
216
                                                                                0x0A, 0xCD,
217
                                                                                0x00, 0x01,
218
                                                                                0x00, 0x03,
219
                                                                                0x00, 0x0D,
220
                                                                                0x00};
221
222
/* Modbus Application Protocol Specification V1.1b3 6.8.1: 04 Force Listen Only Mode */
223
/* Example of a request to to remote device to its Listen Only Mode for Modbus Communications. */
224
static uint8_t forceListenOnlyMode[] = {/* Transaction ID */     0x0A, 0x00,
225
                                        /* Protocol ID */        0x00, 0x00,
226
                                        /* Length */             0x00, 0x06,
227
                                        /* Unit ID */            0x00,
228
                                        /* Function code */      0x08,
229
                                        /* Sub-function code */  0x00, 0x04,
230
                                        /* Data */               0x00, 0x00};
231
232
static uint8_t invalidProtocolIdReq[] = {/* Transaction ID */    0x00, 0x00,
233
                                         /* Protocol ID */       0x00, 0x01,
234
                                         /* Length */            0x00, 0x06,
235
                                         /* Unit ID */           0x00,
236
                                         /* Function code */     0x01,
237
                                         /* Starting Address */  0x78, 0x90,
238
                                         /* Quantity of coils */ 0x00, 0x13 };
239
240
static uint8_t invalidLengthWriteMultipleRegistersReq[] = {
241
                                              /* Transaction ID */          0x00, 0x0A,
242
                                              /* Protocol ID */             0x00, 0x00,
243
                                              /* Length */                  0x00, 0x09,
244
                                              /* Unit ID */                 0x00,
245
                                              /* Function code */           0x10,
246
                                              /* Starting Address */        0x00, 0x01,
247
                                              /* Quantity of Registers */   0x00, 0x02,
248
                                              /* Byte count */              0x04,
249
                                              /* Registers Value */         0x00, 0x0A,
250
                                                                            0x01, 0x02};
251
252
static uint8_t exceededLengthWriteMultipleRegistersReq[] = {
253
                                              /* Transaction ID */          0x00, 0x0A,
254
                                              /* Protocol ID */             0x00, 0x00,
255
                                              /* Length */                  0xff, 0xfa,
256
                                              /* Unit ID */                 0x00,
257
                                              /* Function code */           0x10,
258
                                              /* Starting Address */        0x00, 0x01,
259
                                              /* Quantity of Registers */   0x7f, 0xf9,
260
                                              /* Byte count */              0xff};
261
262
static uint8_t invalidLengthPDUWriteMultipleRegistersReq[] = {
263
                                              /* Transaction ID */          0x00, 0x0A,
264
                                              /* Protocol ID */             0x00, 0x00,
265
                                              /* Length */                  0x00, 0x02,
266
                                              /* Unit ID */                 0x00,
267
                                              /* Function code */           0x10};
268
269
/** \test Send Modbus Read Coils request/response. */
270
static int ModbusParserTest01(void) {
271
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
272
    Flow f;
273
    TcpSession ssn;
274
275
    FAIL_IF_NULL(alp_tctx);
276
277
    memset(&f, 0, sizeof(f));
278
    memset(&ssn, 0, sizeof(ssn));
279
280
    FLOW_INITIALIZE(&f);
281
    f.protoctx  = (void *)&ssn;
282
    f.proto     = IPPROTO_TCP;
283
    f.alproto   = ALPROTO_MODBUS;
284
285
    StreamTcpInitConfig(true);
286
287
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
288
                                STREAM_TOSERVER, readCoilsReq,
289
                                sizeof(readCoilsReq));
290
    FAIL_IF_NOT(r == 0);
291
292
    ModbusState *modbus_state = f.alstate;
293
    FAIL_IF_NULL(modbus_state);
294
295
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
296
    FAIL_IF_NULL(request._0);
297
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 1);
298
    FAIL_IF_NOT(rs_modbus_message_get_read_request_address(&request) == 0x7890);
299
    FAIL_IF_NOT(rs_modbus_message_get_read_request_quantity(&request) == 19);
300
301
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
302
                            STREAM_TOCLIENT, readCoilsRsp,
303
                            sizeof(readCoilsRsp));
304
    FAIL_IF_NOT(r == 0);
305
306
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
307
308
    AppLayerParserThreadCtxFree(alp_tctx);
309
    StreamTcpFreeConfig(true);
310
    FLOW_DESTROY(&f);
311
    PASS;
312
}
313
314
/** \test Send Modbus Write Multiple registers request/response. */
315
static int ModbusParserTest02(void) {
316
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
317
    Flow f;
318
    TcpSession ssn;
319
320
    FAIL_IF_NULL(alp_tctx);
321
322
    memset(&f, 0, sizeof(f));
323
    memset(&ssn, 0, sizeof(ssn));
324
325
    FLOW_INITIALIZE(&f);
326
    f.protoctx  = (void *)&ssn;
327
    f.proto     = IPPROTO_TCP;
328
    f.alproto   = ALPROTO_MODBUS;
329
330
    StreamTcpInitConfig(true);
331
332
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
333
                                STREAM_TOSERVER, writeMultipleRegistersReq,
334
                                sizeof(writeMultipleRegistersReq));
335
    FAIL_IF_NOT(r == 0);
336
337
    ModbusState *modbus_state = f.alstate;
338
    FAIL_IF_NULL(modbus_state);
339
340
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
341
    FAIL_IF_NULL(request._0);
342
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 16);
343
    FAIL_IF_NOT(rs_modbus_message_get_write_multreq_address(&request) == 0x01);
344
    FAIL_IF_NOT(rs_modbus_message_get_write_multreq_quantity(&request) == 2);
345
346
    size_t data_len;
347
    const uint8_t *data = rs_modbus_message_get_write_multreq_data(&request, &data_len);
348
    FAIL_IF_NOT(data_len == 4);
349
    FAIL_IF_NOT(data[0] == 0x00);
350
    FAIL_IF_NOT(data[1] == 0x0A);
351
    FAIL_IF_NOT(data[2] == 0x01);
352
    FAIL_IF_NOT(data[3] == 0x02);
353
354
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
355
                            STREAM_TOCLIENT, writeMultipleRegistersRsp,
356
                            sizeof(writeMultipleRegistersRsp));
357
    FAIL_IF_NOT(r == 0);
358
359
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
360
361
    AppLayerParserThreadCtxFree(alp_tctx);
362
    StreamTcpFreeConfig(true);
363
    FLOW_DESTROY(&f);
364
    PASS;
365
}
366
367
/** \test Send Modbus Read/Write Multiple registers request/response with mismatch value. */
368
static int ModbusParserTest03(void) {
369
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
370
    DetectEngineThreadCtx *det_ctx = NULL;
371
    Flow f;
372
    Packet *p = NULL;
373
    Signature *s = NULL;
374
    TcpSession ssn;
375
    ThreadVars tv;
376
377
    FAIL_IF_NULL(alp_tctx);
378
379
    memset(&tv, 0, sizeof(ThreadVars));
380
    memset(&f, 0, sizeof(Flow));
381
    memset(&ssn, 0, sizeof(TcpSession));
382
383
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
384
385
    FLOW_INITIALIZE(&f);
386
    f.alproto   = ALPROTO_MODBUS;
387
    f.protoctx  = (void *)&ssn;
388
    f.proto     = IPPROTO_TCP;
389
    f.alproto   = ALPROTO_MODBUS;
390
    f.flags     |= FLOW_IPV4;
391
392
    p->flow         = &f;
393
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
394
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
395
396
    StreamTcpInitConfig(true);
397
398
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
399
    FAIL_IF_NULL(de_ctx);
400
401
    de_ctx->flags |= DE_QUIET;
402
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
403
                                      "(msg:\"Modbus Data mismatch\"; "
404
                                      "app-layer-event: "
405
                                      "modbus.value_mismatch; "
406
                                      "sid:1;)");
407
    FAIL_IF_NULL(s);
408
409
    SigGroupBuild(de_ctx);
410
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
411
412
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
413
                                STREAM_TOSERVER,
414
                                readWriteMultipleRegistersReq,
415
                                sizeof(readWriteMultipleRegistersReq));
416
    FAIL_IF_NOT(r == 0);
417
418
    ModbusState *modbus_state = f.alstate;
419
    FAIL_IF_NULL(modbus_state);
420
421
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
422
    FAIL_IF_NULL(request._0);
423
424
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 23);
425
    FAIL_IF_NOT(rs_modbus_message_get_rw_multreq_read_address(&request) == 0x03);
426
    FAIL_IF_NOT(rs_modbus_message_get_rw_multreq_read_quantity(&request) == 6);
427
    FAIL_IF_NOT(rs_modbus_message_get_rw_multreq_write_address(&request) == 0x0E);
428
    FAIL_IF_NOT(rs_modbus_message_get_rw_multreq_write_quantity(&request) == 3);
429
430
    size_t data_len;
431
    uint8_t const *data = rs_modbus_message_get_rw_multreq_write_data(&request, &data_len);
432
    FAIL_IF_NOT(data_len == 6);
433
    FAIL_IF_NOT(data[0] == 0x12);
434
    FAIL_IF_NOT(data[1] == 0x34);
435
    FAIL_IF_NOT(data[2] == 0x56);
436
    FAIL_IF_NOT(data[3] == 0x78);
437
    FAIL_IF_NOT(data[4] == 0x9A);
438
    FAIL_IF_NOT(data[5] == 0xBC);
439
440
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
441
                            STREAM_TOCLIENT, readWriteMultipleRegistersRsp,
442
                            sizeof(readWriteMultipleRegistersRsp));
443
    FAIL_IF_NOT(r == 0);
444
445
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
446
447
    /* do detect */
448
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
449
450
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
451
452
    SigGroupCleanup(de_ctx);
453
    SigCleanSignatures(de_ctx);
454
455
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
456
    DetectEngineCtxFree(de_ctx);
457
458
    AppLayerParserThreadCtxFree(alp_tctx);
459
    StreamTcpFreeConfig(true);
460
    FLOW_DESTROY(&f);
461
    UTHFreePackets(&p, 1);
462
    PASS;
463
}
464
465
/** \test Send Modbus Force Listen Only Mode request. */
466
static int ModbusParserTest04(void) {
467
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
468
    Flow f;
469
    TcpSession ssn;
470
471
    FAIL_IF_NULL(alp_tctx);
472
473
    memset(&f, 0, sizeof(f));
474
    memset(&ssn, 0, sizeof(ssn));
475
476
    FLOW_INITIALIZE(&f);
477
    f.protoctx  = (void *)&ssn;
478
    f.proto     = IPPROTO_TCP;
479
    f.alproto   = ALPROTO_MODBUS;
480
481
    StreamTcpInitConfig(true);
482
483
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
484
                                STREAM_TOSERVER, forceListenOnlyMode,
485
                                sizeof(forceListenOnlyMode));
486
    FAIL_IF_NOT(r == 0);
487
488
    ModbusState *modbus_state = f.alstate;
489
    FAIL_IF_NULL(modbus_state);
490
491
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
492
    FAIL_IF_NULL(request._0);
493
494
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 8);
495
    FAIL_IF_NOT(rs_modbus_message_get_subfunction(&request) == 4);
496
497
    AppLayerParserThreadCtxFree(alp_tctx);
498
    StreamTcpFreeConfig(true);
499
    FLOW_DESTROY(&f);
500
    PASS;
501
}
502
503
/** \test Send Modbus invalid Protocol version in request. */
504
static int ModbusParserTest05(void) {
505
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
506
    DetectEngineThreadCtx *det_ctx = NULL;
507
    Flow f;
508
    Packet *p = NULL;
509
    Signature *s = NULL;
510
    TcpSession ssn;
511
    ThreadVars tv;
512
513
    FAIL_IF_NULL(alp_tctx);
514
515
    memset(&tv, 0, sizeof(ThreadVars));
516
    memset(&f, 0, sizeof(Flow));
517
    memset(&ssn, 0, sizeof(TcpSession));
518
519
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
520
521
    FLOW_INITIALIZE(&f);
522
    f.alproto   = ALPROTO_MODBUS;
523
    f.protoctx  = (void *)&ssn;
524
    f.proto     = IPPROTO_TCP;
525
    f.alproto   = ALPROTO_MODBUS;
526
    f.flags     |= FLOW_IPV4;
527
528
    p->flow         = &f;
529
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
530
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
531
532
    StreamTcpInitConfig(true);
533
534
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
535
    FAIL_IF_NULL(de_ctx);
536
537
    de_ctx->flags |= DE_QUIET;
538
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
539
                                      "(msg:\"Modbus invalid Protocol version\"; "
540
                                      "app-layer-event: "
541
                                      "modbus.invalid_protocol_id; "
542
                                      "sid:1;)");
543
    FAIL_IF_NULL(s);
544
545
    SigGroupBuild(de_ctx);
546
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
547
548
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
549
                                STREAM_TOSERVER, invalidProtocolIdReq,
550
                                sizeof(invalidProtocolIdReq));
551
    FAIL_IF_NOT(r == 0);
552
553
    ModbusState *modbus_state = f.alstate;
554
    FAIL_IF_NULL(modbus_state);
555
556
    /* do detect */
557
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
558
559
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
560
561
    SigGroupCleanup(de_ctx);
562
    SigCleanSignatures(de_ctx);
563
564
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
565
    DetectEngineCtxFree(de_ctx);
566
567
    AppLayerParserThreadCtxFree(alp_tctx);
568
    StreamTcpFreeConfig(true);
569
    FLOW_DESTROY(&f);
570
    UTHFreePackets(&p, 1);
571
    PASS;
572
}
573
574
/** \test Send Modbus unsolicited response. */
575
static int ModbusParserTest06(void) {
576
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
577
    DetectEngineThreadCtx *det_ctx = NULL;
578
    Flow f;
579
    Packet *p = NULL;
580
    Signature *s = NULL;
581
    TcpSession ssn;
582
    ThreadVars tv;
583
584
    FAIL_IF_NULL(alp_tctx);
585
586
    memset(&tv, 0, sizeof(ThreadVars));
587
    memset(&f, 0, sizeof(Flow));
588
    memset(&ssn, 0, sizeof(TcpSession));
589
590
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
591
592
    FLOW_INITIALIZE(&f);
593
    f.alproto   = ALPROTO_MODBUS;
594
    f.protoctx  = (void *)&ssn;
595
    f.proto     = IPPROTO_TCP;
596
    f.alproto   = ALPROTO_MODBUS;
597
    f.flags     |= FLOW_IPV4;
598
599
    p->flow         = &f;
600
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
601
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
602
603
    StreamTcpInitConfig(true);
604
605
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
606
    FAIL_IF_NULL(de_ctx);
607
608
    de_ctx->flags |= DE_QUIET;
609
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
610
                                      "(msg:\"Modbus unsolicited response\"; "
611
                                      "app-layer-event: "
612
                                      "modbus.unsolicited_response; "
613
                                      "sid:1;)");
614
    FAIL_IF_NULL(s);
615
616
    SigGroupBuild(de_ctx);
617
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
618
619
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
620
                                STREAM_TOCLIENT, readCoilsRsp,
621
                                sizeof(readCoilsRsp));
622
    FAIL_IF_NOT(r == 0);
623
624
    ModbusState *modbus_state = f.alstate;
625
    FAIL_IF_NULL(modbus_state);
626
627
    /* do detect */
628
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
629
630
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
631
632
    SigGroupCleanup(de_ctx);
633
    SigCleanSignatures(de_ctx);
634
635
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
636
    DetectEngineCtxFree(de_ctx);
637
638
    AppLayerParserThreadCtxFree(alp_tctx);
639
    StreamTcpFreeConfig(true);
640
    FLOW_DESTROY(&f);
641
    UTHFreePackets(&p, 1);
642
    PASS;
643
}
644
645
/** \test Send Modbus invalid Length request. */
646
static int ModbusParserTest07(void) {
647
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
648
    DetectEngineThreadCtx *det_ctx = NULL;
649
    Flow f;
650
    Packet *p = NULL;
651
    Signature *s = NULL;
652
    TcpSession ssn;
653
    ThreadVars tv;
654
655
    FAIL_IF_NULL(alp_tctx);
656
657
    memset(&tv, 0, sizeof(ThreadVars));
658
    memset(&f, 0, sizeof(Flow));
659
    memset(&ssn, 0, sizeof(TcpSession));
660
661
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
662
663
    FLOW_INITIALIZE(&f);
664
    f.alproto   = ALPROTO_MODBUS;
665
    f.protoctx  = (void *)&ssn;
666
    f.proto     = IPPROTO_TCP;
667
    f.alproto   = ALPROTO_MODBUS;
668
    f.flags     |= FLOW_IPV4;
669
670
    p->flow         = &f;
671
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
672
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
673
674
    StreamTcpInitConfig(true);
675
676
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
677
    FAIL_IF_NULL(de_ctx);
678
679
    de_ctx->flags |= DE_QUIET;
680
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
681
                                      "(msg:\"Modbus invalid Length\"; "
682
                                      "app-layer-event: "
683
                                      "modbus.invalid_length; "
684
                                      "sid:1;)");
685
    FAIL_IF_NULL(s);
686
687
    SigGroupBuild(de_ctx);
688
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
689
690
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
691
                                STREAM_TOSERVER,
692
                                invalidLengthWriteMultipleRegistersReq,
693
                                sizeof(invalidLengthWriteMultipleRegistersReq));
694
    FAIL_IF_NOT(r == 1);
695
696
    ModbusState *modbus_state = f.alstate;
697
    FAIL_IF_NULL(modbus_state);
698
699
    /* do detect */
700
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
701
702
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
703
704
    SigGroupCleanup(de_ctx);
705
    SigCleanSignatures(de_ctx);
706
707
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
708
    DetectEngineCtxFree(de_ctx);
709
710
    AppLayerParserThreadCtxFree(alp_tctx);
711
    StreamTcpFreeConfig(true);
712
    FLOW_DESTROY(&f);
713
    UTHFreePackets(&p, 1);
714
    PASS;
715
}
716
717
/** \test Send Modbus Read Coils request and error response with Exception code invalid. */
718
static int ModbusParserTest08(void) {
719
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
720
    DetectEngineThreadCtx *det_ctx = NULL;
721
    Flow f;
722
    Packet *p = NULL;
723
    Signature *s = NULL;
724
    TcpSession ssn;
725
    ThreadVars tv;
726
727
    FAIL_IF_NULL(alp_tctx);
728
729
    memset(&tv, 0, sizeof(ThreadVars));
730
    memset(&f, 0, sizeof(Flow));
731
    memset(&ssn, 0, sizeof(TcpSession));
732
733
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
734
735
    FLOW_INITIALIZE(&f);
736
    f.alproto   = ALPROTO_MODBUS;
737
    f.protoctx  = (void *)&ssn;
738
    f.proto     = IPPROTO_TCP;
739
    f.alproto   = ALPROTO_MODBUS;
740
    f.flags     |= FLOW_IPV4;
741
742
    p->flow         = &f;
743
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
744
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
745
746
    StreamTcpInitConfig(true);
747
748
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
749
    FAIL_IF_NULL(de_ctx);
750
751
    de_ctx->flags |= DE_QUIET;
752
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
753
                                      "(msg:\"Modbus Exception code invalid\"; "
754
                                      "app-layer-event: "
755
                                      "modbus.invalid_exception_code; "
756
                                      "sid:1;)");
757
    FAIL_IF_NULL(s);
758
759
    SigGroupBuild(de_ctx);
760
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
761
762
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
763
                                STREAM_TOSERVER, readCoilsReq,
764
                                sizeof(readCoilsReq));
765
    FAIL_IF_NOT(r == 0);
766
767
    ModbusState *modbus_state = f.alstate;
768
    FAIL_IF_NULL(modbus_state);
769
770
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
771
    FAIL_IF_NULL(request._0);
772
773
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 1);
774
    FAIL_IF_NOT(rs_modbus_message_get_read_request_address(&request) == 0x7890);
775
    FAIL_IF_NOT(rs_modbus_message_get_read_request_quantity(&request) == 19);
776
777
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
778
                            STREAM_TOCLIENT, readCoilsErrorRsp,
779
                            sizeof(readCoilsErrorRsp));
780
    FAIL_IF_NOT(r == 0);
781
782
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
783
784
    /* do detect */
785
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
786
787
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
788
789
    SigGroupCleanup(de_ctx);
790
    SigCleanSignatures(de_ctx);
791
792
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
793
    DetectEngineCtxFree(de_ctx);
794
795
    AppLayerParserThreadCtxFree(alp_tctx);
796
    StreamTcpFreeConfig(true);
797
    FLOW_DESTROY(&f);
798
    UTHFreePackets(&p, 1);
799
    PASS;
800
}
801
802
/** \test Modbus fragmentation - 1 ADU over 2 TCP packets. */
803
static int ModbusParserTest09(void) {
804
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
805
    Flow f;
806
    TcpSession ssn;
807
808
    uint32_t    input_len = sizeof(readCoilsReq), part2_len = 3;
809
    uint8_t     *input = readCoilsReq;
810
811
    FAIL_IF_NULL(alp_tctx);
812
813
    memset(&f, 0, sizeof(f));
814
    memset(&ssn, 0, sizeof(ssn));
815
816
    FLOW_INITIALIZE(&f);
817
    f.protoctx  = (void *)&ssn;
818
    f.proto     = IPPROTO_TCP;
819
    f.alproto   = ALPROTO_MODBUS;
820
821
    StreamTcpInitConfig(true);
822
823
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
824
                                STREAM_TOSERVER, input, input_len - part2_len);
825
    FAIL_IF_NOT(r == 1);
826
827
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
828
                            STREAM_TOSERVER, input, input_len);
829
    FAIL_IF_NOT(r == 0);
830
831
    ModbusState *modbus_state = f.alstate;
832
    FAIL_IF_NULL(modbus_state);
833
834
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
835
    FAIL_IF_NULL(request._0);
836
837
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 1);
838
    FAIL_IF_NOT(rs_modbus_message_get_read_request_address(&request) == 0x7890);
839
    FAIL_IF_NOT(rs_modbus_message_get_read_request_quantity(&request) == 19);
840
841
    input_len = sizeof(readCoilsRsp);
842
    part2_len = 10;
843
    input = readCoilsRsp;
844
845
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
846
                            STREAM_TOCLIENT, input, input_len - part2_len);
847
    FAIL_IF_NOT(r == 1);
848
849
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
850
                            STREAM_TOCLIENT, input, input_len);
851
    FAIL_IF_NOT(r == 0);
852
853
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
854
855
    AppLayerParserThreadCtxFree(alp_tctx);
856
    StreamTcpFreeConfig(true);
857
    FLOW_DESTROY(&f);
858
    PASS;
859
}
860
861
/** \test Modbus fragmentation - 2 ADU in 1 TCP packet. */
862
static int ModbusParserTest10(void) {
863
    uint32_t    input_len = sizeof(readCoilsReq) + sizeof(writeMultipleRegistersReq);
864
    uint8_t     *input, *ptr;
865
866
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
867
    Flow f;
868
    TcpSession ssn;
869
870
    FAIL_IF_NULL(alp_tctx);
871
872
    input  = (uint8_t *) SCMalloc (input_len * sizeof(uint8_t));
873
    FAIL_IF_NULL(input);
874
875
    memcpy(input, readCoilsReq, sizeof(readCoilsReq));
876
    memcpy(input + sizeof(readCoilsReq), writeMultipleRegistersReq, sizeof(writeMultipleRegistersReq));
877
878
    memset(&f, 0, sizeof(f));
879
    memset(&ssn, 0, sizeof(ssn));
880
881
    FLOW_INITIALIZE(&f);
882
    f.protoctx  = (void *)&ssn;
883
    f.proto     = IPPROTO_TCP;
884
    f.alproto   = ALPROTO_MODBUS;
885
886
    StreamTcpInitConfig(true);
887
888
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
889
                                STREAM_TOSERVER, input, input_len);
890
    FAIL_IF_NOT(r == 0);
891
892
    ModbusState *modbus_state = f.alstate;
893
    FAIL_IF_NULL(modbus_state);
894
895
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 2);
896
897
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 1);
898
    FAIL_IF_NULL(request._0);
899
900
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 16);
901
    FAIL_IF_NOT(rs_modbus_message_get_write_multreq_address(&request) == 0x01);
902
    FAIL_IF_NOT(rs_modbus_message_get_write_multreq_quantity(&request) == 2);
903
904
    size_t data_len;
905
    uint8_t const *data = rs_modbus_message_get_write_multreq_data(&request, &data_len);
906
    FAIL_IF_NOT(data_len == 4);
907
    FAIL_IF_NOT(data[0] == 0x00);
908
    FAIL_IF_NOT(data[1] == 0x0A);
909
    FAIL_IF_NOT(data[2] == 0x01);
910
    FAIL_IF_NOT(data[3] == 0x02);
911
912
    input_len = sizeof(readCoilsRsp) + sizeof(writeMultipleRegistersRsp);
913
914
    ptr = (uint8_t *) SCRealloc (input, input_len * sizeof(uint8_t));
915
    FAIL_IF_NULL(ptr);
916
    input = ptr;
917
918
    memcpy(input, readCoilsRsp, sizeof(readCoilsRsp));
919
    memcpy(input + sizeof(readCoilsRsp), writeMultipleRegistersRsp, sizeof(writeMultipleRegistersRsp));
920
921
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT, input, input_len);
922
    FAIL_IF_NOT(r == 0);
923
924
    SCFree(input);
925
    AppLayerParserThreadCtxFree(alp_tctx);
926
    StreamTcpFreeConfig(true);
927
    FLOW_DESTROY(&f);
928
    PASS;
929
}
930
931
/** \test Send Modbus exceed Length request. */
932
static int ModbusParserTest11(void) {
933
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
934
    DetectEngineThreadCtx *det_ctx = NULL;
935
    Flow f;
936
    Packet *p = NULL;
937
    Signature *s = NULL;
938
    TcpSession ssn;
939
    ThreadVars tv;
940
941
    size_t input_len = 65536;
942
    uint8_t *input = SCCalloc(1, input_len);
943
944
    FAIL_IF(input == NULL);
945
946
    memcpy(input, exceededLengthWriteMultipleRegistersReq,
947
            sizeof(exceededLengthWriteMultipleRegistersReq));
948
949
    FAIL_IF(alp_tctx == NULL);
950
951
    memset(&tv, 0, sizeof(ThreadVars));
952
    memset(&f, 0, sizeof(Flow));
953
    memset(&ssn, 0, sizeof(TcpSession));
954
955
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
956
957
    FLOW_INITIALIZE(&f);
958
    f.alproto   = ALPROTO_MODBUS;
959
    f.protoctx  = (void *)&ssn;
960
    f.proto     = IPPROTO_TCP;
961
    f.alproto   = ALPROTO_MODBUS;
962
    f.flags     |= FLOW_IPV4;
963
964
    p->flow         = &f;
965
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
966
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
967
968
    StreamTcpInitConfig(true);
969
970
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
971
    FAIL_IF_NULL(de_ctx);
972
973
    de_ctx->flags |= DE_QUIET;
974
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
975
                                      "(msg:\"Modbus invalid Length\"; "
976
                                      "app-layer-event: "
977
                                      "modbus.invalid_length; "
978
                                      "sid:1;)");
979
    FAIL_IF_NULL(s);
980
981
    SigGroupBuild(de_ctx);
982
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
983
984
    int r = AppLayerParserParse(
985
            NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER, input, input_len);
986
    FAIL_IF_NOT(r == 0);
987
988
    ModbusState *modbus_state = f.alstate;
989
    FAIL_IF_NULL(modbus_state);
990
991
    /* do detect */
992
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
993
994
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
995
996
    SigGroupCleanup(de_ctx);
997
    SigCleanSignatures(de_ctx);
998
999
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1000
    DetectEngineCtxFree(de_ctx);
1001
1002
    AppLayerParserThreadCtxFree(alp_tctx);
1003
    StreamTcpFreeConfig(true);
1004
    FLOW_DESTROY(&f);
1005
    UTHFreePackets(&p, 1);
1006
    PASS;
1007
}
1008
1009
/** \test Send Modbus invalid PDU Length. */
1010
static int ModbusParserTest12(void) {
1011
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1012
    DetectEngineThreadCtx *det_ctx = NULL;
1013
    Flow f;
1014
    Packet *p = NULL;
1015
    Signature *s = NULL;
1016
    TcpSession ssn;
1017
    ThreadVars tv;
1018
1019
    FAIL_IF_NULL(alp_tctx);
1020
1021
    memset(&tv, 0, sizeof(ThreadVars));
1022
    memset(&f, 0, sizeof(Flow));
1023
    memset(&ssn, 0, sizeof(TcpSession));
1024
1025
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1026
1027
    FLOW_INITIALIZE(&f);
1028
    f.alproto   = ALPROTO_MODBUS;
1029
    f.protoctx  = (void *)&ssn;
1030
    f.proto     = IPPROTO_TCP;
1031
    f.alproto   = ALPROTO_MODBUS;
1032
    f.flags     |= FLOW_IPV4;
1033
1034
    p->flow         = &f;
1035
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
1036
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
1037
1038
    StreamTcpInitConfig(true);
1039
1040
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1041
    FAIL_IF_NULL(de_ctx);
1042
1043
    de_ctx->flags |= DE_QUIET;
1044
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
1045
                                      "(msg:\"Modbus invalid Length\"; "
1046
                                      "app-layer-event: "
1047
                                      "modbus.invalid_length; "
1048
                                      "sid:1;)");
1049
    FAIL_IF_NULL(s);
1050
1051
    SigGroupBuild(de_ctx);
1052
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1053
1054
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1055
                                STREAM_TOSERVER,
1056
                                invalidLengthPDUWriteMultipleRegistersReq,
1057
                                sizeof(invalidLengthPDUWriteMultipleRegistersReq));
1058
    FAIL_IF_NOT(r == 0);
1059
1060
    ModbusState *modbus_state = f.alstate;
1061
    FAIL_IF_NULL(modbus_state);
1062
1063
    /* do detect */
1064
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1065
1066
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1067
1068
    SigGroupCleanup(de_ctx);
1069
    SigCleanSignatures(de_ctx);
1070
1071
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1072
    DetectEngineCtxFree(de_ctx);
1073
1074
    AppLayerParserThreadCtxFree(alp_tctx);
1075
    StreamTcpFreeConfig(true);
1076
    FLOW_DESTROY(&f);
1077
    UTHFreePackets(&p, 1);
1078
    PASS;
1079
}
1080
1081
/** \test Send Modbus Mask Write register request/response. */
1082
static int ModbusParserTest13(void) {
1083
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1084
    Flow f;
1085
    TcpSession ssn;
1086
1087
    FAIL_IF_NULL(alp_tctx);
1088
1089
    memset(&f, 0, sizeof(f));
1090
    memset(&ssn, 0, sizeof(ssn));
1091
1092
    FLOW_INITIALIZE(&f);
1093
    f.protoctx  = (void *)&ssn;
1094
    f.proto     = IPPROTO_TCP;
1095
    f.alproto   = ALPROTO_MODBUS;
1096
1097
    StreamTcpInitConfig(true);
1098
1099
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1100
                                STREAM_TOSERVER, maskWriteRegisterReq,
1101
                                sizeof(maskWriteRegisterReq));
1102
    FAIL_IF_NOT(r == 0);
1103
1104
    ModbusState *modbus_state = f.alstate;
1105
    FAIL_IF_NULL(modbus_state);
1106
1107
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
1108
    FAIL_IF_NULL(request._0);
1109
1110
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 22);
1111
    FAIL_IF_NOT(rs_modbus_message_get_and_mask(&request) == 0x00F2);
1112
    FAIL_IF_NOT(rs_modbus_message_get_or_mask(&request) == 0x0025);
1113
1114
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1115
                            STREAM_TOCLIENT, maskWriteRegisterRsp,
1116
                            sizeof(maskWriteRegisterRsp));
1117
    FAIL_IF_NOT(r == 0);
1118
1119
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
1120
1121
    AppLayerParserThreadCtxFree(alp_tctx);
1122
    StreamTcpFreeConfig(true);
1123
    FLOW_DESTROY(&f);
1124
    PASS;
1125
}
1126
1127
/** \test Send Modbus Write single register request/response. */
1128
static int ModbusParserTest14(void) {
1129
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1130
    Flow f;
1131
    TcpSession ssn;
1132
1133
    FAIL_IF_NULL(alp_tctx);
1134
1135
    memset(&f, 0, sizeof(f));
1136
    memset(&ssn, 0, sizeof(ssn));
1137
1138
    FLOW_INITIALIZE(&f);
1139
    f.protoctx  = (void *)&ssn;
1140
    f.proto     = IPPROTO_TCP;
1141
    f.alproto   = ALPROTO_MODBUS;
1142
1143
    StreamTcpInitConfig(true);
1144
1145
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1146
                                STREAM_TOSERVER, writeSingleRegisterReq,
1147
                                sizeof(writeSingleRegisterReq));
1148
    FAIL_IF_NOT(r == 0);
1149
1150
    ModbusState *modbus_state = f.alstate;
1151
    FAIL_IF_NULL(modbus_state);
1152
1153
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
1154
    FAIL_IF_NULL(request._0);
1155
1156
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 6);
1157
    FAIL_IF_NOT(rs_modbus_message_get_write_address(&request) == 0x0001);
1158
    FAIL_IF_NOT(rs_modbus_message_get_write_data(&request) == 0x0003);
1159
1160
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1161
                            STREAM_TOCLIENT, writeSingleRegisterRsp,
1162
                            sizeof(writeSingleRegisterRsp));
1163
    FAIL_IF_NOT(r == 0);
1164
1165
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
1166
1167
    AppLayerParserThreadCtxFree(alp_tctx);
1168
    StreamTcpFreeConfig(true);
1169
    FLOW_DESTROY(&f);
1170
    PASS;
1171
}
1172
1173
/** \test Send invalid Modbus Mask Write register request. */
1174
static int ModbusParserTest15(void) {
1175
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1176
    DetectEngineThreadCtx *det_ctx = NULL;
1177
    Flow f;
1178
    Packet *p = NULL;
1179
    Signature *s = NULL;
1180
    TcpSession ssn;
1181
    ThreadVars tv;
1182
1183
    FAIL_IF_NULL(alp_tctx);
1184
1185
    memset(&tv, 0, sizeof(ThreadVars));
1186
    memset(&f, 0, sizeof(f));
1187
    memset(&ssn, 0, sizeof(ssn));
1188
1189
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1190
1191
    FLOW_INITIALIZE(&f);
1192
    f.alproto   = ALPROTO_MODBUS;
1193
    f.protoctx  = (void *)&ssn;
1194
    f.proto     = IPPROTO_TCP;
1195
    f.alproto   = ALPROTO_MODBUS;
1196
    f.flags     |= FLOW_IPV4;
1197
1198
    p->flow         = &f;
1199
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
1200
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
1201
1202
    StreamTcpInitConfig(true);
1203
1204
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1205
    FAIL_IF_NULL(de_ctx);
1206
1207
    de_ctx->flags |= DE_QUIET;
1208
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
1209
                                      "(msg:\"Modbus invalid Length\"; "
1210
                                      "app-layer-event: "
1211
                                      "modbus.invalid_length; "
1212
                                      "sid:1;)");
1213
    FAIL_IF_NULL(s);
1214
1215
    SigGroupBuild(de_ctx);
1216
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1217
1218
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1219
                                STREAM_TOSERVER, invalidMaskWriteRegisterReq,
1220
                                sizeof(invalidMaskWriteRegisterReq));
1221
    FAIL_IF_NOT(r == 0);
1222
1223
    ModbusState *modbus_state = f.alstate;
1224
    FAIL_IF_NULL(modbus_state);
1225
1226
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
1227
    FAIL_IF_NULL(request._0);
1228
1229
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 22);
1230
1231
    /* do detect */
1232
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1233
1234
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1235
1236
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1237
                            STREAM_TOCLIENT, maskWriteRegisterRsp,
1238
                            sizeof(maskWriteRegisterRsp));
1239
    FAIL_IF_NOT(r == 0);
1240
1241
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
1242
    ModbusMessage response = rs_modbus_state_get_tx_response(modbus_state, 0);
1243
    FAIL_IF_NULL(response._0);
1244
1245
    FAIL_IF_NOT(rs_modbus_message_get_function(&response) == 22);
1246
1247
    SigGroupCleanup(de_ctx);
1248
    SigCleanSignatures(de_ctx);
1249
1250
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1251
    DetectEngineCtxFree(de_ctx);
1252
1253
    AppLayerParserThreadCtxFree(alp_tctx);
1254
    StreamTcpFreeConfig(true);
1255
    FLOW_DESTROY(&f);
1256
    UTHFreePackets(&p, 1);
1257
    PASS;
1258
}
1259
1260
/** \test Send invalid Modbus Mask Write register request. */
1261
static int ModbusParserTest16(void) {
1262
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1263
    DetectEngineThreadCtx *det_ctx = NULL;
1264
    Flow f;
1265
    Packet *p = NULL;
1266
    Signature *s = NULL;
1267
    TcpSession ssn;
1268
    ThreadVars tv;
1269
1270
    FAIL_IF_NULL(alp_tctx);
1271
1272
    memset(&tv, 0, sizeof(ThreadVars));
1273
    memset(&f, 0, sizeof(f));
1274
    memset(&ssn, 0, sizeof(ssn));
1275
1276
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1277
1278
    FLOW_INITIALIZE(&f);
1279
    f.alproto   = ALPROTO_MODBUS;
1280
    f.protoctx  = (void *)&ssn;
1281
    f.proto     = IPPROTO_TCP;
1282
    f.alproto   = ALPROTO_MODBUS;
1283
    f.flags     |= FLOW_IPV4;
1284
1285
    p->flow         = &f;
1286
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
1287
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
1288
1289
    StreamTcpInitConfig(true);
1290
1291
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1292
    FAIL_IF_NULL(de_ctx);
1293
1294
    de_ctx->flags |= DE_QUIET;
1295
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
1296
                                      "(msg:\"Modbus invalid Length\"; "
1297
                                      "app-layer-event: "
1298
                                      "modbus.invalid_length; "
1299
                                      "sid:1;)");
1300
    FAIL_IF_NULL(s);
1301
1302
    SigGroupBuild(de_ctx);
1303
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1304
1305
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1306
                                STREAM_TOSERVER,
1307
                                invalidWriteSingleRegisterReq,
1308
                                sizeof(invalidWriteSingleRegisterReq));
1309
    FAIL_IF_NOT(r == 0);
1310
1311
    ModbusState *modbus_state = f.alstate;
1312
    FAIL_IF_NULL(modbus_state);
1313
1314
    ModbusMessage request = rs_modbus_state_get_tx_request(modbus_state, 0);
1315
    FAIL_IF_NULL(request._0);
1316
1317
    FAIL_IF_NOT(rs_modbus_message_get_function(&request) == 6);
1318
    size_t data_len;
1319
    const uint8_t *data = rs_modbus_message_get_bytevec_data(&request, &data_len);
1320
    FAIL_IF_NOT(data_len == 2);
1321
    FAIL_IF_NOT(data[0] == 0x00);
1322
    FAIL_IF_NOT(data[1] == 0x01);
1323
1324
    /* do detect */
1325
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1326
1327
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1328
1329
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1330
                            STREAM_TOCLIENT, writeSingleRegisterRsp,
1331
                            sizeof(writeSingleRegisterRsp));
1332
    FAIL_IF_NOT(r == 0);
1333
1334
    FAIL_IF_NOT(rs_modbus_state_get_tx_count(modbus_state) == 1);
1335
    ModbusMessage response = rs_modbus_state_get_tx_response(modbus_state, 0);
1336
    FAIL_IF_NULL(response._0);
1337
1338
    FAIL_IF_NOT(rs_modbus_message_get_function(&response) == 6);
1339
    FAIL_IF_NOT(rs_modbus_message_get_write_address(&response) == 0x0001);
1340
1341
    SigGroupCleanup(de_ctx);
1342
    SigCleanSignatures(de_ctx);
1343
1344
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1345
    DetectEngineCtxFree(de_ctx);
1346
1347
    AppLayerParserThreadCtxFree(alp_tctx);
1348
    StreamTcpFreeConfig(true);
1349
    FLOW_DESTROY(&f);
1350
    UTHFreePackets(&p, 1);
1351
    PASS;}
1352
1353
/** \test Checks if stream_depth is correct */
1354
static int ModbusParserTest17(void) {
1355
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1356
    Flow f;
1357
    TcpSession ssn;
1358
1359
    FAIL_IF_NULL(alp_tctx);
1360
1361
    memset(&f, 0, sizeof(f));
1362
    memset(&ssn, 0, sizeof(ssn));
1363
1364
    FLOW_INITIALIZE(&f);
1365
    f.protoctx  = (void *)&ssn;
1366
    f.proto     = IPPROTO_TCP;
1367
    f.alproto   = ALPROTO_MODBUS;
1368
1369
    StreamTcpInitConfig(true);
1370
1371
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
1372
                                readCoilsReq, sizeof(readCoilsReq));
1373
    FAIL_IF(r != 0);
1374
1375
    FAIL_IF(f.alstate == NULL);
1376
1377
    FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
1378
1379
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
1380
                            readCoilsRsp, sizeof(readCoilsRsp));
1381
    FAIL_IF(r != 0);
1382
1383
    FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
1384
1385
    AppLayerParserThreadCtxFree(alp_tctx);
1386
    StreamTcpFreeConfig(true);
1387
    FLOW_DESTROY(&f);
1388
    PASS;
1389
}
1390
1391
/*/ \test Checks if stream depth is correct over 2 TCP packets */
1392
static int ModbusParserTest18(void) {
1393
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1394
    Flow f;
1395
    TcpSession ssn;
1396
1397
    uint32_t    input_len = sizeof(readCoilsReq), part2_len = 3;
1398
    uint8_t     *input = readCoilsReq;
1399
1400
    FAIL_IF_NULL(alp_tctx);
1401
1402
    memset(&f, 0, sizeof(f));
1403
    memset(&ssn, 0, sizeof(ssn));
1404
1405
    FLOW_INITIALIZE(&f);
1406
    f.protoctx  = (void *)&ssn;
1407
    f.proto     = IPPROTO_TCP;
1408
    f.alproto   = ALPROTO_MODBUS;
1409
1410
    StreamTcpInitConfig(true);
1411
1412
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
1413
                                input, input_len - part2_len);
1414
    FAIL_IF(r != 1);
1415
1416
    FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
1417
1418
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
1419
                            input, input_len);
1420
    FAIL_IF(r != 0);
1421
1422
    FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
1423
1424
    FAIL_IF(f.alstate == NULL);
1425
1426
    input_len = sizeof(readCoilsRsp);
1427
    part2_len = 10;
1428
    input = readCoilsRsp;
1429
1430
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
1431
                            input, input_len - part2_len);
1432
    FAIL_IF(r != 1);
1433
1434
    FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
1435
1436
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOCLIENT,
1437
                            input, input_len);
1438
    FAIL_IF(r != 0);
1439
1440
    FAIL_IF(((TcpSession *)(f.protoctx))->reassembly_depth != MODBUS_CONFIG_DEFAULT_STREAM_DEPTH);
1441
1442
    AppLayerParserThreadCtxFree(alp_tctx);
1443
    StreamTcpFreeConfig(true);
1444
    FLOW_DESTROY(&f);
1445
    PASS;
1446
}
1447
1448
/** \test Send Modbus invalid function. */
1449
static int ModbusParserTest19(void) {
1450
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1451
    DetectEngineThreadCtx *det_ctx = NULL;
1452
    Flow f;
1453
    Packet *p = NULL;
1454
    Signature *s = NULL;
1455
    TcpSession ssn;
1456
    ThreadVars tv;
1457
1458
    FAIL_IF_NULL(alp_tctx);
1459
1460
    memset(&tv, 0, sizeof(ThreadVars));
1461
    memset(&f, 0, sizeof(Flow));
1462
    memset(&ssn, 0, sizeof(TcpSession));
1463
1464
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1465
1466
    FLOW_INITIALIZE(&f);
1467
    f.alproto   = ALPROTO_MODBUS;
1468
    f.protoctx  = (void *)&ssn;
1469
    f.proto     = IPPROTO_TCP;
1470
    f.alproto   = ALPROTO_MODBUS;
1471
    f.flags     |= FLOW_IPV4;
1472
1473
    p->flow         = &f;
1474
    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
1475
    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
1476
1477
    StreamTcpInitConfig(true);
1478
1479
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1480
    FAIL_IF_NULL(de_ctx);
1481
1482
    de_ctx->flags |= DE_QUIET;
1483
    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
1484
                                      "(msg:\"Modbus invalid Function code\"; "
1485
                                      "app-layer-event: "
1486
                                      "modbus.invalid_function_code; "
1487
                                      "sid:1;)");
1488
    FAIL_IF_NULL(s);
1489
1490
    SigGroupBuild(de_ctx);
1491
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1492
1493
    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
1494
                                STREAM_TOSERVER,
1495
                                invalidFunctionCode,
1496
                                sizeof(invalidFunctionCode));
1497
    FAIL_IF_NOT(r == 0);
1498
1499
    ModbusState *modbus_state = f.alstate;
1500
    FAIL_IF_NULL(modbus_state);
1501
1502
    /* do detect */
1503
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1504
1505
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1506
1507
    SigGroupCleanup(de_ctx);
1508
    SigCleanSignatures(de_ctx);
1509
1510
    DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx);
1511
    DetectEngineCtxFree(de_ctx);
1512
1513
    AppLayerParserThreadCtxFree(alp_tctx);
1514
    StreamTcpFreeConfig(true);
1515
    FLOW_DESTROY(&f);
1516
    UTHFreePackets(&p, 1);
1517
    PASS;
1518
}
1519
#endif /* UNITTESTS */
1520
1521
0
void ModbusParserRegisterTests(void) {
1522
#ifdef UNITTESTS
1523
    UtRegisterTest("ModbusParserTest01 - Modbus Read Coils request",
1524
                   ModbusParserTest01);
1525
    UtRegisterTest("ModbusParserTest02 - Modbus Write Multiple registers request",
1526
                   ModbusParserTest02);
1527
    UtRegisterTest("ModbusParserTest03 - Modbus Read/Write Multiple registers request",
1528
                   ModbusParserTest03);
1529
    UtRegisterTest("ModbusParserTest04 - Modbus Force Listen Only Mode request",
1530
                   ModbusParserTest04);
1531
    UtRegisterTest("ModbusParserTest05 - Modbus invalid Protocol version",
1532
                   ModbusParserTest05);
1533
    UtRegisterTest("ModbusParserTest06 - Modbus unsolicited response",
1534
                   ModbusParserTest06);
1535
    UtRegisterTest("ModbusParserTest07 - Modbus invalid Length request",
1536
                   ModbusParserTest07);
1537
    UtRegisterTest("ModbusParserTest08 - Modbus Exception code invalid",
1538
                   ModbusParserTest08);
1539
    UtRegisterTest("ModbusParserTest09 - Modbus fragmentation - 1 ADU in 2 TCP packets",
1540
                   ModbusParserTest09);
1541
    UtRegisterTest("ModbusParserTest10 - Modbus fragmentation - 2 ADU in 1 TCP packet",
1542
                   ModbusParserTest10);
1543
    UtRegisterTest("ModbusParserTest11 - Modbus exceeded Length request",
1544
                   ModbusParserTest11);
1545
    UtRegisterTest("ModbusParserTest12 - Modbus invalid PDU Length",
1546
                   ModbusParserTest12);
1547
    UtRegisterTest("ModbusParserTest13 - Modbus Mask Write register request",
1548
                   ModbusParserTest13);
1549
    UtRegisterTest("ModbusParserTest14 - Modbus Write single register request",
1550
                   ModbusParserTest14);
1551
    UtRegisterTest("ModbusParserTest15 - Modbus invalid Mask Write register request",
1552
                   ModbusParserTest15);
1553
    UtRegisterTest("ModbusParserTest16 - Modbus invalid Write single register request",
1554
                   ModbusParserTest16);
1555
    UtRegisterTest("ModbusParserTest17 - Modbus stream depth",
1556
                   ModbusParserTest17);
1557
    UtRegisterTest("ModbusParserTest18 - Modbus stream depth in 2 TCP packets",
1558
                   ModbusParserTest18);
1559
    UtRegisterTest("ModbusParserTest19 - Modbus invalid Function code",
1560
                   ModbusParserTest19);
1561
#endif /* UNITTESTS */
1562
0
}