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 117 : 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 117 : os_memset(mpm_ie, 0, sizeof(*mpm_ie));
74 :
75 : /* remove optional PMK at end */
76 117 : if (len >= 16) {
77 17 : len -= 16;
78 17 : mpm_ie->pmk = ie + len - 16;
79 : }
80 :
81 117 : if ((action_field == PLINK_OPEN && len != 4) ||
82 31 : (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 117 : if (len < 4)
90 0 : return -1;
91 117 : mpm_ie->proto_id = ie;
92 117 : mpm_ie->llid = ie + 2;
93 117 : ie += 4;
94 117 : len -= 4;
95 :
96 : /* close reason is always present at end for close */
97 117 : 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 117 : if (len)
106 53 : mpm_ie->plid = ie;
107 :
108 117 : return 0;
109 : }
110 :
111 :
112 95 : static int plink_free_count(struct hostapd_data *hapd)
113 : {
114 95 : if (hapd->max_plinks > hapd->num_plinks)
115 86 : return hapd->max_plinks - hapd->num_plinks;
116 9 : return 0;
117 : }
118 :
119 :
120 58 : static u16 copy_supp_rates(struct wpa_supplicant *wpa_s,
121 : struct sta_info *sta,
122 : struct ieee802_11_elems *elems)
123 : {
124 58 : 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 58 : 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 174 : sta->supported_rates_len = merge_byte_arrays(
140 58 : sta->supported_rates, sizeof(sta->supported_rates),
141 58 : elems->supp_rates, elems->supp_rates_len,
142 58 : elems->ext_supp_rates, elems->ext_supp_rates_len);
143 :
144 58 : return WLAN_STATUS_SUCCESS;
145 : }
146 :
147 :
148 : /* return true if elems from a neighbor match this MBSS */
149 95 : static Boolean matches_local(struct wpa_supplicant *wpa_s,
150 : struct ieee802_11_elems *elems)
151 : {
152 95 : struct mesh_conf *mconf = wpa_s->ifmsh->mconf;
153 :
154 95 : if (elems->mesh_config_len < 5)
155 0 : return FALSE;
156 :
157 285 : return (mconf->meshid_len == elems->mesh_id_len &&
158 95 : os_memcmp(mconf->meshid, elems->mesh_id,
159 95 : elems->mesh_id_len) == 0 &&
160 190 : mconf->mesh_pp_id == elems->mesh_config[0] &&
161 190 : mconf->mesh_pm_id == elems->mesh_config[1] &&
162 190 : mconf->mesh_cc_id == elems->mesh_config[2] &&
163 285 : mconf->mesh_sp_id == elems->mesh_config[3] &&
164 95 : mconf->mesh_auth_id == elems->mesh_config[4]);
165 : }
166 :
167 :
168 : /* check if local link id is already used with another peer */
169 58 : static Boolean llid_in_use(struct wpa_supplicant *wpa_s, u16 llid)
170 : {
171 : struct sta_info *sta;
172 58 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
173 :
174 124 : for (sta = hapd->sta_list; sta; sta = sta->next) {
175 66 : if (sta->my_lid == llid)
176 0 : return TRUE;
177 : }
178 :
179 58 : return FALSE;
180 : }
181 :
182 :
183 : /* generate an llid for a link and set to initial state */
184 58 : static void mesh_mpm_init_link(struct wpa_supplicant *wpa_s,
185 : struct sta_info *sta)
186 : {
187 : u16 llid;
188 :
189 : do {
190 58 : if (os_get_random((u8 *) &llid, sizeof(llid)) < 0)
191 0 : continue;
192 58 : } while (!llid || llid_in_use(wpa_s, llid));
193 :
194 58 : sta->my_lid = llid;
195 58 : 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 58 : sta->plink_state = PLINK_LISTEN;
202 58 : }
203 :
204 :
205 163 : 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 163 : struct hostapd_iface *ifmsh = wpa_s->ifmsh;
212 163 : struct hostapd_data *bss = ifmsh->bss[0];
213 163 : 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 163 : u8 ie_len, add_plid = 0;
220 : int ret;
221 163 : int ampe = conf->security & MESH_CONF_SEC_AMPE;
222 : size_t buf_len;
223 :
224 163 : if (!sta)
225 0 : return;
226 :
227 163 : 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 163 : if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
238 113 : buf_len += 2 + 26 + /* HT capabilities */
239 : 2 + 22; /* HT operation */
240 : }
241 : #endif /* CONFIG_IEEE80211N */
242 163 : buf = wpabuf_alloc(buf_len);
243 163 : if (!buf)
244 0 : return;
245 :
246 163 : cat = wpabuf_mhead_u8(buf);
247 163 : wpabuf_put_u8(buf, WLAN_ACTION_SELF_PROTECTED);
248 163 : wpabuf_put_u8(buf, type);
249 :
250 163 : if (type != PLINK_CLOSE) {
251 : u8 info;
252 :
253 : /* capability info */
254 113 : wpabuf_put_le16(buf, ampe ? IEEE80211_CAP_PRIVACY : 0);
255 :
256 : /* aid */
257 113 : if (type == PLINK_CONFIRM)
258 40 : wpabuf_put_le16(buf, sta->peer_lid);
259 :
260 : /* IE: supp + ext. supp rates */
261 113 : pos = hostapd_eid_supp_rates(bss, supp_rates);
262 113 : pos = hostapd_eid_ext_supp_rates(bss, pos);
263 113 : wpabuf_put_data(buf, supp_rates, pos - supp_rates);
264 :
265 : /* IE: Mesh ID */
266 113 : wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
267 113 : wpabuf_put_u8(buf, conf->meshid_len);
268 113 : wpabuf_put_data(buf, conf->meshid, conf->meshid_len);
269 :
270 : /* IE: mesh conf */
271 113 : wpabuf_put_u8(buf, WLAN_EID_MESH_CONFIG);
272 113 : wpabuf_put_u8(buf, 7);
273 113 : wpabuf_put_u8(buf, conf->mesh_pp_id);
274 113 : wpabuf_put_u8(buf, conf->mesh_pm_id);
275 113 : wpabuf_put_u8(buf, conf->mesh_cc_id);
276 113 : wpabuf_put_u8(buf, conf->mesh_sp_id);
277 113 : wpabuf_put_u8(buf, conf->mesh_auth_id);
278 113 : info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1;
279 : /* TODO: Add Connected to Mesh Gate/AS subfields */
280 113 : wpabuf_put_u8(buf, info);
281 : /* always forwarding & accepting plinks for now */
282 113 : wpabuf_put_u8(buf, 0x1 | 0x8);
283 : } else { /* Peer closing frame */
284 : /* IE: Mesh ID */
285 50 : wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
286 50 : wpabuf_put_u8(buf, conf->meshid_len);
287 50 : wpabuf_put_data(buf, conf->meshid, conf->meshid_len);
288 : }
289 :
290 : /* IE: Mesh Peering Management element */
291 163 : ie_len = 4;
292 163 : if (ampe)
293 25 : ie_len += PMKID_LEN;
294 163 : switch (type) {
295 : case PLINK_OPEN:
296 73 : break;
297 : case PLINK_CONFIRM:
298 40 : ie_len += 2;
299 40 : add_plid = 1;
300 40 : break;
301 : case PLINK_CLOSE:
302 50 : ie_len += 2;
303 50 : add_plid = 1;
304 50 : ie_len += 2; /* reason code */
305 50 : break;
306 : }
307 :
308 163 : wpabuf_put_u8(buf, WLAN_EID_PEER_MGMT);
309 163 : wpabuf_put_u8(buf, ie_len);
310 : /* peering protocol */
311 163 : if (ampe)
312 25 : wpabuf_put_le16(buf, 1);
313 : else
314 138 : wpabuf_put_le16(buf, 0);
315 163 : wpabuf_put_le16(buf, sta->my_lid);
316 163 : if (add_plid)
317 90 : wpabuf_put_le16(buf, sta->peer_lid);
318 163 : if (type == PLINK_CLOSE)
319 50 : wpabuf_put_le16(buf, close_reason);
320 163 : if (ampe) {
321 25 : if (sta->sae == NULL) {
322 0 : wpa_msg(wpa_s, MSG_INFO, "Mesh MPM: no SAE session");
323 0 : goto fail;
324 : }
325 25 : mesh_rsn_get_pmkid(wpa_s->mesh_rsn, sta,
326 25 : wpabuf_put(buf, PMKID_LEN));
327 : }
328 :
329 : #ifdef CONFIG_IEEE80211N
330 163 : if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
331 113 : pos = hostapd_eid_ht_capabilities(bss, ht_capa_oper);
332 113 : pos = hostapd_eid_ht_operation(bss, pos);
333 113 : wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper);
334 : }
335 : #endif /* CONFIG_IEEE80211N */
336 :
337 163 : 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 326 : ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0,
344 163 : sta->addr, wpa_s->own_addr, wpa_s->own_addr,
345 163 : wpabuf_head(buf), wpabuf_len(buf), 0);
346 163 : if (ret < 0)
347 0 : wpa_msg(wpa_s, MSG_INFO,
348 : "Mesh MPM: failed to send peering frame");
349 :
350 : fail:
351 163 : wpabuf_free(buf);
352 : }
353 :
354 :
355 : /* configure peering state in ours and driver's station entry */
356 151 : 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 151 : sta->plink_state = state;
364 :
365 151 : os_memset(¶ms, 0, sizeof(params));
366 151 : params.addr = sta->addr;
367 151 : params.plink_state = state;
368 151 : params.set = 1;
369 :
370 1057 : wpa_msg(wpa_s, MSG_DEBUG, "MPM set " MACSTR " into %s",
371 906 : MAC2STR(sta->addr), mplstate[state]);
372 151 : ret = wpa_drv_sta_add(wpa_s, ¶ms);
373 151 : if (ret) {
374 0 : wpa_msg(wpa_s, MSG_ERROR, "Driver failed to set " MACSTR
375 0 : ": %d", MAC2STR(sta->addr), ret);
376 : }
377 151 : }
378 :
379 :
380 12 : static void mesh_mpm_fsm_restart(struct wpa_supplicant *wpa_s,
381 : struct sta_info *sta)
382 : {
383 12 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
384 :
385 12 : eloop_cancel_timeout(plink_timer, wpa_s, sta);
386 :
387 12 : ap_free_sta(hapd, sta);
388 12 : }
389 :
390 :
391 42 : static void plink_timer(void *eloop_ctx, void *user_data)
392 : {
393 42 : struct wpa_supplicant *wpa_s = eloop_ctx;
394 42 : struct sta_info *sta = user_data;
395 42 : u16 reason = 0;
396 42 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
397 :
398 42 : switch (sta->plink_state) {
399 : case PLINK_OPEN_RCVD:
400 : case PLINK_OPEN_SENT:
401 : /* retry timer */
402 30 : if (sta->mpm_retries < conf->dot11MeshMaxRetries) {
403 40 : eloop_register_timeout(
404 20 : conf->dot11MeshRetryTimeout / 1000,
405 20 : (conf->dot11MeshRetryTimeout % 1000) * 1000,
406 : plink_timer, wpa_s, sta);
407 20 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0);
408 20 : sta->mpm_retries++;
409 20 : break;
410 : }
411 10 : reason = WLAN_REASON_MESH_MAX_RETRIES;
412 : /* fall through on else */
413 :
414 : case PLINK_CNF_RCVD:
415 : /* confirm timer */
416 10 : if (!reason)
417 0 : reason = WLAN_REASON_MESH_CONFIRM_TIMEOUT;
418 10 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
419 10 : eloop_register_timeout(conf->dot11MeshHoldingTimeout / 1000,
420 10 : (conf->dot11MeshHoldingTimeout % 1000) * 1000,
421 : plink_timer, wpa_s, sta);
422 10 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason);
423 10 : break;
424 : case PLINK_HOLDING:
425 : /* holding timer */
426 12 : mesh_mpm_fsm_restart(wpa_s, sta);
427 12 : break;
428 : default:
429 0 : break;
430 : }
431 42 : }
432 :
433 :
434 : /* initiate peering with station */
435 : static void
436 53 : mesh_mpm_plink_open(struct wpa_supplicant *wpa_s, struct sta_info *sta,
437 : enum mesh_plink_state next_state)
438 : {
439 53 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
440 :
441 53 : eloop_cancel_timeout(plink_timer, wpa_s, sta);
442 53 : eloop_register_timeout(conf->dot11MeshRetryTimeout / 1000,
443 53 : (conf->dot11MeshRetryTimeout % 1000) * 1000,
444 : plink_timer, wpa_s, sta);
445 53 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0);
446 53 : wpa_mesh_set_plink_state(wpa_s, sta, next_state);
447 53 : }
448 :
449 :
450 28 : int mesh_mpm_plink_close(struct hostapd_data *hapd,
451 : struct sta_info *sta, void *ctx)
452 : {
453 28 : struct wpa_supplicant *wpa_s = ctx;
454 28 : int reason = WLAN_REASON_MESH_PEERING_CANCELLED;
455 :
456 28 : if (sta) {
457 28 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
458 28 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason);
459 168 : wpa_printf(MSG_DEBUG, "MPM closing plink sta=" MACSTR,
460 168 : MAC2STR(sta->addr));
461 28 : eloop_cancel_timeout(plink_timer, wpa_s, sta);
462 28 : return 0;
463 : }
464 :
465 0 : return 1;
466 : }
467 :
468 :
469 29 : void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh)
470 : {
471 29 : struct hostapd_data *hapd = ifmsh->bss[0];
472 :
473 : /* notify peers we're leaving */
474 29 : ap_for_each_sta(hapd, mesh_mpm_plink_close, wpa_s);
475 :
476 29 : hapd->num_plinks = 0;
477 29 : hostapd_free_stas(hapd);
478 29 : }
479 :
480 :
481 : /* for mesh_rsn to indicate this peer has completed authentication, and we're
482 : * ready to start AMPE */
483 6 : void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr)
484 : {
485 6 : 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 6 : sta = ap_get_sta(data, addr);
491 6 : if (!sta) {
492 0 : wpa_msg(wpa_s, MSG_DEBUG, "no such mesh peer");
493 6 : return;
494 : }
495 :
496 : /* TODO: Should do nothing if this STA is already authenticated, but
497 : * the AP code already sets this flag. */
498 6 : sta->flags |= WLAN_STA_AUTH;
499 :
500 6 : mesh_rsn_init_ampe_sta(wpa_s, sta);
501 :
502 6 : os_memset(¶ms, 0, sizeof(params));
503 6 : params.addr = sta->addr;
504 6 : params.flags = WPA_STA_AUTHENTICATED | WPA_STA_AUTHORIZED;
505 6 : params.set = 1;
506 :
507 36 : wpa_msg(wpa_s, MSG_DEBUG, "MPM authenticating " MACSTR,
508 36 : MAC2STR(sta->addr));
509 6 : ret = wpa_drv_sta_add(wpa_s, ¶ms);
510 6 : 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 6 : if (!sta->my_lid)
517 0 : mesh_mpm_init_link(wpa_s, sta);
518 :
519 6 : 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 58 : 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 58 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
534 58 : struct hostapd_data *data = wpa_s->ifmsh->bss[0];
535 : struct sta_info *sta;
536 : int ret;
537 :
538 58 : sta = ap_get_sta(data, addr);
539 58 : if (!sta) {
540 40 : sta = ap_sta_add(data, addr);
541 40 : if (!sta)
542 0 : return NULL;
543 : }
544 :
545 : /* initialize sta */
546 58 : if (copy_supp_rates(wpa_s, sta, elems)) {
547 0 : ap_free_sta(data, sta);
548 0 : return NULL;
549 : }
550 :
551 58 : mesh_mpm_init_link(wpa_s, sta);
552 :
553 : #ifdef CONFIG_IEEE80211N
554 58 : copy_sta_ht_capab(data, sta, elems->ht_capabilities,
555 58 : elems->ht_capabilities_len);
556 58 : update_ht_state(data, sta);
557 : #endif /* CONFIG_IEEE80211N */
558 :
559 : /* insert into driver */
560 58 : os_memset(¶ms, 0, sizeof(params));
561 58 : params.supp_rates = sta->supported_rates;
562 58 : params.supp_rates_len = sta->supported_rates_len;
563 58 : params.addr = addr;
564 58 : params.plink_state = sta->plink_state;
565 58 : params.aid = sta->peer_lid;
566 58 : params.listen_interval = 100;
567 58 : params.ht_capabilities = sta->ht_capabilities;
568 58 : params.flags |= WPA_STA_WMM;
569 58 : params.flags_mask |= WPA_STA_AUTHENTICATED;
570 58 : if (conf->security == MESH_CONF_SEC_NONE) {
571 48 : params.flags |= WPA_STA_AUTHORIZED;
572 48 : params.flags |= WPA_STA_AUTHENTICATED;
573 : } else {
574 10 : sta->flags |= WLAN_STA_MFP;
575 10 : params.flags |= WPA_STA_MFP;
576 : }
577 :
578 58 : ret = wpa_drv_sta_add(wpa_s, ¶ms);
579 58 : 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 58 : return sta;
588 : }
589 :
590 :
591 50 : void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
592 : struct ieee802_11_elems *elems)
593 : {
594 50 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
595 50 : struct hostapd_data *data = wpa_s->ifmsh->bss[0];
596 : struct sta_info *sta;
597 50 : struct wpa_ssid *ssid = wpa_s->current_ssid;
598 :
599 50 : sta = mesh_mpm_add_peer(wpa_s, addr, elems);
600 50 : if (!sta)
601 0 : return;
602 :
603 50 : 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 1 : mgmt = wpabuf_head(data->mesh_pending_auth);
612 1 : os_reltime_age(&data->mesh_pending_auth_time, &age);
613 2 : if (age.sec < 2 &&
614 1 : os_memcmp(mgmt->sa, addr, ETH_ALEN) == 0) {
615 2 : wpa_printf(MSG_DEBUG,
616 : "mesh: Process pending Authentication frame from %u.%06u seconds ago",
617 1 : (unsigned int) age.sec,
618 1 : (unsigned int) age.usec);
619 1 : os_memset(&fi, 0, sizeof(fi));
620 2 : ieee802_11_mgmt(
621 : data,
622 1 : wpabuf_head(data->mesh_pending_auth),
623 1 : wpabuf_len(data->mesh_pending_auth),
624 : &fi);
625 : }
626 1 : wpabuf_free(data->mesh_pending_auth);
627 1 : data->mesh_pending_auth = NULL;
628 : }
629 2 : return;
630 : }
631 :
632 48 : if (conf->security == MESH_CONF_SEC_NONE)
633 39 : mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
634 : else
635 9 : mesh_rsn_auth_sae_sta(wpa_s, sta);
636 : }
637 :
638 :
639 119 : void mesh_mpm_mgmt_rx(struct wpa_supplicant *wpa_s, struct rx_mgmt *rx_mgmt)
640 : {
641 : struct hostapd_frame_info fi;
642 :
643 119 : os_memset(&fi, 0, sizeof(fi));
644 119 : fi.datarate = rx_mgmt->datarate;
645 119 : fi.ssi_signal = rx_mgmt->ssi_signal;
646 119 : ieee802_11_mgmt(wpa_s->ifmsh->bss[0], rx_mgmt->frame,
647 : rx_mgmt->frame_len, &fi);
648 119 : }
649 :
650 :
651 24 : static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
652 : struct sta_info *sta)
653 : {
654 24 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
655 24 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
656 24 : u8 seq[6] = {};
657 :
658 144 : wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR " established",
659 144 : MAC2STR(sta->addr));
660 :
661 24 : if (conf->security & MESH_CONF_SEC_AMPE) {
662 6 : wpa_drv_set_key(wpa_s, WPA_ALG_CCMP, sta->addr, 0, 0,
663 6 : seq, sizeof(seq), sta->mtk, sizeof(sta->mtk));
664 6 : wpa_drv_set_key(wpa_s, WPA_ALG_CCMP, sta->addr, 1, 0,
665 : seq, sizeof(seq),
666 6 : sta->mgtk, sizeof(sta->mgtk));
667 6 : wpa_drv_set_key(wpa_s, WPA_ALG_IGTK, sta->addr, 4, 0,
668 : seq, sizeof(seq),
669 6 : sta->mgtk, sizeof(sta->mgtk));
670 :
671 6 : wpa_hexdump_key(MSG_DEBUG, "mtk:", sta->mtk, sizeof(sta->mtk));
672 6 : wpa_hexdump_key(MSG_DEBUG, "mgtk:",
673 6 : sta->mgtk, sizeof(sta->mgtk));
674 : }
675 :
676 24 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_ESTAB);
677 24 : hapd->num_plinks++;
678 :
679 24 : sta->flags |= WLAN_STA_ASSOC;
680 :
681 24 : eloop_cancel_timeout(plink_timer, wpa_s, sta);
682 :
683 : /* Send ctrl event */
684 144 : wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_PEER_CONNECTED MACSTR,
685 144 : MAC2STR(sta->addr));
686 24 : }
687 :
688 :
689 114 : static void mesh_mpm_fsm(struct wpa_supplicant *wpa_s, struct sta_info *sta,
690 : enum plink_event event)
691 : {
692 114 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
693 114 : struct mesh_conf *conf = wpa_s->ifmsh->mconf;
694 114 : u16 reason = 0;
695 :
696 912 : wpa_msg(wpa_s, MSG_DEBUG, "MPM " MACSTR " state %s event %s",
697 798 : MAC2STR(sta->addr), mplstate[sta->plink_state],
698 : mplevent[event]);
699 :
700 114 : switch (sta->plink_state) {
701 : case PLINK_LISTEN:
702 12 : switch (event) {
703 : case CLS_ACPT:
704 0 : mesh_mpm_fsm_restart(wpa_s, sta);
705 0 : break;
706 : case OPN_ACPT:
707 8 : mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_RCVD);
708 8 : mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CONFIRM,
709 : 0);
710 8 : break;
711 : default:
712 4 : break;
713 : }
714 12 : break;
715 : case PLINK_OPEN_SENT:
716 31 : 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 24 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_OPEN_RCVD);
735 24 : mesh_mpm_send_plink_action(wpa_s, sta,
736 : PLINK_CONFIRM, 0);
737 24 : 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 7 : break;
747 : }
748 31 : break;
749 : case PLINK_OPEN_RCVD:
750 58 : 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 8 : mesh_mpm_send_plink_action(wpa_s, sta,
769 : PLINK_CONFIRM, 0);
770 8 : break;
771 : case CNF_ACPT:
772 24 : if (conf->security & MESH_CONF_SEC_AMPE)
773 6 : mesh_rsn_derive_mtk(wpa_s, sta);
774 24 : mesh_mpm_plink_estab(wpa_s, sta);
775 24 : break;
776 : default:
777 26 : break;
778 : }
779 58 : 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 12 : switch (event) {
809 : case CLS_ACPT:
810 12 : wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
811 12 : reason = WLAN_REASON_MESH_CLOSE_RCVD;
812 :
813 24 : eloop_register_timeout(
814 12 : conf->dot11MeshHoldingTimeout / 1000,
815 12 : (conf->dot11MeshHoldingTimeout % 1000) * 1000,
816 : plink_timer, wpa_s, sta);
817 12 : sta->mpm_close_reason = reason;
818 :
819 84 : wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR
820 : " closed with reason %d",
821 72 : MAC2STR(sta->addr), reason);
822 :
823 72 : wpa_msg_ctrl(wpa_s, MSG_INFO,
824 : MESH_PEER_DISCONNECTED MACSTR,
825 72 : MAC2STR(sta->addr));
826 :
827 12 : hapd->num_plinks--;
828 :
829 12 : mesh_mpm_send_plink_action(wpa_s, sta,
830 : PLINK_CLOSE, reason);
831 12 : 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 12 : 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 114 : }
864 :
865 :
866 117 : 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 117 : struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
871 117 : struct mesh_conf *mconf = wpa_s->ifmsh->mconf;
872 : struct sta_info *sta;
873 117 : 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 117 : if (mgmt->u.action.category != WLAN_ACTION_SELF_PROTECTED)
882 3 : return;
883 :
884 117 : action_field = mgmt->u.action.u.slf_prot_action.action;
885 117 : if (action_field != PLINK_OPEN &&
886 22 : action_field != PLINK_CONFIRM &&
887 : action_field != PLINK_CLOSE)
888 0 : return;
889 :
890 117 : ies = mgmt->u.action.u.slf_prot_action.variable;
891 117 : 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 117 : 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 117 : wpa_printf(MSG_DEBUG, "MPM: Received PLINK action %u", action_field);
902 :
903 117 : if (action_field == PLINK_OPEN || action_field == PLINK_CONFIRM) {
904 95 : wpa_printf(MSG_DEBUG, "MPM: Capability 0x%x",
905 95 : WPA_GET_LE16(ies));
906 95 : ies += 2; /* capability */
907 95 : ie_len -= 2;
908 : }
909 117 : if (action_field == PLINK_CONFIRM) {
910 31 : wpa_printf(MSG_DEBUG, "MPM: AID 0x%x", WPA_GET_LE16(ies));
911 31 : ies += 2; /* aid */
912 31 : ie_len -= 2;
913 : }
914 :
915 : /* check for mesh peering, mesh id and mesh config IEs */
916 117 : 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 117 : if (!elems.peer_mgmt) {
921 0 : wpa_printf(MSG_DEBUG,
922 : "MPM: No Mesh Peering Management element");
923 0 : return;
924 : }
925 117 : if (action_field != PLINK_CLOSE) {
926 95 : 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 95 : 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 117 : ret = mesh_mpm_parse_peer_mgmt(wpa_s, action_field,
940 : elems.peer_mgmt,
941 117 : elems.peer_mgmt_len,
942 : &peer_mgmt_ie);
943 117 : 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 117 : plid = WPA_GET_LE16(peer_mgmt_ie.llid);
950 117 : if (peer_mgmt_ie.plid)
951 53 : llid = WPA_GET_LE16(peer_mgmt_ie.plid);
952 117 : wpa_printf(MSG_DEBUG, "MPM: plid=0x%x llid=0x%x", plid, llid);
953 :
954 117 : 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 125 : if (!sta && action_field == PLINK_OPEN &&
961 8 : !(mconf->security & MESH_CONF_SEC_AMPE))
962 8 : sta = mesh_mpm_add_peer(wpa_s, mgmt->sa, &elems);
963 :
964 117 : if (!sta) {
965 1 : wpa_printf(MSG_DEBUG, "MPM: No STA entry for peer");
966 1 : return;
967 : }
968 :
969 : #ifdef CONFIG_SAE
970 : /* peer is in sae_accepted? */
971 116 : if (sta->sae && sta->sae->state != SAE_ACCEPTED) {
972 2 : wpa_printf(MSG_DEBUG, "MPM: SAE not yet accepted for peer");
973 2 : return;
974 : }
975 : #endif /* CONFIG_SAE */
976 :
977 114 : if (!sta->my_lid)
978 0 : mesh_mpm_init_link(wpa_s, sta);
979 :
980 129 : if ((mconf->security & MESH_CONF_SEC_AMPE) &&
981 15 : 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 114 : 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 114 : switch (action_field) {
995 : case PLINK_OPEN:
996 64 : 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 58 : } else if (sta->peer_lid && sta->peer_lid != plid) {
1002 18 : event = OPN_IGNR;
1003 : } else {
1004 40 : sta->peer_lid = plid;
1005 40 : event = OPN_ACPT;
1006 : }
1007 64 : break;
1008 : case PLINK_CONFIRM:
1009 31 : if (plink_free_count(hapd) == 0) {
1010 3 : event = CNF_IGNR;
1011 3 : wpa_printf(MSG_INFO,
1012 : "MPM: Peer link num over quota(%d)",
1013 : hapd->max_plinks);
1014 55 : } else if (sta->my_lid != llid ||
1015 54 : (sta->peer_lid && sta->peer_lid != plid)) {
1016 4 : event = CNF_IGNR;
1017 : } else {
1018 24 : if (!sta->peer_lid)
1019 0 : sta->peer_lid = plid;
1020 24 : event = CNF_ACPT;
1021 : }
1022 31 : break;
1023 : case PLINK_CLOSE:
1024 19 : 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 12 : event = CLS_ACPT;
1035 7 : else if (sta->peer_lid != plid)
1036 3 : event = CLS_IGNR;
1037 4 : else if (peer_mgmt_ie.plid && sta->my_lid != llid)
1038 4 : event = CLS_IGNR;
1039 : else
1040 0 : event = CLS_ACPT;
1041 19 : 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 114 : mesh_mpm_fsm(wpa_s, sta, event);
1051 : }
1052 :
1053 :
1054 : /* called by ap_free_sta */
1055 40 : void mesh_mpm_free_sta(struct sta_info *sta)
1056 : {
1057 40 : eloop_cancel_timeout(plink_timer, ELOOP_ALL_CTX, sta);
1058 40 : eloop_cancel_timeout(mesh_auth_timer, ELOOP_ALL_CTX, sta);
1059 40 : }
|