aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-iec104.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-iec104.c')
-rw-r--r--epan/dissectors/packet-iec104.c508
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 */