aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h34
-rw-r--r--net/wireless/nl80211.c54
-rw-r--r--net/wireless/nl80211.h5
-rw-r--r--net/wireless/reg.c28
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
3494void 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
3543nla_put_failure:
3544 genlmsg_cancel(msg, hdr);
3545 nlmsg_free(msg);
3546}
3547
3494/* initialisation/exit functions */ 3548/* initialisation/exit functions */
3495 3549
3496int nl80211_init(void) 3550int 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
32extern void
33nl80211_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/*