Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 256232
b: refs/heads/master
c: e5497d7
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Jul 6, 2011
1 parent 2bd7fff commit 24308f6
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 830af02f24fbc087999b757b8eca51829c67fa6f
refs/heads/master: e5497d766adb92bcbd1fa4a147e188f84f34b20a
39 changes: 39 additions & 0 deletions trunk/include/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,14 @@
* more background information, see
* http://wireless.kernel.org/en/users/Documentation/WoWLAN.
*
* @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver
* the necessary information for supporting GTK rekey offload. This
* feature is typically used during WoWLAN. The configuration data
* is contained in %NL80211_ATTR_REKEY_DATA (which is nested and
* contains the data in sub-attributes). After rekeying happened,
* this command may also be sent by the driver as an MLME event to
* inform userspace of the new replay counter.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -605,6 +613,8 @@ enum nl80211_commands {
NL80211_CMD_SCHED_SCAN_RESULTS,
NL80211_CMD_SCHED_SCAN_STOPPED,

NL80211_CMD_SET_REKEY_OFFLOAD,

/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
Expand Down Expand Up @@ -996,6 +1006,9 @@ enum nl80211_commands {
* are managed in software: interfaces of these types aren't subject to
* any restrictions in their number or combinations.
*
* @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information
* necessary for GTK rekeying in the device, see &enum nl80211_rekey_data.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -1194,6 +1207,8 @@ enum nl80211_attrs {
NL80211_ATTR_INTERFACE_COMBINATIONS,
NL80211_ATTR_SOFTWARE_IFTYPES,

NL80211_ATTR_REKEY_DATA,

/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
Expand Down Expand Up @@ -2361,4 +2376,28 @@ enum nl80211_plink_state {
MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1
};

#define NL80211_KCK_LEN 16
#define NL80211_KEK_LEN 16
#define NL80211_REPLAY_CTR_LEN 8

/**
* enum nl80211_rekey_data - attributes for GTK rekey offload
* @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes
* @NL80211_REKEY_DATA_KEK: key encryption key (binary)
* @NL80211_REKEY_DATA_KCK: key confirmation key (binary)
* @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary)
* @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal)
* @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal)
*/
enum nl80211_rekey_data {
__NL80211_REKEY_DATA_INVALID,
NL80211_REKEY_DATA_KEK,
NL80211_REKEY_DATA_KCK,
NL80211_REKEY_DATA_REPLAY_CTR,

/* keep last */
NUM_NL80211_REKEY_DATA,
MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1
};

#endif /* __LINUX_NL80211_H */
26 changes: 26 additions & 0 deletions trunk/include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,18 @@ struct cfg80211_wowlan {
int n_patterns;
};

/**
* struct cfg80211_gtk_rekey_data - rekey data
* @kek: key encryption key
* @kck: key confirmation key
* @replay_ctr: replay counter
*/
struct cfg80211_gtk_rekey_data {
u8 kek[NL80211_KEK_LEN];
u8 kck[NL80211_KCK_LEN];
u8 replay_ctr[NL80211_REPLAY_CTR_LEN];
};

/**
* struct cfg80211_ops - backend description for wireless configuration
*
Expand Down Expand Up @@ -1197,6 +1209,8 @@ struct cfg80211_wowlan {
*
* @set_default_mgmt_key: set the default management frame key on an interface
*
* @set_rekey_data: give the data necessary for GTK rekeying to the driver
*
* @add_beacon: Add a beacon with given parameters, @head, @interval
* and @dtim_period will be valid, @tail is optional.
* @set_beacon: Change the beacon parameters for an access point mode
Expand Down Expand Up @@ -1499,6 +1513,9 @@ struct cfg80211_ops {
struct net_device *dev,
struct cfg80211_sched_scan_request *request);
int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev);

int (*set_rekey_data)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_gtk_rekey_data *data);
};

/*
Expand Down Expand Up @@ -3033,6 +3050,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
void cfg80211_cqm_pktloss_notify(struct net_device *dev,
const u8 *peer, u32 num_packets, gfp_t gfp);

/**
* cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
* @dev: network device
* @bssid: BSSID of AP (to avoid races)
* @replay_ctr: new replay counter
*/
void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
const u8 *replay_ctr, gfp_t gfp);

/* Logging, debugging and troubleshooting/diagnostic helpers. */

/* wiphy_printk helpers, similar to dev_printk */
Expand Down
11 changes: 11 additions & 0 deletions trunk/net/wireless/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -1084,3 +1084,14 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
}
EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);

