Skip to content

Commit ffa6194

Browse files
authored
feat(link): add a radiotap dissector for IEEE80211_RADIOTAP on LinuxSLL (#2509)
1 parent 11f6aae commit ffa6194

20 files changed

Lines changed: 1027 additions & 63 deletions

‎docs/source/pcapkit/protocols/link/index.rst‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ link layer, with detailed implementation and methods.
3333
linux_sll2
3434
loopback
3535
netlink
36+
radiotap
3637
vlan
3738
c_tag
3839
s_tag
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
Radiotap - IEEE 802.11 Radiotap Header
2+
========================================
3+
4+
.. module:: pcapkit.protocols.link.radiotap
5+
6+
:mod:`pcapkit.protocols.link.radiotap` contains
7+
:class:`~pcapkit.protocols.link.radiotap.Radiotap`
8+
only, which implements the extractor for the radiotap header [*]_ capture
9+
tools prepend to an 802.11 frame, as seen on a
10+
``LINKTYPE_LINUX_SLL``/``LINKTYPE_LINUX_SLL2`` capture whose ``arphrd_type``
11+
is ``ARPHRD_IEEE80211_RADIOTAP``. Radiotap is not part of the 802.11
12+
standard itself -- it is a prefix written by the capturing tool, in front of
13+
the raw 802.11 MAC frame. Its fixed start, all little-endian, is described
14+
as below:
15+
16+
.. table::
17+
18+
====== ==== ======================== ================================
19+
Octets Bits Name Description
20+
====== ==== ======================== ================================
21+
0 0 ``radiotap.it_version`` Header Revision (always ``0``)
22+
1 8 ``radiotap.it_pad`` Padding
23+
2 16 ``radiotap.it_len`` Header Length (header included)
24+
4 32 ``radiotap.it_present`` First Present-Flags Word
25+
====== ==== ======================== ================================
26+
27+
followed by a chain of further present-flags words -- bit 31 of a word
28+
signals that another follows -- and then the optional-field region those
29+
bitmasks select, each field aligned and sized per its own type. ``it_len``
30+
bounds the whole of it; the 802.11 MAC frame starts at that offset.
31+
32+
Scope
33+
-----
34+
35+
Decoding every optional field radiotap.org defines, and the 802.11 MAC
36+
frame behind them, is future work tracked on :issue:`2460` and
37+
:issue:`2502` -- this is already the widest of that issue's five
38+
follow-ups, and the 802.11 MAC frame is a protocol family of its own. This
39+
first cut instead:
40+
41+
* **Decodes** the fixed 8-octet start -- ``it_version``, ``it_pad``,
42+
``it_len`` -- and walks the present-flags chain far enough to know how
43+
many words it has
44+
(:attr:`~pcapkit.protocols.data.link.radiotap.Radiotap.present`), without
45+
decoding what any bit selects.
46+
* **Skips, rather than decodes,** the optional-field region those bits
47+
select -- the octets between the present-flags chain and ``it_len`` are
48+
kept whole and undissected, as
49+
:attr:`~pcapkit.protocols.data.link.radiotap.Radiotap.fields`.
50+
* **Leaves opaque** everything from ``it_len`` on: the 802.11 MAC frame
51+
itself, which has no dissector anywhere in this package yet. It is kept
52+
as :class:`~pcapkit.protocols.misc.raw.Raw` (or
53+
:class:`~pcapkit.protocols.misc.null.NoPayload` when nothing follows),
54+
unconditionally.
55+
56+
.. autoclass:: pcapkit.protocols.link.radiotap.Radiotap
57+
:no-members:
58+
:show-inheritance:
59+
60+
.. autoproperty:: name
61+
.. autoproperty:: alias
62+
.. autoproperty:: length
63+
64+
.. automethod:: id
65+
66+
.. automethod:: read
67+
.. automethod:: make
68+
69+
.. automethod:: __length_hint__
70+
.. automethod:: __index__
71+
72+
.. automethod:: _make_data
73+
.. automethod:: _import_next_layer
74+
75+
.. autoattribute:: __proto__
76+
:no-value:
77+
78+
Header Schemas
79+
--------------
80+
81+
.. module:: pcapkit.protocols.schema.link.radiotap
82+
83+
.. autoclass:: pcapkit.protocols.schema.link.radiotap.Radiotap
84+
:members:
85+
:show-inheritance:
86+
87+
Data Models
88+
-----------
89+
90+
.. module:: pcapkit.protocols.data.link.radiotap
91+
92+
.. autoclass:: pcapkit.protocols.data.link.radiotap.Radiotap
93+
:members:
94+
:show-inheritance:
95+
96+
.. rubric:: Footnotes
97+
98+
.. [*] <https://www.radiotap.org/>; the Linux kernel's
99+
``include/net/ieee80211_radiotap.h`` and ``net/wireless/radiotap.c``; and
100+
Wireshark's ``packet-ieee80211-radiotap.c``.

‎pcapkit/__init__.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@
112112
'Raw', # Raw Packet
113113

114114
'ARP', 'C_Tag', 'Ethernet', 'FRAD', 'GRE', 'InARP', 'L2TP', # Link Layer
115-
'L2TPv2', 'LinuxSLL', 'LinuxSLL1', 'LinuxSLL2', 'Loopback', 'Netlink', 'S_Tag', 'VLAN',
115+
'L2TPv2', 'LinuxSLL', 'LinuxSLL1', 'LinuxSLL2', 'Loopback', 'Netlink', 'Radiotap',
116+
'S_Tag', 'VLAN',
116117

117118
'AH', 'ESP', 'ICMP', 'ICMPv4', 'ICMPv6', # Internet Layer
118119
'IGMP', 'IGMPv1', 'IGMPv2', 'IGMPv3', 'IP', 'IPsec', 'IPv4', 'IPv6', 'IPX',

‎pcapkit/all.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,9 @@
122122
'NoPayload', # No Payload
123123
'Raw', # Raw Packet
124124
'ARP', 'C_Tag', 'Ethernet', 'FRAD', 'GRE', 'InARP', 'L2TP', 'L2TPv2', 'LinuxSLL', 'LinuxSLL1',
125-
'LinuxSLL2', 'Loopback', 'Netlink', 'S_Tag', 'VLAN', # Link Layer
125+
'LinuxSLL2', 'Loopback', 'Netlink', 'Radiotap', 'S_Tag', 'VLAN', # Link Layer
126126
'AH', 'ESP', 'ICMP', 'ICMPv4', 'ICMPv6', 'IGMP', 'IGMPv1', 'IGMPv2', 'IGMPv3',
127127
'IP', 'IPsec', 'IPv4', 'IPv6', 'IPX', # Internet Layer
128-
129128
'HIP', 'HOPOPT', 'IPv6_Ext', 'IPv6_Frag', 'IPv6_Opts', 'IPv6_Route', 'MH',
130129
# IPv6 Extension Header
131130
'IP_Pseudo', # IP Pseudo-Header

‎pcapkit/protocols/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
# Link Layer
5353
'ARP', 'C_Tag', 'Ethernet', 'FRAD', 'GRE', 'InARP', 'L2TP', 'L2TPv2', 'LinuxSLL', 'LinuxSLL1',
54-
'LinuxSLL2', 'Loopback', 'Netlink', 'S_Tag', 'VLAN',
54+
'LinuxSLL2', 'Loopback', 'Netlink', 'Radiotap', 'S_Tag', 'VLAN',
5555

5656
# Internet Layer
5757
'AH', 'ESP', 'ICMP', 'ICMPv4', 'ICMPv6', 'IGMP', 'IGMPv1', 'IGMPv2', 'IGMPv3',

‎pcapkit/protocols/data/__init__.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@
8080
# Netlink Socket Framing
8181
'Netlink',
8282

83+
# IEEE 802.11 Radiotap Header
84+
'Radiotap',
85+
8386
# 802.1Q/802.1ad VLAN Tag Types
8487
'VLAN', 'VLAN_TCI',
8588

‎pcapkit/protocols/data/link/__init__.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
# Netlink Socket Framing
3030
from pcapkit.protocols.data.link.netlink import Netlink
3131

32+
# IEEE 802.11 Radiotap Header
33+
from pcapkit.protocols.data.link.radiotap import Radiotap
34+
3235
# 802.1Q/802.1ad VLAN Tag Types
3336
from pcapkit.protocols.data.link.vlan import TCI as VLAN_TCI
3437
from pcapkit.protocols.data.link.vlan import VLAN
@@ -58,6 +61,9 @@
5861
# Netlink Socket Framing
5962
'Netlink',
6063

64+
# IEEE 802.11 Radiotap Header
65+
'Radiotap',
66+
6167
# 802.1Q/802.1ad VLAN Tag Types
6268
'VLAN', 'VLAN_TCI',
6369
]
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# -*- coding: utf-8 -*-
2+
"""data models for IEEE 802.11 radiotap headers"""
3+
4+
from typing import TYPE_CHECKING
5+
6+
from pcapkit.corekit.infoclass import info_final
7+
from pcapkit.protocols.data.protocol import Protocol
8+
9+
if TYPE_CHECKING:
10+
pass
11+
12+
__all__ = ['Radiotap']
13+
14+
15+
@info_final
16+
class Radiotap(Protocol):
17+
"""Data model for an IEEE 802.11 radiotap header.
18+
19+
Only the fixed 8-octet start is decoded field by field; the rest is kept
20+
whole, see :attr:`present` and :attr:`fields` and the module docstring's
21+
*Scope* section on :mod:`pcapkit.protocols.link.radiotap`.
22+
23+
"""
24+
25+
#: Header revision; ``0`` is the only version radiotap.org defines, and
26+
#: the only one this package decodes.
27+
it_version: 'int'
28+
#: Padding octet, kept for alignment; not interpreted.
29+
it_pad: 'int'
30+
#: Total length of the radiotap header -- the fixed 8-octet start,
31+
#: every extended present-flags word, and the optional-field region
32+
#: they select -- in octets; the 802.11 MAC frame starts here. Kept
33+
#: exactly as captured, even where it disagrees with :attr:`present`
34+
#: and :attr:`fields`.
35+
it_len: 'int'
36+
#: Every present-flags word in the chain that was actually read, in
37+
#: order; index ``0`` is the mandatory first word (radiotap.org's own
38+
#: ``it_present``). Bit 31 of a word signals that another word
39+
#: follows; it is clear on the last word read, unless the capture ran
40+
#: out before a word it claimed would follow.
41+
present: 'tuple[int, ...]'
42+
#: The optional-field region :attr:`present` selects, kept whole and
43+
#: undissected.
44+
fields: 'bytes'
45+
46+
if TYPE_CHECKING:
47+
def __init__(self, it_version: 'int', it_pad: 'int', it_len: 'int', # pylint: disable=unused-argument,super-init-not-called,multiple-statements
48+
present: 'tuple[int, ...]', fields: 'bytes') -> 'None': ... # pylint: disable=unused-argument

