Exemplo n.º 1
0
/*
 *  get a Lilliputian signed 64 bit integer from a tvb
 */
WSLUA_METHOD TvbRange_le_int64(lua_State* L) {
	/* Get a Little Endian signed 64 bit integer from a TvbRange. The range must be 1-8 octets long. */
    TvbRange tvbr = checkTvbRange(L,1);
    if (!(tvbr && tvbr->tvb)) return 0;
    if (tvbr->tvb->expired) {
        luaL_error(L,"expired tvb");
        return 0;
    }

    switch (tvbr->len) {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8: {
            Int64 num = (Int64)g_malloc(sizeof(gint64));
            *num = (gint64)tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset);
            pushInt64(L,num);
            WSLUA_RETURN(1);
        }
        default:
            luaL_error(L,"TvbRange:le_int64() does not handle %d byte integers",tvbr->len);
            return 0;
    }
}
Exemplo n.º 2
0
/*
 *  get a Lilliputian signed 64 bit integer from a tvb
 */
WSLUA_METHOD TvbRange_le_int64(lua_State* L) {
    /* Get a Little Endian signed 64 bit integer from a `TvbRange`, as an `Int64` object.
       The range must be 1, 2, 4 or 8 octets long. */
    TvbRange tvbr = checkTvbRange(L,1);
    if (!(tvbr && tvbr->tvb)) return 0;
    if (tvbr->tvb->expired) {
        luaL_error(L,"expired tvb");
        return 0;
    }

    switch (tvbr->len) {
        case 1:
            pushInt64(L,(gint8)tvb_get_guint8(tvbr->tvb->ws_tvb,tvbr->offset));
            return 1;
        case 2:
            pushInt64(L,(gint16)tvb_get_letohs(tvbr->tvb->ws_tvb,tvbr->offset));
            return 1;
        case 4:
            pushInt64(L,(gint32)tvb_get_letohl(tvbr->tvb->ws_tvb,tvbr->offset));
            return 1;
        case 8:
            pushInt64(L,(gint64)tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset));
            WSLUA_RETURN(1); /* The `Int64` object. */
        default:
            luaL_error(L,"TvbRange:le_int64() does not handle %d byte integers",tvbr->len);
            return 0;
    }
}
static guint64
corosync_totemsrp_get_guint64(tvbuff_t* tvb, gint offset, const guint encoding)
{
  if (encoding == ENC_LITTLE_ENDIAN)
    return tvb_get_letoh64(tvb, offset);

  return tvb_get_ntoh64(tvb, offset);
}
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      zdp_parse_neighbor_table_entry
 *  DESCRIPTION
 *      Parses and displays a neighbor table entry.
 *  PARAMETERS
 *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
 *      packet_into *pinfo  - pointer to packet information fields
 *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
 *  RETURNS
 *      void
 *---------------------------------------------------------------
 */
static void
zdp_parse_neighbor_table_entry(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint8 version)
{
    proto_item      *ti = NULL;
    guint           len = 0;

    guint64 ext_pan;
    guint16 pan;
    guint64 ext_addr;
    guint16 device;
    guint8  type;
    guint8  idle_rx;
    guint8  rel;
    guint8  permit_joining;
    guint8  depth;
    guint8  lqi;

    if (version >= ZBEE_VERSION_2007) {
        /* ZigBee 2006 & later use an extended PAN Identifier. */
        ext_pan = tvb_get_letoh64(tvb, *offset + len);
        if (tree) ti = proto_tree_add_text(tree, tvb, *offset, 0, "{Extended PAN: %s", eui64_to_str(ext_pan));
        len += 8;
    }
    else {
        /* ZigBee 2003 & earlier use a short PAN Identifier. */
        pan = tvb_get_letohs(tvb, *offset + len);
        if (tree) ti = proto_tree_add_text(tree, tvb, *offset, 0, "{PAN: 0x%04x", pan);
        len += 2;
    }

    ext_addr = tvb_get_letoh64(tvb, *offset + len);
    if (tree) proto_item_append_text(ti, ", Extended Addr: %s", ep_eui64_to_display(ext_addr));
    len += 8;

    device = tvb_get_letohs(tvb, *offset + len);
    if (tree) proto_item_append_text(ti, ", Addr: 0x%04x", device);
    len += 2;

    if (version >= ZBEE_VERSION_2007) {
        type    = (tvb_get_guint8(tvb, *offset + len) & 0x03) >> 0;
        idle_rx = (tvb_get_guint8(tvb, *offset + len) & 0x0c) >> 2;
        rel     = (tvb_get_guint8(tvb, *offset + len) & 0x70) >> 4;
    }
Exemplo n.º 5
0
static int dissect_req_cookie(tvbuff_t * tvb, proto_tree *tree, int offset)
{
	guint32 req;
	req= tvb_get_letoh64(tvb, offset);
	if (!req)
		proto_tree_add_text(tree, tvb, offset, 8, "Ack not required");
	else
		proto_tree_add_item(tree, hf_lnet_ksm_zc_req_cookie, tvb, offset, 8, little_endian);
	return offset + 8;
}
Exemplo n.º 6
0
static int dissect_ack_cookie(tvbuff_t * tvb, proto_tree *tree, int offset)
{
	guint32 ack;
	ack= tvb_get_letoh64(tvb, offset);
	if (!ack)
		proto_tree_add_text(tree, tvb, offset, 8, "Not ack");
	else
		proto_tree_add_item(tree, hf_lnet_ksm_zc_ack_cookie, tvb, offset, 8, little_endian);
	return offset + 8;
}
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      zdp_parse_nwk_desc
 *  DESCRIPTION
 *      Parses and displays a single network descriptor
 *  PARAMETERS
 *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
 *      packet_into *pinfo  - pointer to packet information fields
 *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
 *  RETURNS
 *      void
 *---------------------------------------------------------------
 */
static void
zdp_parse_nwk_desc(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint8 version)
{
    proto_item      *ti = NULL;
    guint           len = 0;

    guint64     ext_pan;
    guint16     pan;
    guint8      channel;
    guint8      profile;
    guint8      profile_version;
    guint8      beacon;
    guint8      superframe;
    gboolean    permit;

    if (version >= ZBEE_VERSION_2007) {
        /* Extended PAN Identifiers are used in ZigBee 2006 & later. */
        ext_pan = tvb_get_letoh64(tvb, *offset + len);
        if (tree) ti = proto_tree_add_text(tree, tvb, *offset, 0, "{Pan: %s", eui64_to_str(ext_pan));
        len += 8;
    }
    else {
        /* Short PAN Identifiers are used in ZigBee 2003 and earlier. */
        pan = tvb_get_letohs(tvb, *offset + len);
        if (tree) ti = proto_tree_add_text(tree, tvb, *offset, 0, "{Pan: 0x%04x", pan);
        len += 2;
    }

    channel = tvb_get_guint8(tvb, *offset + len);
    if (tree) proto_item_append_text(ti, ", Channel: %d", channel);
    len += 1;

    profile = (tvb_get_guint8(tvb, *offset + len) & 0x0f) >> 0;
    profile_version = (tvb_get_guint8(tvb, *offset + len) & 0xf0) >> 4;
    if (tree) proto_item_append_text(ti, ", Profile: 0x%01x, Version: %d", profile, profile_version);
    len += 1;

    beacon      = (tvb_get_guint8(tvb, *offset + len) & 0x0f) >> 0;
    superframe  = (tvb_get_guint8(tvb, *offset + len) & 0xf0) >> 4;
    if ((tree) && (beacon == 0xf)) {
        proto_item_append_text(ti, ", Beacons Disabled");
    }
    else if (tree) {
        proto_item_append_text(ti, ", BeaconOrder: %d, SuperframeOrder: %d", beacon, superframe);
    }
    len += 1;

    permit = tvb_get_guint8(tvb, *offset) & 0x01;
    if (tree) proto_item_append_text(ti, ", PermitJoining: %s}", permit?"True":"False");
    len += 1;

    if (tree) proto_item_set_len(ti, len);
    *offset += len;
} /* zdp_parse_nwk_desc */
Exemplo n.º 8
0
/* dissect 9P Qid */
static void dissect_9P_qid(tvbuff_t * tvb,  proto_tree * tree,int offset)
{
	proto_item *qid_item,*qidtype_item;
	proto_tree *qid_tree,*qidtype_tree;
	guint64 path;
	guint32 vers;
	guint8 type;

	if(!tree)
		return;
	
	type = tvb_get_guint8(tvb,offset);
	vers = tvb_get_letohs(tvb,offset+1);
	path = tvb_get_letoh64(tvb,offset+1+4);

	qid_item = proto_tree_add_text(tree,tvb,offset,13,"Qid type=0x%02x vers=%d path=%" G_GINT64_MODIFIER "u",type,vers,path);
	qid_tree = proto_item_add_subtree(qid_item,ett_9P_qid);

	qidtype_item = proto_tree_add_item(qid_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
	qidtype_tree = proto_item_add_subtree(qidtype_item,ett_9P_qidtype);

	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTDIR, 8, "Directory", "not a Directory"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTAPPEND, 8, "Append only", "not Append only"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTEXCL, 8, "Exclusive use", "not Exclusive use"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTMOUNT, 8, "Mounted channel", "not a Mounted channel"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTAUTH, 8, "Authentication file", "not an Authentication file"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTTMP, 8, "Temporary file (not backed up)", "not a Temporary file"));

	proto_tree_add_item(qid_tree, hf_9P_qidvers, tvb, offset+1, 4, TRUE);
	proto_tree_add_item(qid_tree, hf_9P_qidpath, tvb, offset+1+4, 8, TRUE);
}
Exemplo n.º 9
0
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      zdp_parse_bind_table_entry
 *  DESCRIPTION
 *      Parses and displays a single binding table entry.
 *  PARAMETERS
 *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
 *      packet_into *pinfo  - pointer to packet information fields
 *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
 *  RETURNS
 *      void
 *---------------------------------------------------------------
 */
