diff options
author | Robert Sauter <sauter@locoslab.com> | 2018-02-16 12:58:12 +0100 |
---|---|---|
committer | Stig Bjørlykke <stig@bjorlykke.org> | 2018-02-17 18:14:35 +0000 |
commit | f0393a5975e96665c6d828ec2d7d103372e18acd (patch) | |
tree | 54525040c2ab75816890612e0be43ab58c776584 /epan/dissectors/packet-wisun.c | |
parent | 306c1c85cdf321ba81e5ccf0c6299182f66ea34c (diff) |
wisun: Add EDFE support
During an EDFE exchange the source addresses are omitted after the first frame.
Restore the information to enable decryption and 6LoWPAN reassembly.
Change-Id: I9660c81e0536cea56caf104a16e41eaf6c123e09
Reviewed-on: https://code.wireshark.org/review/25819
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot
Reviewed-by: Stig Bjørlykke <stig@bjorlykke.org>
Diffstat (limited to 'epan/dissectors/packet-wisun.c')
-rw-r--r-- | epan/dissectors/packet-wisun.c | 84 |
1 files changed, 80 insertions, 4 deletions
diff --git a/epan/dissectors/packet-wisun.c b/epan/dissectors/packet-wisun.c index c7980cf776..863fb5b7c0 100644 --- a/epan/dissectors/packet-wisun.c +++ b/epan/dissectors/packet-wisun.c @@ -22,12 +22,26 @@ #include <epan/etypes.h> #include <epan/oui.h> #include <wsutil/pint.h> +#include <wmem/wmem_map.h> +#include <wmem/wmem_tree.h> #include "packet-ieee802154.h" void proto_register_wisun(void); void proto_reg_handoff_wisun(void); +/* EDFE support */ +typedef struct { + ieee802154_map_rec initiator; // use start_fnum and end_fnum to record exchange start/end + ieee802154_map_rec target; +} edfe_exchange_t; + +// for each exchange, maps both source address and destination address to a +// (distinct) tree that uses the frame number of the first exchange frame to +// map to the shared edfe_exchange_t +static wmem_map_t* edfe_byaddr; + + /* Wi-SUN Header IE Sub-ID Values. */ #define WISUN_SUBID_UTT 1 #define WISUN_SUBID_BT 2 @@ -243,6 +257,7 @@ static expert_field ei_wisun_subid_unsupported = EI_INIT; static expert_field ei_wisun_wsie_short_format = EI_INIT; static expert_field ei_wisun_wsie_unsupported = EI_INIT; static expert_field ei_wisun_usie_channel_plan_invalid = EI_INIT; +static expert_field ei_wisun_edfe_start_not_found = EI_INIT; static int wisun_add_wbxml_uint(tvbuff_t *tvb, proto_tree *tree, int hf, guint offset) @@ -288,15 +303,71 @@ dissect_wisun_btie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guin return 6; } +static void +edfe_insert_exchange(guint64* addr, edfe_exchange_t* exchange) +{ + wmem_tree_t* byframe = (wmem_tree_t *)wmem_map_lookup(edfe_byaddr, addr); + if (!byframe) { + byframe = wmem_tree_new(wmem_file_scope()); + wmem_map_insert(edfe_byaddr, addr, byframe); + } + wmem_tree_insert32(byframe, exchange->initiator.start_fnum, exchange); +} + static int -dissect_wisun_fcie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset) +dissect_wisun_fcie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, ieee802154_packet *packet) { nstime_t ts; ts.secs = 0; - ts.nsecs = tvb_get_guint8(tvb, offset) * 1000000UL; + guint8 tx = tvb_get_guint8(tvb, offset); + ts.nsecs = tx * 1000000; proto_tree_add_time(tree, hf_wisun_fcie_tx, tvb, offset, 1, &ts); - ts.nsecs = tvb_get_guint8(tvb, offset+1) * 1000000UL; + guint8 rx = tvb_get_guint8(tvb, offset + 1); + ts.nsecs = rx * 1000000; proto_tree_add_time(tree, hf_wisun_fcie_rx, tvb, offset + 1, 1, &ts); + + // EDFE processing + ieee802154_hints_t* hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, + proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0); + if (packet && hints && packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) { + // first packet has source address + if (!hints->map_rec && packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) { + edfe_exchange_t* ex = wmem_new(wmem_file_scope(), edfe_exchange_t); + ex->initiator.proto = ex->target.proto = "Wi-SUN"; + ex->initiator.addr64 = packet->src64; + ex->target.addr64 = packet->dst64; + ex->initiator.start_fnum = pinfo->num; + ex->initiator.end_fnum = ~(guint)0; + edfe_insert_exchange(&ex->initiator.addr64, ex); + edfe_insert_exchange(&ex->target.addr64, ex); + } else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) { + if (!hints->map_rec) { + wmem_tree_t* byframe = (wmem_tree_t *)wmem_map_lookup(edfe_byaddr, &packet->dst64); + if (byframe) { + edfe_exchange_t *ex = (edfe_exchange_t *)wmem_tree_lookup32_le(byframe, pinfo->num); + if (ex && pinfo->num <= ex->initiator.end_fnum) { + hints->map_rec = ex->initiator.addr64 == packet->dst64 ? &ex->target : &ex->initiator; + if (tx == 0 && rx == 0) { + // last frame + ex->initiator.end_fnum = pinfo->num; + } + } + } + } + if (hints->map_rec) { + // Set address to ensure that 6LoWPAN reassembly works + // Adapted from packet-ieee802.15.4.c + guint64 *p_addr = wmem_new(pinfo->pool, guint64); + /* Copy and convert the address to network byte order. */ + *p_addr = pntoh64(&(hints->map_rec->addr64)); + set_address(&pinfo->dl_src, AT_EUI64, 8, p_addr); + copy_address_shallow(&pinfo->src, &pinfo->dl_src); + } else { + expert_add_info(pinfo, tree, &ei_wisun_edfe_start_not_found); + } + } + } + return 2; } @@ -321,6 +392,7 @@ dissect_wisun_hie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat guint offset; proto_tree *subtree; guint8 subid = tvb_get_guint8(tvb, 2); + ieee802154_packet *packet = (ieee802154_packet*)data; offset = 3; switch (subid) { @@ -336,7 +408,7 @@ dissect_wisun_hie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat case WISUN_SUBID_FC: subtree = wisun_create_hie_tree(tvb, tree, hf_wisun_fcie, ett_wisun_fcie); - offset += dissect_wisun_fcie(tvb, pinfo, subtree, offset); + offset += dissect_wisun_fcie(tvb, pinfo, subtree, offset, packet); break; case WISUN_SUBID_RSL: @@ -1057,6 +1129,8 @@ void proto_register_wisun(void) "Invalid Channel Plan", EXPFILL }}, { &ei_wisun_wsie_unsupported, { "wisun.wsie.unsupported", PI_PROTOCOL, PI_WARN, "Unsupported Sub-IE ID", EXPFILL }}, + { &ei_wisun_edfe_start_not_found, { "wisun.edfe.start_not_found", PI_SEQUENCE, PI_WARN, + "EDFE Transfer: start frame not found", EXPFILL }}, }; expert_module_t* expert_wisun; @@ -1071,6 +1145,8 @@ void proto_register_wisun(void) expert_register_field_array(expert_wisun, ei, array_length(ei)); register_dissector("wisun.sec", dissect_wisun_sec, proto_wisun_sec); + + edfe_byaddr = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_int64_hash, g_int64_equal); } void proto_reg_handoff_wisun(void) |