diff options
| author | David S. Miller <davem@davemloft.net> | 2009-11-24 18:01:29 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-11-24 18:01:29 -0500 |
| commit | 4ba3eb034fb6fd1990ccc5a6d71d5abcda37b905 (patch) | |
| tree | 0789ba36d96dba330416a1e6a9a68e891a78802a /net/wireless | |
| parent | 35700212b45ea9f98fa682cfc1bc1a67c9ccc34b (diff) | |
| parent | 18b6c9a2213d3b6e0212e8b225abf95f7564206a (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/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 | } |
