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.c259
1 files changed, 244 insertions, 15 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 98fa8eb6cc4..6a82c898f83 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -176,6 +176,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
176 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, 176 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
177 [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, 177 [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, 178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
179 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
179}; 180};
180 181
181/* policy for the key attributes */ 182/* policy for the key attributes */
@@ -206,6 +207,14 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
206 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED }, 207 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
207}; 208};
208 209
210/* policy for GTK rekey offload attributes */
211static const struct nla_policy
212nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
213 [NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN },
214 [NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
215 [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
216};
217
209/* ifidx get helper */ 218/* ifidx get helper */
210static int nl80211_get_ifidx(struct netlink_callback *cb) 219static int nl80211_get_ifidx(struct netlink_callback *cb)
211{ 220{
@@ -3461,9 +3470,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3461 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3470 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3462 return -EINVAL; 3471 return -EINVAL;
3463 3472
3464 if (rdev->sched_scan_req)
3465 return -EINPROGRESS;
3466
3467 if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) 3473 if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
3468 return -EINVAL; 3474 return -EINVAL;
3469 3475
@@ -3502,12 +3508,21 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3502 if (ie_len > wiphy->max_scan_ie_len) 3508 if (ie_len > wiphy->max_scan_ie_len)
3503 return -EINVAL; 3509 return -EINVAL;
3504 3510
3511 mutex_lock(&rdev->sched_scan_mtx);
3512
3513 if (rdev->sched_scan_req) {
3514 err = -EINPROGRESS;
3515 goto out;
3516 }
3517
3505 request = kzalloc(sizeof(*request) 3518 request = kzalloc(sizeof(*request)
3506 + sizeof(*request->ssids) * n_ssids 3519 + sizeof(*request->ssids) * n_ssids
3507 + sizeof(*request->channels) * n_channels 3520 + sizeof(*request->channels) * n_channels
3508 + ie_len, GFP_KERNEL); 3521 + ie_len, GFP_KERNEL);
3509 if (!request) 3522 if (!request) {
3510 return -ENOMEM; 3523 err = -ENOMEM;
3524 goto out;
3525 }
3511 3526
3512 if (n_ssids) 3527 if (n_ssids)
3513 request->ssids = (void *)&request->channels[n_channels]; 3528 request->ssids = (void *)&request->channels[n_channels];
@@ -3605,6 +3620,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3605out_free: 3620out_free:
3606 kfree(request); 3621 kfree(request);
3607out: 3622out:
3623 mutex_unlock(&rdev->sched_scan_mtx);
3608 return err; 3624 return err;
3609} 3625}
3610 3626
@@ -3612,15 +3628,21 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
3612 struct genl_info *info) 3628 struct genl_info *info)
3613{ 3629{
3614 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 3630 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3631 int err;
3615 3632
3616 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || 3633 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
3617 !rdev->ops->sched_scan_stop) 3634 !rdev->ops->sched_scan_stop)
3618 return -EOPNOTSUPP; 3635 return -EOPNOTSUPP;
3619 3636
3620 return __cfg80211_stop_sched_scan(rdev, false); 3637 mutex_lock(&rdev->sched_scan_mtx);
3638 err = __cfg80211_stop_sched_scan(rdev, false);
3639 mutex_unlock(&rdev->sched_scan_mtx);
3640
3641 return err;
3621} 3642}
3622 3643
3623static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, 3644static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
3645 u32 seq, int flags,
3624 struct cfg80211_registered_device *rdev, 3646 struct cfg80211_registered_device *rdev,
3625 struct wireless_dev *wdev, 3647 struct wireless_dev *wdev,
3626 struct cfg80211_internal_bss *intbss) 3648 struct cfg80211_internal_bss *intbss)
@@ -3632,11 +3654,13 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
3632 3654
3633 ASSERT_WDEV_LOCK(wdev); 3655 ASSERT_WDEV_LOCK(wdev);
3634 3656
3635 hdr = nl80211hdr_put(msg, pid, seq, flags, 3657 hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).pid, seq, flags,
3636 NL80211_CMD_NEW_SCAN_RESULTS); 3658 NL80211_CMD_NEW_SCAN_RESULTS);
3637 if (!hdr) 3659 if (!hdr)
3638 return -1; 3660 return -1;
3639 3661
3662 genl_dump_check_consistent(cb, hdr, &nl80211_fam);
3663
3640 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation); 3664 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation);
3641 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex); 3665 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex);
3642 3666
@@ -3725,11 +3749,12 @@ static int nl80211_dump_scan(struct sk_buff *skb,
3725 spin_lock_bh(&rdev->bss_lock); 3749 spin_lock_bh(&rdev->bss_lock);
3726 cfg80211_bss_expire(rdev); 3750 cfg80211_bss_expire(rdev);
3727 3751
3752 cb->seq = rdev->bss_generation;
3753
3728 list_for_each_entry(scan, &rdev->bss_list, list) { 3754 list_for_each_entry(scan, &rdev->bss_list, list) {
3729 if (++idx <= start) 3755 if (++idx <= start)
3730 continue; 3756 continue;
3731 if (nl80211_send_bss(skb, 3757 if (nl80211_send_bss(skb, cb,
3732 NETLINK_CB(cb->skb).pid,
3733 cb->nlh->nlmsg_seq, NLM_F_MULTI, 3758 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3734 rdev, wdev, scan) < 0) { 3759 rdev, wdev, scan) < 0) {
3735 idx--; 3760 idx--;
@@ -3753,10 +3778,6 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
3753 void *hdr; 3778 void *hdr;
3754 struct nlattr *infoattr; 3779 struct nlattr *infoattr;
3755 3780
3756 /* Survey without a channel doesn't make sense */
3757 if (!survey->channel)
3758 return -EINVAL;
3759
3760 hdr = nl80211hdr_put(msg, pid, seq, flags, 3781 hdr = nl80211hdr_put(msg, pid, seq, flags,
3761 NL80211_CMD_NEW_SURVEY_RESULTS); 3782 NL80211_CMD_NEW_SURVEY_RESULTS);
3762 if (!hdr) 3783 if (!hdr)
@@ -3819,6 +3840,8 @@ static int nl80211_dump_survey(struct sk_buff *skb,
3819 } 3840 }
3820 3841
3821 while (1) { 3842 while (1) {
3843 struct ieee80211_channel *chan;
3844
3822 res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx, 3845 res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx,
3823 &survey); 3846 &survey);
3824 if (res == -ENOENT) 3847 if (res == -ENOENT)
@@ -3826,6 +3849,19 @@ static int nl80211_dump_survey(struct sk_buff *skb,
3826 if (res) 3849 if (res)
3827 goto out_err; 3850 goto out_err;
3828 3851
3852 /* Survey without a channel doesn't make sense */
3853 if (!survey.channel) {
3854 res = -EINVAL;
3855 goto out;
3856 }
3857
3858 chan = ieee80211_get_channel(&dev->wiphy,
3859 survey.channel->center_freq);
3860 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
3861 survey_idx++;
3862 continue;
3863 }
3864
3829 if (nl80211_send_survey(skb, 3865 if (nl80211_send_survey(skb,
3830 NETLINK_CB(cb->skb).pid, 3866 NETLINK_CB(cb->skb).pid,
3831 cb->nlh->nlmsg_seq, NLM_F_MULTI, 3867 cb->nlh->nlmsg_seq, NLM_F_MULTI,
@@ -4360,6 +4396,93 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
4360 return err; 4396 return err;
4361} 4397}
4362 4398
4399static int nl80211_testmode_dump(struct sk_buff *skb,
4400 struct netlink_callback *cb)
4401{
4402 struct cfg80211_registered_device *dev;
4403 int err;
4404 long phy_idx;
4405 void *data = NULL;
4406 int data_len = 0;
4407
4408 if (cb->args[0]) {
4409 /*
4410 * 0 is a valid index, but not valid for args[0],
4411 * so we need to offset by 1.
4412 */
4413 phy_idx = cb->args[0] - 1;
4414 } else {
4415 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
4416 nl80211_fam.attrbuf, nl80211_fam.maxattr,
4417 nl80211_policy);
4418 if (err)
4419 return err;
4420 if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY])
4421 return -EINVAL;
4422 phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
4423 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
4424 cb->args[1] =
4425 (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
4426 }
4427
4428 if (cb->args[1]) {
4429 data = nla_data((void *)cb->args[1]);
4430 data_len = nla_len((void *)cb->args[1]);
4431 }
4432
4433 mutex_lock(&cfg80211_mutex);
4434 dev = cfg80211_rdev_by_wiphy_idx(phy_idx);
4435 if (!dev) {
4436 mutex_unlock(&cfg80211_mutex);
4437 return -ENOENT;
4438 }
4439 cfg80211_lock_rdev(dev);
4440 mutex_unlock(&cfg80211_mutex);
4441
4442 if (!dev->ops->testmode_dump) {
4443 err = -EOPNOTSUPP;
4444 goto out_err;
4445 }
4446
4447 while (1) {
4448 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).pid,
4449 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4450 NL80211_CMD_TESTMODE);
4451 struct nlattr *tmdata;
4452
4453 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) {
4454 genlmsg_cancel(skb, hdr);
4455 break;
4456 }
4457
4458 tmdata = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
4459 if (!tmdata) {
4460 genlmsg_cancel(skb, hdr);
4461 break;
4462 }
4463 err = dev->ops->testmode_dump(&dev->wiphy, skb, cb,
4464 data, data_len);
4465 nla_nest_end(skb, tmdata);
4466
4467 if (err == -ENOBUFS || err == -ENOENT) {
4468 genlmsg_cancel(skb, hdr);
4469 break;
4470 } else if (err) {
4471 genlmsg_cancel(skb, hdr);
4472 goto out_err;
4473 }
4474
4475 genlmsg_end(skb, hdr);
4476 }
4477
4478 err = skb->len;
4479 /* see above */
4480 cb->args[0] = phy_idx + 1;
4481 out_err:
4482 cfg80211_unlock_rdev(dev);
4483 return err;
4484}
4485
4363static struct sk_buff * 4486static struct sk_buff *
4364__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev, 4487__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
4365 int approxlen, u32 pid, u32 seq, gfp_t gfp) 4488 int approxlen, u32 pid, u32 seq, gfp_t gfp)
@@ -5306,6 +5429,57 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
5306 return err; 5429 return err;
5307} 5430}
5308 5431
5432static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
5433{
5434 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5435 struct net_device *dev = info->user_ptr[1];
5436 struct wireless_dev *wdev = dev->ieee80211_ptr;
5437 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
5438 struct cfg80211_gtk_rekey_data rekey_data;
5439 int err;
5440
5441 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
5442 return -EINVAL;
5443
5444 err = nla_parse(tb, MAX_NL80211_REKEY_DATA,
5445 nla_data(info->attrs[NL80211_ATTR_REKEY_DATA]),
5446 nla_len(info->attrs[NL80211_ATTR_REKEY_DATA]),
5447 nl80211_rekey_policy);
5448 if (err)
5449 return err;
5450
5451 if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
5452 return -ERANGE;
5453 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN)
5454 return -ERANGE;
5455 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
5456 return -ERANGE;
5457
5458 memcpy(rekey_data.kek, nla_data(tb[NL80211_REKEY_DATA_KEK]),
5459 NL80211_KEK_LEN);
5460 memcpy(rekey_data.kck, nla_data(tb[NL80211_REKEY_DATA_KCK]),
5461 NL80211_KCK_LEN);
5462 memcpy(rekey_data.replay_ctr,
5463 nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]),
5464 NL80211_REPLAY_CTR_LEN);
5465
5466 wdev_lock(wdev);
5467 if (!wdev->current_bss) {
5468 err = -ENOTCONN;
5469 goto out;
5470 }
5471
5472 if (!rdev->ops->set_rekey_data) {
5473 err = -EOPNOTSUPP;
5474 goto out;
5475 }
5476
5477 err = rdev->ops->set_rekey_data(&rdev->wiphy, dev, &rekey_data);
5478 out:
5479 wdev_unlock(wdev);
5480 return err;
5481}
5482
5309#define NL80211_FLAG_NEED_WIPHY 0x01 5483#define NL80211_FLAG_NEED_WIPHY 0x01
5310#define NL80211_FLAG_NEED_NETDEV 0x02 5484#define NL80211_FLAG_NEED_NETDEV 0x02
5311#define NL80211_FLAG_NEED_RTNL 0x04 5485#define NL80211_FLAG_NEED_RTNL 0x04
@@ -5657,6 +5831,7 @@ static struct genl_ops nl80211_ops[] = {
5657 { 5831 {
5658 .cmd = NL80211_CMD_TESTMODE, 5832 .cmd = NL80211_CMD_TESTMODE,
5659 .doit = nl80211_testmode_do, 5833 .doit = nl80211_testmode_do,
5834 .dumpit = nl80211_testmode_dump,
5660 .policy = nl80211_policy, 5835 .policy = nl80211_policy,
5661 .flags = GENL_ADMIN_PERM, 5836 .flags = GENL_ADMIN_PERM,
5662 .internal_flags = NL80211_FLAG_NEED_WIPHY | 5837 .internal_flags = NL80211_FLAG_NEED_WIPHY |
@@ -5836,6 +6011,14 @@ static struct genl_ops nl80211_ops[] = {
5836 .internal_flags = NL80211_FLAG_NEED_WIPHY | 6011 .internal_flags = NL80211_FLAG_NEED_WIPHY |
5837 NL80211_FLAG_NEED_RTNL, 6012 NL80211_FLAG_NEED_RTNL,
5838 }, 6013 },
6014 {
6015 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
6016 .doit = nl80211_set_rekey_data,
6017 .policy = nl80211_policy,
6018 .flags = GENL_ADMIN_PERM,
6019 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
6020 NL80211_FLAG_NEED_RTNL,
6021 },
5839}; 6022};
5840 6023
5841static struct genl_multicast_group nl80211_mlme_mcgrp = { 6024static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -6463,7 +6646,8 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
6463 if (addr) 6646 if (addr)
6464 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); 6647 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
6465 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type); 6648 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type);
6466 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); 6649 if (key_id != -1)
6650 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id);
6467 if (tsc) 6651 if (tsc)
6468 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc); 6652 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc);
6469 6653
@@ -6779,6 +6963,51 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
6779 nlmsg_free(msg); 6963 nlmsg_free(msg);
6780} 6964}
6781 6965
6966void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
6967 struct net_device *netdev, const u8 *bssid,
6968 const u8 *replay_ctr, gfp_t gfp)
6969{
6970 struct sk_buff *msg;
6971 struct nlattr *rekey_attr;
6972 void *hdr;
6973
6974 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
6975 if (!msg)
6976 return;
6977
6978 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
6979 if (!hdr) {
6980 nlmsg_free(msg);
6981 return;
6982 }
6983
6984 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
6985 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
6986 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
6987
6988 rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
6989 if (!rekey_attr)
6990 goto nla_put_failure;
6991
6992 NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR,
6993 NL80211_REPLAY_CTR_LEN, replay_ctr);
6994
6995 nla_nest_end(msg, rekey_attr);
6996
6997 if (genlmsg_end(msg, hdr) < 0) {
6998 nlmsg_free(msg);
6999 return;
7000 }
7001
7002 genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
7003 nl80211_mlme_mcgrp.id, gfp);
7004 return;
7005
7006 nla_put_failure:
7007 genlmsg_cancel(msg, hdr);
7008 nlmsg_free(msg);
7009}
7010
6782void 7011void
6783nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, 7012nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
6784 struct net_device *netdev, const u8 *peer, 7013 struct net_device *netdev, const u8 *peer,