Line data Source code
1 : /*
2 : * WPA Supplicant - Basic mesh peer management
3 : * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved.
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "utils/includes.h"
10 :
11 : #include "utils/common.h"
12 : #include "utils/eloop.h"
13 : #include "common/ieee802_11_defs.h"
14 : #include "ap/hostapd.h"
15 : #include "ap/sta_info.h"
16 : #include "ap/ieee802_11.h"
17 : #include "wpa_supplicant_i.h"
18 : #include "driver_i.h"
19 : #include "mesh_mpm.h"
20 : #include "mesh_rsn.h"
21 :
22 : struct mesh_peer_mgmt_ie {
23 : const u8 *proto_id;
24 : const u8 *llid;
25 : const u8 *plid;
26 : const u8 *reason;
27 : const u8 *pmk;
28 : };
29 :
30 : static void plink_timer(void *eloop_ctx, void *user_data);
31 :
32 :
33 : enum plink_event {
34 : PLINK_UNDEFINED,
35 : OPN_ACPT,
36 : OPN_RJCT,
37 : OPN_IGNR,
38 : CNF_ACPT,
39 : CNF_RJCT,
40 : CNF_IGNR,
41 : CLS_ACPT,
42 : CLS_IGNR
43 : };
44 :
45 : static const char * const mplstate[] = {
46 : [PLINK_LISTEN] = "LISTEN",
47 : [PLINK_OPEN_SENT] = "OPEN_SENT",
48 : [PLINK_OPEN_RCVD] = "OPEN_RCVD",
49 : [PLINK_CNF_RCVD] = "CNF_RCVD",
50 : [PLINK_ESTAB] = "ESTAB",
51 : [PLINK_HOLDING] = "HOLDING",
52 : [PLINK_BLOCKED] = "BLOCKED"
53 : };
54 :
55 : static const char * const mplevent[] = {
56 : [PLINK_UNDEFINED] = "UNDEFINED",
57 : [OPN_ACPT] = "OPN_ACPT",
58 : [OPN_RJCT] = "OPN_RJCT",
59 : [OPN_IGNR] = "OPN_IGNR",
60 : [CNF_ACPT] = "CNF_ACPT",
61 : [CNF_RJCT] = "CNF_RJCT",
62 : [CNF_IGNR] = "CNF_IGNR",
63 : [CLS_ACPT] = "CLS_ACPT",
64 : [CLS_IGNR] = "CLS_IGNR"
65 : };
66 :
67 :
68 111 : static int mesh_mpm_parse_peer_mgmt(struct wpa_supplicant *wpa_s,
69 : u8 action_field,
70 : const u8 *ie, size_t len,
71 : struct mesh_peer_mgmt_ie *mpm_ie)
72 : {
73 111 : os_memset(mpm_ie, 0, sizeof(*mpm_ie));
74 :
75 : /* remove optional PMK at end */
76 111 : if (len >= 16) {
77 25 : len -= 16;
78 25 : mpm_ie->pmk = ie + len - 16;
79 : }
80 :
81 111 : if ((action_field == PLINK_OPEN && len != 4) ||
82 35 : (action_field == PLINK_CONFIRM && len != 6) ||
83 22 : (action_field == PLINK_CLOSE && len != 6 && len != 8)) {
84 0 : wpa_msg(wpa_s, MSG_DEBUG, "MPM: Invalid peer mgmt ie");
85 0 : return -1;
86 : }
87 :
88 : /* required fields */
89 111 : if (len < 4)
90 0 : return -1;
91 111 : mpm_ie->proto_id = ie;
92 111 : mpm_ie->llid = ie + 2;
93 111 : ie += 4;
94 111 : len -= 4;
95 :
96 : /* close reason is always present at end for close */
97 111 : if (action_field == PLINK_CLOSE) {
98 22 : if (len < 2)
99 0 : return -1;
100 22 : mpm_ie->reason = ie + len - 2;
101 22 : len -= 2;
102 : }
103 :
104 : /* plid, present for confirm, and possibly close */
105 111 : if (len)
106 57 : mpm_ie->plid = ie;
107 :
108 111 : return 0;
109 : }
110 :
111 :
112 89 : static int plink_free_count(struct hostapd_data *hapd)
113 : {
114 89 : if (hapd->max_plinks > hapd->num_plinks)
115 77 : return hapd->max_plinks - hapd->num_plinks;
116 12 : return 0;
117 : }
118 :
119 :
120 55 : static u16 copy_supp_rates(struct wpa_supplicant *wpa_s,
121 : struct sta_info *sta,
122 : struct ieee802_11_elems *elems)
123 : {
124 55 : if (!elems->supp_rates) {
125 0 : wpa_msg(wpa_s, MSG_ERROR, "no supported rates from " MACSTR,
126 0 : MAC2STR(sta->addr));
127 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
128 : }
129 :
130 55 : if (elems->supp_rates_len + elems->ext_supp_rates_len >
131 : sizeof(sta->supported_rates)) {
132 0 : wpa_msg(wpa_s, MSG_ERROR,
133 : "Invalid supported rates element length " MACSTR
134 0 : " %d+%d", MAC2STR(sta->addr), elems->supp_rates_len,
135 0 : elems->ext_supp_rates_len);
136 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
137 : }
138 :
139 165 : sta->supported_rates_len = merge_byte_arrays(
140 55 : sta->supported_rates, sizeof(sta->supported_rates),
141 55 : elems->supp_rates, elems->supp_rates_len,
142 55 : elems->ext_supp_rates, elems->ext_supp_rates_len);
143 :
144 55 : return WLAN_STATUS_SUCCESS;
145 : }
146 :
147 :
148 : /* return true if elems from a neighbor match this MBSS */
149 89 : static Boolean matches_local(struct wpa_supplicant *wpa_s,
150 : struct ieee802_11_elems *elems)
151 : {
152 89 : struct mesh_conf *mconf = wpa_s->ifmsh->mconf;
153 :
154 89 : if (elems->mesh_config_len < 5)
155 0 : return FALSE;
156 :
157 267 : return (mconf->meshid_len == elems->mesh_id_len &&
158 89 : os_memcmp(mconf->meshid, elems->mesh_id,
159 89 : elems->mesh_id_len) == 0 &&
160 178 : mconf->mesh_pp_id == elems->mesh_config[0] &&
161 178 : mconf->mesh_pm_id == elems->mesh_config[1] &&
162 178 : mconf->mesh_cc_id == elems->mesh_config[2] &&
163 267 : mconf->mesh_sp_id == elems->mesh_config[3] &&
164 89 : mconf->mesh_auth_id == elems->mesh_config[4]);
165 : }
166 :
167 :
168 : /* check if local link id is already used with another peer */
169 55 : static Boolean llid_in_use(struct wpa_supplicant *wpa_s, u16 llid)
170 : {
171 : struct sta_info *sta;
172 55 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
173 :
174 121 : for (sta = hapd->sta_list; sta; sta = sta->next) {
175 66 : if (sta->my_lid == llid)
176 0 : return TRUE;
177 : }
178 :
179 55 : return FALSE;
180 : }
181 :
182 :
183 : /* generate an llid for a link and set to initial state */
184 55 : static void mesh_mpm_init_link(struct wpa_supplicant *wpa_s,
185 : struct sta_info *sta)
186 : {
187 : u16 llid;
188 :
189 : do {
190 55 : if (os_get_random((u8 *) &llid, sizeof(llid)) < 0)
191 0 : continue;
192 55 : } while (!llid || llid_in_use(wpa_s, llid));
193 :
194 55 : sta->my_lid = llid;
195 55 : sta->peer_lid = 0;
196 :
197 : /*
198 : * We do not use wpa_mesh_set_plink_state() here because there is no
199 : * entry in kernel yet.
200 : */
201 55 : sta->plink_state = PLINK_LISTEN;
202 55 : }
203 :
204 :
205 143 : static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
206 : struct sta_info *sta,
207 : enum plink_action_field type,
208 : u16 close_reason)
209 : {
210 : struct wpabuf *buf;
211 143 : struct hostapd_iface *ifmsh = wpa_s->ifmsh;
212 143 : struct hostapd_data *bss = ifmsh->bss[0];
213 143 : struct mesh_conf *conf = ifmsh->mconf;
214 : u8 supp_rates[2 + 2 + 32];
215 : #ifdef CONFIG_IEEE80211N
216 : u8 ht_capa_oper[2 + 26 + 2 + 22];
217 : #endif /* CONFIG_IEEE80211N */
218 : u8 *pos, *cat;
219 143 : u8 ie_len, add_plid = 0;
220 : int ret;
221 143 : int ampe = conf->security & MESH_CONF_SEC_AMPE;
222 : size_t buf_len;
223 :
224 143 : if (!sta)
225 0 : return;
226 :
227 143 : buf_len = 2 + /* capability info */
228 : 2 + /* AID */
229 : 2 + 8 + /* supported rates */
230 : 2 + (32 - 8) +
231 : 2 + 32 + /* mesh ID */
232 : 2 + 7 + /* mesh config */
233 : 2 + 23 + /* peering management */
234 : 2 + 96 + /* AMPE */
235 : 2 + 16; /* MIC */
236 : #ifdef CONFIG_IEEE80211N
237 143 : if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
238 79 : buf_len += 2 + 26 + /* HT capabilities */
239 : 2 + 22; /* HT operation */
240 : }
241 : #endif /* CONFIG_IEEE80211N */
242 143 : buf = wpabuf_alloc(buf_len);
243 143 : if (!buf)
244 0 : return;
245 :
246 143 : cat = wpabuf_mhead_u8(buf);
247 143 : wpabuf_put_u8(buf, WLAN_ACTION_SELF_PROTECTED);
248 143 : wpabuf_put_u8(buf, type);
249 :
250 143 : if (type != PLINK_CLOSE) {
251 : u8 info;
252 :
253 : /* capability info */
254 89 : wpabuf_put_le16(buf, ampe ? IEEE80211_CAP_PRIVACY : 0);
255 :
256 : /* aid */
257 89 : if (type == PLINK_CONFIRM)
258 35 : wpabuf_put_le16(buf, sta->peer_lid);
259 :
260 : /* IE: supp + ext. supp rates */
261 89 : pos = hostapd_eid_supp_rates(bss, supp_rates);
262 89 : pos = hostapd_eid_ext_supp_rates(bss, pos);
263 89 : wpabuf_put_data(buf, supp_rates, pos - supp_rates);
264 :
265 : /* IE: Mesh ID */
266 89 : wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
267 89 : wpabuf_put_u8(buf, conf->meshid_len);
268 89 : wpabuf_put_data(buf, conf->meshid, conf->meshid_len);
269 :
270 : /* IE: mesh conf */
271 89 : wpabuf_put_u8(buf, WLAN_EID_MESH_CONFIG);
272 89 : wpabuf_put_u8(buf, 7);
273 89 : wpabuf_put_u8(buf, conf->mesh_pp_id);
274 89 : wpabuf_put_u8(buf, conf->mesh_pm_id);
275 89 : wpabuf_put_u8(buf, conf->mesh_cc_id);
276 89 : wpabuf_put_u8(buf, conf->mesh_sp_id);
277 89 : wpabuf_put_u8(buf, conf->mesh_auth_id);
278 89 : info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1;
279 : /* TODO: Add Connected to Mesh Gate/AS subfields */
280 89 : wpabuf_put_u8(buf, info);
281 : /* always forwarding & accepting plinks for now */
282 89 : wpabuf_put_u8(buf, 0x1 | 0x8);
283 : } else { /* Peer closing frame */
284 : /* IE: Mesh ID */
285 54 : wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
286 54 : wpabuf_put_u8(buf, conf->meshid_len);
287 54 : wpabuf_put_data(buf, conf->meshid, conf->meshid_len);
288 : }
289 :
290 : /* IE: Mesh Peering Management element */
291 143 : ie_len = 4;
292 143 : if (ampe)
293 38 : ie_len += PMKID_LEN;
294 143 : switch (type) {
295 : case PLINK_OPEN:
296 54 : break;
297 : case PLINK_CONFIRM:
298 35 : ie_len += 2;
299 35 : add_plid = 1;
300 35 : break;
301 : case PLINK_CLOSE:
302 54 : ie_len += 2;
303 54 : add_plid = 1;
304 54 : ie_len += 2; /* reason code */
305 54 : break;
306 : }
307 :
308 143 : wpabuf_put_u8(buf, WLAN_EID_PEER_MGMT);
309 143 : wpabuf_put_u8(buf, ie_len);
310 : /* peering protocol */
311 143 : if (ampe)
312 38 : wpabuf_put_le16(buf, 1);
313 : else
314 105 : wpabuf_put_le16(buf, 0);
315 143 : wpabuf_put_le16(buf, sta->my_lid);
316 143 : if (add_plid)
317 89 : wpabuf_put_le16(buf, sta->peer_lid);
318 143 : if (type == PLINK_CLOSE)
319 54 : wpabuf_put_le16(buf, close_reason);
320 143 : if (ampe) {
321 38 : if (sta->sae == NULL) {
322 0 : wpa_msg(wpa_s, MSG_INFO, "Mesh MPM: no SAE session");
323 0 : goto fail;
324 : }
325 38 : mesh_rsn_get_pmkid(wpa_s->mesh_rsn, sta,
326 38 : wpabuf_put(buf, PMKID_LEN));
327 : }
328 :
329 : #ifdef CONFIG_IEEE80211N
330 143 : if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
331 79 : pos = hostapd_eid_ht_capabilities(bss, ht_capa_oper);
332 79 : pos = hostapd_eid_ht_operation(bss, pos);
333 79 : wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper);
334 : }
335 : #endif /* CONFIG_IEEE80211N */
336 :
337 143 : if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
338 0 : wpa_msg(wpa_s, MSG_INFO,
339 : "Mesh MPM: failed to add AMPE and MIC IE");
340 0 : goto fail;
341 : }
342 :
343 286 : ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0,
344 143 : sta->addr, wpa_s->own_addr, wpa_s->own_addr,
345 143 : wpabuf_head(buf), wpabuf_len(buf), 0);
346 143 : if (ret < 0)
347 0 : wpa_msg(wpa_s, MSG_INFO,
348 : "Mesh MPM: failed to send peering frame");
349 :
350 : fail:
351 143 : wpabuf_free(buf);
352 : }
353 :
354 :
355 : /* configure peering state in ours and driver's station entry */
356 156 : void wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s,
357 : struct sta_info *sta,
358 : enum mesh_plink_state state)
359 : {
360 : struct hostapd_sta_add_params params;
361 : int ret;
362 :
363 156 : sta->plink_state = state;
364 :
365 156 : os_memset(¶ms, 0, sizeof(params));
366 156 : params.addr = sta->addr;
367 156 : params.plink_state = state;
368 156 : params.set = 1;
369 :
370 1092 : wpa_msg(wpa_s, MSG_DEBUG, "MPM set " MACSTR " into %s",
371 936 : MAC2STR(sta->addr), mplstate[state]);
372 156 : ret = wpa_drv_sta_add(wpa_s, ¶ms);
373 156 : if (ret) {
374 0 : wpa_msg(wpa_s, MSG_ERROR, "Driver failed to set " MACSTR
375 0 : ": %d", MAC2STR(sta->addr), ret);
376 : }
377 156 : }
378 :
379 :
380 4 : static void mesh_mpm_fsm_restart(struct wpa_supplicant *wpa_s,
381 : struct sta_info *sta)
382 : {
383 4 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
384 :
385 4 : eloop_cancel_timeout(plink_timer, wpa_s, sta);
386 :
387 4 : ap_free_sta(hapd, sta);
388 4 : }
389 :
390 :
391 16 : static void plink_timer(void *eloop_ctx, void *user_data)
392 : {
393 16 : struct wpa_supplicant *wpa_s = eloop_ctx;
394 16 : struct sta_info *sta = user_data;
395 16 : u16 reason = 0;
396 16 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
397 :
398 16 : switch (sta->plink_state) {
399 : case PLINK_OPEN_RCVD:
400 : case PLINK_OPEN_SENT:
401 : /* retry timer */
402 12 : if (sta->mpm_retries < conf->dot11MeshMaxRetries) {
403 18 : eloop_register_timeout(
404 9 : conf->dot11MeshRetryTimeout / 1000,
405 9 : (conf->dot11MeshRetryTimeout % 1000) * 1000,
406 : plink_timer, wpa_s, sta);
407 9 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0);
408 9 : sta->mpm_retries++;
409 9 : break;
410 : }
411 3 : reason = WLAN_REASON_MESH_MAX_RETRIES;
412 : /* fall through on else */
413 :
414 : case PLINK_CNF_RCVD:
415 : /* confirm timer */
416 3 : if (!reason)
417 0 : reason = WLAN_REASON_MESH_CONFIRM_TIMEOUT;
418 3 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
419 3 : eloop_register_timeout(conf->dot11MeshHoldingTimeout / 1000,
420 3 : (conf->dot11MeshHoldingTimeout % 1000) * 1000,
421 : plink_timer, wpa_s, sta);
422 3 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason);
423 3 : break;
424 : case PLINK_HOLDING:
425 : /* holding timer */
426 4 : mesh_mpm_fsm_restart(wpa_s, sta);
427 4 : break;
428 : default:
429 0 : break;
430 : }
431 16 : }
432 :
433 :
434 : /* initiate peering with station */
435 : static void
436 45 : mesh_mpm_plink_open(struct wpa_supplicant *wpa_s, struct sta_info *sta,
437 : enum mesh_plink_state next_state)
438 : {
439 45 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
440 :
441 45 : eloop_cancel_timeout(plink_timer, wpa_s, sta);
442 45 : eloop_register_timeout(conf->dot11MeshRetryTimeout / 1000,
443 45 : (conf->dot11MeshRetryTimeout % 1000) * 1000,
444 : plink_timer, wpa_s, sta);
445 45 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0);
446 45 : wpa_mesh_set_plink_state(wpa_s, sta, next_state);
447 45 : }
448 :
449 :
450 38 : int mesh_mpm_plink_close(struct hostapd_data *hapd,
451 : struct sta_info *sta, void *ctx)
452 : {
453 38 : struct wpa_supplicant *wpa_s = ctx;
454 38 : int reason = WLAN_REASON_MESH_PEERING_CANCELLED;
455 :
456 38 : if (sta) {
457 38 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
458 38 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason);
459 228 : wpa_printf(MSG_DEBUG, "MPM closing plink sta=" MACSTR,
460 228 : MAC2STR(sta->addr));
461 38 : eloop_cancel_timeout(plink_timer, wpa_s, sta);
462 38 : return 0;
463 : }
464 :
465 0 : return 1;
466 : }
467 :
468 :
469 34 : void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh)
470 : {
471 34 : struct hostapd_data *hapd = ifmsh->bss[0];
472 :
473 : /* notify peers we're leaving */
474 34 : ap_for_each_sta(hapd, mesh_mpm_plink_close, wpa_s);
475 :
476 34 : hapd->num_plinks = 0;
477 34 : hostapd_free_stas(hapd);
478 34 : }
479 :
480 :
481 : /* for mesh_rsn to indicate this peer has completed authentication, and we're
482 : * ready to start AMPE */
483 8 : void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr)
484 : {
485 8 : struct hostapd_data *data = wpa_s->ifmsh->bss[0];
486 : struct hostapd_sta_add_params params;
487 : struct sta_info *sta;
488 : int ret;
489 :
490 8 : sta = ap_get_sta(data, addr);
491 8 : if (!sta) {
492 0 : wpa_msg(wpa_s, MSG_DEBUG, "no such mesh peer");
493 8 : return;
494 : }
495 :
496 : /* TODO: Should do nothing if this STA is already authenticated, but
497 : * the AP code already sets this flag. */
498 8 : sta->flags |= WLAN_STA_AUTH;
499 :
500 8 : mesh_rsn_init_ampe_sta(wpa_s, sta);
501 :
502 8 : os_memset(¶ms, 0, sizeof(params));
503 8 : params.addr = sta->addr;
504 8 : params.flags = WPA_STA_AUTHENTICATED | WPA_STA_AUTHORIZED;
505 8 : params.set = 1;
506 :
507 48 : wpa_msg(wpa_s, MSG_DEBUG, "MPM authenticating " MACSTR,
508 48 : MAC2STR(sta->addr));
509 8 : ret = wpa_drv_sta_add(wpa_s, ¶ms);
510 8 : if (ret) {
511 0 : wpa_msg(wpa_s, MSG_ERROR,
512 : "Driver failed to set " MACSTR ": %d",
513 0 : MAC2STR(sta->addr), ret);
514 : }
515 :
516 8 : if (!sta->my_lid)
517 0 : mesh_mpm_init_link(wpa_s, sta);
518 :
519 8 : mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
520 : }
521 :
522 : /*
523 : * Initialize a sta_info structure for a peer and upload it into the driver
524 : * in preparation for beginning authentication or peering. This is done when a
525 : * Beacon (secure or open mesh) or a peering open frame (for open mesh) is
526 : * received from the peer for the first time.
527 : */
528 55 : static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
529 : const u8 *addr,
530 : struct ieee802_11_elems *elems)
531 : {
532 : struct hostapd_sta_add_params params;
533 55 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
534 55 : struct hostapd_data *data = wpa_s->ifmsh->bss[0];
535 : struct sta_info *sta;
536 : int ret;
537 :
538 55 : sta = ap_get_sta(data, addr);
539 55 : if (!sta) {
540 42 : sta = ap_sta_add(data, addr);
541 42 : if (!sta)
542 0 : return NULL;
543 : }
544 :
545 : /* initialize sta */
546 55 : if (copy_supp_rates(wpa_s, sta, elems)) {
547 0 : ap_free_sta(data, sta);
548 0 : return NULL;
549 : }
550 :
551 55 : mesh_mpm_init_link(wpa_s, sta);
552 :
553 : #ifdef CONFIG_IEEE80211N
554 55 : copy_sta_ht_capab(data, sta, elems->ht_capabilities,
555 55 : elems->ht_capabilities_len);
556 55 : update_ht_state(data, sta);
557 : #endif /* CONFIG_IEEE80211N */
558 :
559 : /* insert into driver */
560 55 : os_memset(¶ms, 0, sizeof(params));
561 55 : params.supp_rates = sta->supported_rates;
562 55 : params.supp_rates_len = sta->supported_rates_len;
563 55 : params.addr = addr;
564 55 : params.plink_state = sta->plink_state;
565 55 : params.aid = sta->peer_lid;
566 55 : params.listen_interval = 100;
567 55 : params.ht_capabilities = sta->ht_capabilities;
568 55 : params.flags |= WPA_STA_WMM;
569 55 : params.flags_mask |= WPA_STA_AUTHENTICATED;
570 55 : if (conf->security == MESH_CONF_SEC_NONE) {
571 37 : params.flags |= WPA_STA_AUTHORIZED;
572 37 : params.flags |= WPA_STA_AUTHENTICATED;
573 : } else {
574 18 : sta->flags |= WLAN_STA_MFP;
575 18 : params.flags |= WPA_STA_MFP;
576 : }
577 :
578 55 : ret = wpa_drv_sta_add(wpa_s, ¶ms);
579 55 : if (ret) {
580 0 : wpa_msg(wpa_s, MSG_ERROR,
581 : "Driver failed to insert " MACSTR ": %d",
582 0 : MAC2STR(addr), ret);
583 0 : ap_free_sta(data, sta);
584 0 : return NULL;
585 : }
586 :
587 55 : return sta;
588 : }
589 :
590 :
591 54 : void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
592 : struct ieee802_11_elems *elems)
593 : {
594 54 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
595 54 : struct hostapd_data *data = wpa_s->ifmsh->bss[0];
596 : struct sta_info *sta;
597 54 : struct wpa_ssid *ssid = wpa_s->current_ssid;
598 :
599 54 : sta = mesh_mpm_add_peer(wpa_s, addr, elems);
600 54 : if (!sta)
601 0 : return;
602 :
603 54 : if (ssid && ssid->no_auto_peer) {
604 12 : wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with "
605 12 : MACSTR " because of no_auto_peer", MAC2STR(addr));
606 2 : if (data->mesh_pending_auth) {
607 : struct os_reltime age;
608 : const struct ieee80211_mgmt *mgmt;
609 : struct hostapd_frame_info fi;
610 :
611 0 : mgmt = wpabuf_head(data->mesh_pending_auth);
612 0 : os_reltime_age(&data->mesh_pending_auth_time, &age);
613 0 : if (age.sec < 2 &&
614 0 : os_memcmp(mgmt->sa, addr, ETH_ALEN) == 0) {
615 0 : wpa_printf(MSG_DEBUG,
616 : "mesh: Process pending Authentication frame from %u.%06u seconds ago",
617 0 : (unsigned int) age.sec,
618 0 : (unsigned int) age.usec);
619 0 : os_memset(&fi, 0, sizeof(fi));
620 0 : ieee802_11_mgmt(
621 : data,
622 0 : wpabuf_head(data->mesh_pending_auth),
623 0 : wpabuf_len(data->mesh_pending_auth),
624 : &fi);
625 : }
626 0 : wpabuf_free(data->mesh_pending_auth);
627 0 : data->mesh_pending_auth = NULL;
628 : }
629 2 : return;
630 : }
631 :
632 52 : if (conf->security == MESH_CONF_SEC_NONE)
633 35 : mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
634 : else
635 17 : mesh_rsn_auth_sae_sta(wpa_s, sta);
636 : }
637 :
638 :
639 461 : void mesh_mpm_mgmt_rx(struct wpa_supplicant *wpa_s, struct rx_mgmt *rx_mgmt)
640 : {
641 : struct hostapd_frame_info fi;
642 :
643 461 : os_memset(&fi, 0, sizeof(fi));
644 461 : fi.datarate = rx_mgmt->datarate;
645 461 : fi.ssi_signal = rx_mgmt->ssi_signal;
646 461 : ieee802_11_mgmt(wpa_s->ifmsh->bss[0], rx_mgmt->frame,
647 : rx_mgmt->frame_len, &fi);
648 461 : }
649 :
650 :
651 26 : static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
652 : struct sta_info *sta)
653 : {
654 26 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
655 26 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
656 26 : u8 seq[6] = {};
657 :
658 156 : wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR " established",
659 156 : MAC2STR(sta->addr));
660 :
661 26 : if (conf->security & MESH_CONF_SEC_AMPE) {
662 8 : wpa_drv_set_key(wpa_s, WPA_ALG_CCMP, sta->addr, 0, 0,
663 8 : seq, sizeof(seq), sta->mtk, sizeof(sta->mtk));
664 8 : wpa_drv_set_key(wpa_s, WPA_ALG_CCMP, sta->addr, 1, 0,
665 : seq, sizeof(seq),
666 8 : sta->mgtk, sizeof(sta->mgtk));
667 8 : wpa_drv_set_key(wpa_s, WPA_ALG_IGTK, sta->addr, 4, 0,
668 : seq, sizeof(seq),
669 8 : sta->mgtk, sizeof(sta->mgtk));
670 :
671 8 : wpa_hexdump_key(MSG_DEBUG, "mtk:", sta->mtk, sizeof(sta->mtk));
672 8 : wpa_hexdump_key(MSG_DEBUG, "mgtk:",
673 8 : sta->mgtk, sizeof(sta->mgtk));
674 : }
675 :
676 26 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_ESTAB);
677 26 : hapd->num_plinks++;
678 :
679 26 : sta->flags |= WLAN_STA_ASSOC;
680 :
681 26 : eloop_cancel_timeout(plink_timer, wpa_s, sta);
682 :
683 : /* Send ctrl event */
684 156 : wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_PEER_CONNECTED MACSTR,
685 156 : MAC2STR(sta->addr));
686 26 : }
687 :
688 :
689 106 : static void mesh_mpm_fsm(struct wpa_supplicant *wpa_s, struct sta_info *sta,
690 : enum plink_event event)
691 : {
692 106 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
693 106 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
694 106 : u16 reason = 0;
695 :
696 848 : wpa_msg(wpa_s, MSG_DEBUG, "MPM " MACSTR " state %s event %s",
697 742 : MAC2STR(sta->addr), mplstate[sta->plink_state],
698 : mplevent[event]);
699 :
700 106 : switch (sta->plink_state) {
701 : case PLINK_LISTEN:
702 2 : switch (event) {
703 : case CLS_ACPT:
704 0 : mesh_mpm_fsm_restart(wpa_s, sta);
705 0 : break;
706 : case OPN_ACPT:
707 2 : mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_RCVD);
708 2 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CONFIRM,
709 : 0);
710 2 : break;
711 : default:
712 0 : break;
713 : }
714 2 : break;
715 : case PLINK_OPEN_SENT:
716 42 : switch (event) {
717 : case OPN_RJCT:
718 : case CNF_RJCT:
719 0 : reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
720 : /* fall-through */
721 : case CLS_ACPT:
722 0 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
723 0 : if (!reason)
724 0 : reason = WLAN_REASON_MESH_CLOSE_RCVD;
725 0 : eloop_register_timeout(
726 0 : conf->dot11MeshHoldingTimeout / 1000,
727 0 : (conf->dot11MeshHoldingTimeout % 1000) * 1000,
728 : plink_timer, wpa_s, sta);
729 0 : mesh_mpm_send_plink_action(wpa_s, sta,
730 : PLINK_CLOSE, reason);
731 0 : break;
732 : case OPN_ACPT:
733 : /* retry timer is left untouched */
734 29 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_OPEN_RCVD);
735 29 : mesh_mpm_send_plink_action(wpa_s, sta,
736 : PLINK_CONFIRM, 0);
737 29 : break;
738 : case CNF_ACPT:
739 0 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_CNF_RCVD);
740 0 : eloop_register_timeout(
741 0 : conf->dot11MeshConfirmTimeout / 1000,
742 0 : (conf->dot11MeshConfirmTimeout % 1000) * 1000,
743 : plink_timer, wpa_s, sta);
744 0 : break;
745 : default:
746 13 : break;
747 : }
748 42 : break;
749 : case PLINK_OPEN_RCVD:
750 48 : switch (event) {
751 : case OPN_RJCT:
752 : case CNF_RJCT:
753 0 : reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
754 : /* fall-through */
755 : case CLS_ACPT:
756 0 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
757 0 : if (!reason)
758 0 : reason = WLAN_REASON_MESH_CLOSE_RCVD;
759 0 : eloop_register_timeout(
760 0 : conf->dot11MeshHoldingTimeout / 1000,
761 0 : (conf->dot11MeshHoldingTimeout % 1000) * 1000,
762 : plink_timer, wpa_s, sta);
763 0 : sta->mpm_close_reason = reason;
764 0 : mesh_mpm_send_plink_action(wpa_s, sta,
765 : PLINK_CLOSE, reason);
766 0 : break;
767 : case OPN_ACPT:
768 4 : mesh_mpm_send_plink_action(wpa_s, sta,
769 : PLINK_CONFIRM, 0);
770 4 : break;
771 : case CNF_ACPT:
772 26 : if (conf->security & MESH_CONF_SEC_AMPE)
773 8 : mesh_rsn_derive_mtk(wpa_s, sta);
774 26 : mesh_mpm_plink_estab(wpa_s, sta);
775 26 : break;
776 : default:
777 18 : break;
778 : }
779 48 : break;
780 : case PLINK_CNF_RCVD:
781 0 : switch (event) {
782 : case OPN_RJCT:
783 : case CNF_RJCT:
784 0 : reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
785 : /* fall-through */
786 : case CLS_ACPT:
787 0 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
788 0 : if (!reason)
789 0 : reason = WLAN_REASON_MESH_CLOSE_RCVD;
790 0 : eloop_register_timeout(
791 0 : conf->dot11MeshHoldingTimeout / 1000,
792 0 : (conf->dot11MeshHoldingTimeout % 1000) * 1000,
793 : plink_timer, wpa_s, sta);
794 0 : sta->mpm_close_reason = reason;
795 0 : mesh_mpm_send_plink_action(wpa_s, sta,
796 : PLINK_CLOSE, reason);
797 0 : break;
798 : case OPN_ACPT:
799 0 : mesh_mpm_plink_estab(wpa_s, sta);
800 0 : mesh_mpm_send_plink_action(wpa_s, sta,
801 : PLINK_CONFIRM, 0);
802 0 : break;
803 : default:
804 0 : break;
805 : }
806 0 : break;
807 : case PLINK_ESTAB:
808 13 : switch (event) {
809 : case CLS_ACPT:
810 13 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
811 13 : reason = WLAN_REASON_MESH_CLOSE_RCVD;
812 :
813 26 : eloop_register_timeout(
814 13 : conf->dot11MeshHoldingTimeout / 1000,
815 13 : (conf->dot11MeshHoldingTimeout % 1000) * 1000,
816 : plink_timer, wpa_s, sta);
817 13 : sta->mpm_close_reason = reason;
818 :
819 91 : wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR
820 : " closed with reason %d",
821 78 : MAC2STR(sta->addr), reason);
822 :
823 78 : wpa_msg_ctrl(wpa_s, MSG_INFO,
824 : MESH_PEER_DISCONNECTED MACSTR,
825 78 : MAC2STR(sta->addr));
826 :
827 13 : hapd->num_plinks--;
828 :
829 13 : mesh_mpm_send_plink_action(wpa_s, sta,
830 : PLINK_CLOSE, reason);
831 13 : break;
832 : case OPN_ACPT:
833 0 : mesh_mpm_send_plink_action(wpa_s, sta,
834 : PLINK_CONFIRM, 0);
835 0 : break;
836 : default:
837 0 : break;
838 : }
839 13 : break;
840 : case PLINK_HOLDING:
841 1 : switch (event) {
842 : case CLS_ACPT:
843 0 : mesh_mpm_fsm_restart(wpa_s, sta);
844 0 : break;
845 : case OPN_ACPT:
846 : case CNF_ACPT:
847 : case OPN_RJCT:
848 : case CNF_RJCT:
849 0 : reason = sta->mpm_close_reason;
850 0 : mesh_mpm_send_plink_action(wpa_s, sta,
851 : PLINK_CLOSE, reason);
852 0 : break;
853 : default:
854 1 : break;
855 : }
856 1 : break;
857 : default:
858 0 : wpa_msg(wpa_s, MSG_DEBUG,
859 : "Unsupported MPM event %s for state %s",
860 0 : mplevent[event], mplstate[sta->plink_state]);
861 0 : break;
862 : }
863 106 : }
864 :
865 :
866 111 : void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s,
867 : const struct ieee80211_mgmt *mgmt, size_t len)
868 : {
869 : u8 action_field;
870 111 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
871 111 : struct mesh_conf *mconf = wpa_s->ifmsh->mconf;
872 : struct sta_info *sta;
873 111 : u16 plid = 0, llid = 0;
874 : enum plink_event event;
875 : struct ieee802_11_elems elems;
876 : struct mesh_peer_mgmt_ie peer_mgmt_ie;
877 : const u8 *ies;
878 : size_t ie_len;
879 : int ret;
880 :
881 111 : if (mgmt->u.action.category != WLAN_ACTION_SELF_PROTECTED)
882 5 : return;
883 :
884 111 : action_field = mgmt->u.action.u.slf_prot_action.action;
885 111 : if (action_field != PLINK_OPEN &&
886 22 : action_field != PLINK_CONFIRM &&
887 : action_field != PLINK_CLOSE)
888 0 : return;
889 :
890 111 : ies = mgmt->u.action.u.slf_prot_action.variable;
891 111 : ie_len = (const u8 *) mgmt + len -
892 : mgmt->u.action.u.slf_prot_action.variable;
893 :
894 : /* at least expect mesh id and peering mgmt */
895 111 : if (ie_len < 2 + 2) {
896 0 : wpa_printf(MSG_DEBUG,
897 : "MPM: Ignore too short action frame %u ie_len %u",
898 : action_field, (unsigned int) ie_len);
899 0 : return;
900 : }
901 111 : wpa_printf(MSG_DEBUG, "MPM: Received PLINK action %u", action_field);
902 :
903 111 : if (action_field == PLINK_OPEN || action_field == PLINK_CONFIRM) {
904 89 : wpa_printf(MSG_DEBUG, "MPM: Capability 0x%x",
905 89 : WPA_GET_LE16(ies));
906 89 : ies += 2; /* capability */
907 89 : ie_len -= 2;
908 : }
909 111 : if (action_field == PLINK_CONFIRM) {
910 35 : wpa_printf(MSG_DEBUG, "MPM: AID 0x%x", WPA_GET_LE16(ies));
911 35 : ies += 2; /* aid */
912 35 : ie_len -= 2;
913 : }
914 :
915 : /* check for mesh peering, mesh id and mesh config IEs */
916 111 : if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed) {
917 0 : wpa_printf(MSG_DEBUG, "MPM: Failed to parse PLINK IEs");
918 0 : return;
919 : }
920 111 : if (!elems.peer_mgmt) {
921 0 : wpa_printf(MSG_DEBUG,
922 : "MPM: No Mesh Peering Management element");
923 0 : return;
924 : }
925 111 : if (action_field != PLINK_CLOSE) {
926 89 : if (!elems.mesh_id || !elems.mesh_config) {
927 0 : wpa_printf(MSG_DEBUG,
928 : "MPM: No Mesh ID or Mesh Configuration element");
929 0 : return;
930 : }
931 :
932 89 : if (!matches_local(wpa_s, &elems)) {
933 0 : wpa_printf(MSG_DEBUG,
934 : "MPM: Mesh ID or Mesh Configuration element do not match local MBSS");
935 0 : return;
936 : }
937 : }
938 :
939 111 : ret = mesh_mpm_parse_peer_mgmt(wpa_s, action_field,
940 : elems.peer_mgmt,
941 111 : elems.peer_mgmt_len,
942 : &peer_mgmt_ie);
943 111 : if (ret) {
944 0 : wpa_printf(MSG_DEBUG, "MPM: Mesh parsing rejected frame");
945 0 : return;
946 : }
947 :
948 : /* the sender's llid is our plid and vice-versa */
949 111 : plid = WPA_GET_LE16(peer_mgmt_ie.llid);
950 111 : if (peer_mgmt_ie.plid)
951 57 : llid = WPA_GET_LE16(peer_mgmt_ie.plid);
952 111 : wpa_printf(MSG_DEBUG, "MPM: plid=0x%x llid=0x%x", plid, llid);
953 :
954 111 : sta = ap_get_sta(hapd, mgmt->sa);
955 :
956 : /*
957 : * If this is an open frame from an unknown STA, and this is an
958 : * open mesh, then go ahead and add the peer before proceeding.
959 : */
960 112 : if (!sta && action_field == PLINK_OPEN &&
961 1 : !(mconf->security & MESH_CONF_SEC_AMPE))
962 1 : sta = mesh_mpm_add_peer(wpa_s, mgmt->sa, &elems);
963 :
964 111 : if (!sta) {
965 0 : wpa_printf(MSG_DEBUG, "MPM: No STA entry for peer");
966 0 : return;
967 : }
968 :
969 : #ifdef CONFIG_SAE
970 : /* peer is in sae_accepted? */
971 111 : if (sta->sae && sta->sae->state != SAE_ACCEPTED) {
972 5 : wpa_printf(MSG_DEBUG, "MPM: SAE not yet accepted for peer");
973 5 : return;
974 : }
975 : #endif /* CONFIG_SAE */
976 :
977 106 : if (!sta->my_lid)
978 0 : mesh_mpm_init_link(wpa_s, sta);
979 :
980 126 : if ((mconf->security & MESH_CONF_SEC_AMPE) &&
981 20 : mesh_rsn_process_ampe(wpa_s, sta, &elems,
982 : &mgmt->u.action.category,
983 : ies, ie_len)) {
984 0 : wpa_printf(MSG_DEBUG, "MPM: RSN process rejected frame");
985 0 : return;
986 : }
987 :
988 106 : if (sta->plink_state == PLINK_BLOCKED) {
989 0 : wpa_printf(MSG_DEBUG, "MPM: PLINK_BLOCKED");
990 0 : return;
991 : }
992 :
993 : /* Now we will figure out the appropriate event... */
994 106 : switch (action_field) {
995 : case PLINK_OPEN:
996 54 : if (plink_free_count(hapd) == 0) {
997 6 : event = OPN_IGNR;
998 6 : wpa_printf(MSG_INFO,
999 : "MPM: Peer link num over quota(%d)",
1000 : hapd->max_plinks);
1001 48 : } else if (sta->peer_lid && sta->peer_lid != plid) {
1002 13 : event = OPN_IGNR;
1003 : } else {
1004 35 : sta->peer_lid = plid;
1005 35 : event = OPN_ACPT;
1006 : }
1007 54 : break;
1008 : case PLINK_CONFIRM:
1009 35 : if (plink_free_count(hapd) == 0) {
1010 6 : event = CNF_IGNR;
1011 6 : wpa_printf(MSG_INFO,
1012 : "MPM: Peer link num over quota(%d)",
1013 : hapd->max_plinks);
1014 57 : } else if (sta->my_lid != llid ||
1015 56 : (sta->peer_lid && sta->peer_lid != plid)) {
1016 3 : event = CNF_IGNR;
1017 : } else {
1018 26 : if (!sta->peer_lid)
1019 0 : sta->peer_lid = plid;
1020 26 : event = CNF_ACPT;
1021 : }
1022 35 : break;
1023 : case PLINK_CLOSE:
1024 17 : if (sta->plink_state == PLINK_ESTAB)
1025 : /* Do not check for llid or plid. This does not
1026 : * follow the standard but since multiple plinks
1027 : * per cand are not supported, it is necessary in
1028 : * order to avoid a livelock when MP A sees an
1029 : * establish peer link to MP B but MP B does not
1030 : * see it. This can be caused by a timeout in
1031 : * B's peer link establishment or B being
1032 : * restarted.
1033 : */
1034 13 : event = CLS_ACPT;
1035 4 : else if (sta->peer_lid != plid)
1036 2 : event = CLS_IGNR;
1037 2 : else if (peer_mgmt_ie.plid && sta->my_lid != llid)
1038 2 : event = CLS_IGNR;
1039 : else
1040 0 : event = CLS_ACPT;
1041 17 : break;
1042 : default:
1043 : /*
1044 : * This cannot be hit due to the action_field check above, but
1045 : * compilers may not be able to figure that out and can warn
1046 : * about uninitialized event below.
1047 : */
1048 0 : return;
1049 : }
1050 106 : mesh_mpm_fsm(wpa_s, sta, event);
1051 : }
1052 :
1053 :
1054 : /* called by ap_free_sta */
1055 42 : void mesh_mpm_free_sta(struct sta_info *sta)
1056 : {
1057 42 : eloop_cancel_timeout(plink_timer, ELOOP_ALL_CTX, sta);
1058 42 : eloop_cancel_timeout(mesh_auth_timer, ELOOP_ALL_CTX, sta);
1059 42 : }
|