void
zdp_parse_bind_table_entry(proto_tree *tree, tvbuff_t *tvb, guint *offset, packet_info *pinfo)
{
    proto_item      *ti = NULL;
    guint           len = 0;

    guint64 src64;
    guint8  src_ep;
    guint16 cluster;
    guint8  mode;
    guint64 dst64;
    guint16 dst;
    guint8  dst_ep;

    /* Add the source address. */
    src64 = tvb_get_letoh64(tvb, *offset + len);
    if (tree) ti = proto_tree_add_text(tree, tvb, *offset, 0, "Bind {Src: %s", get_eui64_name(src64));
    len += sizeof(guint64);

    /* Add the source endpoint. */
    src_ep = tvb_get_guint8(tvb, *offset + len);
    if (tree) proto_item_append_text(ti, ", Src Endpoint: %d", src_ep);
    len += sizeof(guint8);

    /* Add the cluster ID. */
    if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) {
        cluster = tvb_get_letohs(tvb, *offset + len);
        len += sizeof(guint16);
    }
    else {
        cluster = tvb_get_guint8(tvb, *offset + len);
        len += sizeof(guint8);
    }
    if (tree) proto_item_append_text(ti, ", Cluster: %d", cluster);

    /* Get the destination address mode. */
    if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) {
        mode = tvb_get_guint8(tvb, *offset + len);
        len += sizeof(guint8);
    }
    else {
        /* Mode field doesn't exist and always uses unicast in 2003 & earlier. */
        mode = ZBEE_ZDP_ADDR_MODE_UNICAST;
    }

    /* Add the destination address. */
    if (mode == ZBEE_ZDP_ADDR_MODE_GROUP) {
        dst = tvb_get_letohs(tvb, *offset + len);
        if (tree) proto_item_append_text(ti, ", Dst: 0x%04x}", dst);
        len += sizeof(guint16);
    }
    else if (mode == ZBEE_ZDP_ADDR_MODE_UNICAST) {
        dst64 = tvb_get_letoh64(tvb, *offset + len);
        if (tree) proto_item_append_text(ti, ", Dst: %s", get_eui64_name(dst64));
        len += sizeof(guint64);

        dst_ep = tvb_get_guint8(tvb, *offset + len);
        if (tree) proto_item_append_text(ti, ", Dst Endpoint: %d}", dst_ep);
        len += sizeof(guint8);
    }
    else {
        if (tree) proto_item_append_text(ti, "}");
    }

    if (tree) {
        proto_item_set_len(ti, len);
    }
    *offset += len;
} /* zdp_parse_bind_table_entry */
static void
dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *radiotap_tree = NULL;
    proto_tree *pt, *present_tree = NULL;
    proto_tree *ft;
    proto_item *ti = NULL, *hidden_item;
    int align_offset, offset;
    tvbuff_t *next_tvb;
    guint32 version;
    guint length, length_remaining;
    guint32 rate, freq, flags;
    gint8 dbm;
    guint8 db, rflags;
    guint32 present, next_present;
    int bit;
    /* backward compat with bit 14 == fcs in header */
    proto_item *hdr_fcs_ti = NULL;
    int hdr_fcs_offset = 0;
    guint32 sent_fcs = 0;
    guint32 calc_fcs;

    struct _radiotap_info *radiotap_info;
    static struct _radiotap_info rtp_info_arr[1];
    
    radiotap_info = &rtp_info_arr[0];

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
    col_clear(pinfo->cinfo, COL_INFO);
    offset = 0;

    version = tvb_get_guint8(tvb, offset);
    length = tvb_get_letohs(tvb, offset+2);
    present = tvb_get_letohl(tvb, offset+4);
    
    radiotap_info->radiotap_length = length;

    col_add_fstr(pinfo->cinfo, COL_INFO, "Radiotap Capture v%u, Length %u",
		version, length);

    /* Dissect the packet */
    if (tree) {
	ti = proto_tree_add_protocol_format(tree, proto_radiotap,
		tvb, 0, length, "Radiotap Header v%u, Length %u", version, length);
	radiotap_tree = proto_item_add_subtree(ti, ett_radiotap);
	proto_tree_add_uint(radiotap_tree, hf_radiotap_version,
		tvb, offset, 1, version);
	proto_tree_add_item(radiotap_tree, hf_radiotap_pad,
		tvb, offset + 1, 1, FALSE);
	ti = proto_tree_add_uint(radiotap_tree, hf_radiotap_length,
		tvb, offset + 2, 2, length);
    }
    length_remaining = length;

    /*
     * FIXME: This only works if there is exactly 1 it_present
     *        field in the header
     */
    if (length_remaining < RADIOTAP_MIN_HEADER_LEN) {
	/*
	 * Radiotap header is shorter than the fixed-length portion
	 * plus one "present" bitset.
	 */
	if (tree)
	    proto_item_append_text(ti, " (bogus - minimum length is 8)");
	return;
    }
    /* Subtree for the "present flags" bitfield. */
    if (tree) {
	pt = proto_tree_add_uint(radiotap_tree, hf_radiotap_present,
	    tvb, offset + 4, 4, present);
	present_tree = proto_item_add_subtree(pt, ett_radiotap_present);

	proto_tree_add_item(present_tree, hf_radiotap_present_tsft,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_flags,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_rate,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_channel,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_fhss,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_dbm_antsignal,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_dbm_antnoise,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_lock_quality,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_tx_attenuation,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_db_tx_attenuation,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_dbm_tx_attenuation,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_antenna,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_db_antsignal,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_db_antnoise,
	    tvb, offset + 4, 4, TRUE);
	if (radiotap_bit14_fcs) {
		proto_tree_add_item(present_tree, hf_radiotap_present_hdrfcs,
			tvb, offset + 4, 4, TRUE);
	} else {
		proto_tree_add_item(present_tree, hf_radiotap_present_rxflags,
			tvb, offset + 4, 4, TRUE);
	}
	proto_tree_add_item(present_tree, hf_radiotap_present_xchannel,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_ext,
	    tvb, offset + 4, 4, TRUE);
    }
    offset += RADIOTAP_MIN_HEADER_LEN;
    length_remaining -= RADIOTAP_MIN_HEADER_LEN;

    rflags = 0;
    for (; present; present = next_present) {
	/* clear the least significant bit that is set */
	next_present = present & (present - 1);

	/* extract the least significant bit that is set */
	bit = BITNO_32(present ^ next_present);

	switch (bit) {

	case IEEE80211_RADIOTAP_TSFT:
	    align_offset = ALIGN_OFFSET(offset, 8);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 8)
		break;
            radiotap_info->tsft=tvb_get_letoh64(tvb, offset);
	    if (tree) {
		proto_tree_add_uint64(radiotap_tree, hf_radiotap_mactime,
				tvb, offset, 8,radiotap_info->tsft );
	    }
	    offset+=8;
	    length_remaining-=8;
	    break;

	case IEEE80211_RADIOTAP_FLAGS:
	{
	    proto_tree *flags_tree;
	    if (length_remaining < 1)
		break;
	    rflags = tvb_get_guint8(tvb, offset);
	    if (tree) {
		ft = proto_tree_add_item(radiotap_tree, hf_radiotap_flags,
					 tvb, offset, 1, FALSE);
		flags_tree = proto_item_add_subtree(ft, ett_radiotap_flags);

		proto_tree_add_item(flags_tree, hf_radiotap_flags_cfp,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_preamble,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_wep,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_frag,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_fcs,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_datapad,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_badfcs,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_shortgi,
			tvb, offset, 1, FALSE);
	    }
	    offset++;
	    length_remaining--;
	    break;
	}

	case IEEE80211_RADIOTAP_RATE:
	    if (length_remaining < 1)
		break;
	    rate = tvb_get_guint8(tvb, offset);
	    if (rate & 0x80) {
		/* XXX adjust by CW and short GI like other sniffers? */
		rate = ieee80211_htrates[rate & 0xf];
	    }
	    col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%d.%d",
		rate / 2, rate & 1 ? 5 : 0);
	    if (tree) {
		proto_tree_add_float_format(radiotap_tree, hf_radiotap_datarate,
			tvb, offset, 1, (float)rate / 2,
			"Data Rate: %.1f Mb/s", (float)rate / 2);
	    }
	    offset++;
	    length_remaining--;
            radiotap_info->rate = rate;
	    break;

	case IEEE80211_RADIOTAP_CHANNEL:
	{
	    proto_item *it;
	    proto_tree *flags_tree;
	    gchar *chan_str;

	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    if (tree) {
		freq = tvb_get_letohs(tvb, offset);
		flags = tvb_get_letohs(tvb, offset+2);
		chan_str = ieee80211_mhz_to_str(freq);
		col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%s", chan_str);
		proto_tree_add_uint_format(radiotap_tree, hf_radiotap_channel_frequency,
				tvb, offset, 2, freq,
				"Channel frequency: %s", chan_str);
		g_free(chan_str);
		/* We're already 2-byte aligned. */
		it = proto_tree_add_uint(radiotap_tree, hf_radiotap_channel_flags,
			tvb, offset+2, 2, flags);
		flags_tree = proto_item_add_subtree(it, ett_radiotap_channel_flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_turbo,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_cck,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_ofdm,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_2ghz,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_5ghz,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_passive,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_dynamic,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_gfsk,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_gsm,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_sturbo,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_half,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_quarter,
			tvb, offset+3, 1, flags);
		radiotap_info->freq=freq;
		radiotap_info->flags=flags;
	    }
	    offset+=4 /* Channel + flags */;
	    length_remaining-=4;
	    break;
	}

	case IEEE80211_RADIOTAP_FHSS:
	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    proto_tree_add_item(radiotap_tree, hf_radiotap_fhss_hopset,
		tvb, offset, 1, FALSE);
	    proto_tree_add_item(radiotap_tree, hf_radiotap_fhss_pattern,
		tvb, offset, 1, FALSE);
	    offset+=2;
	    length_remaining-=2;
	    break;

	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
	    if (length_remaining < 1)
		break;
	    dbm = (gint8) tvb_get_guint8(tvb, offset);
	    col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", dbm);
	    if (tree) {
		proto_tree_add_int_format(radiotap_tree,
					  hf_radiotap_dbm_antsignal,
					  tvb, offset, 1, dbm,
					  "SSI Signal: %d dBm", dbm);
	    }
	    offset++;
	    length_remaining--;
            radiotap_info->dbm_antsignal=dbm;
	    break;

	case IEEE80211_RADIOTAP_DBM_ANTNOISE:
	    if (length_remaining < 1)
		break;
	    dbm = (gint8) tvb_get_guint8(tvb, offset);
	    if (tree) {
		proto_tree_add_int_format(radiotap_tree,
					  hf_radiotap_dbm_antnoise,
					  tvb, offset, 1, dbm,
					  "SSI Noise: %d dBm", dbm);
	    }
	    offset++;
	    length_remaining--;
            radiotap_info->dbm_antnoise=dbm;
	    break;

	case IEEE80211_RADIOTAP_LOCK_QUALITY:
	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    if (tree) {
		proto_tree_add_uint(radiotap_tree, hf_radiotap_quality,
				tvb, offset, 2, tvb_get_letohs(tvb, offset));
	    }
	    offset+=2;
	    length_remaining-=2;
	    break;

	case IEEE80211_RADIOTAP_TX_ATTENUATION:
	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    proto_tree_add_item(radiotap_tree, hf_radiotap_tx_attenuation,
		tvb, offset, 2, FALSE);
	    offset+=2;
	    length_remaining-=2;
	    break;

	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    proto_tree_add_item(radiotap_tree, hf_radiotap_db_tx_attenuation,
		tvb, offset, 2, FALSE);
	    offset+=2;
	    length_remaining-=2;
	    break;

	case IEEE80211_RADIOTAP_DBM_TX_POWER:
	    if (length_remaining < 1)
		break;
	    if (tree) {
		proto_tree_add_int(radiotap_tree, hf_radiotap_txpower,
				   tvb, offset, 1, tvb_get_guint8(tvb, offset));
	    }
	    offset++;
	    length_remaining--;
	    break;

	case IEEE80211_RADIOTAP_ANTENNA:
	    if (length_remaining < 1)
		break;
	    if (tree) {
		proto_tree_add_uint(radiotap_tree, hf_radiotap_antenna,
				   tvb, offset, 1, tvb_get_guint8(tvb, offset));
	    }
	    offset++;
	    length_remaining--;
	    break;

	case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
	    if (length_remaining < 1)
		break;
	    db = tvb_get_guint8(tvb, offset);
	    col_add_fstr(pinfo->cinfo, COL_RSSI, "%u dB", db);
	    if (tree) {
		proto_tree_add_uint_format(radiotap_tree,
					   hf_radiotap_db_antsignal,
					   tvb, offset, 1, db,
					   "SSI Signal: %u dB", db);
	    }
	    offset++;
	    length_remaining--;
	    break;

	case IEEE80211_RADIOTAP_DB_ANTNOISE:
	    if (length_remaining < 1)
		break;
	    db = tvb_get_guint8(tvb, offset);
	    if (tree) {
		proto_tree_add_uint_format(radiotap_tree,
					   hf_radiotap_db_antnoise,
					   tvb, offset, 1, db,
					   "SSI Noise: %u dB", db);
	    }
	    offset++;
	    length_remaining--;
	    break;

	case IEEE80211_RADIOTAP_RX_FLAGS:
	{
	    proto_tree *flags_tree;
	    if (radiotap_bit14_fcs) {
	        align_offset = ALIGN_OFFSET(offset, 4);
	        offset += align_offset;
	        length_remaining -= align_offset;
	        if (length_remaining < 4)
	            break;
                if (tree) {
                    sent_fcs = tvb_get_ntohl(tvb, offset);
                    hdr_fcs_ti = proto_tree_add_uint(radiotap_tree, hf_radiotap_fcs,
                                                     tvb, offset, 4, sent_fcs);
                    hdr_fcs_offset = offset;
                }
                offset+=4;
                length_remaining-=4;
	    } else {
	        proto_item *it;

                align_offset = ALIGN_OFFSET(offset, 2);
                offset += align_offset;
                length_remaining -= align_offset;
                if (length_remaining < 2)
                    break;
                if (tree) {
                    flags = tvb_get_letohs(tvb, offset);
                    it = proto_tree_add_uint(radiotap_tree, hf_radiotap_rxflags,
                            tvb, offset, 2, flags);
                    flags_tree = proto_item_add_subtree(it, ett_radiotap_rxflags);
                    proto_tree_add_boolean(flags_tree, hf_radiotap_rxflags_badplcp,
                            tvb, offset, 1, flags);
                }
                offset+=2;
                length_remaining-=2;
            }
	    break;
	}

	case IEEE80211_RADIOTAP_XCHANNEL:
	{
	    proto_item *it;
	    proto_tree *flags_tree;

	    align_offset = ALIGN_OFFSET(offset, 4);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 8)
		break;
	    if (tree) {
	        int channel;
	        guint8 maxpower;

		flags = tvb_get_letohl(tvb, offset);
		freq = tvb_get_letohs(tvb, offset+4);
		channel = tvb_get_guint8(tvb, offset+6);
		maxpower = tvb_get_guint8(tvb, offset+7);
		proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel,
			tvb, offset+6, 1, (guint32) channel);
		proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_frequency,
			tvb, offset+4, 2, freq);
		it = proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_flags,
			tvb, offset+0, 4, flags);
		flags_tree = proto_item_add_subtree(it, ett_radiotap_xchannel_flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_turbo,
			tvb, offset+0, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_cck,
			tvb, offset+0, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ofdm,
			tvb, offset+0, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_2ghz,
			tvb, offset+0, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_5ghz,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_passive,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_dynamic,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_gfsk,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_gsm,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_sturbo,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_half,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_quarter,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht20,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht40u,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht40d,
			tvb, offset+2, 1, flags);
