Hi Guy,
I have fixed the bugs you pointed out:
https://github.com/nmap/npcap/commit/244e81226e99944f6bd4c12d713e97cb59139ec0
And I have also finished the radiotap "Rate" header. The looking up code is
like:
------------------------------------------------------------
USHORT
NPF_LookUpDataRateMappingTable(
IN POPEN_INSTANCE pOpen,
IN UCHAR ucDataRate
)
{
UINT i;
PDOT11_DATA_RATE_MAPPING_TABLE pTable = &pOpen->DataRateMappingTable;
USHORT usRetDataRateValue = 0;
TRACE_ENTER();
if (!pOpen->HasDataRateMappingTable)
{
TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Data rate mapping table not found, Open
= %p\n", pOpen);
TRACE_EXIT();
return usRetDataRateValue;
}
for (i = 0; i < pTable->uDataRateMappingLength; i ++)
{
if (pTable->DataRateMappingEntries[i].ucDataRateIndex == ucDataRate)
{
usRetDataRateValue = pTable->DataRateMappingEntries[i].usDataRateValue;
break;
}
}
TRACE_EXIT();
return usRetDataRateValue;
}
#endif
------------------------------------------------------------
And there's also a truncation from usDataRateValue (16 bits) to Radiotap
"Rate" field (8 bits). I hope a direct assignment is OK:
*((UCHAR*)Dot11RadiotapHeader + cur) = (UCHAR) usDataRateValue;
My capture result is like:
Data Rate: 22.0 Mb/s
My network speed is usually 10Mb/s - 100Mb/s. So I believe this is a valid
result.
And I also found the "SSI Signal" can be many values in my capture: -57
dBm, -91 dBm, -10 dBm, -94 dBm.
So I think it's somewhat meaningful too.
AFAIK, the radiotap feature is finished now. The software is:
https://github.com/nmap/npcap/releases/download/v0.06-r14/npcap-nmap-0.06-r14-wifi2.exe
Cheers,
Yang
On Sat, Apr 9, 2016 at 3:32 PM, Guy Harris <[email protected]> wrote:
> On Apr 8, 2016, at 9:25 PM, Yang Luo <[email protected]> wrote:
>
> > On Thu, Apr 7, 2016 at 9:37 AM, Guy Harris <[email protected]> wrote:
> >
> >> provide a radiotap Flags field with 0x10 set if the frame includes
> the FCS (you'll probably have to experiment a bit to see whether you get
> the FCS or not - the answer might differ for data and management frames,
> based on Network Monitor's behavior) and with 0x40 set if
> DOT11_RECV_FLAG_RAW_PACKET_FCS_FAILURE is set in uReceiveFlags;
> >
> > FCS is the suffix 4 bytes of a packet. Actually I didn't see those 4
> bytes in the packets (only 802.11 data for now) using Wireshark (captured
> by npcap-nmap-0.06-r13-wifi.exe). So I'm afraid it's the case that I can't
> get FCS for data frames? As I didn't start the work of capturing management
> frames yet. it will not be considered for now.
> >
> > So I think I will just leave FLags field with 0x00 then.
>
> Yes, that's the right thing to do.
>
> >> provide a radiotap Channel field where the frequency value is the
> uChCenterFrequency field of the structure and the flags are derived from
> the uChCenterFrequency and uPhyId fields of the structure - assuming that
> the uPhyId value is one of the ones from
> >>
> >>
> https://msdn.microsoft.com/en-us/library/windows/hardware/ff548741(v=vs.85).aspx
> >>
> >> then the mapping would be:
> >>
> >> dot11_phy_type_fhss - set 0x0800 in the flags (11 legacy FHSS);
> >>
> >> dot11_phy_type_ofdm - set 0x0040 in the flags (11a);
> >>
> >> dot11_phy_type_hrdsss - set 0x0020 in the flags (11b);
> >>
> >> dot11_phy_type_erp - set 0x0040 in the flags (11g, unknown
> whether it's pure or not);
> >>
> >> and, unless it's dot11_phy_type_irbaseband, set 0x0100 if the
> frequency is in the 5 GHz range or set 0x0080 if it's in the 2.4 GHz range;
> >
> > How to determine if uChCenterFrequency is 5GHz or 2.4GHz? What about the
> following conditions?
> > if (pwInfo->uChCenterFrequency == 5000)
> > and
> > if (pwInfo->uChCenterFrequency == 2400)
>
> No, it's a range, not a value. A test we use in Wireshark for CommView
> files is to check whether the center frequency is > 2484, so do
>
> if (pwInfo->uChCenterFrequency > 2484)
> 5 GHz band;
> else
> 2.4 GHz band;
>
> > Also I found the frequency of Radiotap "Channel" field is 16bit, but
> uChCenterFrequency is a ULONG type (32bit). They are both MHz unit. I hope
> a direct assignment is OK?
>
> It's OK for now, but 2^16 MHz is 65 GHz, and there's apparently some
> discussion of 60 GHz wireless communication, so, while a 16-bit frequency
> field might not become a problem in the short term, it might become a
> problem later. That'd require a change to radiotap.
>
> If the frequency is > 65535 MHz, I'd leave the channel field out.
>
> >> provide a radiotap Antenna signal field whose value is the value of
> the lRSSI field in the structure;
> >
> > Again a size truncating issue. I found radiotap Antenna signal field is
> 8bit. And pwInfo->lRSSI is a LONG type (32bit). is a direct assignment OK?
>
> 100 dBm is 10,000,000,000 milliwatts, at least if I'm interpreting
>
> https://en.wikipedia.org/wiki/Decibel
>
> correctly, so that's 10,000,000 watts.
>
> I *really* would not want to be anywhere near a Wi-Fi station transmitting
> at that power level. :-)
>
> -100 dBm is 1/10,000,000,000 milliwatts, which is .1 picowatt; I'm not a
> radio expert, but I suspect there might not be any radios capable of
> detecting that low a power level except in specialized physics or radio
> astronomy cases. (It's 1/10th the power consumption of an average human
> cell:
>
>
> https://en.wikipedia.org/wiki/Orders_of_magnitude_(power)#Picowatt_.2810.E2.88.9212_watt.29
>
> so it's not much power.)
>
> So I don't think you have to worry about a dBm power level that doesn't
> fit in 8 bits. You should leave out the antenna signal field if the value
> doesn't fit in 8 bits.
>
> >> if the phy is dot11_phy_type_ht, provide a radiotap MCS field where
> the known field is 0 and the other fields are also zeroed out (i.e., it's
> 11n, but we don't know anything else about it);
> >>
> >> if the phy is dot11_phy_type_vht, provide a radiotap VHT field where
> the known field is 0 and the other fields are also zeroed out (i.e., it's
> 11ac, but we don't know anything else about it).
> >
> > So simply speaking, if phy is dot11_phy_type_ht, then MCS field (3
> bytes) all zero.
> > If phy is dot11_phy_type_vht, then VHT field (12 bytes) all zero.
>
> Yes. It would nice if Microsoft were to specify, and vendors' drivers
> were to supply, more information, but at least supplying "empty" MCS and
> VHT fields will let the program processing the capture know that the packet
> was an HT or VHT packet.
>
> > Also, another question is, how large buffer is needed at most for the
> whole Radiotap header (including Radiotap data)?
> > Like the below code, I allocated a buffer of 256 bytes. I don't know if
> this is enough big. Or if there are any better handle ways?
>
> The beginning of the radiotap header is 8 bytes.
>
> Then the fields you'd supply, if *all* the fields were present, would be:
>
> TSFT: 8 bytes
>
> Flags: 1 byte
>
> Rate: 1 byte
>
> Channel: 4 bytes
>
> Antenna signal: 1 byte, plus 1 byte of alignment *if* this is a
> VHT frame
>
> MCS or VHT: MCS = 12 bytes, VHT = 12 bytes
>
> so the largest radiotap header you'd supply would be 8+8+1+1+4+2+12 = 36
> bytes.
>
> > For now, all the code about the Radiotap is here:
> > ---------------------------------------------------------------
> >
> > PDOT11_EXTSTA_RECV_CONTEXT pwInfo;
> > IEEE80211_RADIOTAP_HEADER RadiotapHeader = { 0 };
>
> > CHAR buf[256];
> > int cur = 0;
>
> You should actually initialize it to 8, to leave room for the
> IEEE80211_RADIOTAP_HEADER at the beginning.
>
> It's probably easiest to construct the IEEE80211_RADIOTAP_HEADER while
> you're filling in the rest of the radiotap header, and then copy it in
> place at the end.
>
> > // [Radiotap] "Flags" field.
>
> > if (TRUE) // The packet doesn't have FCS. We
> always have no FCS for all packets currently.
> > {
> > RadiotapHeader.it_present |=
> IEEE80211_RADIOTAP_FLAGS;
> > *((UCHAR*)buf + cur) = 0x0; // 0x0: none
> > cur += sizeof(UCHAR) / sizeof(UCHAR);
> > }
> > else // The packet has FCS.
> > {
> > RadiotapHeader.it_present |=
> IEEE80211_RADIOTAP_FLAGS;
> > *((UCHAR*)buf + cur) = 0x10; // 0x10:
> frame includes FCS
> >
> > // FCS check fails.
> > if ((pwInfo->uReceiveFlags &
> DOT11_RECV_FLAG_RAW_PACKET_FCS_FAILURE) ==
> DOT11_RECV_FLAG_RAW_PACKET_FCS_FAILURE)
> > {
> > *((UCHAR*)buf + cur) |= 0x40; //
> 0x40: frame failed FCS check
> > }
> >
> > cur += sizeof(UCHAR) / sizeof(UCHAR);
> > }
>
> You're providing a Flags field in all cases, so I'd just do
>
> // [Radiotap] "Flags" field.
> RadiotapHeader.it_present |=
> IEEE80211_RADIOTAP_FLAGS;
> if (TRUE) // The packet doesn't have FCS. We
> always have no FCS for all packets currently.
> {
> *((UCHAR*)buf + cur) = 0x0; // 0x0: none
> }
> else // The packet has FCS.
> {
> *((UCHAR*)buf + cur) = 0x10; // 0x10:
> frame includes FCS
>
> // FCS check fails.
> if ((pwInfo->uReceiveFlags &
> DOT11_RECV_FLAG_RAW_PACKET_FCS_FAILURE) ==
> DOT11_RECV_FLAG_RAW_PACKET_FCS_FAILURE)
> {
> *((UCHAR*)buf + cur) |= 0x40; //
> 0x40: frame failed FCS check
> }
> }
> cur += sizeof(UCHAR) / sizeof(UCHAR);
>
> > RadiotapHeader.it_present |=
> IEEE80211_RADIOTAP_CHANNEL;
> > *((USHORT*)buf + cur) = flags;
> > cur += sizeof(USHORT) / sizeof(UCHAR);
> > *((USHORT*)buf + cur) =
> pwInfo->uChCenterFrequency;
> > cur += sizeof(USHORT) / sizeof(UCHAR);
> > }
>
> The frequency comes before the channel, so that should be
>
> *((USHORT*)buf + cur) =
> pwInfo->uChCenterFrequency;
> cur += sizeof(USHORT) / sizeof(UCHAR);
> *((USHORT*)buf + cur) = flags;
> cur += sizeof(USHORT) / sizeof(UCHAR);
>
> > // [Radiotap] "Antenna signal" field.
> > if (TRUE)
> > {
> > RadiotapHeader.it_present |=
> IEEE80211_RADIOTAP_DBM_ANTSIGNAL;
> > RtlCopyMemory(buf + cur, &pwInfo->lRSSI,
> sizeof(UCHAR) / sizeof(UCHAR));
> > cur += sizeof(UCHAR) / sizeof(UCHAR);
> > }
> >
> > // [Radiotap] "MCS" field.
> > if (pwInfo->uPhyId == dot11_phy_type_ht)
> > {
> > RadiotapHeader.it_present |=
> IEEE80211_RADIOTAP_MCS;
> > RtlZeroMemory(buf + cur, 3 * sizeof(UCHAR)
> / sizeof(UCHAR));
> > cur += 3 * sizeof(UCHAR) / sizeof(UCHAR);
> > }
> > // [Radiotap] "VHT" field.
> > else if (pwInfo->uPhyId == dot11_phy_type_vht)
> > {
> > RadiotapHeader.it_present |=
> IEEE80211_RADIOTAP_VHT;
> > RtlZeroMemory(buf + cur, 12 *
> sizeof(UCHAR) / sizeof(UCHAR));
> > cur += 12 * sizeof(UCHAR) / sizeof(UCHAR);
> > }
>
> You'd need to do
>
> cur += sizeof(UCHAR) / sizeof(UCHAR);
>
> before putting the VHT field into the packet, because the VHT field has to
> be aligned on a 2-byte boundary, and the antenna field is on a 2-byte
> boundary but is only 1 byte long. (The MCS field, however, doesn't have to
> be aligned on a 2-byte boundary, so you *don't* need to pad anything for HT
> frames.)
>
> After all this is done, you'd need to do
>
> // Set the total length of the radiotap header
> RadiotapHeader.it_len = cur;
>
> and then do
>
> RtlCopyMemory(buf, &RadiotapHeader, sizeof RadiotapHeader);
>
> to put the IEEE80211_RADIOTAP_HEADER at the beginning of the radiotap
> header.
>
>
___________________________________________________________________________
Sent via: Wireshark-dev mailing list <[email protected]>
Archives: https://www.wireshark.org/lists/wireshark-dev
Unsubscribe: https://wireshark.org/mailman/options/wireshark-dev
mailto:[email protected]?subject=unsubscribe