diff --git a/scripts/base/protocols/modbus/modbus.bro b/scripts/base/protocols/modbus/modbus.bro index ec8dfbd58f..0d2422f8ed 100644 --- a/scripts/base/protocols/modbus/modbus.bro +++ b/scripts/base/protocols/modbus/modbus.bro @@ -87,6 +87,156 @@ event modbus_response(c:connection,is_orig:bool,tid:count,pid: count,uid:count, } +#REQUEST FC=1 +event modbus_read_coils_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count, ref:count, bcount:count) + { + + local f:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + f=open_for_append (string_cat(path,"f1_new.log")); + m=open_for_append (string_cat(path,"fall_new.log")); + ftime=strftime("%F %T",network_time()); + + src= cat(c$id$orig_h); + dst=cat(c$id$resp_h); + src_p=cat(c$id$orig_p); + dst_p=cat(c$id$resp_p); + + #according to the specification, this FC typically has 0xxxx offset in the memory map + #local prefix_ref:count; + #prefix_ref=ref+40000; + + + local text=string_cat(ftime,"\t",src,"\t",dst,"\t", src_p, "\t REQUEST \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t", cat(fc),"\t", cat(ref), "\t", cat(bcount),"\n"); + + write_file(f,text); + write_file(m,text); + + print fmt("flying"); + close(f); + close(m); + + } + + + +#RESPONSE FC=1 +event modbus_read_coils_response(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count, bcount:count,bits:string) + { + + local f:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + f=open_for_append (string_cat(path,"f1_new.log")); + m=open_for_append (string_cat(path,"fall_new.log")); + ftime=strftime("%F %T",network_time()); + + src= cat(c$id$orig_h); + dst=cat(c$id$resp_h); + src_p=cat(c$id$orig_p); + dst_p=cat(c$id$resp_p); + + #according to the specification, this FC typically has 0xxxx offset in the memory map + #local prefix_ref:count; + #prefix_ref=ref+00000; + + + local text=string_cat(ftime,"\t",src,"\t",dst,"\t", src_p, "\t RESPONSE \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t", cat(fc),"\t", cat(bcount),"\t",bits,"\n"); + + write_file(f,text); + write_file(m,text); + + print fmt("flying"); + close(f); + close(m); + + } + + +#REQUEST FC=2 +event modbus_read_input_discretes_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count, ref:count, bcount:count) + { + local f:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + f=open_for_append (string_cat(path,"f2_new.log")); + m=open_for_append (string_cat(path,"fall_new.log")); + ftime=strftime("%F %T",network_time()); + + src= cat(c$id$orig_h); + dst=cat(c$id$resp_h); + src_p=cat(c$id$orig_p); + dst_p=cat(c$id$resp_p); + + #according to the specification, this FC typically has 1xxxx offset in the memory map + local prefix_ref:count; + prefix_ref=ref+10000; + + + local text=string_cat(ftime,"\t",src,"\t",dst,"\t", src_p, "\t REQUEST \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t", cat(fc),"\t", cat(prefix_ref), "\t", cat(bcount),"\n"); + + write_file(f,text); + write_file(m,text); + + print fmt("flying"); + close(f); + close(m); + } + + +#RESPONSE FC=2 +event modbus_read_input_discretes_response(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count, bcount:count,bits:string) + { + + local f:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + f=open_for_append (string_cat(path,"f2_new.log")); + m=open_for_append (string_cat(path,"fall_new.log")); + ftime=strftime("%F %T",network_time()); + + src= cat(c$id$orig_h); + dst=cat(c$id$resp_h); + src_p=cat(c$id$orig_p); + dst_p=cat(c$id$resp_p); + + #according to the specification, this FC typically has 1xxxx offset in the memory map + #local prefix_ref:count; + #prefix_ref=ref+10000; + + + local text=string_cat(ftime,"\t",src,"\t",dst,"\t", src_p, "\t RESPONSE \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t", cat(fc),"\t",cat(bcount),"\t", bits,"\n"); + + write_file(f,text); + write_file(m,text); + + print fmt("flying"); + close(f); + close(m); + } + + @@ -390,6 +540,77 @@ event modbus_write_single_response(c:connection,is_orig:bool,tid:count,pid:count } +#REQUEST FC=15 +event modbus_force_coils_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,bitCount:count,byteCount:count,coils:string) + { + + local h:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + h=open_for_append (string_cat(path,"f15_new.log")); + m=open_for_append (string_cat(path,"fall_new.log")); + ftime=strftime("%F %T",network_time()); + src= cat(c$id$orig_h); + dst=cat(c$id$resp_h); + + src_p=cat(c$id$orig_p); + dst_p=cat(c$id$resp_p); + + #according to the specification, this FC usually has 0xxxx offset in the memory map + #local prefix_ref:count; + #prefix_ref=ref+00000; + + local text=string_cat(ftime,"\t",src,"\t",dst,"\t", src_p, "\t REQUEST \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t", cat(fc),"\t",cat(ref), "\t",cat(bitCount),"\t",cat(byteCount),coils,"\n"); + + write_file(h,text); + write_file(m,text); + + close(h); + close(m); + + } + + + +#RESPONSE FC=15 +event modbus_force_coils_response(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,bitCount:count) + { + + local h:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + h=open_for_append (string_cat(path,"f15_new.log")); + m=open_for_append (string_cat(path,"fall_new.log")); + ftime=strftime("%F %T",network_time()); + src= cat(c$id$orig_h); + dst=cat(c$id$resp_h); + + src_p=cat(c$id$orig_p); + dst_p=cat(c$id$resp_p); + + #according to the specification, this FC usually has 0xxxx offset in the memory map + #local prefix_ref:count; + #prefix_ref=ref+00000; + + local text=string_cat(ftime,"\t",src,"\t",dst,"\t", src_p, "\t RESPONSE \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t", cat(fc),"\t",cat(ref), "\t",cat(bitCount),"\n"); + + write_file(h,text); + write_file(m,text); + + close(h); + close(m); + + } @@ -612,6 +833,80 @@ event modbus_read_write_request(c:connection,is_orig:bool,t:int_vec,tid:count,pi } +#REQUEST FC=24 +event modbus_read_FIFO_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count, ref:count) + { + + local f:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + f=open_for_append (string_cat(path,"f23_new.log")); + m=open_for_append (string_cat(path,"fall_new.log")); + ftime=strftime("%F %T",network_time()); + + src= cat(c$id$orig_h); + dst=cat(c$id$resp_h); + src_p=cat(c$id$orig_p); + dst_p=cat(c$id$resp_p); + + #according to the specification, this FC typically has 4xxxx offset in the memory map + #local prefix_ref:count; + # prefix_ref=ref+40000; + + + local text=string_cat(ftime,"\t",src,"\t",dst,"\t", src_p, "\t REQUEST \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t", cat(fc),"\t", cat(ref), "\t","\n"); + + write_file(f,text); + write_file(m,text); + + print fmt("flying"); + close(f); + close(m); + + } + + +#RESPONSE FC=24 +event modbus_read_FIFO_response(c:connection,is_orig:bool,t:int_vec,tid:count,pid:count,uid:count,fc:count,bcount:count) + { + + local h:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + h=open_for_append (string_cat(path,"f3_new.log")); + m=open_for_append (string_cat(path,"fall_new.log")); + ftime=strftime("%F %T",network_time()); + + src= cat(c$id$orig_h); + dst=cat(c$id$resp_h); + src_p=cat(c$id$orig_p); + dst_p=cat(c$id$resp_p); + + local text=string_cat(ftime,"\t",src,"\t",dst,"\t", src_p, "\t RESPONSE \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t", cat(fc),"\t",cat(bcount),"\t",cat(t),"\n"); + + write_file(h,text); + write_file(m,text); + + + close(h); + close(m); + + } + + + + + # REQUEST FC=7 (exception) event modbus_read_except_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,len:count) { diff --git a/simulation1.pcap b/simulation1.pcap new file mode 100644 index 0000000000..b0c2bb0b33 Binary files /dev/null and b/simulation1.pcap differ diff --git a/src/Modbus.h b/src/Modbus.h index 8acd81dc28..5c4936e85c 100644 --- a/src/Modbus.h +++ b/src/Modbus.h @@ -24,7 +24,13 @@ public: // Put event names in this function static bool Available() { return - modbus_read_multi_request + modbus_read_coils_request + || modbus_read_coils_response + + || modbus_read_input_discretes_request + || modbus_read_input_discretes_response + + || modbus_read_multi_request || modbus_read_multi_response || modbus_read_input_request @@ -36,16 +42,22 @@ public: || modbus_write_coil_request || modbus_write_coil_response + + || modbus_force_coils_request + || modbus_force_coils_response + || modbus_write_multi_request || modbus_write_multi_response || modbus_mask_write_request || modbus_mask_write_response - || modbus_read_write_request || modbus_read_write_response + || modbus_read_FIFO_request + || modbus_read_FIFO_response + || modbus_read_except_request || modbus_read_except_response diff --git a/src/event.bif b/src/event.bif index efdbe8f23a..232190e8ba 100644 --- a/src/event.bif +++ b/src/event.bif @@ -6623,6 +6623,14 @@ event modbus_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc # Event that passes response header only event modbus_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count%); + + +# Event that passes modbus request function code =1 +event modbus_read_coils_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,bcount:count%); + +# Event that passes modbus request function code =2 +event modbus_read_input_discretes_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,bcount:count%); + # Event that passes modbus request function code =3 event modbus_read_multi_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,wcount:count,len:count%); @@ -6635,6 +6643,9 @@ event modbus_write_coil_request%(c:connection,is_orig:bool,tid:count,pid:count,u # Event that passes modbus request function code =6 event modbus_write_single_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,len:count,ref:count,value:count%); +# Event that passes modbus request function code =15 +event modbus_force_coils_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,bitCount:count,byteCount:count,coils:string%); + #Event that passes modbus request function code=16 event modbus_write_multi_request%(c:connection,is_orig:bool,t:int_vec,tid:count,pid:count,uid:count,fc:count,ref:count,wCount:count,bCount:count,len:count%); @@ -6646,9 +6657,23 @@ event modbus_mask_write_request%(c:connection,is_orig:bool,tid:count,pid:count,u #Event that passes modbus request function code=23 event modbus_read_write_request%(c:connection,is_orig:bool,t:int_vec,tid:count,pid:count,uid:count,fc:count,refRead:count,wcRead:count,refWrite:count,wcWrite:count,bCount:count,len:count%); +#Event that passes modbus request function code=24 +event modbus_read_FIFO_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count%); + #Event that passes modbus request function code=7 event modbus_read_except_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,len:count%); + + + +#Event that passes modbus response function code=1 +event modbus_read_coils_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,bcount:count,bits:string%); + + +#Event that passes modbus response function code=2 +event modbus_read_input_discretes_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,bcount:count,bits:string%); + + #Event that passes modbus response function code=3 event modbus_read_multi_response%(c:connection,is_orig:bool,t:int_vec,tid:count,pid:count,uid:count,fc:count,bCount:count,len:count%); @@ -6661,6 +6686,9 @@ event modbus_write_coil_response%(c:connection,is_orig:bool,tid:count,pid:count, #Event that passes modbus response function code=6 event modbus_write_single_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,len:count,ref:count,value:count%); +#Event that passes modbus response function code=15 +event modbus_force_coils_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,bitCount:count%); + #Event that passes modbus response function code=16 event modbus_write_multi_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,wcount:count,len:count%); @@ -6672,6 +6700,14 @@ event modbus_mask_write_response%(c:connection,is_orig:bool,tid:count,pid:count, #Event that passes modbus response function code=23 event modbus_read_write_response%(c:connection,is_orig:bool,t:int_vec,tid:count,pid:count,uid:count,fc:count,bCount:count,len:count%); + +#Event that passes modbus response function code=24 +event modbus_read_FIFO_response%(c:connection,is_orig:bool,t:int_vec,tid:count,pid:count,uid:count,fc:count,bcount:count%); + + + + + #Event that passes modbus response function code=7 event modbus_read_except_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,status:count,len:count%); diff --git a/src/modbus-analyzer.pac b/src/modbus-analyzer.pac index f2bde53ac0..220f5bcb10 100644 --- a/src/modbus-analyzer.pac +++ b/src/modbus-analyzer.pac @@ -35,6 +35,40 @@ function deliver_message(tid:uint16, pid:uint16, uid: uint8, fc: uint8, flag:int %} + +#REQUEST FC=1 +function deliver_ReadCoilsReq(tid:uint16, pid:uint16, uid:uint8, fc:uint8, ref:uint16, bitCount:uint16): bool + %{ + + if ( ::modbus_read_coils_request ) + { + BifEvent::generate_modbus_read_coils_request( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,ref,bitCount); + } + return true; + + %} + +#REQUEST FC=2 +function deliver_ReadInputDiscReq(tid:uint16, pid:uint16, uid:uint8, fc:uint8, ref:uint16, bitCount:uint16): bool + %{ + + if ( ::modbus_read_input_discretes_request ) + { + BifEvent::generate_modbus_read_input_discretes_request( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,ref,bitCount); + } + return true; + + %} + + + + #REQUEST FC=3 function deliver_ReadMultiRegReq(tid:uint16,pid:uint16,uid:uint8,fc:uint8, ref: uint16, wcount:uint16,flag:uint16,len:uint16): bool %{ @@ -105,6 +139,21 @@ function deliver_WriteSingleRegReq(tid:uint16,pid:uint16,uid:uint8,fc:uint8,len: +#REQUEST FC=15 +function deliver_ForceMultiCoilsReq(tid:uint16,pid:uint16,uid:uint8,fc:uint8,ref:uint16,bitCount:uint16,byteCount:uint16,coils:bytestring): bool + + %{ + + if ( ::modbus_force_coils_request ) + { + BifEvent::generate_modbus_force_coils_request( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,ref,bitCount,byteCount, new StringVal(coils.length(), (const char*) coils.data())); + } + return true; + + %} #REQUEST FC=16 function deliver_WriteMultiRegReq( writeMulti: WriteMultipleRegistersRequest, tid:uint16, pid:uint16, uid: uint8, fc: uint8,len:uint16): bool @@ -178,6 +227,59 @@ function deliver_ReadWriteRegReq(doMulti: ReadWriteRegistersRequest, tid:uint16, %} +#REQUEST FC=24 +function deliver_ReadFIFOReq(tid:uint16,pid:uint16,uid:uint8,fc:uint8, ref: uint16): bool + %{ + + if ( ::modbus_read_FIFO_request ) + { + BifEvent::generate_modbus_read_FIFO_request( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,ref); + } + return true; + + %} + + + + +#RESPONSE FC=1 +function deliver_ReadCoilsRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,bcount:uint8,bits:bytestring): bool + %{ + + if ( ::modbus_read_coils_response ) + { + BifEvent::generate_modbus_read_coils_response( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,bcount, new StringVal(bits.length(), (const char*) bits.data())); +; + } + return true; + + %} + + +#RESPONSE FC=2 +function deliver_ReadInputDiscRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,bcount:uint8,bits:bytestring): bool + %{ + + if ( ::modbus_read_input_discretes_response ) + { + BifEvent::generate_modbus_read_input_discretes_response( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,bcount, new StringVal(bits.length(), (const char*) bits.data())); +; + } + return true; + + %} + + + #RESPONSE FC=3 @@ -207,7 +309,7 @@ function deliver_ReadMultiRegRes( doMulti: ReadMultipleRegistersResponse, tid:ui %} -#RESPONSE fc=4 +#RESPONSE FC=4 function deliver_ReadInputRegRes( doMulti: ReadInputRegistersResponse, tid:uint16, pid:uint16, uid: uint8, fc: uint16,len:uint16): bool %{ @@ -235,7 +337,7 @@ function deliver_ReadInputRegRes( doMulti: ReadInputRegistersResponse, tid:uint1 -#REQUEST fc=5 +#RESPONSE FC=5 function deliver_WriteCoilRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8, ref: uint16,onOff:uint8,other:uint8): bool %{ @@ -253,7 +355,7 @@ function deliver_WriteCoilRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8, ref: uin -#RESPONSE fc=6 +#RESPONSE FC=6 function deliver_WriteSingleRegRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,len:uint16,ref:uint16,value:uint16): bool %{ @@ -269,7 +371,24 @@ function deliver_WriteSingleRegRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,len: %} -#RESPONSE fc=16 +#RESPONSE FC=15 +function deliver_ForceMultiCoilsRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,ref:uint16,bitCount:uint16): bool + %{ + + if ( ::modbus_force_coils_response) + { + BifEvent::generate_modbus_force_coils_response( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,ref,bitCount); + } + return true; + + %} + + + +#RESPONSE FC=16 function deliver_WriteMultiRegRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8, ref: uint16, wcount:uint16,len:uint16): bool %{ @@ -286,7 +405,7 @@ function deliver_WriteMultiRegRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8, ref: -#REQUEST FC=22 +#RESPONSE FC=22 function deliver_MaskWriteRegRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,ref:uint16,andMask:uint16,orMask:uint16): bool %{ @@ -329,6 +448,35 @@ function deliver_ReadWriteRegRes(doMulti: ReadWriteRegistersResponse, tid:uint16 %} +#RESPONSE FC=24 +function deliver_ReadFIFORes( doMulti: ReadFIFOQueueResponse, tid:uint16, pid:uint16, uid: uint8, fc: uint16): bool + %{ + + VectorVal * t=new VectorVal( new VectorType(base_type(TYPE_INT))); + + for (unsigned int i=0; i < (${doMulti.registerData})->size(); ++i) + { + + Val* r=new Val(((*doMulti->registerData())[i]),TYPE_INT); + t->Assign(i,r,0,OP_ASSIGN); + } + + + + if ( ::modbus_read_FIFO_response ) + { + + BifEvent::generate_modbus_read_FIFO_response( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),t,tid,pid,uid,fc,${doMulti.byteCount}); + } + return true; + %} + + + + #EXCEPTION function deliver_Exception(tid:uint16,pid:uint16,uid:uint8,fc:uint8,code:uint8): bool %{ diff --git a/src/modbus-protocol.pac b/src/modbus-protocol.pac index 843a50fa99..54209427f2 100644 --- a/src/modbus-protocol.pac +++ b/src/modbus-protocol.pac @@ -139,19 +139,19 @@ type ModbusTCP_RequestPDU = record { READ_MULTIPLE_REGISTERS -> readMultipleRegisters: ReadMultipleRegistersRequest(header.len-2,header); WRITE_MULTIPLE_REGISTERS -> writeMultipleRegisters: WriteMultipleRegistersRequest(header.len-2,header); # Class 1 - READ_COILS -> readCoils: ReadCoilsRequest(header.len-2); - READ_INPUT_DISCRETES -> readInputDiscretes: ReadInputDiscretesRequest(header.len-2); + READ_COILS -> readCoils: ReadCoilsRequest(header.len-2,header); + READ_INPUT_DISCRETES -> readInputDiscretes: ReadInputDiscretesRequest(header.len-2,header); READ_INPUT_REGISTERS -> readInputRegisters: ReadInputRegistersRequest(header.len-2,header); WRITE_COIL -> writeCoil: WriteCoilRequest(header.len-2,header); WRITE_SINGLE_REGISTER -> writeSingleRegister: WriteSingleRegisterRequest(header.len-2,header); READ_EXCEPTION_STATUS -> readExceptionStatus: ReadExceptionStatusRequest(header.len-2,header); # Class 2 - FORCE_MULTIPLE_COILS -> forceMultipleCoils: ForceMultipleCoilsRequest(header.len-2); + FORCE_MULTIPLE_COILS -> forceMultipleCoils: ForceMultipleCoilsRequest(header.len-2,header); READ_GENERAL_REFERENCE -> readGeneralReference: ReadGeneralReferenceRequest(header.len-2); WRITE_GENERAL_REFERENCE -> writeGeneralReference: WriteGeneralReferenceRequest(header.len-2); MASK_WRITE_REGISTER -> maskWriteRegister: MaskWriteRegisterRequest(header.len-2,header); READ_WRITE_REGISTERS -> readWriteRegisters: ReadWriteRegistersRequest(header.len-2,header); - READ_FIFO_QUEUE -> readFIFOQueue: ReadFIFOQueueRequest(header.len-2); + READ_FIFO_QUEUE -> readFIFOQueue: ReadFIFOQueueRequest(header.len-2,header); # All the rest default -> unknown: bytestring &restofdata; }; @@ -181,22 +181,31 @@ type WriteMultipleRegistersRequest(len: uint16, header: ModbusTCP_TransportHeade byteCount: uint8; registers: uint16[wordCount] &length = byteCount; } &let { - -deliver: bool =$context.flow.deliver_WriteMultiRegReq(this,header.tid,header.pid,header.uid,header.fc,len); + deliver: bool =$context.flow.deliver_WriteMultiRegReq(this,header.tid,header.pid,header.uid,header.fc,len); }; # Class 1 requests -type ReadCoilsRequest(len: uint16) = record { + +#REQUEST FC=1 +type ReadCoilsRequest(len: uint16,header:ModbusTCP_TransportHeader) = record { referenceNumber: uint16; bitCount: uint16 &check(bitCount <= 2000); -}; +} &let +{ +deliver: bool =$context.flow.deliver_ReadCoilsReq(header.tid,header.pid,header.uid,header.fc,referenceNumber,bitCount); + }; -type ReadInputDiscretesRequest(len: uint16) = record { + +#REQUEST FC=2 +type ReadInputDiscretesRequest(len: uint16,header:ModbusTCP_TransportHeader) = record { referenceNumber: uint16; bitCount: uint16 &check(bitCount <= 2000); -}; - +} +&let +{ +deliver: bool =$context.flow.deliver_ReadInputDiscReq(header.tid,header.pid,header.uid,header.fc,referenceNumber,bitCount); + }; #REQUEST FC=4 @@ -242,11 +251,14 @@ deliver: bool =$context.flow.deliver_ReadExceptStatReq(header.tid,header.pid,hea }; # Class 2 requests -type ForceMultipleCoilsRequest(len: uint16) = record { +type ForceMultipleCoilsRequest(len: uint16,header:ModbusTCP_TransportHeader) = record { referenceNumber: uint16; bitCount: uint16 &check(bitCount <= 800); byteCount: uint8 &check(byteCount == (bitCount + 7)/8); coils: bytestring &length = byteCount; +} + &let { +deliver: bool =$context.flow.deliver_ForceMultiCoilsReq(header.tid,header.pid,header.uid,header.fc,referenceNumber,bitCount,byteCount,coils); }; type ReadGeneralReferenceRequest(len: uint16) = record { @@ -287,8 +299,12 @@ type ReadWriteRegistersRequest(len: uint16,header: ModbusTCP_TransportHeader) = deliver: bool =$context.flow.deliver_ReadWriteRegReq(this,header.tid,header.pid,header.uid,header.fc,len); }; -type ReadFIFOQueueRequest(len: uint16) = record { +#REQUEST FC=24 +type ReadFIFOQueueRequest(len: uint16,header: ModbusTCP_TransportHeader) = record { referenceNumber: uint16; +} +&let{ + deliver: bool =$context.flow.deliver_ReadFIFOReq(header.tid,header.pid,header.uid,header.fc,referenceNumber); }; #Responses @@ -300,18 +316,18 @@ type ModbusTCP_ResponsePDU = record { READ_MULTIPLE_REGISTERS -> readMultipleRegisters: ReadMultipleRegistersResponse(header.len-2, header); WRITE_MULTIPLE_REGISTERS -> writeMultipleRegisters: WriteMultipleRegistersResponse(header.len-2,header); # Class 1 - READ_COILS -> readCoils: ReadCoilsResponse(header.len-2); - READ_INPUT_DISCRETES -> readInputDiscretes: ReadInputDiscretesResponse(header.len-2); + READ_COILS -> readCoils: ReadCoilsResponse(header.len-2,header); + READ_INPUT_DISCRETES -> readInputDiscretes: ReadInputDiscretesResponse(header.len-2,header); READ_INPUT_REGISTERS -> readInputRegisters: ReadInputRegistersResponse(header.len-2,header); WRITE_COIL -> writeCoil: WriteCoilResponse(header.len-2,header); WRITE_SINGLE_REGISTER -> writeSingleRegister: WriteSingleRegisterResponse(header.len-2,header); READ_EXCEPTION_STATUS -> readExceptionStatus: ReadExceptionStatusResponse(header.len-2,header); - FORCE_MULTIPLE_COILS -> forceMultipleCoils: ForceMultipleCoilsResponse(header.len-2); + FORCE_MULTIPLE_COILS -> forceMultipleCoils: ForceMultipleCoilsResponse(header.len-2,header); READ_GENERAL_REFERENCE -> readGeneralReference: ReadGeneralReferenceResponse(header.len-2); WRITE_GENERAL_REFERENCE -> writeGeneralReference: WriteGeneralReferenceResponse(header.len-2); MASK_WRITE_REGISTER -> maskWriteRegister: MaskWriteRegisterResponse(header.len-2,header); READ_WRITE_REGISTERS -> readWriteRegisters: ReadWriteRegistersResponse(header.len-2,header); - READ_FIFO_QUEUE -> readFIFOQueue: ReadFIFOQueueResponse(header.len-2); + READ_FIFO_QUEUE -> readFIFOQueue: ReadFIFOQueueResponse(header.len-2,header); # Exceptions READ_MULTIPLE_REGISTERS_EXCEPTION -> readMultipleRegistersException : Exception(header.len-2,header); WRITE_MULTIPLE_REGISTERS_EXCEPTION -> writeMultipleRegistersException: Exception(header.len-2,header); @@ -361,15 +377,26 @@ deliver: bool =$context.flow.deliver_WriteMultiRegRes(header.tid,header.pid,head # Class 1 responses -type ReadCoilsResponse(len: uint16) = record { +###RESPONSE FC=1 +type ReadCoilsResponse(len: uint16,header:ModbusTCP_TransportHeader) = record { byteCount: uint8; bits: bytestring &length = byteCount; -}; +}&let{ + deliver: bool =$context.flow.deliver_ReadCoilsRes(header.tid,header.pid,header.uid,header.fc,byteCount,bits); +} +; -type ReadInputDiscretesResponse(len: uint16) = record { + +###RESPONSE FC=2 +type ReadInputDiscretesResponse(len: uint16,header:ModbusTCP_TransportHeader) = record { byteCount: uint8; bits: bytestring &length = byteCount; -}; +} +&let{ + deliver: bool =$context.flow.deliver_ReadInputDiscRes(header.tid,header.pid,header.uid,header.fc,byteCount,bits); +} + +; ###RESPONSE FC=4 @@ -412,10 +439,16 @@ deliver: bool =$context.flow.deliver_ReadExceptStatRes(header.tid,header.pid,hea # Class 2 responses -type ForceMultipleCoilsResponse(len: uint16) = record { +#RESPONSE FC=15 +type ForceMultipleCoilsResponse(len: uint16,header:ModbusTCP_TransportHeader) = record { referenceNumber: uint16; bitCount: uint16; -}; +} + &let { + +deliver: bool =$context.flow.deliver_ForceMultiCoilsRes(header.tid,header.pid,header.uid,header.fc,referenceNumber,bitCount); +} +; type ReadGeneralReferenceResponse(len: uint16) = record { byteCount: uint8; @@ -451,11 +484,17 @@ type ReadWriteRegistersResponse(len: uint16,header:ModbusTCP_TransportHeader) = - -type ReadFIFOQueueResponse(len: uint16) = record { +###RESPONSE FC=24 +type ReadFIFOQueueResponse(len: uint16,header:ModbusTCP_TransportHeader) = record { byteCount: uint16 &check(byteCount <= 64); wordCount: uint16 &check(wordCount <= 31); registerData: uint16[wordCount] &length = byteCount; -} &length = len; +} &length = len, +&let{ + deliver: bool =$context.flow.deliver_ReadFIFORes(this,header.tid,header.pid,header.uid,header.fc); + } + +; + #