LCOV - code coverage report
Current view: top level - wpa_supplicant - mesh_mpm.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 604 655 92.2 %
Date: 2016-10-02 Functions: 24 24 100.0 %

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

Generated by: LCOV version 1.10