#if 0
		proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_maxpower,
			tvb, offset+7, 1, maxpower);
#endif
	    }
	    offset+=8 /* flags + freq + ieee + maxregpower */;
	    length_remaining-=8;
	    break;
	}

	default:
	    /*
	     * This indicates a field whose size we do not
	     * know, so we cannot proceed.
	     */
	    next_present = 0;
	    continue;
	}
    }

    /* This handles the case of an FCS exiting at the end of the frame. */
    if (rflags & IEEE80211_RADIOTAP_F_FCS)
	pinfo->pseudo_header->ieee_802_11.fcs_len = 4;
    else
	pinfo->pseudo_header->ieee_802_11.fcs_len = 0;

    /* Grab the rest of the frame. */
    next_tvb = tvb_new_subset_remaining(tvb, length);

    /* If we had an in-header FCS, check it.
     * This can only happen if the backward-compat configuration option
     * is chosen by the user. */
    if (hdr_fcs_ti) {
        /* It would be very strange for the header to have an FCS for the
         * frame *and* the frame to have the FCS at the end, but it's possible, so
         * take that into account by using the FCS length recorded in pinfo. */

        /* Watch out for [erroneously] short frames */
        if (tvb_length(next_tvb) > (unsigned int) pinfo->pseudo_header->ieee_802_11.fcs_len) {
            calc_fcs = crc32_802_tvb(next_tvb,
                    tvb_length(next_tvb) - pinfo->pseudo_header->ieee_802_11.fcs_len);

            /* By virtue of hdr_fcs_ti being set, we know that 'tree' is set,
             * so there's no need to check it here. */
            if (calc_fcs == sent_fcs) {
                proto_item_append_text(hdr_fcs_ti, " [correct]");
            }
            else {
                proto_item_append_text(hdr_fcs_ti,
                        " [incorrect, should be 0x%08x]", calc_fcs);
                hidden_item = proto_tree_add_boolean(radiotap_tree, hf_radiotap_fcs_bad,
                        tvb, hdr_fcs_offset, 4, TRUE);
                PROTO_ITEM_SET_HIDDEN(hidden_item);
            }
        }
        else {
                proto_item_append_text(hdr_fcs_ti,
                        " [cannot verify - not enough data]");
        }
    }

    /* dissect the 802.11 header next */
    call_dissector((rflags & IEEE80211_RADIOTAP_F_DATAPAD) ?
        ieee80211_datapad_handle : ieee80211_handle,
        next_tvb, pinfo, tree);
    
    tap_queue_packet(radiotap_tap, pinfo, radiotap_info);
}
Exemplo n.º 11
0
static int
dissect_dtpt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*dtpt_tree = NULL;
	proto_item	*dtpt_item = NULL;
	guint8		version;
	guint8		message_type;
	guint32		flags;
	guint32		payload_size;

	version = tvb_get_guint8(tvb, 0);
	if (version != 1) return 0;
	message_type = tvb_get_guint8(tvb, 1);
	switch (message_type) {
		case LookupBeginRequest:
		case LookupBeginResponse:
		case LookupNextRequest:
		case LookupNextResponse:
		case LookupEndRequest:
			if (tvb_reported_length(tvb) != 20) return 0;
		break;
		case ConnectRequest:
		case ConnectResponseOK:
		case ConnectResponseERR:
			if (tvb_reported_length(tvb) != 36) return 0;
		break;
		default:
			return 0;
	}

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTPT");
	if (check_col(pinfo->cinfo, COL_INFO))
		col_add_str(pinfo->cinfo, COL_INFO, val_to_str(message_type, names_message_type, "Unknown (%d)"));

	if (message_type == LookupBeginRequest) {
		conversation_t *c;
		c = find_or_create_conversation(pinfo);
		conversation_set_dissector(c, dtpt_conversation_handle);
	}

	if (tree) {
		dtpt_item = proto_tree_add_item(tree, proto_dtpt,
				tvb, 0, -1, ENC_NA);
		if (dtpt_item)
			dtpt_tree = proto_item_add_subtree(dtpt_item, ett_dtpt);
	}

	if (dtpt_tree) {
		proto_tree_add_uint(dtpt_tree, hf_dtpt_version,
			tvb, 0, 1, version);
		proto_tree_add_uint(dtpt_tree, hf_dtpt_message_type,
			tvb, 1, 1, message_type);

		switch (message_type) {
			case LookupBeginRequest: {
				proto_item* flags_item = NULL;
				proto_tree*	flags_tree = NULL;

				flags = tvb_get_letohl(tvb, 12);

				flags_item = proto_tree_add_uint(dtpt_tree, hf_dtpt_flags,
					tvb, 12, 4, flags);
				if (flags_item) {
					flags_tree = proto_item_add_subtree(flags_item, ett_dtpt_flags);
				}
				if (flags_tree) {
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_res_service,   tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushprevious, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushcache,    tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_query_string, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_aliases, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_blob, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_addr, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_comment, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_version, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_type, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_name, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nearest, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nocontainers, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_containers, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_deep, tvb, 12, 4, flags);
				}
				payload_size = tvb_get_letohl(tvb, 16);
				proto_tree_add_uint(dtpt_tree, hf_dtpt_payload_size,
					tvb, 16, 4, payload_size);
			}
			break;
			case LookupBeginResponse: {
				proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle,
					tvb, 4, 8, tvb_get_letoh64(tvb, 4));
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 12, 4, tvb_get_letohl(tvb, 12));
			}
			break;
			case LookupNextRequest: {
				proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle,
					tvb, 4, 8, tvb_get_letoh64(tvb, 4));
				proto_tree_add_uint(dtpt_tree, hf_dtpt_buffer_size,
					tvb, 16, 4, tvb_get_letohl(tvb, 16));
			}
			break;
			case LookupNextResponse: {
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 12, 4, tvb_get_letohl(tvb, 12));
				proto_tree_add_uint(dtpt_tree, hf_dtpt_data_size,
					tvb, 16, 4, tvb_get_letohl(tvb, 16));
			}
			break;
			case LookupEndRequest: {
				proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle,
					tvb, 4, 8, tvb_get_letoh64(tvb, 4));
			}
			break;
			case ConnectRequest: {
				dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT);
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 32, 4, tvb_get_letohl(tvb, 32));
			}
			break;
			case ConnectResponseOK: {
				dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT);
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 32, 4, tvb_get_letohl(tvb, 32));
			}
			break;
			case ConnectResponseERR: {
				dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT);
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 32, 4, tvb_get_letohl(tvb, 32));
			}
			break;
		}
	}

	return tvb_length(tvb);
}
Exemplo n.º 12
0
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      dissect_zbee_secure
 *  DESCRIPTION
 *      Dissects and decrypts secured ZigBee frames.
 *
 *      Will return a valid tvbuff only if security processing was
 *      successful. If processing fails, then this function will
 *      handle internally and return NULL.
 *  PARAMETERS
 *      tvbuff_t    *tvb    - pointer to buffer containing raw packet.
 *      packet_into *pinfo  - pointer to packet information fields
 *      proto_tree  *tree   - pointer to data tree Wireshark uses to display packet.
 *      guint       offset  - pointer to the start of the auxilliary security header.
 *      guint64     src     - extended source address, or 0 if unknown.
 *  RETURNS
 *      tvbuff_t *
 *---------------------------------------------------------------
 */
