This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

Can Python show if a PcapNG trace file came from 802.11n or 802.11ac?

0

I'm trying to determine the 802.11 protocol variant - from PcapNG trace files created by wiretap (see relevant question on StackOverflow, and another relevant question on StackOverflow).

The link-layer header type for the interface on which the packet was captured is LINKTYPE_IEEE802_11_RADIOTAP (127), so I can use radiotap.py to extract the Channel field and thus ascertain if the 802.11 protocol variant is a, b, or g.

However, to ascertain if I have 802.11n or 802.11ac, I need to access the XChannel/MCS or the VHT fields. These fields are not defined in radiotap.py, which means I need to extend radiotap.py's parse function.

I tried and failed: I suspect I'm setting the alignment/structures wrong (or some other obscure bug) and the existing radiotap.py code isn't helping me much.

Can anyone suggest which changes should I make in radiotap.py so it'll recognise the XChannel, MCS, and VHT fields?


A sample PcapNG trace file is here.

My Python code is:

#!/usr/bin/env python

from pcapng import FileScanner import radiotap

def hex_str_to_num(hex_str,out_format='X'): if out_format.upper() == 'B': return ' '.join(format(ord(x), out_format).zfill(8) for x in hex_str) else: return ' '.join(format(ord(x), out_format).zfill(2) for x in hex_str)

def get_protocol_variant(channel): """ 0x0010 Turbo Channel 0x0020 CCK channel 0x0040 OFDM channel 0x0080 2 GHz spectrum channel 0x0100 5 GHz spectrum channel 0x0200 Only passive scan allowed 0x0400 Dynamic CCK-OFDM channel 0x0800 GFSK channel (FHSS PHY)

If link-layer header type for the interface is LINKTYPE_IEEE802_11, protocol variant
cannot be ascertained.

If link-layer header type for the interface is LINKTYPE_IEEE802_11_RADIOTAP, then 
the packet begins with a radiotap header giving various meta-data about the packet.

If the radiotap header includes the Channel field, then, from the information there,
the protocol variant may be ascertained as following:

    "5 GHz spectrum channel" + "OFDM channel" = 802.11a;
    "2 GHz spectrum channel" + "CCK channel" = 802.11b;
    "2 GHz spectrum channel" + "OFDM channel" = 802.11g;
    "2 GHz spectrum channel" + "Dynamic CCK-OFDM channel" = 802.11g;
    (the difference between the two flavors of 802.11g indicates whether there 
     might also be 802.11b traffic on the same channel - that's what the 
     "Dynamic CCK-OFDM channel" indicates).

    However, if the MCS field is present, it's 802.11n, not any of those other types,
    and if the VHT field is present, it's 802.11ac.

    There might also be an XChannel field, which can be interpreted similarly to the 
    Channel field, although it also contains some information for 802.11n.
"""

def check(_name, _const):
    _bit = None
    if (channel & _const):
        _bit = True
        print _name,_bit
    return _bit

TURBO = 0x0010
CCK   = 0x0020
OFDM  = 0x0040
GHz_2 = 0x0080
GHz_5 = 0x0100
PASSI = 0x0200
DYNAM = 0x0400
GFSK  = 0x0800

variant = None

turbo = check("turbo", TURBO)
cck = check("cck", CCK)
ofdm = check("ofdm", OFDM)
ghz_2 = check("ghz_2", GHz_2)
ghz_5 = check("ghz_5", GHz_5)
passi = check("passi", PASSI)
dynam = check("dynam", DYNAM)
gfsk = check("gfsk", GFSK)

if ghz_5 and ofdm:
    variant = "802.11a"
elif ghz_2 and cck:
    variant = "802.11b"
elif ghz_2 and ofdm:
    variant = "802.11g"
elif ghz_2 and dynam:
    variant = "802.11g"

print "variant",variant    
return variant

PCAPNG = "/cygdrive/c/tmp/trace3.pcapng" MAX = 5 INTERFACEDESCRIPTION = 1 ENHANCEDPACKET = 6 LINKTYPE_IEEE802_11_RADIOTAP = 127

