52 SCRegisterModbusParser();
79#define MODBUS_CONFIG_DEFAULT_STREAM_DEPTH 0
82static uint8_t invalidFunctionCode[] = {
92static uint8_t readCoilsReq[] = { 0x00, 0x00,
100static uint8_t readCoilsRsp[] = { 0x00, 0x00,
108static uint8_t readCoilsErrorRsp[] = {
120static uint8_t writeSingleRegisterReq[] = { 0x00, 0x0A,
128static uint8_t invalidWriteSingleRegisterReq[] = { 0x00, 0x0A,
135static uint8_t writeSingleRegisterRsp[] = { 0x00, 0x0A,
145static uint8_t writeMultipleRegistersReq[] = { 0x00, 0x0A,
156static uint8_t writeMultipleRegistersRsp[] = { 0x00, 0x0A,
166static uint8_t maskWriteRegisterReq[] = { 0x00, 0x0A,
175static uint8_t invalidMaskWriteRegisterReq[] = { 0x00, 0x0A,
183static uint8_t maskWriteRegisterRsp[] = { 0x00, 0x0A,
195static uint8_t readWriteMultipleRegistersReq[] = { 0x12, 0x34,
210static uint8_t readWriteMultipleRegistersRsp[] = { 0x12, 0x34,
225static uint8_t forceListenOnlyMode[] = { 0x0A, 0x00,
233static uint8_t invalidProtocolIdReq[] = { 0x00, 0x00,
241static uint8_t invalidLengthWriteMultipleRegistersReq[] = {
253static uint8_t exceededLengthWriteMultipleRegistersReq[] = {
263static uint8_t invalidLengthPDUWriteMultipleRegistersReq[] = {
271static int ModbusParserTest01(
void) {
278 memset(&f, 0,
sizeof(f));
279 memset(&ssn, 0,
sizeof(ssn));
283 f.
proto = IPPROTO_TCP;
289 STREAM_TOSERVER, readCoilsReq,
290 sizeof(readCoilsReq));
293 ModbusState *modbus_state = f.
alstate;
296 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
298 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 1);
299 FAIL_IF_NOT(SCModbusMessageGetReadRequestAddress(&request) == 0x7890);
300 FAIL_IF_NOT(SCModbusMessageGetReadRequestQuantity(&request) == 19);
303 STREAM_TOCLIENT, readCoilsRsp,
304 sizeof(readCoilsRsp));
307 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
316static int ModbusParserTest02(
void) {
323 memset(&f, 0,
sizeof(f));
324 memset(&ssn, 0,
sizeof(ssn));
328 f.
proto = IPPROTO_TCP;
334 STREAM_TOSERVER, writeMultipleRegistersReq,
335 sizeof(writeMultipleRegistersReq));
338 ModbusState *modbus_state = f.
alstate;
341 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
343 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 16);
344 FAIL_IF_NOT(SCModbusMessageGetWriteMultreqAddress(&request) == 0x01);
345 FAIL_IF_NOT(SCModbusMessageGetWriteMultreqQuantity(&request) == 2);
348 const uint8_t *data = SCModbusMessageGetWriteMultreqData(&request, &data_len);
356 STREAM_TOCLIENT, writeMultipleRegistersRsp,
357 sizeof(writeMultipleRegistersRsp));
360 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
369static int ModbusParserTest03(
void) {
381 memset(&f, 0,
sizeof(
Flow));
389 f.
proto = IPPROTO_TCP;
404 "(msg:\"Modbus Data mismatch\"; "
406 "modbus.value_mismatch; "
415 readWriteMultipleRegistersReq,
416 sizeof(readWriteMultipleRegistersReq));
419 ModbusState *modbus_state = f.
alstate;
422 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
425 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 23);
426 FAIL_IF_NOT(SCModbusMessageGetRwMultreqReadAddress(&request) == 0x03);
427 FAIL_IF_NOT(SCModbusMessageGetRwMultreqReadQuantity(&request) == 6);
428 FAIL_IF_NOT(SCModbusMessageGetRwMultreqWriteAddress(&request) == 0x0E);
429 FAIL_IF_NOT(SCModbusMessageGetRwMultreqWriteQuantity(&request) == 3);
432 uint8_t
const *data = SCModbusMessageGetRwMultreqWriteData(&request, &data_len);
442 STREAM_TOCLIENT, readWriteMultipleRegistersRsp,
443 sizeof(readWriteMultipleRegistersRsp));
446 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
467static int ModbusParserTest04(
void) {
474 memset(&f, 0,
sizeof(f));
475 memset(&ssn, 0,
sizeof(ssn));
479 f.
proto = IPPROTO_TCP;
485 STREAM_TOSERVER, forceListenOnlyMode,
486 sizeof(forceListenOnlyMode));
489 ModbusState *modbus_state = f.
alstate;
492 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
495 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 8);
496 FAIL_IF_NOT(SCModbusMessageGetSubfunction(&request) == 4);
505static int ModbusParserTest05(
void) {
517 memset(&f, 0,
sizeof(
Flow));
525 f.
proto = IPPROTO_TCP;
540 "(msg:\"Modbus invalid Protocol version\"; "
542 "modbus.invalid_protocol_id; "
550 STREAM_TOSERVER, invalidProtocolIdReq,
551 sizeof(invalidProtocolIdReq));
554 ModbusState *modbus_state = f.
alstate;
576static int ModbusParserTest06(
void) {
588 memset(&f, 0,
sizeof(
Flow));
596 f.
proto = IPPROTO_TCP;
611 "(msg:\"Modbus unsolicited response\"; "
613 "modbus.unsolicited_response; "
621 STREAM_TOCLIENT, readCoilsRsp,
622 sizeof(readCoilsRsp));
625 ModbusState *modbus_state = f.
alstate;
647static int ModbusParserTest07(
void) {
659 memset(&f, 0,
sizeof(
Flow));
667 f.
proto = IPPROTO_TCP;
682 "(msg:\"Modbus invalid Length\"; "
684 "modbus.invalid_length; "
693 invalidLengthWriteMultipleRegistersReq,
694 sizeof(invalidLengthWriteMultipleRegistersReq));
697 ModbusState *modbus_state = f.
alstate;
719static int ModbusParserTest08(
void) {
731 memset(&f, 0,
sizeof(
Flow));
739 f.
proto = IPPROTO_TCP;
754 "(msg:\"Modbus Exception code invalid\"; "
756 "modbus.invalid_exception_code; "
764 STREAM_TOSERVER, readCoilsReq,
765 sizeof(readCoilsReq));
768 ModbusState *modbus_state = f.
alstate;
771 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
774 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 1);
775 FAIL_IF_NOT(SCModbusMessageGetReadRequestAddress(&request) == 0x7890);
776 FAIL_IF_NOT(SCModbusMessageGetReadRequestQuantity(&request) == 19);
779 STREAM_TOCLIENT, readCoilsErrorRsp,
780 sizeof(readCoilsErrorRsp));
783 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
804static int ModbusParserTest09(
void) {
809 uint32_t input_len =
sizeof(readCoilsReq), part2_len = 3;
810 uint8_t *input = readCoilsReq;
814 memset(&f, 0,
sizeof(f));
815 memset(&ssn, 0,
sizeof(ssn));
819 f.
proto = IPPROTO_TCP;
825 STREAM_TOSERVER, input, input_len - part2_len);
829 STREAM_TOSERVER, input, input_len);
832 ModbusState *modbus_state = f.
alstate;
835 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
838 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 1);
839 FAIL_IF_NOT(SCModbusMessageGetReadRequestAddress(&request) == 0x7890);
840 FAIL_IF_NOT(SCModbusMessageGetReadRequestQuantity(&request) == 19);
842 input_len =
sizeof(readCoilsRsp);
844 input = readCoilsRsp;
847 STREAM_TOCLIENT, input, input_len - part2_len);
851 STREAM_TOCLIENT, input, input_len);
854 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
863static int ModbusParserTest10(
void) {
864 uint32_t input_len =
sizeof(readCoilsReq) +
sizeof(writeMultipleRegistersReq);
865 uint8_t *input, *ptr;
873 input = (uint8_t *)
SCMalloc (input_len *
sizeof(uint8_t));
876 memcpy(input, readCoilsReq,
sizeof(readCoilsReq));
877 memcpy(input +
sizeof(readCoilsReq), writeMultipleRegistersReq,
sizeof(writeMultipleRegistersReq));
879 memset(&f, 0,
sizeof(f));
880 memset(&ssn, 0,
sizeof(ssn));
884 f.
proto = IPPROTO_TCP;
890 STREAM_TOSERVER, input, input_len);
893 ModbusState *modbus_state = f.
alstate;
896 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 2);
898 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 1);
901 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 16);
902 FAIL_IF_NOT(SCModbusMessageGetWriteMultreqAddress(&request) == 0x01);
903 FAIL_IF_NOT(SCModbusMessageGetWriteMultreqQuantity(&request) == 2);
906 uint8_t
const *data = SCModbusMessageGetWriteMultreqData(&request, &data_len);
913 input_len =
sizeof(readCoilsRsp) +
sizeof(writeMultipleRegistersRsp);
915 ptr = (uint8_t *)
SCRealloc (input, input_len *
sizeof(uint8_t));
919 memcpy(input, readCoilsRsp,
sizeof(readCoilsRsp));
920 memcpy(input +
sizeof(readCoilsRsp), writeMultipleRegistersRsp,
sizeof(writeMultipleRegistersRsp));
933static int ModbusParserTest11(
void) {
942 size_t input_len = 65536;
943 uint8_t *input =
SCCalloc(1, input_len);
947 memcpy(input, exceededLengthWriteMultipleRegistersReq,
948 sizeof(exceededLengthWriteMultipleRegistersReq));
953 memset(&f, 0,
sizeof(
Flow));
961 f.
proto = IPPROTO_TCP;
976 "(msg:\"Modbus invalid Length\"; "
978 "modbus.invalid_length; "
989 ModbusState *modbus_state = f.
alstate;
1011static int ModbusParserTest12(
void) {
1023 memset(&f, 0,
sizeof(
Flow));
1031 f.
proto = IPPROTO_TCP;
1046 "(msg:\"Modbus invalid Length\"; "
1048 "modbus.invalid_length; "
1057 invalidLengthPDUWriteMultipleRegistersReq,
1058 sizeof(invalidLengthPDUWriteMultipleRegistersReq));
1061 ModbusState *modbus_state = f.
alstate;
1083static int ModbusParserTest13(
void) {
1090 memset(&f, 0,
sizeof(f));
1091 memset(&ssn, 0,
sizeof(ssn));
1095 f.
proto = IPPROTO_TCP;
1101 STREAM_TOSERVER, maskWriteRegisterReq,
1102 sizeof(maskWriteRegisterReq));
1105 ModbusState *modbus_state = f.
alstate;
1108 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
1111 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 22);
1112 FAIL_IF_NOT(SCModbusMessageGetAndMask(&request) == 0x00F2);
1113 FAIL_IF_NOT(SCModbusMessageGetOrMask(&request) == 0x0025);
1116 STREAM_TOCLIENT, maskWriteRegisterRsp,
1117 sizeof(maskWriteRegisterRsp));
1120 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
1129static int ModbusParserTest14(
void) {
1136 memset(&f, 0,
sizeof(f));
1137 memset(&ssn, 0,
sizeof(ssn));
1141 f.
proto = IPPROTO_TCP;
1147 STREAM_TOSERVER, writeSingleRegisterReq,
1148 sizeof(writeSingleRegisterReq));
1151 ModbusState *modbus_state = f.
alstate;
1154 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
1157 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 6);
1158 FAIL_IF_NOT(SCModbusMessageGetWriteAddress(&request) == 0x0001);
1159 FAIL_IF_NOT(SCModbusMessageGetWriteData(&request) == 0x0003);
1162 STREAM_TOCLIENT, writeSingleRegisterRsp,
1163 sizeof(writeSingleRegisterRsp));
1166 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
1175static int ModbusParserTest15(
void) {
1187 memset(&f, 0,
sizeof(f));
1188 memset(&ssn, 0,
sizeof(ssn));
1195 f.
proto = IPPROTO_TCP;
1210 "(msg:\"Modbus invalid Length\"; "
1212 "modbus.invalid_length; "
1220 STREAM_TOSERVER, invalidMaskWriteRegisterReq,
1221 sizeof(invalidMaskWriteRegisterReq));
1224 ModbusState *modbus_state = f.
alstate;
1227 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
1230 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 22);
1238 STREAM_TOCLIENT, maskWriteRegisterRsp,
1239 sizeof(maskWriteRegisterRsp));
1242 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
1243 ModbusMessage response = SCModbusStateGetTxResponse(modbus_state, 0);
1246 FAIL_IF_NOT(SCModbusMessageGetFunction(&response) == 22);
1262static int ModbusParserTest16(
void) {
1274 memset(&f, 0,
sizeof(f));
1275 memset(&ssn, 0,
sizeof(ssn));
1282 f.
proto = IPPROTO_TCP;
1297 "(msg:\"Modbus invalid Length\"; "
1299 "modbus.invalid_length; "
1308 invalidWriteSingleRegisterReq,
1309 sizeof(invalidWriteSingleRegisterReq));
1312 ModbusState *modbus_state = f.
alstate;
1315 ModbusMessage request = SCModbusStateGetTxRequest(modbus_state, 0);
1318 FAIL_IF_NOT(SCModbusMessageGetFunction(&request) == 6);
1320 const uint8_t *data = SCModbusMessageGetBytevecData(&request, &data_len);
1331 STREAM_TOCLIENT, writeSingleRegisterRsp,
1332 sizeof(writeSingleRegisterRsp));
1335 FAIL_IF_NOT(SCModbusStateGetTxCount(modbus_state) == 1);
1336 ModbusMessage response = SCModbusStateGetTxResponse(modbus_state, 0);
1339 FAIL_IF_NOT(SCModbusMessageGetFunction(&response) == 6);
1340 FAIL_IF_NOT(SCModbusMessageGetWriteAddress(&response) == 0x0001);
1355static int ModbusParserTest17(
void) {
1362 memset(&f, 0,
sizeof(f));
1363 memset(&ssn, 0,
sizeof(ssn));
1367 f.
proto = IPPROTO_TCP;
1373 readCoilsReq,
sizeof(readCoilsReq));
1381 readCoilsRsp,
sizeof(readCoilsRsp));
1393static int ModbusParserTest18(
void) {
1398 uint32_t input_len =
sizeof(readCoilsReq), part2_len = 3;
1399 uint8_t *input = readCoilsReq;
1403 memset(&f, 0,
sizeof(f));
1404 memset(&ssn, 0,
sizeof(ssn));
1408 f.
proto = IPPROTO_TCP;
1414 input, input_len - part2_len);
1427 input_len =
sizeof(readCoilsRsp);
1429 input = readCoilsRsp;
1432 input, input_len - part2_len);
1450static int ModbusParserTest19(
void) {
1462 memset(&f, 0,
sizeof(
Flow));
1470 f.
proto = IPPROTO_TCP;
1485 "(msg:\"Modbus invalid Function code\"; "
1487 "modbus.invalid_function_code; "
1496 invalidFunctionCode,
1497 sizeof(invalidFunctionCode));
1500 ModbusState *modbus_state = f.
alstate;
1525 ModbusParserTest01);
1526 UtRegisterTest(
"ModbusParserTest02 - Modbus Write Multiple registers request",
1527 ModbusParserTest02);
1528 UtRegisterTest(
"ModbusParserTest03 - Modbus Read/Write Multiple registers request",
1529 ModbusParserTest03);
1530 UtRegisterTest(
"ModbusParserTest04 - Modbus Force Listen Only Mode request",
1531 ModbusParserTest04);
1532 UtRegisterTest(
"ModbusParserTest05 - Modbus invalid Protocol version",
1533 ModbusParserTest05);
1534 UtRegisterTest(
"ModbusParserTest06 - Modbus unsolicited response",
1535 ModbusParserTest06);
1536 UtRegisterTest(
"ModbusParserTest07 - Modbus invalid Length request",
1537 ModbusParserTest07);
1538 UtRegisterTest(
"ModbusParserTest08 - Modbus Exception code invalid",
1539 ModbusParserTest08);
1540 UtRegisterTest(
"ModbusParserTest09 - Modbus fragmentation - 1 ADU in 2 TCP packets",
1541 ModbusParserTest09);
1542 UtRegisterTest(
"ModbusParserTest10 - Modbus fragmentation - 2 ADU in 1 TCP packet",
1543 ModbusParserTest10);
1544 UtRegisterTest(
"ModbusParserTest11 - Modbus exceeded Length request",
1545 ModbusParserTest11);
1547 ModbusParserTest12);
1548 UtRegisterTest(
"ModbusParserTest13 - Modbus Mask Write register request",
1549 ModbusParserTest13);
1550 UtRegisterTest(
"ModbusParserTest14 - Modbus Write single register request",
1551 ModbusParserTest14);
1552 UtRegisterTest(
"ModbusParserTest15 - Modbus invalid Mask Write register request",
1553 ModbusParserTest15);
1554 UtRegisterTest(
"ModbusParserTest16 - Modbus invalid Write single register request",
1555 ModbusParserTest16);
1557 ModbusParserTest17);
1558 UtRegisterTest(
"ModbusParserTest18 - Modbus stream depth in 2 TCP packets",
1559 ModbusParserTest18);
1560 UtRegisterTest(
"ModbusParserTest19 - Modbus invalid Function code",
1561 ModbusParserTest19);
#define MODBUS_CONFIG_DEFAULT_STREAM_DEPTH
void ModbusParserRegisterTests(void)
void RegisterModbusParsers(void)
Function to register the Modbus protocol parser.
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void SigCleanSignatures(DetectEngineCtx *de_ctx)
int SigGroupCleanup(DetectEngineCtx *de_ctx)
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
#define FLOW_INITIALIZE(f)
#define FLOW_PKT_TOSERVER
#define FLOW_PKT_ESTABLISHED
AppLayerParserThreadCtx * alp_tctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
void StreamTcpFreeConfig(bool quiet)
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
main detection engine ctx
AppProto alproto
application level protocol
Per thread variable structure.
#define SCRealloc(ptr, sz)
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
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.