tvbuff_t *
dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset, guint64 src)
{
    proto_tree *    sec_tree = NULL;
    proto_item *    sec_root;
    proto_tree *    field_tree;
    proto_item *    ti;

    zbee_security_packet    packet;
    guint           mic_len;
    guint           payload_len;
    tvbuff_t *      payload_tvb;

#ifdef HAVE_LIBGCRYPT
    const guint8 *  enc_buffer;
    guint8 *        dec_buffer;
    guint8 *        key_buffer;
    guint8          nonce[ZBEE_SEC_CONST_NONCE_LEN];
#endif

    /* Create a substree for the security information. */
    if (tree) {
        sec_root = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ZigBee Security Header");
        sec_tree = proto_item_add_subtree(sec_root, ett_zbee_sec);
    }

    /*  Get and display the Security control field */
    packet.control  = tvb_get_guint8(tvb, offset);
    /* Patch the security level. */
    packet.control &= ~ZBEE_SEC_CONTROL_LEVEL;
    packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level);
    /*
     * Eww, I think I just threw up a little...  ZigBee requires this field
     * to be patched before computing the MIC, but we don't have write-access
     * to the tvbuff. So we need to allocate a copy of the whole thing just
     * so we can fix these 3 bits.
     */
#ifdef HAVE_LIBGCRYPT
    enc_buffer = ep_tvb_memdup(tvb, 0, tvb_length(tvb));
    /*
     * Override the const qualifiers and patch the security level field, we
     * know it is safe to overide the const qualifiers because we just
     * allocated this memory via ep_tvb_memdup().
     */
    ((guint8 *)(enc_buffer))[offset] = packet.control;
#endif /* HAVE_LIBGCRYPT */
    packet.level    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL);
    packet.key      = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
    packet.nonce    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE);
    if (tree) {
        ti = proto_tree_add_text(sec_tree, tvb, offset, sizeof(guint8), "Security Control Field");
        field_tree = proto_item_add_subtree(ti, ett_zbee_sec_control);

        proto_tree_add_uint(field_tree, hf_zbee_sec_key, tvb, offset, sizeof(guint8), packet.control & ZBEE_SEC_CONTROL_KEY);
        proto_tree_add_boolean(field_tree, hf_zbee_sec_nonce, tvb, offset, sizeof(guint8), packet.control & ZBEE_SEC_CONTROL_NONCE);
    }
    offset += sizeof(guint8);

    /* Get and display the frame counter field. */
    packet.counter = tvb_get_letohl(tvb, offset);
    if (tree) {
        proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, sizeof(guint32), packet.counter);
    }
    offset += sizeof(guint32);

    if (packet.nonce) {
        /* Get and display the source address. */
        packet.src = tvb_get_letoh64(tvb, offset);
        if (tree) {
            proto_tree_add_eui64(sec_tree, hf_zbee_sec_src, tvb, offset, sizeof(guint64), packet.src);
        }
        offset += sizeof(guint64);
    }
    else {
        /* This field is required in the security decryption process, so
         * fill it in in case the higher layer provided it.
         */
        packet.src = src;
    }

    if (packet.key == ZBEE_SEC_KEY_NWK) {
        /* Get and display the key sequence number. */
        packet.key_seqno = tvb_get_guint8(tvb, offset);
        if (tree) {
            proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, sizeof(guint8), packet.key_seqno);
        }
        offset += sizeof(guint8);
    }

    /* Determine the length of the MIC. */
    switch (packet.level){
        case ZBEE_SEC_ENC:
        case ZBEE_SEC_NONE:
        default:
            mic_len=0;
            break;

        case ZBEE_SEC_ENC_MIC32:
        case ZBEE_SEC_MIC32:
            mic_len=4;
            break;

        case ZBEE_SEC_ENC_MIC64:
        case ZBEE_SEC_MIC64:
            mic_len=8;
            break;

        case ZBEE_SEC_ENC_MIC128:
        case ZBEE_SEC_MIC128:
            mic_len=16;
            break;
    } /* switch */

    /* Ensure that the payload exists (length >= 1) for this length. */
    payload_len = tvb_ensure_length_remaining(tvb, offset+mic_len+1)+1;

    /* Get and display the MIC. */
    if (mic_len) {
        /* Display the MIC. */
        if (tree) {
            ti = proto_tree_add_bytes(sec_tree, hf_zbee_sec_mic, tvb, tvb_length(tvb)-mic_len, mic_len, ep_tvb_memdup(tvb, tvb_length(tvb)-mic_len, mic_len));
        }
    }

    /**********************************************
     *  Perform Security Operations on the Frame  *
     **********************************************
     */
    if ((packet.level == ZBEE_SEC_NONE) ||
        (packet.level == ZBEE_SEC_MIC32) ||
        (packet.level == ZBEE_SEC_MIC64) ||
        (packet.level == ZBEE_SEC_MIC128)) {
        /* Payload is only integrity protected. Just return the sub-tvbuff. */
        return tvb_new_subset(tvb, offset, payload_len, payload_len);
    }

