diff --git a/scripts/base/protocols/modbus/modbus.bro b/scripts/base/protocols/modbus/modbus.bro index 0d2422f8ed..979371fa49 100644 --- a/scripts/base/protocols/modbus/modbus.bro +++ b/scripts/base/protocols/modbus/modbus.bro @@ -688,6 +688,274 @@ event modbus_write_multi_response(c:connection,is_orig:bool,tid:count,pid:count, + + +#REQUEST FC=20 +event modbus_read_reference_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,refCount:count,t:int_vec) + { + + local k:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + + k=open_for_append (string_cat(path,"f20_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 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(refCount),"\t",cat(t),"\n"); + + write_file(k,text); + write_file(m,text); + + close(k); + close(m); + + } + + + +#RESPONSE FC=20 +event modbus_read_reference_response(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,byteCount:count,t:int_vec) + { + + local k:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + + k=open_for_append (string_cat(path,"f20_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 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 RESPONSE \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t",cat(fc),"\t",cat(byteCount),"\t",cat(t),"\n"); + + write_file(k,text); + write_file(m,text); + + close(k); + close(m); + + } + + +#REQUEST FC=20 (for single reference) +event modbus_read_single_reference_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,refType:count,refNumber:count,wordCount:count) + { + + local k:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + + k=open_for_append (string_cat(path,"f20_singles_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 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(refType),"\t",cat(refNumber),"\t",cat(wordCount),"\n"); + + write_file(k,text); + write_file(m,text); + + close(k); + close(m); + + } + +#RESPONSE FC=20 (for single reference) +event modbus_read_single_reference_response(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,byteCount:count,refType:count,t:int_vec) + { + + local k:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + + k=open_for_append (string_cat(path,"f20_singles_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 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 RESPONSE \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t",cat(fc),"\t",cat(byteCount),"\t",cat(refType),"\t",cat(t),"\n"); + + write_file(k,text); + write_file(m,text); + + close(k); + close(m); + + } + + + + +#REQUEST FC=21 +event modbus_write_reference_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,byteCount:count,t:int_vec) + { + + local k:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + + k=open_for_append (string_cat(path,"f21_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 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(byteCount),"\t",cat(t),"\n"); + + write_file(k,text); + write_file(m,text); + + close(k); + close(m); + + } + + +#RESPONSE FC=21 +event modbus_read_reference_response(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,byteCount:count,t:int_vec) + { + + local k:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + + k=open_for_append (string_cat(path,"f21_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 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 RESPONSE \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t",cat(fc),"\t",cat(byteCount),"\t",cat(t),"\n"); + + write_file(k,text); + write_file(m,text); + + close(k); + close(m); + + } + +#REQUEST/RESPONSE FC=20 (for single reference) +event modbus_write_single_reference(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,refType:count,refNumber:count,wordCount:count,t:int_vec) + { + + local k:file; + local m:file; + local ftime:string; + local src:string; + local dst:string; + local src_p:string; + local dst_p:string; + + + k=open_for_append (string_cat(path,"f21_singles_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 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/RESPONSE \t",cat(tid), "\t",cat(pid),"\t", cat(uid),"\t",cat(fc),"\t",cat(refType),"\t",cat(refNumber),"\t",cat(wordCount),"\t",cat(t),"\n"); + + write_file(k,text); + write_file(m,text); + + close(k); + close(m); + + } + #REQUEST FC=22 event modbus_mask_write_request(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,andMask:count,orMask:count) { diff --git a/src/Modbus.h b/src/Modbus.h index 5c4936e85c..900c3c6322 100644 --- a/src/Modbus.h +++ b/src/Modbus.h @@ -46,8 +46,19 @@ public: || modbus_force_coils_request || modbus_force_coils_response + || modbus_read_reference_request + || modbus_read_reference_response + + || modbus_read_single_reference_request + || modbus_read_single_reference_response + + || modbus_write_reference_request + || modbus_write_reference_response + + || modbus_write_single_reference + || modbus_write_multi_request - || modbus_write_multi_response + || modbus_write_multi_response || modbus_mask_write_request || modbus_mask_write_response diff --git a/src/event.bif b/src/event.bif index 232190e8ba..25d5959bd1 100644 --- a/src/event.bif +++ b/src/event.bif @@ -6650,10 +6650,26 @@ event modbus_force_coils_request%(c:connection,is_orig:bool,tid:count,pid:count, 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%); -#Event that passes modbus request function code=22 +#Event that passes modbus request function code=20 +event modbus_read_reference_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,refCount:count,t:int_vec%); + +#Event that passes modbus request function code=20 for single reference +event modbus_read_single_reference_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,refType:count,refNumber:count,wordCount:count%); + + +#Event that passes modbus request function code=21 +event modbus_write_reference_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,byteCount:count,t:int_vec%); + + +#Event that passes modbus request/response function code=21 for single reference +event modbus_write_single_reference%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,refType:count,refNumber:count,wordCount:count,t:int_vec%); + +#Event that passes modbus request function code=22 event modbus_mask_write_request%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,andMask:count,orMask:count%); + + #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%); @@ -6693,6 +6709,16 @@ event modbus_force_coils_response%(c:connection,is_orig:bool,tid:count,pid:count event modbus_write_multi_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,wcount:count,len:count%); +#Event that passes modbus response function code=20 +event modbus_read_reference_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,byteCount:count,t:int_vec%); + +#Event that passes modbus response function code=20 for single reference +event modbus_read_single_reference_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,byteCount:count,refType:count,t:int_vec%); + +#Event that passes modbus response function code=21 +event modbus_write_reference_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,byteCount:count,t:int_vec%); + + #Event that passes modbus response function code=22 event modbus_mask_write_response%(c:connection,is_orig:bool,tid:count,pid:count,uid:count,fc:count,ref:count,andMask:count,orMask:count%); diff --git a/src/modbus-analyzer.pac b/src/modbus-analyzer.pac index 220f5bcb10..44ac504652 100644 --- a/src/modbus-analyzer.pac +++ b/src/modbus-analyzer.pac @@ -183,6 +183,161 @@ function deliver_WriteMultiRegReq( writeMulti: WriteMultipleRegistersRequest, ti %} +#REQUEST FC=20 +function deliver_ReadReferenceReq(tid:uint16, pid:uint16, uid: uint8, fc: uint8,refCount:uint8,reference:Reference[]): bool + %{ + + + VectorVal * t=new VectorVal( new VectorType(base_type(TYPE_INT))); + + for (unsigned int i=0; i < (${reference}->size()); ++i) + { + + Val* r=new Val((${reference[i].refType}),TYPE_INT); + t->Assign(i,r,0,OP_ASSIGN); + + Val* k=new Val((${reference[i].refNumber}),TYPE_INT); + t->Assign(i,k,0,OP_ASSIGN); + + Val* l=new Val((${reference[i].wordCount}),TYPE_INT); + t->Assign(i,l,0,OP_ASSIGN); + + + } + + + + if ( ::modbus_read_reference_request ) + { + + BifEvent::generate_modbus_read_reference_request( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,refCount,t); + } + return true; + + %} + +#REQUEST FC=20 (to read single reference) +function deliver_ReadSingleReferenceReq(tid:uint16,pid:uint16,uid:uint8,fc:uint8,refType:uint8,refNumber:uint32,wordCount:uint16): bool + %{ + + if ( ::modbus_read_single_reference_request) + { + BifEvent::generate_modbus_read_single_reference_request( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,refType,refNumber,wordCount); + } + return true; + + %} + + + +#RESPONSE FC=20 (to read single reference) +function deliver_ReadSingleReferenceRes(tid:uint16, pid:uint16, uid: uint8, fc: uint8,byteCount:uint8,refType:uint8,ref:ReferenceResponse): bool + %{ + + + VectorVal * t=new VectorVal( new VectorType(base_type(TYPE_INT))); + + for (unsigned int i=0; i < (${ref.registerValue}->size()); ++i) + { + + Val* r=new Val(((*ref->registerValue())[i]),TYPE_INT); + t->Assign(i,r,0,OP_ASSIGN); + } + + + + if ( ::modbus_read_single_reference_response ) + { + + BifEvent::generate_modbus_read_single_reference_response( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,byteCount,refType,t); + } + return true; + + %} + + + +#REQUEST FC=21 +function deliver_WriteReferenceReq(tid:uint16,pid:uint16,uid:uint8,fc:uint8,byteCount:uint8,reference:ReferenceWithData[]): bool + %{ + + + VectorVal * t=new VectorVal( new VectorType(base_type(TYPE_INT))); + + for (unsigned int i=0; i < (${reference}->size()); ++i) + { + + Val* r=new Val((${reference[i].refType}),TYPE_INT); + t->Assign(i,r,0,OP_ASSIGN); + + Val* k=new Val((${reference[i].refNumber}),TYPE_INT); + t->Assign(i,k,0,OP_ASSIGN); + + Val* n=new Val((${reference[i].wordCount}),TYPE_INT); + t->Assign(i,n,0,OP_ASSIGN); + + for (unsigned int j=0; j<(${reference[i].registerValue}->size());++j) + { + k=new Val((${reference[i].registerValue[j]}),TYPE_INT); + t->Assign(i,k,0,OP_ASSIGN); + } + + } + + + + if ( ::modbus_write_reference_request ) + { + + BifEvent::generate_modbus_write_reference_request( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,byteCount,t); + } + return true; + + %} + + + + +#RESPONSE FC=21 (to write single reference) +function deliver_WriteSingleReference(tid:uint16, pid:uint16, uid: uint8, fc: uint8,refType:uint8,refNumber:uint32,wordCount:uint16,ref:ReferenceWithData): bool + %{ + + + VectorVal * t=new VectorVal( new VectorType(base_type(TYPE_INT))); + + for (unsigned int i=0; i < (${ref.registerValue}->size()); ++i) + { + + Val* r=new Val(((*ref->registerValue())[i]),TYPE_INT); + t->Assign(i,r,0,OP_ASSIGN); + } + + + + if ( ::modbus_write_single_reference) + { + + BifEvent::generate_modbus_write_single_reference( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,refType,refNumber,wordCount,t); + } + return true; + + %} + #REQUEST FC=22 function deliver_MaskWriteRegReq(tid:uint16,pid:uint16,uid:uint8,fc:uint8,ref:uint16,andMask:uint16,orMask:uint16): bool %{ @@ -405,6 +560,88 @@ function deliver_WriteMultiRegRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8, ref: + +#RESPONSE FC=20 +function deliver_ReadReferenceRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,byteCount:uint8,reference:ReferenceResponse[]): bool + %{ + + + VectorVal * t=new VectorVal( new VectorType(base_type(TYPE_INT))); + + for (unsigned int i=0; i < (${reference}->size()); ++i) + { + + Val* r=new Val((${reference[i].byteCount}),TYPE_INT); + t->Assign(i,r,0,OP_ASSIGN); + + Val* k=new Val((${reference[i].refType}),TYPE_INT); + t->Assign(i,k,0,OP_ASSIGN); + + for (unsigned int j=0; j<(${reference[i].registerValue}->size());++j) + { + k=new Val((${reference[i].registerValue[j]}),TYPE_INT); + t->Assign(i,k,0,OP_ASSIGN); + } + + } + + + + if ( ::modbus_read_reference_response ) + { + + BifEvent::generate_modbus_read_reference_response( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,byteCount,t); + } + return true; + + %} + +#RESPONSE FC=21 +function deliver_WriteReferenceRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,byteCount:uint8,reference:ReferenceWithData[]): bool + %{ + + + VectorVal * t=new VectorVal( new VectorType(base_type(TYPE_INT))); + + for (unsigned int i=0; i < (${reference}->size()); ++i) + { + + Val* r=new Val((${reference[i].refType}),TYPE_INT); + t->Assign(i,r,0,OP_ASSIGN); + + Val* k=new Val((${reference[i].refNumber}),TYPE_INT); + t->Assign(i,k,0,OP_ASSIGN); + + Val* n=new Val((${reference[i].wordCount}),TYPE_INT); + t->Assign(i,n,0,OP_ASSIGN); + + for (unsigned int j=0; j<(${reference[i].registerValue}->size());++j) + { + k=new Val((${reference[i].registerValue[j]}),TYPE_INT); + t->Assign(i,k,0,OP_ASSIGN); + } + + } + + + + if ( ::modbus_write_reference_response ) + { + + BifEvent::generate_modbus_write_reference_response( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(),tid,pid,uid,fc,byteCount,t); + } + return true; + + %} + + + #RESPONSE FC=22 function deliver_MaskWriteRegRes(tid:uint16,pid:uint16,uid:uint8,fc:uint8,ref:uint16,andMask:uint16,orMask:uint16): bool %{ diff --git a/src/modbus-protocol.pac b/src/modbus-protocol.pac index 54209427f2..d8c48f2027 100644 --- a/src/modbus-protocol.pac +++ b/src/modbus-protocol.pac @@ -112,19 +112,42 @@ type ModbusTCP_TransportHeader = record { -type Reference = record { +type Reference (header:ModbusTCP_TransportHeader) = record { refType: uint8; refNumber: uint32; wordCount: uint16; +} +&let { +deliver: bool =$context.flow.deliver_ReadSingleReferenceReq(header.tid,header.pid,header.uid,header.fc,refType,refNumber,wordCount); }; -type ReferenceWithData = record { + +type ReferenceWithData (header:ModbusTCP_TransportHeader) = record { refType: uint8; refNumber: uint32; wordCount: uint16; registerValue: uint16[wordCount] &length = 2*wordCount; # TODO: check that the array length is calculated correctly +} +&let { +deliver: bool =$context.flow.deliver_WriteSingleReference(header.tid,header.pid,header.uid,header.fc,refType,refNumber,wordCount,this); +} + +; + +#Dina modified +type ReferenceResponse(header:ModbusTCP_TransportHeader)=record{ + byteCount:uint8; + refType:uint8; + registerValue:uint16[wordCount]; +} + &let { + wordCount : uint8 = byteCount/2; + + deliver: bool =$context.flow.deliver_ReadSingleReferenceRes(header.tid,header.pid,header.uid,header.fc,byteCount,refType,this); + }; + type Exception(len: uint16,header:ModbusTCP_TransportHeader) = record { code: uint8; }&let { @@ -147,8 +170,8 @@ type ModbusTCP_RequestPDU = record { READ_EXCEPTION_STATUS -> readExceptionStatus: ReadExceptionStatusRequest(header.len-2,header); # Class 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); + READ_GENERAL_REFERENCE -> readGeneralreference: ReadGeneralReferenceRequest(header.len-2,header); + WRITE_GENERAL_REFERENCE -> writeGeneralReference: WriteGeneralReferenceRequest(header.len-2,header); 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,header); @@ -251,6 +274,8 @@ deliver: bool =$context.flow.deliver_ReadExceptStatReq(header.tid,header.pid,hea }; # Class 2 requests + +#REQUEST FC=15 type ForceMultipleCoilsRequest(len: uint16,header:ModbusTCP_TransportHeader) = record { referenceNumber: uint16; bitCount: uint16 &check(bitCount <= 800); @@ -261,20 +286,30 @@ type ForceMultipleCoilsRequest(len: uint16,header:ModbusTCP_TransportHeader) = r deliver: bool =$context.flow.deliver_ForceMultiCoilsReq(header.tid,header.pid,header.uid,header.fc,referenceNumber,bitCount,byteCount,coils); }; -type ReadGeneralReferenceRequest(len: uint16) = record { +#REQUEST FC=20 +type ReadGeneralReferenceRequest(len: uint16,header:ModbusTCP_TransportHeader) = record { byteCount: uint8; - references: Reference[referenceCount] &length = byteCount; + references: Reference(header)[referenceCount] &length = byteCount; } &let { referenceCount: uint8 = byteCount/7; + + deliver: bool =$context.flow.deliver_ReadReferenceReq(header.tid,header.pid,header.uid,header.fc,referenceCount,references); + }; -type WriteGeneralReferenceRequest(len: uint16) = record { + +#REQUEST FC=21 +type WriteGeneralReferenceRequest(len: uint16,header:ModbusTCP_TransportHeader) = record { byteCount: uint8; - references: ReferenceWithData[] &until($input.length() == 0) &length = byteCount; -} &length = len; + references: ReferenceWithData(header)[] &until($input.length() == 0) &length = byteCount; +} &length = len, + &let { + deliver: bool =$context.flow.deliver_WriteReferenceReq(header.tid,header.pid,header.uid,header.fc,byteCount,references); + +}; -#REQUEST FC=22 +#REQUESTeFC=22 type MaskWriteRegisterRequest(len: uint16,header: ModbusTCP_TransportHeader) = record { referenceNumber: uint16; andMask: uint16; @@ -323,8 +358,8 @@ type ModbusTCP_ResponsePDU = record { 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,header); - READ_GENERAL_REFERENCE -> readGeneralReference: ReadGeneralReferenceResponse(header.len-2); - WRITE_GENERAL_REFERENCE -> writeGeneralReference: WriteGeneralReferenceResponse(header.len-2); + READ_GENERAL_REFERENCE -> readGeneralReference: ReadGeneralReferenceResponse(header.len-2,header); + WRITE_GENERAL_REFERENCE -> writeGeneralReference: WriteGeneralReferenceResponse(header.len-2,header); 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,header); @@ -450,18 +485,31 @@ deliver: bool =$context.flow.deliver_ForceMultiCoilsRes(header.tid,header.pid,he } ; -type ReadGeneralReferenceResponse(len: uint16) = record { + +###RESPONSE FC=20 +type ReadGeneralReferenceResponse(len: uint16,header:ModbusTCP_TransportHeader) = record { byteCount: uint8; - references: bytestring &length = byteCount; -} &length = len; + #references: bytestring &length = byteCount; + #Dina modified + references:ReferenceResponse (header) [] &until($input.length()==0) &length=byteCount; +} &length = len, +&let{ + deliver: bool =$context.flow.deliver_ReadReferenceRes(header.tid,header.pid,header.uid,header.fc,byteCount,references); +}; -type WriteGeneralReferenceResponse(len: uint16) = record { +###RESPONSE FC=21 +type WriteGeneralReferenceResponse(len: uint16,header:ModbusTCP_TransportHeader) = record { byteCount: uint8; - references: ReferenceWithData[] &until($input.length() == 0) &length = byteCount; -} &length = len; + references: ReferenceWithData(header)[] &until($input.length() == 0) &length = byteCount; +} &length = len, +&let { + deliver: bool =$context.flow.deliver_WriteReferenceRes(header.tid,header.pid,header.uid,header.fc,byteCount,references); + +}; -###RESPONSE FC=22 + +###RESPOeSE FC=22 type MaskWriteRegisterResponse(len: uint16,header:ModbusTCP_TransportHeader) = record { referenceNumber: uint16; andMask: uint16;