diff options
-rw-r--r-- | include/linux/nl80211.h | 34 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 54 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 5 | ||||
-rw-r--r-- | net/wireless/reg.c | 28 |
4 files changed, 106 insertions, 15 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 209cacee5285..05ba3539b77e 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * Copyright 2008 Michael Wu <flamingice@sourmilk.net> | 7 | * Copyright 2008 Michael Wu <flamingice@sourmilk.net> |
8 | * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com> | 8 | * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com> |
9 | * Copyright 2008 Michael Buesch <mb@bu3sch.de> | 9 | * Copyright 2008 Michael Buesch <mb@bu3sch.de> |
10 | * Copyright 2008 Luis R. Rodriguez <lrodriguez@atheros.com> | 10 | * Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com> |
11 | * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com> | 11 | * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com> |
12 | * Copyright 2008 Colin McCabe <colin@cozybit.com> | 12 | * Copyright 2008 Colin McCabe <colin@cozybit.com> |
13 | * | 13 | * |
@@ -166,6 +166,22 @@ | |||
166 | * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is | 166 | * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is |
167 | * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on | 167 | * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on |
168 | * to (%NL80211_ATTR_REG_ALPHA2). | 168 | * to (%NL80211_ATTR_REG_ALPHA2). |
169 | * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon | ||
170 | * has been found while world roaming thus enabling active scan or | ||
171 | * any mode of operation that initiates TX (beacons) on a channel | ||
172 | * where we would not have been able to do either before. As an example | ||
173 | * if you are world roaming (regulatory domain set to world or if your | ||
174 | * driver is using a custom world roaming regulatory domain) and while | ||
175 | * doing a passive scan on the 5 GHz band you find an AP there (if not | ||
176 | * on a DFS channel) you will now be able to actively scan for that AP | ||
177 | * or use AP mode on your card on that same channel. Note that this will | ||
178 | * never be used for channels 1-11 on the 2 GHz band as they are always | ||
179 | * enabled world wide. This beacon hint is only sent if your device had | ||
180 | * either disabled active scanning or beaconing on a channel. We send to | ||
181 | * userspace the wiphy on which we removed a restriction from | ||
182 | * (%NL80211_ATTR_WIPHY) and the channel on which this occurred | ||
183 | * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) | ||
184 | * the beacon hint was processed. | ||
169 | * | 185 | * |
170 | * @NL80211_CMD_AUTHENTICATE: authentication request and notification. | 186 | * @NL80211_CMD_AUTHENTICATE: authentication request and notification. |
171 | * This command is used both as a command (request to authenticate) and | 187 | * This command is used both as a command (request to authenticate) and |
@@ -270,6 +286,8 @@ enum nl80211_commands { | |||
270 | 286 | ||
271 | NL80211_CMD_MICHAEL_MIC_FAILURE, | 287 | NL80211_CMD_MICHAEL_MIC_FAILURE, |
272 | 288 | ||
289 | NL80211_CMD_REG_BEACON_HINT, | ||
290 | |||
273 | /* add new commands above here */ | 291 | /* add new commands above here */ |
274 | 292 | ||
275 | /* used to define NL80211_CMD_MAX below */ | 293 | /* used to define NL80211_CMD_MAX below */ |
@@ -288,6 +306,7 @@ enum nl80211_commands { | |||
288 | #define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE | 306 | #define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE |
289 | #define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE | 307 | #define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE |
290 | #define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE | 308 | #define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE |
309 | #define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT | ||
291 | 310 | ||
292 | /** | 311 | /** |
293 | * enum nl80211_attrs - nl80211 netlink attributes | 312 | * enum nl80211_attrs - nl80211 netlink attributes |
@@ -423,6 +442,17 @@ enum nl80211_commands { | |||
423 | * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as | 442 | * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as |
424 | * a u32 | 443 | * a u32 |
425 | * | 444 | * |
445 | * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change | ||
446 | * due to considerations from a beacon hint. This attribute reflects | ||
447 | * the state of the channel _before_ the beacon hint processing. This | ||
448 | * attributes consists of a nested attribute containing | ||
449 | * NL80211_FREQUENCY_ATTR_* | ||
450 | * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change | ||
451 | * due to considerations from a beacon hint. This attribute reflects | ||
452 | * the state of the channel _after_ the beacon hint processing. This | ||
453 | * attributes consists of a nested attribute containing | ||
454 | * NL80211_FREQUENCY_ATTR_* | ||
455 | * | ||
426 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 456 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
427 | * @__NL80211_ATTR_AFTER_LAST: internal use | 457 | * @__NL80211_ATTR_AFTER_LAST: internal use |
428 | */ | 458 | */ |
@@ -511,6 +541,8 @@ enum nl80211_attrs { | |||
511 | 541 | ||
512 | NL80211_ATTR_MAX_SCAN_IE_LEN, | 542 | NL80211_ATTR_MAX_SCAN_IE_LEN, |
513 | 543 | ||
544 | NL80211_ATTR_FREQ_BEFORE, | ||
545 | NL80211_ATTR_FREQ_AFTER, | ||
514 | /* add attributes here, update the policy in nl80211.c */ | 546 | /* add attributes here, update the policy in nl80211.c */ |
515 | 547 | ||
516 | __NL80211_ATTR_AFTER_LAST, | 548 | __NL80211_ATTR_AFTER_LAST, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7285bdc4e598..85b5aa3c76f8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3491,6 +3491,60 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | |||
3491 | nlmsg_free(msg); | 3491 | nlmsg_free(msg); |
3492 | } | 3492 | } |
3493 | 3493 | ||
3494 | void nl80211_send_beacon_hint_event(struct wiphy *wiphy, | ||
3495 | struct ieee80211_channel *channel_before, | ||
3496 | struct ieee80211_channel *channel_after) | ||
3497 | { | ||
3498 | struct sk_buff *msg; | ||
3499 | void *hdr; | ||
3500 | struct nlattr *nl_freq; | ||
3501 | |||
3502 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | ||
3503 | if (!msg) | ||
3504 | return; | ||
3505 | |||
3506 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT); | ||
3507 | if (!hdr) { | ||
3508 | nlmsg_free(msg); | ||
3509 | return; | ||
3510 | } | ||
3511 | |||
3512 | /* | ||
3513 | * Since we are applying the beacon hint to a wiphy we know its | ||
3514 | * wiphy_idx is valid | ||
3515 | */ | ||
3516 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)); | ||
3517 | |||
3518 | /* Before */ | ||
3519 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); | ||
3520 | if (!nl_freq) | ||
3521 | goto nla_put_failure; | ||
3522 | if (nl80211_msg_put_channel(msg, channel_before)) | ||
3523 | goto nla_put_failure; | ||
3524 | nla_nest_end(msg, nl_freq); | ||
3525 | |||
3526 | /* After */ | ||
3527 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER); | ||
3528 | if (!nl_freq) | ||
3529 | goto nla_put_failure; | ||
3530 | if (nl80211_msg_put_channel(msg, channel_after)) | ||
3531 | goto nla_put_failure; | ||
3532 | nla_nest_end(msg, nl_freq); | ||
3533 | |||
3534 | if (genlmsg_end(msg, hdr) < 0) { | ||
3535 | nlmsg_free(msg); | ||
3536 | return; | ||
3537 | } | ||
3538 | |||
3539 | genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_ATOMIC); | ||
3540 | |||
3541 | return; | ||
3542 | |||
3543 | nla_put_failure: | ||
3544 | genlmsg_cancel(msg, hdr); | ||
3545 | nlmsg_free(msg); | ||
3546 | } | ||
3547 | |||
3494 | /* initialisation/exit functions */ | 3548 | /* initialisation/exit functions */ |
3495 | 3549 | ||
3496 | int nl80211_init(void) | 3550 | int nl80211_init(void) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index e4b92cccd157..b3aaa59afa08 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -29,4 +29,9 @@ nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | |||
29 | enum nl80211_key_type key_type, | 29 | enum nl80211_key_type key_type, |
30 | int key_id, const u8 *tsc); | 30 | int key_id, const u8 *tsc); |
31 | 31 | ||
32 | extern void | ||
33 | nl80211_send_beacon_hint_event(struct wiphy *wiphy, | ||
34 | struct ieee80211_channel *channel_before, | ||
35 | struct ieee80211_channel *channel_after); | ||
36 | |||
32 | #endif /* __NET_WIRELESS_NL80211_H */ | 37 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4af4304cec3e..574e217bcc86 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1049,18 +1049,10 @@ static void handle_reg_beacon(struct wiphy *wiphy, | |||
1049 | unsigned int chan_idx, | 1049 | unsigned int chan_idx, |
1050 | struct reg_beacon *reg_beacon) | 1050 | struct reg_beacon *reg_beacon) |
1051 | { | 1051 | { |
1052 | #ifdef CONFIG_CFG80211_REG_DEBUG | ||
1053 | #define REG_DEBUG_BEACON_FLAG(desc) \ | ||
1054 | printk(KERN_DEBUG "cfg80211: Enabling " desc " on " \ | ||
1055 | "frequency: %d MHz (Ch %d) on %s\n", \ | ||
1056 | reg_beacon->chan.center_freq, \ | ||
1057 | ieee80211_frequency_to_channel(reg_beacon->chan.center_freq), \ | ||
1058 | wiphy_name(wiphy)); | ||
1059 | #else | ||
1060 | #define REG_DEBUG_BEACON_FLAG(desc) do {} while (0) | ||
1061 | #endif | ||
1062 | struct ieee80211_supported_band *sband; | 1052 | struct ieee80211_supported_band *sband; |
1063 | struct ieee80211_channel *chan; | 1053 | struct ieee80211_channel *chan; |
1054 | bool channel_changed = false; | ||
1055 | struct ieee80211_channel chan_before; | ||
1064 | 1056 | ||
1065 | assert_cfg80211_lock(); | 1057 | assert_cfg80211_lock(); |
1066 | 1058 | ||
@@ -1070,20 +1062,28 @@ static void handle_reg_beacon(struct wiphy *wiphy, | |||
1070 | if (likely(chan->center_freq != reg_beacon->chan.center_freq)) | 1062 | if (likely(chan->center_freq != reg_beacon->chan.center_freq)) |
1071 | return; | 1063 | return; |
1072 | 1064 | ||
1065 | if (chan->beacon_found) | ||
1066 | return; | ||
1067 | |||
1068 | chan->beacon_found = true; | ||
1069 | |||
1070 | chan_before.center_freq = chan->center_freq; | ||
1071 | chan_before.flags = chan->flags; | ||
1072 | |||
1073 | if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && | 1073 | if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && |
1074 | !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) { | 1074 | !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) { |
1075 | chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 1075 | chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; |
1076 | REG_DEBUG_BEACON_FLAG("active scanning"); | 1076 | channel_changed = true; |
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && | 1079 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && |
1080 | !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) { | 1080 | !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) { |
1081 | chan->flags &= ~IEEE80211_CHAN_NO_IBSS; | 1081 | chan->flags &= ~IEEE80211_CHAN_NO_IBSS; |
1082 | REG_DEBUG_BEACON_FLAG("beaconing"); | 1082 | channel_changed = true; |
1083 | } | 1083 | } |
1084 | 1084 | ||
1085 | chan->beacon_found = true; | 1085 | if (channel_changed) |
1086 | #undef REG_DEBUG_BEACON_FLAG | 1086 | nl80211_send_beacon_hint_event(wiphy, &chan_before, chan); |
1087 | } | 1087 | } |
1088 | 1088 | ||
1089 | /* | 1089 | /* |