/* * 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; }
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; }
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 commview_read_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info) { commview_header_t cv_hdr; struct tm tm; guint frequency; if(!commview_read_header(&cv_hdr, fh, err, err_info)) return FALSE; switch(cv_hdr.flags & FLAGS_MEDIUM) { case MEDIUM_ETHERNET : phdr->pkt_encap = WTAP_ENCAP_ETHERNET; phdr->pseudo_header.eth.fcs_len = -1; /* Unknown */ break; case MEDIUM_WIFI : phdr->pkt_encap = WTAP_ENCAP_IEEE_802_11_WITH_RADIO; phdr->pseudo_header.ieee_802_11.fcs_len = -1; /* Unknown */ phdr->pseudo_header.ieee_802_11.decrypted = FALSE; phdr->pseudo_header.ieee_802_11.datapad = FALSE; phdr->pseudo_header.ieee_802_11.phy = PHDR_802_11_PHY_UNKNOWN; phdr->pseudo_header.ieee_802_11.presence_flags = PHDR_802_11_HAS_CHANNEL | PHDR_802_11_HAS_DATA_RATE | PHDR_802_11_HAS_SIGNAL_PERCENT; switch (cv_hdr.band) { case BAND_11A: phdr->pseudo_header.ieee_802_11.phy = PHDR_802_11_PHY_11A; phdr->pseudo_header.ieee_802_11.phy_info.info_11a.presence_flags = PHDR_802_11A_HAS_TURBO_TYPE; phdr->pseudo_header.ieee_802_11.phy_info.info_11a.turbo_type = PHDR_802_11A_TURBO_TYPE_NORMAL; frequency = ieee80211_chan_to_mhz(cv_hdr.channel, FALSE); break; case BAND_11B: phdr->pseudo_header.ieee_802_11.phy = PHDR_802_11_PHY_11B; phdr->pseudo_header.ieee_802_11.phy_info.info_11b.presence_flags = 0; frequency = ieee80211_chan_to_mhz(cv_hdr.channel, TRUE); break; case BAND_11G: phdr->pseudo_header.ieee_802_11.phy = PHDR_802_11_PHY_11G; phdr->pseudo_header.ieee_802_11.phy_info.info_11g.presence_flags = PHDR_802_11G_HAS_MODE; phdr->pseudo_header.ieee_802_11.phy_info.info_11g.mode = PHDR_802_11G_MODE_NORMAL; frequency = ieee80211_chan_to_mhz(cv_hdr.channel, TRUE); break; case BAND_11A_TURBO: phdr->pseudo_header.ieee_802_11.phy = PHDR_802_11_PHY_11A; phdr->pseudo_header.ieee_802_11.phy_info.info_11a.presence_flags = PHDR_802_11A_HAS_TURBO_TYPE; phdr->pseudo_header.ieee_802_11.phy_info.info_11a.turbo_type = PHDR_802_11A_TURBO_TYPE_TURBO; frequency = ieee80211_chan_to_mhz(cv_hdr.channel, FALSE); break; case BAND_SUPERG: phdr->pseudo_header.ieee_802_11.phy = PHDR_802_11_PHY_11G; phdr->pseudo_header.ieee_802_11.phy_info.info_11g.presence_flags = PHDR_802_11G_HAS_MODE; phdr->pseudo_header.ieee_802_11.phy_info.info_11g.mode = PHDR_802_11G_MODE_SUPER_G; frequency = ieee80211_chan_to_mhz(cv_hdr.channel, TRUE); break; case BAND_11N_5GHZ: phdr->pseudo_header.ieee_802_11.phy = PHDR_802_11_PHY_11N; phdr->pseudo_header.ieee_802_11.phy_info.info_11n.presence_flags = 0; frequency = ieee80211_chan_to_mhz(cv_hdr.channel, FALSE); break; case BAND_11N_2_4GHZ: phdr->pseudo_header.ieee_802_11.phy = PHDR_802_11_PHY_11N; phdr->pseudo_header.ieee_802_11.phy_info.info_11n.presence_flags = 0; frequency = ieee80211_chan_to_mhz(cv_hdr.channel, TRUE); break; case BAND_PUBLIC_SAFETY: /* * XXX - what do we do here? What are the channel * numbers? How do we distinguish the several * different flavors of 4.9 GHz frequencies? */ frequency = 0; break; default: frequency = 0; break; } if (frequency != 0) { phdr->pseudo_header.ieee_802_11.presence_flags |= PHDR_802_11_HAS_FREQUENCY; phdr->pseudo_header.ieee_802_11.frequency = frequency; } phdr->pseudo_header.ieee_802_11.channel = cv_hdr.channel; phdr->pseudo_header.ieee_802_11.data_rate = cv_hdr.rate | (cv_hdr.direction << 8); phdr->pseudo_header.ieee_802_11.signal_percent = cv_hdr.signal_level_percent; /* * XXX - these are positive in captures I've seen; does * that mean that they are the negative of the actual * dBm value? (80 dBm is a bit more power than most * countries' regulatory agencies are likely to allow * any individual to have in their home. :-)) * * XXX - sometimes these are 0; assume that means that no * value is provided. */ if (cv_hdr.signal_level_dbm != 0) { phdr->pseudo_header.ieee_802_11.signal_dbm = -cv_hdr.signal_level_dbm; phdr->pseudo_header.ieee_802_11.presence_flags |= PHDR_802_11_HAS_SIGNAL_DBM; } if (cv_hdr.noise_level != 0) { phdr->pseudo_header.ieee_802_11.noise_dbm = -cv_hdr.noise_level; phdr->pseudo_header.ieee_802_11.presence_flags |= PHDR_802_11_HAS_NOISE_DBM; } break; case MEDIUM_TOKEN_RING : phdr->pkt_encap = WTAP_ENCAP_TOKEN_RING; break; default : *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("commview: unsupported encap: %u", cv_hdr.flags & FLAGS_MEDIUM); return FALSE; } tm.tm_year = cv_hdr.year - 1900; tm.tm_mon = cv_hdr.month - 1; tm.tm_mday = cv_hdr.day; tm.tm_hour = cv_hdr.hours; tm.tm_min = cv_hdr.minutes; tm.tm_sec = cv_hdr.seconds; tm.tm_isdst = -1; phdr->rec_type = REC_TYPE_PACKET; phdr->presence_flags = WTAP_HAS_TS; phdr->len = cv_hdr.data_len; phdr->caplen = cv_hdr.data_len; phdr->ts.secs = mktime(&tm); phdr->ts.nsecs = cv_hdr.usecs * 1000; return wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info); }