diff options
Diffstat (limited to 'epan/dissectors/packet-iec104.c')
-rw-r--r-- | epan/dissectors/packet-iec104.c | 508 |
1 files changed, 261 insertions, 247 deletions
diff --git a/epan/dissectors/packet-iec104.c b/epan/dissectors/packet-iec104.c index e743b95024..d506862d63 100644 --- a/epan/dissectors/packet-iec104.c +++ b/epan/dissectors/packet-iec104.c @@ -36,6 +36,10 @@ void proto_reg_handoff_iec60870_5_103(void); void proto_register_iec60870_asdu(void); static dissector_handle_t iec60870_asdu_handle; +static dissector_handle_t iec60870_104_handle; +static dissector_handle_t iec60870_101_handle; +static dissector_handle_t iec60870_5_103_handle; + /* the asdu header structure */ struct asduheader { @@ -75,10 +79,10 @@ typedef struct { #define IEC104_PORT 2404 /* Define the iec101/103/104 protos */ -static int proto_iec60870_101 = -1; -static int proto_iec60870_5_103 = -1; -static int proto_iec60870_104 = -1; -static int proto_iec60870_asdu = -1; +static int proto_iec60870_101; +static int proto_iec60870_5_103; +static int proto_iec60870_104; +static int proto_iec60870_asdu; /* Protocol constants */ #define APCI_START 0x68 @@ -110,7 +114,7 @@ static const value_string apci_types [] = { { 0, NULL } }; -/* Constants relative to the filed, independent of the field position in the byte */ +/* Constants relative to the field, independent of the field position in the byte */ /* U (Unnumbered) constants */ #define U_STARTDT_ACT 0x01 #define U_STARTDT_CON 0x02 @@ -655,143 +659,146 @@ static const true_false_string tfs_local_dst = { "DST", "Local" }; static const true_false_string tfs_coi_i = { "Initialisation after change of local parameters", "Initialisation with unchanged local parameters" }; static const true_false_string tfs_adjusted_not_adjusted = { "Adjusted", "Not Adjusted" }; +static guint global_iec60870_link_addr_len = 1; static guint global_iec60870_cot_len = 1; static guint global_iec60870_asdu_addr_len = 1; static guint global_iec60870_ioa_len = 2; /* Protocol fields to be filtered */ -static int hf_apdulen = -1; -static int hf_apcitype = -1; -static int hf_apciutype = -1; -static int hf_apcitx = -1; -static int hf_apcirx = -1; -static int hf_apcidata = -1; - -static int hf_addr = -1; -static int hf_oa = -1; -static int hf_typeid = -1; -static int hf_causetx = -1; -static int hf_nega = -1; -static int hf_test = -1; -static int hf_ioa = -1; -static int hf_numix = -1; -static int hf_sq = -1; -static int hf_cp24time = -1; -static int hf_cp24time_ms = -1; -static int hf_cp24time_min = -1; -static int hf_cp24time_iv = -1; -static int hf_cp56time = -1; -static int hf_cp56time_ms = -1; -static int hf_cp56time_min = -1; -static int hf_cp56time_gen = -1; -static int hf_cp56time_iv = -1; -static int hf_cp56time_hour = -1; -static int hf_cp56time_su = -1; -static int hf_cp56time_day = -1; -static int hf_cp56time_dow = -1; -static int hf_cp56time_month = -1; -static int hf_cp56time_year = -1; -static int hf_siq = -1; -static int hf_siq_spi = -1; -static int hf_siq_bl = -1; -static int hf_siq_sb = -1; -static int hf_siq_nt = -1; -static int hf_siq_iv = -1; -static int hf_diq = -1; -static int hf_diq_dpi = -1; -static int hf_diq_bl = -1; -static int hf_diq_sb = -1; -static int hf_diq_nt = -1; -static int hf_diq_iv = -1; -static int hf_qds = -1; -static int hf_qds_ov = -1; -static int hf_qds_bl = -1; -static int hf_qds_sb = -1; -static int hf_qds_nt = -1; -static int hf_qds_iv = -1; -static int hf_vti = -1; -static int hf_vti_v = -1; -static int hf_vti_t = -1; -static int hf_qos = -1; -static int hf_qos_ql = -1; -static int hf_qos_se = -1; -static int hf_sco = -1; -static int hf_sco_on = -1; -static int hf_sco_qu = -1; -static int hf_sco_se = -1; -static int hf_dco = -1; -static int hf_dco_on = -1; -static int hf_dco_qu = -1; -static int hf_dco_se = -1; -static int hf_rco = -1; -static int hf_rco_up = -1; -static int hf_rco_qu = -1; -static int hf_rco_se = -1; -static int hf_qpm = -1; -static int hf_qpm_kpa = -1; -static int hf_qpm_lpc = -1; -static int hf_qpm_pop = -1; -static int hf_coi = -1; -static int hf_coi_r = -1; -static int hf_coi_i = -1; -static int hf_qoi = -1; -static int hf_qcc = -1; -static int hf_qcc_rqt = -1; -static int hf_qcc_frz = -1; -static int hf_qrp = -1; -static int hf_bcr_count = -1; -static int hf_bcr_sq = -1; -static int hf_bcr_cy = -1; -static int hf_bcr_ca = -1; -static int hf_bcr_iv = -1; -static int hf_start = -1; - -static int hf_asdu_bitstring = -1; -static int hf_asdu_float = -1; -static int hf_asdu_normval = -1; -static int hf_asdu_scalval = -1; -static int hf_asdu_raw_data = -1; - -static gint ett_apci = -1; -static gint ett_asdu = -1; -static gint ett_asdu_objects = -1; -static gint ett_siq = -1; -static gint ett_diq = -1; -static gint ett_vti = -1; -static gint ett_qds = -1; -static gint ett_qos = -1; -static gint ett_sco = -1; -static gint ett_dco = -1; -static gint ett_rco = -1; -static gint ett_qpm = -1; -static gint ett_coi = -1; -static gint ett_qcc = -1; -static gint ett_cp24time = -1; -static gint ett_cp56time = -1; - -static expert_field ei_iec104_short_asdu = EI_INIT; -static expert_field ei_iec104_apdu_min_len = EI_INIT; -static expert_field ei_iec104_apdu_invalid_len = EI_INIT; +static int hf_apdulen; +static int hf_apcitype_i; +static int hf_apcitype_s_u; +static int hf_apciutype; +static int hf_apcitx; +static int hf_apcirx; +static int hf_apcidata; + +static int hf_addr; +static int hf_oa; +static int hf_typeid; +static int hf_causetx; +static int hf_nega; +static int hf_test; +static int hf_ioa; +static int hf_numix; +static int hf_sq; +static int hf_cp24time; +static int hf_cp24time_ms; +static int hf_cp24time_min; +static int hf_cp24time_iv; +static int hf_cp56time; +static int hf_cp56time_ms; +static int hf_cp56time_min; +static int hf_cp56time_gen; +static int hf_cp56time_iv; +static int hf_cp56time_hour; +static int hf_cp56time_su; +static int hf_cp56time_day; +static int hf_cp56time_dow; +static int hf_cp56time_month; +static int hf_cp56time_year; +static int hf_siq; +static int hf_siq_spi; +static int hf_siq_bl; +static int hf_siq_sb; +static int hf_siq_nt; +static int hf_siq_iv; +static int hf_diq; +static int hf_diq_dpi; +static int hf_diq_bl; +static int hf_diq_sb; +static int hf_diq_nt; +static int hf_diq_iv; +static int hf_qds; +static int hf_qds_ov; +static int hf_qds_bl; +static int hf_qds_sb; +static int hf_qds_nt; +static int hf_qds_iv; +static int hf_vti; +static int hf_vti_v; +static int hf_vti_t; +static int hf_qos; +static int hf_qos_ql; +static int hf_qos_se; +static int hf_sco; +static int hf_sco_on; +static int hf_sco_qu; +static int hf_sco_se; +static int hf_dco; +static int hf_dco_on; +static int hf_dco_qu; +static int hf_dco_se; +static int hf_rco; +static int hf_rco_up; +static int hf_rco_qu; +static int hf_rco_se; +static int hf_qpm; +static int hf_qpm_kpa; +static int hf_qpm_lpc; +static int hf_qpm_pop; +static int hf_coi; +static int hf_coi_r; +static int hf_coi_i; +static int hf_qoi; +static int hf_qcc; +static int hf_qcc_rqt; +static int hf_qcc_frz; +static int hf_qrp; +static int hf_bcr; +static int hf_bcr_count; +static int hf_bcr_sq; +static int hf_bcr_cy; +static int hf_bcr_ca; +static int hf_bcr_iv; +static int hf_start; + +static int hf_asdu_bitstring; +static int hf_asdu_float; +static int hf_asdu_normval; +static int hf_asdu_scalval; +static int hf_asdu_raw_data; + +static gint ett_apci; +static gint ett_asdu; +static gint ett_asdu_objects; +static gint ett_siq; +static gint ett_diq; +static gint ett_vti; +static gint ett_qds; +static gint ett_qos; +static gint ett_sco; +static gint ett_dco; +static gint ett_rco; +static gint ett_qpm; +static gint ett_coi; +static gint ett_qcc; +static gint ett_cp24time; +static gint ett_cp56time; + +static expert_field ei_iec104_short_asdu; +static expert_field ei_iec104_apdu_min_len; +static expert_field ei_iec104_apdu_invalid_len; /* IEC 101 stuff */ /* Initialize the protocol and registered fields */ -static int hf_iec60870_101_frame = -1; -static int hf_iec60870_101_length = -1; -static int hf_iec60870_101_num_user_octets = -1; -static int hf_iec60870_101_ctrlfield = -1; -static int hf_iec60870_101_ctrl_prm = -1; -static int hf_iec60870_101_ctrl_fcb = -1; -static int hf_iec60870_101_ctrl_fcv = -1; -static int hf_iec60870_101_ctrl_dfc = -1; -static int hf_iec60870_101_ctrl_func_pri_to_sec = -1; -static int hf_iec60870_101_ctrl_func_sec_to_pri = -1; -static int hf_iec60870_101_linkaddr = -1; -static int hf_iec60870_101_checksum = -1; -static int hf_iec60870_101_stopchar = -1; +static int hf_iec60870_101_frame; +static int hf_iec60870_101_length; +static int hf_iec60870_101_num_user_octets; +static int hf_iec60870_101_ctrlfield; +static int hf_iec60870_101_ctrl_prm; +static int hf_iec60870_101_ctrl_fcb; +static int hf_iec60870_101_ctrl_fcv; +static int hf_iec60870_101_ctrl_dfc; +static int hf_iec60870_101_ctrl_func_pri_to_sec; +static int hf_iec60870_101_ctrl_func_sec_to_pri; +static int hf_iec60870_101_linkaddr; +static int hf_iec60870_101_checksum; +static int hf_iec60870_101_stopchar; /* Initialize the subtree pointers */ -static gint ett_iec60870_101 = -1; -static gint ett_iec60870_101_ctrlfield = -1; +static gint ett_iec60870_101; +static gint ett_iec60870_101_ctrlfield; /* Frame Format */ #define IEC101_VAR_LEN 0x68 @@ -853,53 +860,53 @@ static const value_string iec60870_101_ctrl_func_sec_to_pri_values[] = { /* IEC 60870-5-103 Variables */ /* Initialize the protocol and registered fields */ -static int hf_iec60870_5_103_areva_cmd = -1; -static int hf_iec60870_5_103_asdu_address = -1; -static int hf_iec60870_5_103_asdu_typeid_mon = -1; -static int hf_iec60870_5_103_asdu_typeid_ctrl = -1; -static int hf_iec60870_5_103_asdu205_ms = -1; -static int hf_iec60870_5_103_asdu205_min = -1; -static int hf_iec60870_5_103_asdu205_h = -1; -static int hf_iec60870_5_103_asdu205_value = -1; -static int hf_iec60870_5_103_checksum = -1; -static int hf_iec60870_5_103_col = -1; -static int hf_iec60870_5_103_cot_mon = -1; -static int hf_iec60870_5_103_cot_ctrl = -1; -static int hf_iec60870_5_103_cp32time2a = -1; -static int hf_iec60870_5_103_cp32time2a_ms = -1; -static int hf_iec60870_5_103_cp32time2a_min = -1; -static int hf_iec60870_5_103_cp32time2a_res1 = -1; -static int hf_iec60870_5_103_cp32time2a_iv = -1; -static int hf_iec60870_5_103_cp32time2a_hr = -1; -static int hf_iec60870_5_103_cp32time2a_res2 = -1; -static int hf_iec60870_5_103_cp32time2a_sum = -1; -static int hf_iec60870_5_103_ctrlfield = -1; -static int hf_iec60870_5_103_ctrl_prm = -1; -static int hf_iec60870_5_103_ctrl_fcb = -1; -static int hf_iec60870_5_103_ctrl_fcv = -1; -static int hf_iec60870_5_103_ctrl_dfc = -1; -static int hf_iec60870_5_103_ctrl_func_pri_to_sec = -1; -static int hf_iec60870_5_103_ctrl_func_sec_to_pri = -1; -static int hf_iec60870_5_103_dco = -1; -static int hf_iec60870_5_103_dpi = -1; -static int hf_iec60870_5_103_frame = -1; -static int hf_iec60870_5_103_func_type = -1; -static int hf_iec60870_5_103_info_num = -1; -static int hf_iec60870_5_103_length = -1; -static int hf_iec60870_5_103_linkaddr = -1; -static int hf_iec60870_5_103_mfg = -1; -static int hf_iec60870_5_103_mfg_sw = -1; -static int hf_iec60870_5_103_num_user_octets = -1; -static int hf_iec60870_5_103_rii = -1; -static int hf_iec60870_5_103_scn = -1; -static int hf_iec60870_5_103_sin = -1; -static int hf_iec60870_5_103_sq = -1; -static int hf_iec60870_5_103_stopchar = -1; +static int hf_iec60870_5_103_areva_cmd; +static int hf_iec60870_5_103_asdu_address; +static int hf_iec60870_5_103_asdu_typeid_mon; +static int hf_iec60870_5_103_asdu_typeid_ctrl; +static int hf_iec60870_5_103_asdu205_ms; +static int hf_iec60870_5_103_asdu205_min; +static int hf_iec60870_5_103_asdu205_h; +static int hf_iec60870_5_103_asdu205_value; +static int hf_iec60870_5_103_checksum; +static int hf_iec60870_5_103_col; +static int hf_iec60870_5_103_cot_mon; +static int hf_iec60870_5_103_cot_ctrl; +static int hf_iec60870_5_103_cp32time2a; +static int hf_iec60870_5_103_cp32time2a_ms; +static int hf_iec60870_5_103_cp32time2a_min; +static int hf_iec60870_5_103_cp32time2a_res1; +static int hf_iec60870_5_103_cp32time2a_iv; +static int hf_iec60870_5_103_cp32time2a_hr; +static int hf_iec60870_5_103_cp32time2a_res2; +static int hf_iec60870_5_103_cp32time2a_sum; +static int hf_iec60870_5_103_ctrlfield; +static int hf_iec60870_5_103_ctrl_prm; +static int hf_iec60870_5_103_ctrl_fcb; +static int hf_iec60870_5_103_ctrl_fcv; +static int hf_iec60870_5_103_ctrl_dfc; +static int hf_iec60870_5_103_ctrl_func_pri_to_sec; +static int hf_iec60870_5_103_ctrl_func_sec_to_pri; +static int hf_iec60870_5_103_dco; +static int hf_iec60870_5_103_dpi; +static int hf_iec60870_5_103_frame; +static int hf_iec60870_5_103_func_type; +static int hf_iec60870_5_103_info_num; +static int hf_iec60870_5_103_length; +static int hf_iec60870_5_103_linkaddr; +static int hf_iec60870_5_103_mfg; +static int hf_iec60870_5_103_mfg_sw; +static int hf_iec60870_5_103_num_user_octets; +static int hf_iec60870_5_103_rii; +static int hf_iec60870_5_103_scn; +static int hf_iec60870_5_103_sin; +static int hf_iec60870_5_103_sq; +static int hf_iec60870_5_103_stopchar; /* Initialize the subtree pointers */ -static gint ett_iec60870_5_103 = -1; -static gint ett_iec60870_5_103_ctrlfield = -1; -static gint ett_iec60870_5_103_cp32time2a = -1; +static gint ett_iec60870_5_103; +static gint ett_iec60870_5_103_ctrlfield; +static gint ett_iec60870_5_103_cp32time2a; /* Frame Format */ #define IEC103_VAR_LEN 0x68 @@ -1453,14 +1460,20 @@ static void get_BSIspt(tvbuff_t *tvb, guint8 *offset, proto_tree *iec104_header_ ==================================================================== */ static void get_BCR(tvbuff_t *tvb, guint8 *offset, proto_tree *iec104_header_tree) { - proto_tree_add_item(iec104_header_tree, hf_bcr_count, tvb, *offset, 4, ENC_LITTLE_ENDIAN); - *offset += 4; - - proto_tree_add_item(iec104_header_tree, hf_bcr_sq, tvb, *offset, 1, ENC_LITTLE_ENDIAN); - proto_tree_add_item(iec104_header_tree, hf_bcr_cy, tvb, *offset, 1, ENC_LITTLE_ENDIAN); - proto_tree_add_item(iec104_header_tree, hf_bcr_ca, tvb, *offset, 1, ENC_LITTLE_ENDIAN); - proto_tree_add_item(iec104_header_tree, hf_bcr_iv, tvb, *offset, 1, ENC_LITTLE_ENDIAN); - *offset += 1; + proto_item* ti; + proto_tree* bcr_tree; + + ti = proto_tree_add_item(iec104_header_tree, hf_bcr, tvb, *offset, 4, ENC_LITTLE_ENDIAN); + bcr_tree = proto_item_add_subtree(ti, ett_vti); + + proto_tree_add_item(bcr_tree, hf_bcr_count, tvb, *offset, 4, ENC_LITTLE_ENDIAN); + (*offset) += 4; + + proto_tree_add_item(bcr_tree, hf_bcr_sq, tvb, *offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(bcr_tree, hf_bcr_cy, tvb, *offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(bcr_tree, hf_bcr_ca, tvb, *offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(bcr_tree, hf_bcr_iv, tvb, *offset, 1, ENC_LITTLE_ENDIAN); + (*offset)++; } /* ==================================================================== @@ -1663,7 +1676,7 @@ static int dissect_iec60870_asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree * it104 = proto_tree_add_item(tree, proto_iec60870_asdu, tvb, offset, -1, ENC_NA); it104tree = proto_item_add_subtree(it104, ett_asdu); - res = wmem_strbuf_new_label(pinfo->pool); + res = wmem_strbuf_create(pinfo->pool); /* Type identification */ asduh.TypeId = tvb_get_guint8(tvb, offset); @@ -2046,7 +2059,7 @@ static int dissect_iec60870_asdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree * /* check correct apdu length */ if (Len != offset) { - expert_add_info(pinfo, it104tree, &ei_iec104_apdu_invalid_len); + expert_add_info_format(pinfo, it104tree, &ei_iec104_apdu_invalid_len, "Invalid Apdulen (%d != %d)", Len, offset); return offset; } @@ -2060,7 +2073,7 @@ static int dissect_iec60870_104(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t { guint TcpLen = tvb_reported_length(tvb); guint8 Start, len, type, temp8; - guint16 apci_txid, apci_rxid; + guint32 apci_txid, apci_rxid, apci_u_type; guint Off; proto_item *it104, *ti; proto_tree *it104tree; @@ -2072,7 +2085,7 @@ static int dissect_iec60870_104(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t it104 = proto_tree_add_item(tree, proto_iec60870_104, tvb, 0, -1, ENC_NA); it104tree = proto_item_add_subtree(it104, ett_apci); - res = wmem_strbuf_new_label(pinfo->pool); + res = wmem_strbuf_create(pinfo->pool); Start = 0; for (Off = 0; Off <= TcpLen - 2; Off++) { @@ -2104,9 +2117,9 @@ static int dissect_iec60870_104(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t type = temp8 & 0x03; if (type == I_TYPE) - proto_tree_add_bits_item(it104tree, hf_apcitype, tvb, (Off + 2) * 8 + 7, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(it104tree, hf_apcitype_i, tvb, Off + 2, 4, ENC_LITTLE_ENDIAN); else - proto_tree_add_bits_item(it104tree, hf_apcitype, tvb, (Off + 2) * 8 + 6, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(it104tree, hf_apcitype_s_u, tvb, Off + 2, 4, ENC_LITTLE_ENDIAN); if (len <= APDU_MAX_LEN) { wmem_strbuf_append_printf(res, "%s %s ", @@ -2119,20 +2132,17 @@ static int dissect_iec60870_104(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t switch(type) { case I_TYPE: - apci_txid = tvb_get_letohs(tvb, Off + 2) >> 1; - apci_rxid = tvb_get_letohs(tvb, Off + 4) >> 1; + proto_tree_add_item_ret_uint(it104tree, hf_apcitx, tvb, Off + 2, 4, ENC_LITTLE_ENDIAN, &apci_txid); + proto_tree_add_item_ret_uint(it104tree, hf_apcirx, tvb, Off + 2, 4, ENC_LITTLE_ENDIAN, &apci_rxid); wmem_strbuf_append_printf(res, "(%d,%d) ", apci_txid, apci_rxid); - proto_tree_add_uint(it104tree, hf_apcitx, tvb, Off+2, 2, apci_txid); - proto_tree_add_uint(it104tree, hf_apcirx, tvb, Off+4, 2, apci_rxid); break; case S_TYPE: - apci_rxid = tvb_get_letohs(tvb, Off + 4) >> 1; + proto_tree_add_item_ret_uint(it104tree, hf_apcirx, tvb, Off + 2, 4, ENC_LITTLE_ENDIAN, &apci_rxid); wmem_strbuf_append_printf(res, "(%d) ", apci_rxid); - proto_tree_add_uint(it104tree, hf_apcirx, tvb, Off+4, 2, apci_rxid); break; case U_TYPE: - wmem_strbuf_append_printf(res, "(%s) ", val_to_str_const((temp8 >> 2) & 0x3F, u_types, "<ERR>")); - proto_tree_add_item(it104tree, hf_apciutype, tvb, Off + 2, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item_ret_uint(it104tree, hf_apciutype, tvb, Off + 2, 4, ENC_LITTLE_ENDIAN, &apci_u_type); + wmem_strbuf_append_printf(res, "(%s) ", val_to_str_const(apci_u_type, u_types, "<ERR>")); break; } @@ -2172,8 +2182,9 @@ dissect_iec60870_101(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* /* Set up structures needed to add the protocol subtree and manage it */ proto_item *iec101_item, *ctrlfield_item; proto_tree *iec101_tree, *ctrlfield_tree; - guint8 frametype, ctrlfield_prm, linkaddr, data_len; - int offset = 0; + guint8 frametype, ctrlfield_prm; + guint32 linkaddr, data_len; + int offset = 0; struct asdu_parms parms; /* Make entries in Protocol column on summary display */ @@ -2195,10 +2206,9 @@ dissect_iec60870_101(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* if (frametype == IEC101_VAR_LEN) { proto_tree_add_item(iec101_tree, hf_iec60870_101_length, tvb, offset, 1, ENC_LITTLE_ENDIAN); - proto_tree_add_item(iec101_tree, hf_iec60870_101_num_user_octets, tvb, offset+1, 1, ENC_LITTLE_ENDIAN); - - /* data_len - 2 is used as we are not including the ctrl field and link address bytes in the length passed to the asdu dissector */ - data_len = tvb_get_guint8(tvb, offset+1) - 2; + proto_tree_add_item_ret_uint(iec101_tree, hf_iec60870_101_num_user_octets, tvb, offset+1, 1, ENC_LITTLE_ENDIAN, &data_len); + /* do not include the ctrl field and link address bytes in the length passed to the asdu dissector */ + data_len -= 1 + global_iec60870_link_addr_len; proto_tree_add_item(iec101_tree, hf_iec60870_101_frame, tvb, offset+2, 1, ENC_LITTLE_ENDIAN); offset += 3; } @@ -2223,10 +2233,11 @@ dissect_iec60870_101(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* } offset += 1; - proto_tree_add_item(iec101_tree, hf_iec60870_101_linkaddr, tvb, offset, 1, ENC_LITTLE_ENDIAN); - linkaddr = tvb_get_guint8(tvb, offset); - col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Link Address: %d ", linkaddr); - offset += 1; + if (global_iec60870_link_addr_len) { + proto_tree_add_item_ret_uint(iec101_tree, hf_iec60870_101_linkaddr, tvb, offset, global_iec60870_link_addr_len, ENC_LITTLE_ENDIAN, &linkaddr); + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Link Address: %d ", linkaddr); + offset += global_iec60870_link_addr_len; + } /* If this is a variable length frame, we need to call the ASDU dissector */ if (frametype == IEC101_VAR_LEN) { @@ -2268,20 +2279,24 @@ proto_register_iec60870_104(void) { "ApduLen", "iec60870_104.apdulen", FT_UINT8, BASE_DEC, NULL, 0x0, "APDU Len", HFILL }}, - { &hf_apcitype, - { "Type", "iec60870_104.type", FT_UINT8, BASE_HEX, VALS(apci_types), 0x00, + { &hf_apcitype_i, + { "Type", "iec60870_104.type", FT_UINT32, BASE_HEX, VALS(apci_types), 0x00000001, + "APCI type", HFILL }}, + + { &hf_apcitype_s_u, + { "Type", "iec60870_104.type", FT_UINT32, BASE_HEX, VALS(apci_types), 0x00000003, "APCI type", HFILL }}, { &hf_apciutype, - { "UType", "iec60870_104.utype", FT_UINT8, BASE_HEX, VALS(u_types), 0xFC, + { "UType", "iec60870_104.utype", FT_UINT32, BASE_HEX, VALS(u_types), 0x000000FC, "Apci U type", HFILL }}, { &hf_apcitx, - { "Tx", "iec60870_104.tx", FT_UINT16, BASE_DEC, NULL, 0, + { "Tx", "iec60870_104.tx", FT_UINT32, BASE_DEC, NULL, 0x0000FFFE, NULL, HFILL }}, { &hf_apcirx, - { "Rx", "iec60870_104.rx", FT_UINT16, BASE_DEC, NULL, 0, + { "Rx", "iec60870_104.rx", FT_UINT32, BASE_DEC, NULL, 0xFFFE0000, NULL, HFILL }}, { &hf_apcidata, @@ -2302,6 +2317,9 @@ proto_register_iec60870_104(void) proto_register_subtree_array(ett_ap, array_length(ett_ap)); prefs_register_protocol(proto_iec60870_104, NULL); + + iec60870_104_handle = register_dissector("iec60870_104", dissect_iec60870_104_tcp, proto_iec60870_104); + } /* Register ASDU dissection, shared by the '101 and '104 dissectors */ @@ -2571,11 +2589,11 @@ proto_register_iec60870_asdu(void) NULL, HFILL }}, { &hf_coi_r, - { "R", "iec60870_asdu.coi_r", FT_UINT8, BASE_DEC, VALS(coi_r_types), 0x7F, + { "R", "iec60870_asdu.coi.r", FT_UINT8, BASE_DEC, VALS(coi_r_types), 0x7F, "COI R", HFILL }}, { &hf_coi_i, - { "I", "iec60870_asdu.coi_i", FT_BOOLEAN, 8, TFS(&tfs_coi_i), 0x80, + { "I", "iec60870_asdu.coi.i", FT_BOOLEAN, 8, TFS(&tfs_coi_i), 0x80, "COI I", HFILL }}, { &hf_qoi, @@ -2587,19 +2605,23 @@ proto_register_iec60870_asdu(void) NULL, HFILL } }, { &hf_qcc_rqt, - { "RQT", "iec60870_asdu.rqt", FT_UINT8, BASE_DEC, VALS(rqt_r_types), 0x3F, + { "RQT", "iec60870_asdu.qcc.rqt", FT_UINT8, BASE_DEC, VALS(rqt_r_types), 0x3F, NULL, HFILL } }, { &hf_qcc_frz, - { "FRZ", "iec60870_asdu.frz", FT_UINT8, BASE_DEC, VALS(frz_r_types), 0xC0, + { "FRZ", "iec60870_asdu.qcc.frz", FT_UINT8, BASE_DEC, VALS(frz_r_types), 0xC0, NULL, HFILL } }, { &hf_qrp, { "QRP", "iec60870_asdu.qrp", FT_UINT8, BASE_DEC, VALS(qrp_r_types), 0, NULL, HFILL }}, + { &hf_bcr, + { "BCR", "iec60870_asdu.bcr", FT_INT32, BASE_DEC, NULL, 0x0, + "Binary Counter", HFILL }}, + { &hf_bcr_count, - { "Binary Counter", "iec60870_asdu.bcr.count", FT_INT32, BASE_DEC, NULL, 0x0, + { "Value", "iec60870_asdu.bcr.count", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_bcr_sq, @@ -2670,7 +2692,7 @@ proto_register_iec60870_asdu(void) expert_module_t* expert_iec60870; proto_iec60870_asdu = proto_register_protocol("IEC 60870-5-101/104 ASDU", "IEC 60870-5-101/104 ASDU", "iec60870_asdu"); - iec60870_asdu_handle = create_dissector_handle(dissect_iec60870_asdu, proto_iec60870_asdu); + iec60870_asdu_handle = register_dissector("iec60870_asdu", dissect_iec60870_asdu, proto_iec60870_asdu); /* Provide an alias to the previous name of this dissector */ proto_register_alias(proto_iec60870_asdu, "104asdu"); @@ -2686,23 +2708,9 @@ proto_register_iec60870_asdu(void) void proto_reg_handoff_iec60870_104(void) { - dissector_handle_t iec60870_104_handle; - - iec60870_104_handle = create_dissector_handle(dissect_iec60870_104_tcp, proto_iec60870_104); - dissector_add_uint_with_preference("tcp.port", IEC104_PORT, iec60870_104_handle); } -static void -apply_iec60870_101_prefs(void) -{ - /* IEC101 uses user customizable preferences for the configurable field lengths */ - global_iec60870_cot_len = prefs_get_uint_value("iec60870_101", "cot_len"); - global_iec60870_asdu_addr_len = prefs_get_uint_value("iec60870_101", "asdu_addr_len"); - global_iec60870_ioa_len = prefs_get_uint_value("iec60870_101", "asdu_ioa_len"); -} - - /******************************************************************************************************/ /* Return length of IEC 101 Protocol over TCP message (used for re-assembly) */ /******************************************************************************************************/ @@ -2718,7 +2726,7 @@ get_iec101_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_, void *data len = 1; break; case IEC101_FIXED_LEN: - len = 5; + len = global_iec60870_link_addr_len + 4; break; case IEC101_VAR_LEN: len = tvb_get_guint8(tvb, offset+1) + 6; @@ -2778,7 +2786,7 @@ proto_register_iec60870_101(void) { &hf_iec60870_101_ctrl_func_sec_to_pri, { "CF Func Code", "iec60870_101.ctrl_func_sec_to_pri", FT_UINT8, BASE_DEC, VALS(iec60870_101_ctrl_func_sec_to_pri_values), 0x0F, "Control Field Function Code, Sec to Pri", HFILL }}, { &hf_iec60870_101_linkaddr, - { "Data Link Address", "iec60870_101.linkaddr", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { "Data Link Address", "iec60870_101.linkaddr", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_iec60870_101_checksum, { "Checksum", "iec60870_101.checksum", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_iec60870_101_stopchar, @@ -2801,9 +2809,18 @@ proto_register_iec60870_101(void) proto_register_field_array(proto_iec60870_101, iec60870_101_hf, array_length(iec60870_101_hf)); proto_register_subtree_array(ett_serial, array_length(ett_serial)); + iec60870_101_handle = register_dissector("iec60870_101", dissect_iec60870_101_tcp, proto_iec60870_101); + /* Register required preferences for IEC 101 configurable field lengths */ iec60870_101_module = prefs_register_protocol(proto_iec60870_101, NULL); + static const enum_val_t link_addr_len[] = { + {"0", "0 octet", 0}, + {"1", "1 octet", 1}, + {"2", "2 octet", 2}, + {NULL, NULL, -1} + }; + static const enum_val_t cot_len[] = { {"1", "1 octet", 1}, {"2", "2 octet", 2}, @@ -2817,11 +2834,17 @@ proto_register_iec60870_101(void) }; static const enum_val_t asdu_ioa_len[] = { + {"1", "1 octet", 1}, {"2", "2 octet", 2}, {"3", "3 octet", 3}, {NULL, NULL, -1} }; + prefs_register_enum_preference(iec60870_101_module, "linkaddr_len", + "Length of the Link Address Field", + "Length of the Link Address Field, configurable in '101 and absent in '104", + &global_iec60870_link_addr_len, link_addr_len, FALSE); + prefs_register_enum_preference(iec60870_101_module, "cot_len", "Length of the Cause of Transmission Field", "Length of the Cause of Transmission Field, configurable in '101 and fixed at 2 octets with '104", @@ -2842,16 +2865,10 @@ proto_register_iec60870_101(void) void proto_reg_handoff_iec60870_101(void) { - dissector_handle_t iec60870_101_handle; - - iec60870_101_handle = create_dissector_handle(dissect_iec60870_101_tcp, proto_iec60870_101); - /* Add decode-as connection to determine user-customized TCP port */ dissector_add_for_decode_as_with_preference("tcp.port", iec60870_101_handle); /* Add dissection for serial pcap files generated by the RTAC */ dissector_add_for_decode_as("rtacser.data", iec60870_101_handle); - - apply_iec60870_101_prefs(); } /******************************************************************************************************/ @@ -2978,7 +2995,7 @@ dissect_iec60870_5_103(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void case 0x05: /* ASDU 5 - Identification */ proto_tree_add_item(iec103_tree, hf_iec60870_5_103_col, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; - proto_tree_add_item(iec103_tree, hf_iec60870_5_103_mfg, tvb, offset, 8, ENC_ASCII|ENC_NA); + proto_tree_add_item(iec103_tree, hf_iec60870_5_103_mfg, tvb, offset, 8, ENC_ASCII); offset += 8; proto_tree_add_item(iec103_tree, hf_iec60870_5_103_mfg_sw, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; @@ -3168,15 +3185,12 @@ proto_register_iec60870_5_103(void) proto_register_field_array(proto_iec60870_5_103, iec60870_5_103_hf, array_length(iec60870_5_103_hf)); proto_register_subtree_array(ett_serial, array_length(ett_serial)); + iec60870_5_103_handle = register_dissector("iec60870_5_103", dissect_iec60870_5_103_tcp, proto_iec60870_5_103); } void proto_reg_handoff_iec60870_5_103(void) { - dissector_handle_t iec60870_5_103_handle; - - iec60870_5_103_handle = create_dissector_handle(dissect_iec60870_5_103_tcp, proto_iec60870_5_103); - /* Add decode-as connection to determine user-customized TCP port */ dissector_add_for_decode_as_with_preference("tcp.port", iec60870_5_103_handle); /* Add dissection for serial pcap files generated by the RTAC */ |