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>
This commit is contained in:
Robert Sauter 2018-02-16 12:58:12 +01:00 committed by Stig Bjørlykke
parent 306c1c85cd
commit f0393a5975
1 changed files with 80 additions and 4 deletions

View File

@ -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)