wl_nl80211/
attr.rs

1// SPDX-License-Identifier: MIT
2
3// Most documentation comments are copied and modified from linux kernel
4// include/uapi/linux/nl80211.h which is holding these license disclaimer:
5/*
6 * 802.11 netlink interface public header
7 *
8 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
9 * Copyright 2008 Michael Wu <flamingice@sourmilk.net>
10 * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
11 * Copyright 2008 Michael Buesch <m@bues.ch>
12 * Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
13 * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
14 * Copyright 2008 Colin McCabe <colin@cozybit.com>
15 * Copyright 2015-2017	Intel Deutschland GmbH
16 * Copyright (C) 2018-2024 Intel Corporation
17 *
18 * Permission to use, copy, modify, and/or distribute this software for any
19 * purpose with or without fee is hereby granted, provided that the above
20 * copyright notice and this permission notice appear in all copies.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
23 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
25 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
27 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
28 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 *
30 */
31
32use netlink_packet_core::{
33    parse_string, parse_u16, parse_u32, parse_u64, parse_u8, DecodeError,
34    DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer, NlasIterator,
35    Parseable, ParseableParametrized,
36};
37
38use crate::{
39    bytes::{write_u16, write_u32, write_u64},
40    scan::{Nla80211ScanFreqNlas, Nla80211ScanSsidNlas},
41    wiphy::Nl80211Commands,
42    Nl80211Band, Nl80211BandTypes, Nl80211BssInfo, Nl80211ChannelWidth,
43    Nl80211CipherSuit, Nl80211Command, Nl80211ExtFeature, Nl80211ExtFeatures,
44    Nl80211ExtendedCapability, Nl80211Features, Nl80211HtCapabilityMask,
45    Nl80211HtWiphyChannelType, Nl80211IfMode, Nl80211IfTypeExtCapa,
46    Nl80211IfTypeExtCapas, Nl80211IfaceComb, Nl80211IfaceFrameType,
47    Nl80211InterfaceType, Nl80211InterfaceTypes, Nl80211MloLink,
48    Nl80211ScanFlags, Nl80211SchedScanMatch, Nl80211SchedScanPlan,
49    Nl80211StationInfo, Nl80211SurveyInfo, Nl80211TransmitQueueStat,
50    Nl80211VhtCapability, Nl80211WowlanTriggersSupport,
51};
52
53const ETH_ALEN: usize = 6;
54
55struct MacAddressNlas(Vec<MacAddressNla>);
56
57impl std::ops::Deref for MacAddressNlas {
58    type Target = Vec<MacAddressNla>;
59
60    fn deref(&self) -> &Self::Target {
61        &self.0
62    }
63}
64
65impl From<&Vec<[u8; ETH_ALEN]>> for MacAddressNlas {
66    fn from(macs: &Vec<[u8; ETH_ALEN]>) -> Self {
67        let mut nlas = Vec::new();
68        for (i, mac) in macs.iter().enumerate() {
69            let nla = MacAddressNla {
70                index: i as u16,
71                mac: *mac,
72            };
73            nlas.push(nla);
74        }
75        MacAddressNlas(nlas)
76    }
77}
78
79impl From<MacAddressNlas> for Vec<[u8; ETH_ALEN]> {
80    fn from(macs: MacAddressNlas) -> Self {
81        let mut macs = macs;
82        macs.0.drain(..).map(|c| c.mac).collect()
83    }
84}
85
86impl MacAddressNlas {
87    pub fn parse(payload: &[u8]) -> Result<Self, DecodeError> {
88        let mut macs: Vec<MacAddressNla> = Vec::new();
89        for (index, nla) in NlasIterator::new(payload).enumerate() {
90            let error_msg = format!("Invalid NL80211_ATTR_MAC_ADDRS: {nla:?}");
91            let nla = &nla.context(error_msg.clone())?;
92            let mut mac = [0u8; ETH_ALEN];
93            mac.copy_from_slice(&nla.value()[..ETH_ALEN]);
94            macs.push(MacAddressNla {
95                index: index as u16,
96                mac,
97            });
98        }
99        Ok(Self(macs))
100    }
101}
102
103struct MacAddressNla {
104    index: u16,
105    mac: [u8; ETH_ALEN],
106}
107
108impl Nla for MacAddressNla {
109    fn value_len(&self) -> usize {
110        ETH_ALEN
111    }
112
113    fn emit_value(&self, buffer: &mut [u8]) {
114        buffer[..ETH_ALEN].copy_from_slice(&self.mac)
115    }
116
117    fn kind(&self) -> u16 {
118        self.index
119    }
120}
121
122// const NL80211_ATTR_UNSPEC:u16 = 0;
123const NL80211_ATTR_WIPHY: u16 = 1;
124const NL80211_ATTR_WIPHY_NAME: u16 = 2;
125const NL80211_ATTR_IFINDEX: u16 = 3;
126const NL80211_ATTR_IFNAME: u16 = 4;
127const NL80211_ATTR_IFTYPE: u16 = 5;
128const NL80211_ATTR_MAC: u16 = 6;
129// const NL80211_ATTR_KEY_DATA:u16 = 7;
130// const NL80211_ATTR_KEY_IDX:u16 = 8;
131// const NL80211_ATTR_KEY_CIPHER:u16 = 9;
132// const NL80211_ATTR_KEY_SEQ:u16 = 10;
133// const NL80211_ATTR_KEY_DEFAULT:u16 = 11;
134// const NL80211_ATTR_BEACON_INTERVAL:u16 = 12;
135// const NL80211_ATTR_DTIM_PERIOD:u16 = 13;
136// const NL80211_ATTR_BEACON_HEAD:u16 = 14;
137// const NL80211_ATTR_BEACON_TAIL:u16 = 15;
138// const NL80211_ATTR_STA_AID:u16 = 16;
139// const NL80211_ATTR_STA_FLAGS:u16 = 17;
140// const NL80211_ATTR_STA_LISTEN_INTERVAL:u16 = 18;
141// const NL80211_ATTR_STA_SUPPORTED_RATES:u16 = 19;
142// const NL80211_ATTR_STA_VLAN:u16 = 20;
143const NL80211_ATTR_STA_INFO: u16 = 21;
144const NL80211_ATTR_WIPHY_BANDS: u16 = 22;
145// const NL80211_ATTR_MNTR_FLAGS:u16 = 23;
146// const NL80211_ATTR_MESH_ID:u16 = 24;
147// const NL80211_ATTR_STA_PLINK_ACTION:u16 = 25;
148// const NL80211_ATTR_MPATH_NEXT_HOP:u16 = 26;
149// const NL80211_ATTR_MPATH_INFO:u16 = 27;
150// const NL80211_ATTR_BSS_CTS_PROT:u16 = 28;
151// const NL80211_ATTR_BSS_SHORT_PREAMBLE:u16 = 29;
152// const NL80211_ATTR_BSS_SHORT_SLOT_TIME:u16 = 30;
153// const NL80211_ATTR_HT_CAPABILITY:u16 = 31;
154const NL80211_ATTR_SUPPORTED_IFTYPES: u16 = 32;
155// const NL80211_ATTR_REG_ALPHA2:u16 = 33;
156// const NL80211_ATTR_REG_RULES:u16 = 34;
157// const NL80211_ATTR_MESH_CONFIG:u16 = 35;
158// const NL80211_ATTR_BSS_BASIC_RATES:u16 = 36;
159// const NL80211_ATTR_WIPHY_TXQ_PARAMS:u16 = 37;
160const NL80211_ATTR_WIPHY_FREQ: u16 = 38;
161const NL80211_ATTR_WIPHY_CHANNEL_TYPE: u16 = 39;
162// const NL80211_ATTR_KEY_DEFAULT_MGMT:u16 = 40;
163// const NL80211_ATTR_MGMT_SUBTYPE:u16 = 41;
164// const NL80211_ATTR_IE:u16 = 42;
165const NL80211_ATTR_MAX_NUM_SCAN_SSIDS: u16 = 43;
166const NL80211_ATTR_SCAN_FREQUENCIES: u16 = 44;
167const NL80211_ATTR_SCAN_SSIDS: u16 = 45;
168const NL80211_ATTR_GENERATION: u16 = 46;
169const NL80211_ATTR_BSS: u16 = 47;
170// const NL80211_ATTR_REG_INITIATOR:u16 = 48;
171// const NL80211_ATTR_REG_TYPE:u16 = 49;
172const NL80211_ATTR_SUPPORTED_COMMANDS: u16 = 50;
173// const NL80211_ATTR_FRAME:u16 = 51;
174const NL80211_ATTR_SSID: u16 = 52;
175// const NL80211_ATTR_AUTH_TYPE:u16 = 53;
176// const NL80211_ATTR_REASON_CODE:u16 = 54;
177// const NL80211_ATTR_KEY_TYPE:u16 = 55;
178const NL80211_ATTR_MAX_SCAN_IE_LEN: u16 = 56;
179const NL80211_ATTR_CIPHER_SUITES: u16 = 57;
180// const NL80211_ATTR_FREQ_BEFORE:u16 = 58;
181// const NL80211_ATTR_FREQ_AFTER:u16 = 59;
182// const NL80211_ATTR_FREQ_FIXED:u16 = 60;
183const NL80211_ATTR_WIPHY_RETRY_SHORT: u16 = 61;
184const NL80211_ATTR_WIPHY_RETRY_LONG: u16 = 62;
185const NL80211_ATTR_WIPHY_FRAG_THRESHOLD: u16 = 63;
186const NL80211_ATTR_WIPHY_RTS_THRESHOLD: u16 = 64;
187// const NL80211_ATTR_TIMED_OUT:u16 = 65;
188// const NL80211_ATTR_USE_MFP:u16 = 66;
189// const NL80211_ATTR_STA_FLAGS2:u16 = 67;
190// const NL80211_ATTR_CONTROL_PORT:u16 = 68;
191// const NL80211_ATTR_TESTDATA:u16 = 69;
192// const NL80211_ATTR_PRIVACY:u16 = 70;
193// const NL80211_ATTR_DISCONNECTED_BY_AP:u16 = 71;
194// const NL80211_ATTR_STATUS_CODE:u16 = 72;
195// const NL80211_ATTR_CIPHER_SUITES_PAIRWISE:u16 = 73;
196// const NL80211_ATTR_CIPHER_SUITE_GROUP:u16 = 74;
197// const NL80211_ATTR_WPA_VERSIONS:u16 = 75;
198// const NL80211_ATTR_AKM_SUITES:u16 = 76;
199// const NL80211_ATTR_REQ_IE:u16 = 77;
200// const NL80211_ATTR_RESP_IE:u16 = 78;
201// const NL80211_ATTR_PREV_BSSID:u16 = 79;
202// const NL80211_ATTR_KEY:u16 = 80;
203// const NL80211_ATTR_KEYS:u16 = 81;
204// const NL80211_ATTR_PID:u16 = 82;
205const NL80211_ATTR_4ADDR: u16 = 83;
206const NL80211_ATTR_SURVEY_INFO: u16 = 84;
207// const NL80211_ATTR_PMKID:u16 = 85;
208const NL80211_ATTR_MAX_NUM_PMKIDS: u16 = 86;
209// const NL80211_ATTR_DURATION:u16 = 87;
210// const NL80211_ATTR_COOKIE:u16 = 88;
211const NL80211_ATTR_WIPHY_COVERAGE_CLASS: u16 = 89;
212// const NL80211_ATTR_TX_RATES:u16 = 90;
213// const NL80211_ATTR_FRAME_MATCH:u16 = 91;
214// const NL80211_ATTR_ACK:u16 = 92;
215// const NL80211_ATTR_PS_STATE:u16 = 93;
216// const NL80211_ATTR_CQM:u16 = 94;
217// const NL80211_ATTR_LOCAL_STATE_CHANGE:u16 = 95;
218// const NL80211_ATTR_AP_ISOLATE:u16 = 96;
219// const NL80211_ATTR_WIPHY_TX_POWER_SETTING:u16 = 97;
220const NL80211_ATTR_WIPHY_TX_POWER_LEVEL: u16 = 98;
221const NL80211_ATTR_TX_FRAME_TYPES: u16 = 99;
222const NL80211_ATTR_RX_FRAME_TYPES: u16 = 100;
223// Covered by frame_type.rs
224// const NL80211_ATTR_FRAME_TYPE:u16 = 101;
225const NL80211_ATTR_CONTROL_PORT_ETHERTYPE: u16 = 102;
226// const NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT:u16 = 103;
227const NL80211_ATTR_SUPPORT_IBSS_RSN: u16 = 104;
228const NL80211_ATTR_WIPHY_ANTENNA_TX: u16 = 105;
229const NL80211_ATTR_WIPHY_ANTENNA_RX: u16 = 106;
230// const NL80211_ATTR_MCAST_RATE:u16 = 107;
231const NL80211_ATTR_OFFCHANNEL_TX_OK: u16 = 108;
232// const NL80211_ATTR_BSS_HT_OPMODE:u16 = 109;
233// const NL80211_ATTR_KEY_DEFAULT_TYPES:u16 = 110;
234const NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: u16 = 111;
235// const NL80211_ATTR_MESH_SETUP:u16 = 112;
236const NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: u16 = 113;
237const NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: u16 = 114;
238const NL80211_ATTR_SUPPORT_MESH_AUTH: u16 = 115;
239// const NL80211_ATTR_STA_PLINK_STATE:u16 = 116;
240// const NL80211_ATTR_WOWLAN_TRIGGERS:u16 = 117;
241const NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: u16 = 118;
242const NL80211_ATTR_SCHED_SCAN_INTERVAL: u16 = 119;
243const NL80211_ATTR_INTERFACE_COMBINATIONS: u16 = 120;
244const NL80211_ATTR_SOFTWARE_IFTYPES: u16 = 121;
245// const NL80211_ATTR_REKEY_DATA:u16 = 122;
246const NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: u16 = 123;
247const NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: u16 = 124;
248// const NL80211_ATTR_SCAN_SUPP_RATES:u16 = 125;
249// const NL80211_ATTR_HIDDEN_SSID:u16 = 126;
250// const NL80211_ATTR_IE_PROBE_RESP:u16 = 127;
251// const NL80211_ATTR_IE_ASSOC_RESP:u16 = 128;
252// const NL80211_ATTR_STA_WME:u16 = 129;
253const NL80211_ATTR_SUPPORT_AP_UAPSD: u16 = 130;
254const NL80211_ATTR_ROAM_SUPPORT: u16 = 131;
255const NL80211_ATTR_SCHED_SCAN_MATCH: u16 = 132;
256const NL80211_ATTR_MAX_MATCH_SETS: u16 = 133;
257// const NL80211_ATTR_PMKSA_CANDIDATE:u16 = 134;
258// const NL80211_ATTR_TX_NO_CCK_RATE:u16 = 135;
259// const NL80211_ATTR_TDLS_ACTION:u16 = 136;
260// const NL80211_ATTR_TDLS_DIALOG_TOKEN:u16 = 137;
261// const NL80211_ATTR_TDLS_OPERATION:u16 = 138;
262const NL80211_ATTR_TDLS_SUPPORT: u16 = 139;
263const NL80211_ATTR_TDLS_EXTERNAL_SETUP: u16 = 140;
264// const NL80211_ATTR_DEVICE_AP_SME:u16 = 141;
265// const NL80211_ATTR_DONT_WAIT_FOR_ACK:u16 = 142;
266const NL80211_ATTR_FEATURE_FLAGS: u16 = 143;
267const NL80211_ATTR_PROBE_RESP_OFFLOAD: u16 = 144;
268// const NL80211_ATTR_PROBE_RESP:u16 = 145;
269// const NL80211_ATTR_DFS_REGION:u16 = 146;
270// const NL80211_ATTR_DISABLE_HT:u16 = 147;
271const NL80211_ATTR_HT_CAPABILITY_MASK: u16 = 148;
272// const NL80211_ATTR_NOACK_MAP:u16 = 149;
273// const NL80211_ATTR_INACTIVITY_TIMEOUT:u16 = 150;
274// const NL80211_ATTR_RX_SIGNAL_DBM:u16 = 151;
275// const NL80211_ATTR_BG_SCAN_PERIOD:u16 = 152;
276const NL80211_ATTR_WDEV: u16 = 153;
277// const NL80211_ATTR_USER_REG_HINT_TYPE:u16 = 154;
278// const NL80211_ATTR_CONN_FAILED_REASON:u16 = 155;
279// const NL80211_ATTR_AUTH_DATA:u16 = 156;
280const NL80211_ATTR_VHT_CAPABILITY: u16 = 157;
281const NL80211_ATTR_SCAN_FLAGS: u16 = 158;
282const NL80211_ATTR_CHANNEL_WIDTH: u16 = 159;
283const NL80211_ATTR_CENTER_FREQ1: u16 = 160;
284const NL80211_ATTR_CENTER_FREQ2: u16 = 161;
285// const NL80211_ATTR_P2P_CTWINDOW:u16 = 162;
286// const NL80211_ATTR_P2P_OPPPS:u16 = 163;
287// const NL80211_ATTR_LOCAL_MESH_POWER_MODE:u16 = 164;
288// const NL80211_ATTR_ACL_POLICY:u16 = 165;
289const NL80211_ATTR_MAC_ADDRS: u16 = 166;
290// const NL80211_ATTR_MAC_ACL_MAX:u16 = 167;
291// const NL80211_ATTR_RADAR_EVENT:u16 = 168;
292const NL80211_ATTR_EXT_CAPA: u16 = 169;
293const NL80211_ATTR_EXT_CAPA_MASK: u16 = 170;
294// const NL80211_ATTR_STA_CAPABILITY:u16 = 171;
295// const NL80211_ATTR_STA_EXT_CAPABILITY:u16 = 172;
296// const NL80211_ATTR_PROTOCOL_FEATURES:u16 = 173;
297const NL80211_ATTR_SPLIT_WIPHY_DUMP: u16 = 174;
298// const NL80211_ATTR_DISABLE_VHT:u16 = 175;
299const NL80211_ATTR_VHT_CAPABILITY_MASK: u16 = 176;
300// const NL80211_ATTR_MDID:u16 = 177;
301// const NL80211_ATTR_IE_RIC:u16 = 178;
302// const NL80211_ATTR_CRIT_PROT_ID:u16 = 179;
303// const NL80211_ATTR_MAX_CRIT_PROT_DURATION:u16 = 180;
304// const NL80211_ATTR_PEER_AID:u16 = 181;
305// const NL80211_ATTR_COALESCE_RULE:u16 = 182;
306// const NL80211_ATTR_CH_SWITCH_COUNT:u16 = 183;
307// const NL80211_ATTR_CH_SWITCH_BLOCK_TX:u16 = 184;
308// const NL80211_ATTR_CSA_IES:u16 = 185;
309// const NL80211_ATTR_CNTDWN_OFFS_BEACON:u16 = 186;
310// const NL80211_ATTR_CNTDWN_OFFS_PRESP:u16 = 187;
311// const NL80211_ATTR_RXMGMT_FLAGS:u16 = 188;
312// const NL80211_ATTR_STA_SUPPORTED_CHANNELS:u16 = 189;
313// const NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES:u16 = 190;
314// const NL80211_ATTR_HANDLE_DFS:u16 = 191;
315// const NL80211_ATTR_SUPPORT_5_MHZ:u16 = 192;
316// const NL80211_ATTR_SUPPORT_10_MHZ:u16 = 193;
317// const NL80211_ATTR_OPMODE_NOTIF:u16 = 194;
318// const NL80211_ATTR_VENDOR_ID:u16 = 195;
319// const NL80211_ATTR_VENDOR_SUBCMD:u16 = 196;
320// const NL80211_ATTR_VENDOR_DATA:u16 = 197;
321// const NL80211_ATTR_VENDOR_EVENTS:u16 = 198;
322// const NL80211_ATTR_QOS_MAP:u16 = 199;
323// const NL80211_ATTR_MAC_HINT:u16 = 200;
324// const NL80211_ATTR_WIPHY_FREQ_HINT:u16 = 201;
325// const NL80211_ATTR_MAX_AP_ASSOC_STA:u16 = 202;
326// const NL80211_ATTR_TDLS_PEER_CAPABILITY:u16 = 203;
327// const NL80211_ATTR_SOCKET_OWNER:u16 = 204;
328// const NL80211_ATTR_CSA_C_OFFSETS_TX:u16 = 205;
329const NL80211_ATTR_MAX_CSA_COUNTERS: u16 = 206;
330// const NL80211_ATTR_TDLS_INITIATOR:u16 = 207;
331// const NL80211_ATTR_USE_RRM:u16 = 208;
332// const NL80211_ATTR_WIPHY_DYN_ACK:u16 = 209;
333// const NL80211_ATTR_TSID:u16 = 210;
334// const NL80211_ATTR_USER_PRIO:u16 = 211;
335// const NL80211_ATTR_ADMITTED_TIME:u16 = 212;
336// const NL80211_ATTR_SMPS_MODE:u16 = 213;
337// const NL80211_ATTR_OPER_CLASS:u16 = 214;
338const NL80211_ATTR_MAC_MASK: u16 = 215;
339const NL80211_ATTR_WIPHY_SELF_MANAGED_REG: u16 = 216;
340const NL80211_ATTR_EXT_FEATURES: u16 = 217;
341const NL80211_ATTR_SURVEY_RADIO_STATS: u16 = 218;
342// const NL80211_ATTR_NETNS_FD:u16 = 219;
343const NL80211_ATTR_SCHED_SCAN_DELAY: u16 = 220;
344// const NL80211_ATTR_REG_INDOOR:u16 = 221;
345const NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS: u16 = 222;
346const NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL: u16 = 223;
347const NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS: u16 = 224;
348const NL80211_ATTR_SCHED_SCAN_PLANS: u16 = 225;
349// const NL80211_ATTR_PBSS:u16 = 226;
350// const NL80211_ATTR_BSS_SELECT:u16 = 227;
351// const NL80211_ATTR_STA_SUPPORT_P2P_PS:u16 = 228;
352// const NL80211_ATTR_PAD:u16 = 229;
353const NL80211_ATTR_IFTYPE_EXT_CAPA: u16 = 230;
354// const NL80211_ATTR_MU_MIMO_GROUP_DATA:u16 = 231;
355// const NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR:u16 = 232;
356// const NL80211_ATTR_SCAN_START_TIME_TSF:u16 = 233;
357// const NL80211_ATTR_SCAN_START_TIME_TSF_BSSID:u16 = 234;
358const NL80211_ATTR_MEASUREMENT_DURATION: u16 = 235;
359// const NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY:u16 = 236;
360// const NL80211_ATTR_MESH_PEER_AID:u16 = 237;
361// const NL80211_ATTR_NAN_MASTER_PREF:u16 = 238;
362const NL80211_ATTR_BANDS: u16 = 239;
363// const NL80211_ATTR_NAN_FUNC:u16 = 240;
364// const NL80211_ATTR_NAN_MATCH:u16 = 241;
365// const NL80211_ATTR_FILS_KEK:u16 = 242;
366// const NL80211_ATTR_FILS_NONCES:u16 = 243;
367// const NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED:u16 = 244;
368// const NL80211_ATTR_BSSID:u16 = 245;
369// const NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI:u16 = 246;
370// const NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST:u16 = 247;
371// const NL80211_ATTR_TIMEOUT_REASON:u16 = 248;
372// const NL80211_ATTR_FILS_ERP_USERNAME:u16 = 249;
373// const NL80211_ATTR_FILS_ERP_REALM:u16 = 250;
374// const NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM:u16 = 251;
375// const NL80211_ATTR_FILS_ERP_RRK:u16 = 252;
376// const NL80211_ATTR_FILS_CACHE_ID:u16 = 253;
377// const NL80211_ATTR_PMK:u16 = 254;
378// const NL80211_ATTR_SCHED_SCAN_MULTI:u16 = 255;
379const NL80211_ATTR_SCHED_SCAN_MAX_REQS: u16 = 256;
380// const NL80211_ATTR_WANT_1X_4WAY_HS:u16 = 257;
381// const NL80211_ATTR_PMKR0_NAME:u16 = 258;
382// const NL80211_ATTR_PORT_AUTHORIZED:u16 = 259;
383// const NL80211_ATTR_EXTERNAL_AUTH_ACTION:u16 = 260;
384// const NL80211_ATTR_EXTERNAL_AUTH_SUPPORT:u16 = 261;
385// const NL80211_ATTR_NSS:u16 = 262;
386// const NL80211_ATTR_ACK_SIGNAL:u16 = 263;
387// const NL80211_ATTR_CONTROL_PORT_OVER_NL80211:u16 = 264;
388const NL80211_ATTR_TXQ_STATS: u16 = 265;
389const NL80211_ATTR_TXQ_LIMIT: u16 = 266;
390const NL80211_ATTR_TXQ_MEMORY_LIMIT: u16 = 267;
391const NL80211_ATTR_TXQ_QUANTUM: u16 = 268;
392// const NL80211_ATTR_HE_CAPABILITY:u16 = 269;
393// const NL80211_ATTR_FTM_RESPONDER:u16 = 270;
394// const NL80211_ATTR_FTM_RESPONDER_STATS:u16 = 271;
395// const NL80211_ATTR_TIMEOUT:u16 = 272;
396// const NL80211_ATTR_PEER_MEASUREMENTS:u16 = 273;
397// const NL80211_ATTR_AIRTIME_WEIGHT:u16 = 274;
398// const NL80211_ATTR_STA_TX_POWER_SETTING:u16 = 275;
399// const NL80211_ATTR_STA_TX_POWER:u16 = 276;
400// const NL80211_ATTR_SAE_PASSWORD:u16 = 277;
401// const NL80211_ATTR_TWT_RESPONDER:u16 = 278;
402// const NL80211_ATTR_HE_OBSS_PD:u16 = 279;
403// const NL80211_ATTR_WIPHY_EDMG_CHANNELS:u16 = 280;
404// const NL80211_ATTR_WIPHY_EDMG_BW_CONFIG:u16 = 281;
405// const NL80211_ATTR_VLAN_ID:u16 = 282;
406// const NL80211_ATTR_HE_BSS_COLOR:u16 = 283;
407// const NL80211_ATTR_IFTYPE_AKM_SUITES:u16 = 284;
408// const NL80211_ATTR_TID_CONFIG:u16 = 285;
409// const NL80211_ATTR_CONTROL_PORT_NO_PREAUTH:u16 = 286;
410// const NL80211_ATTR_PMK_LIFETIME:u16 = 287;
411// const NL80211_ATTR_PMK_REAUTH_THRESHOLD:u16 = 288;
412// const NL80211_ATTR_RECEIVE_MULTICAST:u16 = 289;
413const NL80211_ATTR_WIPHY_FREQ_OFFSET: u16 = 290;
414// const NL80211_ATTR_CENTER_FREQ1_OFFSET:u16 = 291;
415// const NL80211_ATTR_SCAN_FREQ_KHZ:u16 = 292;
416// const NL80211_ATTR_HE_6GHZ_CAPABILITY:u16 = 293;
417// const NL80211_ATTR_FILS_DISCOVERY:u16 = 294;
418// const NL80211_ATTR_UNSOL_BCAST_PROBE_RESP:u16 = 295;
419// const NL80211_ATTR_S1G_CAPABILITY:u16 = 296;
420// const NL80211_ATTR_S1G_CAPABILITY_MASK:u16 = 297;
421// const NL80211_ATTR_SAE_PWE:u16 = 298;
422// const NL80211_ATTR_RECONNECT_REQUESTED:u16 = 299;
423// const NL80211_ATTR_SAR_SPEC:u16 = 300;
424// const NL80211_ATTR_DISABLE_HE:u16 = 301;
425// const NL80211_ATTR_OBSS_COLOR_BITMAP:u16 = 302;
426// const NL80211_ATTR_COLOR_CHANGE_COUNT:u16 = 303;
427// const NL80211_ATTR_COLOR_CHANGE_COLOR:u16 = 304;
428// const NL80211_ATTR_COLOR_CHANGE_ELEMS:u16 = 305;
429// const NL80211_ATTR_MBSSID_CONFIG:u16 = 306;
430// const NL80211_ATTR_MBSSID_ELEMS:u16 = 307;
431// const NL80211_ATTR_RADAR_BACKGROUND:u16 = 308;
432// const NL80211_ATTR_AP_SETTINGS_FLAGS:u16 = 309;
433// const NL80211_ATTR_EHT_CAPABILITY:u16 = 310;
434// const NL80211_ATTR_DISABLE_EHT:u16 = 311;
435const NL80211_ATTR_MLO_LINKS: u16 = 312;
436// Covered in mlo.rs
437// const NL80211_ATTR_MLO_LINK_ID: u16 = 313;
438// const NL80211_ATTR_MLD_ADDR:u16 = 314;
439// const NL80211_ATTR_MLO_SUPPORT:u16 = 315;
440const NL80211_ATTR_MAX_NUM_AKM_SUITES: u16 = 316;
441const NL80211_ATTR_EML_CAPABILITY: u16 = 317;
442const NL80211_ATTR_MLD_CAPA_AND_OPS: u16 = 318;
443// const NL80211_ATTR_TX_HW_TIMESTAMP:u16 = 319;
444// const NL80211_ATTR_RX_HW_TIMESTAMP:u16 = 320;
445// const NL80211_ATTR_TD_BITMAP:u16 = 321;
446// const NL80211_ATTR_PUNCT_BITMAP:u16 = 322;
447const NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS: u16 = 323;
448// const NL80211_ATTR_HW_TIMESTAMP_ENABLED:u16 = 324;
449// const NL80211_ATTR_EMA_RNR_ELEMS:u16 = 325;
450// const NL80211_ATTR_MLO_LINK_DISABLED:u16 = 326;
451// const NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA:u16 = 327;
452// const NL80211_ATTR_MLO_TTLM_DLINK:u16 = 328;
453// const NL80211_ATTR_MLO_TTLM_ULINK:u16 = 329;
454// const NL80211_ATTR_ASSOC_SPP_AMSDU:u16 = 330;
455// const NL80211_ATTR_WIPHY_RADIOS:u16 = 331;
456// const NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS:u16 = 332;
457
458#[derive(Debug, PartialEq, Eq, Clone)]
459#[non_exhaustive]
460pub enum Nl80211Attr {
461    Wiphy(u32),
462    WiphyName(String),
463    IfIndex(u32),
464    IfName(String),
465    IfType(Nl80211InterfaceType),
466    IfTypeExtCap(Vec<Nl80211IfTypeExtCapa>),
467    Mac([u8; ETH_ALEN]),
468    MacMask([u8; ETH_ALEN]),
469    MacAddrs(Vec<[u8; ETH_ALEN]>),
470    Wdev(u64),
471    Generation(u32),
472    Use4Addr(bool),
473    WiphyFreq(u32),
474    WiphyFreqOffset(u32),
475    WiphyChannelType(Nl80211HtWiphyChannelType),
476    ChannelWidth(Nl80211ChannelWidth),
477    CenterFreq1(u32),
478    CenterFreq2(u32),
479    WiphyTxPowerLevel(u32),
480    Ssid(String),
481    StationInfo(Vec<Nl80211StationInfo>),
482    SurveyInfo(Vec<Nl80211SurveyInfo>),
483    TransmitQueueStats(Vec<Nl80211TransmitQueueStat>),
484    TransmitQueueLimit(u32),
485    TransmitQueueMemoryLimit(u32),
486    TransmitQueueQuantum(u32),
487    MloLinks(Vec<Nl80211MloLink>),
488    WiphyRetryShort(u8),
489    WiphyRetryLong(u8),
490    WiphyFragThreshold(u32),
491    WiphyRtsThreshold(u32),
492    WiphyCoverageClass(u8),
493    MaxNumScanSsids(u8),
494    MaxNumSchedScanSsids(u8),
495    MaxScanIeLen(u16),
496    MaxSchedScanIeLen(u16),
497    MaxMatchSets(u8),
498    SupportIbssRsn,
499    SupportMeshAuth,
500    SupportApUapsd,
501    RoamSupport,
502    TdlsSupport,
503    TdlsExternalSetup,
504    CipherSuites(Vec<Nl80211CipherSuit>),
505    MaxNumPmkids(u8),
506    ControlPortEthertype,
507    WiphyAntennaAvailTx(u32),
508    WiphyAntennaAvailRx(u32),
509    ApProbeRespOffload(u32),
510    WiphyAntennaTx(u32),
511    WiphyAntennaRx(u32),
512    SupportedIftypes(Vec<Nl80211IfMode>),
513    WiphyBands(Vec<Nl80211Band>),
514    /// flag attribute, indicate userspace supports
515    /// receiving the data for a single wiphy split across multiple
516    /// messages, given with wiphy dump message
517    SplitWiphyDump,
518    SupportedCommand(Vec<Nl80211Command>),
519    /// in milliseconds
520    MaxRemainOnChannelDuration(u32),
521    OffchannelTxOk,
522    SurveyRadioStats,
523    WowlanTriggersSupport(Vec<Nl80211WowlanTriggersSupport>),
524    SoftwareIftypes(Vec<Nl80211InterfaceType>),
525    Features(Nl80211Features),
526    ExtFeatures(Vec<Nl80211ExtFeature>),
527    InterfaceCombination(Vec<Nl80211IfaceComb>),
528    HtCapabilityMask(Nl80211HtCapabilityMask),
529    TxFrameTypes(Vec<Nl80211IfaceFrameType>),
530    RxFrameTypes(Vec<Nl80211IfaceFrameType>),
531    MaxNumSchedScanPlans(u32),
532    MaxScanPlanInterval(u32),
533    MaxScanPlanIterations(u32),
534    ExtCap(Nl80211ExtendedCapability),
535    ExtCapMask(Nl80211ExtendedCapability),
536    VhtCap(Nl80211VhtCapability),
537    VhtCapMask(Nl80211VhtCapability),
538    MaxCsaCounters(u8),
539    WiphySelfManagedReg,
540    SchedScanMaxReqs(u32),
541    EmlCapability(u16),
542    MldCapaAndOps(u16),
543    Bands(Nl80211BandTypes),
544    /// Maximum number of AKM suites allowed for connect command.
545    MaxNumAkmSuites(u16),
546    /// Maximum number of peers that HW timestamping can be enabled for
547    /// concurrently. A value of 0xffff indicates setting for all peers(i.e.
548    /// not specifying an address with set hardware timestamp) is
549    /// supported.
550    MaxHwTimestampPeers(u16),
551    /// Basic Service Set (BSS)
552    Bss(Vec<Nl80211BssInfo>),
553    ScanSsids(Vec<String>),
554    ScanFlags(Nl80211ScanFlags),
555    MeasurementDuration(u16),
556    /// Scan interval in millisecond(ms)
557    SchedScanInterval(u32),
558    /// Delay before the first cycle of a scheduled scan is started.  Or the
559    /// delay before a WoWLAN net-detect scan is started, counting from the
560    /// moment the system is suspended. This value is in seconds.
561    SchedScanDelay(u32),
562    /// Scan frequencies in MHz.
563    ScanFrequencies(Vec<u32>),
564    /// Sets of attributes to match during scheduled scans. Only BSSs
565    /// that match any of the sets will be reported. These are pass-thru
566    /// filter rules. For a match to succeed, the BSS must match all
567    /// attributes of a set. Since not every hardware supports matching all
568    /// types of attributes, there is no guarantee that the reported BSSs are
569    /// fully complying with the match sets and userspace needs to be able to
570    /// ignore them by itself. Thus, the implementation is somewhat
571    /// hardware-dependent, but this is only an optimization and the userspace
572    /// application needs to handle all the non-filtered results anyway.
573    SchedScanMatch(Vec<Nl80211SchedScanMatch>),
574    /// A list of scan plans for scheduled scan. Each scan plan defines the
575    /// number of scan iterations and the interval between scans. The last scan
576    /// plan will always run infinitely, thus it must not specify the number of
577    /// iterations, only the interval between scans. The scan plans are
578    /// executed sequentially.
579    SchedScanPlans(Vec<Nl80211SchedScanPlan>),
580    Other(DefaultNla),
581}
582
583impl Nla for Nl80211Attr {
584    fn value_len(&self) -> usize {
585        match self {
586            Self::IfIndex(_)
587            | Self::Wiphy(_)
588            | Self::IfType(_)
589            | Self::Generation(_)
590            | Self::WiphyFreq(_)
591            | Self::WiphyFreqOffset(_)
592            | Self::WiphyChannelType(_)
593            | Self::CenterFreq1(_)
594            | Self::CenterFreq2(_)
595            | Self::WiphyTxPowerLevel(_)
596            | Self::ChannelWidth(_)
597            | Self::WiphyFragThreshold(_)
598            | Self::WiphyRtsThreshold(_)
599            | Self::WiphyAntennaAvailTx(_)
600            | Self::WiphyAntennaAvailRx(_)
601            | Self::ApProbeRespOffload(_)
602            | Self::WiphyAntennaTx(_)
603            | Self::WiphyAntennaRx(_)
604            | Self::MaxNumSchedScanPlans(_)
605            | Self::MaxScanPlanInterval(_)
606            | Self::MaxScanPlanIterations(_)
607            | Self::SchedScanMaxReqs(_)
608            | Self::TransmitQueueLimit(_)
609            | Self::TransmitQueueMemoryLimit(_)
610            | Self::TransmitQueueQuantum(_)
611            | Self::SchedScanInterval(_)
612            | Self::SchedScanDelay(_) => 4,
613            Self::Wdev(_) => 8,
614            Self::IfName(s) | Self::Ssid(s) | Self::WiphyName(s) => s.len() + 1,
615            Self::Mac(_) | Self::MacMask(_) => ETH_ALEN,
616            Self::MacAddrs(s) => {
617                MacAddressNlas::from(s).as_slice().buffer_len()
618            }
619            Self::Use4Addr(_) => 1,
620            Self::WiphyRetryShort(_)
621            | Self::WiphyRetryLong(_)
622            | Self::WiphyCoverageClass(_)
623            | Self::MaxNumScanSsids(_)
624            | Self::MaxNumSchedScanSsids(_)
625            | Self::MaxMatchSets(_)
626            | Self::MaxNumPmkids(_) => 1,
627            Self::TransmitQueueStats(nlas) => nlas.as_slice().buffer_len(),
628            Self::StationInfo(nlas) => nlas.as_slice().buffer_len(),
629            Self::SurveyInfo(nlas) => nlas.as_slice().buffer_len(),
630            Self::MloLinks(links) => links.as_slice().buffer_len(),
631            Self::MaxScanIeLen(_) | Self::MaxSchedScanIeLen(_) => 2,
632            Self::SupportIbssRsn
633            | Self::SupportMeshAuth
634            | Self::SupportApUapsd
635            | Self::RoamSupport
636            | Self::TdlsSupport
637            | Self::TdlsExternalSetup
638            | Self::ControlPortEthertype
639            | Self::OffchannelTxOk
640            | Self::SurveyRadioStats
641            | Self::WiphySelfManagedReg => 0,
642            Self::CipherSuites(s) => 4 * s.len(),
643            Self::SupportedIftypes(s) => s.as_slice().buffer_len(),
644            Self::WiphyBands(s) => s.as_slice().buffer_len(),
645            Self::SplitWiphyDump => 0,
646            Self::SupportedCommand(s) => {
647                Nl80211Commands::from(s).as_slice().buffer_len()
648            }
649            Self::MaxRemainOnChannelDuration(_) => 4,
650            Self::WowlanTriggersSupport(s) => s.as_slice().buffer_len(),
651            Self::SoftwareIftypes(s) => {
652                Nl80211InterfaceTypes::from(s).as_slice().buffer_len()
653            }
654            Self::Features(_) => 4,
655            Self::ExtFeatures(_) => Nl80211ExtFeatures::LENGTH,
656            Self::InterfaceCombination(s) => s.as_slice().buffer_len(),
657            Self::HtCapabilityMask(_) => Nl80211HtCapabilityMask::LENGTH,
658            Self::TxFrameTypes(s) => s.as_slice().buffer_len(),
659            Self::RxFrameTypes(s) => s.as_slice().buffer_len(),
660            Self::ExtCap(v) => v.len(),
661            Self::ExtCapMask(v) => v.len(),
662            Self::VhtCap(v) => v.buffer_len(),
663            Self::VhtCapMask(v) => v.buffer_len(),
664            Self::MaxCsaCounters(_) => 1,
665            Self::IfTypeExtCap(s) => {
666                Nl80211IfTypeExtCapas::from(s).as_slice().buffer_len()
667            }
668            Self::EmlCapability(_)
669            | Self::MldCapaAndOps(_)
670            | Self::MaxNumAkmSuites(_)
671            | Self::MaxHwTimestampPeers(_)
672            | Self::MeasurementDuration(_) => 2,
673            Self::Bands(_) => Nl80211BandTypes::LENGTH,
674            Self::Bss(v) => v.as_slice().buffer_len(),
675            Self::ScanSsids(v) => {
676                Nla80211ScanSsidNlas::from(v).as_slice().buffer_len()
677            }
678            Self::ScanFlags(v) => v.buffer_len(),
679            Self::ScanFrequencies(v) => {
680                Nla80211ScanFreqNlas::from(v).as_slice().buffer_len()
681            }
682            Self::SchedScanMatch(v) => v.as_slice().buffer_len(),
683            Self::SchedScanPlans(v) => v.as_slice().buffer_len(),
684            Self::Other(attr) => attr.value_len(),
685        }
686    }
687
688    fn kind(&self) -> u16 {
689        match self {
690            Self::Wiphy(_) => NL80211_ATTR_WIPHY,
691            Self::WiphyName(_) => NL80211_ATTR_WIPHY_NAME,
692            Self::IfIndex(_) => NL80211_ATTR_IFINDEX,
693            Self::IfName(_) => NL80211_ATTR_IFNAME,
694            Self::IfType(_) => NL80211_ATTR_IFTYPE,
695            Self::Mac(_) => NL80211_ATTR_MAC,
696            Self::MacMask(_) => NL80211_ATTR_MAC_MASK,
697            Self::MacAddrs(_) => NL80211_ATTR_MAC_ADDRS,
698            Self::Wdev(_) => NL80211_ATTR_WDEV,
699            Self::Generation(_) => NL80211_ATTR_GENERATION,
700            Self::Use4Addr(_) => NL80211_ATTR_4ADDR,
701            Self::WiphyFreq(_) => NL80211_ATTR_WIPHY_FREQ,
702            Self::WiphyFreqOffset(_) => NL80211_ATTR_WIPHY_FREQ_OFFSET,
703            Self::WiphyChannelType(_) => NL80211_ATTR_WIPHY_CHANNEL_TYPE,
704            Self::ChannelWidth(_) => NL80211_ATTR_CHANNEL_WIDTH,
705            Self::CenterFreq1(_) => NL80211_ATTR_CENTER_FREQ1,
706            Self::CenterFreq2(_) => NL80211_ATTR_CENTER_FREQ2,
707            Self::WiphyTxPowerLevel(_) => NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
708            Self::Ssid(_) => NL80211_ATTR_SSID,
709            Self::StationInfo(_) => NL80211_ATTR_STA_INFO,
710            Self::SurveyInfo(_) => NL80211_ATTR_SURVEY_INFO,
711            Self::SurveyRadioStats => NL80211_ATTR_SURVEY_RADIO_STATS,
712            Self::TransmitQueueStats(_) => NL80211_ATTR_TXQ_STATS,
713            Self::TransmitQueueLimit(_) => NL80211_ATTR_TXQ_LIMIT,
714            Self::TransmitQueueMemoryLimit(_) => NL80211_ATTR_TXQ_MEMORY_LIMIT,
715            Self::TransmitQueueQuantum(_) => NL80211_ATTR_TXQ_QUANTUM,
716            Self::MloLinks(_) => NL80211_ATTR_MLO_LINKS,
717            Self::WiphyRetryShort(_) => NL80211_ATTR_WIPHY_RETRY_SHORT,
718            Self::WiphyRetryLong(_) => NL80211_ATTR_WIPHY_RETRY_LONG,
719            Self::WiphyFragThreshold(_) => NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
720            Self::WiphyRtsThreshold(_) => NL80211_ATTR_WIPHY_RTS_THRESHOLD,
721            Self::WiphyCoverageClass(_) => NL80211_ATTR_WIPHY_COVERAGE_CLASS,
722            Self::MaxNumScanSsids(_) => NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
723            Self::MaxNumSchedScanSsids(_) => {
724                NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS
725            }
726            Self::MaxScanIeLen(_) => NL80211_ATTR_MAX_SCAN_IE_LEN,
727            Self::MaxSchedScanIeLen(_) => NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
728            Self::MaxMatchSets(_) => NL80211_ATTR_MAX_MATCH_SETS,
729            Self::SupportIbssRsn => NL80211_ATTR_SUPPORT_IBSS_RSN,
730            Self::SupportMeshAuth => NL80211_ATTR_SUPPORT_MESH_AUTH,
731            Self::SupportApUapsd => NL80211_ATTR_SUPPORT_AP_UAPSD,
732            Self::RoamSupport => NL80211_ATTR_ROAM_SUPPORT,
733            Self::TdlsSupport => NL80211_ATTR_TDLS_SUPPORT,
734            Self::TdlsExternalSetup => NL80211_ATTR_TDLS_EXTERNAL_SETUP,
735            Self::CipherSuites(_) => NL80211_ATTR_CIPHER_SUITES,
736            Self::MaxNumPmkids(_) => NL80211_ATTR_MAX_NUM_PMKIDS,
737            Self::ControlPortEthertype => NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
738            Self::WiphyAntennaAvailTx(_) => NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
739            Self::WiphyAntennaAvailRx(_) => NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
740            Self::ApProbeRespOffload(_) => NL80211_ATTR_PROBE_RESP_OFFLOAD,
741            Self::WiphyAntennaTx(_) => NL80211_ATTR_WIPHY_ANTENNA_TX,
742            Self::WiphyAntennaRx(_) => NL80211_ATTR_WIPHY_ANTENNA_RX,
743            Self::SupportedIftypes(_) => NL80211_ATTR_SUPPORTED_IFTYPES,
744            Self::WiphyBands(_) => NL80211_ATTR_WIPHY_BANDS,
745            Self::SplitWiphyDump => NL80211_ATTR_SPLIT_WIPHY_DUMP,
746            Self::SupportedCommand(_) => NL80211_ATTR_SUPPORTED_COMMANDS,
747            Self::MaxRemainOnChannelDuration(_) => {
748                NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION
749            }
750            Self::OffchannelTxOk => NL80211_ATTR_OFFCHANNEL_TX_OK,
751            Self::WowlanTriggersSupport(_) => {
752                NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED
753            }
754            Self::SoftwareIftypes(_) => NL80211_ATTR_SOFTWARE_IFTYPES,
755            Self::Features(_) => NL80211_ATTR_FEATURE_FLAGS,
756            Self::ExtFeatures(_) => NL80211_ATTR_EXT_FEATURES,
757            Self::InterfaceCombination(_) => {
758                NL80211_ATTR_INTERFACE_COMBINATIONS
759            }
760            Self::HtCapabilityMask(_) => NL80211_ATTR_HT_CAPABILITY_MASK,
761            Self::TxFrameTypes(_) => NL80211_ATTR_TX_FRAME_TYPES,
762            Self::RxFrameTypes(_) => NL80211_ATTR_RX_FRAME_TYPES,
763            Self::MaxNumSchedScanPlans(_) => {
764                NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS
765            }
766            Self::MaxScanPlanInterval(_) => NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
767            Self::MaxScanPlanIterations(_) => {
768                NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS
769            }
770            Self::ExtCap(_) => NL80211_ATTR_EXT_CAPA,
771            Self::ExtCapMask(_) => NL80211_ATTR_EXT_CAPA_MASK,
772            Self::VhtCap(_) => NL80211_ATTR_VHT_CAPABILITY,
773            Self::VhtCapMask(_) => NL80211_ATTR_VHT_CAPABILITY_MASK,
774            Self::MaxCsaCounters(_) => NL80211_ATTR_MAX_CSA_COUNTERS,
775            Self::WiphySelfManagedReg => NL80211_ATTR_WIPHY_SELF_MANAGED_REG,
776            Self::SchedScanMaxReqs(_) => NL80211_ATTR_SCHED_SCAN_MAX_REQS,
777            Self::IfTypeExtCap(_) => NL80211_ATTR_IFTYPE_EXT_CAPA,
778            Self::EmlCapability(_) => NL80211_ATTR_EML_CAPABILITY,
779            Self::MldCapaAndOps(_) => NL80211_ATTR_MLD_CAPA_AND_OPS,
780            Self::Bands(_) => NL80211_ATTR_BANDS,
781            Self::MaxNumAkmSuites(_) => NL80211_ATTR_MAX_NUM_AKM_SUITES,
782            Self::MaxHwTimestampPeers(_) => NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS,
783            Self::Bss(_) => NL80211_ATTR_BSS,
784            Self::ScanSsids(_) => NL80211_ATTR_SCAN_SSIDS,
785            Self::ScanFlags(_) => NL80211_ATTR_SCAN_FLAGS,
786            Self::MeasurementDuration(_) => NL80211_ATTR_MEASUREMENT_DURATION,
787            Self::SchedScanInterval(_) => NL80211_ATTR_SCHED_SCAN_INTERVAL,
788            Self::SchedScanDelay(_) => NL80211_ATTR_SCHED_SCAN_DELAY,
789            Self::ScanFrequencies(_) => NL80211_ATTR_SCAN_FREQUENCIES,
790            Self::SchedScanMatch(_) => NL80211_ATTR_SCHED_SCAN_MATCH,
791            Self::SchedScanPlans(_) => NL80211_ATTR_SCHED_SCAN_PLANS,
792            Self::Other(attr) => attr.kind(),
793        }
794    }
795
796    fn emit_value(&self, buffer: &mut [u8]) {
797        match self {
798            Self::IfIndex(d)
799            | Self::Wiphy(d)
800            | Self::Generation(d)
801            | Self::WiphyFreq(d)
802            | Self::WiphyFreqOffset(d)
803            | Self::CenterFreq1(d)
804            | Self::CenterFreq2(d)
805            | Self::WiphyTxPowerLevel(d)
806            | Self::WiphyFragThreshold(d)
807            | Self::WiphyRtsThreshold(d)
808            | Self::WiphyAntennaAvailTx(d)
809            | Self::WiphyAntennaAvailRx(d)
810            | Self::ApProbeRespOffload(d)
811            | Self::WiphyAntennaTx(d)
812            | Self::WiphyAntennaRx(d)
813            | Self::MaxNumSchedScanPlans(d)
814            | Self::MaxScanPlanInterval(d)
815            | Self::MaxScanPlanIterations(d)
816            | Self::SchedScanMaxReqs(d)
817            | Self::TransmitQueueLimit(d)
818            | Self::TransmitQueueMemoryLimit(d)
819            | Self::TransmitQueueQuantum(d)
820            | Self::SchedScanInterval(d)
821            | Self::SchedScanDelay(d) => write_u32(buffer, *d),
822            Self::MaxScanIeLen(d) | Self::MaxSchedScanIeLen(d) => {
823                write_u16(buffer, *d)
824            }
825            Self::Wdev(d) => write_u64(buffer, *d),
826            Self::IfType(d) => write_u32(buffer, (*d).into()),
827            Self::Mac(s) | Self::MacMask(s) => buffer.copy_from_slice(s),
828            Self::MacAddrs(s) => {
829                MacAddressNlas::from(s).as_slice().emit(buffer)
830            }
831            Self::IfName(s) | Self::Ssid(s) | Self::WiphyName(s) => {
832                buffer[..s.len()].copy_from_slice(s.as_bytes());
833                buffer[s.len()] = 0;
834            }
835            Self::Use4Addr(d) => buffer[0] = *d as u8,
836            Self::SupportIbssRsn
837            | Self::SupportMeshAuth
838            | Self::SupportApUapsd
839            | Self::RoamSupport
840            | Self::TdlsSupport
841            | Self::TdlsExternalSetup
842            | Self::ControlPortEthertype
843            | Self::OffchannelTxOk
844            | Self::SurveyRadioStats
845            | Self::WiphySelfManagedReg => (),
846            Self::WiphyChannelType(d) => write_u32(buffer, (*d).into()),
847            Self::ChannelWidth(d) => write_u32(buffer, (*d).into()),
848            Self::StationInfo(nlas) => nlas.as_slice().emit(buffer),
849            Self::SurveyInfo(nlas) => nlas.as_slice().emit(buffer),
850            Self::TransmitQueueStats(nlas) => nlas.as_slice().emit(buffer),
851            Self::MloLinks(links) => links.as_slice().emit(buffer),
852            Self::WiphyRetryShort(d)
853            | Self::WiphyRetryLong(d)
854            | Self::WiphyCoverageClass(d)
855            | Self::MaxNumScanSsids(d)
856            | Self::MaxNumSchedScanSsids(d)
857            | Self::MaxMatchSets(d)
858            | Self::MaxNumPmkids(d) => buffer[0] = *d,
859            Self::CipherSuites(suits) => {
860                let nums: Vec<u32> =
861                    suits.as_slice().iter().map(|s| u32::from(*s)).collect();
862                for (i, v) in nums.as_slice().iter().enumerate() {
863                    buffer[i * 4..(i + 1) * 4]
864                        .copy_from_slice(&v.to_ne_bytes());
865                }
866            }
867            Self::SupportedIftypes(s) => s.as_slice().emit(buffer),
868            Self::WiphyBands(s) => s.as_slice().emit(buffer),
869            Self::SplitWiphyDump => (),
870            Self::SupportedCommand(s) => {
871                Nl80211Commands::from(s).as_slice().emit(buffer)
872            }
873            Self::MaxRemainOnChannelDuration(d) => write_u32(buffer, *d),
874            Self::WowlanTriggersSupport(s) => s.as_slice().emit(buffer),
875            Self::SoftwareIftypes(s) => {
876                Nl80211InterfaceTypes::from(s).as_slice().emit(buffer)
877            }
878            Self::Features(d) => {
879                buffer.copy_from_slice(&d.bits().to_ne_bytes())
880            }
881            Self::ExtFeatures(s) => Nl80211ExtFeatures::from(s).emit(buffer),
882            Self::InterfaceCombination(s) => s.as_slice().emit(buffer),
883            Self::HtCapabilityMask(s) => s.emit(buffer),
884            Self::TxFrameTypes(s) => s.as_slice().emit(buffer),
885            Self::RxFrameTypes(s) => s.as_slice().emit(buffer),
886            Self::ExtCap(v) => v.emit(buffer),
887            Self::ExtCapMask(v) => v.emit(buffer),
888            Self::VhtCap(v) => v.emit(buffer),
889            Self::VhtCapMask(v) => v.emit(buffer),
890            Self::MaxCsaCounters(v) => buffer[0] = *v,
891            Self::IfTypeExtCap(s) => {
892                Nl80211IfTypeExtCapas::from(s).as_slice().emit(buffer)
893            }
894            Self::EmlCapability(d)
895            | Self::MldCapaAndOps(d)
896            | Self::MaxNumAkmSuites(d)
897            | Self::MaxHwTimestampPeers(d)
898            | Self::MeasurementDuration(d) => write_u16(buffer, *d),
899            Self::Bands(v) => v.emit(buffer),
900            Self::Bss(v) => v.as_slice().emit(buffer),
901            Self::ScanSsids(v) => {
902                Nla80211ScanSsidNlas::from(v).as_slice().emit(buffer)
903            }
904            Self::ScanFlags(v) => v.emit(buffer),
905            Self::ScanFrequencies(v) => {
906                Nla80211ScanFreqNlas::from(v).as_slice().emit(buffer)
907            }
908            Self::SchedScanMatch(v) => v.as_slice().emit(buffer),
909            Self::SchedScanPlans(v) => v.as_slice().emit(buffer),
910            Self::Other(attr) => attr.emit(buffer),
911        }
912    }
913}
914
915impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Nl80211Attr {
916    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
917        let payload = buf.value();
918        Ok(match buf.kind() {
919            NL80211_ATTR_IFINDEX => {
920                let err_msg =
921                    format!("Invalid NL80211_ATTR_IFINDEX value {payload:?}");
922                Self::IfIndex(parse_u32(payload).context(err_msg)?)
923            }
924            NL80211_ATTR_WIPHY => {
925                let err_msg =
926                    format!("Invalid NL80211_ATTR_WIPHY value {payload:?}");
927                Self::Wiphy(parse_u32(payload).context(err_msg)?)
928            }
929            NL80211_ATTR_WIPHY_NAME => {
930                let err_msg = format!(
931                    "Invalid NL80211_ATTR_WIPHY_NAME value {payload:?}"
932                );
933                Self::WiphyName(parse_string(payload).context(err_msg)?)
934            }
935            NL80211_ATTR_IFNAME => {
936                let err_msg =
937                    format!("Invalid NL80211_ATTR_IFNAME value {payload:?}");
938                Self::IfName(parse_string(payload).context(err_msg)?)
939            }
940            NL80211_ATTR_IFTYPE => {
941                Self::IfType(Nl80211InterfaceType::parse(payload)?)
942            }
943            NL80211_ATTR_WDEV => {
944                let err_msg =
945                    format!("Invalid NL80211_ATTR_WDEV value {payload:?}");
946                Self::Wdev(parse_u64(payload).context(err_msg)?)
947            }
948            NL80211_ATTR_MAC => Self::Mac(if payload.len() == ETH_ALEN {
949                let mut ret = [0u8; ETH_ALEN];
950                ret.copy_from_slice(&payload[..ETH_ALEN]);
951                ret
952            } else {
953                return Err(format!(
954                    "Invalid length of NL80211_ATTR_MAC, \
955                    expected length {ETH_ALEN} got {payload:?}"
956                )
957                .into());
958            }),
959            NL80211_ATTR_MAC_MASK => {
960                Self::MacMask(if payload.len() == ETH_ALEN {
961                    let mut ret = [0u8; ETH_ALEN];
962                    ret.copy_from_slice(&payload[..ETH_ALEN]);
963                    ret
964                } else {
965                    return Err(format!(
966                        "Invalid length of NL80211_ATTR_MAC_MASK, \
967                        expected length {ETH_ALEN} got {payload:?}"
968                    )
969                    .into());
970                })
971            }
972            NL80211_ATTR_MAC_ADDRS => {
973                Self::MacAddrs(MacAddressNlas::parse(payload)?.into())
974            }
975            NL80211_ATTR_GENERATION => {
976                let err_msg = format!(
977                    "Invalid NL80211_ATTR_GENERATION value {payload:?}"
978                );
979                Self::Generation(parse_u32(payload).context(err_msg)?)
980            }
981            NL80211_ATTR_BSS => {
982                let err_msg =
983                    format!("Invalid NL80211_ATTR_BSS value {payload:?}");
984                let mut nlas = Vec::new();
985                for nla in NlasIterator::new(payload) {
986                    let nla = &nla.context(err_msg.clone())?;
987                    nlas.push(Nl80211BssInfo::parse(nla)?);
988                }
989                Self::Bss(nlas)
990            }
991            NL80211_ATTR_4ADDR => {
992                let err_msg =
993                    format!("Invalid NL80211_ATTR_4ADDR value {payload:?}");
994                Self::Use4Addr(parse_u8(payload).context(err_msg)? > 0)
995            }
996            NL80211_ATTR_WIPHY_FREQ => {
997                let err_msg = format!(
998                    "Invalid NL80211_ATTR_WIPHY_FREQ value {payload:?}"
999                );
1000                Self::WiphyFreq(parse_u32(payload).context(err_msg)?)
1001            }
1002            NL80211_ATTR_WIPHY_FREQ_OFFSET => {
1003                let err_msg = format!(
1004                    "Invalid NL80211_ATTR_WIPHY_FREQ_OFFSET value {payload:?}"
1005                );
1006                Self::WiphyFreqOffset(parse_u32(payload).context(err_msg)?)
1007            }
1008            NL80211_ATTR_WIPHY_CHANNEL_TYPE => {
1009                let err_msg = format!(
1010                    "Invalid NL80211_ATTR_WIPHY_CHANNEL_TYPE value {payload:?}"
1011                );
1012                Self::WiphyChannelType(
1013                    parse_u32(payload).context(err_msg)?.into(),
1014                )
1015            }
1016            NL80211_ATTR_CHANNEL_WIDTH => {
1017                let err_msg = format!(
1018                    "Invalid NL80211_ATTR_CHANNEL_WIDTH value {payload:?}"
1019                );
1020                Self::ChannelWidth(parse_u32(payload).context(err_msg)?.into())
1021            }
1022            NL80211_ATTR_CENTER_FREQ1 => {
1023                let err_msg = format!(
1024                    "Invalid NL80211_ATTR_CENTER_FREQ1 value {payload:?}"
1025                );
1026                Self::CenterFreq1(parse_u32(payload).context(err_msg)?)
1027            }
1028            NL80211_ATTR_CENTER_FREQ2 => {
1029                let err_msg = format!(
1030                    "Invalid NL80211_ATTR_CENTER_FREQ2 value {payload:?}"
1031                );
1032                Self::CenterFreq2(parse_u32(payload).context(err_msg)?)
1033            }
1034            NL80211_ATTR_WIPHY_TX_POWER_LEVEL => {
1035                let err_msg = format!(
1036                    "Invalid NL80211_ATTR_WIPHY_TX_POWER_LEVEL value {payload:?}"
1037                );
1038                Self::WiphyTxPowerLevel(parse_u32(payload).context(err_msg)?)
1039            }
1040            NL80211_ATTR_SSID => {
1041                let err_msg =
1042                    format!("Invalid NL80211_ATTR_SSID value {payload:?}");
1043                Self::Ssid(parse_string(payload).context(err_msg)?)
1044            }
1045            NL80211_ATTR_STA_INFO => {
1046                let err_msg =
1047                    format!("Invalid NL80211_ATTR_STA_INFO value {payload:?}");
1048                let mut nlas = Vec::new();
1049                for nla in NlasIterator::new(payload) {
1050                    let nla = &nla.context(err_msg.clone())?;
1051                    nlas.push(
1052                        Nl80211StationInfo::parse(nla)
1053                            .context(err_msg.clone())?,
1054                    );
1055                }
1056                Self::StationInfo(nlas)
1057            }
1058            NL80211_ATTR_SURVEY_INFO => {
1059                let err_msg = format!(
1060                    "Invalid NL80211_ATTR_SURVEY_INFO value {payload:?}"
1061                );
1062                let mut nlas = Vec::new();
1063                for nla in NlasIterator::new(payload) {
1064                    let nla = &nla.context(err_msg.clone())?;
1065                    nlas.push(
1066                        Nl80211SurveyInfo::parse(nla)
1067                            .context(err_msg.clone())?,
1068                    );
1069                }
1070                Self::SurveyInfo(nlas)
1071            }
1072            NL80211_ATTR_SURVEY_RADIO_STATS => Self::SurveyRadioStats,
1073            NL80211_ATTR_TXQ_STATS => {
1074                let err_msg =
1075                    format!("Invalid NL80211_ATTR_TXQ_STATS value {payload:?}");
1076                let mut nlas = Vec::new();
1077                for nla in NlasIterator::new(payload) {
1078                    let nla = &nla.context(err_msg.clone())?;
1079                    nlas.push(
1080                        Nl80211TransmitQueueStat::parse(nla)
1081                            .context(err_msg.clone())?,
1082                    );
1083                }
1084                Self::TransmitQueueStats(nlas)
1085            }
1086            NL80211_ATTR_TXQ_LIMIT => {
1087                Self::TransmitQueueLimit(parse_u32(payload).context(
1088                    format!("Invalid NL80211_ATTR_TXQ_LIMIT {payload:?}"),
1089                )?)
1090            }
1091            NL80211_ATTR_TXQ_MEMORY_LIMIT => Self::TransmitQueueMemoryLimit(
1092                parse_u32(payload).context(format!(
1093                    "Invalid NL80211_ATTR_TXQ_MEMORY_LIMIT {payload:?}"
1094                ))?,
1095            ),
1096            NL80211_ATTR_TXQ_QUANTUM => {
1097                Self::TransmitQueueQuantum(parse_u32(payload).context(
1098                    format!("Invalid NL80211_ATTR_TXQ_QUANTUM {payload:?}"),
1099                )?)
1100            }
1101            NL80211_ATTR_MLO_LINKS => {
1102                let err_msg =
1103                    format!("Invalid NL80211_ATTR_MLO_LINKS value {payload:?}");
1104                let mut links = Vec::new();
1105                for nla in NlasIterator::new(payload) {
1106                    let nla = &nla.context(err_msg.clone())?;
1107                    links.push(
1108                        Nl80211MloLink::parse(nla).context(err_msg.clone())?,
1109                    );
1110                }
1111                Self::MloLinks(links)
1112            }
1113            NL80211_ATTR_WIPHY_RETRY_SHORT => {
1114                let err_msg = format!(
1115                    "Invalid NL80211_ATTR_WIPHY_RETRY_SHORT value {payload:?}"
1116                );
1117                Self::WiphyRetryShort(parse_u8(payload).context(err_msg)?)
1118            }
1119            NL80211_ATTR_WIPHY_RETRY_LONG => {
1120                let err_msg = format!(
1121                    "Invalid NL80211_ATTR_WIPHY_RETRY_LONG value {payload:?}"
1122                );
1123                Self::WiphyRetryLong(parse_u8(payload).context(err_msg)?)
1124            }
1125            NL80211_ATTR_WIPHY_FRAG_THRESHOLD => {
1126                let err_msg = format!(
1127                    "Invalid NL80211_ATTR_WIPHY_FRAG_THRESHOLD value {payload:?}"
1128                );
1129                Self::WiphyFragThreshold(parse_u32(payload).context(err_msg)?)
1130            }
1131            NL80211_ATTR_WIPHY_RTS_THRESHOLD => {
1132                let err_msg = format!(
1133                    "Invalid NL80211_ATTR_WIPHY_RTS_THRESHOLD value {payload:?}"
1134                );
1135                Self::WiphyRtsThreshold(parse_u32(payload).context(err_msg)?)
1136            }
1137            NL80211_ATTR_WIPHY_COVERAGE_CLASS => {
1138                let err_msg = format!(
1139                    "Invalid NL80211_ATTR_WIPHY_COVERAGE_CLASS value {payload:?}"
1140                );
1141                Self::WiphyCoverageClass(parse_u8(payload).context(err_msg)?)
1142            }
1143            NL80211_ATTR_MAX_NUM_SCAN_SSIDS => {
1144                let err_msg = format!(
1145                    "Invalid NL80211_ATTR_MAX_NUM_SCAN_SSIDS value {payload:?}"
1146                );
1147                Self::MaxNumScanSsids(parse_u8(payload).context(err_msg)?)
1148            }
1149            NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS => {
1150                let err_msg = format!(
1151                    "Invalid NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS value {payload:?}"
1152                );
1153                Self::MaxNumSchedScanSsids(parse_u8(payload).context(err_msg)?)
1154            }
1155            NL80211_ATTR_MAX_SCAN_IE_LEN => {
1156                let err_msg = format!(
1157                    "Invalid NL80211_ATTR_MAX_SCAN_IE_LEN value {payload:?}"
1158                );
1159                Self::MaxScanIeLen(parse_u16(payload).context(err_msg)?)
1160            }
1161            NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN => {
1162                let err_msg = format!(
1163                    "Invalid NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN value {payload:?}"
1164                );
1165                Self::MaxSchedScanIeLen(parse_u16(payload).context(err_msg)?)
1166            }
1167            NL80211_ATTR_MAX_MATCH_SETS => {
1168                let err_msg = format!(
1169                    "Invalid NL80211_ATTR_MAX_MATCH_SETS value {payload:?}"
1170                );
1171                Self::MaxMatchSets(parse_u8(payload).context(err_msg)?)
1172            }
1173            NL80211_ATTR_SUPPORT_IBSS_RSN => Self::SupportIbssRsn,
1174            NL80211_ATTR_SUPPORT_MESH_AUTH => Self::SupportMeshAuth,
1175            NL80211_ATTR_SUPPORT_AP_UAPSD => Self::SupportApUapsd,
1176            NL80211_ATTR_ROAM_SUPPORT => Self::RoamSupport,
1177            NL80211_ATTR_TDLS_SUPPORT => Self::TdlsSupport,
1178            NL80211_ATTR_TDLS_EXTERNAL_SETUP => Self::TdlsExternalSetup,
1179            NL80211_ATTR_CIPHER_SUITES => {
1180                let err_msg = format!(
1181                    "Invalid NL80211_ATTR_CIPHER_SUITES value {payload:?}"
1182                );
1183                let mut suits = Vec::new();
1184                for i in 0..(payload.len() / 4) {
1185                    suits.push(
1186                        parse_u32(&payload[i * 4..(i + 1) * 4])
1187                            .context(err_msg.clone())?
1188                            .into(),
1189                    );
1190                }
1191                Self::CipherSuites(suits)
1192            }
1193            NL80211_ATTR_MAX_NUM_PMKIDS => {
1194                let err_msg = format!(
1195                    "Invalid NL80211_ATTR_MAX_NUM_PMKIDS value {payload:?}"
1196                );
1197                Self::MaxNumPmkids(parse_u8(payload).context(err_msg)?)
1198            }
1199            NL80211_ATTR_CONTROL_PORT_ETHERTYPE => Self::ControlPortEthertype,
1200            NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX => {
1201                let err_msg = format!(
1202                    "Invalid NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX value {payload:?}"
1203                );
1204                Self::WiphyAntennaAvailTx(parse_u32(payload).context(err_msg)?)
1205            }
1206            NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX => {
1207                let err_msg = format!(
1208                    "Invalid NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX value {payload:?}"
1209                );
1210                Self::WiphyAntennaAvailRx(parse_u32(payload).context(err_msg)?)
1211            }
1212            NL80211_ATTR_PROBE_RESP_OFFLOAD => {
1213                let err_msg = format!(
1214                    "Invalid NL80211_ATTR_PROBE_RESP_OFFLOAD value {payload:?}"
1215                );
1216                Self::ApProbeRespOffload(parse_u32(payload).context(err_msg)?)
1217            }
1218            NL80211_ATTR_WIPHY_ANTENNA_TX => {
1219                let err_msg = format!(
1220                    "Invalid NL80211_ATTR_WIPHY_ANTENNA_TX value {payload:?}"
1221                );
1222                Self::WiphyAntennaTx(parse_u32(payload).context(err_msg)?)
1223            }
1224            NL80211_ATTR_WIPHY_ANTENNA_RX => {
1225                let err_msg = format!(
1226                    "Invalid NL80211_ATTR_WIPHY_ANTENNA_RX value {payload:?}"
1227                );
1228                Self::WiphyAntennaRx(parse_u32(payload).context(err_msg)?)
1229            }
1230            NL80211_ATTR_SUPPORTED_IFTYPES => {
1231                let err_msg = format!(
1232                    "Invalid NL80211_ATTR_SUPPORTED_IFTYPES value {payload:?}"
1233                );
1234                let mut nlas = Vec::new();
1235                for nla in NlasIterator::new(payload) {
1236                    let nla = &nla.context(err_msg.clone())?;
1237                    nlas.push(
1238                        Nl80211IfMode::parse(nla).context(err_msg.clone())?,
1239                    );
1240                }
1241                Self::SupportedIftypes(nlas)
1242            }
1243            NL80211_ATTR_WIPHY_BANDS => {
1244                let mut nlas = Vec::new();
1245                for nla in NlasIterator::new(payload) {
1246                    let err_msg = format!(
1247                        "Invalid NL80211_ATTR_WIPHY_BANDS value {nla:?}"
1248                    );
1249                    let nla = &nla.context(err_msg.clone())?;
1250                    nlas.push(Nl80211Band::parse(nla)?);
1251                }
1252                Self::WiphyBands(nlas)
1253            }
1254            NL80211_ATTR_SPLIT_WIPHY_DUMP => Self::SplitWiphyDump,
1255            NL80211_ATTR_SUPPORTED_COMMANDS => {
1256                Self::SupportedCommand(Nl80211Commands::parse(payload)?.into())
1257            }
1258            NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION => {
1259                let err_msg = format!(
1260                    "Invalid \
1261                    NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION {payload:?}"
1262                );
1263                Self::MaxRemainOnChannelDuration(
1264                    parse_u32(payload).context(err_msg)?,
1265                )
1266            }
1267            NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED => {
1268                let mut nlas = Vec::new();
1269                for nla in NlasIterator::new(payload) {
1270                    let err_msg = format!(
1271                        "Invalid NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED \
1272                        value {nla:?}"
1273                    );
1274                    let nla = &nla.context(err_msg.clone())?;
1275                    nlas.push(Nl80211WowlanTriggersSupport::parse(nla)?);
1276                }
1277                Self::WowlanTriggersSupport(nlas)
1278            }
1279            NL80211_ATTR_OFFCHANNEL_TX_OK => Self::OffchannelTxOk,
1280            NL80211_ATTR_SOFTWARE_IFTYPES => Self::SoftwareIftypes(
1281                Nl80211InterfaceTypes::parse(
1282                    payload,
1283                    "NL80211_ATTR_SOFTWARE_IFTYPES",
1284                )?
1285                .0,
1286            ),
1287            NL80211_ATTR_FEATURE_FLAGS => Self::Features(
1288                Nl80211Features::from_bits_retain(parse_u32(payload).context(
1289                    format!("Invalid NL80211_ATTR_FEATURE_FLAGS {payload:?}"),
1290                )?),
1291            ),
1292            NL80211_ATTR_EXT_FEATURES => {
1293                Self::ExtFeatures(Nl80211ExtFeatures::parse(payload)?.0)
1294            }
1295            NL80211_ATTR_INTERFACE_COMBINATIONS => {
1296                let mut nlas = Vec::new();
1297                for (index, nla) in NlasIterator::new(payload).enumerate() {
1298                    let err_msg = format!(
1299                        "Invalid NL80211_ATTR_INTERFACE_COMBINATIONS \
1300                        value {nla:?}"
1301                    );
1302                    let nla = &nla.context(err_msg.clone())?;
1303                    nlas.push(Nl80211IfaceComb::parse_with_param(
1304                        nla,
1305                        index as u16,
1306                    )?);
1307                }
1308                Self::InterfaceCombination(nlas)
1309            }
1310            NL80211_ATTR_HT_CAPABILITY_MASK => {
1311                Self::HtCapabilityMask(Nl80211HtCapabilityMask::new(payload))
1312            }
1313            NL80211_ATTR_RX_FRAME_TYPES => {
1314                let mut nlas = Vec::new();
1315                for nla in NlasIterator::new(payload) {
1316                    let err_msg = format!(
1317                        "Invalid NL80211_ATTR_RX_FRAME_TYPES value {nla:?}"
1318                    );
1319                    let nla = &nla.context(err_msg.clone())?;
1320                    nlas.push(Nl80211IfaceFrameType::parse(nla)?);
1321                }
1322                Self::RxFrameTypes(nlas)
1323            }
1324            NL80211_ATTR_TX_FRAME_TYPES => {
1325                let mut nlas = Vec::new();
1326                for nla in NlasIterator::new(payload) {
1327                    let err_msg = format!(
1328                        "Invalid NL80211_ATTR_RX_FRAME_TYPES value {nla:?}"
1329                    );
1330                    let nla = &nla.context(err_msg.clone())?;
1331                    nlas.push(Nl80211IfaceFrameType::parse(nla)?);
1332                }
1333                Self::TxFrameTypes(nlas)
1334            }
1335            NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS => {
1336                Self::MaxNumSchedScanPlans(parse_u32(payload).context(
1337                    format!(
1338                        "Invalid NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS \
1339                        {payload:?}"
1340                    ),
1341                )?)
1342            }
1343            NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL => Self::MaxScanPlanInterval(
1344                parse_u32(payload).context(format!(
1345                    "Invalid NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL \
1346                        {payload:?}"
1347                ))?,
1348            ),
1349            NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS => {
1350                Self::MaxScanPlanIterations(parse_u32(payload).context(
1351                    format!(
1352                        "Invalid NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS \
1353                        {payload:?}"
1354                    ),
1355                )?)
1356            }
1357            NL80211_ATTR_EXT_CAPA => {
1358                Self::ExtCap(Nl80211ExtendedCapability::new(payload))
1359            }
1360            NL80211_ATTR_EXT_CAPA_MASK => {
1361                Self::ExtCapMask(Nl80211ExtendedCapability::new(payload))
1362            }
1363            NL80211_ATTR_VHT_CAPABILITY => {
1364                Self::VhtCap(Nl80211VhtCapability::parse(payload)?)
1365            }
1366            NL80211_ATTR_VHT_CAPABILITY_MASK => {
1367                Self::VhtCapMask(Nl80211VhtCapability::parse(payload)?)
1368            }
1369            NL80211_ATTR_MAX_CSA_COUNTERS => {
1370                Self::MaxCsaCounters(parse_u8(payload).context(format!(
1371                    "Invalid NL80211_ATTR_MAX_CSA_COUNTERS {payload:?}"
1372                ))?)
1373            }
1374            NL80211_ATTR_WIPHY_SELF_MANAGED_REG => Self::WiphySelfManagedReg,
1375            NL80211_ATTR_SCHED_SCAN_MAX_REQS => {
1376                Self::SchedScanMaxReqs(parse_u32(payload).context(format!(
1377                    "Invalid NL80211_ATTR_SCHED_SCAN_MAX_REQS {payload:?}"
1378                ))?)
1379            }
1380            NL80211_ATTR_IFTYPE_EXT_CAPA => {
1381                Self::IfTypeExtCap(Nl80211IfTypeExtCapas::parse(buf)?.into())
1382            }
1383            NL80211_ATTR_EML_CAPABILITY => {
1384                Self::EmlCapability(parse_u16(payload).context(format!(
1385                    "Invalid NL80211_ATTR_EML_CAPABILITY {payload:?}"
1386                ))?)
1387            }
1388            NL80211_ATTR_MLD_CAPA_AND_OPS => {
1389                Self::MldCapaAndOps(parse_u16(payload).context(format!(
1390                    "Invalid NL80211_ATTR_MLD_CAPA_AND_OPS {payload:?}"
1391                ))?)
1392            }
1393            NL80211_ATTR_BANDS => {
1394                Self::Bands(Nl80211BandTypes::parse(payload)?)
1395            }
1396            NL80211_ATTR_MAX_NUM_AKM_SUITES => {
1397                Self::MaxNumAkmSuites(parse_u16(payload).context(format!(
1398                    "Invalid NL80211_ATTR_MAX_NUM_AKM_SUITES {payload:?}"
1399                ))?)
1400            }
1401            NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS => Self::MaxHwTimestampPeers(
1402                parse_u16(payload).context(format!(
1403                    "Invalid NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS {payload:?}"
1404                ))?,
1405            ),
1406            NL80211_ATTR_SCAN_SSIDS => {
1407                Self::ScanSsids(Nla80211ScanSsidNlas::parse(payload)?.into())
1408            }
1409            NL80211_ATTR_SCAN_FLAGS => {
1410                Self::ScanFlags(Nl80211ScanFlags::parse(payload)?)
1411            }
1412            NL80211_ATTR_MEASUREMENT_DURATION => {
1413                let err_msg = format!(
1414                    "Invalid NL80211_ATTR_MEASUREMENT_DURATION value {payload:?}"
1415                );
1416                Self::MeasurementDuration(parse_u16(payload).context(err_msg)?)
1417            }
1418            NL80211_ATTR_SCHED_SCAN_INTERVAL => {
1419                let err_msg = format!(
1420                    "Invalid NL80211_ATTR_SCHED_SCAN_INTERVAL value {payload:?}"
1421                );
1422                Self::SchedScanInterval(parse_u32(payload).context(err_msg)?)
1423            }
1424            NL80211_ATTR_SCHED_SCAN_DELAY => {
1425                let err_msg = format!(
1426                    "Invalid NL80211_ATTR_SCHED_SCAN_DELAY value {payload:?}"
1427                );
1428                Self::SchedScanDelay(parse_u32(payload).context(err_msg)?)
1429            }
1430            NL80211_ATTR_SCAN_FREQUENCIES => Self::ScanFrequencies(
1431                Nla80211ScanFreqNlas::parse(payload)?.into(),
1432            ),
1433            NL80211_ATTR_SCHED_SCAN_MATCH => {
1434                let err_msg = format!(
1435                    "Invalid NL80211_ATTR_SCHED_SCAN_MATCH value {payload:?}"
1436                );
1437                let mut nlas = Vec::new();
1438                for nla in NlasIterator::new(payload) {
1439                    let nla = &nla.context(err_msg.clone())?;
1440                    nlas.push(Nl80211SchedScanMatch::parse(nla)?);
1441                }
1442                Self::SchedScanMatch(nlas)
1443            }
1444            NL80211_ATTR_SCHED_SCAN_PLANS => {
1445                let err_msg = format!(
1446                    "Invalid NL80211_ATTR_SCHED_SCAN_PLANS value {payload:?}"
1447                );
1448                let mut nlas = Vec::new();
1449                for nla in NlasIterator::new(payload) {
1450                    let nla = &nla.context(err_msg.clone())?;
1451                    nlas.push(Nl80211SchedScanPlan::parse(nla)?);
1452                }
1453                Self::SchedScanPlans(nlas)
1454            }
1455            _ => Self::Other(
1456                DefaultNla::parse(buf).context("invalid NLA (unknown kind)")?,
1457            ),
1458        })
1459    }
1460}