~okay19/ubuntu/wily/wpa/fix-bug-1405452

« back to all changes in this revision

Viewing changes to wpa_supplicant/mesh_mpm.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2015-07-27 17:29:24 UTC
  • mfrom: (1.1.3) (2.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20150727172924-9mhlszpmx7dgwzbd
Tags: 2.4-0ubuntu1
* New upstream release.
* Merge with Debian unstable; remaining changes:
  - debian/patches/session-ticket.patch: disable the TLS Session Ticket
    extension to fix auth with 802.1x PEAP on some hardware.
  - debian/patches/android_hal_fw_path_change.patch: add a DBus method for
    requesting a firmware change when working with the Android HAL; this is
    used to set a device in P2P or AP mode; conditional to CONFIG_ANDROID_HAL
    being enabled.
  - debian/config/wpasupplicant/linux: enable CONFIG_ANDROID_HAL.
  - debian/control: Build-Depends on android-headers to get the required wifi
    headers for the HAL support.
  - debian/patches/dbus-available-sta.patch: Make the list of connected
    stations available on DBus for hotspot mode; along with some of the
    station properties, such as rx/tx packets, bytes, capabilities, etc.
  - debian/patches/CVE-2015-4141.patch: check chunk size: src/wps/httpread.c
    - CVE-2015-4141
  - debian/patches/CVE-2015-4142.patch: check length in src/ap/wmm.c.
    - CVE-2015-4142
  - debian/patches/CVE-2015-4143-4146.patch: check lengths in
      src/eap_peer/eap_pwd.c, src/eap_server/eap_server_pwd.c.
    - CVE-2015-4143, CVE-2015-4144, CVE-2015-4145, CVE-2015-4146
  - debian/config/wpasupplicant/linux:
    - Enable CONFIG_AP_MODE (AP mode support) (LP: #1209511).
    - Enable CONFIG_P2P (Wi-Fi Direct support).
* debian/patches/wpa_supplicant-MACsec-fix-build-failure-for-IEEE8021.patch,
  debian/patches/include-ieee802_11_common.c-in-wpa_supplicant-build-.patch,
  d/p/hostapd_fix-hostapd-operation-without-hw_mode-driver-data.patch:
  dropped patches included upstream.
* Refreshed all patches.

Show diffs side-by-side

added added

removed removed

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