aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/asn1/goose
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 /epan/dissectors/asn1/goose
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.
Diffstat (limited to 'epan/dissectors/asn1/goose')
-rw-r--r--epan/dissectors/asn1/goose/goose.cnf16
-rw-r--r--epan/dissectors/asn1/goose/packet-goose-template.c70
2 files changed, 79 insertions, 7 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;