xref: /linux/include/linux/ieee80211-mesh.h (revision b5a051f6b840d48f159166ef073d3021989bfb50)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * IEEE 802.11 mesh definitions
4  *
5  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6  * <jkmaline@cc.hut.fi>
7  * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8  * Copyright (c) 2005, Devicescape Software, Inc.
9  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
10  * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
11  * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
12  * Copyright (c) 2018 - 2025 Intel Corporation
13  */
14 
15 #ifndef LINUX_IEEE80211_MESH_H
16 #define LINUX_IEEE80211_MESH_H
17 
18 #include <linux/types.h>
19 #include <linux/if_ether.h>
20 
21 #define IEEE80211_MAX_MESH_ID_LEN	32
22 
23 struct ieee80211s_hdr {
24 	u8 flags;
25 	u8 ttl;
26 	__le32 seqnum;
27 	u8 eaddr1[ETH_ALEN];
28 	u8 eaddr2[ETH_ALEN];
29 } __packed __aligned(2);
30 
31 struct ieee80211_mesh_hwmp_preq_target {
32 	u8 flags;
33 	u8 addr[ETH_ALEN];
34 	__le32 sn;
35 } __packed;
36 
37 struct ieee80211_mesh_hwmp_preq_top {
38 	u8 flags;
39 	u8 hopcount;
40 	u8 ttl;
41 	__le32 preq_id;
42 	u8 orig_addr[ETH_ALEN];
43 	__le32 orig_sn;
44 
45 	/* optional AE, lifetime, metric, target */
46 	u8 variable[];
47 } __packed;
48 
49 struct ieee80211_mesh_hwmp_preq_bottom {
50 	__le32 lifetime;
51 	__le32 metric;
52 	u8 target_count;
53 	struct ieee80211_mesh_hwmp_preq_target targets[];
54 } __packed;
55 
56 struct ieee80211_mesh_hwmp_prep_top {
57 	u8 flags;
58 	u8 hopcount;
59 	u8 ttl;
60 	u8 target_addr[ETH_ALEN];
61 	__le32 target_sn;
62 
63 	/* optional Target External Address */
64 	u8 variable[];
65 } __packed;
66 
67 struct ieee80211_mesh_hwmp_prep_bottom {
68 	__le32 lifetime;
69 	__le32 metric;
70 	u8 orig_addr[ETH_ALEN];
71 	__le32 orig_sn;
72 } __packed;
73 
74 struct ieee80211_mesh_hwmp_perr_dst {
75 	u8 flags;
76 	u8 addr[ETH_ALEN];
77 	__le32 sn;
78 	/* optional Destination External Address */
79 	u8 variable[];
80 } __packed;
81 
82 struct ieee80211_mesh_hwmp_perr {
83 	u8 ttl;
84 	u8 number_of_dst;
85 	/* Destinations */
86 	u8 variable[];
87 } __packed;
88 
89 /* Mesh flags */
90 #define MESH_FLAGS_AE_A4 	0x1
91 #define MESH_FLAGS_AE_A5_A6	0x2
92 #define MESH_FLAGS_AE		0x3
93 #define MESH_FLAGS_PS_DEEP	0x4
94 
95 /* HWMP IE processing macros */
96 #define AE_F			(1<<6)
97 
98 /**
99  * enum ieee80211_preq_flags - mesh PREQ element flags
100  *
101  * @IEEE80211_PREQ_PROACTIVE_PREP_FLAG: proactive PREP subfield
102  */
103 enum ieee80211_preq_flags {
104 	IEEE80211_PREQ_PROACTIVE_PREP_FLAG	= 1<<2,
105 };
106 
107 /**
108  * enum ieee80211_preq_target_flags - mesh PREQ element per target flags
109  *
110  * @IEEE80211_PREQ_TO_FLAG: target only subfield
111  * @IEEE80211_PREQ_USN_FLAG: unknown target HWMP sequence number subfield
112  */
113 enum ieee80211_preq_target_flags {
114 	IEEE80211_PREQ_TO_FLAG	= 1<<0,
115 	IEEE80211_PREQ_USN_FLAG	= 1<<2,
116 };
117 
118 /**
119  * struct ieee80211_mesh_chansw_params_ie - mesh channel switch parameters IE
120  * @mesh_ttl: Time To Live
121  * @mesh_flags: Flags
122  * @mesh_reason: Reason Code
123  * @mesh_pre_value: Precedence Value
124  *
125  * This structure represents the payload of the "Mesh Channel Switch
126  * Parameters element" as described in IEEE Std 802.11-2020 section
127  * 9.4.2.102.
128  */
129 struct ieee80211_mesh_chansw_params_ie {
130 	u8 mesh_ttl;
131 	u8 mesh_flags;
132 	__le16 mesh_reason;
133 	__le16 mesh_pre_value;
134 } __packed;
135 
136 /**
137  * struct ieee80211_meshconf_ie - Mesh Configuration element
138  * @meshconf_psel: Active Path Selection Protocol Identifier
139  * @meshconf_pmetric: Active Path Selection Metric Identifier
140  * @meshconf_congest: Congestion Control Mode Identifier
141  * @meshconf_synch: Synchronization Method Identifier
142  * @meshconf_auth: Authentication Protocol Identifier
143  * @meshconf_form: Mesh Formation Info
144  * @meshconf_cap: Mesh Capability (see &enum mesh_config_capab_flags)
145  *
146  * This structure represents the payload of the "Mesh Configuration
147  * element" as described in IEEE Std 802.11-2020 section 9.4.2.97.
148  */
149 struct ieee80211_meshconf_ie {
150 	u8 meshconf_psel;
151 	u8 meshconf_pmetric;
152 	u8 meshconf_congest;
153 	u8 meshconf_synch;
154 	u8 meshconf_auth;
155 	u8 meshconf_form;
156 	u8 meshconf_cap;
157 } __packed;
158 
159 /**
160  * enum mesh_config_capab_flags - Mesh Configuration IE capability field flags
161  *
162  * @IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish
163  *	additional mesh peerings with other mesh STAs
164  * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
165  * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure
166  *	is ongoing
167  * @IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL: STA is in deep sleep mode or has
168  *	neighbors in deep sleep mode
169  *
170  * Enumerates the "Mesh Capability" as described in IEEE Std
171  * 802.11-2020 section 9.4.2.97.7.
172  */
173 enum mesh_config_capab_flags {
174 	IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS		= 0x01,
175 	IEEE80211_MESHCONF_CAPAB_FORWARDING		= 0x08,
176 	IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING		= 0x20,
177 	IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL	= 0x40,
178 };
179 
180 #define IEEE80211_MESHCONF_FORM_CONNECTED_TO_GATE 0x1
181 
182 /*
183  * mesh channel switch parameters element's flag indicator
184  *
185  */
186 #define WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT BIT(0)
187 #define WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR BIT(1)
188 #define WLAN_EID_CHAN_SWITCH_PARAM_REASON BIT(2)
189 
190 /**
191  * struct ieee80211_rann_ie - RANN (root announcement) element
192  * @rann_flags: Flags
193  * @rann_hopcount: Hop Count
194  * @rann_ttl: Element TTL
195  * @rann_addr: Root Mesh STA Address
196  * @rann_seq: HWMP Sequence Number
197  * @rann_interval: Interval
198  * @rann_metric: Metric
199  *
200  * This structure represents the payload of the "RANN element" as
201  * described in IEEE Std 802.11-2020 section 9.4.2.111.
202  */
203 struct ieee80211_rann_ie {
204 	u8 rann_flags;
205 	u8 rann_hopcount;
206 	u8 rann_ttl;
207 	u8 rann_addr[ETH_ALEN];
208 	__le32 rann_seq;
209 	__le32 rann_interval;
210 	__le32 rann_metric;
211 } __packed;
212 
213 enum ieee80211_rann_flags {
214 	RANN_FLAG_IS_GATE = 1 << 0,
215 };
216 
217 /* Mesh action codes */
218 enum ieee80211_mesh_actioncode {
219 	WLAN_MESH_ACTION_LINK_METRIC_REPORT,
220 	WLAN_MESH_ACTION_HWMP_PATH_SELECTION,
221 	WLAN_MESH_ACTION_GATE_ANNOUNCEMENT,
222 	WLAN_MESH_ACTION_CONGESTION_CONTROL_NOTIFICATION,
223 	WLAN_MESH_ACTION_MCCA_SETUP_REQUEST,
224 	WLAN_MESH_ACTION_MCCA_SETUP_REPLY,
225 	WLAN_MESH_ACTION_MCCA_ADVERTISEMENT_REQUEST,
226 	WLAN_MESH_ACTION_MCCA_ADVERTISEMENT,
227 	WLAN_MESH_ACTION_MCCA_TEARDOWN,
228 	WLAN_MESH_ACTION_TBTT_ADJUSTMENT_REQUEST,
229 	WLAN_MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE,
230 };
231 
232 /**
233  * enum ieee80211_mesh_sync_method - mesh synchronization method identifier
234  *
235  * @IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET: the default synchronization method
236  * @IEEE80211_SYNC_METHOD_VENDOR: a vendor specific synchronization method
237  *	that will be specified in a vendor specific information element
238  */
239 enum ieee80211_mesh_sync_method {
240 	IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET = 1,
241 	IEEE80211_SYNC_METHOD_VENDOR = 255,
242 };
243 
244 /**
245  * enum ieee80211_mesh_path_protocol - mesh path selection protocol identifier
246  *
247  * @IEEE80211_PATH_PROTOCOL_HWMP: the default path selection protocol
248  * @IEEE80211_PATH_PROTOCOL_VENDOR: a vendor specific protocol that will
249  *	be specified in a vendor specific information element
250  */
251 enum ieee80211_mesh_path_protocol {
252 	IEEE80211_PATH_PROTOCOL_HWMP = 1,
253 	IEEE80211_PATH_PROTOCOL_VENDOR = 255,
254 };
255 
256 /**
257  * enum ieee80211_mesh_path_metric - mesh path selection metric identifier
258  *
259  * @IEEE80211_PATH_METRIC_AIRTIME: the default path selection metric
260  * @IEEE80211_PATH_METRIC_VENDOR: a vendor specific metric that will be
261  *	specified in a vendor specific information element
262  */
263 enum ieee80211_mesh_path_metric {
264 	IEEE80211_PATH_METRIC_AIRTIME = 1,
265 	IEEE80211_PATH_METRIC_VENDOR = 255,
266 };
267 
268 /**
269  * enum ieee80211_root_mode_identifier - root mesh STA mode identifier
270  *
271  * These attribute are used by dot11MeshHWMPRootMode to set root mesh STA mode
272  *
273  * @IEEE80211_ROOTMODE_NO_ROOT: the mesh STA is not a root mesh STA (default)
274  * @IEEE80211_ROOTMODE_ROOT: the mesh STA is a root mesh STA if greater than
275  *	this value
276  * @IEEE80211_PROACTIVE_PREQ_NO_PREP: the mesh STA is a root mesh STA supports
277  *	the proactive PREQ with proactive PREP subfield set to 0
278  * @IEEE80211_PROACTIVE_PREQ_WITH_PREP: the mesh STA is a root mesh STA
279  *	supports the proactive PREQ with proactive PREP subfield set to 1
280  * @IEEE80211_PROACTIVE_RANN: the mesh STA is a root mesh STA supports
281  *	the proactive RANN
282  */
283 enum ieee80211_root_mode_identifier {
284 	IEEE80211_ROOTMODE_NO_ROOT = 0,
285 	IEEE80211_ROOTMODE_ROOT = 1,
286 	IEEE80211_PROACTIVE_PREQ_NO_PREP = 2,
287 	IEEE80211_PROACTIVE_PREQ_WITH_PREP = 3,
288 	IEEE80211_PROACTIVE_RANN = 4,
289 };
290 
ieee80211_mesh_preq_prep_ae_enabled(const u8 * ie)291 static inline bool ieee80211_mesh_preq_prep_ae_enabled(const u8 *ie)
292 {
293 	return ie[0] & AE_F;
294 }
295 
296 static inline struct ieee80211_mesh_hwmp_preq_bottom *
ieee80211_mesh_hwmp_preq_get_bottom(const u8 * ie)297 ieee80211_mesh_hwmp_preq_get_bottom(const u8 *ie)
298 {
299 	struct ieee80211_mesh_hwmp_preq_top *top = (void *)ie;
300 
301 	return (void *)&top->variable[
302 		ieee80211_mesh_preq_prep_ae_enabled(ie) ? ETH_ALEN : 0];
303 }
304 
305 static inline struct ieee80211_mesh_hwmp_prep_bottom *
ieee80211_mesh_hwmp_prep_get_bottom(const u8 * ie)306 ieee80211_mesh_hwmp_prep_get_bottom(const u8 *ie)
307 {
308 	struct ieee80211_mesh_hwmp_prep_top *top = (void *)ie;
309 
310 	return (void *)&top->variable[
311 		ieee80211_mesh_preq_prep_ae_enabled(ie) ? ETH_ALEN : 0];
312 }
313 
314 static inline struct ieee80211_mesh_hwmp_perr_dst *
ieee80211_mesh_hwmp_perr_get_dst(const u8 * ie,u8 dst_idx)315 ieee80211_mesh_hwmp_perr_get_dst(const u8 *ie, u8 dst_idx)
316 {
317 	struct ieee80211_mesh_hwmp_perr *perr_ie = (void *)ie;
318 	struct ieee80211_mesh_hwmp_perr_dst *dst;
319 	u8 *pos = perr_ie->variable;
320 	int i;
321 
322 	for (i = 0; i < dst_idx + 1; i++) {
323 		dst = (void *)pos;
324 		pos += sizeof(struct ieee80211_mesh_hwmp_perr_dst) +
325 			  ((dst->flags & AE_F) ? ETH_ALEN : 0)
326 			  /* Destination External Address */ +
327 			  2 /* Reason Code */;
328 	}
329 
330 	return dst;
331 }
332 
333 static inline u8 *
ieee80211_mesh_hwmp_perr_get_addr(const u8 * ie,u8 dst_idx)334 ieee80211_mesh_hwmp_perr_get_addr(const u8 *ie, u8 dst_idx)
335 {
336 	struct ieee80211_mesh_hwmp_perr_dst *dst =
337 		ieee80211_mesh_hwmp_perr_get_dst(ie, dst_idx);
338 
339 	return dst->addr;
340 }
341 
342 static inline u32
ieee80211_mesh_hwmp_perr_get_sn(const u8 * ie,u8 dst_idx)343 ieee80211_mesh_hwmp_perr_get_sn(const u8 *ie, u8 dst_idx)
344 {
345 	struct ieee80211_mesh_hwmp_perr_dst *dst =
346 		ieee80211_mesh_hwmp_perr_get_dst(ie, dst_idx);
347 
348 	return le32_to_cpu(dst->sn);
349 }
350 
351 static inline u16
ieee80211_mesh_hwmp_perr_get_rcode(const u8 * ie,u8 dst_idx)352 ieee80211_mesh_hwmp_perr_get_rcode(const u8 *ie, u8 dst_idx)
353 {
354 	struct ieee80211_mesh_hwmp_perr_dst *dst =
355 		ieee80211_mesh_hwmp_perr_get_dst(ie, dst_idx);
356 
357 	return get_unaligned_le16(&dst->variable[
358 		(dst->flags & AE_F) ? ETH_ALEN : 0]);
359 }
360 
361 /* IEEE Std 802.11-2016 9.4.2.113 PREQ element */
ieee80211_mesh_preq_size_ok(const u8 * pos,u8 elen)362 static inline bool ieee80211_mesh_preq_size_ok(const u8 *pos, u8 elen)
363 {
364 	struct ieee80211_mesh_hwmp_preq_bottom *preq_elem_bottom;
365 	u8 target_count;
366 	int needed;
367 
368 	/* Check if the element contains flags */
369 	needed = sizeof(struct ieee80211_mesh_hwmp_preq_top);
370 	if (elen < needed)
371 		return false;
372 
373 	/* Check if the element contains target_count */
374 	needed += (ieee80211_mesh_preq_prep_ae_enabled(pos) ? ETH_ALEN : 0)
375 		 /* Originator External Address */ +
376 		 sizeof(struct ieee80211_mesh_hwmp_preq_bottom);
377 	if (elen < needed)
378 		return false;
379 
380 	preq_elem_bottom = ieee80211_mesh_hwmp_preq_get_bottom(pos);
381 	target_count = preq_elem_bottom->target_count;
382 	/* IEEE Std 802.11-2016 Table 14-10 to 14-16 */
383 	if (target_count < 1)
384 		return false;
385 
386 	needed += target_count * sizeof(struct ieee80211_mesh_hwmp_preq_target);
387 	return elen == needed;
388 }
389 
390 /* IEEE Std 802.11-2016 9.4.2.114 PREP element */
ieee80211_mesh_prep_size_ok(const u8 * pos,u8 elen)391 static inline bool ieee80211_mesh_prep_size_ok(const u8 *pos, u8 elen)
392 {
393 	u8 needed;
394 
395 	/* Check if the element contains flags */
396 	needed = sizeof(struct ieee80211_mesh_hwmp_prep_top);
397 	if (elen < needed)
398 		return false;
399 
400 	needed += (ieee80211_mesh_preq_prep_ae_enabled(pos) ? ETH_ALEN : 0)
401 		 /* Target External Address */ +
402 		 sizeof(struct ieee80211_mesh_hwmp_prep_bottom);
403 	return elen == needed;
404 }
405 
406 /* IEEE Std 802.11-2016 9.4.2.115 PERR element */
ieee80211_mesh_perr_size_ok(const u8 * pos,u8 elen)407 static inline bool ieee80211_mesh_perr_size_ok(const u8 *pos, u8 elen)
408 {
409 	struct ieee80211_mesh_hwmp_perr *perr_elem = (void *)pos;
410 	const u8 *start = pos;
411 	u8 number_of_dst;
412 	int needed;
413 	int i;
414 
415 	needed = sizeof(struct ieee80211_mesh_hwmp_perr);
416 
417 	/* Check if the element contains number of dst */
418 	if (elen < needed)
419 		return false;
420 
421 	pos += sizeof(struct ieee80211_mesh_hwmp_perr);
422 	number_of_dst = perr_elem->number_of_dst;
423 
424 	for (i = 0; i < number_of_dst; i++) {
425 		struct ieee80211_mesh_hwmp_perr_dst *dst = (void *)pos;
426 		u8 dst_len = sizeof(struct ieee80211_mesh_hwmp_perr_dst);
427 
428 		/* Check if the element contains flags */
429 		if (elen < pos - start + dst_len)
430 			return false;
431 
432 		dst_len += ((dst->flags & AE_F) ? ETH_ALEN : 0)
433 			  /* Destination External Address */ +
434 			  2 /* Reason Code */;
435 		needed += dst_len;
436 		pos += dst_len;
437 	}
438 
439 	return elen == needed;
440 }
441 
442 #endif /* LINUX_IEEE80211_MESH_H */
443