diff options
author | jake <jake@f5534014-38df-0310-8fa8-9805f1628bb7> | 2010-12-22 23:28:23 +0000 |
---|---|---|
committer | jake <jake@f5534014-38df-0310-8fa8-9805f1628bb7> | 2010-12-22 23:28:23 +0000 |
commit | 2b4b2836f88d620a8e3ec710573be10b6f336105 (patch) | |
tree | d469df3229bdde90530f2d9cb23a58b9df2515ff /epan/dissectors/packet-iec104.c | |
parent | f61aa44bfa4299e0548b1a1b4efce1aaa8e274dd (diff) |
From Jiří Engelthaler:
Fixes computing of milliseconds in CP56time2a and add "bitstring of 32 bits"
and "step position" support (ASDU types 5,7,32,33,47,51,60 and 64).
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@35249 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors/packet-iec104.c')
-rw-r--r-- | epan/dissectors/packet-iec104.c | 202 |
1 files changed, 186 insertions, 16 deletions
diff --git a/epan/dissectors/packet-iec104.c b/epan/dissectors/packet-iec104.c index dbb87bacae..79c3d89d91 100644 --- a/epan/dissectors/packet-iec104.c +++ b/epan/dissectors/packet-iec104.c @@ -72,7 +72,7 @@ struct apciheader { /* asdu value time stamp structure */ typedef struct { - guint8 cp56t_ms; + guint16 cp56t_ms; guint8 cp56t_s; guint8 cp56t_min; guint8 cp56t_h; @@ -124,6 +124,9 @@ typedef struct { gboolean OFF; gboolean ON; + gboolean UP; + gboolean DOWN; + /* QOC qualifier-bits */ guint16 QU; /* qualifier-value */ gboolean ZeroP; /* No pulse */ @@ -475,8 +478,9 @@ static int hf_ioa = -1; static int hf_numix = -1; static int hf_sq = -1; -static gint hf_iec104_asdufloat = -1; -static gint hf_iec104_asdunormval = -1; +static gint hf_asdu_bitstring = -1; +static gint hf_asdu_float = -1; +static gint hf_asdu_normval = -1; static gint ett_apci = -1; static gint ett_asdu = -1; @@ -668,13 +672,22 @@ static void get_QDP( td_ValueInfo *value _U_, tvbuff_t *tvb _U_, guint8 *offset /* ==================================================================== VTI: Value with transient state indication ==================================================================== */ -#if 0 static void get_VTI( td_ValueInfo *value _U_, tvbuff_t *tvb _U_, guint8 *offset _U_, proto_tree *iec104_header_tree _U_ ) { - /* todo */ + guint8 vti; + vti = tvb_get_guint8(tvb, *offset); + + value->MV.VTI= vti & 0x7F; + value->TRANSIENT = (vti & 0x80) != 0; + + if( iec104_header_tree != NULL ) + { + proto_tree_add_text( iec104_header_tree, tvb, *offset, 1, "Value: %d - Status: %s", + value->MV.VTI, value->TRANSIENT?"Transient":"Not transient" ); + } + (*offset)++; } -#endif /* ==================================================================== NVA: Normalized value @@ -686,7 +699,7 @@ static void get_NVA( td_ValueInfo *value, tvbuff_t *tvb, guint8 *offset, proto_t if ( iec104_header_tree != NULL ) { - proto_tree_add_int(iec104_header_tree, hf_iec104_asdunormval, + proto_tree_add_int(iec104_header_tree, hf_asdu_normval, tvb, *offset, 2, value->MV.NVA); /* todo ... presentation as float +/- 1 (val/32767) ... */ } @@ -702,7 +715,7 @@ static void get_NVAspt( td_SpInfo *spt, tvbuff_t *tvb, guint8 *offset, if ( iec104_header_tree != NULL ) { - proto_tree_add_int(iec104_header_tree, hf_iec104_asdunormval, + proto_tree_add_int(iec104_header_tree, hf_asdu_normval, tvb, *offset, 2, spt->SP.NVA); /* todo ... presentation as float +/- 1 */ } @@ -719,7 +732,7 @@ static void get_SVA( td_ValueInfo *value, tvbuff_t *tvb, guint8 *offset, proto_t value->MV.SVA = tvb_get_letohs(tvb, *offset); if ( iec104_header_tree != NULL ) { - proto_tree_add_int(iec104_header_tree, hf_iec104_asdunormval, + proto_tree_add_int(iec104_header_tree, hf_asdu_normval, tvb, *offset, 2, value->MV.SVA); } (*offset) += 2; @@ -733,7 +746,7 @@ static void get_SVAspt( td_SpInfo *spt, tvbuff_t *tvb, guint8 *offset, spt->SP.SVA = tvb_get_letohs(tvb, *offset); if ( iec104_header_tree != NULL ) { - proto_tree_add_int(iec104_header_tree, hf_iec104_asdunormval, + proto_tree_add_int(iec104_header_tree, hf_asdu_normval, tvb, *offset, 2, spt->SP.SVA); } (*offset) += 2; @@ -750,7 +763,7 @@ static void get_FLT( td_ValueInfo *value, tvbuff_t *tvb, guint8 *offset, proto_t if ( iec104_header_tree != NULL ) { - proto_tree_add_float(iec104_header_tree, hf_iec104_asdufloat, + proto_tree_add_float(iec104_header_tree, hf_asdu_float, tvb, *offset, 4, value->MV.FLT); } (*offset) += 4; @@ -765,7 +778,7 @@ static void get_FLTspt( td_SpInfo *spt, tvbuff_t *tvb, guint8 *offset, proto_tre if ( iec104_header_tree != NULL ) { - proto_tree_add_float(iec104_header_tree, hf_iec104_asdufloat, + proto_tree_add_float(iec104_header_tree, hf_asdu_float, tvb, *offset, 4, spt->SP.FLT); } (*offset) += 4; @@ -774,6 +787,31 @@ static void get_FLTspt( td_SpInfo *spt, tvbuff_t *tvb, guint8 *offset, proto_tre } /* ==================================================================== + "BSI": Binary state information, 32 bit + ==================================================================== */ +static void get_BSI( td_ValueInfo *value _U_, tvbuff_t *tvb, guint8 *offset, proto_tree *iec104_header_tree ) +{ + if ( iec104_header_tree != NULL ) + { + proto_tree_add_bits_item(iec104_header_tree, hf_asdu_bitstring, + tvb, *offset*8, 32, ENC_BIG_ENDIAN); + } + (*offset) += 4; + +} + +static void get_BSIspt( td_ValueInfo *value _U_, tvbuff_t *tvb, guint8 *offset, proto_tree *iec104_header_tree ) +{ + if ( iec104_header_tree != NULL ) + { + proto_tree_add_bits_item(iec104_header_tree, hf_asdu_bitstring, + tvb, *offset*8, 32, ENC_BIG_ENDIAN); + } + (*offset) += 4; + +} + +/* ==================================================================== todo -- BCR: Binary counter reading ==================================================================== */ /* void get_BCR( td_ValueInfo *value, tvbuff_t *tvb, guint8 *offset, @@ -933,6 +971,54 @@ static void get_DCO( td_CmdInfo *value, tvbuff_t *tvb, guint8 *offset, proto_tre (*offset)++; } + +/* ==================================================================== + RCO: Regulating step command (IEV 371-03-13) + ==================================================================== */ +static void get_RCO( td_CmdInfo *value, tvbuff_t *tvb, guint8 *offset, proto_tree *iec104_header_tree ) +{ + guint8 data; + /* Up/Down */ + data = tvb_get_guint8(tvb, *offset); + value->UP = FALSE; + value->DOWN = FALSE; + switch ( data & 0x03 ) + { + case 1: + value->DOWN = TRUE; + break; + case 2: + value->UP = TRUE; + break; + default: + ; + break; + } + + /* QOC */ + get_QOC( value, data ); + + + if( iec104_header_tree != NULL ) + { + if ( value->QU < 4 ) + { + proto_tree_add_text( iec104_header_tree, tvb, *offset, 1, "Command: %s%s%s, Qualifier: %s%s%s%s, %s", + value->UP?"UP":"", value->DOWN?"DOWN":"", (value->UP | value->DOWN)?"":"Error: On/Off not defined", + value->ZeroP?"No pulse defined":"", value->ShortP?"Short Pulse":"", + value->LongP?"Long Pulse":"", value->Persist?"Persistent Output":"", + value->SE?"Select":"Execute"); + } else { + proto_tree_add_text( iec104_header_tree, tvb, *offset, 1, "Command: %s%s%s, Qualifier: QU=%d, %s", + value->UP?"UP":"", value->DOWN?"DOWN":"", (value->UP | value->DOWN)?"":"Error: On/Off not defined", + value->QU, + value->SE?"Select":"Execute"); + } + } + + (*offset)++; + +} /* .... end Misc. functions for dissection of signal values */ @@ -1060,8 +1146,12 @@ static void dissect_iec104asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr switch (asduh->TypeId) { case M_SP_NA_1: case M_DP_NA_1: + case M_ST_NA_1: + case M_BO_NA_1: case M_SP_TB_1: case M_DP_TB_1: + case M_ST_TB_1: + case M_BO_TB_1: case M_ME_NA_1: case M_ME_NB_1: case M_ME_NC_1: @@ -1071,14 +1161,18 @@ static void dissect_iec104asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr case M_ME_TF_1: case C_SC_NA_1: case C_DC_NA_1: + case C_RC_NA_1: case C_SE_NA_1: case C_SE_NB_1: case C_SE_NC_1: + case C_BO_NA_1: case C_SC_TA_1: case C_DC_TA_1: + case C_RC_TA_1: case C_SE_TA_1: case C_SE_TB_1: case C_SE_TC_1: + case C_BO_TA_1: case C_CS_NA_1: /* create subtree for the signal values ... */ @@ -1143,6 +1237,24 @@ static void dissect_iec104asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr } get_DIQ( &value, tvb, &offset, trSignal ); break; + case M_ST_NA_1: /* 5 Step position information */ + /* check length */ + if( Len < (guint)(offset+2) ) { + proto_tree_add_text( trSignal, tvb, offset, 1, "<ERR Short Asdu>" ); + return; + } + get_VTI( &value, tvb, &offset, trSignal ); + get_QDS( &value, tvb, &offset, trSignal ); + break; + case M_BO_NA_1: /* 7 Bitstring of 32 bits */ + /* check length */ + if( Len < (guint)(offset+5) ) { + proto_tree_add_text( trSignal, tvb, offset, 1, "<ERR Short Asdu>" ); + return; + } + get_BSI( &value, tvb, &offset, trSignal ); + get_QDS( &value, tvb, &offset, trSignal ); + break; case M_ME_NA_1: /* 9 Measured value, normalized value */ /* check length */ if( Len < (guint)(offset+3) ) { @@ -1196,6 +1308,26 @@ static void dissect_iec104asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr get_DIQ( &value, tvb, &offset, trSignal ); get_CP56Time( &cp56t, tvb, &offset, trSignal ); break; + case M_ST_TB_1: /* 32 Step position information with time tag CP56Time2a */ + /* check length */ + if( Len < (guint)(offset+9) ) { + proto_tree_add_text( trSignal, tvb, offset, 1, "<ERR Short Asdu>" ); + return; + } + get_VTI( &value, tvb, &offset, trSignal ); + get_QDS( &value, tvb, &offset, trSignal ); + get_CP56Time( &cp56t, tvb, &offset, trSignal ); + break; + case M_BO_TB_1: /* 33 bitstring of 32 bit with time tag CP56Time2a */ + /* check length */ + if( Len < (guint)(offset+12) ) { + proto_tree_add_text( trSignal, tvb, offset, 1, "<ERR Short Asdu>" ); + return; + } + get_BSI( &value, tvb, &offset, trSignal ); + get_QDS( &value, tvb, &offset, trSignal ); + get_CP56Time( &cp56t, tvb, &offset, trSignal ); + break; case M_ME_TD_1: /* 34 Measured value, normalized value with time tag CP56Time2a */ /* check length */ if( Len < (guint)(offset+10) ) { @@ -1242,6 +1374,14 @@ static void dissect_iec104asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr } get_DCO( &cmd, tvb, &offset, trSignal ); break; + case C_RC_NA_1: /* 47 Regulating step command */ + /* check length */ + if( Len < (guint)(offset+1) ) { + proto_tree_add_text( trSignal, tvb, offset, 1, "<ERR Short Asdu>" ); + return; + } + get_RCO( &cmd, tvb, &offset, trSignal ); + break; case C_SE_NA_1: /* 48 Set point command, normalized value */ /* check length */ if( Len < (guint)(offset+3) ) { @@ -1269,6 +1409,14 @@ static void dissect_iec104asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr get_FLTspt( &spt, tvb, &offset, trSignal ); get_QOS( &spt, tvb, &offset, trSignal ); break; + case C_BO_NA_1: /* 51 Bitstring of 32 bits */ + /* check length */ + if( Len < (guint)(offset+4) ) { + proto_tree_add_text( trSignal, tvb, offset, 1, "<ERR Short Asdu>" ); + return; + } + get_BSIspt( &value, tvb, &offset, trSignal ); + break; case C_SC_TA_1: /* 58 Single command with time tag CP56Time2a */ /* check length */ if( Len < (guint)(offset+8) ) { @@ -1287,6 +1435,15 @@ static void dissect_iec104asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr get_DCO( &cmd, tvb, &offset, trSignal ); get_CP56Time( &cp56t, tvb, &offset, trSignal ); break; + case C_RC_TA_1: /* 60 Regulating step command with time tag CP56Time2a */ + /* check length */ + if( Len < (guint)(offset+8) ) { + proto_tree_add_text( trSignal, tvb, offset, 1, "<ERR Short Asdu>" ); + return; + } + get_RCO( &cmd, tvb, &offset, trSignal ); + get_CP56Time( &cp56t, tvb, &offset, trSignal ); + break; case C_SE_TA_1: /* 61 Set point command, normalized value with time tag CP56Time2a */ /* check length */ if( Len < (guint)(offset+10) ) { @@ -1317,6 +1474,15 @@ static void dissect_iec104asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr get_QOS( &spt, tvb, &offset, trSignal ); get_CP56Time( &cp56t, tvb, &offset, trSignal ); break; + case C_BO_TA_1: /* 64 Bitstring of 32 bits with time tag CP56Time2a */ + /* check length */ + if( Len < (guint)(offset+11) ) { + proto_tree_add_text( trSignal, tvb, offset, 1, "<ERR Short Asdu>" ); + return; + } + get_BSIspt( &value, tvb, &offset, trSignal ); + get_CP56Time( &cp56t, tvb, &offset, trSignal ); + break; case C_CS_NA_1: /* 103 clock synchronization command */ /* check length */ if( Len < (guint)(offset+7) ) { @@ -1559,12 +1725,16 @@ proto_register_iec104asdu(void) { "SQ", "104asdu.sq", FT_BOOLEAN, 8, NULL, F_SQ, "Sequence", HFILL }}, - { &hf_iec104_asdufloat, - { "Object value", "iec104.asdu_float", FT_FLOAT, BASE_NONE, NULL, 0x0, + { &hf_asdu_bitstring, + { "Object value", "104asdu.bitstring", FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_asdu_float, + { "Object value", "104asdu.float", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }}, - { &hf_iec104_asdunormval, - { "Object value", "iec104.asdu_asdunormval", FT_INT16, BASE_DEC, NULL, 0x0, + { &hf_asdu_normval, + { "Object value", "104asdu.normval", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, }; |