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 void mate_gog_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_gog* gog, mate_gop* gop) { proto_item *gog_item; proto_tree *gog_tree; proto_tree *gog_time_tree; proto_item *gog_gops_item; proto_tree *gog_gops_tree; mate_gop* gog_gops; proto_item *gog_gop_item; proto_tree *gog_gop_tree; mate_pdu* pdu; gog_item = proto_tree_add_uint(tree,gog->cfg->hfid,tvb,0,0,gog->id); gog_tree = proto_item_add_subtree(gog_item,gog->cfg->ett); gog_attrs_tree(gog_tree,pinfo,tvb,gog); if (gog->cfg->show_times) { gog_time_tree = proto_tree_add_subtree_format(gog_tree,tvb,0,0,gog->cfg->ett_times,NULL,"%s Times",gog->cfg->name); proto_tree_add_float(gog_time_tree, gog->cfg->hfid_start_time, tvb, 0, 0, gog->start_time); proto_tree_add_float(gog_time_tree, gog->cfg->hfid_last_time, tvb, 0, 0, gog->last_time - gog->start_time); } gog_gops_item = proto_tree_add_uint(gog_tree, gog->cfg->hfid_gog_num_of_gops, tvb, 0, 0, gog->num_of_gops); gog_gops_tree = proto_item_add_subtree(gog_gops_item, gog->cfg->ett_children); for (gog_gops = gog->gops; gog_gops; gog_gops = gog_gops->next) { if (gop != gog_gops) { if (gog->cfg->gop_tree_mode == GOP_FULL_TREE) { mate_gop_tree(gog_gops_tree, pinfo, tvb, gog_gops); } else { gog_gop_item = proto_tree_add_uint(gog_gops_tree,gog_gops->cfg->hfid,tvb,0,0,gog_gops->id); if (gog->cfg->gop_tree_mode == GOP_BASIC_TREE) { gog_gop_tree = proto_item_add_subtree(gog_gop_item, gog->cfg->ett_gog_gop); proto_tree_add_float(gog_gop_tree, hf_mate_started_at, tvb,0,0,gog_gops->start_time); proto_tree_add_float_format(gog_gop_tree, hf_mate_duration, tvb,0,0, gog_gops->last_time - gog_gops->start_time, "%s Duration: %f", gog_gops->cfg->name, gog_gops->last_time - gog_gops->start_time); if (gog_gops->released) proto_tree_add_float_format(gog_gop_tree, hf_mate_released_time, tvb,0,0, gog_gops->release_time - gog_gops->start_time, "%s has been released, Time: %f", gog_gops->cfg->name, gog_gops->release_time - gog_gops->start_time); proto_tree_add_uint(gog_gop_tree, hf_mate_number_of_pdus, tvb,0,0, gog_gops->num_of_pdus); if (gop->pdus && gop->cfg->pdu_tree_mode != GOP_NO_TREE) { proto_tree_add_uint(gog_gop_tree,gog->cfg->hfid_gog_gopstart,tvb,0,0,gog_gops->pdus->frame); for (pdu = gog_gops->pdus->next ; pdu; pdu = pdu->next) { if (pdu->is_stop) { proto_tree_add_uint(gog_gop_tree,gog->cfg->hfid_gog_gopstop,tvb,0,0,pdu->frame); break; } } } } } } else { proto_tree_add_uint_format(gog_gops_tree,gop->cfg->hfid,tvb,0,0,gop->id,"current %s Gop: %d",gop->cfg->name,gop->id); } } }