with open(PCAPNG, "r") as pcapng_file: scanner = FileScanner(pcapng_file) counter = MAX link_type = None for block in scanner: print print "magic_number",hex(block.magic_number) print block

    if block.magic_number == ENHANCEDPACKET:
        if link_type == LINKTYPE_IEEE802_11_RADIOTAP:
            payload_data = block.packet_payload_info[2]
            print "packet_payload_data (hex):",hex_str_to_num(payload_data,"X")
            radiotap_dict = radiotap.parse(payload_data)
            radiotap_hedear_len = radiotap.get_length(payload_data)
            print "radiotap_dict",radiotap_dict
            channel = radiotap_dict[radiotap.RTAP_CHANNEL]
            protocol_variant = get_protocol_variant(channel)
            print "protocol_variant",protocol_variant
            """
            print "channel",channel,hex(channel),bin(channel)
            print "radiotap_hedear_len",radiotap_hedear_len
            payload_802_11 = payload_data[radiotap_hedear_len+1:]
            print "payload_802_11 (hex)",hex_str_to_num(payload_802_11,"X")
            """
    elif block.magic_number == INTERFACEDESCRIPTION:
        link_type = block.link_type

    counter -= 1
    if not counter:
        break</code></pre><p>and its output is:</p><pre><code>magic_number 0xa0d0d0a

SectionHeader(version_major=1, version_minor=0, section_length=-1, options=Options({'shb_userappl': [u'Dumpcap 1.12.4 (v1.12.4-0-gb4861da from master-1.12)'], 'shb_os': [u'Mac OS X 10.10.2, build 14C109 (Darwin 14.1.0)']}))

magic_number 0x1 InterfaceDescription(link_type=127, reserved='\x00\x00', snaplen=262144, options=Options({'if_os': [u'Mac OS X 10.10.2, build 14C109 (Darwin 14.1.0)'], 'if_tsresol': [6], 'if_name': [u'en1']}))

magic_number 0x6 EnhancedPacket(interface_id=0, timestamp_high=332139, timestamp_low=2801116064L, packet_payload_info=(45, 45, '\x00\x00\x19\x00o\x08\x00\x00I\xb2&amp;\x00\x00\x00\x00\x12\x18q\[email protected]\x01\xb1\xaa\x00\xb4\x00\x90\x00\xf4\x0f\x1b\xb8sL\x92\x175\x00\x01\xe3\xcf\x00\x12'), options=Options({})) packet_payload_data (hex): 00 00 19 00 6F 08 00 00 60 49 B2 26 00 00 00 00 12 18 71 16 40 01 B1 AA 00 B4 00 90 00 F4 0F 1B B8 73 4C 60 92 17 35 00 01 E3 CF 00 12 radiotap_dict {0: 649218400, 1: 18, 2: 24, 3: 20977265, 5: -79, 6: -86, 11: 0} turbo True cck True ofdm True passi True dynam True variant None protocol_variant None

magic_number 0x6 EnhancedPacket(interface_id=0, timestamp_high=332139, timestamp_low=2801116070L, packet_payload_info=(39, 39, '\x00\x00\x19\x00o\x08\x00\x00\x92I\xb2&\x00\x00\x00\x00\x12\x18q[email protected]\x01\xcd\xaa\x00\xc4\x00\x00\x92\x175\x00\x01\xf7eny'), options=Options({})) packet_payload_data (hex): 00 00 19 00 6F 08 00 00 92 49 B2 26 00 00 00 00 12 18 71 16 40 01 CD AA 00 C4 00 60 00 60 92 17 35 00 01 F7 65 6E 79 radiotap_dict {0: 649218450, 1: 18, 2: 24, 3: 20977265, 5: -51, 6: -86, 11: 0} turbo True cck True ofdm True passi True dynam True variant None protocol_variant None

magic_number 0x6 EnhancedPacket(interface_id=0, timestamp_high=332139, timestamp_low=2801116213L, packet_payload_info=(57, 57, '\x00\x00\x19\x00o\x08\x00\x00\tJ\xb2&\x00\x00\x00\x00\x12\x18q[email protected]\x01\xca\xaa\x00\x94\x00\x00\x00`\x92\x175\x00\x01\xf4\x0f\x1b\xb8sL\x04\x00\xc0#\xff\xff\xff\xff\xff\xff\xff\xffX\xd0Y\'), options=Options({})) packet_payload_data (hex): 00 00 19 00 6F 08 00 00 09 4A B2 26 00 00 00 00 12 18 71 16 40 01 CA AA 00 94 00 00 00 60 92 17 35 00 01 F4 0F 1B B8 73 4C 04 00 C0 23 FF FF FF FF FF FF FF FF 58 D0 59 5C radiotap_dict {0: 649218569, 1: 18, 2: 24, 3: 20977265, 5: -54, 6: -86, 11: 0} turbo True cck True ofdm True passi True

asked 31 Mar ‘15, 08:52

ronbarak's gravatar image

ronbarak
10225
accept rate: 0%

edited 31 Mar ‘15, 15:15