aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAitor Garcia <garcia.aitor@gmail.com>2020-12-29 00:14:05 +0100
committerPascal Quantin <pascal@wireshark.org>2020-12-29 20:13:19 +0100
commit8454674581f6d98473f7870902bd4a42202a69ec (patch)
tree61087a5abf39b782b633aa81ea1954c0556b803c
parent71e3969d63d70e1e57b58568926534e963bd3b31 (diff)
GOOSE: Interpret reserve1 S bit
The simulated mirror bit of the reserve1 field is now interpreted. New expert info warning: S bit set and simulation attribute clear.
-rw-r--r--epan/dissectors/asn1/goose/goose.cnf16
-rw-r--r--epan/dissectors/asn1/goose/packet-goose-template.c70
-rw-r--r--epan/dissectors/packet-goose.c112
3 files changed, 177 insertions, 21 deletions
diff --git a/epan/dissectors/asn1/goose/goose.cnf b/epan/dissectors/asn1/goose/goose.cnf
index 750ed29741..6b3ab1131e 100644
--- a/epan/dissectors/asn1/goose/goose.cnf
+++ b/epan/dissectors/asn1/goose/goose.cnf
@@ -16,6 +16,22 @@ GetReferenceRequestPdu/offset getReferenceRequest_offset
#.FIELD_ATTR
GetReferenceRequestPdu/offset ABBREV=getReferenceRequest.offset
+#.FN_BODY IECGoosePdu/simulation VAL_PTR = &value
+ gboolean value;
+ guint32 len = tvb_reported_length_remaining(tvb, offset);
+ int origin_offset = offset;
+%(DEFAULT_BODY)s
+ if((actx->private_data) && (actx->created_item)){
+ goose_chk_data_t *data_chk = (goose_chk_data_t *)actx->private_data;
+ proto_tree *expert_inf_tree = NULL;
+ /* S bit set and Simulation attribute clear: reject as invalid GOOSE */
+ if((data_chk->s_bit == TRUE) && (value == FALSE)){
+ /* It really looks better showed as a new subtree */
+ expert_inf_tree = proto_item_add_subtree(actx->created_item, ett_expert_inf_sim);
+ proto_tree_add_expert(expert_inf_tree, actx->pinfo, &ei_goose_invalid_sim, tvb, origin_offset, len);
+ }
+ }
+#.END
#.FN_BODY UtcTime
diff --git a/epan/dissectors/asn1/goose/packet-goose-template.c b/epan/dissectors/asn1/goose/packet-goose-template.c
index 197972c51e..5a8360c0b7 100644
--- a/epan/dissectors/asn1/goose/packet-goose-template.c
+++ b/epan/dissectors/asn1/goose/packet-goose-template.c
@@ -3,8 +3,8 @@
* Martin Lutz 2008
*
* Routines for IEC 61850 R-GOOSE packet dissection
- * Đorđije Manojlović 2020
- *
+ * Dordije Manojlovic 2020
+ *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
@@ -65,10 +65,21 @@ static int hf_goose_hmac = -1;
static int hf_goose_appid = -1;
static int hf_goose_length = -1;
static int hf_goose_reserve1 = -1;
+static int hf_goose_reserve1_s_bit = -1;
static int hf_goose_reserve2 = -1;
+/* Bit fields in the Reserved fields */
+#define F_RESERVE1_S_BIT 0x8000
+
+/* GOOSE stored data for expert info verifications */
+typedef struct _goose_chk_data{
+ gboolean s_bit;
+}goose_chk_data_t;
+#define GOOSE_CHK_DATA_LEN (sizeof(goose_chk_data_t))
+
static expert_field ei_goose_mal_utctime = EI_INIT;
static expert_field ei_goose_zero_pdu = EI_INIT;
+static expert_field ei_goose_invalid_sim = EI_INIT;
#include "packet-goose-hf.c"
@@ -80,6 +91,8 @@ static int ett_session_user_info = -1;
static int ett_payload = -1;
static int ett_padding = -1;
static int ett_goose = -1;
+static int ett_reserve1 = -1;
+static int ett_expert_inf_sim = -1;
#include "packet-goose-ett.c"
@@ -127,11 +140,21 @@ dissect_goose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
guint32 offset = 0;
guint32 old_offset;
guint32 length;
+ guint32 reserve1_val;
proto_item *item = NULL;
proto_tree *tree = NULL;
+ goose_chk_data_t *data_chk = NULL;
asn1_ctx_t asn1_ctx;
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+ static int * const reserve1_flags[] = {
+ &hf_goose_reserve1_s_bit,
+ NULL
+ };
+
+ asn1_ctx.private_data = wmem_alloc(wmem_packet_scope(), GOOSE_CHK_DATA_LEN);
+ data_chk = (goose_chk_data_t *)asn1_ctx.private_data;
+
col_set_str(pinfo->cinfo, COL_PROTOCOL, GOOSE_PNAME);
col_clear(pinfo->cinfo, COL_INFO);
@@ -147,8 +170,19 @@ dissect_goose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
ENC_BIG_ENDIAN, &length);
/* Reserved 1 */
- proto_tree_add_item(tree, hf_goose_reserve1, tvb, offset + 4, 2,
- ENC_BIG_ENDIAN);
+ reserve1_val = tvb_get_guint16(tvb, offset + 4, ENC_BIG_ENDIAN);
+ proto_tree_add_bitmask_value(tree, tvb, offset + 4, hf_goose_reserve1, ett_reserve1,
+ reserve1_flags, reserve1_val);
+
+ /* Store the header sim value for later expert info checks */
+ if(data_chk){
+ if(reserve1_val & F_RESERVE1_S_BIT){
+ data_chk->s_bit = TRUE;
+ }else{
+ data_chk->s_bit = FALSE;
+ }
+ }
+
/* Reserved 2 */
proto_tree_add_item(tree, hf_goose_reserve2, tvb, offset + 6, 2,
@@ -177,12 +211,16 @@ dissect_rgoose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
{
guint offset = 0, old_offset = 0;
guint32 init_v_length, payload_tag, padding_length, length;
- guint32 payload_length, apdu_offset = 0, apdu_length;
+ guint32 payload_length, apdu_offset = 0, apdu_length, apdu_simulation;
proto_item *item = NULL;
proto_tree *tree = NULL, *r_goose_tree = NULL, *sess_user_info_tree = NULL;
+ goose_chk_data_t *data_chk = NULL;
asn1_ctx_t asn1_ctx;
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+ asn1_ctx.private_data = wmem_alloc(wmem_packet_scope(), GOOSE_CHK_DATA_LEN);
+ data_chk = (goose_chk_data_t *)asn1_ctx.private_data;
+
col_set_str(pinfo->cinfo, COL_PROTOCOL, R_GOOSE_PNAME);
col_clear(pinfo->cinfo, COL_INFO);
@@ -266,8 +304,8 @@ dissect_rgoose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
proto_tree_add_item_ret_uint(tree, hf_goose_apdu_tag, tvb, offset++, 1,
ENC_BIG_ENDIAN, &payload_tag);
/* Simulation flag */
- proto_tree_add_item(tree, hf_goose_apdu_simulation, tvb, offset++, 1,
- ENC_BIG_ENDIAN);
+ proto_tree_add_item_ret_uint(tree, hf_goose_apdu_simulation, tvb, offset++,
+ 1, ENC_BIG_ENDIAN, &apdu_simulation);
/* APPID */
proto_tree_add_item(tree, hf_goose_apdu_appid, tvb, offset, 2,
ENC_BIG_ENDIAN);
@@ -277,6 +315,15 @@ dissect_rgoose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
return tvb_captured_length(tvb);
}
+ /* Store the header sim value for later expert info checks */
+ if(data_chk){
+ if(apdu_simulation){
+ data_chk->s_bit = TRUE;
+ }else{
+ data_chk->s_bit = FALSE;
+ }
+ }
+
/* APDU length */
proto_tree_add_item_ret_uint(tree, hf_goose_apdu_length, tvb, offset, 2,
ENC_BIG_ENDIAN, &apdu_length);
@@ -498,6 +545,10 @@ void proto_register_goose(void) {
{ "Reserved 1", "goose.reserve1",
FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_goose_reserve1_s_bit,
+ { "Simulated", "goose.reserve1.s_bit",
+ FT_BOOLEAN, 16, NULL, F_RESERVE1_S_BIT, "BOOLEAN", HFILL } },
+
{ &hf_goose_reserve2,
{ "Reserved 2", "goose.reserve2",
FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
@@ -514,6 +565,8 @@ void proto_register_goose(void) {
&ett_payload,
&ett_padding,
&ett_goose,
+ &ett_reserve1,
+ &ett_expert_inf_sim,
#include "packet-goose-ettarr.c"
};
@@ -524,6 +577,9 @@ void proto_register_goose(void) {
{ &ei_goose_zero_pdu,
{ "goose.zero_pdu", PI_PROTOCOL, PI_ERROR,
"Internal error, zero-byte GOOSE PDU", EXPFILL }},
+ { &ei_goose_invalid_sim,
+ { "goose.invalid_sim", PI_PROTOCOL, PI_WARN,
+ "Invalid GOOSE: S bit set and Simulation attribute clear", EXPFILL }},
};
expert_module_t* expert_goose;
diff --git a/epan/dissectors/packet-goose.c b/epan/dissectors/packet-goose.c
index cf9b4b8975..4a125d0743 100644
--- a/epan/dissectors/packet-goose.c
+++ b/epan/dissectors/packet-goose.c
@@ -10,6 +10,9 @@
* Routines for IEC 61850 GOOSE packet dissection
* Martin Lutz 2008
*
+ * Routines for IEC 61850 R-GOOSE packet dissection
+ * Dordije Manojlovic 2020
+ *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
@@ -70,10 +73,21 @@ static int hf_goose_hmac = -1;
static int hf_goose_appid = -1;
static int hf_goose_length = -1;
static int hf_goose_reserve1 = -1;
+static int hf_goose_reserve1_s_bit = -1;
static int hf_goose_reserve2 = -1;
+/* Bit fields in the Reserved fields */
+#define F_RESERVE1_S_BIT 0x8000
+
+/* GOOSE stored data for expert info verifications */
+typedef struct _goose_chk_data{
+ gboolean s_bit;
+}goose_chk_data_t;
+#define GOOSE_CHK_DATA_LEN (sizeof(goose_chk_data_t))
+
static expert_field ei_goose_mal_utctime = EI_INIT;
static expert_field ei_goose_zero_pdu = EI_INIT;
+static expert_field ei_goose_invalid_sim = EI_INIT;
/*--- Included file: packet-goose-hf.c ---*/
@@ -114,7 +128,7 @@ static int hf_goose_goID = -1; /* VisibleString */
static int hf_goose_t = -1; /* UtcTime */
static int hf_goose_stNum = -1; /* INTEGER */
static int hf_goose_sqNum = -1; /* INTEGER */
-static int hf_goose_simulation = -1; /* BOOLEAN */
+static int hf_goose_simulation = -1; /* T_simulation */
static int hf_goose_ndsCom = -1; /* BOOLEAN */
static int hf_goose_numDatSetEntries = -1; /* INTEGER */
static int hf_goose_allData = -1; /* SEQUENCE_OF_Data */
@@ -139,7 +153,7 @@ static int hf_goose_mMSString = -1; /* MMSString */
static int hf_goose_utc_time = -1; /* UtcTime */
/*--- End of included file: packet-goose-hf.c ---*/
-#line 71 "./asn1/goose/packet-goose-template.c"
+#line 85 "./asn1/goose/packet-goose-template.c"
/* Initialize the subtree pointers */
static int ett_r_goose = -1;
@@ -149,6 +163,8 @@ static int ett_session_user_info = -1;
static int ett_payload = -1;
static int ett_padding = -1;
static int ett_goose = -1;
+static int ett_reserve1 = -1;
+static int ett_expert_inf_sim = -1;
/*--- Included file: packet-goose-ett.c ---*/
@@ -172,7 +188,7 @@ static gint ett_goose_SEQUENCE_OF_Data = -1;
static gint ett_goose_Data = -1;
/*--- End of included file: packet-goose-ett.c ---*/
-#line 82 "./asn1/goose/packet-goose-template.c"
+#line 98 "./asn1/goose/packet-goose-template.c"
/*--- Included file: packet-goose-fn.c ---*/
@@ -499,7 +515,7 @@ dissect_goose_GSEMngtPdu(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offse
static int
dissect_goose_UtcTime(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
-#line 21 "./asn1/goose/goose.cnf"
+#line 37 "./asn1/goose/goose.cnf"
guint32 len;
guint32 seconds;
@@ -546,6 +562,31 @@ dissect_goose_UtcTime(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _
static int
+dissect_goose_T_simulation(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 20 "./asn1/goose/goose.cnf"
+ gboolean value;
+ guint32 len = tvb_reported_length_remaining(tvb, offset);
+ int origin_offset = offset;
+ offset = dissect_ber_boolean(implicit_tag, actx, tree, tvb, offset, hf_index, &value);
+
+ if((actx->private_data) && (actx->created_item)){
+ goose_chk_data_t *data_chk = (goose_chk_data_t *)actx->private_data;
+ proto_tree *expert_inf_tree = NULL;
+ /* S bit set and Simulation attribute clear: reject as invalid GOOSE */
+ if((data_chk->s_bit == TRUE) && (value == FALSE)){
+ /* It really looks better showed as a new subtree */
+ expert_inf_tree = proto_item_add_subtree(actx->created_item, ett_expert_inf_sim);
+ proto_tree_add_expert(expert_inf_tree, actx->pinfo, &ei_goose_invalid_sim, tvb, origin_offset, len);
+ }
+ }
+
+
+ return offset;
+}
+
+
+
+static int
dissect_goose_BOOLEAN(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
offset = dissect_ber_boolean(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
@@ -695,7 +736,7 @@ static const ber_sequence_t IECGoosePdu_sequence[] = {
{ &hf_goose_t , BER_CLASS_CON, 4, BER_FLAGS_IMPLTAG, dissect_goose_UtcTime },
{ &hf_goose_stNum , BER_CLASS_CON, 5, BER_FLAGS_IMPLTAG, dissect_goose_INTEGER },
{ &hf_goose_sqNum , BER_CLASS_CON, 6, BER_FLAGS_IMPLTAG, dissect_goose_INTEGER },
- { &hf_goose_simulation , BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_goose_BOOLEAN },
+ { &hf_goose_simulation , BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_goose_T_simulation },
{ &hf_goose_confRev , BER_CLASS_CON, 8, BER_FLAGS_IMPLTAG, dissect_goose_INTEGER },
{ &hf_goose_ndsCom , BER_CLASS_CON, 9, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_goose_BOOLEAN },
{ &hf_goose_numDatSetEntries, BER_CLASS_CON, 10, BER_FLAGS_IMPLTAG, dissect_goose_INTEGER },
@@ -729,7 +770,7 @@ dissect_goose_GOOSEpdu(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset
/*--- End of included file: packet-goose-fn.c ---*/
-#line 84 "./asn1/goose/packet-goose-template.c"
+#line 100 "./asn1/goose/packet-goose-template.c"
static dissector_handle_t goose_handle = NULL;
static dissector_handle_t ositp_handle = NULL;
@@ -773,11 +814,21 @@ dissect_goose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
guint32 offset = 0;
guint32 old_offset;
guint32 length;
+ guint32 reserve1_val;
proto_item *item = NULL;
proto_tree *tree = NULL;
+ goose_chk_data_t *data_chk = NULL;
asn1_ctx_t asn1_ctx;
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+ static int * const reserve1_flags[] = {
+ &hf_goose_reserve1_s_bit,
+ NULL
+ };
+
+ asn1_ctx.private_data = wmem_alloc(wmem_packet_scope(), GOOSE_CHK_DATA_LEN);
+ data_chk = (goose_chk_data_t *)asn1_ctx.private_data;
+
col_set_str(pinfo->cinfo, COL_PROTOCOL, GOOSE_PNAME);
col_clear(pinfo->cinfo, COL_INFO);
@@ -793,8 +844,19 @@ dissect_goose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
ENC_BIG_ENDIAN, &length);
/* Reserved 1 */
- proto_tree_add_item(tree, hf_goose_reserve1, tvb, offset + 4, 2,
- ENC_BIG_ENDIAN);
+ reserve1_val = tvb_get_guint16(tvb, offset + 4, ENC_BIG_ENDIAN);
+ proto_tree_add_bitmask_value(tree, tvb, offset + 4, hf_goose_reserve1, ett_reserve1,
+ reserve1_flags, reserve1_val);
+
+ /* Store the header sim value for later expert info checks */
+ if(data_chk){
+ if(reserve1_val & F_RESERVE1_S_BIT){
+ data_chk->s_bit = TRUE;
+ }else{
+ data_chk->s_bit = FALSE;
+ }
+ }
+
/* Reserved 2 */
proto_tree_add_item(tree, hf_goose_reserve2, tvb, offset + 6, 2,
@@ -823,12 +885,16 @@ dissect_rgoose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
{
guint offset = 0, old_offset = 0;
guint32 init_v_length, payload_tag, padding_length, length;
- guint32 payload_length, apdu_offset = 0, apdu_length;
+ guint32 payload_length, apdu_offset = 0, apdu_length, apdu_simulation;
proto_item *item = NULL;
proto_tree *tree = NULL, *r_goose_tree = NULL, *sess_user_info_tree = NULL;
+ goose_chk_data_t *data_chk = NULL;
asn1_ctx_t asn1_ctx;
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+ asn1_ctx.private_data = wmem_alloc(wmem_packet_scope(), GOOSE_CHK_DATA_LEN);
+ data_chk = (goose_chk_data_t *)asn1_ctx.private_data;
+
col_set_str(pinfo->cinfo, COL_PROTOCOL, R_GOOSE_PNAME);
col_clear(pinfo->cinfo, COL_INFO);
@@ -912,8 +978,8 @@ dissect_rgoose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
proto_tree_add_item_ret_uint(tree, hf_goose_apdu_tag, tvb, offset++, 1,
ENC_BIG_ENDIAN, &payload_tag);
/* Simulation flag */
- proto_tree_add_item(tree, hf_goose_apdu_simulation, tvb, offset++, 1,
- ENC_BIG_ENDIAN);
+ proto_tree_add_item_ret_uint(tree, hf_goose_apdu_simulation, tvb, offset++,
+ 1, ENC_BIG_ENDIAN, &apdu_simulation);
/* APPID */
proto_tree_add_item(tree, hf_goose_apdu_appid, tvb, offset, 2,
ENC_BIG_ENDIAN);
@@ -923,6 +989,15 @@ dissect_rgoose(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
return tvb_captured_length(tvb);
}
+ /* Store the header sim value for later expert info checks */
+ if(data_chk){
+ if(apdu_simulation){
+ data_chk->s_bit = TRUE;
+ }else{
+ data_chk->s_bit = FALSE;
+ }
+ }
+
/* APDU length */
proto_tree_add_item_ret_uint(tree, hf_goose_apdu_length, tvb, offset, 2,
ENC_BIG_ENDIAN, &apdu_length);
@@ -1144,6 +1219,10 @@ void proto_register_goose(void) {
{ "Reserved 1", "goose.reserve1",
FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_goose_reserve1_s_bit,
+ { "Simulated", "goose.reserve1.s_bit",
+ FT_BOOLEAN, 16, NULL, F_RESERVE1_S_BIT, "BOOLEAN", HFILL } },
+
{ &hf_goose_reserve2,
{ "Reserved 2", "goose.reserve2",
FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
@@ -1298,7 +1377,7 @@ void proto_register_goose(void) {
{ &hf_goose_simulation,
{ "simulation", "goose.simulation",
FT_BOOLEAN, BASE_NONE, NULL, 0,
- "BOOLEAN", HFILL }},
+ NULL, HFILL }},
{ &hf_goose_ndsCom,
{ "ndsCom", "goose.ndsCom",
FT_BOOLEAN, BASE_NONE, NULL, 0,
@@ -1389,7 +1468,7 @@ void proto_register_goose(void) {
"UtcTime", HFILL }},
/*--- End of included file: packet-goose-hfarr.c ---*/
-#line 503 "./asn1/goose/packet-goose-template.c"
+#line 557 "./asn1/goose/packet-goose-template.c"
};
/* List of subtrees */
@@ -1401,6 +1480,8 @@ void proto_register_goose(void) {
&ett_payload,
&ett_padding,
&ett_goose,
+ &ett_reserve1,
+ &ett_expert_inf_sim,
/*--- Included file: packet-goose-ettarr.c ---*/
#line 1 "./asn1/goose/packet-goose-ettarr.c"
@@ -1423,7 +1504,7 @@ void proto_register_goose(void) {
&ett_goose_Data,
/*--- End of included file: packet-goose-ettarr.c ---*/
-#line 515 "./asn1/goose/packet-goose-template.c"
+#line 571 "./asn1/goose/packet-goose-template.c"
};
static ei_register_info ei[] = {
@@ -1433,6 +1514,9 @@ void proto_register_goose(void) {
{ &ei_goose_zero_pdu,
{ "goose.zero_pdu", PI_PROTOCOL, PI_ERROR,
"Internal error, zero-byte GOOSE PDU", EXPFILL }},
+ { &ei_goose_invalid_sim,
+ { "goose.invalid_sim", PI_PROTOCOL, PI_WARN,
+ "Invalid GOOSE: S bit set and Simulation attribute clear", EXPFILL }},
};
expert_module_t* expert_goose;