aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-batadv.c
diff options
context:
space:
mode:
authorJeff Morriss <jeff.morriss@ulticom.com>2011-05-14 14:31:51 +0000
committerJeff Morriss <jeff.morriss@ulticom.com>2011-05-14 14:31:51 +0000
commita8b851ceab32dec0368337c8d664394ee93dd679 (patch)
treea6bdc205489997b3377579f24dd770102f8add04 /epan/dissectors/packet-batadv.c
parent393f2467e460977d689a90104f252da01d13dfd0 (diff)
From Sven Eckelmann via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5658 :
Add support for v12 fragmented unicast. svn path=/trunk/; revision=37143
Diffstat (limited to 'epan/dissectors/packet-batadv.c')
-rw-r--r--epan/dissectors/packet-batadv.c296
1 files changed, 295 insertions, 1 deletions
diff --git a/epan/dissectors/packet-batadv.c b/epan/dissectors/packet-batadv.c
index c4a6254818..e7d55b83ba 100644
--- a/epan/dissectors/packet-batadv.c
+++ b/epan/dissectors/packet-batadv.c
@@ -31,6 +31,7 @@
#include <epan/prefs.h>
#include <epan/tap.h>
#include <epan/addr_resolv.h>
+#include <epan/reassemble.h>
/* Start content from packet-batadv.h */
#define ETH_P_BATMAN 0x4305
@@ -40,6 +41,7 @@
#define BATADV_UNICAST_V5 0x03
#define BATADV_BCAST_V5 0x04
#define BATADV_VIS_V5 0x05
+#define BATADV_UNICAST_FRAG_V12 0x06
#define ECHO_REPLY 0
#define DESTINATION_UNREACHABLE 3
@@ -151,6 +153,17 @@ struct unicast_packet_v6 {
};
#define UNICAST_PACKET_V6_SIZE 9
+struct unicast_frag_packet_v12 {
+ guint8 packet_type;
+ guint8 version;
+ address dest;
+ guint8 ttl;
+ guint8 flags;
+ address orig;
+ guint16 seqno;
+};
+#define UNICAST_FRAG_PACKET_V12_SIZE 18
+
struct bcast_packet_v6 {
guint8 packet_type;
guint8 version; /* batman version field */
@@ -210,8 +223,11 @@ static gint ett_batadv_bcast = -1;
static gint ett_batadv_icmp = -1;
static gint ett_batadv_icmp_rr = -1;
static gint ett_batadv_unicast = -1;
+static gint ett_batadv_unicast_frag = -1;
static gint ett_batadv_vis = -1;
static gint ett_batadv_vis_entry = -1;
+static gint ett_msg_fragment = -1;
+static gint ett_msg_fragments = -1;
/* hfs */
static int hf_batadv_packet_type = -1;
@@ -248,6 +264,13 @@ static int hf_batadv_unicast_version = -1;
static int hf_batadv_unicast_dst = -1;
static int hf_batadv_unicast_ttl = -1;
+static int hf_batadv_unicast_frag_version = -1;
+static int hf_batadv_unicast_frag_dst = -1;
+static int hf_batadv_unicast_frag_ttl = -1;
+static int hf_batadv_unicast_frag_flags = -1;
+static int hf_batadv_unicast_frag_orig = -1;
+static int hf_batadv_unicast_frag_seqno = -1;
+
static int hf_batadv_vis_version = -1;
static int hf_batadv_vis_type = -1;
static int hf_batadv_vis_seqno = -1;
@@ -261,10 +284,23 @@ static int hf_batadv_vis_entry_src = -1;
static int hf_batadv_vis_entry_dst = -1;
static int hf_batadv_vis_entry_quality = -1;
+static int hf_msg_fragments = -1;
+static int hf_msg_fragment = -1;
+static int hf_msg_fragment_overlap = -1;
+static int hf_msg_fragment_overlap_conflicts = -1;
+static int hf_msg_fragment_multiple_tails = -1;
+static int hf_msg_fragment_too_long_fragment = -1;
+static int hf_msg_fragment_error = -1;
+static int hf_msg_fragment_count = -1;
+static int hf_msg_reassembled_in = -1;
+static int hf_msg_reassembled_length = -1;
+
/* flags */
static int hf_batadv_batman_flags_directlink = -1;
static int hf_batadv_batman_flags_vis_server = -1;
static int hf_batadv_batman_flags_primaries_first_hop = -1;
+static int hf_batadv_unicast_frag_flags_head = -1;
+static int hf_batadv_unicast_frag_flags_largetail = -1;
static const value_string icmp_packettypenames[] = {
{ ECHO_REPLY, "ECHO_REPLY" },
@@ -280,6 +316,26 @@ static const value_string vis_packettypenames[] = {
{ 0, NULL }
};
+static const fragment_items msg_frag_items = {
+ /* Fragment subtrees */
+ &ett_msg_fragment,
+ &ett_msg_fragments,
+ /* Fragment fields */
+ &hf_msg_fragments,
+ &hf_msg_fragment,
+ &hf_msg_fragment_overlap,
+ &hf_msg_fragment_overlap_conflicts,
+ &hf_msg_fragment_multiple_tails,
+ &hf_msg_fragment_too_long_fragment,
+ &hf_msg_fragment_error,
+ &hf_msg_fragment_count,
+ /* Reassembled in field */
+ &hf_msg_reassembled_in,
+ &hf_msg_reassembled_length,
+ /* Tag */
+ "Message fragments"
+};
+
/* forward declaration */
void proto_reg_handoff_batadv(void);
@@ -303,7 +359,9 @@ static void dissect_batadv_icmp_v6(tvbuff_t *tvb, packet_info *pinfo, proto_tree
static void dissect_batadv_icmp_v7(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
static void dissect_batadv_unicast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static void dissect_batadv_unicast_frag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
static void dissect_batadv_unicast_v6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static void dissect_batadv_unicast_frag_v12(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
static void dissect_batadv_vis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
static void dissect_batadv_vis_v6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
@@ -323,6 +381,10 @@ static int proto_batadv_plugin = -1;
static int batadv_tap = -1;
static int batadv_follow_tap = -1;
+/* segmented messages */
+static GHashTable *msg_fragment_table = NULL;
+static GHashTable *msg_reassembled_table = NULL;
+
static unsigned int batadv_ethertype = ETH_P_BATMAN;
static void dissect_batman_plugin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
@@ -343,6 +405,9 @@ static void dissect_batman_plugin(tvbuff_t *tvb, packet_info *pinfo, proto_tree
case BATADV_UNICAST_V5:
dissect_batadv_unicast(tvb, pinfo, tree);
break;
+ case BATADV_UNICAST_FRAG_V12:
+ dissect_batadv_unicast_frag(tvb, pinfo, tree);
+ break;
case BATADV_BCAST_V5:
dissect_batadv_bcast(tvb, pinfo, tree);
break;
@@ -1489,6 +1554,132 @@ static void dissect_batadv_unicast_v6(tvbuff_t *tvb, packet_info *pinfo, proto_t
}
}
+static void dissect_batadv_unicast_frag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 version;
+
+ /* set protocol name */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BATADV_UNICAST_FRAG");
+
+ version = tvb_get_guint8(tvb, 1);
+ switch (version) {
+ case 12:
+ case 13:
+ dissect_batadv_unicast_frag_v12(tvb, pinfo, tree);
+ break;
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unsupported Version %d", version);
+ call_dissector(data_handle, tvb, pinfo, tree);
+ break;
+ }
+}
+
+static void dissect_batadv_unicast_frag_v12(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *tf;
+ struct unicast_frag_packet_v12 *unicast_frag_packeth;
+ const guint8 *dest_addr, *orig_addr;
+ gboolean save_fragmented = FALSE;
+ fragment_data *frag_msg = NULL;
+ proto_tree *batadv_unicast_frag_tree = NULL, *flag_tree;
+
+ tvbuff_t *new_tvb;
+ guint length_remaining;
+ int offset = 0;
+ int head = 0;
+
+ unicast_frag_packeth = ep_alloc(sizeof(struct unicast_frag_packet_v12));
+
+ unicast_frag_packeth->version = tvb_get_guint8(tvb, 1);
+ dest_addr = tvb_get_ptr(tvb, 2, 6);
+ SET_ADDRESS(&unicast_frag_packeth->dest, AT_ETHER, 6, dest_addr);
+ unicast_frag_packeth->ttl = tvb_get_guint8(tvb, 8);
+ unicast_frag_packeth->flags = tvb_get_guint8(tvb, 9);
+ orig_addr = tvb_get_ptr(tvb, 10, 6);
+ SET_ADDRESS(&unicast_frag_packeth->orig, AT_ETHER, 6, orig_addr);
+ unicast_frag_packeth->seqno = tvb_get_ntohs(tvb, 16);
+
+ save_fragmented = pinfo->fragmented;
+ pinfo->fragmented = TRUE;
+
+ /* Set info column */
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* Set tree info */
+ if (tree) {
+ proto_item *ti;
+
+ if (PTREE_DATA(tree)->visible) {
+ ti = proto_tree_add_protocol_format(tree, proto_batadv_plugin, tvb, 0, UNICAST_PACKET_V6_SIZE,
+ "B.A.T.M.A.N. Unicast Fragment, Dst: %s (%s)",
+ get_ether_name(dest_addr), ether_to_str(dest_addr));
+ } else {
+ ti = proto_tree_add_item(tree, proto_batadv_plugin, tvb, 0, UNICAST_PACKET_V6_SIZE, FALSE);
+ }
+ batadv_unicast_frag_tree = proto_item_add_subtree(ti, ett_batadv_unicast_frag);
+ }
+
+ /* items */
+ proto_tree_add_uint_format(batadv_unicast_frag_tree, hf_batadv_packet_type, tvb, offset, 1, BATADV_UNICAST_V5,
+ "Packet Type: %s (%u)", "BATADV_UNICAST", BATADV_UNICAST_V5);
+ offset += 1;
+
+ proto_tree_add_item(batadv_unicast_frag_tree, hf_batadv_unicast_frag_version, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_ether(batadv_unicast_frag_tree, hf_batadv_unicast_frag_dst, tvb, offset, 6, dest_addr);
+ offset += 6;
+
+ proto_tree_add_item(batadv_unicast_frag_tree, hf_batadv_unicast_frag_ttl, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ tf = proto_tree_add_item(batadv_unicast_frag_tree, hf_batadv_unicast_frag_flags, tvb, offset, 1, FALSE);
+ /* <flags> */
+ flag_tree = proto_item_add_subtree(tf, ett_batadv_batman_flags);
+ proto_tree_add_boolean(flag_tree, hf_batadv_unicast_frag_flags_head, tvb, offset, 1, unicast_frag_packeth->flags);
+ proto_tree_add_boolean(flag_tree, hf_batadv_unicast_frag_flags_largetail, tvb, offset, 1, unicast_frag_packeth->flags);
+ /* </flags> */
+ offset += 1;
+
+ proto_tree_add_ether(batadv_unicast_frag_tree, hf_batadv_unicast_frag_orig, tvb, offset, 6, orig_addr);
+ offset += 6;
+
+ proto_tree_add_item(batadv_unicast_frag_tree, hf_batadv_unicast_frag_seqno, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, orig_addr);
+ SET_ADDRESS(&pinfo->src, AT_ETHER, 6, orig_addr);
+
+ SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dest_addr);
+ SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dest_addr);
+
+ tap_queue_packet(batadv_tap, pinfo, unicast_frag_packeth);
+
+ length_remaining = tvb_length_remaining(tvb, offset);
+
+ head = (unicast_frag_packeth->flags & 0x1);
+ frag_msg = fragment_add_seq_check(tvb, offset, pinfo,
+ unicast_frag_packeth->seqno + head,
+ msg_fragment_table,
+ msg_reassembled_table,
+ 1 - head,
+ tvb_length_remaining(tvb, offset),
+ head);
+
+ new_tvb = process_reassembled_data(tvb, offset, pinfo,
+ "Reassembled Message", frag_msg, &msg_frag_items,
+ NULL, batadv_unicast_frag_tree);
+ if (new_tvb) {
+ if (have_tap_listener(batadv_follow_tap)) {
+ tap_queue_packet(batadv_follow_tap, pinfo, new_tvb);
+ }
+
+ call_dissector(eth_handle, new_tvb, pinfo, tree);
+ }
+
+ pinfo->fragmented = save_fragmented;
+}
+
static void dissect_batadv_vis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
guint8 version;
@@ -1807,6 +1998,12 @@ static void dissect_vis_entry_v8(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tr
}
}
+static void batadv_init_routine(void)
+{
+ fragment_table_init(&msg_fragment_table);
+ reassembled_table_init(&msg_reassembled_table);
+}
+
void proto_register_batadv(void)
{
module_t *batadv_module;
@@ -1972,6 +2169,46 @@ void proto_register_batadv(void)
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
+ { &hf_batadv_unicast_frag_version,
+ { "Version", "batadv.unicast_frag.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_batadv_unicast_frag_dst,
+ { "Destination", "batadv.unicast_frag.dst",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_batadv_unicast_frag_ttl,
+ { "Time to Live", "batadv.unicast_frag.ttl",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_batadv_unicast_frag_flags,
+ { "Flags", "batadv.unicast_frag.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_batadv_unicast_frag_flags_head,
+ { "Head", "batadv.unicast_frag.flags.head",
+ FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x01,
+ NULL, HFILL }
+ },
+ { &hf_batadv_unicast_frag_flags_largetail,
+ { "Largetail", "batadv.unicast_frag.flags.largetail",
+ FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x02,
+ NULL, HFILL }
+ },
+ { &hf_batadv_unicast_frag_orig,
+ { "Originator", "batadv.unicast_frag.orig",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_batadv_unicast_frag_seqno,
+ { "Sequence number", "batadv.unicast_frag.seq",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
{ &hf_batadv_vis_version,
{ "Version", "batadv.vis.version",
FT_UINT8, BASE_DEC, NULL, 0x0,
@@ -2031,6 +2268,58 @@ void proto_register_batadv(void)
{ "Quality", "batadv.vis.quality",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
+ },
+ { &hf_msg_fragments,
+ {"Message fragments", "batadv.unicast_frag.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_fragment,
+ {"Message fragment", "batadv.unicast_frag.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_fragment_overlap,
+ {"Message fragment overlap", "batadv.unicast_frag.fragment.overlap",
+ FT_BOOLEAN, 0, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_fragment_overlap_conflicts,
+ {"Message fragment overlapping with conflicting data",
+ "batadv.unicast_frag.fragment.overlap.conflicts",
+ FT_BOOLEAN, 0, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_fragment_multiple_tails,
+ {"Message has multiple tail fragments",
+ "batadv.unicast_frag.fragment.multiple_tails",
+ FT_BOOLEAN, 0, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_fragment_too_long_fragment,
+ {"Message fragment too long", "batadv.unicast_frag.fragment.too_long_fragment",
+ FT_BOOLEAN, 0, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_fragment_error,
+ {"Message defragmentation error", "batadv.unicast_frag.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_fragment_count,
+ {"Message fragment count", "batadv.unicast_frag.fragment.count",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_reassembled_in,
+ {"Reassembled in", "msg.reassembled.in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_msg_reassembled_length,
+ {"Reassembled length", "msg.reassembled.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
}
};
@@ -2044,8 +2333,11 @@ void proto_register_batadv(void)
&ett_batadv_icmp,
&ett_batadv_icmp_rr,
&ett_batadv_unicast,
+ &ett_batadv_unicast_frag,
&ett_batadv_vis,
- &ett_batadv_vis_entry
+ &ett_batadv_vis_entry,
+ &ett_msg_fragment,
+ &ett_msg_fragments
};
proto_batadv_plugin = proto_register_protocol(
@@ -2064,6 +2356,8 @@ void proto_register_batadv(void)
proto_register_subtree_array(ett, array_length(ett));
proto_register_field_array(proto_batadv_plugin, hf, array_length(hf));
+
+ register_init_routine(&batadv_init_routine);
}
void proto_reg_handoff_batadv(void)