diff options
author | Aitor Garcia <garcia.aitor@gmail.com> | 2020-12-29 00:14:05 +0100 |
---|---|---|
committer | Pascal Quantin <pascal@wireshark.org> | 2020-12-29 20:13:19 +0100 |
commit | 8454674581f6d98473f7870902bd4a42202a69ec (patch) | |
tree | 61087a5abf39b782b633aa81ea1954c0556b803c | |
parent | 71e3969d63d70e1e57b58568926534e963bd3b31 (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.cnf | 16 | ||||
-rw-r--r-- | epan/dissectors/asn1/goose/packet-goose-template.c | 70 | ||||
-rw-r--r-- | epan/dissectors/packet-goose.c | 112 |
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; |