diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/Kconfig | 6 | ||||
-rw-r--r-- | net/wireless/core.c | 17 | ||||
-rw-r--r-- | net/wireless/core.h | 2 | ||||
-rw-r--r-- | net/wireless/ibss.c | 4 | ||||
-rw-r--r-- | net/wireless/mlme.c | 56 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 40 | ||||
-rw-r--r-- | net/wireless/reg.c | 13 | ||||
-rw-r--r-- | net/wireless/scan.c | 40 | ||||
-rw-r--r-- | net/wireless/util.c | 36 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 49 |
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 | ||
77 | config CFG80211_DEFAULT_PS_VALUE | ||
78 | int | ||
79 | default 1 if CFG80211_DEFAULT_PS | ||
80 | default 0 | ||
81 | depends on CFG80211 | ||
82 | |||
83 | config CFG80211_DEFAULT_PS | 77 | config 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); |
275 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); | 275 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); |
276 | int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | ||
277 | struct net_device *dev, bool nowext); | ||
276 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 278 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
277 | struct net_device *dev, bool nowext); | 279 | struct net_device *dev, bool nowext); |
278 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); | 280 | void __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 | ||
172 | static int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 172 | int __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 | } |
244 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 244 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
245 | 245 | ||
246 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | 246 | static 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 | |||
268 | void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr) | ||
269 | { | ||
270 | __cfg80211_auth_remove(dev->ieee80211_ptr, addr); | ||
271 | } | ||
272 | EXPORT_SYMBOL(__cfg80211_auth_canceled); | ||
273 | |||
274 | void 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 | ||
971 | static 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 | |||
971 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | 997 | static 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); |
1596 | out: | 1597 | out: |
1597 | mutex_unlock(®_mutex); | 1598 | mutex_unlock(®_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 | ||
231 | static int cmp_bss(struct cfg80211_bss *a, | 232 | static 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 | } |