#ifdef HAVE_LIBGCRYPT
    /* Ensure we have enough security material to decrypt this payload. */
    switch (packet.key) {
        /* Network Keys use the shared network key. */
        case ZBEE_SEC_KEY_NWK:
            if (!zbee_sec_have_nwk_key) {
                /* Without a key we can't decrypt (if we could what good would security be?)*/
                goto decrypt_failed;
            }
            if (packet.src == 0) {
                /* Without the extended source address, we can't create the nonce. */
                goto decrypt_failed;
            }
            /* The key, is the network key. */
            key_buffer = zbee_sec_nwk_key;
            break;

        /* Link Key might use the trust center link key. */
        case ZBEE_SEC_KEY_LINK:
            if (!zbee_sec_have_tclink_key) {
                /* Without a key we can't decrypt. */
                goto decrypt_failed;
            }
            if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){
                /* Without the extended source address, we can't create the nonce. */
                goto decrypt_failed;
            }
            else if (packet.src == 0) {
                packet.src = zbee_sec_tcaddr;
            }
            key_buffer = zbee_sec_tclink_key;
            break;

        /* Key-Transport Key should use the trust center link key. */
        case ZBEE_SEC_KEY_TRANSPORT:
            if (!zbee_sec_have_tclink_key) {
                /* Without a key we can't decrypt. */
                goto decrypt_failed;
            }
            if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){
                /* Without the extended source address, we can't create the nonce. */
                goto decrypt_failed;
            }
            else if (packet.src == 0) {
                packet.src = zbee_sec_tcaddr;
            }
            key_buffer = zbee_sec_key_hash(zbee_sec_tclink_key, 0x00, pinfo);
            break;

        /* Key-Load Key should use the trust center link key. */
        case ZBEE_SEC_KEY_LOAD:
            if (!zbee_sec_have_tclink_key) {
                /* Without a key we can't decrypt. */
                goto decrypt_failed;
            }
            if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){
                /* Without the extended source address, we can't create the nonce. */
                goto decrypt_failed;
            }
            else if (packet.src == 0) {
                packet.src = zbee_sec_tcaddr;
            }
            key_buffer = zbee_sec_key_hash(zbee_sec_tclink_key, 0x02, pinfo);
            break;

        default:
            goto decrypt_failed;
    } /* switch */

    /* Create the nonce. */
    zbee_sec_make_nonce(nonce, &packet);
    /* Allocate memory to decrypt the payload into. */
    dec_buffer = g_malloc(payload_len);
    /* Perform Decryption. */
    if (!zbee_sec_ccm_decrypt(key_buffer, /* key */
                nonce,              /* Nonce */
                enc_buffer,         /* a, length l(a) */
                enc_buffer+offset,  /* c, length l(c) = l(m) + M */
                dec_buffer,         /* m, length l(m) */
                offset,             /* l(a) */
                payload_len,        /* l(m) */
                mic_len)) {         /* M */
        /* Decryption Failed! */
        g_free(dec_buffer);
        goto decrypt_failed;
    }

    /* Setup the new tvbuff_t and return */
    payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len);
    add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload");
    /* Done! */
    return payload_tvb;

decrypt_failed:
#endif /* HAVE_LIBGCRYPT */

    /* Add expert info. */
    expert_add_info_format(pinfo, sec_tree, PI_UNDECODED, PI_WARN, "Encrypted Payload");
    /* Create a buffer for the undecrypted payload. */
    payload_tvb = tvb_new_subset(tvb, offset, payload_len, -1);
    /* Dump the payload to the data dissector. */
    call_dissector(data_handle, payload_tvb, pinfo, tree);
    /* Couldn't decrypt, so return NULL. */
    return NULL;

} /* dissect_zbee_secure */
static int
dissect_netmon_802_11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
  struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
  proto_tree *wlan_tree = NULL, *opmode_tree;
  proto_item *ti;
  tvbuff_t   *next_tvb;
  int         offset;
  guint8      version;
  guint16     length;
  guint32     phy_type;
  guint32     flags;
  guint32     channel;
  gint        calc_channel;
  gint32      rssi;
  guint8      rate;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
  col_clear(pinfo->cinfo, COL_INFO);
  offset = 0;

  version = tvb_get_guint8(tvb, offset);
  length = tvb_get_letohs(tvb, offset+1);
  col_add_fstr(pinfo->cinfo, COL_INFO, "NetMon WLAN Capture v%u, Length %u",
               version, length);
  if (version != 2) {
    /* XXX - complain */
    goto skip;
  }
  if (length < MIN_HEADER_LEN) {
    /* XXX - complain */
    goto skip;
  }

  /* Dissect the packet */
  ti = proto_tree_add_item(tree, proto_netmon_802_11, tvb, 0, length,
                           ENC_NA);
  wlan_tree = proto_item_add_subtree(ti, ett_netmon_802_11);

  /*
   * XXX - is this the NDIS_OBJECT_HEADER structure:
   *
   *    https://msdn.microsoft.com/en-us/library/windows/hardware/ff566588(v=vs.85).aspx
   *
   * at the beginning of a DOT11_EXTSTA_RECV_CONTEXT structure:
   *
   *    https://msdn.microsoft.com/en-us/library/windows/hardware/ff548626(v=vs.85).aspx
   *
   * If so, the byte at an offset of 0 would be the appropriate type for the
   * structure following it, i.e. NDIS_OBJECT_TYPE_DEFAULT.
   */
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_version, tvb, offset, 1,
                      ENC_LITTLE_ENDIAN);
  offset += 1;
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_length, tvb, offset, 2,
                      ENC_LITTLE_ENDIAN);
  offset += 2;

  /*
   * This isn't in the DOT11_EXTSTA_RECV_CONTEXT structure.
   */
  ti = proto_tree_add_item(wlan_tree, hf_netmon_802_11_op_mode, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  opmode_tree = proto_item_add_subtree(ti, ett_netmon_802_11_op_mode);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_sta, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_ap, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_sta_ext, tvb,
                      offset, 4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_mon, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  offset += 4;

  /*
   * uReceiveFlags?
   */
  flags = tvb_get_letohl(tvb, offset);
  offset += 4;
  if (flags != 0xffffffff) {
    /*
     * uPhyId?
     */
    phy_type = tvb_get_letohl(tvb, offset);
    switch (phy_type) {

    case PHY_TYPE_UNKNOWN:
        phdr->phy = PHDR_802_11_PHY_UNKNOWN;
        break;

    case PHY_TYPE_FHSS:
        phdr->phy = PHDR_802_11_PHY_11_FHSS;
        phdr->phy_info.info_11_fhss.presence_flags = 0;
        break;

    case PHY_TYPE_IR_BASEBAND:
        phdr->phy = PHDR_802_11_PHY_11_IR;
        break;

    case PHY_TYPE_DSSS:
        phdr->phy = PHDR_802_11_PHY_11_DSSS;
        break;

    case PHY_TYPE_HR_DSSS:
        phdr->phy = PHDR_802_11_PHY_11B;
        phdr->phy_info.info_11b.presence_flags = 0;
        break;

    case PHY_TYPE_OFDM:
        phdr->phy = PHDR_802_11_PHY_11A;
        phdr->phy_info.info_11a.presence_flags = 0;
        break;

    case PHY_TYPE_ERP:
        phdr->phy = PHDR_802_11_PHY_11G;
        phdr->phy_info.info_11g.presence_flags = 0;
        break;

    case PHY_TYPE_HT:
        phdr->phy = PHDR_802_11_PHY_11N;
        phdr->phy_info.info_11n.presence_flags = 0;
        break;

    case PHY_TYPE_VHT:
        phdr->phy = PHDR_802_11_PHY_11AC;
        phdr->phy_info.info_11ac.presence_flags = 0;
        break;

    default:
        phdr->phy = PHDR_802_11_PHY_UNKNOWN;
        break;
    }
    proto_tree_add_item(wlan_tree, hf_netmon_802_11_phy_type, tvb, offset, 4,
                        ENC_LITTLE_ENDIAN);
    offset += 4;

    /*
     * uChCenterFrequency?
     */
    channel = tvb_get_letohl(tvb, offset);
    if (channel < 1000) {
      if (channel == 0) {
        proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_channel,
                                         tvb, offset, 4, channel,
                                         "Unknown");
      } else {
        guint frequency;

        phdr->presence_flags |= PHDR_802_11_HAS_CHANNEL;
        phdr->channel = channel;
        proto_tree_add_uint(wlan_tree, hf_netmon_802_11_channel,
                            tvb, offset, 4, channel);
        switch (phdr->phy) {

        case PHDR_802_11_PHY_11B:
        case PHDR_802_11_PHY_11G:
          /* 2.4 GHz channel */
          frequency = ieee80211_chan_to_mhz(channel, TRUE);
          break;

        case PHDR_802_11_PHY_11A:
          /* 5 GHz channel */
          frequency = ieee80211_chan_to_mhz(channel, FALSE);
          break;

        default:
          frequency = 0;
          break;
        }
        if (frequency != 0) {
          phdr->presence_flags |= PHDR_802_11_HAS_FREQUENCY;
          phdr->frequency = frequency;
        }
      }
    } else {
      phdr->presence_flags |= PHDR_802_11_HAS_FREQUENCY;
      phdr->frequency = channel;
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_frequency,
                                       tvb, offset, 4, channel,
                                       "%u Mhz", channel);
      calc_channel = ieee80211_mhz_to_chan(channel);
      if (calc_channel != -1) {
        phdr->presence_flags |= PHDR_802_11_HAS_CHANNEL;
        phdr->channel = calc_channel;
      }
    }
    offset += 4;

    /*
     * usNumberOfMPDUsReceived is missing.
     */

    /*
     * lRSSI?
     */
    rssi = tvb_get_letohl(tvb, offset);
    if (rssi == 0) {
      proto_tree_add_int_format_value(wlan_tree, hf_netmon_802_11_rssi,
                                      tvb, offset, 4, rssi,
                                      "Unknown");
    } else {
      phdr->presence_flags |= PHDR_802_11_HAS_SIGNAL_DBM;
      phdr->signal_dbm = rssi;
      proto_tree_add_int_format_value(wlan_tree, hf_netmon_802_11_rssi,
                                      tvb, offset, 4, rssi,
                                      "%d dBm", rssi);
    }
    offset += 4;

    /*
     * ucDataRate?
     */
    rate = tvb_get_guint8(tvb, offset);
    if (rate == 0) {
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_datarate,
                                       tvb, offset, 1, rate,
                                       "Unknown");
    } else {
      phdr->presence_flags |= PHDR_802_11_HAS_DATA_RATE;
      phdr->data_rate = rate;
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_datarate,
                                       tvb, offset, 1, rate,
                                       "%f Mb/s", rate*.5);
    }
    offset += 1;
  } else
    offset += 13;

  /*
   * ullTimestamp?
   *
   * If so, should this check the presense flag in flags?
   */
  phdr->presence_flags |= PHDR_802_11_HAS_TSF_TIMESTAMP;
  phdr->tsf_timestamp = tvb_get_letoh64(tvb, offset);
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_timestamp, tvb, offset, 8,
                      ENC_LITTLE_ENDIAN);
  /*offset += 8;*/

