aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/quantenna/qtnfmac/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/quantenna/qtnfmac/event.c')
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/event.c185
1 files changed, 142 insertions, 43 deletions
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 3fd1a9217737..6c1b886339ac 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -150,6 +150,13 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
150 struct cfg80211_chan_def chandef; 150 struct cfg80211_chan_def chandef;
151 struct cfg80211_bss *bss = NULL; 151 struct cfg80211_bss *bss = NULL;
152 u8 *ie = NULL; 152 u8 *ie = NULL;
153 size_t payload_len;
154 u16 tlv_type;
155 u16 tlv_value_len;
156 size_t tlv_full_len;
157 const struct qlink_tlv_hdr *tlv;
158 const u8 *rsp_ies = NULL;
159 size_t rsp_ies_len = 0;
153 160
154 if (unlikely(len < sizeof(*join_info))) { 161 if (unlikely(len < sizeof(*join_info))) {
155 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 162 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
@@ -167,67 +174,118 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
167 pr_debug("VIF%u.%u: BSSID:%pM status:%u\n", 174 pr_debug("VIF%u.%u: BSSID:%pM status:%u\n",
168 vif->mac->macid, vif->vifid, join_info->bssid, status); 175 vif->mac->macid, vif->vifid, join_info->bssid, status);
169 176
170 if (status == WLAN_STATUS_SUCCESS) { 177 if (status != WLAN_STATUS_SUCCESS)
171 qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef); 178 goto done;
172 if (!cfg80211_chandef_valid(&chandef)) { 179
173 pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n", 180 qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef);
181 if (!cfg80211_chandef_valid(&chandef)) {
182 pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
183 vif->mac->macid, vif->vifid,
184 chandef.chan->center_freq,
185 chandef.center_freq1,
186 chandef.center_freq2,
187 chandef.width);
188 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
189 goto done;
190 }
191
192 bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid,
193 NULL, 0, IEEE80211_BSS_TYPE_ESS,
194 IEEE80211_PRIVACY_ANY);
195 if (!bss) {
196 pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
197 vif->mac->macid, vif->vifid,
198 join_info->bssid, chandef.chan->hw_value);
199
200 if (!vif->wdev.ssid_len) {
201 pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
174 vif->mac->macid, vif->vifid, 202 vif->mac->macid, vif->vifid,
175 chandef.chan->center_freq, 203 join_info->bssid);
176 chandef.center_freq1,
177 chandef.center_freq2,
178 chandef.width);
179 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 204 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
180 goto done; 205 goto done;
181 } 206 }
182 207
183 bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid, 208 ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL);
184 NULL, 0, IEEE80211_BSS_TYPE_ESS, 209 if (!ie) {
185 IEEE80211_PRIVACY_ANY); 210 pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n",
211 vif->mac->macid, vif->vifid,
212 join_info->bssid);
213 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
214 goto done;
215 }
216
217 ie[0] = WLAN_EID_SSID;
218 ie[1] = vif->wdev.ssid_len;
219 memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len);
220
221 bss = cfg80211_inform_bss(wiphy, chandef.chan,
222 CFG80211_BSS_FTYPE_UNKNOWN,
223 join_info->bssid, 0,
224 WLAN_CAPABILITY_ESS, 100,
225 ie, 2 + vif->wdev.ssid_len,
226 0, GFP_KERNEL);
186 if (!bss) { 227 if (!bss) {
187 pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n", 228 pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n",
188 vif->mac->macid, vif->vifid, 229 vif->mac->macid, vif->vifid,
189 join_info->bssid, chandef.chan->hw_value); 230 join_info->bssid);
231 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
232 goto done;
233 }
234 }
190 235
191 if (!vif->wdev.ssid_len) { 236 payload_len = len - sizeof(*join_info);
192 pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n", 237 tlv = (struct qlink_tlv_hdr *)join_info->ies;
193 vif->mac->macid, vif->vifid, 238
194 join_info->bssid); 239 while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
195 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 240 tlv_type = le16_to_cpu(tlv->type);
196 goto done; 241 tlv_value_len = le16_to_cpu(tlv->len);
197 } 242 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
198 243
199 ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL); 244 if (payload_len < tlv_full_len) {
200 if (!ie) { 245 pr_warn("invalid %u TLV\n", tlv_type);
201 pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n", 246 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
202 vif->mac->macid, vif->vifid, 247 goto done;
203 join_info->bssid); 248 }
249
250 if (tlv_type == QTN_TLV_ID_IE_SET) {
251 const struct qlink_tlv_ie_set *ie_set;
252 unsigned int ie_len;
253
254 if (payload_len < sizeof(*ie_set)) {
255 pr_warn("invalid IE_SET TLV\n");
204 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 256 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
205 goto done; 257 goto done;
206 } 258 }
207 259
208 ie[0] = WLAN_EID_SSID; 260 ie_set = (const struct qlink_tlv_ie_set *)tlv;
209 ie[1] = vif->wdev.ssid_len; 261 ie_len = tlv_value_len -
210 memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len); 262 (sizeof(*ie_set) - sizeof(ie_set->hdr));
211 263
212 bss = cfg80211_inform_bss(wiphy, chandef.chan, 264 switch (ie_set->type) {
213 CFG80211_BSS_FTYPE_UNKNOWN, 265 case QLINK_IE_SET_ASSOC_RESP:
214 join_info->bssid, 0, 266 if (ie_len) {
215 WLAN_CAPABILITY_ESS, 100, 267 rsp_ies = ie_set->ie_data;
216 ie, 2 + vif->wdev.ssid_len, 268 rsp_ies_len = ie_len;
217 0, GFP_KERNEL); 269 }
218 if (!bss) { 270 break;
219 pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n", 271 default:
220 vif->mac->macid, vif->vifid, 272 pr_warn("unexpected IE type: %u\n",
221 join_info->bssid); 273 ie_set->type);
222 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 274 break;
223 goto done;
224 } 275 }
225 } 276 }
277
278 payload_len -= tlv_full_len;
279 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
226 } 280 }
227 281
282 if (payload_len)
283 pr_warn("VIF%u.%u: unexpected remaining payload: %zu\n",
284 vif->mac->macid, vif->vifid, payload_len);
285
228done: 286done:
229 cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL, 287 cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, rsp_ies,
230 0, status, GFP_KERNEL); 288 rsp_ies_len, status, GFP_KERNEL);
231 if (bss) { 289 if (bss) {
232 if (!ether_addr_equal(vif->bssid, join_info->bssid)) 290 if (!ether_addr_equal(vif->bssid, join_info->bssid))
233 ether_addr_copy(vif->bssid, join_info->bssid); 291 ether_addr_copy(vif->bssid, join_info->bssid);
@@ -516,6 +574,43 @@ static int qtnf_event_handle_radar(struct qtnf_vif *vif,
516 return 0; 574 return 0;
517} 575}
518 576
577static int
578qtnf_event_handle_external_auth(struct qtnf_vif *vif,
579 const struct qlink_event_external_auth *ev,
580 u16 len)
581{
582 struct cfg80211_external_auth_params auth = {0};
583 struct wiphy *wiphy = priv_to_wiphy(vif->mac);
584 int ret;
585
586 if (len < sizeof(*ev)) {
587 pr_err("MAC%u: payload is too short\n", vif->mac->macid);
588 return -EINVAL;
589 }
590
591 if (!wiphy->registered || !vif->netdev)
592 return 0;
593
594 if (ev->ssid_len) {
595 memcpy(auth.ssid.ssid, ev->ssid, ev->ssid_len);
596 auth.ssid.ssid_len = ev->ssid_len;
597 }
598
599 auth.key_mgmt_suite = le32_to_cpu(ev->akm_suite);
600 ether_addr_copy(auth.bssid, ev->bssid);
601 auth.action = ev->action;
602
603 pr_info("%s: external auth bss=%pM action=%u akm=%u\n",
604 vif->netdev->name, auth.bssid, auth.action,
605 auth.key_mgmt_suite);
606
607 ret = cfg80211_external_auth_request(vif->netdev, &auth, GFP_KERNEL);
608 if (ret)
609 pr_warn("failed to offload external auth request\n");
610
611 return ret;
612}
613
519static int qtnf_event_parse(struct qtnf_wmac *mac, 614static int qtnf_event_parse(struct qtnf_wmac *mac,
520 const struct sk_buff *event_skb) 615 const struct sk_buff *event_skb)
521{ 616{
@@ -574,6 +669,10 @@ static int qtnf_event_parse(struct qtnf_wmac *mac,
574 ret = qtnf_event_handle_radar(vif, (const void *)event, 669 ret = qtnf_event_handle_radar(vif, (const void *)event,
575 event_len); 670 event_len);
576 break; 671 break;
672 case QLINK_EVENT_EXTERNAL_AUTH:
673 ret = qtnf_event_handle_external_auth(vif, (const void *)event,
674 event_len);
675 break;
577 default: 676 default:
578 pr_warn("unknown event type: %x\n", event_id); 677 pr_warn("unknown event type: %x\n", event_id);
579 break; 678 break;