diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/Kconfig | 7 | ||||
| -rw-r--r-- | net/core/dev.c | 4 | ||||
| -rw-r--r-- | net/core/skbuff.c | 3 | ||||
| -rw-r--r-- | net/ipv4/proc.c | 2 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 10 | ||||
| -rw-r--r-- | net/ipv6/datagram.c | 2 | ||||
| -rw-r--r-- | net/ipv6/proc.c | 1 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 27 | ||||
| -rw-r--r-- | net/mac80211/cfg.c | 103 | ||||
| -rw-r--r-- | net/mac80211/main.c | 12 | ||||
| -rw-r--r-- | net/mac80211/mlme.c | 9 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 55 | ||||
| -rw-r--r-- | net/mac80211/wep.c | 4 | ||||
| -rw-r--r-- | net/mac80211/wme.c | 3 | ||||
| -rw-r--r-- | net/rfkill/rfkill.c | 62 | ||||
| -rw-r--r-- | net/sched/sch_api.c | 57 | ||||
| -rw-r--r-- | net/sched/sch_generic.c | 8 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 275 |
18 files changed, 356 insertions, 288 deletions
diff --git a/net/Kconfig b/net/Kconfig index b98668751749..7612cc8c337c 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
| @@ -2,9 +2,7 @@ | |||
| 2 | # Network configuration | 2 | # Network configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | menu "Networking" | 5 | menuconfig NET |
| 6 | |||
| 7 | config NET | ||
| 8 | bool "Networking support" | 6 | bool "Networking support" |
| 9 | ---help--- | 7 | ---help--- |
| 10 | Unless you really know what you are doing, you should say Y here. | 8 | Unless you really know what you are doing, you should say Y here. |
| @@ -22,7 +20,6 @@ config NET | |||
| 22 | recommended to read the NET-HOWTO, available from | 20 | recommended to read the NET-HOWTO, available from |
| 23 | <http://www.tldp.org/docs.html#howto>. | 21 | <http://www.tldp.org/docs.html#howto>. |
| 24 | 22 | ||
| 25 | # Make sure that all config symbols are dependent on NET | ||
| 26 | if NET | 23 | if NET |
| 27 | 24 | ||
| 28 | menu "Networking options" | 25 | menu "Networking options" |
| @@ -252,5 +249,3 @@ source "net/rfkill/Kconfig" | |||
| 252 | source "net/9p/Kconfig" | 249 | source "net/9p/Kconfig" |
| 253 | 250 | ||
| 254 | endif # if NET | 251 | endif # if NET |
| 255 | endmenu # Networking | ||
| 256 | |||
diff --git a/net/core/dev.c b/net/core/dev.c index 8d13a9b9f1df..63d6bcddbf46 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2100,7 +2100,7 @@ static int ing_filter(struct sk_buff *skb) | |||
| 2100 | rxq = &dev->rx_queue; | 2100 | rxq = &dev->rx_queue; |
| 2101 | 2101 | ||
| 2102 | q = rxq->qdisc; | 2102 | q = rxq->qdisc; |
| 2103 | if (q) { | 2103 | if (q != &noop_qdisc) { |
| 2104 | spin_lock(qdisc_lock(q)); | 2104 | spin_lock(qdisc_lock(q)); |
| 2105 | result = qdisc_enqueue_root(skb, q); | 2105 | result = qdisc_enqueue_root(skb, q); |
| 2106 | spin_unlock(qdisc_lock(q)); | 2106 | spin_unlock(qdisc_lock(q)); |
| @@ -2113,7 +2113,7 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb, | |||
| 2113 | struct packet_type **pt_prev, | 2113 | struct packet_type **pt_prev, |
| 2114 | int *ret, struct net_device *orig_dev) | 2114 | int *ret, struct net_device *orig_dev) |
| 2115 | { | 2115 | { |
| 2116 | if (!skb->dev->rx_queue.qdisc) | 2116 | if (skb->dev->rx_queue.qdisc == &noop_qdisc) |
| 2117 | goto out; | 2117 | goto out; |
| 2118 | 2118 | ||
| 2119 | if (*pt_prev) { | 2119 | if (*pt_prev) { |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 4e0c92274189..84640172d65d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -485,6 +485,9 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) | |||
| 485 | C(head); | 485 | C(head); |
| 486 | C(data); | 486 | C(data); |
| 487 | C(truesize); | 487 | C(truesize); |
| 488 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) | ||
| 489 | C(do_not_encrypt); | ||
| 490 | #endif | ||
| 488 | atomic_set(&n->users, 1); | 491 | atomic_set(&n->users, 1); |
| 489 | 492 | ||
| 490 | atomic_inc(&(skb_shinfo(skb)->dataref)); | 493 | atomic_inc(&(skb_shinfo(skb)->dataref)); |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 834356ea99df..8f5a403f6f6b 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
| @@ -232,6 +232,8 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
| 232 | SNMP_MIB_ITEM("TCPDSACKIgnoredOld", LINUX_MIB_TCPDSACKIGNOREDOLD), | 232 | SNMP_MIB_ITEM("TCPDSACKIgnoredOld", LINUX_MIB_TCPDSACKIGNOREDOLD), |
| 233 | SNMP_MIB_ITEM("TCPDSACKIgnoredNoUndo", LINUX_MIB_TCPDSACKIGNOREDNOUNDO), | 233 | SNMP_MIB_ITEM("TCPDSACKIgnoredNoUndo", LINUX_MIB_TCPDSACKIGNOREDNOUNDO), |
| 234 | SNMP_MIB_ITEM("TCPSpuriousRTOs", LINUX_MIB_TCPSPURIOUSRTOS), | 234 | SNMP_MIB_ITEM("TCPSpuriousRTOs", LINUX_MIB_TCPSPURIOUSRTOS), |
| 235 | SNMP_MIB_ITEM("TCPMD5NotFound", LINUX_MIB_TCPMD5NOTFOUND), | ||
| 236 | SNMP_MIB_ITEM("TCPMD5Unexpected", LINUX_MIB_TCPMD5UNEXPECTED), | ||
| 235 | SNMP_MIB_SENTINEL | 237 | SNMP_MIB_SENTINEL |
| 236 | }; | 238 | }; |
| 237 | 239 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a2b06d0cc26b..b3875c0d83c7 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -1116,18 +1116,12 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) | |||
| 1116 | return 0; | 1116 | return 0; |
| 1117 | 1117 | ||
| 1118 | if (hash_expected && !hash_location) { | 1118 | if (hash_expected && !hash_location) { |
| 1119 | LIMIT_NETDEBUG(KERN_INFO "MD5 Hash expected but NOT found " | 1119 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); |
| 1120 | "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", | ||
| 1121 | NIPQUAD(iph->saddr), ntohs(th->source), | ||
| 1122 | NIPQUAD(iph->daddr), ntohs(th->dest)); | ||
| 1123 | return 1; | 1120 | return 1; |
| 1124 | } | 1121 | } |
| 1125 | 1122 | ||
| 1126 | if (!hash_expected && hash_location) { | 1123 | if (!hash_expected && hash_location) { |
| 1127 | LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found " | 1124 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); |
| 1128 | "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", | ||
| 1129 | NIPQUAD(iph->saddr), ntohs(th->source), | ||
| 1130 | NIPQUAD(iph->daddr), ntohs(th->dest)); | ||
| 1131 | return 1; | 1125 | return 1; |
| 1132 | } | 1126 | } |
| 1133 | 1127 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index f7b535dec860..410046a8cc91 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -732,7 +732,7 @@ int datagram_send_ctl(struct net *net, | |||
| 732 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", | 732 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", |
| 733 | cmsg->cmsg_type); | 733 | cmsg->cmsg_type); |
| 734 | err = -EINVAL; | 734 | err = -EINVAL; |
| 735 | break; | 735 | goto exit_f; |
| 736 | } | 736 | } |
| 737 | } | 737 | } |
| 738 | 738 | ||
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index f82f6074cf85..0179b66864f1 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
| @@ -286,7 +286,6 @@ proc_net_fail: | |||
| 286 | 286 | ||
| 287 | void ipv6_misc_proc_exit(void) | 287 | void ipv6_misc_proc_exit(void) |
| 288 | { | 288 | { |
| 289 | proc_net_remove(&init_net, "sockstat6"); | ||
| 290 | proc_net_remove(&init_net, "dev_snmp6"); | 289 | proc_net_remove(&init_net, "dev_snmp6"); |
| 291 | proc_net_remove(&init_net, "snmp6"); | 290 | proc_net_remove(&init_net, "snmp6"); |
| 292 | unregister_pernet_subsys(&ipv6_proc_ops); | 291 | unregister_pernet_subsys(&ipv6_proc_ops); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index cff778b23a7f..1db45216b232 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -849,28 +849,17 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
| 849 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); | 849 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); |
| 850 | hash_location = tcp_parse_md5sig_option(th); | 850 | hash_location = tcp_parse_md5sig_option(th); |
| 851 | 851 | ||
| 852 | /* do we have a hash as expected? */ | 852 | /* We've parsed the options - do we have a hash? */ |
| 853 | if (!hash_expected) { | 853 | if (!hash_expected && !hash_location) |
| 854 | if (!hash_location) | 854 | return 0; |
| 855 | return 0; | 855 | |
| 856 | if (net_ratelimit()) { | 856 | if (hash_expected && !hash_location) { |
| 857 | printk(KERN_INFO "MD5 Hash NOT expected but found " | 857 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); |
| 858 | "(" NIP6_FMT ", %u)->" | ||
| 859 | "(" NIP6_FMT ", %u)\n", | ||
| 860 | NIP6(ip6h->saddr), ntohs(th->source), | ||
| 861 | NIP6(ip6h->daddr), ntohs(th->dest)); | ||
| 862 | } | ||
| 863 | return 1; | 858 | return 1; |
| 864 | } | 859 | } |
| 865 | 860 | ||
| 866 | if (!hash_location) { | 861 | if (!hash_expected && hash_location) { |
| 867 | if (net_ratelimit()) { | 862 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); |
| 868 | printk(KERN_INFO "MD5 Hash expected but NOT found " | ||
| 869 | "(" NIP6_FMT ", %u)->" | ||
| 870 | "(" NIP6_FMT ", %u)\n", | ||
| 871 | NIP6(ip6h->saddr), ntohs(th->source), | ||
| 872 | NIP6(ip6h->daddr), ntohs(th->dest)); | ||
| 873 | } | ||
| 874 | return 1; | 863 | return 1; |
| 875 | } | 864 | } |
| 876 | 865 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8e7ba0e62cf5..297c257864c7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -81,6 +81,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
| 81 | enum nl80211_iftype type, u32 *flags, | 81 | enum nl80211_iftype type, u32 *flags, |
| 82 | struct vif_params *params) | 82 | struct vif_params *params) |
| 83 | { | 83 | { |
| 84 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
| 84 | struct net_device *dev; | 85 | struct net_device *dev; |
| 85 | enum ieee80211_if_types itype; | 86 | enum ieee80211_if_types itype; |
| 86 | struct ieee80211_sub_if_data *sdata; | 87 | struct ieee80211_sub_if_data *sdata; |
| @@ -95,6 +96,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
| 95 | if (itype == IEEE80211_IF_TYPE_INVALID) | 96 | if (itype == IEEE80211_IF_TYPE_INVALID) |
| 96 | return -EINVAL; | 97 | return -EINVAL; |
| 97 | 98 | ||
| 99 | if (dev == local->mdev) | ||
| 100 | return -EOPNOTSUPP; | ||
| 101 | |||
| 98 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 102 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 99 | 103 | ||
| 100 | ret = ieee80211_if_change_type(sdata, itype); | 104 | ret = ieee80211_if_change_type(sdata, itype); |
| @@ -117,12 +121,16 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
| 117 | u8 key_idx, u8 *mac_addr, | 121 | u8 key_idx, u8 *mac_addr, |
| 118 | struct key_params *params) | 122 | struct key_params *params) |
| 119 | { | 123 | { |
| 124 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
| 120 | struct ieee80211_sub_if_data *sdata; | 125 | struct ieee80211_sub_if_data *sdata; |
| 121 | struct sta_info *sta = NULL; | 126 | struct sta_info *sta = NULL; |
| 122 | enum ieee80211_key_alg alg; | 127 | enum ieee80211_key_alg alg; |
| 123 | struct ieee80211_key *key; | 128 | struct ieee80211_key *key; |
| 124 | int err; | 129 | int err; |
| 125 | 130 | ||
| 131 | if (dev == local->mdev) | ||
| 132 | return -EOPNOTSUPP; | ||
| 133 | |||
| 126 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 134 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 127 | 135 | ||
| 128 | switch (params->cipher) { | 136 | switch (params->cipher) { |
| @@ -167,10 +175,14 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
| 167 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 175 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
| 168 | u8 key_idx, u8 *mac_addr) | 176 | u8 key_idx, u8 *mac_addr) |
| 169 | { | 177 | { |
| 178 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
| 170 | struct ieee80211_sub_if_data *sdata; | 179 | struct ieee80211_sub_if_data *sdata; |
| 171 | struct sta_info *sta; | 180 | struct sta_info *sta; |
| 172 | int ret; | 181 | int ret; |
| 173 | 182 | ||
| 183 | if (dev == local->mdev) | ||
| 184 | return -EOPNOTSUPP; | ||
| 185 | |||
| 174 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 186 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 175 | 187 | ||
| 176 | rcu_read_lock(); | 188 | rcu_read_lock(); |
| @@ -211,7 +223,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
| 211 | void (*callback)(void *cookie, | 223 | void (*callback)(void *cookie, |
| 212 | struct key_params *params)) | 224 | struct key_params *params)) |
| 213 | { | 225 | { |
| 214 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 226 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 227 | struct ieee80211_sub_if_data *sdata; | ||
| 215 | struct sta_info *sta = NULL; | 228 | struct sta_info *sta = NULL; |
| 216 | u8 seq[6] = {0}; | 229 | u8 seq[6] = {0}; |
| 217 | struct key_params params; | 230 | struct key_params params; |
| @@ -220,6 +233,11 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
| 220 | u16 iv16; | 233 | u16 iv16; |
| 221 | int err = -ENOENT; | 234 | int err = -ENOENT; |
| 222 | 235 | ||
| 236 | if (dev == local->mdev) | ||
| 237 | return -EOPNOTSUPP; | ||
| 238 | |||
| 239 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 240 | |||
| 223 | rcu_read_lock(); | 241 | rcu_read_lock(); |
| 224 | 242 | ||
| 225 | if (mac_addr) { | 243 | if (mac_addr) { |
| @@ -293,8 +311,12 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
| 293 | struct net_device *dev, | 311 | struct net_device *dev, |
| 294 | u8 key_idx) | 312 | u8 key_idx) |
| 295 | { | 313 | { |
| 314 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
| 296 | struct ieee80211_sub_if_data *sdata; | 315 | struct ieee80211_sub_if_data *sdata; |
| 297 | 316 | ||
| 317 | if (dev == local->mdev) | ||
| 318 | return -EOPNOTSUPP; | ||
| 319 | |||
| 298 | rcu_read_lock(); | 320 | rcu_read_lock(); |
| 299 | 321 | ||
| 300 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 322 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| @@ -475,9 +497,15 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 475 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 497 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
| 476 | struct beacon_parameters *params) | 498 | struct beacon_parameters *params) |
| 477 | { | 499 | { |
| 478 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 500 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 501 | struct ieee80211_sub_if_data *sdata; | ||
| 479 | struct beacon_data *old; | 502 | struct beacon_data *old; |
| 480 | 503 | ||
| 504 | if (dev == local->mdev) | ||
| 505 | return -EOPNOTSUPP; | ||
| 506 | |||
| 507 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 508 | |||
| 481 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 509 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) |
| 482 | return -EINVAL; | 510 | return -EINVAL; |
| 483 | 511 | ||
| @@ -492,9 +520,15 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
| 492 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | 520 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, |
| 493 | struct beacon_parameters *params) | 521 | struct beacon_parameters *params) |
| 494 | { | 522 | { |
| 495 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 523 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 524 | struct ieee80211_sub_if_data *sdata; | ||
| 496 | struct beacon_data *old; | 525 | struct beacon_data *old; |
| 497 | 526 | ||
| 527 | if (dev == local->mdev) | ||
| 528 | return -EOPNOTSUPP; | ||
| 529 | |||
| 530 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 531 | |||
| 498 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 532 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) |
| 499 | return -EINVAL; | 533 | return -EINVAL; |
| 500 | 534 | ||
| @@ -508,9 +542,15 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
| 508 | 542 | ||
| 509 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | 543 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) |
| 510 | { | 544 | { |
| 511 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 545 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 546 | struct ieee80211_sub_if_data *sdata; | ||
| 512 | struct beacon_data *old; | 547 | struct beacon_data *old; |
| 513 | 548 | ||
| 549 | if (dev == local->mdev) | ||
| 550 | return -EOPNOTSUPP; | ||
| 551 | |||
| 552 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 553 | |||
| 514 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 554 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) |
| 515 | return -EINVAL; | 555 | return -EINVAL; |
| 516 | 556 | ||
| @@ -646,11 +686,14 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
| 646 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | 686 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, |
| 647 | u8 *mac, struct station_parameters *params) | 687 | u8 *mac, struct station_parameters *params) |
| 648 | { | 688 | { |
| 649 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 689 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 650 | struct sta_info *sta; | 690 | struct sta_info *sta; |
| 651 | struct ieee80211_sub_if_data *sdata; | 691 | struct ieee80211_sub_if_data *sdata; |
| 652 | int err; | 692 | int err; |
| 653 | 693 | ||
| 694 | if (dev == local->mdev || params->vlan == local->mdev) | ||
| 695 | return -EOPNOTSUPP; | ||
| 696 | |||
| 654 | /* Prevent a race with changing the rate control algorithm */ | 697 | /* Prevent a race with changing the rate control algorithm */ |
| 655 | if (!netif_running(dev)) | 698 | if (!netif_running(dev)) |
| 656 | return -ENETDOWN; | 699 | return -ENETDOWN; |
| @@ -701,10 +744,15 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 701 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 744 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, |
| 702 | u8 *mac) | 745 | u8 *mac) |
| 703 | { | 746 | { |
| 704 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 747 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 705 | struct ieee80211_local *local = sdata->local; | 748 | struct ieee80211_sub_if_data *sdata; |
| 706 | struct sta_info *sta; | 749 | struct sta_info *sta; |
| 707 | 750 | ||
| 751 | if (dev == local->mdev) | ||
| 752 | return -EOPNOTSUPP; | ||
| 753 | |||
| 754 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 755 | |||
| 708 | if (mac) { | 756 | if (mac) { |
| 709 | rcu_read_lock(); | 757 | rcu_read_lock(); |
| 710 | 758 | ||
| @@ -730,10 +778,13 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
| 730 | u8 *mac, | 778 | u8 *mac, |
| 731 | struct station_parameters *params) | 779 | struct station_parameters *params) |
| 732 | { | 780 | { |
| 733 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 781 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 734 | struct sta_info *sta; | 782 | struct sta_info *sta; |
| 735 | struct ieee80211_sub_if_data *vlansdata; | 783 | struct ieee80211_sub_if_data *vlansdata; |
| 736 | 784 | ||
| 785 | if (dev == local->mdev || params->vlan == local->mdev) | ||
| 786 | return -EOPNOTSUPP; | ||
| 787 | |||
| 737 | rcu_read_lock(); | 788 | rcu_read_lock(); |
| 738 | 789 | ||
| 739 | /* XXX: get sta belonging to dev */ | 790 | /* XXX: get sta belonging to dev */ |
| @@ -752,7 +803,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
| 752 | return -EINVAL; | 803 | return -EINVAL; |
| 753 | } | 804 | } |
| 754 | 805 | ||
| 755 | sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 806 | sta->sdata = vlansdata; |
| 756 | ieee80211_send_layer2_update(sta); | 807 | ieee80211_send_layer2_update(sta); |
| 757 | } | 808 | } |
| 758 | 809 | ||
| @@ -767,15 +818,20 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
| 767 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | 818 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, |
| 768 | u8 *dst, u8 *next_hop) | 819 | u8 *dst, u8 *next_hop) |
| 769 | { | 820 | { |
| 770 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 821 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 771 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 822 | struct ieee80211_sub_if_data *sdata; |
| 772 | struct mesh_path *mpath; | 823 | struct mesh_path *mpath; |
| 773 | struct sta_info *sta; | 824 | struct sta_info *sta; |
| 774 | int err; | 825 | int err; |
| 775 | 826 | ||
| 827 | if (dev == local->mdev) | ||
| 828 | return -EOPNOTSUPP; | ||
| 829 | |||
| 776 | if (!netif_running(dev)) | 830 | if (!netif_running(dev)) |
| 777 | return -ENETDOWN; | 831 | return -ENETDOWN; |
| 778 | 832 | ||
| 833 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 834 | |||
| 779 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 835 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) |
| 780 | return -ENOTSUPP; | 836 | return -ENOTSUPP; |
| 781 | 837 | ||
| @@ -817,14 +873,19 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
| 817 | struct net_device *dev, | 873 | struct net_device *dev, |
| 818 | u8 *dst, u8 *next_hop) | 874 | u8 *dst, u8 *next_hop) |
| 819 | { | 875 | { |
| 820 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 876 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 821 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 877 | struct ieee80211_sub_if_data *sdata; |
| 822 | struct mesh_path *mpath; | 878 | struct mesh_path *mpath; |
| 823 | struct sta_info *sta; | 879 | struct sta_info *sta; |
| 824 | 880 | ||
| 881 | if (dev == local->mdev) | ||
| 882 | return -EOPNOTSUPP; | ||
| 883 | |||
| 825 | if (!netif_running(dev)) | 884 | if (!netif_running(dev)) |
| 826 | return -ENETDOWN; | 885 | return -ENETDOWN; |
| 827 | 886 | ||
| 887 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 888 | |||
| 828 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 889 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) |
| 829 | return -ENOTSUPP; | 890 | return -ENOTSUPP; |
| 830 | 891 | ||
| @@ -891,9 +952,15 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 891 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) | 952 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) |
| 892 | 953 | ||
| 893 | { | 954 | { |
| 894 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 955 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 956 | struct ieee80211_sub_if_data *sdata; | ||
| 895 | struct mesh_path *mpath; | 957 | struct mesh_path *mpath; |
| 896 | 958 | ||
| 959 | if (dev == local->mdev) | ||
| 960 | return -EOPNOTSUPP; | ||
| 961 | |||
| 962 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 963 | |||
| 897 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 964 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) |
| 898 | return -ENOTSUPP; | 965 | return -ENOTSUPP; |
| 899 | 966 | ||
| @@ -913,9 +980,15 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 913 | int idx, u8 *dst, u8 *next_hop, | 980 | int idx, u8 *dst, u8 *next_hop, |
| 914 | struct mpath_info *pinfo) | 981 | struct mpath_info *pinfo) |
| 915 | { | 982 | { |
| 916 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 983 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 984 | struct ieee80211_sub_if_data *sdata; | ||
| 917 | struct mesh_path *mpath; | 985 | struct mesh_path *mpath; |
| 918 | 986 | ||
| 987 | if (dev == local->mdev) | ||
| 988 | return -EOPNOTSUPP; | ||
| 989 | |||
| 990 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 991 | |||
| 919 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 992 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) |
| 920 | return -ENOTSUPP; | 993 | return -ENOTSUPP; |
| 921 | 994 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f1a83d450ea0..a4c5b90de769 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -1233,18 +1233,12 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
| 1233 | /* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to | 1233 | /* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to |
| 1234 | * make a prepared TX frame (one that has been given to hw) to look like brand | 1234 | * make a prepared TX frame (one that has been given to hw) to look like brand |
| 1235 | * new IEEE 802.11 frame that is ready to go through TX processing again. | 1235 | * new IEEE 802.11 frame that is ready to go through TX processing again. |
| 1236 | * Also, tx_packet_data in cb is restored from tx_control. */ | 1236 | */ |
| 1237 | static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | 1237 | static void ieee80211_remove_tx_extra(struct ieee80211_local *local, |
| 1238 | struct ieee80211_key *key, | 1238 | struct ieee80211_key *key, |
| 1239 | struct sk_buff *skb) | 1239 | struct sk_buff *skb) |
| 1240 | { | 1240 | { |
| 1241 | int hdrlen, iv_len, mic_len; | 1241 | int hdrlen, iv_len, mic_len; |
| 1242 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 1243 | |||
| 1244 | info->flags &= IEEE80211_TX_CTL_REQ_TX_STATUS | | ||
| 1245 | IEEE80211_TX_CTL_DO_NOT_ENCRYPT | | ||
| 1246 | IEEE80211_TX_CTL_REQUEUE | | ||
| 1247 | IEEE80211_TX_CTL_EAPOL_FRAME; | ||
| 1248 | 1242 | ||
| 1249 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1243 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
| 1250 | 1244 | ||
| @@ -1731,8 +1725,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 1731 | result = ieee80211_wep_init(local); | 1725 | result = ieee80211_wep_init(local); |
| 1732 | 1726 | ||
| 1733 | if (result < 0) { | 1727 | if (result < 0) { |
| 1734 | printk(KERN_DEBUG "%s: Failed to initialize wep\n", | 1728 | printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", |
| 1735 | wiphy_name(local->hw.wiphy)); | 1729 | wiphy_name(local->hw.wiphy), result); |
| 1736 | goto fail_wep; | 1730 | goto fail_wep; |
| 1737 | } | 1731 | } |
| 1738 | 1732 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d7c371e36bf0..acb04133a95d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -606,7 +606,6 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, | |||
| 606 | int encrypt) | 606 | int encrypt) |
| 607 | { | 607 | { |
| 608 | struct ieee80211_sub_if_data *sdata; | 608 | struct ieee80211_sub_if_data *sdata; |
| 609 | struct ieee80211_tx_info *info; | ||
| 610 | 609 | ||
| 611 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 610 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 612 | skb->dev = sdata->local->mdev; | 611 | skb->dev = sdata->local->mdev; |
| @@ -614,11 +613,8 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, | |||
| 614 | skb_set_network_header(skb, 0); | 613 | skb_set_network_header(skb, 0); |
| 615 | skb_set_transport_header(skb, 0); | 614 | skb_set_transport_header(skb, 0); |
| 616 | 615 | ||
| 617 | info = IEEE80211_SKB_CB(skb); | 616 | skb->iif = sdata->dev->ifindex; |
| 618 | memset(info, 0, sizeof(struct ieee80211_tx_info)); | 617 | skb->do_not_encrypt = !encrypt; |
| 619 | info->control.ifindex = sdata->dev->ifindex; | ||
| 620 | if (!encrypt) | ||
| 621 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
| 622 | 618 | ||
| 623 | dev_queue_xmit(skb); | 619 | dev_queue_xmit(skb); |
| 624 | } | 620 | } |
| @@ -3303,6 +3299,7 @@ void ieee80211_start_mesh(struct net_device *dev) | |||
| 3303 | ifsta = &sdata->u.sta; | 3299 | ifsta = &sdata->u.sta; |
| 3304 | ifsta->state = IEEE80211_MESH_UP; | 3300 | ifsta->state = IEEE80211_MESH_UP; |
| 3305 | ieee80211_sta_timer((unsigned long)sdata); | 3301 | ieee80211_sta_timer((unsigned long)sdata); |
| 3302 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
| 3306 | } | 3303 | } |
| 3307 | #endif | 3304 | #endif |
| 3308 | 3305 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0fbadd8b983c..69019e943873 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -305,7 +305,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
| 305 | rcu_read_unlock(); | 305 | rcu_read_unlock(); |
| 306 | 306 | ||
| 307 | local->total_ps_buffered = total; | 307 | local->total_ps_buffered = total; |
| 308 | #ifdef MAC80211_VERBOSE_PS_DEBUG | 308 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
| 309 | printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", | 309 | printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", |
| 310 | wiphy_name(local->hw.wiphy), purged); | 310 | wiphy_name(local->hw.wiphy), purged); |
| 311 | #endif | 311 | #endif |
| @@ -342,7 +342,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
| 342 | purge_old_ps_buffers(tx->local); | 342 | purge_old_ps_buffers(tx->local); |
| 343 | if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= | 343 | if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= |
| 344 | AP_MAX_BC_BUFFER) { | 344 | AP_MAX_BC_BUFFER) { |
| 345 | #ifdef MAC80211_VERBOSE_PS_DEBUG | 345 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
| 346 | if (net_ratelimit()) { | 346 | if (net_ratelimit()) { |
| 347 | printk(KERN_DEBUG "%s: BC TX buffer full - " | 347 | printk(KERN_DEBUG "%s: BC TX buffer full - " |
| 348 | "dropping the oldest frame\n", | 348 | "dropping the oldest frame\n", |
| @@ -389,7 +389,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
| 389 | purge_old_ps_buffers(tx->local); | 389 | purge_old_ps_buffers(tx->local); |
| 390 | if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) { | 390 | if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) { |
| 391 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); | 391 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); |
| 392 | #ifdef MAC80211_VERBOSE_PS_DEBUG | 392 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
| 393 | if (net_ratelimit()) { | 393 | if (net_ratelimit()) { |
| 394 | printk(KERN_DEBUG "%s: STA %s TX " | 394 | printk(KERN_DEBUG "%s: STA %s TX " |
| 395 | "buffer full - dropping oldest frame\n", | 395 | "buffer full - dropping oldest frame\n", |
| @@ -439,14 +439,14 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
| 439 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 439 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
| 440 | u16 fc = tx->fc; | 440 | u16 fc = tx->fc; |
| 441 | 441 | ||
| 442 | if (unlikely(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) | 442 | if (unlikely(tx->skb->do_not_encrypt)) |
| 443 | tx->key = NULL; | 443 | tx->key = NULL; |
| 444 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 444 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
| 445 | tx->key = key; | 445 | tx->key = key; |
| 446 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 446 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
| 447 | tx->key = key; | 447 | tx->key = key; |
| 448 | else if (tx->sdata->drop_unencrypted && | 448 | else if (tx->sdata->drop_unencrypted && |
| 449 | !(info->flags & IEEE80211_TX_CTL_EAPOL_FRAME) && | 449 | (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) && |
| 450 | !(info->flags & IEEE80211_TX_CTL_INJECTED)) { | 450 | !(info->flags & IEEE80211_TX_CTL_INJECTED)) { |
| 451 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 451 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
| 452 | return TX_DROP; | 452 | return TX_DROP; |
| @@ -476,7 +476,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
| 476 | } | 476 | } |
| 477 | 477 | ||
| 478 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 478 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
| 479 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | 479 | tx->skb->do_not_encrypt = 1; |
| 480 | 480 | ||
| 481 | return TX_CONTINUE; | 481 | return TX_CONTINUE; |
| 482 | } | 482 | } |
| @@ -732,6 +732,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
| 732 | memcpy(skb_put(frag, copylen), pos, copylen); | 732 | memcpy(skb_put(frag, copylen), pos, copylen); |
| 733 | memcpy(frag->cb, first->cb, sizeof(frag->cb)); | 733 | memcpy(frag->cb, first->cb, sizeof(frag->cb)); |
| 734 | skb_copy_queue_mapping(frag, first); | 734 | skb_copy_queue_mapping(frag, first); |
| 735 | frag->do_not_encrypt = first->do_not_encrypt; | ||
| 735 | 736 | ||
| 736 | pos += copylen; | 737 | pos += copylen; |
| 737 | left -= copylen; | 738 | left -= copylen; |
| @@ -852,7 +853,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
| 852 | 853 | ||
| 853 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 854 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
| 854 | 855 | ||
| 855 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | 856 | skb->do_not_encrypt = 1; |
| 856 | info->flags |= IEEE80211_TX_CTL_INJECTED; | 857 | info->flags |= IEEE80211_TX_CTL_INJECTED; |
| 857 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 858 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
| 858 | 859 | ||
| @@ -925,8 +926,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
| 925 | skb_trim(skb, skb->len - FCS_LEN); | 926 | skb_trim(skb, skb->len - FCS_LEN); |
| 926 | } | 927 | } |
| 927 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | 928 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) |
| 928 | info->flags &= | 929 | tx->skb->do_not_encrypt = 0; |
| 929 | ~IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
| 930 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | 930 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) |
| 931 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 931 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
| 932 | break; | 932 | break; |
| @@ -1042,10 +1042,9 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
| 1042 | struct sk_buff *skb, | 1042 | struct sk_buff *skb, |
| 1043 | struct net_device *mdev) | 1043 | struct net_device *mdev) |
| 1044 | { | 1044 | { |
| 1045 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 1046 | struct net_device *dev; | 1045 | struct net_device *dev; |
| 1047 | 1046 | ||
| 1048 | dev = dev_get_by_index(&init_net, info->control.ifindex); | 1047 | dev = dev_get_by_index(&init_net, skb->iif); |
| 1049 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { | 1048 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { |
| 1050 | dev_put(dev); | 1049 | dev_put(dev); |
| 1051 | dev = NULL; | 1050 | dev = NULL; |
| @@ -1306,8 +1305,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
| 1306 | bool may_encrypt; | 1305 | bool may_encrypt; |
| 1307 | int ret; | 1306 | int ret; |
| 1308 | 1307 | ||
| 1309 | if (info->control.ifindex) | 1308 | if (skb->iif) |
| 1310 | odev = dev_get_by_index(&init_net, info->control.ifindex); | 1309 | odev = dev_get_by_index(&init_net, skb->iif); |
| 1311 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { | 1310 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { |
| 1312 | dev_put(odev); | 1311 | dev_put(odev); |
| 1313 | odev = NULL; | 1312 | odev = NULL; |
| @@ -1321,9 +1320,13 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
| 1321 | return 0; | 1320 | return 0; |
| 1322 | } | 1321 | } |
| 1323 | 1322 | ||
| 1323 | memset(info, 0, sizeof(*info)); | ||
| 1324 | |||
| 1325 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
| 1326 | |||
| 1324 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); | 1327 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); |
| 1325 | 1328 | ||
| 1326 | may_encrypt = !(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT); | 1329 | may_encrypt = !skb->do_not_encrypt; |
| 1327 | 1330 | ||
| 1328 | headroom = osdata->local->tx_headroom; | 1331 | headroom = osdata->local->tx_headroom; |
| 1329 | if (may_encrypt) | 1332 | if (may_encrypt) |
| @@ -1348,7 +1351,6 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
| 1348 | struct net_device *dev) | 1351 | struct net_device *dev) |
| 1349 | { | 1352 | { |
| 1350 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1353 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
| 1351 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 1352 | struct ieee80211_radiotap_header *prthdr = | 1354 | struct ieee80211_radiotap_header *prthdr = |
| 1353 | (struct ieee80211_radiotap_header *)skb->data; | 1355 | (struct ieee80211_radiotap_header *)skb->data; |
| 1354 | u16 len_rthdr; | 1356 | u16 len_rthdr; |
| @@ -1371,11 +1373,11 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
| 1371 | skb->dev = local->mdev; | 1373 | skb->dev = local->mdev; |
| 1372 | 1374 | ||
| 1373 | /* needed because we set skb device to master */ | 1375 | /* needed because we set skb device to master */ |
| 1374 | info->control.ifindex = dev->ifindex; | 1376 | skb->iif = dev->ifindex; |
| 1375 | 1377 | ||
| 1376 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | 1378 | /* sometimes we do encrypt injected frames, will be fixed |
| 1377 | /* Interfaces should always request a status report */ | 1379 | * up in radiotap parser if not wanted */ |
| 1378 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1380 | skb->do_not_encrypt = 0; |
| 1379 | 1381 | ||
| 1380 | /* | 1382 | /* |
| 1381 | * fix up the pointers accounting for the radiotap | 1383 | * fix up the pointers accounting for the radiotap |
| @@ -1419,7 +1421,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1419 | struct net_device *dev) | 1421 | struct net_device *dev) |
| 1420 | { | 1422 | { |
| 1421 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1423 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
| 1422 | struct ieee80211_tx_info *info; | ||
| 1423 | struct ieee80211_sub_if_data *sdata; | 1424 | struct ieee80211_sub_if_data *sdata; |
| 1424 | int ret = 1, head_need; | 1425 | int ret = 1, head_need; |
| 1425 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1426 | u16 ethertype, hdrlen, meshhdrlen = 0; |
| @@ -1645,14 +1646,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1645 | nh_pos += hdrlen; | 1646 | nh_pos += hdrlen; |
| 1646 | h_pos += hdrlen; | 1647 | h_pos += hdrlen; |
| 1647 | 1648 | ||
| 1648 | info = IEEE80211_SKB_CB(skb); | 1649 | skb->iif = dev->ifindex; |
| 1649 | memset(info, 0, sizeof(*info)); | ||
| 1650 | info->control.ifindex = dev->ifindex; | ||
| 1651 | if (ethertype == ETH_P_PAE) | ||
| 1652 | info->flags |= IEEE80211_TX_CTL_EAPOL_FRAME; | ||
| 1653 | |||
| 1654 | /* Interfaces should always request a status report */ | ||
| 1655 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
| 1656 | 1650 | ||
| 1657 | skb->dev = local->mdev; | 1651 | skb->dev = local->mdev; |
| 1658 | dev->stats.tx_packets++; | 1652 | dev->stats.tx_packets++; |
| @@ -1922,6 +1916,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
| 1922 | 1916 | ||
| 1923 | info = IEEE80211_SKB_CB(skb); | 1917 | info = IEEE80211_SKB_CB(skb); |
| 1924 | 1918 | ||
| 1919 | skb->do_not_encrypt = 1; | ||
| 1920 | |||
| 1925 | info->band = band; | 1921 | info->band = band; |
| 1926 | rate_control_get_rate(local->mdev, sband, skb, &rsel); | 1922 | rate_control_get_rate(local->mdev, sband, skb, &rsel); |
| 1927 | 1923 | ||
| @@ -1931,7 +1927,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
| 1931 | "no rate found\n", | 1927 | "no rate found\n", |
| 1932 | wiphy_name(local->hw.wiphy)); | 1928 | wiphy_name(local->hw.wiphy)); |
| 1933 | } | 1929 | } |
| 1934 | dev_kfree_skb(skb); | 1930 | dev_kfree_skb_any(skb); |
| 1935 | skb = NULL; | 1931 | skb = NULL; |
| 1936 | goto out; | 1932 | goto out; |
| 1937 | } | 1933 | } |
| @@ -1940,7 +1936,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
| 1940 | info->tx_rate_idx = rsel.rate_idx; | 1936 | info->tx_rate_idx = rsel.rate_idx; |
| 1941 | 1937 | ||
| 1942 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 1938 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
| 1943 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
| 1944 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1939 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
| 1945 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | 1940 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; |
| 1946 | if (sdata->bss_conf.use_short_preamble && | 1941 | if (sdata->bss_conf.use_short_preamble && |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 872d2fcd1a5b..5c2bf0a3d4db 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
| @@ -31,13 +31,13 @@ int ieee80211_wep_init(struct ieee80211_local *local) | |||
| 31 | local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, | 31 | local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, |
| 32 | CRYPTO_ALG_ASYNC); | 32 | CRYPTO_ALG_ASYNC); |
| 33 | if (IS_ERR(local->wep_tx_tfm)) | 33 | if (IS_ERR(local->wep_tx_tfm)) |
| 34 | return -ENOMEM; | 34 | return PTR_ERR(local->wep_tx_tfm); |
| 35 | 35 | ||
| 36 | local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, | 36 | local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, |
| 37 | CRYPTO_ALG_ASYNC); | 37 | CRYPTO_ALG_ASYNC); |
| 38 | if (IS_ERR(local->wep_rx_tfm)) { | 38 | if (IS_ERR(local->wep_rx_tfm)) { |
| 39 | crypto_free_blkcipher(local->wep_tx_tfm); | 39 | crypto_free_blkcipher(local->wep_tx_tfm); |
| 40 | return -ENOMEM; | 40 | return PTR_ERR(local->wep_rx_tfm); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | return 0; | 43 | return 0; |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 07edda0b8a5c..28437f0001db 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
| @@ -188,6 +188,9 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, | |||
| 188 | { | 188 | { |
| 189 | int i; | 189 | int i; |
| 190 | 190 | ||
| 191 | /* XXX: currently broken due to cb/requeue use */ | ||
| 192 | return -EPERM; | ||
| 193 | |||
| 191 | /* prepare the filter and save it for the SW queue | 194 | /* prepare the filter and save it for the SW queue |
| 192 | * matching the received HW queue */ | 195 | * matching the received HW queue */ |
| 193 | 196 | ||
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 7a560b785097..c6f2f388cb72 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
| @@ -130,7 +130,6 @@ static void update_rfkill_state(struct rfkill *rfkill) | |||
| 130 | 130 | ||
| 131 | /** | 131 | /** |
| 132 | * rfkill_toggle_radio - wrapper for toggle_radio hook | 132 | * rfkill_toggle_radio - wrapper for toggle_radio hook |
| 133 | * | ||
| 134 | * @rfkill: the rfkill struct to use | 133 | * @rfkill: the rfkill struct to use |
| 135 | * @force: calls toggle_radio even if cache says it is not needed, | 134 | * @force: calls toggle_radio even if cache says it is not needed, |
| 136 | * and also makes sure notifications of the state will be | 135 | * and also makes sure notifications of the state will be |
| @@ -141,8 +140,8 @@ static void update_rfkill_state(struct rfkill *rfkill) | |||
| 141 | * calls and handling all the red tape such as issuing notifications | 140 | * calls and handling all the red tape such as issuing notifications |
| 142 | * if the call is successful. | 141 | * if the call is successful. |
| 143 | * | 142 | * |
| 144 | * Note that @force cannot override a (possibly cached) state of | 143 | * Note that the @force parameter cannot override a (possibly cached) |
| 145 | * RFKILL_STATE_HARD_BLOCKED. Any device making use of | 144 | * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of |
| 146 | * RFKILL_STATE_HARD_BLOCKED implements either get_state() or | 145 | * RFKILL_STATE_HARD_BLOCKED implements either get_state() or |
| 147 | * rfkill_force_state(), so the cache either is bypassed or valid. | 146 | * rfkill_force_state(), so the cache either is bypassed or valid. |
| 148 | * | 147 | * |
| @@ -150,7 +149,7 @@ static void update_rfkill_state(struct rfkill *rfkill) | |||
| 150 | * even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to | 149 | * even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to |
| 151 | * give the driver a hint that it should double-BLOCK the transmitter. | 150 | * give the driver a hint that it should double-BLOCK the transmitter. |
| 152 | * | 151 | * |
| 153 | * Caller must have aquired rfkill_mutex. | 152 | * Caller must have acquired rfkill->mutex. |
| 154 | */ | 153 | */ |
| 155 | static int rfkill_toggle_radio(struct rfkill *rfkill, | 154 | static int rfkill_toggle_radio(struct rfkill *rfkill, |
| 156 | enum rfkill_state state, | 155 | enum rfkill_state state, |
| @@ -200,12 +199,12 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, | |||
| 200 | 199 | ||
| 201 | /** | 200 | /** |
| 202 | * rfkill_switch_all - Toggle state of all switches of given type | 201 | * rfkill_switch_all - Toggle state of all switches of given type |
| 203 | * @type: type of interfaces to be affeceted | 202 | * @type: type of interfaces to be affected |
| 204 | * @state: the new state | 203 | * @state: the new state |
| 205 | * | 204 | * |
| 206 | * This function toggles state of all switches of given type unless | 205 | * This function toggles the state of all switches of given type, |
| 207 | * a specific switch is claimed by userspace in which case it is | 206 | * unless a specific switch is claimed by userspace (in which case, |
| 208 | * left alone. | 207 | * that switch is left alone). |
| 209 | */ | 208 | */ |
| 210 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) | 209 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) |
| 211 | { | 210 | { |
| @@ -216,8 +215,11 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) | |||
| 216 | rfkill_states[type] = state; | 215 | rfkill_states[type] = state; |
| 217 | 216 | ||
| 218 | list_for_each_entry(rfkill, &rfkill_list, node) { | 217 | list_for_each_entry(rfkill, &rfkill_list, node) { |
| 219 | if ((!rfkill->user_claim) && (rfkill->type == type)) | 218 | if ((!rfkill->user_claim) && (rfkill->type == type)) { |
| 219 | mutex_lock(&rfkill->mutex); | ||
| 220 | rfkill_toggle_radio(rfkill, state, 0); | 220 | rfkill_toggle_radio(rfkill, state, 0); |
| 221 | mutex_unlock(&rfkill->mutex); | ||
| 222 | } | ||
| 221 | } | 223 | } |
| 222 | 224 | ||
| 223 | mutex_unlock(&rfkill_mutex); | 225 | mutex_unlock(&rfkill_mutex); |
| @@ -228,7 +230,7 @@ EXPORT_SYMBOL(rfkill_switch_all); | |||
| 228 | * rfkill_epo - emergency power off all transmitters | 230 | * rfkill_epo - emergency power off all transmitters |
| 229 | * | 231 | * |
| 230 | * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring | 232 | * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring |
| 231 | * everything in its path but rfkill_mutex. | 233 | * everything in its path but rfkill_mutex and rfkill->mutex. |
| 232 | */ | 234 | */ |
| 233 | void rfkill_epo(void) | 235 | void rfkill_epo(void) |
| 234 | { | 236 | { |
| @@ -236,7 +238,9 @@ void rfkill_epo(void) | |||
| 236 | 238 | ||
| 237 | mutex_lock(&rfkill_mutex); | 239 | mutex_lock(&rfkill_mutex); |
| 238 | list_for_each_entry(rfkill, &rfkill_list, node) { | 240 | list_for_each_entry(rfkill, &rfkill_list, node) { |
| 241 | mutex_lock(&rfkill->mutex); | ||
| 239 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | 242 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); |
| 243 | mutex_unlock(&rfkill->mutex); | ||
| 240 | } | 244 | } |
| 241 | mutex_unlock(&rfkill_mutex); | 245 | mutex_unlock(&rfkill_mutex); |
| 242 | } | 246 | } |
| @@ -252,7 +256,12 @@ EXPORT_SYMBOL_GPL(rfkill_epo); | |||
| 252 | * a notification by the firmware/hardware of the current *real* | 256 | * a notification by the firmware/hardware of the current *real* |
| 253 | * state of the radio rfkill switch. | 257 | * state of the radio rfkill switch. |
| 254 | * | 258 | * |
| 255 | * It may not be called from an atomic context. | 259 | * Devices which are subject to external changes on their rfkill |
| 260 | * state (such as those caused by a hardware rfkill line) MUST | ||
| 261 | * have their driver arrange to call rfkill_force_state() as soon | ||
| 262 | * as possible after such a change. | ||
| 263 | * | ||
| 264 | * This function may not be called from an atomic context. | ||
| 256 | */ | 265 | */ |
| 257 | int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) | 266 | int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) |
| 258 | { | 267 | { |
| @@ -367,6 +376,9 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
| 367 | if (!capable(CAP_NET_ADMIN)) | 376 | if (!capable(CAP_NET_ADMIN)) |
| 368 | return -EPERM; | 377 | return -EPERM; |
| 369 | 378 | ||
| 379 | if (rfkill->user_claim_unsupported) | ||
| 380 | return -EOPNOTSUPP; | ||
| 381 | |||
| 370 | /* | 382 | /* |
| 371 | * Take the global lock to make sure the kernel is not in | 383 | * Take the global lock to make sure the kernel is not in |
| 372 | * the middle of rfkill_switch_all | 384 | * the middle of rfkill_switch_all |
| @@ -375,19 +387,17 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
| 375 | if (error) | 387 | if (error) |
| 376 | return error; | 388 | return error; |
| 377 | 389 | ||
| 378 | if (rfkill->user_claim_unsupported) { | ||
| 379 | error = -EOPNOTSUPP; | ||
| 380 | goto out_unlock; | ||
| 381 | } | ||
| 382 | if (rfkill->user_claim != claim) { | 390 | if (rfkill->user_claim != claim) { |
| 383 | if (!claim) | 391 | if (!claim) { |
| 392 | mutex_lock(&rfkill->mutex); | ||
| 384 | rfkill_toggle_radio(rfkill, | 393 | rfkill_toggle_radio(rfkill, |
| 385 | rfkill_states[rfkill->type], | 394 | rfkill_states[rfkill->type], |
| 386 | 0); | 395 | 0); |
| 396 | mutex_unlock(&rfkill->mutex); | ||
| 397 | } | ||
| 387 | rfkill->user_claim = claim; | 398 | rfkill->user_claim = claim; |
| 388 | } | 399 | } |
| 389 | 400 | ||
| 390 | out_unlock: | ||
| 391 | mutex_unlock(&rfkill_mutex); | 401 | mutex_unlock(&rfkill_mutex); |
| 392 | 402 | ||
| 393 | return error ? error : count; | 403 | return error ? error : count; |
| @@ -516,8 +526,11 @@ static void rfkill_remove_switch(struct rfkill *rfkill) | |||
| 516 | { | 526 | { |
| 517 | mutex_lock(&rfkill_mutex); | 527 | mutex_lock(&rfkill_mutex); |
| 518 | list_del_init(&rfkill->node); | 528 | list_del_init(&rfkill->node); |
| 519 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | ||
| 520 | mutex_unlock(&rfkill_mutex); | 529 | mutex_unlock(&rfkill_mutex); |
| 530 | |||
| 531 | mutex_lock(&rfkill->mutex); | ||
| 532 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | ||
| 533 | mutex_unlock(&rfkill->mutex); | ||
| 521 | } | 534 | } |
| 522 | 535 | ||
| 523 | /** | 536 | /** |
| @@ -526,9 +539,10 @@ static void rfkill_remove_switch(struct rfkill *rfkill) | |||
| 526 | * @type: type of the switch (RFKILL_TYPE_*) | 539 | * @type: type of the switch (RFKILL_TYPE_*) |
| 527 | * | 540 | * |
| 528 | * This function should be called by the network driver when it needs | 541 | * This function should be called by the network driver when it needs |
| 529 | * rfkill structure. Once the structure is allocated the driver shoud | 542 | * rfkill structure. Once the structure is allocated the driver should |
| 530 | * finish its initialization by setting name, private data, enable_radio | 543 | * finish its initialization by setting the name, private data, enable_radio |
| 531 | * and disable_radio methods and then register it with rfkill_register(). | 544 | * and disable_radio methods and then register it with rfkill_register(). |
| 545 | * | ||
| 532 | * NOTE: If registration fails the structure shoudl be freed by calling | 546 | * NOTE: If registration fails the structure shoudl be freed by calling |
| 533 | * rfkill_free() otherwise rfkill_unregister() should be used. | 547 | * rfkill_free() otherwise rfkill_unregister() should be used. |
| 534 | */ | 548 | */ |
| @@ -560,7 +574,7 @@ EXPORT_SYMBOL(rfkill_allocate); | |||
| 560 | * rfkill_free - Mark rfkill structure for deletion | 574 | * rfkill_free - Mark rfkill structure for deletion |
| 561 | * @rfkill: rfkill structure to be destroyed | 575 | * @rfkill: rfkill structure to be destroyed |
| 562 | * | 576 | * |
| 563 | * Decrements reference count of rfkill structure so it is destroyed. | 577 | * Decrements reference count of the rfkill structure so it is destroyed. |
| 564 | * Note that rfkill_free() should _not_ be called after rfkill_unregister(). | 578 | * Note that rfkill_free() should _not_ be called after rfkill_unregister(). |
| 565 | */ | 579 | */ |
| 566 | void rfkill_free(struct rfkill *rfkill) | 580 | void rfkill_free(struct rfkill *rfkill) |
| @@ -585,8 +599,10 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill) | |||
| 585 | static void rfkill_led_trigger_unregister(struct rfkill *rfkill) | 599 | static void rfkill_led_trigger_unregister(struct rfkill *rfkill) |
| 586 | { | 600 | { |
| 587 | #ifdef CONFIG_RFKILL_LEDS | 601 | #ifdef CONFIG_RFKILL_LEDS |
| 588 | if (rfkill->led_trigger.name) | 602 | if (rfkill->led_trigger.name) { |
| 589 | led_trigger_unregister(&rfkill->led_trigger); | 603 | led_trigger_unregister(&rfkill->led_trigger); |
| 604 | rfkill->led_trigger.name = NULL; | ||
| 605 | } | ||
| 590 | #endif | 606 | #endif |
| 591 | } | 607 | } |
| 592 | 608 | ||
| @@ -622,8 +638,8 @@ int rfkill_register(struct rfkill *rfkill) | |||
| 622 | 638 | ||
| 623 | error = device_add(dev); | 639 | error = device_add(dev); |
| 624 | if (error) { | 640 | if (error) { |
| 625 | rfkill_led_trigger_unregister(rfkill); | ||
| 626 | rfkill_remove_switch(rfkill); | 641 | rfkill_remove_switch(rfkill); |
| 642 | rfkill_led_trigger_unregister(rfkill); | ||
| 627 | return error; | 643 | return error; |
| 628 | } | 644 | } |
| 629 | 645 | ||
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index b0601642e227..4840aff47256 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -572,44 +572,21 @@ static u32 qdisc_alloc_handle(struct net_device *dev) | |||
| 572 | static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, | 572 | static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, |
| 573 | struct Qdisc *qdisc) | 573 | struct Qdisc *qdisc) |
| 574 | { | 574 | { |
| 575 | struct Qdisc *oqdisc = dev_queue->qdisc_sleeping; | ||
| 575 | spinlock_t *root_lock; | 576 | spinlock_t *root_lock; |
| 576 | struct Qdisc *oqdisc; | ||
| 577 | int ingress; | ||
| 578 | |||
| 579 | ingress = 0; | ||
| 580 | if (qdisc && qdisc->flags&TCQ_F_INGRESS) | ||
| 581 | ingress = 1; | ||
| 582 | |||
| 583 | if (ingress) { | ||
| 584 | oqdisc = dev_queue->qdisc; | ||
| 585 | } else { | ||
| 586 | oqdisc = dev_queue->qdisc_sleeping; | ||
| 587 | } | ||
| 588 | 577 | ||
| 589 | root_lock = qdisc_root_lock(oqdisc); | 578 | root_lock = qdisc_root_lock(oqdisc); |
| 590 | spin_lock_bh(root_lock); | 579 | spin_lock_bh(root_lock); |
| 591 | 580 | ||
| 592 | if (ingress) { | 581 | /* Prune old scheduler */ |
| 593 | /* Prune old scheduler */ | 582 | if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) |
| 594 | if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) { | 583 | qdisc_reset(oqdisc); |
| 595 | /* delete */ | ||
| 596 | qdisc_reset(oqdisc); | ||
| 597 | dev_queue->qdisc = NULL; | ||
| 598 | } else { /* new */ | ||
| 599 | dev_queue->qdisc = qdisc; | ||
| 600 | } | ||
| 601 | 584 | ||
| 602 | } else { | 585 | /* ... and graft new one */ |
| 603 | /* Prune old scheduler */ | 586 | if (qdisc == NULL) |
| 604 | if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) | 587 | qdisc = &noop_qdisc; |
| 605 | qdisc_reset(oqdisc); | 588 | dev_queue->qdisc_sleeping = qdisc; |
| 606 | 589 | dev_queue->qdisc = &noop_qdisc; | |
| 607 | /* ... and graft new one */ | ||
| 608 | if (qdisc == NULL) | ||
| 609 | qdisc = &noop_qdisc; | ||
| 610 | dev_queue->qdisc_sleeping = qdisc; | ||
| 611 | dev_queue->qdisc = &noop_qdisc; | ||
| 612 | } | ||
| 613 | 590 | ||
| 614 | spin_unlock_bh(root_lock); | 591 | spin_unlock_bh(root_lock); |
| 615 | 592 | ||
| @@ -678,7 +655,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
| 678 | 655 | ||
| 679 | ingress = 0; | 656 | ingress = 0; |
| 680 | num_q = dev->num_tx_queues; | 657 | num_q = dev->num_tx_queues; |
| 681 | if (q && q->flags & TCQ_F_INGRESS) { | 658 | if ((q && q->flags & TCQ_F_INGRESS) || |
| 659 | (new && new->flags & TCQ_F_INGRESS)) { | ||
| 682 | num_q = 1; | 660 | num_q = 1; |
| 683 | ingress = 1; | 661 | ingress = 1; |
| 684 | } | 662 | } |
| @@ -692,13 +670,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
| 692 | if (!ingress) | 670 | if (!ingress) |
| 693 | dev_queue = netdev_get_tx_queue(dev, i); | 671 | dev_queue = netdev_get_tx_queue(dev, i); |
| 694 | 672 | ||
| 695 | if (ingress) { | 673 | old = dev_graft_qdisc(dev_queue, new); |
| 696 | old = dev_graft_qdisc(dev_queue, q); | 674 | if (new && i > 0) |
| 697 | } else { | 675 | atomic_inc(&new->refcnt); |
| 698 | old = dev_graft_qdisc(dev_queue, new); | 676 | |
| 699 | if (new && i > 0) | ||
| 700 | atomic_inc(&new->refcnt); | ||
| 701 | } | ||
| 702 | notify_and_destroy(skb, n, classid, old, new); | 677 | notify_and_destroy(skb, n, classid, old, new); |
| 703 | } | 678 | } |
| 704 | 679 | ||
| @@ -817,7 +792,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | |||
| 817 | goto err_out3; | 792 | goto err_out3; |
| 818 | } | 793 | } |
| 819 | } | 794 | } |
| 820 | if (parent) | 795 | if (parent && !(sch->flags & TCQ_F_INGRESS)) |
| 821 | list_add_tail(&sch->list, &dev_queue->qdisc->list); | 796 | list_add_tail(&sch->list, &dev_queue->qdisc->list); |
| 822 | 797 | ||
| 823 | return sch; | 798 | return sch; |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index fd2a6cadb115..345838a2e369 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
| @@ -596,7 +596,7 @@ static void transition_one_qdisc(struct net_device *dev, | |||
| 596 | int *need_watchdog_p = _need_watchdog; | 596 | int *need_watchdog_p = _need_watchdog; |
| 597 | 597 | ||
| 598 | rcu_assign_pointer(dev_queue->qdisc, new_qdisc); | 598 | rcu_assign_pointer(dev_queue->qdisc, new_qdisc); |
| 599 | if (new_qdisc != &noqueue_qdisc) | 599 | if (need_watchdog_p && new_qdisc != &noqueue_qdisc) |
| 600 | *need_watchdog_p = 1; | 600 | *need_watchdog_p = 1; |
| 601 | } | 601 | } |
| 602 | 602 | ||
| @@ -619,6 +619,7 @@ void dev_activate(struct net_device *dev) | |||
| 619 | 619 | ||
| 620 | need_watchdog = 0; | 620 | need_watchdog = 0; |
| 621 | netdev_for_each_tx_queue(dev, transition_one_qdisc, &need_watchdog); | 621 | netdev_for_each_tx_queue(dev, transition_one_qdisc, &need_watchdog); |
| 622 | transition_one_qdisc(dev, &dev->rx_queue, NULL); | ||
| 622 | 623 | ||
| 623 | if (need_watchdog) { | 624 | if (need_watchdog) { |
| 624 | dev->trans_start = jiffies; | 625 | dev->trans_start = jiffies; |
| @@ -677,6 +678,7 @@ void dev_deactivate(struct net_device *dev) | |||
| 677 | bool running; | 678 | bool running; |
| 678 | 679 | ||
| 679 | netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc); | 680 | netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc); |
| 681 | dev_deactivate_queue(dev, &dev->rx_queue, &noop_qdisc); | ||
| 680 | 682 | ||
| 681 | dev_watchdog_down(dev); | 683 | dev_watchdog_down(dev); |
| 682 | 684 | ||
| @@ -718,7 +720,7 @@ static void dev_init_scheduler_queue(struct net_device *dev, | |||
| 718 | void dev_init_scheduler(struct net_device *dev) | 720 | void dev_init_scheduler(struct net_device *dev) |
| 719 | { | 721 | { |
| 720 | netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); | 722 | netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); |
| 721 | dev_init_scheduler_queue(dev, &dev->rx_queue, NULL); | 723 | dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); |
| 722 | 724 | ||
| 723 | setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev); | 725 | setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev); |
| 724 | } | 726 | } |
| @@ -745,6 +747,6 @@ static void shutdown_scheduler_queue(struct net_device *dev, | |||
| 745 | void dev_shutdown(struct net_device *dev) | 747 | void dev_shutdown(struct net_device *dev) |
| 746 | { | 748 | { |
| 747 | netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); | 749 | netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); |
| 748 | shutdown_scheduler_queue(dev, &dev->rx_queue, NULL); | 750 | shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); |
| 749 | WARN_ON(timer_pending(&dev->watchdog_timer)); | 751 | WARN_ON(timer_pending(&dev->watchdog_timer)); |
| 750 | } | 752 | } |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b7fefffd2d0d..59eb2cf42e5f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -29,16 +29,16 @@ static struct genl_family nl80211_fam = { | |||
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | /* internal helper: get drv and dev */ | 31 | /* internal helper: get drv and dev */ |
| 32 | static int get_drv_dev_by_info_ifindex(struct genl_info *info, | 32 | static int get_drv_dev_by_info_ifindex(struct nlattr **attrs, |
| 33 | struct cfg80211_registered_device **drv, | 33 | struct cfg80211_registered_device **drv, |
| 34 | struct net_device **dev) | 34 | struct net_device **dev) |
| 35 | { | 35 | { |
| 36 | int ifindex; | 36 | int ifindex; |
| 37 | 37 | ||
| 38 | if (!info->attrs[NL80211_ATTR_IFINDEX]) | 38 | if (!attrs[NL80211_ATTR_IFINDEX]) |
| 39 | return -EINVAL; | 39 | return -EINVAL; |
| 40 | 40 | ||
| 41 | ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); | 41 | ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); |
| 42 | *dev = dev_get_by_index(&init_net, ifindex); | 42 | *dev = dev_get_by_index(&init_net, ifindex); |
| 43 | if (!*dev) | 43 | if (!*dev) |
| 44 | return -ENODEV; | 44 | return -ENODEV; |
| @@ -291,21 +291,31 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
| 291 | 291 | ||
| 292 | mutex_lock(&cfg80211_drv_mutex); | 292 | mutex_lock(&cfg80211_drv_mutex); |
| 293 | list_for_each_entry(dev, &cfg80211_drv_list, list) { | 293 | list_for_each_entry(dev, &cfg80211_drv_list, list) { |
| 294 | if (++wp_idx < wp_start) | 294 | if (wp_idx < wp_start) { |
| 295 | wp_idx++; | ||
| 295 | continue; | 296 | continue; |
| 297 | } | ||
| 296 | if_idx = 0; | 298 | if_idx = 0; |
| 297 | 299 | ||
| 298 | mutex_lock(&dev->devlist_mtx); | 300 | mutex_lock(&dev->devlist_mtx); |
| 299 | list_for_each_entry(wdev, &dev->netdev_list, list) { | 301 | list_for_each_entry(wdev, &dev->netdev_list, list) { |
| 300 | if (++if_idx < if_start) | 302 | if (if_idx < if_start) { |
| 303 | if_idx++; | ||
| 301 | continue; | 304 | continue; |
| 305 | } | ||
| 302 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, | 306 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, |
| 303 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 307 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| 304 | wdev->netdev) < 0) | 308 | wdev->netdev) < 0) { |
| 305 | break; | 309 | mutex_unlock(&dev->devlist_mtx); |
| 310 | goto out; | ||
| 311 | } | ||
| 312 | if_idx++; | ||
| 306 | } | 313 | } |
| 307 | mutex_unlock(&dev->devlist_mtx); | 314 | mutex_unlock(&dev->devlist_mtx); |
| 315 | |||
| 316 | wp_idx++; | ||
| 308 | } | 317 | } |
| 318 | out: | ||
| 309 | mutex_unlock(&cfg80211_drv_mutex); | 319 | mutex_unlock(&cfg80211_drv_mutex); |
| 310 | 320 | ||
| 311 | cb->args[0] = wp_idx; | 321 | cb->args[0] = wp_idx; |
| @@ -321,7 +331,7 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 321 | struct net_device *netdev; | 331 | struct net_device *netdev; |
| 322 | int err; | 332 | int err; |
| 323 | 333 | ||
| 324 | err = get_drv_dev_by_info_ifindex(info, &dev, &netdev); | 334 | err = get_drv_dev_by_info_ifindex(info->attrs, &dev, &netdev); |
| 325 | if (err) | 335 | if (err) |
| 326 | return err; | 336 | return err; |
| 327 | 337 | ||
| @@ -392,7 +402,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 392 | } else | 402 | } else |
| 393 | return -EINVAL; | 403 | return -EINVAL; |
| 394 | 404 | ||
| 395 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 405 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 396 | if (err) | 406 | if (err) |
| 397 | return err; | 407 | return err; |
| 398 | ifindex = dev->ifindex; | 408 | ifindex = dev->ifindex; |
| @@ -477,7 +487,7 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 477 | int ifindex, err; | 487 | int ifindex, err; |
| 478 | struct net_device *dev; | 488 | struct net_device *dev; |
| 479 | 489 | ||
| 480 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 490 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 481 | if (err) | 491 | if (err) |
| 482 | return err; | 492 | return err; |
| 483 | ifindex = dev->ifindex; | 493 | ifindex = dev->ifindex; |
| @@ -545,7 +555,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
| 545 | if (info->attrs[NL80211_ATTR_MAC]) | 555 | if (info->attrs[NL80211_ATTR_MAC]) |
| 546 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 556 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 547 | 557 | ||
| 548 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 558 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 549 | if (err) | 559 | if (err) |
| 550 | return err; | 560 | return err; |
| 551 | 561 | ||
| @@ -618,7 +628,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
| 618 | if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) | 628 | if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) |
| 619 | return -EINVAL; | 629 | return -EINVAL; |
| 620 | 630 | ||
| 621 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 631 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 622 | if (err) | 632 | if (err) |
| 623 | return err; | 633 | return err; |
| 624 | 634 | ||
| @@ -699,7 +709,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
| 699 | return -EINVAL; | 709 | return -EINVAL; |
| 700 | } | 710 | } |
| 701 | 711 | ||
| 702 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 712 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 703 | if (err) | 713 | if (err) |
| 704 | return err; | 714 | return err; |
| 705 | 715 | ||
| @@ -735,7 +745,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
| 735 | if (info->attrs[NL80211_ATTR_MAC]) | 745 | if (info->attrs[NL80211_ATTR_MAC]) |
| 736 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 746 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 737 | 747 | ||
| 738 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 748 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 739 | if (err) | 749 | if (err) |
| 740 | return err; | 750 | return err; |
| 741 | 751 | ||
| @@ -764,7 +774,7 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
| 764 | struct beacon_parameters params; | 774 | struct beacon_parameters params; |
| 765 | int haveinfo = 0; | 775 | int haveinfo = 0; |
| 766 | 776 | ||
| 767 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 777 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 768 | if (err) | 778 | if (err) |
| 769 | return err; | 779 | return err; |
| 770 | 780 | ||
| @@ -843,7 +853,7 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | |||
| 843 | int err; | 853 | int err; |
| 844 | struct net_device *dev; | 854 | struct net_device *dev; |
| 845 | 855 | ||
| 846 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 856 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 847 | if (err) | 857 | if (err) |
| 848 | return err; | 858 | return err; |
| 849 | 859 | ||
| @@ -937,67 +947,78 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
| 937 | } | 947 | } |
| 938 | 948 | ||
| 939 | static int nl80211_dump_station(struct sk_buff *skb, | 949 | static int nl80211_dump_station(struct sk_buff *skb, |
| 940 | struct netlink_callback *cb) | 950 | struct netlink_callback *cb) |
| 941 | { | 951 | { |
| 942 | int wp_idx = 0; | ||
| 943 | int if_idx = 0; | ||
| 944 | int sta_idx = cb->args[2]; | ||
| 945 | int wp_start = cb->args[0]; | ||
| 946 | int if_start = cb->args[1]; | ||
| 947 | struct station_info sinfo; | 952 | struct station_info sinfo; |
| 948 | struct cfg80211_registered_device *dev; | 953 | struct cfg80211_registered_device *dev; |
| 949 | struct wireless_dev *wdev; | 954 | struct net_device *netdev; |
| 950 | u8 mac_addr[ETH_ALEN]; | 955 | u8 mac_addr[ETH_ALEN]; |
| 956 | int ifidx = cb->args[0]; | ||
| 957 | int sta_idx = cb->args[1]; | ||
| 951 | int err; | 958 | int err; |
| 952 | int exit = 0; | ||
| 953 | 959 | ||
| 954 | /* TODO: filter by device */ | 960 | if (!ifidx) { |
| 955 | mutex_lock(&cfg80211_drv_mutex); | 961 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
| 956 | list_for_each_entry(dev, &cfg80211_drv_list, list) { | 962 | nl80211_fam.attrbuf, nl80211_fam.maxattr, |
| 957 | if (exit) | 963 | nl80211_policy); |
| 964 | if (err) | ||
| 965 | return err; | ||
| 966 | |||
| 967 | if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]) | ||
| 968 | return -EINVAL; | ||
| 969 | |||
| 970 | ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); | ||
| 971 | if (!ifidx) | ||
| 972 | return -EINVAL; | ||
| 973 | } | ||
| 974 | |||
| 975 | netdev = dev_get_by_index(&init_net, ifidx); | ||
| 976 | if (!netdev) | ||
| 977 | return -ENODEV; | ||
| 978 | |||
| 979 | dev = cfg80211_get_dev_from_ifindex(ifidx); | ||
| 980 | if (IS_ERR(dev)) { | ||
| 981 | err = PTR_ERR(dev); | ||
| 982 | goto out_put_netdev; | ||
| 983 | } | ||
| 984 | |||
| 985 | if (!dev->ops->dump_station) { | ||
| 986 | err = -ENOSYS; | ||
| 987 | goto out_err; | ||
| 988 | } | ||
| 989 | |||
| 990 | rtnl_lock(); | ||
| 991 | |||
| 992 | while (1) { | ||
| 993 | err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, | ||
| 994 | mac_addr, &sinfo); | ||
| 995 | if (err == -ENOENT) | ||
| 958 | break; | 996 | break; |
| 959 | if (++wp_idx < wp_start) | 997 | if (err) |
| 960 | continue; | 998 | goto out_err_rtnl; |
| 961 | if_idx = 0; | ||
| 962 | 999 | ||
| 963 | mutex_lock(&dev->devlist_mtx); | 1000 | if (nl80211_send_station(skb, |
| 964 | list_for_each_entry(wdev, &dev->netdev_list, list) { | 1001 | NETLINK_CB(cb->skb).pid, |
| 965 | if (exit) | 1002 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| 966 | break; | 1003 | netdev, mac_addr, |
| 967 | if (++if_idx < if_start) | 1004 | &sinfo) < 0) |
| 968 | continue; | 1005 | goto out; |
| 969 | if (!dev->ops->dump_station) | ||
| 970 | continue; | ||
| 971 | 1006 | ||
| 972 | for (;; ++sta_idx) { | 1007 | sta_idx++; |
| 973 | rtnl_lock(); | ||
| 974 | err = dev->ops->dump_station(&dev->wiphy, | ||
| 975 | wdev->netdev, sta_idx, mac_addr, | ||
| 976 | &sinfo); | ||
| 977 | rtnl_unlock(); | ||
| 978 | if (err) { | ||
| 979 | sta_idx = 0; | ||
| 980 | break; | ||
| 981 | } | ||
| 982 | if (nl80211_send_station(skb, | ||
| 983 | NETLINK_CB(cb->skb).pid, | ||
| 984 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
| 985 | wdev->netdev, mac_addr, | ||
| 986 | &sinfo) < 0) { | ||
| 987 | exit = 1; | ||
| 988 | break; | ||
| 989 | } | ||
| 990 | } | ||
| 991 | } | ||
| 992 | mutex_unlock(&dev->devlist_mtx); | ||
| 993 | } | 1008 | } |
| 994 | mutex_unlock(&cfg80211_drv_mutex); | ||
| 995 | 1009 | ||
| 996 | cb->args[0] = wp_idx; | ||
| 997 | cb->args[1] = if_idx; | ||
| 998 | cb->args[2] = sta_idx; | ||
| 999 | 1010 | ||
| 1000 | return skb->len; | 1011 | out: |
| 1012 | cb->args[1] = sta_idx; | ||
| 1013 | err = skb->len; | ||
| 1014 | out_err_rtnl: | ||
| 1015 | rtnl_unlock(); | ||
| 1016 | out_err: | ||
| 1017 | cfg80211_put_dev(dev); | ||
| 1018 | out_put_netdev: | ||
| 1019 | dev_put(netdev); | ||
| 1020 | |||
| 1021 | return err; | ||
| 1001 | } | 1022 | } |
| 1002 | 1023 | ||
| 1003 | static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | 1024 | static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) |
| @@ -1016,7 +1037,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1016 | 1037 | ||
| 1017 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1038 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 1018 | 1039 | ||
| 1019 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 1040 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 1020 | if (err) | 1041 | if (err) |
| 1021 | return err; | 1042 | return err; |
| 1022 | 1043 | ||
| @@ -1112,7 +1133,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1112 | params.plink_action = | 1133 | params.plink_action = |
| 1113 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 1134 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
| 1114 | 1135 | ||
| 1115 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 1136 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 1116 | if (err) | 1137 | if (err) |
| 1117 | return err; | 1138 | return err; |
| 1118 | 1139 | ||
| @@ -1172,7 +1193,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1172 | ¶ms.station_flags)) | 1193 | ¶ms.station_flags)) |
| 1173 | return -EINVAL; | 1194 | return -EINVAL; |
| 1174 | 1195 | ||
| 1175 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 1196 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 1176 | if (err) | 1197 | if (err) |
| 1177 | return err; | 1198 | return err; |
| 1178 | 1199 | ||
| @@ -1207,7 +1228,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1207 | if (info->attrs[NL80211_ATTR_MAC]) | 1228 | if (info->attrs[NL80211_ATTR_MAC]) |
| 1208 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1229 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 1209 | 1230 | ||
| 1210 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 1231 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 1211 | if (err) | 1232 | if (err) |
| 1212 | return err; | 1233 | return err; |
| 1213 | 1234 | ||
| @@ -1277,68 +1298,78 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, | |||
| 1277 | } | 1298 | } |
| 1278 | 1299 | ||
| 1279 | static int nl80211_dump_mpath(struct sk_buff *skb, | 1300 | static int nl80211_dump_mpath(struct sk_buff *skb, |
| 1280 | struct netlink_callback *cb) | 1301 | struct netlink_callback *cb) |
| 1281 | { | 1302 | { |
| 1282 | int wp_idx = 0; | ||
| 1283 | int if_idx = 0; | ||
| 1284 | int sta_idx = cb->args[2]; | ||
| 1285 | int wp_start = cb->args[0]; | ||
| 1286 | int if_start = cb->args[1]; | ||
| 1287 | struct mpath_info pinfo; | 1303 | struct mpath_info pinfo; |
| 1288 | struct cfg80211_registered_device *dev; | 1304 | struct cfg80211_registered_device *dev; |
| 1289 | struct wireless_dev *wdev; | 1305 | struct net_device *netdev; |
| 1290 | u8 dst[ETH_ALEN]; | 1306 | u8 dst[ETH_ALEN]; |
| 1291 | u8 next_hop[ETH_ALEN]; | 1307 | u8 next_hop[ETH_ALEN]; |
| 1308 | int ifidx = cb->args[0]; | ||
| 1309 | int path_idx = cb->args[1]; | ||
| 1292 | int err; | 1310 | int err; |
| 1293 | int exit = 0; | ||
| 1294 | 1311 | ||
| 1295 | /* TODO: filter by device */ | 1312 | if (!ifidx) { |
| 1296 | mutex_lock(&cfg80211_drv_mutex); | 1313 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
| 1297 | list_for_each_entry(dev, &cfg80211_drv_list, list) { | 1314 | nl80211_fam.attrbuf, nl80211_fam.maxattr, |
| 1298 | if (exit) | 1315 | nl80211_policy); |
| 1316 | if (err) | ||
| 1317 | return err; | ||
| 1318 | |||
| 1319 | if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]) | ||
| 1320 | return -EINVAL; | ||
| 1321 | |||
| 1322 | ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); | ||
| 1323 | if (!ifidx) | ||
| 1324 | return -EINVAL; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | netdev = dev_get_by_index(&init_net, ifidx); | ||
| 1328 | if (!netdev) | ||
| 1329 | return -ENODEV; | ||
| 1330 | |||
| 1331 | dev = cfg80211_get_dev_from_ifindex(ifidx); | ||
| 1332 | if (IS_ERR(dev)) { | ||
| 1333 | err = PTR_ERR(dev); | ||
| 1334 | goto out_put_netdev; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | if (!dev->ops->dump_mpath) { | ||
| 1338 | err = -ENOSYS; | ||
| 1339 | goto out_err; | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | rtnl_lock(); | ||
| 1343 | |||
| 1344 | while (1) { | ||
| 1345 | err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, | ||
| 1346 | dst, next_hop, &pinfo); | ||
| 1347 | if (err == -ENOENT) | ||
| 1299 | break; | 1348 | break; |
| 1300 | if (++wp_idx < wp_start) | 1349 | if (err) |
| 1301 | continue; | 1350 | goto out_err_rtnl; |
| 1302 | if_idx = 0; | ||
| 1303 | 1351 | ||
| 1304 | mutex_lock(&dev->devlist_mtx); | 1352 | if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, |
| 1305 | list_for_each_entry(wdev, &dev->netdev_list, list) { | 1353 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| 1306 | if (exit) | 1354 | netdev, dst, next_hop, |
| 1307 | break; | 1355 | &pinfo) < 0) |
| 1308 | if (++if_idx < if_start) | 1356 | goto out; |
| 1309 | continue; | ||
| 1310 | if (!dev->ops->dump_mpath) | ||
| 1311 | continue; | ||
| 1312 | 1357 | ||
| 1313 | for (;; ++sta_idx) { | 1358 | path_idx++; |
| 1314 | rtnl_lock(); | ||
| 1315 | err = dev->ops->dump_mpath(&dev->wiphy, | ||
| 1316 | wdev->netdev, sta_idx, dst, | ||
| 1317 | next_hop, &pinfo); | ||
| 1318 | rtnl_unlock(); | ||
| 1319 | if (err) { | ||
| 1320 | sta_idx = 0; | ||
| 1321 | break; | ||
| 1322 | } | ||
| 1323 | if (nl80211_send_mpath(skb, | ||
| 1324 | NETLINK_CB(cb->skb).pid, | ||
| 1325 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
| 1326 | wdev->netdev, dst, next_hop, | ||
| 1327 | &pinfo) < 0) { | ||
| 1328 | exit = 1; | ||
| 1329 | break; | ||
| 1330 | } | ||
| 1331 | } | ||
| 1332 | } | ||
| 1333 | mutex_unlock(&dev->devlist_mtx); | ||
| 1334 | } | 1359 | } |
| 1335 | mutex_unlock(&cfg80211_drv_mutex); | ||
| 1336 | 1360 | ||
| 1337 | cb->args[0] = wp_idx; | ||
| 1338 | cb->args[1] = if_idx; | ||
| 1339 | cb->args[2] = sta_idx; | ||
| 1340 | 1361 | ||
| 1341 | return skb->len; | 1362 | out: |
| 1363 | cb->args[1] = path_idx; | ||
| 1364 | err = skb->len; | ||
| 1365 | out_err_rtnl: | ||
| 1366 | rtnl_unlock(); | ||
| 1367 | out_err: | ||
| 1368 | cfg80211_put_dev(dev); | ||
| 1369 | out_put_netdev: | ||
| 1370 | dev_put(netdev); | ||
| 1371 | |||
| 1372 | return err; | ||
| 1342 | } | 1373 | } |
| 1343 | 1374 | ||
| 1344 | static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | 1375 | static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) |
| @@ -1358,7 +1389,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | |||
| 1358 | 1389 | ||
| 1359 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1390 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 1360 | 1391 | ||
| 1361 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 1392 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 1362 | if (err) | 1393 | if (err) |
| 1363 | return err; | 1394 | return err; |
| 1364 | 1395 | ||
| @@ -1411,7 +1442,7 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) | |||
| 1411 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1442 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 1412 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); | 1443 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); |
| 1413 | 1444 | ||
| 1414 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 1445 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 1415 | if (err) | 1446 | if (err) |
| 1416 | return err; | 1447 | return err; |
| 1417 | 1448 | ||
| @@ -1446,7 +1477,7 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | |||
| 1446 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1477 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 1447 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); | 1478 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); |
| 1448 | 1479 | ||
| 1449 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 1480 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 1450 | if (err) | 1481 | if (err) |
| 1451 | return err; | 1482 | return err; |
| 1452 | 1483 | ||
| @@ -1475,7 +1506,7 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | |||
| 1475 | if (info->attrs[NL80211_ATTR_MAC]) | 1506 | if (info->attrs[NL80211_ATTR_MAC]) |
| 1476 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1507 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 1477 | 1508 | ||
| 1478 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | 1509 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
| 1479 | if (err) | 1510 | if (err) |
| 1480 | return err; | 1511 | return err; |
| 1481 | 1512 | ||
