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