aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Kaiser <wireshark@kaiser.cx>2016-12-23 19:06:24 +0100
committerMartin Kaiser <wireshark@kaiser.cx>2016-12-26 23:38:10 +0000
commit6427edb18d84a812cd3f9de95f657953f4026589 (patch)
treeb127659e0808e078a845855d242318230437d062
parente41201cde4dcf28c8e22433bd363bf1133f31aa1 (diff)
zvt: dissect the TLV container's payload
add a function to dissect the sequence of TLV elements use a hash table for payload functions like we do for the bitmaps add two tags whose payload is another TLV sequence Change-Id: Ibb19fd7af2f58e201174d07d410557dc315c652a Reviewed-on: https://code.wireshark.org/review/19435 Petri-Dish: Martin Kaiser <wireshark@kaiser.cx> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Martin Kaiser <wireshark@kaiser.cx>
-rw-r--r--epan/dissectors/packet-zvt.c147
1 files changed, 121 insertions, 26 deletions
diff --git a/epan/dissectors/packet-zvt.c b/epan/dissectors/packet-zvt.c
index 506b3b3c0a..1508699cbf 100644
--- a/epan/dissectors/packet-zvt.c
+++ b/epan/dissectors/packet-zvt.c
@@ -58,7 +58,7 @@
#define ZVT_APDU_MIN_LEN 3
-static GHashTable *apdu_table = NULL, *bitmap_table = NULL;
+static GHashTable *apdu_table = NULL, *bitmap_table = NULL, *tlv_table = NULL;
static wmem_tree_t *transactions = NULL;
@@ -185,6 +185,7 @@ static int ett_zvt = -1;
static int ett_zvt_apdu = -1;
static int ett_zvt_bitmap = -1;
static int ett_zvt_tlv_dat_obj = -1;
+static int ett_zvt_tlv_subseq = -1;
static int ett_zvt_tlv_tag = -1;
static int hf_zvt_resp_in = -1;
@@ -261,11 +262,6 @@ static const value_string bitmap[] = {
};
static value_string_ext bitmap_ext = VALUE_STRING_EXT_INIT(bitmap);
-static const value_string tlv_tags[] = {
- { 0, NULL }
-};
-static value_string_ext tlv_tags_ext = VALUE_STRING_EXT_INIT(tlv_tags);
-
static const value_string tlv_tag_class[] = {
{ 0x00, "Universal" },
{ 0x01, "Application" },
@@ -275,7 +271,53 @@ static const value_string tlv_tag_class[] = {
};
static value_string_ext tlv_tag_class_ext = VALUE_STRING_EXT_INIT(tlv_tag_class);
+#define TLV_TAG_DISPLAY_TEXTS 0x24
+#define TLV_TAG_PAYMENT_TYPE 0x2F
+typedef struct _tlv_seq_info_t {
+ guint txt_enc;
+} tlv_seq_info_t;
+
+
+static gint
+dissect_zvt_tlv_seq(tvbuff_t *tvb, gint offset, guint16 seq_max_len,
+ packet_info *pinfo _U_, proto_tree *tree, tlv_seq_info_t *seq_info);
+
+typedef struct _tlv_info_t {
+ guint32 tag;
+ gint (*dissect_payload)(tvbuff_t *, gint, gint,
+ packet_info *, proto_tree *, tlv_seq_info_t *);
+} tlv_info_t;
+
+static gint dissect_zvt_tlv_subseq(
+ tvbuff_t *tvb, gint offset, gint len,
+ packet_info *pinfo, proto_tree *tree, tlv_seq_info_t *seq_info);
+
+static const tlv_info_t tlv_info[] = {
+ { TLV_TAG_DISPLAY_TEXTS, dissect_zvt_tlv_subseq },
+ { TLV_TAG_PAYMENT_TYPE, dissect_zvt_tlv_subseq }
+};
+
+static const value_string tlv_tags[] = {
+ { TLV_TAG_DISPLAY_TEXTS, "Display texts" },
+ { TLV_TAG_PAYMENT_TYPE, "Payment type" },
+ { 0, NULL }
+};
+static value_string_ext tlv_tags_ext = VALUE_STRING_EXT_INIT(tlv_tags);
+
+
+static gint dissect_zvt_tlv_subseq(
+ tvbuff_t *tvb, gint offset, gint len,
+ packet_info *pinfo, proto_tree *tree, tlv_seq_info_t *seq_info)
+{
+ proto_tree *subseq_tree;
+
+ subseq_tree = proto_tree_add_subtree(tree,
+ tvb, offset, len, ett_zvt_tlv_subseq, NULL,
+ "Subsequence");
+
+ return dissect_zvt_tlv_seq(tvb, offset, len, pinfo, subseq_tree, seq_info);
+}
static gint
@@ -351,27 +393,34 @@ dissect_zvt_tlv_len(tvbuff_t *tvb, gint offset,
return len_bytes;
}
-
+
static gint
-dissect_zvt_tlv_container(tvbuff_t *tvb, gint offset,
- packet_info *pinfo, proto_tree *tree)
+dissect_zvt_tlv_seq(tvbuff_t *tvb, gint offset, guint16 seq_max_len,
+ packet_info *pinfo, proto_tree *tree, tlv_seq_info_t *seq_info)
{
- gint offset_start;
- proto_item *dat_obj_it;
- proto_tree *dat_obj_tree;
- gint tag_len;
- guint32 tag;
- gint total_len_bytes, data_len_bytes;
- guint16 data_len = 0;
+ gint offset_start;
+ proto_item *dat_obj_it;
+ proto_tree *dat_obj_tree;
+ gint tag_len;
+ guint32 tag;
+ gint data_len_bytes;
+ guint16 data_len = 0;
+ tlv_info_t *ti;
+ gint ret;
+
+ if (!seq_info) {
+ seq_info = (tlv_seq_info_t *)wmem_alloc(
+ wmem_packet_scope(), sizeof(tlv_seq_info_t));
+
+ /* by default, text lines are using the CP437 charset
+ there's an object to change the encoding
+ (XXX - does this change apply only to the current message?) */
+ seq_info->txt_enc = ENC_CP437;
+ }
offset_start = offset;
- total_len_bytes = dissect_zvt_tlv_len(tvb, offset, pinfo,
- tree, hf_zvt_tlv_total_len, NULL);
- if (total_len_bytes > 0)
- offset += total_len_bytes;
-
- while (tvb_captured_length_remaining(tvb, offset) > 0) {
+ while (offset-offset_start < seq_max_len) {
dat_obj_tree = proto_tree_add_subtree(tree,
tvb, offset, -1, ett_zvt_tlv_dat_obj, &dat_obj_it,
"TLV data object");
@@ -382,20 +431,58 @@ dissect_zvt_tlv_container(tvbuff_t *tvb, gint offset,
offset += tag_len;
data_len_bytes = dissect_zvt_tlv_len(tvb, offset, pinfo,
- dat_obj_tree,hf_zvt_tlv_len, &data_len);
+ dat_obj_tree,hf_zvt_tlv_len, &data_len);
if (data_len_bytes > 0)
offset += data_len_bytes;
- /* XXX - dissect the data-element */
- offset += data_len;
-
+ /* set the sequence length now that we know it
+ this way, we don't have to put the whole switch statement
+ under if (data_len > 0) */
proto_item_set_len(dat_obj_it, tag_len + data_len_bytes + data_len);
+ if (data_len == 0)
+ continue;
+
+ ti = (tlv_info_t *)g_hash_table_lookup(
+ tlv_table, GUINT_TO_POINTER((guint)tag));
+ if (ti && ti->dissect_payload) {
+ ret = ti->dissect_payload(
+ tvb, offset, (gint)data_len, pinfo, dat_obj_tree, seq_info);
+ if (ret <= 0) {
+ /* XXX - expert info */
+ }
+ }
+
+ offset += data_len;
}
return offset - offset_start;
}
+static gint
+dissect_zvt_tlv_container(tvbuff_t *tvb, gint offset,
+ packet_info *pinfo, proto_tree *tree)
+{
+ gint offset_start;
+ gint total_len_bytes, seq_len;
+ guint16 seq_max_len;
+
+ offset_start = offset;
+
+ total_len_bytes = dissect_zvt_tlv_len(tvb, offset, pinfo,
+ tree, hf_zvt_tlv_total_len, &seq_max_len);
+ if (total_len_bytes > 0)
+ offset += total_len_bytes;
+
+ seq_len = dissect_zvt_tlv_seq(
+ tvb, offset, seq_max_len, pinfo, tree, NULL);
+ if (seq_len > 0)
+ offset += seq_len;
+
+ return offset - offset_start;
+}
+
+
static gint dissect_zvt_cc(
tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, proto_tree *tree)
{
@@ -844,6 +931,7 @@ proto_register_zvt(void)
&ett_zvt_apdu,
&ett_zvt_bitmap,
&ett_zvt_tlv_dat_obj,
+ &ett_zvt_tlv_subseq,
&ett_zvt_tlv_tag
};
static hf_register_info hf[] = {
@@ -933,6 +1021,13 @@ proto_register_zvt(void)
(gpointer)(&bitmap_info[i]));
}
+ tlv_table = g_hash_table_new(g_direct_hash, g_direct_equal);
+ for(i=0; i<array_length(tlv_info); i++) {
+ g_hash_table_insert(tlv_table,
+ GUINT_TO_POINTER((guint)tlv_info[i].tag),
+ (gpointer)(&tlv_info[i]));
+ }
+
proto_zvt = proto_register_protocol("ZVT Kassenschnittstelle", "ZVT", "zvt");
proto_register_field_array(proto_zvt, hf, array_length(hf));