Esempio n. 1
0
/*
 * 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;
}
Esempio n. 4
0
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);
}