skip:
  offset = length;

  /* dissect the 802.11 packet next */
  next_tvb = tvb_new_subset_remaining(tvb, offset);
  call_dissector_with_data(ieee80211_radio_handle, next_tvb, pinfo, tree, phdr);
  return offset;
}
Exemplo n.º 14
0
static int
dissect_yami_parameter(tvbuff_t *tvb, proto_tree *tree, int offset, proto_item *par_ti)
{
	const int orig_offset = offset;

	proto_tree *yami_param;
	proto_item *ti;

	char *name;
	int name_offset;
	guint32 name_len;

	guint32 type;

	ti = proto_tree_add_item(tree, hf_yami_param, tvb, offset, 0, ENC_NA);
	yami_param = proto_item_add_subtree(ti, ett_yami_param);

	name_offset = offset;
	name_len = tvb_get_letohl(tvb, offset);
	offset += 4;

	name = tvb_get_ephemeral_string_enc(tvb, offset, name_len, ENC_ASCII | ENC_NA);
	proto_item_append_text(ti, ": %s", name);
	proto_item_append_text(par_ti, "%s, ", name);
	offset += (name_len + 3) & ~3;
	proto_tree_add_string(yami_param, hf_yami_param_name, tvb, name_offset, offset - name_offset, name);

	type = tvb_get_letohl(tvb, offset);
	proto_tree_add_item(yami_param, hf_yami_param_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
	offset += 4;

	switch (type) {
		case YAMI_TYPE_BOOLEAN:
		{
			guint32 val = tvb_get_letohl(tvb, offset);
			proto_item_append_text(ti, ", Type: boolean, Value: %s", val ? "True" : "False");
			proto_tree_add_item(yami_param, hf_yami_param_value_bool, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;
			break;
		}

		case YAMI_TYPE_INTEGER:
		{
			gint32 val = tvb_get_letohl(tvb, offset);
			proto_item_append_text(ti, ", Type: integer, Value: %d", val);
			proto_tree_add_item(yami_param, hf_yami_param_value_int, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;
			break;
		}

		case YAMI_TYPE_LONGLONG:
		{
			gint64 val = tvb_get_letoh64(tvb, offset);
			proto_item_append_text(ti, ", Type: long, Value: %" G_GINT64_MODIFIER "d", val);
			proto_tree_add_item(yami_param, hf_yami_param_value_long, tvb, offset, 8, ENC_LITTLE_ENDIAN);
			offset += 8;
			break;
		}

		case YAMI_TYPE_DOUBLE:
		{
			gdouble val = tvb_get_letohieee_double(tvb, offset);
			proto_item_append_text(ti, ", Type: double, Value: %g", val);
			proto_tree_add_item(yami_param, hf_yami_param_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN);
			offset += 8;
			break;
		}

		case YAMI_TYPE_STRING:
		{
			const int val_offset = offset;
			guint32 val_len;
			char *val;

			val_len = tvb_get_letohl(tvb, offset);
			offset += 4;

			val = tvb_get_ephemeral_string_enc(tvb, offset, val_len, ENC_ASCII | ENC_NA);

			proto_item_append_text(ti, ", Type: string, Value: \"%s\"", val);
			offset += (val_len + 3) & ~3;
			proto_tree_add_string(yami_param, hf_yami_param_value_str, tvb, val_offset, offset - val_offset, val);
			break;
		}

		case YAMI_TYPE_BINARY:
		{
			const int val_offset = offset;
			guint32 val_len;
			const guint8 *val;
			char *repr;

			val_len = tvb_get_letohl(tvb, offset);
			offset += 4;

			val = tvb_get_ptr(tvb, offset, val_len);
			repr = bytes_to_str(val, val_len);

			proto_item_append_text(ti, ", Type: binary, Value: %s", repr);
			offset += (val_len + 3) & ~3;
			proto_tree_add_bytes_format_value(yami_param, hf_yami_param_value_bin, tvb, val_offset, offset - val_offset, val, "%s", repr);
			break;
		}

		case YAMI_TYPE_BOOLEAN_ARRAY:
		{
			guint32 count;
			guint i;
			int j;

			count = tvb_get_letohl(tvb, offset);
			proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;

			proto_item_append_text(ti, ", Type: boolean[], %u items: {", count);

			for (i = 0; i < count/32; i++) {
				guint32 val = tvb_get_letohl(tvb, offset);

				for (j = 0; j < 32; j++) {
					int r = !!(val & (1 << j));

					proto_item_append_text(ti, "%s, ", r ? "T" : "F");
					proto_tree_add_boolean(yami_param, hf_yami_param_value_bool, tvb, offset+(j/8), 1, r);
				}
				offset += 4;
			}

			if (count % 32) {
				guint32 val = tvb_get_letohl(tvb, offset);
				int tmp = count % 32;

				for (j = 0; j < tmp; j++) {
					int r = !!(val & (1 << j));

					proto_item_append_text(ti, "%s, ", r ? "T" : "F");
					proto_tree_add_boolean(yami_param, hf_yami_param_value_bool, tvb, offset+(j/8), 1, r);
				}
				offset += 4;
			}

			proto_item_append_text(ti, "}");
			break;
		}

		case YAMI_TYPE_INTEGER_ARRAY:
		{
			guint32 count;
			guint i;

			count = tvb_get_letohl(tvb, offset);
			proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;

			proto_item_append_text(ti, ", Type: integer[], %u items: {", count);
			for (i = 0; i < count; i++) {
				gint32 val = tvb_get_letohl(tvb, offset);

				proto_item_append_text(ti, "%d, ", val);
				proto_tree_add_item(yami_param, hf_yami_param_value_int, tvb, offset, 4, ENC_LITTLE_ENDIAN);
				offset += 4;
			}
			proto_item_append_text(ti, "}");
			break;
		}

		case YAMI_TYPE_LONGLONG_ARRAY:
		{
			guint32 count;
			guint i;

			count = tvb_get_letohl(tvb, offset);
			proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;

			proto_item_append_text(ti, ", Type: long long[], %u items: {", count);

			for (i = 0; i < count; i++) {
				gint64 val = tvb_get_letoh64(tvb, offset);

				proto_item_append_text(ti, "%" G_GINT64_MODIFIER "d, ", val);
				proto_tree_add_item(yami_param, hf_yami_param_value_long, tvb, offset, 8, ENC_LITTLE_ENDIAN);
				offset += 8;
			}
			proto_item_append_text(ti, "}");
			break;
		}

		case YAMI_TYPE_DOUBLE_ARRAY:
		{
			guint32 count;
			guint i;

			count = tvb_get_letohl(tvb, offset);
			proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;

			proto_item_append_text(ti, ", Type: double[], %u items: {", count);

			for (i = 0; i < count; i++) {
				gdouble val = tvb_get_letohieee_double(tvb, offset);

				proto_item_append_text(ti, "%g, ", val);
				proto_tree_add_item(yami_param, hf_yami_param_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN);
				offset += 8;
			}
			proto_item_append_text(ti, "}");
			break;
		}

		case YAMI_TYPE_STRING_ARRAY:
		{
			guint32 count;
			guint i;

			count = tvb_get_letohl(tvb, offset);
			proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;

			proto_item_append_text(ti, ", Type: string[], %u items: {", count);

			for (i = 0; i < count; i++) {
				const int val_offset = offset;
				guint32 val_len;
				char *val;

				val_len = tvb_get_letohl(tvb, offset);
				offset += 4;

				val = tvb_get_ephemeral_string_enc(tvb, offset, val_len, ENC_ASCII | ENC_NA);

				proto_item_append_text(ti, "\"%s\", ", val);
				proto_tree_add_string(yami_param, hf_yami_param_value_str, tvb, val_offset, offset - val_offset, val);
				offset += (val_len + 3) & ~3;
			}
			proto_item_append_text(ti, "}");
			break;
		}

		case YAMI_TYPE_BINARY_ARRAY:
		{
			guint32 count;
			guint i;

			count = tvb_get_letohl(tvb, offset);
			proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;

			proto_item_append_text(ti, ", Type: binary[], %u items: {", count);

			for (i = 0; i < count; i++) {
				const int val_offset = offset;
				guint32 val_len;
				const guint8 *val;
				char *repr;

				val_len = tvb_get_letohl(tvb, offset);
				offset += 4;

				val = tvb_get_ptr(tvb, offset, val_len);
				repr = bytes_to_str(val, val_len);

				proto_item_append_text(ti, "%s, ", repr);
				offset += (val_len + 3) & ~3;
				proto_tree_add_bytes_format_value(yami_param, hf_yami_param_value_bin, tvb, val_offset, offset - val_offset, val, "%s", repr);
			}
			proto_item_append_text(ti, "}");
			break;
		}

		case YAMI_TYPE_NESTED:
		{
			guint32 count;
			guint i;

			count = tvb_get_letohl(tvb, offset);
			proto_tree_add_item(yami_param, hf_yami_params_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
			offset += 4;

			proto_item_append_text(ti, ", Type: nested, %u parameters: ", count);

			for (i = 0; i < count; i++) {
				offset = dissect_yami_parameter(tvb, yami_param, offset, ti);
				/* smth went wrong */
				if (offset == -1)
					return -1;
			}
			break;
		}

		default:
			proto_item_append_text(ti, ", Type: unknown (%d)!", type);
			return -1;
	}

	proto_item_set_len(ti, offset - orig_offset);
	return offset;
}
static int
dissect_netmon_802_11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
  struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
  proto_tree *wlan_tree = NULL, *opmode_tree;
  proto_item *ti;
  tvbuff_t   *next_tvb;
  int         offset;
  guint8      version;
  guint16     length;
  guint32     phy_type;
  guint32     flags;
  guint32     channel;
  gint        calc_channel;
  gint32      rssi;
  guint8      rate;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
  col_clear(pinfo->cinfo, COL_INFO);
  offset = 0;

  version = tvb_get_guint8(tvb, offset);
  length = tvb_get_letohs(tvb, offset+1);
  col_add_fstr(pinfo->cinfo, COL_INFO, "NetMon WLAN Capture v%u, Length %u",
               version, length);
  if (version != 2) {
    /* XXX - complain */
    goto skip;
  }
  if (length < MIN_HEADER_LEN) {
    /* XXX - complain */
    goto skip;
  }

  /* Dissect the packet */
  ti = proto_tree_add_item(tree, proto_netmon_802_11, tvb, 0, length,
                           ENC_NA);
  wlan_tree = proto_item_add_subtree(ti, ett_netmon_802_11);
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_version, tvb, offset, 1,
                      ENC_LITTLE_ENDIAN);
  offset += 1;
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_length, tvb, offset, 2,
                      ENC_LITTLE_ENDIAN);
  offset += 2;
  ti = proto_tree_add_item(wlan_tree, hf_netmon_802_11_op_mode, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  opmode_tree = proto_item_add_subtree(ti, ett_netmon_802_11_op_mode);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_sta, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_ap, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_sta_ext, tvb,
                      offset, 4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_mon, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  offset += 4;
  flags = tvb_get_letohl(tvb, offset);
  offset += 4;
  if (flags != 0xffffffff) {
    phy_type = tvb_get_letohl(tvb, offset);
    switch (phy_type) {

    case PHY_TYPE_11B:
        phdr->phy = PHDR_802_11_PHY_11B;
        break;

    case PHY_TYPE_11A:
        phdr->phy = PHDR_802_11_PHY_11A;
        phdr->phy_info.info_11a.presence_flags = 0;
        break;

    case PHY_TYPE_11G:
        phdr->phy = PHDR_802_11_PHY_11G;
        phdr->phy_info.info_11g.presence_flags = 0;
        break;

    case PHY_TYPE_11N:
        phdr->phy = PHDR_802_11_PHY_11N;
        phdr->phy_info.info_11n.presence_flags = 0;
        break;

    default:
        phdr->phy = PHDR_802_11_PHY_UNKNOWN;
        break;
    }
    proto_tree_add_item(wlan_tree, hf_netmon_802_11_phy_type, tvb, offset, 4,
                        ENC_LITTLE_ENDIAN);
    offset += 4;
    channel = tvb_get_letohl(tvb, offset);
    if (channel < 1000) {
      if (channel == 0) {
        proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_channel,
                                         tvb, offset, 4, channel,
                                         "Unknown");
      } else {
        guint frequency;

        phdr->presence_flags |= PHDR_802_11_HAS_CHANNEL;
        phdr->channel = channel;
        proto_tree_add_uint(wlan_tree, hf_netmon_802_11_channel,
                            tvb, offset, 4, channel);
        switch (phdr->phy) {

        case PHDR_802_11_PHY_11B:
        case PHDR_802_11_PHY_11G:
          /* 2.4 GHz channel */
          frequency = ieee80211_chan_to_mhz(channel, TRUE);
          break;

        case PHDR_802_11_PHY_11A:
          /* 5 GHz channel */
          frequency = ieee80211_chan_to_mhz(channel, FALSE);
          break;

        default:
          frequency = 0;
          break;
        }
        if (frequency != 0) {
          phdr->presence_flags |= PHDR_802_11_HAS_FREQUENCY;
          phdr->frequency = frequency;
        }
      }
    } else {
      phdr->presence_flags |= PHDR_802_11_HAS_FREQUENCY;
      phdr->frequency = channel;
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_frequency,
                                       tvb, offset, 4, channel,
                                       "%u Mhz", channel);
      calc_channel = ieee80211_mhz_to_chan(channel);
      if (calc_channel != -1) {
        phdr->presence_flags |= PHDR_802_11_HAS_CHANNEL;
        phdr->channel = calc_channel;
      }
    }
    offset += 4;
    rssi = tvb_get_letohl(tvb, offset);
    if (rssi == 0) {
      proto_tree_add_int_format_value(wlan_tree, hf_netmon_802_11_rssi,
                                      tvb, offset, 4, rssi,
                                      "Unknown");
    } else {
      phdr->presence_flags |= PHDR_802_11_HAS_SIGNAL_DBM;
      phdr->signal_dbm = rssi;
      proto_tree_add_int_format_value(wlan_tree, hf_netmon_802_11_rssi,
                                      tvb, offset, 4, rssi,
                                      "%d dBm", rssi);
    }
    offset += 4;
    rate = tvb_get_guint8(tvb, offset);
    if (rate == 0) {
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_datarate,
                                       tvb, offset, 1, rate,
                                       "Unknown");
    } else {
      phdr->presence_flags |= PHDR_802_11_HAS_DATA_RATE;
      phdr->data_rate = rate;
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_datarate,
                                       tvb, offset, 1, rate,
                                       "%f Mb/s", rate*.5);
    }
    offset += 1;
  } else
    offset += 13;
  phdr->presence_flags |= PHDR_802_11_HAS_TSF_TIMESTAMP;
  phdr->tsf_timestamp = tvb_get_letoh64(tvb, offset);
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_timestamp, tvb, offset, 8,
                      ENC_LITTLE_ENDIAN);
  /*offset += 8;*/