void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
const u8 *replay_ctr, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);

nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
}
EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
113 changes: 113 additions & 0 deletions trunk/net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
[NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
[NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
[NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
};

/* policy for the key attributes */
Expand Down Expand Up @@ -206,6 +207,14 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
[NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
};

/* policy for GTK rekey offload attributes */
static const struct nla_policy
nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
[NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN },
[NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
[NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
};

/* ifidx get helper */
static int nl80211_get_ifidx(struct netlink_callback *cb)
{
Expand Down Expand Up @@ -5408,6 +5417,57 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
return err;
}

static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct nlattr *tb[NUM_NL80211_REKEY_DATA];
struct cfg80211_gtk_rekey_data rekey_data;
int err;

if (!info->attrs[NL80211_ATTR_REKEY_DATA])
return -EINVAL;

err = nla_parse(tb, MAX_NL80211_REKEY_DATA,
nla_data(info->attrs[NL80211_ATTR_REKEY_DATA]),
nla_len(info->attrs[NL80211_ATTR_REKEY_DATA]),
nl80211_rekey_policy);
if (err)
return err;

if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
return -ERANGE;
if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN)
return -ERANGE;
if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
return -ERANGE;

memcpy(rekey_data.kek, nla_data(tb[NL80211_REKEY_DATA_KEK]),
NL80211_KEK_LEN);
memcpy(rekey_data.kck, nla_data(tb[NL80211_REKEY_DATA_KCK]),
NL80211_KCK_LEN);
memcpy(rekey_data.replay_ctr,
nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]),
NL80211_REPLAY_CTR_LEN);

wdev_lock(wdev);
if (!wdev->current_bss) {
err = -ENOTCONN;
goto out;
}

if (!rdev->ops->set_rekey_data) {
err = -EOPNOTSUPP;
goto out;
}

err = rdev->ops->set_rekey_data(&rdev->wiphy, dev, &rekey_data);
out:
wdev_unlock(wdev);
return err;
}

#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
Expand Down Expand Up @@ -5939,6 +5999,14 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_WIPHY |
NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
.doit = nl80211_set_rekey_data,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
};

static struct genl_multicast_group nl80211_mlme_mcgrp = {
Expand Down Expand Up @@ -6883,6 +6951,51 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
nlmsg_free(msg);
}

void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
const u8 *replay_ctr, gfp_t gfp)
{
struct sk_buff *msg;
struct nlattr *rekey_attr;
void *hdr;

msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
if (!msg)
return;

hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
if (!hdr) {
nlmsg_free(msg);
return;
}

NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);

rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
if (!rekey_attr)
goto nla_put_failure;

NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR,
NL80211_REPLAY_CTR_LEN, replay_ctr);

nla_nest_end(msg, rekey_attr);

if (genlmsg_end(msg, hdr) < 0) {
nlmsg_free(msg);
return;
}

genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;

nla_put_failure:
genlmsg_cancel(msg, hdr);
nlmsg_free(msg);
}

void
nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *peer,
Expand Down
4 changes: 4 additions & 0 deletions trunk/net/wireless/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,8 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *peer,
u32 num_packets, gfp_t gfp);

void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
const u8 *replay_ctr, gfp_t gfp);

#endif /* __NET_WIRELESS_NL80211_H */

0 comments on commit 24308f6

Please sign in to comment.