aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-11-24 18:01:29 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-24 18:01:29 -0500
commit4ba3eb034fb6fd1990ccc5a6d71d5abcda37b905 (patch)
tree0789ba36d96dba330416a1e6a9a68e891a78802a /net/wireless
parent35700212b45ea9f98fa682cfc1bc1a67c9ccc34b (diff)
parent18b6c9a2213d3b6e0212e8b225abf95f7564206a (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/Kconfig6
-rw-r--r--net/wireless/core.c17
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/ibss.c4
-rw-r--r--net/wireless/mlme.c56
-rw-r--r--net/wireless/nl80211.c40
-rw-r--r--net/wireless/reg.c13
-rw-r--r--net/wireless/scan.c40
-rw-r--r--net/wireless/util.c36
-rw-r--r--net/wireless/wext-compat.c49
10 files changed, 204 insertions, 59 deletions
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 614bdcec1c80..90e93a5701aa 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -74,12 +74,6 @@ config CFG80211_REG_DEBUG
74 74
75 If unsure, say N. 75 If unsure, say N.
76 76
77config CFG80211_DEFAULT_PS_VALUE
78 int
79 default 1 if CFG80211_DEFAULT_PS
80 default 0
81 depends on CFG80211
82
83config CFG80211_DEFAULT_PS 77config CFG80211_DEFAULT_PS
84 bool "enable powersave by default" 78 bool "enable powersave by default"
85 depends on CFG80211 79 depends on CFG80211
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 45bd63ad2eb2..fe6f402a22af 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -231,7 +231,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
231 struct wireless_dev *wdev; 231 struct wireless_dev *wdev;
232 int err = 0; 232 int err = 0;
233 233
234 if (!rdev->wiphy.netnsok) 234 if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
235 return -EOPNOTSUPP; 235 return -EOPNOTSUPP;
236 236
237 list_for_each_entry(wdev, &rdev->netdev_list, list) { 237 list_for_each_entry(wdev, &rdev->netdev_list, list) {
@@ -368,7 +368,9 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
368 rdev->wiphy.dev.class = &ieee80211_class; 368 rdev->wiphy.dev.class = &ieee80211_class;
369 rdev->wiphy.dev.platform_data = rdev; 369 rdev->wiphy.dev.platform_data = rdev;
370 370
371 rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE; 371#ifdef CONFIG_CFG80211_DEFAULT_PS
372 rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
373#endif
372 374
373 wiphy_net_set(&rdev->wiphy, &init_net); 375 wiphy_net_set(&rdev->wiphy, &init_net);
374 376
@@ -483,7 +485,7 @@ int wiphy_register(struct wiphy *wiphy)
483 if (IS_ERR(rdev->wiphy.debugfsdir)) 485 if (IS_ERR(rdev->wiphy.debugfsdir))
484 rdev->wiphy.debugfsdir = NULL; 486 rdev->wiphy.debugfsdir = NULL;
485 487
486 if (wiphy->custom_regulatory) { 488 if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
487 struct regulatory_request request; 489 struct regulatory_request request;
488 490
489 request.wiphy_idx = get_wiphy_idx(wiphy); 491 request.wiphy_idx = get_wiphy_idx(wiphy);
@@ -681,7 +683,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
681 wdev->wext.default_key = -1; 683 wdev->wext.default_key = -1;
682 wdev->wext.default_mgmt_key = -1; 684 wdev->wext.default_mgmt_key = -1;
683 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; 685 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
684 wdev->wext.ps = wdev->wiphy->ps_default; 686 if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
687 wdev->wext.ps = true;
688 else
689 wdev->wext.ps = false;
685 wdev->wext.ps_timeout = 100; 690 wdev->wext.ps_timeout = 100;
686 if (rdev->ops->set_power_mgmt) 691 if (rdev->ops->set_power_mgmt)
687 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, 692 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
@@ -693,6 +698,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
693#endif 698#endif
694 if (!dev->ethtool_ops) 699 if (!dev->ethtool_ops)
695 dev->ethtool_ops = &cfg80211_ethtool_ops; 700 dev->ethtool_ops = &cfg80211_ethtool_ops;
701
702 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
703 wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
704 dev->priv_flags |= IFF_DONT_BRIDGE;
696 break; 705 break;
697 case NETDEV_GOING_DOWN: 706 case NETDEV_GOING_DOWN:
698 switch (wdev->iftype) { 707 switch (wdev->iftype) {
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 5aeebb9085f8..a9db9e6255bb 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -273,6 +273,8 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
273 struct cfg80211_ibss_params *params, 273 struct cfg80211_ibss_params *params,
274 struct cfg80211_cached_keys *connkeys); 274 struct cfg80211_cached_keys *connkeys);
275void cfg80211_clear_ibss(struct net_device *dev, bool nowext); 275void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
276int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
277 struct net_device *dev, bool nowext);
276int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 278int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
277 struct net_device *dev, bool nowext); 279 struct net_device *dev, bool nowext);
278void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); 280void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 39b6d92e2828..34dfc93fa713 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -169,8 +169,8 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
169 wdev_unlock(wdev); 169 wdev_unlock(wdev);
170} 170}
171 171
172static int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 172int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
173 struct net_device *dev, bool nowext) 173 struct net_device *dev, bool nowext)
174{ 174{
175 struct wireless_dev *wdev = dev->ieee80211_ptr; 175 struct wireless_dev *wdev = dev->ieee80211_ptr;
176 int err; 176 int err;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 2610b746effa..1001db4912f7 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -243,21 +243,12 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
243} 243}
244EXPORT_SYMBOL(cfg80211_send_disassoc); 244EXPORT_SYMBOL(cfg80211_send_disassoc);
245 245
246void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) 246static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr)
247{ 247{
248 struct wireless_dev *wdev = dev->ieee80211_ptr;
249 struct wiphy *wiphy = wdev->wiphy;
250 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
251 int i; 248 int i;
252 bool done = false; 249 bool done = false;
253 250
254 wdev_lock(wdev); 251 ASSERT_WDEV_LOCK(wdev);
255
256 nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
257 if (wdev->sme_state == CFG80211_SME_CONNECTING)
258 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
259 WLAN_STATUS_UNSPECIFIED_FAILURE,
260 false, NULL);
261 252
262 for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { 253 for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
263 if (wdev->authtry_bsses[i] && 254 if (wdev->authtry_bsses[i] &&
@@ -272,6 +263,29 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
272 } 263 }
273 264
274 WARN_ON(!done); 265 WARN_ON(!done);
266}
267
268void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr)
269{
270 __cfg80211_auth_remove(dev->ieee80211_ptr, addr);
271}
272EXPORT_SYMBOL(__cfg80211_auth_canceled);
273
274void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
275{
276 struct wireless_dev *wdev = dev->ieee80211_ptr;
277 struct wiphy *wiphy = wdev->wiphy;
278 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
279
280 wdev_lock(wdev);
281
282 nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
283 if (wdev->sme_state == CFG80211_SME_CONNECTING)
284 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
285 WLAN_STATUS_UNSPECIFIED_FAILURE,
286 false, NULL);
287
288 __cfg80211_auth_remove(wdev, addr);
275 289
276 wdev_unlock(wdev); 290 wdev_unlock(wdev);
277} 291}
@@ -446,12 +460,23 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
446 struct cfg80211_assoc_request req; 460 struct cfg80211_assoc_request req;
447 struct cfg80211_internal_bss *bss; 461 struct cfg80211_internal_bss *bss;
448 int i, err, slot = -1; 462 int i, err, slot = -1;
463 bool was_connected = false;
449 464
450 ASSERT_WDEV_LOCK(wdev); 465 ASSERT_WDEV_LOCK(wdev);
451 466
452 memset(&req, 0, sizeof(req)); 467 memset(&req, 0, sizeof(req));
453 468
454 if (wdev->current_bss) 469 if (wdev->current_bss && prev_bssid &&
470 memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) {
471 /*
472 * Trying to reassociate: Allow this to proceed and let the old
473 * association to be dropped when the new one is completed.
474 */
475 if (wdev->sme_state == CFG80211_SME_CONNECTED) {
476 was_connected = true;
477 wdev->sme_state = CFG80211_SME_CONNECTING;
478 }
479 } else if (wdev->current_bss)
455 return -EALREADY; 480 return -EALREADY;
456 481
457 req.ie = ie; 482 req.ie = ie;
@@ -461,8 +486,11 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
461 req.prev_bssid = prev_bssid; 486 req.prev_bssid = prev_bssid;
462 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, 487 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
463 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 488 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
464 if (!req.bss) 489 if (!req.bss) {
490 if (was_connected)
491 wdev->sme_state = CFG80211_SME_CONNECTED;
465 return -ENOENT; 492 return -ENOENT;
493 }
466 494
467 bss = bss_from_pub(req.bss); 495 bss = bss_from_pub(req.bss);
468 496
@@ -480,6 +508,8 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
480 508
481 err = rdev->ops->assoc(&rdev->wiphy, dev, &req); 509 err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
482 out: 510 out:
511 if (err && was_connected)
512 wdev->sme_state = CFG80211_SME_CONNECTED;
483 /* still a reference in wdev->auth_bsses[slot] */ 513 /* still a reference in wdev->auth_bsses[slot] */
484 cfg80211_put_bss(req.bss); 514 cfg80211_put_bss(req.bss);
485 return err; 515 return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 37264d56bace..149539ade15e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -561,7 +561,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
561 CMD(deauth, DEAUTHENTICATE); 561 CMD(deauth, DEAUTHENTICATE);
562 CMD(disassoc, DISASSOCIATE); 562 CMD(disassoc, DISASSOCIATE);
563 CMD(join_ibss, JOIN_IBSS); 563 CMD(join_ibss, JOIN_IBSS);
564 if (dev->wiphy.netnsok) { 564 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
565 i++; 565 i++;
566 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); 566 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
567 } 567 }
@@ -968,6 +968,32 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
968 return 0; 968 return 0;
969} 969}
970 970
971static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
972 struct net_device *netdev, u8 use_4addr,
973 enum nl80211_iftype iftype)
974{
975 if (!use_4addr) {
976 if (netdev && netdev->br_port)
977 return -EBUSY;
978 return 0;
979 }
980
981 switch (iftype) {
982 case NL80211_IFTYPE_AP_VLAN:
983 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
984 return 0;
985 break;
986 case NL80211_IFTYPE_STATION:
987 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
988 return 0;
989 break;
990 default:
991 break;
992 }
993
994 return -EOPNOTSUPP;
995}
996
971static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) 997static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
972{ 998{
973 struct cfg80211_registered_device *rdev; 999 struct cfg80211_registered_device *rdev;
@@ -1011,6 +1037,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1011 if (info->attrs[NL80211_ATTR_4ADDR]) { 1037 if (info->attrs[NL80211_ATTR_4ADDR]) {
1012 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1038 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1013 change = true; 1039 change = true;
1040 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
1041 if (err)
1042 goto unlock;
1014 } else { 1043 } else {
1015 params.use_4addr = -1; 1044 params.use_4addr = -1;
1016 } 1045 }
@@ -1034,6 +1063,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1034 else 1063 else
1035 err = 0; 1064 err = 0;
1036 1065
1066 if (!err && params.use_4addr != -1)
1067 dev->ieee80211_ptr->use_4addr = params.use_4addr;
1068
1037 unlock: 1069 unlock:
1038 dev_put(dev); 1070 dev_put(dev);
1039 cfg80211_unlock_rdev(rdev); 1071 cfg80211_unlock_rdev(rdev);
@@ -1081,8 +1113,12 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1081 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 1113 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1082 } 1114 }
1083 1115
1084 if (info->attrs[NL80211_ATTR_4ADDR]) 1116 if (info->attrs[NL80211_ATTR_4ADDR]) {
1085 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1117 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1118 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
1119 if (err)
1120 goto unlock;
1121 }
1086 1122
1087 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 1123 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
1088 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, 1124 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index f256dfffbf46..1f33017737fd 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1008,7 +1008,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
1008 1008
1009 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && 1009 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
1010 request_wiphy && request_wiphy == wiphy && 1010 request_wiphy && request_wiphy == wiphy &&
1011 request_wiphy->strict_regulatory) { 1011 request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
1012 /* 1012 /*
1013 * This gaurantees the driver's requested regulatory domain 1013 * This gaurantees the driver's requested regulatory domain
1014 * will always be used as a base for further regulatory 1014 * will always be used as a base for further regulatory
@@ -1051,13 +1051,13 @@ static bool ignore_reg_update(struct wiphy *wiphy,
1051 if (!last_request) 1051 if (!last_request)
1052 return true; 1052 return true;
1053 if (initiator == NL80211_REGDOM_SET_BY_CORE && 1053 if (initiator == NL80211_REGDOM_SET_BY_CORE &&
1054 wiphy->custom_regulatory) 1054 wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)
1055 return true; 1055 return true;
1056 /* 1056 /*
1057 * wiphy->regd will be set once the device has its own 1057 * wiphy->regd will be set once the device has its own
1058 * desired regulatory domain set 1058 * desired regulatory domain set
1059 */ 1059 */
1060 if (wiphy->strict_regulatory && !wiphy->regd && 1060 if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd &&
1061 !is_world_regdom(last_request->alpha2)) 1061 !is_world_regdom(last_request->alpha2))
1062 return true; 1062 return true;
1063 return false; 1063 return false;
@@ -1093,7 +1093,7 @@ static void handle_reg_beacon(struct wiphy *wiphy,
1093 1093
1094 chan->beacon_found = true; 1094 chan->beacon_found = true;
1095 1095
1096 if (wiphy->disable_beacon_hints) 1096 if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS)
1097 return; 1097 return;
1098 1098
1099 chan_before.center_freq = chan->center_freq; 1099 chan_before.center_freq = chan->center_freq;
@@ -1164,7 +1164,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
1164 return true; 1164 return true;
1165 if (last_request && 1165 if (last_request &&
1166 last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && 1166 last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1167 wiphy->custom_regulatory) 1167 wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)
1168 return true; 1168 return true;
1169 return false; 1169 return false;
1170} 1170}
@@ -1591,7 +1591,8 @@ static void reg_process_hint(struct regulatory_request *reg_request)
1591 1591
1592 r = __regulatory_hint(wiphy, reg_request); 1592 r = __regulatory_hint(wiphy, reg_request);
1593 /* This is required so that the orig_* parameters are saved */ 1593 /* This is required so that the orig_* parameters are saved */
1594 if (r == -EALREADY && wiphy && wiphy->strict_regulatory) 1594 if (r == -EALREADY && wiphy &&
1595 wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
1595 wiphy_update_regulatory(wiphy, reg_request->initiator); 1596 wiphy_update_regulatory(wiphy, reg_request->initiator);
1596out: 1597out:
1597 mutex_unlock(&reg_mutex); 1598 mutex_unlock(&reg_mutex);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index e2d344ff6745..227d57b8dc41 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -217,7 +217,7 @@ static bool is_mesh(struct cfg80211_bss *a,
217 a->len_information_elements); 217 a->len_information_elements);
218 if (!ie) 218 if (!ie)
219 return false; 219 return false;
220 if (ie[1] != IEEE80211_MESH_CONFIG_LEN) 220 if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
221 return false; 221 return false;
222 222
223 /* 223 /*
@@ -225,7 +225,8 @@ static bool is_mesh(struct cfg80211_bss *a,
225 * comparing since that may differ between stations taking 225 * comparing since that may differ between stations taking
226 * part in the same mesh. 226 * part in the same mesh.
227 */ 227 */
228 return memcmp(ie + 2, meshcfg, IEEE80211_MESH_CONFIG_LEN - 2) == 0; 228 return memcmp(ie + 2, meshcfg,
229 sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
229} 230}
230 231
231static int cmp_bss(struct cfg80211_bss *a, 232static int cmp_bss(struct cfg80211_bss *a,
@@ -399,7 +400,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
399 res->pub.information_elements, 400 res->pub.information_elements,
400 res->pub.len_information_elements); 401 res->pub.len_information_elements);
401 if (!meshid || !meshcfg || 402 if (!meshid || !meshcfg ||
402 meshcfg[1] != IEEE80211_MESH_CONFIG_LEN) { 403 meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) {
403 /* bogus mesh */ 404 /* bogus mesh */
404 kref_put(&res->ref, bss_release); 405 kref_put(&res->ref, bss_release);
405 return NULL; 406 return NULL;
@@ -865,7 +866,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
865 break; 866 break;
866 case WLAN_EID_MESH_CONFIG: 867 case WLAN_EID_MESH_CONFIG:
867 ismesh = true; 868 ismesh = true;
868 if (ie[1] != IEEE80211_MESH_CONFIG_LEN) 869 if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
869 break; 870 break;
870 buf = kmalloc(50, GFP_ATOMIC); 871 buf = kmalloc(50, GFP_ATOMIC);
871 if (!buf) 872 if (!buf)
@@ -873,35 +874,40 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
873 cfg = ie + 2; 874 cfg = ie + 2;
874 memset(&iwe, 0, sizeof(iwe)); 875 memset(&iwe, 0, sizeof(iwe));
875 iwe.cmd = IWEVCUSTOM; 876 iwe.cmd = IWEVCUSTOM;
876 sprintf(buf, "Mesh network (version %d)", cfg[0]); 877 sprintf(buf, "Mesh Network Path Selection Protocol ID: "
878 "0x%02X", cfg[0]);
877 iwe.u.data.length = strlen(buf); 879 iwe.u.data.length = strlen(buf);
878 current_ev = iwe_stream_add_point(info, current_ev, 880 current_ev = iwe_stream_add_point(info, current_ev,
879 end_buf, 881 end_buf,
880 &iwe, buf); 882 &iwe, buf);
881 sprintf(buf, "Path Selection Protocol ID: " 883 sprintf(buf, "Path Selection Metric ID: 0x%02X",
882 "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], 884 cfg[1]);
883 cfg[4]);
884 iwe.u.data.length = strlen(buf); 885 iwe.u.data.length = strlen(buf);
885 current_ev = iwe_stream_add_point(info, current_ev, 886 current_ev = iwe_stream_add_point(info, current_ev,
886 end_buf, 887 end_buf,
887 &iwe, buf); 888 &iwe, buf);
888 sprintf(buf, "Path Selection Metric ID: " 889 sprintf(buf, "Congestion Control Mode ID: 0x%02X",
889 "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], 890 cfg[2]);
890 cfg[8]);
891 iwe.u.data.length = strlen(buf); 891 iwe.u.data.length = strlen(buf);
892 current_ev = iwe_stream_add_point(info, current_ev, 892 current_ev = iwe_stream_add_point(info, current_ev,
893 end_buf, 893 end_buf,
894 &iwe, buf); 894 &iwe, buf);
895 sprintf(buf, "Congestion Control Mode ID: " 895 sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]);
896 "0x%02X%02X%02X%02X", cfg[9], cfg[10],
897 cfg[11], cfg[12]);
898 iwe.u.data.length = strlen(buf); 896 iwe.u.data.length = strlen(buf);
899 current_ev = iwe_stream_add_point(info, current_ev, 897 current_ev = iwe_stream_add_point(info, current_ev,
900 end_buf, 898 end_buf,
901 &iwe, buf); 899 &iwe, buf);
902 sprintf(buf, "Channel Precedence: " 900 sprintf(buf, "Authentication ID: 0x%02X", cfg[4]);
903 "0x%02X%02X%02X%02X", cfg[13], cfg[14], 901 iwe.u.data.length = strlen(buf);
904 cfg[15], cfg[16]); 902 current_ev = iwe_stream_add_point(info, current_ev,
903 end_buf,
904 &iwe, buf);
905 sprintf(buf, "Formation Info: 0x%02X", cfg[5]);
906 iwe.u.data.length = strlen(buf);
907 current_ev = iwe_stream_add_point(info, current_ev,
908 end_buf,
909 &iwe, buf);
910 sprintf(buf, "Capabilities: 0x%02X", cfg[6]);
905 iwe.u.data.length = strlen(buf); 911 iwe.u.data.length = strlen(buf);
906 current_ev = iwe_stream_add_point(info, current_ev, 912 current_ev = iwe_stream_add_point(info, current_ev,
907 end_buf, 913 end_buf,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 5aa39f7cf9b9..59361fdcb5d0 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -658,7 +658,14 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
658 !(rdev->wiphy.interface_modes & (1 << ntype))) 658 !(rdev->wiphy.interface_modes & (1 << ntype)))
659 return -EOPNOTSUPP; 659 return -EOPNOTSUPP;
660 660
661 /* if it's part of a bridge, reject changing type to station/ibss */
662 if (dev->br_port && (ntype == NL80211_IFTYPE_ADHOC ||
663 ntype == NL80211_IFTYPE_STATION))
664 return -EBUSY;
665
661 if (ntype != otype) { 666 if (ntype != otype) {
667 dev->ieee80211_ptr->use_4addr = false;
668
662 switch (otype) { 669 switch (otype) {
663 case NL80211_IFTYPE_ADHOC: 670 case NL80211_IFTYPE_ADHOC:
664 cfg80211_leave_ibss(rdev, dev, false); 671 cfg80211_leave_ibss(rdev, dev, false);
@@ -682,5 +689,34 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
682 689
683 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); 690 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
684 691
692 if (!err && params && params->use_4addr != -1)
693 dev->ieee80211_ptr->use_4addr = params->use_4addr;
694
695 if (!err) {
696 dev->priv_flags &= ~IFF_DONT_BRIDGE;
697 switch (ntype) {
698 case NL80211_IFTYPE_STATION:
699 if (dev->ieee80211_ptr->use_4addr)
700 break;
701 /* fall through */
702 case NL80211_IFTYPE_ADHOC:
703 dev->priv_flags |= IFF_DONT_BRIDGE;
704 break;
705 case NL80211_IFTYPE_AP:
706 case NL80211_IFTYPE_AP_VLAN:
707 case NL80211_IFTYPE_WDS:
708 case NL80211_IFTYPE_MESH_POINT:
709 /* bridging OK */
710 break;
711 case NL80211_IFTYPE_MONITOR:
712 /* monitor can't bridge anyway */
713 break;
714 case NL80211_IFTYPE_UNSPECIFIED:
715 case __NL80211_IFTYPE_AFTER_LAST:
716 /* not happening */
717 break;
718 }
719 }
720
685 return err; 721 return err;
686} 722}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 41abcbdc5fb9..29091ac9f989 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -437,6 +437,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
437{ 437{
438 struct wireless_dev *wdev = dev->ieee80211_ptr; 438 struct wireless_dev *wdev = dev->ieee80211_ptr;
439 int err, i; 439 int err, i;
440 bool rejoin = false;
440 441
441 if (!wdev->wext.keys) { 442 if (!wdev->wext.keys) {
442 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), 443 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
@@ -466,8 +467,24 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
466 467
467 if (remove) { 468 if (remove) {
468 err = 0; 469 err = 0;
469 if (wdev->current_bss) 470 if (wdev->current_bss) {
471 /*
472 * If removing the current TX key, we will need to
473 * join a new IBSS without the privacy bit clear.
474 */
475 if (idx == wdev->wext.default_key &&
476 wdev->iftype == NL80211_IFTYPE_ADHOC) {
477 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
478 rejoin = true;
479 }
470 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 480 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
481 }
482 /*
483 * Applications using wireless extensions expect to be
484 * able to delete keys that don't exist, so allow that.
485 */
486 if (err == -ENOENT)
487 err = 0;
471 if (!err) { 488 if (!err) {
472 if (!addr) { 489 if (!addr) {
473 wdev->wext.keys->params[idx].key_len = 0; 490 wdev->wext.keys->params[idx].key_len = 0;
@@ -478,12 +495,9 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
478 else if (idx == wdev->wext.default_mgmt_key) 495 else if (idx == wdev->wext.default_mgmt_key)
479 wdev->wext.default_mgmt_key = -1; 496 wdev->wext.default_mgmt_key = -1;
480 } 497 }
481 /* 498
482 * Applications using wireless extensions expect to be 499 if (!err && rejoin)
483 * able to delete keys that don't exist, so allow that. 500 err = cfg80211_ibss_wext_join(rdev, wdev);
484 */
485 if (err == -ENOENT)
486 return 0;
487 501
488 return err; 502 return err;
489 } 503 }
@@ -511,11 +525,25 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
511 if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 || 525 if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
512 params->cipher == WLAN_CIPHER_SUITE_WEP104) && 526 params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
513 (tx_key || (!addr && wdev->wext.default_key == -1))) { 527 (tx_key || (!addr && wdev->wext.default_key == -1))) {
514 if (wdev->current_bss) 528 if (wdev->current_bss) {
529 /*
530 * If we are getting a new TX key from not having
531 * had one before we need to join a new IBSS with
532 * the privacy bit set.
533 */
534 if (wdev->iftype == NL80211_IFTYPE_ADHOC &&
535 wdev->wext.default_key == -1) {
536 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
537 rejoin = true;
538 }
515 err = rdev->ops->set_default_key(&rdev->wiphy, 539 err = rdev->ops->set_default_key(&rdev->wiphy,
516 dev, idx); 540 dev, idx);
517 if (!err) 541 }
542 if (!err) {
518 wdev->wext.default_key = idx; 543 wdev->wext.default_key = idx;
544 if (rejoin)
545 err = cfg80211_ibss_wext_join(rdev, wdev);
546 }
519 return err; 547 return err;
520 } 548 }
521 549
@@ -539,10 +567,13 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
539{ 567{
540 int err; 568 int err;
541 569
570 /* devlist mutex needed for possible IBSS re-join */
571 mutex_lock(&rdev->devlist_mtx);
542 wdev_lock(dev->ieee80211_ptr); 572 wdev_lock(dev->ieee80211_ptr);
543 err = __cfg80211_set_encryption(rdev, dev, addr, remove, 573 err = __cfg80211_set_encryption(rdev, dev, addr, remove,
544 tx_key, idx, params); 574 tx_key, idx, params);
545 wdev_unlock(dev->ieee80211_ptr); 575 wdev_unlock(dev->ieee80211_ptr);
576 mutex_unlock(&rdev->devlist_mtx);
546 577
547 return err; 578 return err;
548} 579}