‎pcapkit/protocols/link/__init__.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from pcapkit.protocols.link.gre import GRE
2222
from pcapkit.protocols.link.loopback import Loopback
2323
from pcapkit.protocols.link.netlink import Netlink
24+
from pcapkit.protocols.link.radiotap import Radiotap
2425

2526
# Linux "Cooked" Capture Encapsulation Family
2627
from pcapkit.protocols.link.linux_sll import LinuxSLL
@@ -45,5 +46,5 @@
4546

4647
# Link Layer Protocols
4748
'ARP', 'C_Tag', 'Ethernet', 'FRAD', 'GRE', 'InARP', 'L2TP', 'L2TPv2', 'LinuxSLL', 'LinuxSLL1',
48-
'LinuxSLL2', 'Loopback', 'Netlink', 'S_Tag', 'VLAN',
49+
'LinuxSLL2', 'Loopback', 'Netlink', 'Radiotap', 'S_Tag', 'VLAN',
4950
]

‎pcapkit/protocols/link/link.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
:class:`~pcapkit.protocols.link.ethernet.Ethernet`,
1313
:class:`~pcapkit.protocols.link.frad.FRAD`,
1414
:class:`~pcapkit.protocols.link.l2tp.L2TP`,
15-
:class:`~pcapkit.protocols.link.loopback.Loopback` and
15+
:class:`~pcapkit.protocols.link.loopback.Loopback`,
16+
:class:`~pcapkit.protocols.link.radiotap.Radiotap` and
1617
:class:`~pcapkit.protocols.link.vlan.VLAN`.
1718
1819
"""

0 commit comments

Comments
 (0)