diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 50ff82aa4890..491b0ba40c43 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 */ | ||
211 | static const struct nla_policy | ||
212 | nl80211_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 */ |
210 | static int nl80211_get_ifidx(struct netlink_callback *cb) | 219 | static int nl80211_get_ifidx(struct netlink_callback *cb) |
211 | { | 220 | { |
@@ -5408,6 +5417,57 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
5408 | return err; | 5417 | return err; |
5409 | } | 5418 | } |
5410 | 5419 | ||
5420 | static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) | ||
5421 | { | ||
5422 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
5423 | struct net_device *dev = info->user_ptr[1]; | ||
5424 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
5425 | struct nlattr *tb[NUM_NL80211_REKEY_DATA]; | ||
5426 | struct cfg80211_gtk_rekey_data rekey_data; | ||
5427 | int err; | ||
5428 | |||
5429 | if (!info->attrs[NL80211_ATTR_REKEY_DATA]) | ||
5430 | return -EINVAL; | ||
5431 | |||
5432 | err = nla_parse(tb, MAX_NL80211_REKEY_DATA, | ||
5433 | nla_data(info->attrs[NL80211_ATTR_REKEY_DATA]), | ||
5434 | nla_len(info->attrs[NL80211_ATTR_REKEY_DATA]), | ||
5435 | nl80211_rekey_policy); | ||
5436 | if (err) | ||
5437 | return err; | ||
5438 | |||
5439 | if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN) | ||
5440 | return -ERANGE; | ||
5441 | if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN) | ||
5442 | return -ERANGE; | ||
5443 | if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN) | ||
5444 | return -ERANGE; | ||
5445 | |||
5446 | memcpy(rekey_data.kek, nla_data(tb[NL80211_REKEY_DATA_KEK]), | ||
5447 | NL80211_KEK_LEN); | ||
5448 | memcpy(rekey_data.kck, nla_data(tb[NL80211_REKEY_DATA_KCK]), | ||
5449 | NL80211_KCK_LEN); | ||
5450 | memcpy(rekey_data.replay_ctr, | ||
5451 | nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]), | ||
5452 | NL80211_REPLAY_CTR_LEN); | ||
5453 | |||
5454 | wdev_lock(wdev); | ||
5455 | if (!wdev->current_bss) { | ||
5456 | err = -ENOTCONN; | ||
5457 | goto out; | ||
5458 | } | ||
5459 | |||
5460 | if (!rdev->ops->set_rekey_data) { | ||
5461 | err = -EOPNOTSUPP; | ||
5462 | goto out; | ||
5463 | } | ||
5464 | |||
5465 | err = rdev->ops->set_rekey_data(&rdev->wiphy, dev, &rekey_data); | ||
5466 | out: | ||
5467 | wdev_unlock(wdev); | ||
5468 | return err; | ||
5469 | } | ||
5470 | |||
5411 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 5471 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
5412 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 5472 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
5413 | #define NL80211_FLAG_NEED_RTNL 0x04 | 5473 | #define NL80211_FLAG_NEED_RTNL 0x04 |
@@ -5939,6 +5999,14 @@ static struct genl_ops nl80211_ops[] = { | |||
5939 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | 5999 | .internal_flags = NL80211_FLAG_NEED_WIPHY | |
5940 | NL80211_FLAG_NEED_RTNL, | 6000 | NL80211_FLAG_NEED_RTNL, |
5941 | }, | 6001 | }, |
6002 | { | ||
6003 | .cmd = NL80211_CMD_SET_REKEY_OFFLOAD, | ||
6004 | .doit = nl80211_set_rekey_data, | ||
6005 | .policy = nl80211_policy, | ||
6006 | .flags = GENL_ADMIN_PERM, | ||
6007 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
6008 | NL80211_FLAG_NEED_RTNL, | ||
6009 | }, | ||
5942 | }; | 6010 | }; |
5943 | 6011 | ||
5944 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 6012 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -6883,6 +6951,51 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
6883 | nlmsg_free(msg); | 6951 | nlmsg_free(msg); |
6884 | } | 6952 | } |
6885 | 6953 | ||
6954 | void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | ||
6955 | struct net_device *netdev, const u8 *bssid, | ||
6956 | const u8 *replay_ctr, gfp_t gfp) | ||
6957 | { | ||
6958 | struct sk_buff *msg; | ||
6959 | struct nlattr *rekey_attr; | ||
6960 | void *hdr; | ||
6961 | |||
6962 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
6963 | if (!msg) | ||
6964 | return; | ||
6965 | |||
6966 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD); | ||
6967 | if (!hdr) { | ||
6968 | nlmsg_free(msg); | ||
6969 | return; | ||
6970 | } | ||
6971 | |||
6972 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
6973 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
6974 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); | ||
6975 | |||
6976 | rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA); | ||
6977 | if (!rekey_attr) | ||
6978 | goto nla_put_failure; | ||
6979 | |||
6980 | NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, | ||
6981 | NL80211_REPLAY_CTR_LEN, replay_ctr); | ||
6982 | |||
6983 | nla_nest_end(msg, rekey_attr); | ||
6984 | |||
6985 | if (genlmsg_end(msg, hdr) < 0) { | ||
6986 | nlmsg_free(msg); | ||
6987 | return; | ||
6988 | } | ||
6989 | |||
6990 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
6991 | nl80211_mlme_mcgrp.id, gfp); | ||
6992 | return; | ||
6993 | |||
6994 | nla_put_failure: | ||
6995 | genlmsg_cancel(msg, hdr); | ||
6996 | nlmsg_free(msg); | ||
6997 | } | ||
6998 | |||
6886 | void | 6999 | void |
6887 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | 7000 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, |
6888 | struct net_device *netdev, const u8 *peer, | 7001 | struct net_device *netdev, const u8 *peer, |