Loading net/mac80211/mesh_plink.c +115 −80 Original line number Original line Diff line number Diff line Loading @@ -844,110 +844,69 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, return changed; return changed; } } static void /* mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, * mesh_plink_get_event - get correct MPM event struct ieee80211_mgmt *mgmt, * struct ieee802_11_elems *elems) * @sdata: interface * @sta: peer, leave NULL if processing a frame from a new suitable peer * @elems: peering management IEs * @ftype: frame type * @llid: peer's peer link ID * @plid: peer's local link ID * * Return: new peering event for @sta, but PLINK_UNDEFINED should be treated as * an error. */ static enum plink_event mesh_plink_get_event(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct ieee802_11_elems *elems, enum ieee80211_self_protected_actioncode ftype, __le16 llid, __le16 plid) { { enum plink_event event = PLINK_UNDEFINED; struct sta_info *sta; u8 ie_len = elems->peering_len; enum plink_event event; enum ieee80211_self_protected_actioncode ftype; bool matches_local; bool matches_local; u32 changed = 0; u8 ie_len; __le16 plid, llid = 0; if (!elems->peering) { mpl_dbg(sdata, "Mesh plink: missing necessary peer link ie\n"); return; } if (elems->rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { mpl_dbg(sdata, "Mesh plink: can't establish link with secure peer\n"); return; } ftype = mgmt->u.action.u.self_prot.action_code; ie_len = elems->peering_len; if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 && ie_len != 8)) { mpl_dbg(sdata, "Mesh plink: incorrect plink ie length %d %d\n", ftype, ie_len); return; } if (ftype != WLAN_SP_MESH_PEERING_CLOSE && (!elems->mesh_id || !elems->mesh_config)) { mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); return; } /* Note the lines below are correct, the llid in the frame is the plid * from the point of view of this host. */ memcpy(&plid, PLINK_GET_LLID(elems->peering), 2); if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) memcpy(&llid, PLINK_GET_PLID(elems->peering), 2); /* WARNING: Only for sta pointer, is dropped & re-acquired */ rcu_read_lock(); sta = sta_info_get(sdata, mgmt->sa); matches_local = (ftype == WLAN_SP_MESH_PEERING_CLOSE || matches_local = (ftype == WLAN_SP_MESH_PEERING_CLOSE || mesh_matches_local(sdata, elems)); mesh_matches_local(sdata, elems)); if (ftype == WLAN_SP_MESH_PEERING_OPEN && /* deny open request from non-matching peer */ !rssi_threshold_check(sdata, sta)) { if (!matches_local && !sta) { mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n", event = OPN_RJCT; mgmt->sa); goto out; goto unlock_rcu; } } if (!sta) { if (!sta) { if (ftype != WLAN_SP_MESH_PEERING_OPEN) { if (ftype != WLAN_SP_MESH_PEERING_OPEN) { mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n"); mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n"); goto unlock_rcu; goto out; } } /* ftype == WLAN_SP_MESH_PEERING_OPEN */ /* ftype == WLAN_SP_MESH_PEERING_OPEN */ if (!mesh_plink_free_count(sdata)) { if (!mesh_plink_free_count(sdata)) { mpl_dbg(sdata, "Mesh plink error: no more free plinks\n"); mpl_dbg(sdata, "Mesh plink error: no more free plinks\n"); goto unlock_rcu; goto out; } /* deny open request from non-matching peer */ if (!matches_local) { mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mgmt->sa, 0, plid, cpu_to_le16(WLAN_REASON_MESH_CONFIG)); goto unlock_rcu; } } } else { } else { if (!test_sta_flag(sta, WLAN_STA_AUTH)) { if (!test_sta_flag(sta, WLAN_STA_AUTH)) { mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n"); mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n"); goto unlock_rcu; goto out; } } if (sta->plink_state == NL80211_PLINK_BLOCKED) if (sta->plink_state == NL80211_PLINK_BLOCKED) goto unlock_rcu; goto out; } } /* Now we will figure out the appropriate event... */ /* new matching peer */ event = PLINK_UNDEFINED; if (!sta) { if (!sta) event = OPN_ACPT; event = OPN_ACPT; else { goto out; } switch (ftype) { switch (ftype) { case WLAN_SP_MESH_PEERING_OPEN: case WLAN_SP_MESH_PEERING_OPEN: if (!matches_local) if (!matches_local) event = OPN_RJCT; event = OPN_RJCT; else if (!mesh_plink_free_count(sdata) || if (!mesh_plink_free_count(sdata) || (sta->plid && sta->plid != plid)) (sta->plid && sta->plid != plid)) event = OPN_IGNR; event = OPN_IGNR; else else Loading @@ -956,7 +915,7 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, case WLAN_SP_MESH_PEERING_CONFIRM: case WLAN_SP_MESH_PEERING_CONFIRM: if (!matches_local) if (!matches_local) event = CNF_RJCT; event = CNF_RJCT; else if (!mesh_plink_free_count(sdata) || if (!mesh_plink_free_count(sdata) || (sta->llid != llid || sta->plid != plid)) (sta->llid != llid || sta->plid != plid)) event = CNF_IGNR; event = CNF_IGNR; else else Loading @@ -983,10 +942,78 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, break; break; default: default: mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n"); mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n"); goto unlock_rcu; break; } out: return event; } static void mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, struct ieee802_11_elems *elems) { struct sta_info *sta; enum plink_event event; enum ieee80211_self_protected_actioncode ftype; u32 changed = 0; u8 ie_len = elems->peering_len; __le16 plid, llid = 0; if (!elems->peering) { mpl_dbg(sdata, "Mesh plink: missing necessary peer link ie\n"); return; } } if (elems->rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { mpl_dbg(sdata, "Mesh plink: can't establish link with secure peer\n"); return; } } ftype = mgmt->u.action.u.self_prot.action_code; if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 && ie_len != 8)) { mpl_dbg(sdata, "Mesh plink: incorrect plink ie length %d %d\n", ftype, ie_len); return; } if (ftype != WLAN_SP_MESH_PEERING_CLOSE && (!elems->mesh_id || !elems->mesh_config)) { mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); return; } /* Note the lines below are correct, the llid in the frame is the plid * from the point of view of this host. */ memcpy(&plid, PLINK_GET_LLID(elems->peering), 2); if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) memcpy(&llid, PLINK_GET_PLID(elems->peering), 2); /* WARNING: Only for sta pointer, is dropped & re-acquired */ rcu_read_lock(); sta = sta_info_get(sdata, mgmt->sa); if (ftype == WLAN_SP_MESH_PEERING_OPEN && !rssi_threshold_check(sdata, sta)) { mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n", mgmt->sa); goto unlock_rcu; } /* Now we will figure out the appropriate event... */ event = mesh_plink_get_event(sdata, sta, elems, ftype, llid, plid); if (event == OPN_ACPT) { if (event == OPN_ACPT) { rcu_read_unlock(); rcu_read_unlock(); /* allocate sta entry if necessary and update info */ /* allocate sta entry if necessary and update info */ Loading @@ -996,6 +1023,14 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, goto unlock_rcu; goto unlock_rcu; } } sta->plid = plid; sta->plid = plid; } else if (!sta && event == OPN_RJCT) { mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mgmt->sa, 0, plid, cpu_to_le16(WLAN_REASON_MESH_CONFIG)); goto unlock_rcu; } else if (!sta || event == PLINK_UNDEFINED) { /* something went wrong */ goto unlock_rcu; } } changed |= mesh_plink_fsm(sdata, sta, event); changed |= mesh_plink_fsm(sdata, sta, event); Loading Loading
net/mac80211/mesh_plink.c +115 −80 Original line number Original line Diff line number Diff line Loading @@ -844,110 +844,69 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, return changed; return changed; } } static void /* mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, * mesh_plink_get_event - get correct MPM event struct ieee80211_mgmt *mgmt, * struct ieee802_11_elems *elems) * @sdata: interface * @sta: peer, leave NULL if processing a frame from a new suitable peer * @elems: peering management IEs * @ftype: frame type * @llid: peer's peer link ID * @plid: peer's local link ID * * Return: new peering event for @sta, but PLINK_UNDEFINED should be treated as * an error. */ static enum plink_event mesh_plink_get_event(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct ieee802_11_elems *elems, enum ieee80211_self_protected_actioncode ftype, __le16 llid, __le16 plid) { { enum plink_event event = PLINK_UNDEFINED; struct sta_info *sta; u8 ie_len = elems->peering_len; enum plink_event event; enum ieee80211_self_protected_actioncode ftype; bool matches_local; bool matches_local; u32 changed = 0; u8 ie_len; __le16 plid, llid = 0; if (!elems->peering) { mpl_dbg(sdata, "Mesh plink: missing necessary peer link ie\n"); return; } if (elems->rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { mpl_dbg(sdata, "Mesh plink: can't establish link with secure peer\n"); return; } ftype = mgmt->u.action.u.self_prot.action_code; ie_len = elems->peering_len; if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 && ie_len != 8)) { mpl_dbg(sdata, "Mesh plink: incorrect plink ie length %d %d\n", ftype, ie_len); return; } if (ftype != WLAN_SP_MESH_PEERING_CLOSE && (!elems->mesh_id || !elems->mesh_config)) { mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); return; } /* Note the lines below are correct, the llid in the frame is the plid * from the point of view of this host. */ memcpy(&plid, PLINK_GET_LLID(elems->peering), 2); if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) memcpy(&llid, PLINK_GET_PLID(elems->peering), 2); /* WARNING: Only for sta pointer, is dropped & re-acquired */ rcu_read_lock(); sta = sta_info_get(sdata, mgmt->sa); matches_local = (ftype == WLAN_SP_MESH_PEERING_CLOSE || matches_local = (ftype == WLAN_SP_MESH_PEERING_CLOSE || mesh_matches_local(sdata, elems)); mesh_matches_local(sdata, elems)); if (ftype == WLAN_SP_MESH_PEERING_OPEN && /* deny open request from non-matching peer */ !rssi_threshold_check(sdata, sta)) { if (!matches_local && !sta) { mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n", event = OPN_RJCT; mgmt->sa); goto out; goto unlock_rcu; } } if (!sta) { if (!sta) { if (ftype != WLAN_SP_MESH_PEERING_OPEN) { if (ftype != WLAN_SP_MESH_PEERING_OPEN) { mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n"); mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n"); goto unlock_rcu; goto out; } } /* ftype == WLAN_SP_MESH_PEERING_OPEN */ /* ftype == WLAN_SP_MESH_PEERING_OPEN */ if (!mesh_plink_free_count(sdata)) { if (!mesh_plink_free_count(sdata)) { mpl_dbg(sdata, "Mesh plink error: no more free plinks\n"); mpl_dbg(sdata, "Mesh plink error: no more free plinks\n"); goto unlock_rcu; goto out; } /* deny open request from non-matching peer */ if (!matches_local) { mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mgmt->sa, 0, plid, cpu_to_le16(WLAN_REASON_MESH_CONFIG)); goto unlock_rcu; } } } else { } else { if (!test_sta_flag(sta, WLAN_STA_AUTH)) { if (!test_sta_flag(sta, WLAN_STA_AUTH)) { mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n"); mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n"); goto unlock_rcu; goto out; } } if (sta->plink_state == NL80211_PLINK_BLOCKED) if (sta->plink_state == NL80211_PLINK_BLOCKED) goto unlock_rcu; goto out; } } /* Now we will figure out the appropriate event... */ /* new matching peer */ event = PLINK_UNDEFINED; if (!sta) { if (!sta) event = OPN_ACPT; event = OPN_ACPT; else { goto out; } switch (ftype) { switch (ftype) { case WLAN_SP_MESH_PEERING_OPEN: case WLAN_SP_MESH_PEERING_OPEN: if (!matches_local) if (!matches_local) event = OPN_RJCT; event = OPN_RJCT; else if (!mesh_plink_free_count(sdata) || if (!mesh_plink_free_count(sdata) || (sta->plid && sta->plid != plid)) (sta->plid && sta->plid != plid)) event = OPN_IGNR; event = OPN_IGNR; else else Loading @@ -956,7 +915,7 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, case WLAN_SP_MESH_PEERING_CONFIRM: case WLAN_SP_MESH_PEERING_CONFIRM: if (!matches_local) if (!matches_local) event = CNF_RJCT; event = CNF_RJCT; else if (!mesh_plink_free_count(sdata) || if (!mesh_plink_free_count(sdata) || (sta->llid != llid || sta->plid != plid)) (sta->llid != llid || sta->plid != plid)) event = CNF_IGNR; event = CNF_IGNR; else else Loading @@ -983,10 +942,78 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, break; break; default: default: mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n"); mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n"); goto unlock_rcu; break; } out: return event; } static void mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, struct ieee802_11_elems *elems) { struct sta_info *sta; enum plink_event event; enum ieee80211_self_protected_actioncode ftype; u32 changed = 0; u8 ie_len = elems->peering_len; __le16 plid, llid = 0; if (!elems->peering) { mpl_dbg(sdata, "Mesh plink: missing necessary peer link ie\n"); return; } } if (elems->rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { mpl_dbg(sdata, "Mesh plink: can't establish link with secure peer\n"); return; } } ftype = mgmt->u.action.u.self_prot.action_code; if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 && ie_len != 8)) { mpl_dbg(sdata, "Mesh plink: incorrect plink ie length %d %d\n", ftype, ie_len); return; } if (ftype != WLAN_SP_MESH_PEERING_CLOSE && (!elems->mesh_id || !elems->mesh_config)) { mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); return; } /* Note the lines below are correct, the llid in the frame is the plid * from the point of view of this host. */ memcpy(&plid, PLINK_GET_LLID(elems->peering), 2); if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) memcpy(&llid, PLINK_GET_PLID(elems->peering), 2); /* WARNING: Only for sta pointer, is dropped & re-acquired */ rcu_read_lock(); sta = sta_info_get(sdata, mgmt->sa); if (ftype == WLAN_SP_MESH_PEERING_OPEN && !rssi_threshold_check(sdata, sta)) { mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n", mgmt->sa); goto unlock_rcu; } /* Now we will figure out the appropriate event... */ event = mesh_plink_get_event(sdata, sta, elems, ftype, llid, plid); if (event == OPN_ACPT) { if (event == OPN_ACPT) { rcu_read_unlock(); rcu_read_unlock(); /* allocate sta entry if necessary and update info */ /* allocate sta entry if necessary and update info */ Loading @@ -996,6 +1023,14 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, goto unlock_rcu; goto unlock_rcu; } } sta->plid = plid; sta->plid = plid; } else if (!sta && event == OPN_RJCT) { mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, mgmt->sa, 0, plid, cpu_to_le16(WLAN_REASON_MESH_CONFIG)); goto unlock_rcu; } else if (!sta || event == PLINK_UNDEFINED) { /* something went wrong */ goto unlock_rcu; } } changed |= mesh_plink_fsm(sdata, sta, event); changed |= mesh_plink_fsm(sdata, sta, event); Loading