• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3#   Copyright 2021 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#         http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17from enum import IntEnum, unique
18from typing import Tuple
19
20
21@unique
22class ExtendedCapability(IntEnum):
23    """All extended capabilities present in IEEE 802.11-2020 Table 9-153.
24
25    Each name has a value corresponding to that extended capability's bit offset
26    in the specification's extended capabilities field.
27
28    Note that most extended capabilities are represented by a single bit, which
29    indicates whether the extended capability is advertised by the STA; but
30    some are represented by multiple bits. In the enum, each extended capability
31    has the value of its offset; comments indicate capabilities that use
32    multiple bits.
33    """
34    TWENTY_FORTY_BSS_COEXISTENCE_MANAGEMENT_SUPPORT = 0
35    GLK = 1
36    EXTENDED_CHANNEL_SWITCHING = 2
37    GLK_GCR = 3
38    PSMP_CAPABILITY = 4
39    # 5 reserved
40    S_PSMP_SUPPORT = 6
41    EVENT = 7
42    DIAGNOSTICS = 8
43    MULTICAST_DIAGNOSTICS = 9
44    LOCATION_TRACKING = 10
45    FMS = 11
46    PROXY_ARP_SERVICE = 12
47    COLLOCATED_INTERFERENCE_REPORTING = 13
48    CIVIC_LOCATION = 14
49    GEOSPATIAL_LOCATION = 15
50    TFS = 16
51    WNM_SLEEP_MODE = 17
52    TIM_BROADCAST = 18
53    BSS_TRANSITION = 19
54    QOS_TRAFFIC_CAPABILITY = 20
55    AC_STATION_COUNT = 21
56    MULTIPLE_BSSID = 22
57    TIMING_MEASUREMENT = 23
58    CHANNEL_USAGE = 24
59    SSID_LIST = 25
60    DMS = 26
61    UTC_TSF_OFFSET = 27
62    TPU_BUFFER_STA_SUPPORT = 28
63    TDLS_PEER_PSM_SUPPORT = 29
64    TDLS_CHANNEL_SWITCHING = 30
65    INTERWORKING = 31
66    QOS_MAP = 32
67    EBR = 33
68    SSPN_INTERFACE = 34
69    # 35 reserved
70    MSGCF_CAPABILITY = 36
71    TDLS_SUPPORT = 37
72    TDLS_PROHIBITED = 38
73    TDLS_CHANNEL_SWITCHING_PROHIBITED = 39
74    REJECT_UNADMITTED_FRAME = 40
75    SERVICE_INTERVAL_GRANULARITY = 41
76    # Bits 41-43 contain SERVICE_INTERVAL_GRANULARITY value
77    IDENTIFIER_LOCATION = 44
78    U_APSD_COEXISTENCE = 45
79    WNM_NOTIFICATION = 46
80    QAB_CAPABILITY = 47
81    UTF_8_SSID = 48
82    QMF_ACTIVATED = 49
83    QMF_RECONFIGURATION_ACTIVATED = 50
84    ROBUST_AV_STREAMING = 51
85    ADVANCED_GCR = 52
86    MESH_GCR = 53
87    SCS = 54
88    QLOAD_REPORT = 55
89    ALTERNATE_EDCA = 56
90    UNPROTECTED_TXOP_NEGOTIATION = 57
91    PROTECTED_TXOP_NEGOTIATION = 58
92    # 59 reserved
93    PROTECTED_QLOAD_REPORT = 60
94    TDLS_WIDER_BANDWIDTH = 61
95    OPERATING_MODE_NOTIFICATION = 62
96    MAX_NUMBER_OF_MSDUS_IN_A_MSDU = 63
97    # 63-64 contain MAX_NUMBER_OF_MSDUS_IN_A_MSDU value
98    CHANNEL_SCHEDULE_MANAGEMENT = 65
99    GEODATABASE_INBAND_ENABLING_SIGNAL = 66
100    NETWORK_CHANNEL_CONTROL = 67
101    WHITE_SPACE_MAP = 68
102    CHANNEL_AVAILABILITY_QUERY = 69
103    FINE_TIMING_MEASUREMENT_RESPONDER = 70
104    FINE_TIMING_MEASUREMENT_INITIATOR = 71
105    FILS_CAPABILITY = 72
106    EXTENDED_SPECTRUM_MANAGEMENT_CAPABLE = 73
107    FUTURE_CHANNEL_GUIDANCE = 74
108    PAD = 75
109    # 76-79 reserved
110    COMPLETE_LIST_OF_NON_TX_BSSID_PROFILES = 80
111    SAE_PASSWORD_IDENTIFIERS_IN_USE = 81
112    SAE_PASSWORD_IDENTIFIERS_USED_EXCLUSIVELY = 82
113    # 83 reserved
114    BEACON_PROTECTION_ENABLED = 84
115    MIRRORED_SCS = 85
116    # 86 reserved
117    LOCAL_MAC_ADDRESS_POLICY = 87
118    # 88-n reserved
119
120
121def _offsets(ext_cap_offset: ExtendedCapability) -> Tuple[int, int]:
122    """For given capability, return the byte and bit offsets within the field.
123
124    802.11 divides the extended capability field into bytes, as does the
125    ExtendedCapabilities class below. This function returns the index of the
126    byte that contains the given extended capability, as well as the bit offset
127    inside that byte (all offsets zero-indexed). For example,
128    MULTICAST_DIAGNOSTICS is bit 9, which is within byte 1 at bit offset 1.
129    """
130    byte_offset = ext_cap_offset // 8
131    bit_offset = ext_cap_offset % 8
132    return byte_offset, bit_offset
133
134
135class ExtendedCapabilities:
136    """Extended capability parsing and representation.
137
138    See IEEE 802.11-2020 9.4.2.26.
139    """
140
141    def __init__(self, ext_cap: bytearray = bytearray()):
142        """Represent the given extended capabilities field.
143
144        Args:
145            ext_cap: IEEE 802.11-2020 9.4.2.26 extended capabilities field.
146            Default is an empty field, meaning no extended capabilities are
147            advertised.
148        """
149        self._ext_cap = ext_cap
150
151    def _capability_advertised(self, ext_cap: ExtendedCapability) -> bool:
152        """Whether an extended capability is advertised.
153
154        Args:
155            ext_cap: an extended capability.
156        Returns:
157            True if the bit is present and its value is 1, otherwise False.
158        Raises:
159            NotImplementedError: for extended capabilities that span more than
160            a single bit. These could be supported, but no callers need them
161            at this time.
162        """
163        if ext_cap in [
164                ExtendedCapability.SERVICE_INTERVAL_GRANULARITY,
165                ExtendedCapability.MAX_NUMBER_OF_MSDUS_IN_A_MSDU
166        ]:
167            raise NotImplementedError(
168                f'{ext_cap.name} not implemented yet by {__class__}')
169        byte_offset, bit_offset = _offsets(ext_cap)
170        if len(self._ext_cap) > byte_offset:
171            # Use bit_offset to derive a mask that will check the correct bit.
172            if self._ext_cap[byte_offset] & 2**bit_offset > 0:
173                return True
174        return False
175
176    @property
177    def bss_transition(self) -> bool:
178        return self._capability_advertised(ExtendedCapability.BSS_TRANSITION)
179
180    @property
181    def proxy_arp_service(self) -> bool:
182        return self._capability_advertised(
183            ExtendedCapability.PROXY_ARP_SERVICE)
184
185    @property
186    def utc_tsf_offset(self) -> bool:
187        return self._capability_advertised(ExtendedCapability.UTC_TSF_OFFSET)
188
189    @property
190    def wnm_sleep_mode(self) -> bool:
191        return self._capability_advertised(ExtendedCapability.WNM_SLEEP_MODE)
192
193    # Other extended capability property methods can be added as needed by callers.
194