aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c140
1 files changed, 104 insertions, 36 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0f1b18f209d6..62bdb1adaa4d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -371,8 +371,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
371 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, 371 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
372 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG }, 372 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
373 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, 373 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
374 [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, 374 [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY },
375 [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, 375 [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY },
376 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, 376 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
377 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, 377 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
378 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, 378 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
@@ -386,6 +386,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
386 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, 386 [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
387 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, 387 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
388 [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG }, 388 [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
389 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
389}; 390};
390 391
391/* policy for the key attributes */ 392/* policy for the key attributes */
@@ -970,8 +971,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
970 c->max_interfaces)) 971 c->max_interfaces))
971 goto nla_put_failure; 972 goto nla_put_failure;
972 if (large && 973 if (large &&
973 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, 974 (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
974 c->radar_detect_widths)) 975 c->radar_detect_widths) ||
976 nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
977 c->radar_detect_regions)))
975 goto nla_put_failure; 978 goto nla_put_failure;
976 979
977 nla_nest_end(msg, nl_combi); 980 nla_nest_end(msg, nl_combi);
@@ -1667,6 +1670,13 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
1667 } 1670 }
1668 nla_nest_end(msg, nested); 1671 nla_nest_end(msg, nested);
1669 } 1672 }
1673 state->split_start++;
1674 break;
1675 case 12:
1676 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
1677 nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
1678 rdev->wiphy.max_num_csa_counters))
1679 goto nla_put_failure;
1670 1680
1671 /* done */ 1681 /* done */
1672 state->split_start = 0; 1682 state->split_start = 0;
@@ -3640,6 +3650,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
3640 nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED, 3650 nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED,
3641 sinfo->tx_failed)) 3651 sinfo->tx_failed))
3642 goto nla_put_failure; 3652 goto nla_put_failure;
3653 if ((sinfo->filled & STATION_INFO_EXPECTED_THROUGHPUT) &&
3654 nla_put_u32(msg, NL80211_STA_INFO_EXPECTED_THROUGHPUT,
3655 sinfo->expected_throughput))
3656 goto nla_put_failure;
3643 if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) && 3657 if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) &&
3644 nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, 3658 nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS,
3645 sinfo->beacon_loss_count)) 3659 sinfo->beacon_loss_count))
@@ -5820,7 +5834,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5820 return -EBUSY; 5834 return -EBUSY;
5821 5835
5822 err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, 5836 err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef,
5823 NL80211_IFTYPE_UNSPECIFIED); 5837 wdev->iftype);
5824 if (err < 0) 5838 if (err < 0)
5825 return err; 5839 return err;
5826 5840
@@ -5861,6 +5875,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
5861 u8 radar_detect_width = 0; 5875 u8 radar_detect_width = 0;
5862 int err; 5876 int err;
5863 bool need_new_beacon = false; 5877 bool need_new_beacon = false;
5878 int len, i;
5864 5879
5865 if (!rdev->ops->channel_switch || 5880 if (!rdev->ops->channel_switch ||
5866 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) 5881 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
@@ -5919,26 +5934,55 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
5919 if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]) 5934 if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON])
5920 return -EINVAL; 5935 return -EINVAL;
5921 5936
5922 params.counter_offset_beacon = 5937 len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
5923 nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); 5938 if (!len || (len % sizeof(u16)))
5924 if (params.counter_offset_beacon >= params.beacon_csa.tail_len)
5925 return -EINVAL; 5939 return -EINVAL;
5926 5940
5927 /* sanity check - counters should be the same */ 5941 params.n_counter_offsets_beacon = len / sizeof(u16);
5928 if (params.beacon_csa.tail[params.counter_offset_beacon] != 5942 if (rdev->wiphy.max_num_csa_counters &&
5929 params.count) 5943 (params.n_counter_offsets_beacon >
5944 rdev->wiphy.max_num_csa_counters))
5930 return -EINVAL; 5945 return -EINVAL;
5931 5946
5947 params.counter_offsets_beacon =
5948 nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
5949
5950 /* sanity checks - counters should fit and be the same */
5951 for (i = 0; i < params.n_counter_offsets_beacon; i++) {
5952 u16 offset = params.counter_offsets_beacon[i];
5953
5954 if (offset >= params.beacon_csa.tail_len)
5955 return -EINVAL;
5956
5957 if (params.beacon_csa.tail[offset] != params.count)
5958 return -EINVAL;
5959 }
5960
5932 if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) { 5961 if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) {
5933 params.counter_offset_presp = 5962 len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
5934 nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); 5963 if (!len || (len % sizeof(u16)))
5935 if (params.counter_offset_presp >=
5936 params.beacon_csa.probe_resp_len)
5937 return -EINVAL; 5964 return -EINVAL;
5938 5965
5939 if (params.beacon_csa.probe_resp[params.counter_offset_presp] != 5966 params.n_counter_offsets_presp = len / sizeof(u16);
5940 params.count) 5967 if (rdev->wiphy.max_num_csa_counters &&
5968 (params.n_counter_offsets_beacon >
5969 rdev->wiphy.max_num_csa_counters))
5941 return -EINVAL; 5970 return -EINVAL;
5971
5972 params.counter_offsets_presp =
5973 nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
5974
5975 /* sanity checks - counters should fit and be the same */
5976 for (i = 0; i < params.n_counter_offsets_presp; i++) {
5977 u16 offset = params.counter_offsets_presp[i];
5978
5979 if (offset >= params.beacon_csa.probe_resp_len)
5980 return -EINVAL;
5981
5982 if (params.beacon_csa.probe_resp[offset] !=
5983 params.count)
5984 return -EINVAL;
5985 }
5942 } 5986 }
5943 5987
5944skip_beacons: 5988skip_beacons:
@@ -7784,6 +7828,27 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
7784 if (!chandef.chan && params.offchan) 7828 if (!chandef.chan && params.offchan)
7785 return -EINVAL; 7829 return -EINVAL;
7786 7830
7831 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
7832 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
7833
7834 if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
7835 int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
7836 int i;
7837
7838 if (len % sizeof(u16))
7839 return -EINVAL;
7840
7841 params.n_csa_offsets = len / sizeof(u16);
7842 params.csa_offsets =
7843 nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
7844
7845 /* check that all the offsets fit the frame */
7846 for (i = 0; i < params.n_csa_offsets; i++) {
7847 if (params.csa_offsets[i] >= params.len)
7848 return -EINVAL;
7849 }
7850 }
7851
7787 if (!params.dont_wait_for_ack) { 7852 if (!params.dont_wait_for_ack) {
7788 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 7853 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7789 if (!msg) 7854 if (!msg)
@@ -7797,8 +7862,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
7797 } 7862 }
7798 } 7863 }
7799 7864
7800 params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
7801 params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
7802 params.chan = chandef.chan; 7865 params.chan = chandef.chan;
7803 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie); 7866 err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
7804 if (err) 7867 if (err)
@@ -8495,6 +8558,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
8495 8558
8496 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], 8559 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
8497 rem) { 8560 rem) {
8561 u8 *mask_pat;
8562
8498 nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), 8563 nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
8499 nla_len(pat), NULL); 8564 nla_len(pat), NULL);
8500 err = -EINVAL; 8565 err = -EINVAL;
@@ -8518,19 +8583,18 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
8518 goto error; 8583 goto error;
8519 new_triggers.patterns[i].pkt_offset = pkt_offset; 8584 new_triggers.patterns[i].pkt_offset = pkt_offset;
8520 8585
8521 new_triggers.patterns[i].mask = 8586 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
8522 kmalloc(mask_len + pat_len, GFP_KERNEL); 8587 if (!mask_pat) {
8523 if (!new_triggers.patterns[i].mask) {
8524 err = -ENOMEM; 8588 err = -ENOMEM;
8525 goto error; 8589 goto error;
8526 } 8590 }
8527 new_triggers.patterns[i].pattern = 8591 new_triggers.patterns[i].mask = mask_pat;
8528 new_triggers.patterns[i].mask + mask_len; 8592 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
8529 memcpy(new_triggers.patterns[i].mask,
8530 nla_data(pat_tb[NL80211_PKTPAT_MASK]),
8531 mask_len); 8593 mask_len);
8594 mask_pat += mask_len;
8595 new_triggers.patterns[i].pattern = mask_pat;
8532 new_triggers.patterns[i].pattern_len = pat_len; 8596 new_triggers.patterns[i].pattern_len = pat_len;
8533 memcpy(new_triggers.patterns[i].pattern, 8597 memcpy(mask_pat,
8534 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), 8598 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
8535 pat_len); 8599 pat_len);
8536 i++; 8600 i++;
@@ -8722,6 +8786,8 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
8722 8786
8723 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN], 8787 nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
8724 rem) { 8788 rem) {
8789 u8 *mask_pat;
8790
8725 nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), 8791 nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
8726 nla_len(pat), NULL); 8792 nla_len(pat), NULL);
8727 if (!pat_tb[NL80211_PKTPAT_MASK] || 8793 if (!pat_tb[NL80211_PKTPAT_MASK] ||
@@ -8743,17 +8809,19 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
8743 return -EINVAL; 8809 return -EINVAL;
8744 new_rule->patterns[i].pkt_offset = pkt_offset; 8810 new_rule->patterns[i].pkt_offset = pkt_offset;
8745 8811
8746 new_rule->patterns[i].mask = 8812 mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
8747 kmalloc(mask_len + pat_len, GFP_KERNEL); 8813 if (!mask_pat)
8748 if (!new_rule->patterns[i].mask)
8749 return -ENOMEM; 8814 return -ENOMEM;
8750 new_rule->patterns[i].pattern = 8815
8751 new_rule->patterns[i].mask + mask_len; 8816 new_rule->patterns[i].mask = mask_pat;
8752 memcpy(new_rule->patterns[i].mask, 8817 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
8753 nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len); 8818 mask_len);
8819
8820 mask_pat += mask_len;
8821 new_rule->patterns[i].pattern = mask_pat;
8754 new_rule->patterns[i].pattern_len = pat_len; 8822 new_rule->patterns[i].pattern_len = pat_len;
8755 memcpy(new_rule->patterns[i].pattern, 8823 memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
8756 nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len); 8824 pat_len);
8757 i++; 8825 i++;
8758 } 8826 }
8759 8827