aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-06-30 08:08:12 -0400
committerDavid S. Miller <davem@davemloft.net>2018-06-30 08:08:12 -0400
commit8365da2c0570f02615e7f1d2d729d854029202b0 (patch)
tree223ab9641411c401269e5da80f260cafaf40eedc /net/mac80211/util.c
parenta1be5a20f137bdf436bab86c18998229908ce951 (diff)
parenta4217750586975dee7d6dd8829a1be24a7678b3d (diff)
Merge tag 'mac80211-next-for-davem-2018-06-29' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Small merge conflict in net/mac80211/scan.c, I preserved the kcalloc() conversion. -DaveM Johannes Berg says: ==================== This round's updates: * finally some of the promised HE code, but it turns out to be small - but everything kept changing, so one part I did in the driver was >30 patches for what was ultimately <200 lines of code ... similar here for this code. * improved scan privacy support - can now specify scan flags for randomizing the sequence number as well as reducing the probe request element content * rfkill cleanups * a timekeeping cleanup from Arnd * various other cleanups ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c159
1 files changed, 127 insertions, 32 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 5e2e511c4a6f..3e68132a41fa 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1095,6 +1095,21 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1095 if (elen >= sizeof(*elems->max_idle_period_ie)) 1095 if (elen >= sizeof(*elems->max_idle_period_ie))
1096 elems->max_idle_period_ie = (void *)pos; 1096 elems->max_idle_period_ie = (void *)pos;
1097 break; 1097 break;
1098 case WLAN_EID_EXTENSION:
1099 if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
1100 elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
1101 elems->mu_edca_param_set = (void *)&pos[1];
1102 } else if (pos[0] == WLAN_EID_EXT_HE_CAPABILITY) {
1103 elems->he_cap = (void *)&pos[1];
1104 elems->he_cap_len = elen - 1;
1105 } else if (pos[0] == WLAN_EID_EXT_HE_OPERATION &&
1106 elen >= sizeof(*elems->he_operation) &&
1107 elen >= ieee80211_he_oper_size(&pos[1])) {
1108 elems->he_operation = (void *)&pos[1];
1109 } else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) {
1110 elems->uora_element = (void *)&pos[1];
1111 }
1112 break;
1098 default: 1113 default:
1099 break; 1114 break;
1100 } 1115 }
@@ -1353,9 +1368,10 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
1353 enum nl80211_band band, 1368 enum nl80211_band band,
1354 u32 rate_mask, 1369 u32 rate_mask,
1355 struct cfg80211_chan_def *chandef, 1370 struct cfg80211_chan_def *chandef,
1356 size_t *offset) 1371 size_t *offset, u32 flags)
1357{ 1372{
1358 struct ieee80211_supported_band *sband; 1373 struct ieee80211_supported_band *sband;
1374 const struct ieee80211_sta_he_cap *he_cap;
1359 u8 *pos = buffer, *end = buffer + buffer_len; 1375 u8 *pos = buffer, *end = buffer + buffer_len;
1360 size_t noffset; 1376 size_t noffset;
1361 int supp_rates_len, i; 1377 int supp_rates_len, i;
@@ -1433,6 +1449,9 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
1433 chandef->chan->center_freq); 1449 chandef->chan->center_freq);
1434 } 1450 }
1435 1451
1452 if (flags & IEEE80211_PROBE_FLAG_MIN_CONTENT)
1453 goto done;
1454
1436 /* insert custom IEs that go before HT */ 1455 /* insert custom IEs that go before HT */
1437 if (ie && ie_len) { 1456 if (ie && ie_len) {
1438 static const u8 before_ht[] = { 1457 static const u8 before_ht[] = {
@@ -1460,11 +1479,6 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
1460 sband->ht_cap.cap); 1479 sband->ht_cap.cap);
1461 } 1480 }
1462 1481
1463 /*
1464 * If adding more here, adjust code in main.c
1465 * that calculates local->scan_ies_len.
1466 */
1467
1468 /* insert custom IEs that go before VHT */ 1482 /* insert custom IEs that go before VHT */
1469 if (ie && ie_len) { 1483 if (ie && ie_len) {
1470 static const u8 before_vht[] = { 1484 static const u8 before_vht[] = {
@@ -1507,9 +1521,43 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
1507 sband->vht_cap.cap); 1521 sband->vht_cap.cap);
1508 } 1522 }
1509 1523
1524 /* insert custom IEs that go before HE */
1525 if (ie && ie_len) {
1526 static const u8 before_he[] = {
1527 /*
1528 * no need to list the ones split off before VHT
1529 * or generated here
1530 */
1531 WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_REQ_PARAMS,
1532 WLAN_EID_AP_CSN,
1533 /* TODO: add 11ah/11aj/11ak elements */
1534 };
1535 noffset = ieee80211_ie_split(ie, ie_len,
1536 before_he, ARRAY_SIZE(before_he),
1537 *offset);
1538 if (end - pos < noffset - *offset)
1539 goto out_err;
1540 memcpy(pos, ie + *offset, noffset - *offset);
1541 pos += noffset - *offset;
1542 *offset = noffset;
1543 }
1544
1545 he_cap = ieee80211_get_he_sta_cap(sband);
1546 if (he_cap) {
1547 pos = ieee80211_ie_build_he_cap(pos, he_cap, end);
1548 if (!pos)
1549 goto out_err;
1550 }
1551
1552 /*
1553 * If adding more here, adjust code in main.c
1554 * that calculates local->scan_ies_len.
1555 */
1556
1510 return pos - buffer; 1557 return pos - buffer;
1511 out_err: 1558 out_err:
1512 WARN_ONCE(1, "not enough space for preq IEs\n"); 1559 WARN_ONCE(1, "not enough space for preq IEs\n");
1560 done:
1513 return pos - buffer; 1561 return pos - buffer;
1514} 1562}
1515 1563
@@ -1518,7 +1566,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1518 struct ieee80211_scan_ies *ie_desc, 1566 struct ieee80211_scan_ies *ie_desc,
1519 const u8 *ie, size_t ie_len, 1567 const u8 *ie, size_t ie_len,
1520 u8 bands_used, u32 *rate_masks, 1568 u8 bands_used, u32 *rate_masks,
1521 struct cfg80211_chan_def *chandef) 1569 struct cfg80211_chan_def *chandef,
1570 u32 flags)
1522{ 1571{
1523 size_t pos = 0, old_pos = 0, custom_ie_offset = 0; 1572 size_t pos = 0, old_pos = 0, custom_ie_offset = 0;
1524 int i; 1573 int i;
@@ -1533,7 +1582,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1533 ie, ie_len, i, 1582 ie, ie_len, i,
1534 rate_masks[i], 1583 rate_masks[i],
1535 chandef, 1584 chandef,
1536 &custom_ie_offset); 1585 &custom_ie_offset,
1586 flags);
1537 ie_desc->ies[i] = buffer + old_pos; 1587 ie_desc->ies[i] = buffer + old_pos;
1538 ie_desc->len[i] = pos - old_pos; 1588 ie_desc->len[i] = pos - old_pos;
1539 old_pos = pos; 1589 old_pos = pos;
@@ -1561,7 +1611,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1561 struct ieee80211_channel *chan, 1611 struct ieee80211_channel *chan,
1562 const u8 *ssid, size_t ssid_len, 1612 const u8 *ssid, size_t ssid_len,
1563 const u8 *ie, size_t ie_len, 1613 const u8 *ie, size_t ie_len,
1564 bool directed) 1614 u32 flags)
1565{ 1615{
1566 struct ieee80211_local *local = sdata->local; 1616 struct ieee80211_local *local = sdata->local;
1567 struct cfg80211_chan_def chandef; 1617 struct cfg80211_chan_def chandef;
@@ -1577,7 +1627,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1577 * badly-behaved APs don't respond when this parameter is included. 1627 * badly-behaved APs don't respond when this parameter is included.
1578 */ 1628 */
1579 chandef.width = sdata->vif.bss_conf.chandef.width; 1629 chandef.width = sdata->vif.bss_conf.chandef.width;
1580 if (directed) 1630 if (flags & IEEE80211_PROBE_FLAG_DIRECTED)
1581 chandef.chan = NULL; 1631 chandef.chan = NULL;
1582 else 1632 else
1583 chandef.chan = chan; 1633 chandef.chan = chan;
@@ -1591,7 +1641,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1591 ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), 1641 ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb),
1592 skb_tailroom(skb), &dummy_ie_desc, 1642 skb_tailroom(skb), &dummy_ie_desc,
1593 ie, ie_len, BIT(chan->band), 1643 ie, ie_len, BIT(chan->band),
1594 rate_masks, &chandef); 1644 rate_masks, &chandef, flags);
1595 skb_put(skb, ies_len); 1645 skb_put(skb, ies_len);
1596 1646
1597 if (dst) { 1647 if (dst) {
@@ -1605,27 +1655,6 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1605 return skb; 1655 return skb;
1606} 1656}
1607 1657
1608void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
1609 const u8 *src, const u8 *dst,
1610 const u8 *ssid, size_t ssid_len,
1611 const u8 *ie, size_t ie_len,
1612 u32 ratemask, bool directed, u32 tx_flags,
1613 struct ieee80211_channel *channel, bool scan)
1614{
1615 struct sk_buff *skb;
1616
1617 skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel,
1618 ssid, ssid_len,
1619 ie, ie_len, directed);
1620 if (skb) {
1621 IEEE80211_SKB_CB(skb)->flags |= tx_flags;
1622 if (scan)
1623 ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
1624 else
1625 ieee80211_tx_skb(sdata, skb);
1626 }
1627}
1628
1629u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, 1658u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
1630 struct ieee802_11_elems *elems, 1659 struct ieee802_11_elems *elems,
1631 enum nl80211_band band, u32 *basic_rates) 1660 enum nl80211_band band, u32 *basic_rates)
@@ -2412,6 +2441,72 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
2412 return pos; 2441 return pos;
2413} 2442}
2414 2443
2444u8 *ieee80211_ie_build_he_cap(u8 *pos,
2445 const struct ieee80211_sta_he_cap *he_cap,
2446 u8 *end)
2447{
2448 u8 n;
2449 u8 ie_len;
2450 u8 *orig_pos = pos;
2451
2452 /* Make sure we have place for the IE */
2453 /*
2454 * TODO: the 1 added is because this temporarily is under the EXTENSION
2455 * IE. Get rid of it when it moves.
2456 */
2457 if (!he_cap)
2458 return orig_pos;
2459
2460 n = ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem);
2461 ie_len = 2 + 1 +
2462 sizeof(he_cap->he_cap_elem) + n +
2463 ieee80211_he_ppe_size(he_cap->ppe_thres[0],
2464 he_cap->he_cap_elem.phy_cap_info);
2465
2466 if ((end - pos) < ie_len)
2467 return orig_pos;
2468
2469 *pos++ = WLAN_EID_EXTENSION;
2470 pos++; /* We'll set the size later below */
2471 *pos++ = WLAN_EID_EXT_HE_CAPABILITY;
2472
2473 /* Fixed data */
2474 memcpy(pos, &he_cap->he_cap_elem, sizeof(he_cap->he_cap_elem));
2475 pos += sizeof(he_cap->he_cap_elem);
2476
2477 memcpy(pos, &he_cap->he_mcs_nss_supp, n);
2478 pos += n;
2479
2480 /* Check if PPE Threshold should be present */
2481 if ((he_cap->he_cap_elem.phy_cap_info[6] &
2482 IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0)
2483 goto end;
2484
2485 /*
2486 * Calculate how many PPET16/PPET8 pairs are to come. Algorithm:
2487 * (NSS_M1 + 1) x (num of 1 bits in RU_INDEX_BITMASK)
2488 */
2489 n = hweight8(he_cap->ppe_thres[0] &
2490 IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK);
2491 n *= (1 + ((he_cap->ppe_thres[0] & IEEE80211_PPE_THRES_NSS_MASK) >>
2492 IEEE80211_PPE_THRES_NSS_POS));
2493
2494 /*
2495 * Each pair is 6 bits, and we need to add the 7 "header" bits to the
2496 * total size.
2497 */
2498 n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7;
2499 n = DIV_ROUND_UP(n, 8);
2500
2501 /* Copy PPE Thresholds */
2502 memcpy(pos, &he_cap->ppe_thres, n);
2503 pos += n;
2504
2505end:
2506 orig_pos[1] = (pos - orig_pos) - 2;
2507 return pos;
2508}
2509
2415u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 2510u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
2416 const struct cfg80211_chan_def *chandef, 2511 const struct cfg80211_chan_def *chandef,
2417 u16 prot_mode, bool rifs_mode) 2512 u16 prot_mode, bool rifs_mode)