static void tb80211_update_freq(void) { static unsigned int tb80211_freq_cnt; unsigned int i; gchar *str; gint32 oldfreq = 0; for (i = 0; i < tb80211_freq_cnt; i++) { gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_freq_list_box), 0); } oldfreq = tb80211_current_freq; tb80211_current_freq = -1; if (!tb80211_current_iface) return; tb80211_freq_cnt = tb80211_current_iface->frequencies->len; for (i = 0; i < tb80211_freq_cnt; i++) { int freq; freq = g_array_index(tb80211_current_iface->frequencies, int, i); str = g_strdup_printf("%d MHz (%d)", freq, ieee80211_mhz_to_chan(freq)); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_freq_list_box), str); g_free(str); if (freq == oldfreq) { gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_freq_list_box), i); tb80211_current_freq = oldfreq; } } }
/* * Get channel representation string given a Frequency */ gchar* ieee80211_mhz_to_str(guint freq){ gint chan = ieee80211_mhz_to_chan(freq); gboolean is_bg = FREQ_IS_BG(freq); if (chan < 0) { return g_strdup_printf("%u", freq); } else { return g_strdup_printf("%u [%s %u]", freq, is_bg ? "BG" : "A", chan); } }
/* * Read the packet. * * XXX - we should supply the additional radio information; * the pseudo-header should probably be supplied in a fashion * similar to the radiotap radio header, so that the 802.11 * dissector can determine which, if any, information items * are present. */ static int peektagged_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info) { peektagged_t *peektagged = (peektagged_t *)wth->priv; gboolean read_a_tag = FALSE; guint8 tag_value[6]; guint16 tag; gboolean saw_length = FALSE; guint32 length = 0; guint32 sliceLength = 0; gboolean saw_timestamp_lower = FALSE; gboolean saw_timestamp_upper = FALSE; peektagged_utime timestamp; guint32 ext_flags = 0; gboolean saw_data_rate_or_mcs_index = FALSE; guint32 data_rate_or_mcs_index = 0; gint channel; guint frequency; struct ieee_802_11_phdr ieee_802_11; guint i; int skip_len = 0; guint64 t; timestamp.upper = 0; timestamp.lower = 0; memset(&ieee_802_11, 0, sizeof ieee_802_11); ieee_802_11.fcs_len = -1; /* Unknown */ ieee_802_11.decrypted = FALSE; ieee_802_11.datapad = FALSE; ieee_802_11.phy = PHDR_802_11_PHY_UNKNOWN; /* Extract the fields from the packet header */ do { /* Get the tag and value. XXX - this assumes all values are 4 bytes long. */ if (!wtap_read_bytes_or_eof(fh, tag_value, sizeof tag_value, err, err_info)) { if (*err == 0) { /* * Short read if we've read something already; * just an EOF if we haven't. */ if (read_a_tag) *err = WTAP_ERR_SHORT_READ; } return -1; } read_a_tag = TRUE; tag = pletoh16(&tag_value[0]); switch (tag) { case TAG_PEEKTAGGED_LENGTH: if (saw_length) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("peektagged: record has two length fields"); return -1; } length = pletoh32(&tag_value[2]); saw_length = TRUE; break; case TAG_PEEKTAGGED_TIMESTAMP_LOWER: if (saw_timestamp_lower) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("peektagged: record has two timestamp-lower fields"); return -1; } timestamp.lower = pletoh32(&tag_value[2]); saw_timestamp_lower = TRUE; break; case TAG_PEEKTAGGED_TIMESTAMP_UPPER: if (saw_timestamp_upper) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("peektagged: record has two timestamp-upper fields"); return -1; } timestamp.upper = pletoh32(&tag_value[2]); saw_timestamp_upper = TRUE; break; case TAG_PEEKTAGGED_FLAGS_AND_STATUS: /* XXX - not used yet */ break; case TAG_PEEKTAGGED_CHANNEL: ieee_802_11.has_channel = TRUE; ieee_802_11.channel = pletoh32(&tag_value[2]); break; case TAG_PEEKTAGGED_DATA_RATE_OR_MCS_INDEX: data_rate_or_mcs_index = pletoh32(&tag_value[2]); saw_data_rate_or_mcs_index = TRUE; break; case TAG_PEEKTAGGED_SIGNAL_PERC: ieee_802_11.has_signal_percent = TRUE; ieee_802_11.signal_percent = pletoh32(&tag_value[2]); break; case TAG_PEEKTAGGED_SIGNAL_DBM: ieee_802_11.has_signal_dbm = TRUE; ieee_802_11.signal_dbm = pletoh32(&tag_value[2]); break; case TAG_PEEKTAGGED_NOISE_PERC: ieee_802_11.has_noise_percent = TRUE; ieee_802_11.noise_percent = pletoh32(&tag_value[2]); break; case TAG_PEEKTAGGED_NOISE_DBM: ieee_802_11.has_noise_dbm = TRUE; ieee_802_11.noise_dbm = pletoh32(&tag_value[2]); break; case TAG_PEEKTAGGED_UNKNOWN_0x000A: /* * XXX - seen in some 802.11 captures. * Always seems to have the value 0 or 5. */ break; case TAG_PEEKTAGGED_CENTER_FREQUENCY: /* XXX - also seen in an EtherPeek capture; value unknown */ ieee_802_11.has_frequency = TRUE; ieee_802_11.frequency = pletoh32(&tag_value[2]); break; case TAG_PEEKTAGGED_UNKNOWN_0x000E: /* * XXX - seen in some 802.11 captures. * Usually has the value 4, but, in some packets, has the * values 6 or 302. * * Is this the mysterious "band" field that shows up in * some "Peek remote" protocol captures, with values in * the 30x or 40x ranges? It's not always associated * with the "extended flags" tag for HT/VHT information, * so it's probably not 11n/11ac-specific. Values other * than 4 appear, in my captures, only in packets with * the "extended flags" tag. 302 appeared in a packet * with EXT_FLAG_MCS_INDEX_USED; 6 appeared in packets * without EXT_FLAG_MCS_INDEX_USED. */ break; case TAG_PEEKTAGGED_UNKNOWN_0x000F: /* * XXX - seen in some 802.11 captures; dB or dBm value? * Multiple antennas? */ break; case TAG_PEEKTAGGED_UNKNOWN_0x0010: /* * XXX - seen in some 802.11 captures; dB or dBm value? * Multiple antennas? */ break; case TAG_PEEKTAGGED_UNKNOWN_0x0011: /* * XXX - seen in some 802.11 captures; dB or dBm value? * Multiple antennas? */ break; case TAG_PEEKTAGGED_UNKNOWN_0x0012: /* * XXX - seen in some 802.11 captures; dB or dBm value? * Multiple antennas? */ break; case TAG_PEEKTAGGED_UNKNOWN_0x0013: /* * XXX - seen in some 802.11 captures; dB or dBm value? * Multiple antennas? */ break; case TAG_PEEKTAGGED_UNKNOWN_0x0014: /* * XXX - seen in some 802.11 captures; dB or dBm value? * Multiple antennas? */ break; case TAG_PEEKTAGGED_EXT_FLAGS: /* * We assume this is present for HT and VHT frames and absent * for other frames. */ ext_flags = pletoh32(&tag_value[2]); if (ext_flags & EXT_FLAG_802_11ac) { ieee_802_11.phy = PHDR_802_11_PHY_11AC; /* * XXX - this probably has only one user, so only * one MCS index and only one NSS, but where's the * NSS? */ for (i = 0; i < 4; i++) ieee_802_11.phy_info.info_11ac.nss[i] = 0; switch (ext_flags & EXT_FLAGS_GI) { case EXT_FLAG_HALF_GI: ieee_802_11.phy_info.info_11ac.has_short_gi = TRUE; ieee_802_11.phy_info.info_11ac.short_gi = 1; break; case EXT_FLAG_FULL_GI: ieee_802_11.phy_info.info_11ac.has_short_gi = TRUE; ieee_802_11.phy_info.info_11ac.short_gi = 0; break; default: /* Mutually exclusive flags set or nothing set */ break; } } else { ieee_802_11.phy = PHDR_802_11_PHY_11N; switch (ext_flags & EXT_FLAGS_BANDWIDTH) { case 0: ieee_802_11.phy_info.info_11n.has_bandwidth = TRUE; ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_MHZ; break; case EXT_FLAG_20_MHZ_LOWER: ieee_802_11.phy_info.info_11n.has_bandwidth = TRUE; ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_20L; break; case EXT_FLAG_20_MHZ_UPPER: ieee_802_11.phy_info.info_11n.has_bandwidth = TRUE; ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_20U; break; case EXT_FLAG_40_MHZ: ieee_802_11.phy_info.info_11n.has_bandwidth = TRUE; ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_40_MHZ; break; default: /* Mutually exclusive flags set */ break; } switch (ext_flags & EXT_FLAGS_GI) { case EXT_FLAG_HALF_GI: ieee_802_11.phy_info.info_11n.has_short_gi = TRUE; ieee_802_11.phy_info.info_11n.short_gi = 1; break; case EXT_FLAG_FULL_GI: ieee_802_11.phy_info.info_11n.has_short_gi = TRUE; ieee_802_11.phy_info.info_11n.short_gi = 0; break; default: /* Mutually exclusive flags set or nothing set */ break; } } break; case TAG_PEEKTAGGED_SLICE_LENGTH: sliceLength = pletoh32(&tag_value[2]); break; default: break; } } while (tag != TAG_PEEKTAGGED_SLICE_LENGTH); /* last tag */ if (!saw_length) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("peektagged: record has no length field"); return -1; } if (!saw_timestamp_lower) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("peektagged: record has no timestamp-lower field"); return -1; } if (!saw_timestamp_upper) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("peektagged: record has no timestamp-upper field"); return -1; } /* * If sliceLength is 0, force it to be the actual length of the packet. */ if (sliceLength == 0) sliceLength = length; if (sliceLength > WTAP_MAX_PACKET_SIZE) { /* * Probably a corrupt capture file; don't blow up trying * to allocate space for an immensely-large packet. */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("peektagged: File has %u-byte packet, bigger than maximum of %u", sliceLength, WTAP_MAX_PACKET_SIZE); return -1; } phdr->rec_type = REC_TYPE_PACKET; phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; phdr->len = length; phdr->caplen = sliceLength; /* calculate and fill in packet time stamp */ t = (((guint64) timestamp.upper) << 32) + timestamp.lower; if (!nsfiletime_to_nstime(&phdr->ts, t)) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("peektagged: time stamp outside supported range"); return -1; } switch (wth->file_encap) { case WTAP_ENCAP_IEEE_802_11_WITH_RADIO: if (saw_data_rate_or_mcs_index) { if (ext_flags & EXT_FLAG_MCS_INDEX_USED) { /* * It's an MCS index. * * XXX - what about 11ac? */ if (!(ext_flags & EXT_FLAG_802_11ac)) { ieee_802_11.phy_info.info_11n.has_mcs_index = TRUE; ieee_802_11.phy_info.info_11n.mcs_index = data_rate_or_mcs_index; } } else { /* It's a data rate. */ ieee_802_11.has_data_rate = TRUE; ieee_802_11.data_rate = data_rate_or_mcs_index; } } if (ieee_802_11.has_frequency && !ieee_802_11.has_channel) { /* Frequency, but no channel; try to calculate the channel. */ channel = ieee80211_mhz_to_chan(ieee_802_11.frequency); if (channel != -1) { ieee_802_11.has_channel = TRUE; ieee_802_11.channel = channel; } } else if (ieee_802_11.has_channel && !ieee_802_11.has_frequency) { /* * If it's 11 legacy DHSS, 11b, or 11g, it's 2.4 GHz, * so we can calculate the frequency. * * If it's 11a, it's 5 GHz, so we can calculate the * frequency. */ switch (ieee_802_11.phy) { case PHDR_802_11_PHY_11_DSSS: case PHDR_802_11_PHY_11B: case PHDR_802_11_PHY_11G: frequency = ieee80211_chan_to_mhz(ieee_802_11.channel, TRUE); break; case PHDR_802_11_PHY_11A: frequency = ieee80211_chan_to_mhz(ieee_802_11.channel, FALSE); break; default: /* We don't know the band. */ frequency = 0; break; } if (frequency != 0) { ieee_802_11.has_frequency = TRUE; ieee_802_11.frequency = frequency; } } phdr->pseudo_header.ieee_802_11 = ieee_802_11; if (peektagged->has_fcs) phdr->pseudo_header.ieee_802_11.fcs_len = 4; else { if (phdr->len < 4 || phdr->caplen < 4) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("peektagged: 802.11 packet has length < 4"); return FALSE; } phdr->pseudo_header.ieee_802_11.fcs_len = 0; phdr->len -= 4; phdr->caplen -= 4; skip_len = 4; } phdr->pseudo_header.ieee_802_11.decrypted = FALSE; phdr->pseudo_header.ieee_802_11.datapad = FALSE; break; case WTAP_ENCAP_ETHERNET: /* * The last 4 bytes appear to be 0 in the captures I've seen; * are there any captures where it's an FCS? */ if (phdr->len < 4 || phdr->caplen < 4) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("peektagged: Ethernet packet has length < 4"); return FALSE; } phdr->pseudo_header.eth.fcs_len = 0; phdr->len -= 4; phdr->caplen -= 4; skip_len = 4; break; } /* Read the packet data. */ if (!wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info)) return -1; return skip_len; }
/* Called on freq and type combo box change. */ static void tb80211_set_channel(void) { gchar *info = NULL; int err, selected_chan, new_type, new_freq; GtkComboBox *freq_combo = GTK_COMBO_BOX(tb80211_freq_list_box); GtkComboBox *type_combo = GTK_COMBO_BOX(tb80211_chan_type_box); selected_chan = gtk_combo_box_get_active(freq_combo); if (selected_chan < 0) return; new_freq = g_array_index(tb80211_current_iface->frequencies, int, selected_chan); new_type = get_selected_channel_type(); err = tb80211_do_set_channel(tb80211_current_iface->ifname, new_freq, new_type); if (err) { info = g_strdup_printf("<b>Failed to set channel: %s</b>", g_strerror(abs(err))); /* Try to set back to last working chan */ err = tb80211_do_set_channel(tb80211_current_iface->ifname, tb80211_current_freq, tb80211_current_type); if (err) { gtk_combo_box_set_active(freq_combo, -1); gtk_combo_box_set_active(type_combo, -1); tb80211_current_freq = -1; tb80211_current_type = -1; } else { tb80211_update_freq_and_type(); } } else { info = g_strdup_printf("%s Switched to %d MHz (%d)", tb80211_current_iface->ifname, new_freq, ieee80211_mhz_to_chan(new_freq)); tb80211_current_freq = new_freq; tb80211_current_type = new_type; } tb80211_set_info(info); g_free(info); }
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_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; }