From 4814685f204e3d9019ee6bec73aca354d2b53bf2 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 9 May 2017 17:50:48 +0200 Subject: [PATCH] gsm_osmux: Support multiple OSmux frames per packet Also split and show all AMR payloads Change-Id: I5bde4e87dc51fd4a996a14117813ea89d7005d38 --- epan/dissectors/packet-gsm_osmux.c | 163 ++++++++++++++++++++--------- 1 file changed, 111 insertions(+), 52 deletions(-) diff --git a/epan/dissectors/packet-gsm_osmux.c b/epan/dissectors/packet-gsm_osmux.c index d8b155c2be..590d0acbbc 100644 --- a/epan/dissectors/packet-gsm_osmux.c +++ b/epan/dissectors/packet-gsm_osmux.c @@ -44,6 +44,48 @@ static const value_string osmux_ft_vals[] = {0, NULL} }; +#define AMR_FT_0 0 +#define AMR_FT_1 1 +#define AMR_FT_2 2 +#define AMR_FT_3 3 +#define AMR_FT_4 4 +#define AMR_FT_5 5 +#define AMR_FT_6 6 +#define AMR_FT_7 7 +#define AMR_FT_SID 8 +#define AMR_FT_MAX 9 + +static const value_string amr_ft_names[] = +{ + {AMR_FT_0, "AMR 4.75"}, + {AMR_FT_1, "AMR 5.15"}, + {AMR_FT_2, "AMR 5.90"}, + {AMR_FT_3, "AMR 6.70"}, + {AMR_FT_4, "AMR 7.40"}, + {AMR_FT_5, "AMR 7.95"}, + {AMR_FT_6, "AMR 10.2"}, + {AMR_FT_7, "AMR 12.2"}, + {AMR_FT_SID, "AMR SID"}, + {0, NULL} +}; + +/* Code to calculate payload size */ +struct amr_size_entry { guint8 ft, size; }; +static struct amr_size_entry amr_ft_bytes[] = +{ + {AMR_FT_0, 12}, + {AMR_FT_1, 13}, + {AMR_FT_2, 15}, + {AMR_FT_3, 17}, + {AMR_FT_4, 19}, + {AMR_FT_5, 20}, + {AMR_FT_6, 26}, + {AMR_FT_7, 31}, + {AMR_FT_SID, 6} +}; + +#define OSMUX_AMR_HEADER_LEN 4 + /* Initialize the protocol and registered fields */ static dissector_handle_t osmux_handle; static int proto_osmux = -1; @@ -67,6 +109,13 @@ static gint ett_osmux = -1; static gint ett_osmux_ft_ctr = -1; static gint ett_osmux_amr_ft_cmr = -1; +static guint8 +amr_ft_to_bytes(guint32 amr_ft) +{ + if (amr_ft >= AMR_FT_MAX) /* malformed packet ? */ + return 0; + return amr_ft_bytes[amr_ft].size; +} /* Code to actually dissect the packets */ static gint @@ -88,67 +137,77 @@ dissect_osmux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U int offset = 0; - struct osmux_hdr *osmuxh; - proto_item *ti; - proto_tree *osmux_tree = NULL; - guint8 ft_ctr; - guint32 cid; - guint64 amr_ft_cmr; - col_set_str(pinfo->cinfo, COL_PROTOCOL, "Osmux"); col_clear(pinfo->cinfo, COL_INFO); - osmuxh = wmem_new0(wmem_packet_scope(), struct osmux_hdr); + while (tvb_reported_length_remaining(tvb, offset) >= 2) { - ft_ctr = tvb_get_guint8(tvb, offset); + struct osmux_hdr *osmuxh; + proto_item *ti; + proto_tree *osmux_tree = NULL; + guint8 ft_ctr; + guint64 amr_ft_cmr; + guint i; + guint32 cid, size; - osmuxh->rtp_m = ft_ctr >> 7; - osmuxh->ft = (ft_ctr >> 5) & 0x3; - osmuxh->ctr = (ft_ctr >> 2) & 0x7; - osmuxh->amr_q = !!(ft_ctr & 0x02); - osmuxh->amr_f = !!(ft_ctr & 0x01); + osmuxh = wmem_new0(wmem_packet_scope(), struct osmux_hdr); - col_append_fstr(pinfo->cinfo, COL_INFO, "Osmux "); + ft_ctr = tvb_get_guint8(tvb, offset); - ti = proto_tree_add_protocol_format(tree, proto_osmux, tvb, offset, -1, - "Osmux type %s frame", - val_to_str(osmuxh->ft, osmux_ft_vals, "unknown 0x%02x")); - osmux_tree = proto_item_add_subtree(ti, ett_osmux); + osmuxh->rtp_m = ft_ctr >> 7; + osmuxh->ft = (ft_ctr >> 5) & 0x3; + osmuxh->ctr = (ft_ctr >> 2) & 0x7; + osmuxh->amr_q = !!(ft_ctr & 0x02); + osmuxh->amr_f = !!(ft_ctr & 0x01); - /* Two-byte dummy packets for firewalls (starts with 0x23) */ - if (ft_ctr == 0x23 && tvb_reported_length(tvb) >= 2) { - proto_tree_add_item_ret_uint(osmux_tree, hf_osmux_circuit_id, tvb, offset+1, 1, ENC_BIG_ENDIAN, &cid); - col_append_fstr(pinfo->cinfo, COL_INFO, "Dummy frame (CID %u)", cid); - return 2; + col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Osmux "); + + col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", + val_to_str(osmuxh->ft, osmux_ft_vals, + "unknown 0x%02x")); + + if (osmuxh->rtp_m) + col_append_fstr(pinfo->cinfo, COL_INFO, "(M) "); + + ti = proto_tree_add_protocol_format(tree, proto_osmux, tvb, offset, -1, + "Osmux type %s frame", + val_to_str(osmuxh->ft, osmux_ft_vals, "unknown 0x%02x")); + + osmux_tree = proto_item_add_subtree(ti, ett_osmux); + + proto_tree_add_bitmask(osmux_tree, tvb, offset, hf_osmux_ft_ctr, + ett_osmux_ft_ctr, ft_ctr_fields, ENC_BIG_ENDIAN); + offset++; + + /* Old versions of the protocol used to send dummy packets of only 2 bytes (control + cid):_*/ + if (ft_ctr == 0x23 && tvb_reported_length_remaining(tvb, offset - 1) == 2) { + proto_tree_add_item_ret_uint(osmux_tree, hf_osmux_circuit_id, tvb, offset, 1, ENC_BIG_ENDIAN, &cid); + col_append_fstr(pinfo->cinfo, COL_INFO, "Old Dummy (CID %u)", cid); + tap_queue_packet(osmux_tap, pinfo, osmuxh); + return tvb_reported_length(tvb); + } + + proto_tree_add_item_ret_uint(osmux_tree, hf_osmux_seq, tvb, offset, 1, ENC_BIG_ENDIAN, &osmuxh->seq); + offset++; + + proto_tree_add_item_ret_uint(osmux_tree, hf_osmux_circuit_id, tvb, offset, 1, ENC_BIG_ENDIAN, &osmuxh->circuit_id); + offset++; + col_append_fstr(pinfo->cinfo, COL_INFO, "(CID %u) ", osmuxh->circuit_id); + + proto_tree_add_bitmask_ret_uint64(osmux_tree, tvb, offset, hf_osmux_amr_ft_cmr, + ett_osmux_amr_ft_cmr, amr_ft_cmr_fields, ENC_BIG_ENDIAN, &amr_ft_cmr); + offset++; + osmuxh->amr_ft = (guint32)(amr_ft_cmr & 0xf0) >> 4; + osmuxh->amr_cmr = (guint32)amr_ft_cmr & 0x0f; + size = amr_ft_to_bytes(osmuxh->amr_ft); + for (i = 0; i < osmuxh->ctr + 1; i++) { + proto_tree_add_item(osmux_tree, hf_osmux_amr_data, tvb, offset, size, ENC_NA); + offset += size; + } + + tap_queue_packet(osmux_tap, pinfo, osmuxh); } - col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", - val_to_str(osmuxh->ft, osmux_ft_vals, - "unknown 0x%02x")); - - if (osmuxh->rtp_m) - col_append_fstr(pinfo->cinfo, COL_INFO, "(M)"); - - proto_tree_add_bitmask(osmux_tree, tvb, offset, hf_osmux_ft_ctr, - ett_osmux_ft_ctr, ft_ctr_fields, ENC_BIG_ENDIAN); - offset++; - - proto_tree_add_item_ret_uint(osmux_tree, hf_osmux_seq, tvb, offset, 1, ENC_BIG_ENDIAN, &osmuxh->seq); - offset++; - proto_tree_add_item_ret_uint(osmux_tree, hf_osmux_circuit_id, tvb, offset, 1, ENC_BIG_ENDIAN, &osmuxh->circuit_id); - offset++; - - proto_tree_add_bitmask_ret_uint64(osmux_tree, tvb, offset, hf_osmux_amr_ft_cmr, - ett_osmux_amr_ft_cmr, amr_ft_cmr_fields, ENC_BIG_ENDIAN, &amr_ft_cmr); - offset++; - osmuxh->amr_ft = (guint32)(amr_ft_cmr & 0xf0) >> 4; - osmuxh->amr_cmr = (guint32)amr_ft_cmr & 0x0f; - - - proto_tree_add_item(osmux_tree, hf_osmux_amr_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); - - tap_queue_packet(osmux_tap, pinfo, osmuxh); - return tvb_reported_length(tvb); } @@ -270,7 +329,7 @@ void proto_register_osmux(void) }, {&hf_osmux_amr_ft, {"AMR ft", "osmux.amr_ft", - FT_UINT8, BASE_HEX, NULL, 0xf0, + FT_UINT8, BASE_HEX,VALS(amr_ft_names), 0xf0, "AMR parameter ft", HFILL} }, {&hf_osmux_amr_cmr,