/* * 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; } }
/* * 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; }
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; }
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 */
/* 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); }
/*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); }
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); }
/*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; }
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; }
/*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 */
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);