skip:
  offset = length;

  /* dissect the 802.11 packet next */
  next_tvb = tvb_new_subset_remaining(tvb, offset);
  call_dissector_with_data(ieee80211_radio_handle, next_tvb, pinfo, tree, phdr);
  return offset;
}
Exemplo n.º 16
0
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      dissect_zbee_secure
 *  DESCRIPTION
 *      Dissects and decrypts secured ZigBee frames.
 *
 *      Will return a valid tvbuff only if security processing was
 *      successful. If processing fails, then this function will
 *      handle internally and return NULL.
 *  PARAMETERS
 *      tvbuff_t    *tvb    - pointer to buffer containing raw packet.
 *      packet_info *pinfo  - pointer to packet information fields
 *      proto_tree  *tree   - pointer to data tree Wireshark uses to display packet.
 *      guint       offset  - pointer to the start of the auxilliary security header.
 *      guint64     src64   - extended source address, or 0 if unknown.
 *  RETURNS
 *      tvbuff_t *
 *---------------------------------------------------------------
 */
tvbuff_t *
dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset)
{
    proto_tree     *sec_tree = NULL;
    proto_item     *sec_root;
    proto_tree     *field_tree;
    proto_item     *ti;

    zbee_security_packet    packet;
    guint           mic_len;
    gint            payload_len;
    tvbuff_t       *payload_tvb;

#ifdef HAVE_LIBGCRYPT
    guint8             *enc_buffer;
    guint8             *dec_buffer;
    gboolean            decrypted;
    GSList            **nwk_keyring;
    GSList             *GSList_i;
    key_record_t       *key_rec = NULL;
#endif
    zbee_nwk_hints_t   *nwk_hints;
    ieee802154_hints_t *ieee_hints;
    ieee802154_map_rec *map_rec = NULL;

    /* Init */
    memset(&packet, 0, sizeof(zbee_security_packet));

    /* Get pointers to any useful frame data from lower layers */
    nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK));
    ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd,
    proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN));

    /* Create a subtree for the security information. */
    if (tree) {
        sec_root = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ZigBee Security Header");
        sec_tree = proto_item_add_subtree(sec_root, ett_zbee_sec);
    }

    /*  Get and display the Security control field */
    packet.control  = tvb_get_guint8(tvb, offset);

    /* Patch the security level. */
    packet.control &= ~ZBEE_SEC_CONTROL_LEVEL;
    packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level);

    /*
     * Eww, I think I just threw up a little...  ZigBee requires this field
     * to be patched before computing the MIC, but we don't have write-access
     * to the tvbuff. So we need to allocate a copy of the whole thing just
     * so we can fix these 3 bits. Memory allocated by ep_tvb_memdup() is
     * automatically freed before the next packet is processed.
     */
#ifdef HAVE_LIBGCRYPT
    enc_buffer = (guint8 *)ep_tvb_memdup(tvb, 0, tvb_length(tvb));
    /*
     * Override the const qualifiers and patch the security level field, we
     * know it is safe to overide the const qualifiers because we just
     * allocated this memory via ep_tvb_memdup().
     */
    enc_buffer[offset] = packet.control;
#endif /* HAVE_LIBGCRYPT */
    packet.level    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL);
    packet.key_id   = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
    packet.nonce    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE);
    if (tree) {
        ti = proto_tree_add_text(sec_tree, tvb, offset, 1, "Security Control Field");
        field_tree = proto_item_add_subtree(ti, ett_zbee_sec_control);

        proto_tree_add_uint(field_tree, hf_zbee_sec_key_id, tvb, offset, 1,
                                packet.control & ZBEE_SEC_CONTROL_KEY);
        proto_tree_add_boolean(field_tree, hf_zbee_sec_nonce, tvb, offset, 1,
                                packet.control & ZBEE_SEC_CONTROL_NONCE);
    }
    offset += 1;

    /* Get and display the frame counter field. */
    packet.counter = tvb_get_letohl(tvb, offset);
    if (tree) {
        proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, 4, packet.counter);
    }
    offset += 4;

    if (packet.nonce) {
        /* Get and display the source address of the device that secured this payload. */
        packet.src64 = tvb_get_letoh64(tvb, offset);
        if (tree) {
            proto_tree_add_item(sec_tree, hf_zbee_sec_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
        }
#if 1
        if (!pinfo->fd->flags.visited) {
            switch ( packet.key_id ) {
                case ZBEE_SEC_KEY_LINK:
                if (nwk_hints) {
                    /* Map this long address with the nwk layer short address. */
                    nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src,
                            ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
                }
                break;

                case ZBEE_SEC_KEY_NWK:
                if (ieee_hints) {
                    /* Map this long address with the ieee short address. */
                    ieee_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, ieee_hints->src16,
                        ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
                }
                break;

                /* We ignore the extended source addresses used to encrypt payloads with these
                 * types of keys, because they can emerge from APS tunnels created by nodes whose
                 * short address is not recorded in the packet. */
                case ZBEE_SEC_KEY_TRANSPORT:
                case ZBEE_SEC_KEY_LOAD:
                break;
            }
        }
#endif
        offset += 8;
    }
    else {
        /* Look for a source address in hints */
        switch ( packet.key_id ) {
            case ZBEE_SEC_KEY_NWK:
                /* use the ieee extended source address for NWK decryption */
                if ( ieee_hints && (map_rec = ieee_hints->map_rec) ) packet.src64 = map_rec->addr64;
                else if (tree) proto_tree_add_text(sec_tree, tvb, 0, 0, "[Extended Source: Unknown]");
                break;

            default:
                /* use the nwk extended source address for APS decryption */
                if ( nwk_hints && (map_rec = nwk_hints->map_rec) ) packet.src64 = map_rec->addr64;
                else if (tree) proto_tree_add_text(sec_tree, tvb, 0, 0, "[Extended Source: Unknown]");
                break;
        }
    }

    if (packet.key_id == ZBEE_SEC_KEY_NWK) {
        /* Get and display the key sequence number. */
        packet.key_seqno = tvb_get_guint8(tvb, offset);
        if (tree) {
            proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, 1, packet.key_seqno);
        }
        offset += 1;
    }

    /* Determine the length of the MIC. */
    switch (packet.level) {
        case ZBEE_SEC_ENC:
        case ZBEE_SEC_NONE:
        default:
            mic_len=0;
            break;

        case ZBEE_SEC_ENC_MIC32:
        case ZBEE_SEC_MIC32:
            mic_len=4;
            break;

        case ZBEE_SEC_ENC_MIC64:
        case ZBEE_SEC_MIC64:
            mic_len=8;
            break;

        case ZBEE_SEC_ENC_MIC128:
        case ZBEE_SEC_MIC128:
            mic_len=16;
            break;
    } /* switch */

    /* Get and display the MIC. */
    if (mic_len) {
        /* Display the MIC. */
        if (tree) {
            proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_length(tvb)-mic_len),
                   mic_len, ENC_NA);
        }
    }

    /* Check for null payload. */
    if ( !(payload_len = tvb_reported_length_remaining(tvb, offset+mic_len)) ) {
        return NULL;
    } else if ( payload_len < 0 ) {
        THROW(ReportedBoundsError);
    }

    /**********************************************
     *  Perform Security Operations on the Frame  *
     **********************************************
     */
    if ((packet.level == ZBEE_SEC_NONE) ||
        (packet.level == ZBEE_SEC_MIC32) ||
        (packet.level == ZBEE_SEC_MIC64) ||
        (packet.level == ZBEE_SEC_MIC128)) {

        /* Payload is only integrity protected. Just return the sub-tvbuff. */
        return tvb_new_subset(tvb, offset, payload_len, payload_len);
    }

#ifdef HAVE_LIBGCRYPT
    /* Allocate memory to decrypt the payload into. */
    dec_buffer = (guint8 *)g_malloc(payload_len);

    decrypted = FALSE;
    if ( packet.src64 ) {
        if (pinfo->fd->flags.visited) {
            if ( nwk_hints ) {
                /* Use previously found key */
                switch ( packet.key_id ) {
                    case ZBEE_SEC_KEY_NWK:
                        if ( (key_rec = nwk_hints->nwk) ) {
                            decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, nwk_hints->nwk->key);
                        }
                        break;

                    default:
                        if ( (key_rec = nwk_hints->link) ) {
                            decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, nwk_hints->link->key);
                        }
                        break;
                }
            }
        } /* ( !pinfo->fd->flags.visited ) */
        else {
            /* We only search for sniffed keys in the first pass,
             * to save time, and because decrypting with keys
             * transported in future packets is cheating */

            /* Lookup NWK and link key in hash for this pan. */
            /* This overkill approach is a placeholder for a hash that looks up
             * a key ring for a link key associated with a pair of devices.
             */
            if ( nwk_hints ) {
                nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan);

                if ( nwk_keyring ) {
                    GSList_i = *nwk_keyring;
                    while ( GSList_i && !decrypted ) {
                        decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                        if (decrypted) {
                            /* save pointer to the successful key record */
                            switch (packet.key_id) {
                                case ZBEE_SEC_KEY_NWK:
                                    key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                    break;

                                default:
                                    key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                    break;
                            }
                        } else {
                            GSList_i = g_slist_next(GSList_i);
                        }
                    }
                }

                /* Loop through user's password table for preconfigured keys, our last resort */
                GSList_i = zbee_pc_keyring;
                while ( GSList_i && !decrypted ) {
                    decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                            payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                    if (decrypted) {
                        /* save pointer to the successful key record */
                        switch (packet.key_id) {
                            case ZBEE_SEC_KEY_NWK:
                                key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                break;

                            default:
                                key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                break;
                        }
                    } else {
                        GSList_i = g_slist_next(GSList_i);
                    }
                }
            }
        } /* ( ! pinfo->fd->flags.visited ) */
    } /* ( packet.src64 ) */

    if ( decrypted ) {
        if ( tree && key_rec ) {
            if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) {
                ti = proto_tree_add_text(sec_tree, tvb, 0, 0, "Decryption Key: %s", key_rec->label);
            } else {
                ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0,
                        key_rec->frame_num);
            }
            PROTO_ITEM_SET_GENERATED(ti);
        }

        /* Found a key that worked, setup the new tvbuff_t and return */
        payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len);
        tvb_set_free_cb(payload_tvb, g_free); /* set up callback to free dec_buffer */
        add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload");

        /* Done! */
        return payload_tvb;
    }

    g_free(dec_buffer);
#endif /* HAVE_LIBGCRYPT */

    /* Add expert info. */
    expert_add_info_format(pinfo, sec_tree, PI_UNDECODED, PI_WARN, "Encrypted Payload");
    /* Create a buffer for the undecrypted payload. */
    payload_tvb = tvb_new_subset(tvb, offset, payload_len, -1);
    /* Dump the payload to the data dissector. */
    call_dissector(data_handle, payload_tvb, pinfo, tree);
    /* Couldn't decrypt, so return NULL. */
    return NULL;
} /* dissect_zbee_secure */
Exemplo n.º 17
0
    tree = proto_tree_get_parent_tree(tree);

    SnC_item = proto_tree_add_item(tree, proto_opa_snc, tvb, offset, 16, ENC_NA);
    SnC_tree = proto_item_add_subtree(SnC_item, ett_snc);

    proto_tree_add_item(SnC_tree, hf_opa_snc_portnumber, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    offset += 1;
    proto_tree_add_item(SnC_tree, hf_opa_snc_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    offset += 1;
    proto_tree_add_item(SnC_tree, hf_opa_snc_Reserved16, tvb, offset, 2, ENC_NA);
    offset += 2;
    proto_tree_add_item(SnC_tree, hf_opa_snc_Reserved32, tvb, offset, 4, ENC_NA);
    offset += 4;

    RHF_PBC = tvb_get_letoh64(tvb, offset);
    switch (Direction) {
    case 0:
        PBC_tree = proto_tree_add_subtree(SnC_tree, tvb, offset, 8, ett_sncpbc, NULL, "PBC - Per Buffer Control");
        proto_tree_add_bitmask_list(PBC_tree, tvb, offset + 4, 4, _snc_pbc_1, ENC_LITTLE_ENDIAN);
        proto_tree_add_bitmask_list(PBC_tree, tvb, offset, 4, _snc_pbc_2, ENC_LITTLE_ENDIAN);
        isBypass = (((RHF_PBC >> 28) & 1) == 1);
        break;
    case 1:
        RHF_tree = proto_tree_add_subtree(SnC_tree, tvb, offset, 8, ett_sncrhf, NULL, "RHF - Receive Header Flags");
        proto_tree_add_bitmask_list(RHF_tree, tvb, offset + 4, 4, _snc_rhf_1, ENC_LITTLE_ENDIAN);
        proto_tree_add_bitmask_list(RHF_tree, tvb, offset, 4, _snc_rhf_2, ENC_LITTLE_ENDIAN);
        isBypass = (((RHF_PBC >> 12) & 7) == 4);
        break;
    case 2:     /* For use with internal debugging tools */
        proto_tree_add_item(SnC_tree, hf_opa_snc_Reserved64, tvb, offset, 8, ENC_NA);