diff options
Diffstat (limited to 'net')
36 files changed, 1397 insertions, 1223 deletions
diff --git a/net/Kconfig b/net/Kconfig index 7612cc8c337..d87de48ba65 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -236,14 +236,18 @@ source "net/rxrpc/Kconfig" config FIB_RULES bool -menu "Wireless" +menuconfig WIRELESS + bool "Wireless" depends on !S390 + default y + +if WIRELESS source "net/wireless/Kconfig" source "net/mac80211/Kconfig" source "net/ieee80211/Kconfig" -endmenu +endif # WIRELESS source "net/rfkill/Kconfig" source "net/9p/Kconfig" diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 4e59df5f8e0..1edfdf4c095 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -456,7 +456,7 @@ static void __exit bt_exit(void) subsys_initcall(bt_init); module_exit(bt_exit); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth Core ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 12bba6207a8..80ba30cf4b6 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -736,7 +736,7 @@ MODULE_PARM_DESC(compress_src, "Compress sources headers"); module_param(compress_dst, bool, 0644); MODULE_PARM_DESC(compress_dst, "Compress destination headers"); -MODULE_AUTHOR("David Libault <david.libault@inventel.fr>, Maxim Krasnyansky <maxk@qualcomm.com>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index c85bf8f678d..f4f6615cad9 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -3,8 +3,6 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/platform_device.h> - #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -12,10 +10,164 @@ #undef BT_DBG #define BT_DBG(D...) #endif + +struct class *bt_class = NULL; +EXPORT_SYMBOL_GPL(bt_class); + static struct workqueue_struct *btaddconn; static struct workqueue_struct *btdelconn; -static inline char *typetostr(int type) +static inline char *link_typetostr(int type) +{ + switch (type) { + case ACL_LINK: + return "ACL"; + case SCO_LINK: + return "SCO"; + case ESCO_LINK: + return "eSCO"; + default: + return "UNKNOWN"; + } +} + +static ssize_t show_link_type(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hci_conn *conn = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", link_typetostr(conn->type)); +} + +static ssize_t show_link_address(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hci_conn *conn = dev_get_drvdata(dev); + bdaddr_t bdaddr; + baswap(&bdaddr, &conn->dst); + return sprintf(buf, "%s\n", batostr(&bdaddr)); +} + +static ssize_t show_link_features(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hci_conn *conn = dev_get_drvdata(dev); + + return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + conn->features[0], conn->features[1], + conn->features[2], conn->features[3], + conn->features[4], conn->features[5], + conn->features[6], conn->features[7]); +} + +#define LINK_ATTR(_name,_mode,_show,_store) \ +struct device_attribute link_attr_##_name = __ATTR(_name,_mode,_show,_store) + +static LINK_ATTR(type, S_IRUGO, show_link_type, NULL); +static LINK_ATTR(address, S_IRUGO, show_link_address, NULL); +static LINK_ATTR(features, S_IRUGO, show_link_features, NULL); + +static struct attribute *bt_link_attrs[] = { + &link_attr_type.attr, + &link_attr_address.attr, + &link_attr_features.attr, + NULL +}; + +static struct attribute_group bt_link_group = { + .attrs = bt_link_attrs, +}; + +static struct attribute_group *bt_link_groups[] = { + &bt_link_group, + NULL +}; + +static void bt_link_release(struct device *dev) +{ + void *data = dev_get_drvdata(dev); + kfree(data); +} + +static struct device_type bt_link = { + .name = "link", + .groups = bt_link_groups, + .release = bt_link_release, +}; + +static void add_conn(struct work_struct *work) +{ + struct hci_conn *conn = container_of(work, struct hci_conn, work); + + flush_workqueue(btdelconn); + + if (device_add(&conn->dev) < 0) { + BT_ERR("Failed to register connection device"); + return; + } +} + +void hci_conn_add_sysfs(struct hci_conn *conn) +{ + struct hci_dev *hdev = conn->hdev; + + BT_DBG("conn %p", conn); + + conn->dev.type = &bt_link; + conn->dev.class = bt_class; + conn->dev.parent = &hdev->dev; + + snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d", + hdev->name, conn->handle); + + dev_set_drvdata(&conn->dev, conn); + + device_initialize(&conn->dev); + + INIT_WORK(&conn->work, add_conn); + + queue_work(btaddconn, &conn->work); +} + +/* + * The rfcomm tty device will possibly retain even when conn + * is down, and sysfs doesn't support move zombie device, + * so we should move the device before conn device is destroyed. + */ +static int __match_tty(struct device *dev, void *data) +{ + return !strncmp(dev->bus_id, "rfcomm", 6); +} + +static void del_conn(struct work_struct *work) +{ + struct hci_conn *conn = container_of(work, struct hci_conn, work); + struct hci_dev *hdev = conn->hdev; + + while (1) { + struct device *dev; + + dev = device_find_child(&conn->dev, NULL, __match_tty); + if (!dev) + break; + device_move(dev, NULL); + put_device(dev); + } + + device_del(&conn->dev); + put_device(&conn->dev); + hci_dev_put(hdev); +} + +void hci_conn_del_sysfs(struct hci_conn *conn) +{ + BT_DBG("conn %p", conn); + + if (!device_is_registered(&conn->dev)) + return; + + INIT_WORK(&conn->work, del_conn); + + queue_work(btdelconn, &conn->work); +} + +static inline char *host_typetostr(int type) { switch (type) { case HCI_VIRTUAL: @@ -40,7 +192,7 @@ static inline char *typetostr(int type) static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", typetostr(hdev->type)); + return sprintf(buf, "%s\n", host_typetostr(hdev->type)); } static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -221,183 +373,62 @@ static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR, static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, show_sniff_min_interval, store_sniff_min_interval); -static struct device_attribute *bt_attrs[] = { - &dev_attr_type, - &dev_attr_name, - &dev_attr_class, - &dev_attr_address, - &dev_attr_features, - &dev_attr_manufacturer, - &dev_attr_hci_version, - &dev_attr_hci_revision, - &dev_attr_inquiry_cache, - &dev_attr_idle_timeout, - &dev_attr_sniff_max_interval, - &dev_attr_sniff_min_interval, +static struct attribute *bt_host_attrs[] = { + &dev_attr_type.attr, + &dev_attr_name.attr, + &dev_attr_class.attr, + &dev_attr_address.attr, + &dev_attr_features.attr, + &dev_attr_manufacturer.attr, + &dev_attr_hci_version.attr, + &dev_attr_hci_revision.attr, + &dev_attr_inquiry_cache.attr, + &dev_attr_idle_timeout.attr, + &dev_attr_sniff_max_interval.attr, + &dev_attr_sniff_min_interval.attr, NULL }; -static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct hci_conn *conn = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO"); -} - -static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct hci_conn *conn = dev_get_drvdata(dev); - bdaddr_t bdaddr; - baswap(&bdaddr, &conn->dst); - return sprintf(buf, "%s\n", batostr(&bdaddr)); -} - -static ssize_t show_conn_features(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct hci_conn *conn = dev_get_drvdata(dev); - - return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - conn->features[0], conn->features[1], - conn->features[2], conn->features[3], - conn->features[4], conn->features[5], - conn->features[6], conn->features[7]); -} - -#define CONN_ATTR(_name,_mode,_show,_store) \ -struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store) - -static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL); -static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL); -static CONN_ATTR(features, S_IRUGO, show_conn_features, NULL); - -static struct device_attribute *conn_attrs[] = { - &conn_attr_type, - &conn_attr_address, - &conn_attr_features, - NULL +static struct attribute_group bt_host_group = { + .attrs = bt_host_attrs, }; -struct class *bt_class = NULL; -EXPORT_SYMBOL_GPL(bt_class); - -static struct bus_type bt_bus = { - .name = "bluetooth", +static struct attribute_group *bt_host_groups[] = { + &bt_host_group, + NULL }; -static struct platform_device *bt_platform; - -static void bt_release(struct device *dev) +static void bt_host_release(struct device *dev) { void *data = dev_get_drvdata(dev); kfree(data); } -static void add_conn(struct work_struct *work) -{ - struct hci_conn *conn = container_of(work, struct hci_conn, work); - int i; - - flush_workqueue(btdelconn); - - if (device_add(&conn->dev) < 0) { - BT_ERR("Failed to register connection device"); - return; - } - - for (i = 0; conn_attrs[i]; i++) - if (device_create_file(&conn->dev, conn_attrs[i]) < 0) - BT_ERR("Failed to create connection attribute"); -} - -void hci_conn_add_sysfs(struct hci_conn *conn) -{ - struct hci_dev *hdev = conn->hdev; - - BT_DBG("conn %p", conn); - - conn->dev.bus = &bt_bus; - conn->dev.parent = &hdev->dev; - - conn->dev.release = bt_release; - - snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d", - hdev->name, conn->handle); - - dev_set_drvdata(&conn->dev, conn); - - device_initialize(&conn->dev); - - INIT_WORK(&conn->work, add_conn); - - queue_work(btaddconn, &conn->work); -} - -/* - * The rfcomm tty device will possibly retain even when conn - * is down, and sysfs doesn't support move zombie device, - * so we should move the device before conn device is destroyed. - */ -static int __match_tty(struct device *dev, void *data) -{ - return !strncmp(dev->bus_id, "rfcomm", 6); -} - -static void del_conn(struct work_struct *work) -{ - struct hci_conn *conn = container_of(work, struct hci_conn, work); - struct hci_dev *hdev = conn->hdev; - - while (1) { - struct device *dev; - - dev = device_find_child(&conn->dev, NULL, __match_tty); - if (!dev) - break; - device_move(dev, NULL); - put_device(dev); - } - - device_del(&conn->dev); - put_device(&conn->dev); - hci_dev_put(hdev); -} - -void hci_conn_del_sysfs(struct hci_conn *conn) -{ - BT_DBG("conn %p", conn); - - if (!device_is_registered(&conn->dev)) - return; - - INIT_WORK(&conn->work, del_conn); - - queue_work(btdelconn, &conn->work); -} +static struct device_type bt_host = { + .name = "host", + .groups = bt_host_groups, + .release = bt_host_release, +}; int hci_register_sysfs(struct hci_dev *hdev) { struct device *dev = &hdev->dev; - unsigned int i; int err; BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); - dev->bus = &bt_bus; + dev->type = &bt_host; + dev->class = bt_class; dev->parent = hdev->parent; strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE); - dev->release = bt_release; - dev_set_drvdata(dev, hdev); err = device_register(dev); if (err < 0) return err; - for (i = 0; bt_attrs[i]; i++) - if (device_create_file(dev, bt_attrs[i]) < 0) - BT_ERR("Failed to create device attribute"); - return 0; } @@ -410,59 +441,30 @@ void hci_unregister_sysfs(struct hci_dev *hdev) int __init bt_sysfs_init(void) { - int err; - btaddconn = create_singlethread_workqueue("btaddconn"); - if (!btaddconn) { - err = -ENOMEM; - goto out; - } + if (!btaddconn) + return -ENOMEM; btdelconn = create_singlethread_workqueue("btdelconn"); if (!btdelconn) { - err = -ENOMEM; - goto out_del; - } - - bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0); - if (IS_ERR(bt_platform)) { - err = PTR_ERR(bt_platform); - goto out_platform; + destroy_workqueue(btaddconn); + return -ENOMEM; } - err = bus_register(&bt_bus); - if (err < 0) - goto out_bus; - bt_class = class_create(THIS_MODULE, "bluetooth"); if (IS_ERR(bt_class)) { - err = PTR_ERR(bt_class); - goto out_class; + destroy_workqueue(btdelconn); + destroy_workqueue(btaddconn); + return PTR_ERR(bt_class); } return 0; - -out_class: - bus_unregister(&bt_bus); -out_bus: - platform_device_unregister(bt_platform); -out_platform: - destroy_workqueue(btdelconn); -out_del: - destroy_workqueue(btaddconn); -out: - return err; } void bt_sysfs_cleanup(void) { destroy_workqueue(btaddconn); - destroy_workqueue(btdelconn); class_destroy(bt_class); - - bus_unregister(&bt_bus); - - platform_device_unregister(bt_platform); } diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c1239852834..3396d5bdef1 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2516,7 +2516,7 @@ EXPORT_SYMBOL(l2cap_load); module_init(l2cap_init); module_exit(l2cap_exit); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 6cfc7ba611b..ba537fae0a4 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -2115,7 +2115,7 @@ MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel"); module_param(l2cap_mtu, uint, 0644); MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection"); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 8cda4987486..a16011fedc1 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1002,7 +1002,7 @@ module_exit(sco_exit); module_param(disable_esco, bool, 0644); MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation"); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/core/dev.c b/net/core/dev.c index 8d133802372..60c51f76588 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1990,7 +1990,9 @@ static void net_tx_action(struct softirq_action *h) qdisc_run(q); spin_unlock(root_lock); } else { - __netif_reschedule(q); + if (!test_bit(__QDISC_STATE_DEACTIVATED, + &q->state)) + __netif_reschedule(q); } } } diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index a89f32fa94f..57abe8266be 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -99,7 +99,7 @@ struct gen_estimator_head static struct gen_estimator_head elist[EST_MAX_INTERVAL+1]; -/* Protects against NULL dereference and RCU write-side */ +/* Protects against NULL dereference */ static DEFINE_RWLOCK(est_lock); static void est_timer(unsigned long arg) @@ -185,7 +185,6 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, est->last_packets = bstats->packets; est->avpps = rate_est->pps<<10; - write_lock_bh(&est_lock); if (!elist[idx].timer.function) { INIT_LIST_HEAD(&elist[idx].list); setup_timer(&elist[idx].timer, est_timer, idx); @@ -195,7 +194,6 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx)); list_add_rcu(&est->list, &elist[idx].list); - write_unlock_bh(&est_lock); return 0; } @@ -214,6 +212,7 @@ static void __gen_kill_estimator(struct rcu_head *head) * Removes the rate estimator specified by &bstats and &rate_est * and deletes the timer. * + * NOTE: Called under rtnl_mutex */ void gen_kill_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est) @@ -227,17 +226,17 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats, if (!elist[idx].timer.function) continue; - write_lock_bh(&est_lock); list_for_each_entry_safe(e, n, &elist[idx].list, list) { if (e->rate_est != rate_est || e->bstats != bstats) continue; + write_lock_bh(&est_lock); e->bstats = NULL; + write_unlock_bh(&est_lock); list_del_rcu(&e->list); call_rcu(&e->e_rcu, __gen_kill_estimator); } - write_unlock_bh(&est_lock); } } diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 3bca97f55d4..949772a5a7d 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -157,7 +157,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv) err = ieee80211_networks_allocate(ieee); if (err) { IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err); - goto failed; + goto failed_free_netdev; } ieee80211_networks_initialize(ieee); @@ -193,9 +193,9 @@ struct net_device *alloc_ieee80211(int sizeof_priv) return dev; - failed: - if (dev) - free_netdev(dev); +failed_free_netdev: + free_netdev(dev); +failed: return NULL; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 67ccce2a96b..f79a5160729 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3442,6 +3442,22 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, } } +static int tcp_parse_aligned_timestamp(struct tcp_sock *tp, struct tcphdr *th) +{ + __be32 *ptr = (__be32 *)(th + 1); + + if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) + | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { + tp->rx_opt.saw_tstamp = 1; + ++ptr; + tp->rx_opt.rcv_tsval = ntohl(*ptr); + ++ptr; + tp->rx_opt.rcv_tsecr = ntohl(*ptr); + return 1; + } + return 0; +} + /* Fast parse options. This hopes to only see timestamps. * If it is wrong it falls back on tcp_parse_options(). */ @@ -3453,16 +3469,8 @@ static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, return 0; } else if (tp->rx_opt.tstamp_ok && th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) { - __be32 *ptr = (__be32 *)(th + 1); - if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) - | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { - tp->rx_opt.saw_tstamp = 1; - ++ptr; - tp->rx_opt.rcv_tsval = ntohl(*ptr); - ++ptr; - tp->rx_opt.rcv_tsecr = ntohl(*ptr); + if (tcp_parse_aligned_timestamp(tp, th)) return 1; - } } tcp_parse_options(skb, &tp->rx_opt, 1); return 1; @@ -4161,6 +4169,18 @@ add_sack: } } +static struct sk_buff *tcp_collapse_one(struct sock *sk, struct sk_buff *skb, + struct sk_buff_head *list) +{ + struct sk_buff *next = skb->next; + + __skb_unlink(skb, list); + __kfree_skb(skb); + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOLLAPSED); + + return next; +} + /* Collapse contiguous sequence of skbs head..tail with * sequence numbers start..end. * Segments with FIN/SYN are not collapsed (only because this @@ -4178,11 +4198,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, for (skb = head; skb != tail;) { /* No new bits? It is possible on ofo queue. */ if (!before(start, TCP_SKB_CB(skb)->end_seq)) { - struct sk_buff *next = skb->next; - __skb_unlink(skb, list); - __kfree_skb(skb); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOLLAPSED); - skb = next; + skb = tcp_collapse_one(sk, skb, list); continue; } @@ -4246,11 +4262,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, start += size; } if (!before(start, TCP_SKB_CB(skb)->end_seq)) { - struct sk_buff *next = skb->next; - __skb_unlink(skb, list); - __kfree_skb(skb); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOLLAPSED); - skb = next; + skb = tcp_collapse_one(sk, skb, list); if (skb == tail || tcp_hdr(skb)->syn || tcp_hdr(skb)->fin) @@ -4691,6 +4703,67 @@ out: } #endif /* CONFIG_NET_DMA */ +/* Does PAWS and seqno based validation of an incoming segment, flags will + * play significant role here. + */ +static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, + struct tcphdr *th, int syn_inerr) +{ + struct tcp_sock *tp = tcp_sk(sk); + + /* RFC1323: H1. Apply PAWS check first. */ + if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && + tcp_paws_discard(sk, skb)) { + if (!th->rst) { + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); + tcp_send_dupack(sk, skb); + goto discard; + } + /* Reset is accepted even if it did not pass PAWS. */ + } + + /* Step 1: check sequence number */ + if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) { + /* RFC793, page 37: "In all states except SYN-SENT, all reset + * (RST) segments are validated by checking their SEQ-fields." + * And page 69: "If an incoming segment is not acceptable, + * an acknowledgment should be sent in reply (unless the RST + * bit is set, if so drop the segment and return)". + */ + if (!th->rst) + tcp_send_dupack(sk, skb); + goto discard; + } + + /* Step 2: check RST bit */ + if (th->rst) { + tcp_reset(sk); + goto discard; + } + + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + + /* step 3: check security and precedence [ignored] */ + + /* step 4: Check for a SYN in window. */ + if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { + if (syn_inerr) + TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); + tcp_reset(sk); + return -1; + } + + return 1; + +discard: + __kfree_skb(skb); + return 0; +} + /* * TCP receive function for the ESTABLISHED state. * @@ -4718,6 +4791,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, struct tcphdr *th, unsigned len) { struct tcp_sock *tp = tcp_sk(sk); + int res; /* * Header prediction. @@ -4756,19 +4830,10 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, /* Check timestamp */ if (tcp_header_len == sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) { - __be32 *ptr = (__be32 *)(th + 1); - /* No? Slow path! */ - if (*ptr != htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) - | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) + if (!tcp_parse_aligned_timestamp(tp, th)) goto slow_path; - tp->rx_opt.saw_tstamp = 1; - ++ptr; - tp->rx_opt.rcv_tsval = ntohl(*ptr); - ++ptr; - tp->rx_opt.rcv_tsecr = ntohl(*ptr); - /* If PAWS failed, check it more carefully in slow path */ if ((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) < 0) goto slow_path; @@ -4899,51 +4964,12 @@ slow_path: goto csum_error; /* - * RFC1323: H1. Apply PAWS check first. - */ - if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && - tcp_paws_discard(sk, skb)) { - if (!th->rst) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); - tcp_send_dupack(sk, skb); - goto discard; - } - /* Resets are accepted even if PAWS failed. - - ts_recent update must be made after we are sure - that the packet is in window. - */ - } - - /* * Standard slow path. */ - if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) { - /* RFC793, page 37: "In all states except SYN-SENT, all reset - * (RST) segments are validated by checking their SEQ-fields." - * And page 69: "If an incoming segment is not acceptable, - * an acknowledgment should be sent in reply (unless the RST bit - * is set, if so drop the segment and return)". - */ - if (!th->rst) - tcp_send_dupack(sk, skb); - goto discard; - } - - if (th->rst) { - tcp_reset(sk); - goto discard; - } - - tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); - - if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { - TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); - tcp_reset(sk); - return 1; - } + res = tcp_validate_incoming(sk, skb, th, 1); + if (res <= 0) + return -res; step5: if (th->ack) @@ -5225,6 +5251,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); int queued = 0; + int res; tp->rx_opt.saw_tstamp = 0; @@ -5277,42 +5304,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, return 0; } - if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && - tcp_paws_discard(sk, skb)) { - if (!th->rst) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); - tcp_send_dupack(sk, skb); - goto discard; - } - /* Reset is accepted even if it did not pass PAWS. */ - } - - /* step 1: check sequence number */ - if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) { - if (!th->rst) - tcp_send_dupack(sk, skb); - goto discard; - } - - /* step 2: check RST bit */ - if (th->rst) { - tcp_reset(sk); - goto discard; - } - - tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); - - /* step 3: check security and precedence [ignored] */ - - /* step 4: - * - * Check for a SYN in window. - */ - if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); - tcp_reset(sk); - return 1; - } + res = tcp_validate_incoming(sk, skb, th, 0); + if (res <= 0) + return -res; /* step 5: check the ACK field */ if (th->ack) { diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 297c257864c..6d2ad2bf3ab 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -66,13 +66,16 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) { struct net_device *dev; + struct ieee80211_sub_if_data *sdata; /* we're under RTNL */ dev = __dev_get_by_index(&init_net, ifindex); if (!dev) return -ENODEV; - ieee80211_if_remove(dev); + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + ieee80211_if_remove(sdata); return 0; } @@ -842,13 +845,13 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, return -ENOENT; } - err = mesh_path_add(dst, dev); + err = mesh_path_add(dst, sdata); if (err) { rcu_read_unlock(); return err; } - mpath = mesh_path_lookup(dst, dev); + mpath = mesh_path_lookup(dst, sdata); if (!mpath) { rcu_read_unlock(); return -ENXIO; @@ -862,10 +865,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst) { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + if (dst) - return mesh_path_del(dst, dev); + return mesh_path_del(dst, sdata); - mesh_path_flush(dev); + mesh_path_flush(sdata); return 0; } @@ -897,7 +902,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, return -ENOENT; } - mpath = mesh_path_lookup(dst, dev); + mpath = mesh_path_lookup(dst, sdata); if (!mpath) { rcu_read_unlock(); return -ENOENT; @@ -965,7 +970,7 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, return -ENOTSUPP; rcu_read_lock(); - mpath = mesh_path_lookup(dst, dev); + mpath = mesh_path_lookup(dst, sdata); if (!mpath) { rcu_read_unlock(); return -ENOENT; @@ -993,7 +998,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, return -ENOTSUPP; rcu_read_lock(); - mpath = mesh_path_lookup_by_idx(idx, dev); + mpath = mesh_path_lookup_by_idx(idx, sdata); if (!mpath) { rcu_read_unlock(); return -ENOENT; diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 79a062782d5..6abe5427752 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -201,7 +201,7 @@ static ssize_t sta_agg_status_write(struct file *file, tid_num = tid_num - 100; if (tid_static_rx[tid_num] == 1) { strcpy(state, "off "); - ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0, + ieee80211_sta_stop_rx_ba_session(sta->sdata, da, tid_num, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); sta->ampdu_mlme.tid_state_rx[tid_num] |= HT_AGG_STATE_DEBUGFS_CTL; diff --git a/net/mac80211/event.c b/net/mac80211/event.c index 2280f40b456..8de60de70bc 100644 --- a/net/mac80211/event.c +++ b/net/mac80211/event.c @@ -8,7 +8,6 @@ * mac80211 - events */ -#include <linux/netdevice.h> #include <net/iw_handler.h> #include "ieee80211_i.h" @@ -17,7 +16,7 @@ * (in the variable hdr) must be long enough to extract the TKIP * fields like TSC */ -void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, +void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, struct ieee80211_hdr *hdr) { union iwreq_data wrqu; @@ -32,7 +31,7 @@ void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, print_mac(mac, hdr->addr2)); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = strlen(buf); - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); + wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); kfree(buf); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ec59345af65..8361054fb7c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -32,14 +32,6 @@ /* ieee80211.o internal definitions, etc. These are not included into * low-level drivers. */ -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08) - -#define IEEE80211_FC(type, subtype) cpu_to_le16(type | subtype) - struct ieee80211_local; /* Maximum number of broadcast/multicast frames to buffer when some of the @@ -108,7 +100,7 @@ struct ieee80211_sta_bss { u64 timestamp; int beacon_int; - bool probe_resp; + unsigned long last_probe_resp; unsigned long last_update; /* during assocation, we save an ERP value from a probe response so @@ -174,7 +166,7 @@ struct ieee80211_tx_data { struct sk_buff **extra_frag; int num_extra_frag; - u16 fc, ethertype; + u16 ethertype; unsigned int flags; }; @@ -202,7 +194,7 @@ struct ieee80211_rx_data { struct ieee80211_rx_status *status; struct ieee80211_rate *rate; - u16 fc, ethertype; + u16 ethertype; unsigned int flags; int sent_ps_buffered; int queue; @@ -300,17 +292,35 @@ struct mesh_config { #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) +/* flags for MLME request*/ +#define IEEE80211_STA_REQ_SCAN 0 +#define IEEE80211_STA_REQ_DIRECT_PROBE 1 +#define IEEE80211_STA_REQ_AUTH 2 +#define IEEE80211_STA_REQ_RUN 3 + +/* flags used for setting mlme state */ +enum ieee80211_sta_mlme_state { + IEEE80211_STA_MLME_DISABLED, + IEEE80211_STA_MLME_DIRECT_PROBE, + IEEE80211_STA_MLME_AUTHENTICATE, + IEEE80211_STA_MLME_ASSOCIATE, + IEEE80211_STA_MLME_ASSOCIATED, + IEEE80211_STA_MLME_IBSS_SEARCH, + IEEE80211_STA_MLME_IBSS_JOINED, + IEEE80211_STA_MLME_MESH_UP +}; + +/* bitfield of allowed auth algs */ +#define IEEE80211_AUTH_ALG_OPEN BIT(0) +#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) +#define IEEE80211_AUTH_ALG_LEAP BIT(2) + struct ieee80211_if_sta { struct timer_list timer; struct work_struct work; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; - enum { - IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, - IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, - IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED, - IEEE80211_MESH_UP - } state; + enum ieee80211_sta_mlme_state state; size_t ssid_len; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; @@ -353,20 +363,17 @@ struct ieee80211_if_sta { struct sk_buff_head skb_queue; - int auth_tries, assoc_tries; + int assoc_scan_tries; /* number of scans done pre-association */ + int direct_probe_tries; /* retries for direct probes */ + int auth_tries; /* retries for auth req */ + int assoc_tries; /* retries for assoc req */ unsigned long request; unsigned long last_probe; unsigned int flags; -#define IEEE80211_STA_REQ_SCAN 0 -#define IEEE80211_STA_REQ_AUTH 1 -#define IEEE80211_STA_REQ_RUN 2 -#define IEEE80211_AUTH_ALG_OPEN BIT(0) -#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) -#define IEEE80211_AUTH_ALG_LEAP BIT(2) unsigned int auth_algs; /* bitfield of allowed auth algs */ int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ int auth_transaction; @@ -859,65 +866,65 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, /* ieee80211_ioctl.c */ extern const struct iw_handler_def ieee80211_iw_handler_def; -int ieee80211_set_freq(struct net_device *dev, int freq); +int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); /* ieee80211_sta.c */ void ieee80211_sta_timer(unsigned long data); void ieee80211_sta_work(struct work_struct *work); void ieee80211_sta_scan_work(struct work_struct *work); -void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); -int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len); -int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len); -int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid); -int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); -void ieee80211_sta_req_auth(struct net_device *dev, +int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); +int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); +int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); +int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); +void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); -int ieee80211_sta_scan_results(struct net_device *dev, +int ieee80211_sta_scan_results(struct ieee80211_local *local, struct iw_request_info *info, char *buf, size_t len); ieee80211_rx_result ieee80211_sta_rx_scan( - struct net_device *dev, struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); void ieee80211_rx_bss_list_init(struct ieee80211_local *local); void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); -int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); -struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len); +struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u8 *bssid, u8 *addr, u64 supp_rates); -int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); -int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); +int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); +int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed); -u32 ieee80211_reset_erp_info(struct net_device *dev); +u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_ht_info *ht_info); int ieee80211_ht_addt_info_ie_to_ht_bss_info( struct ieee80211_ht_addt_info *ht_add_info_ie, struct ieee80211_ht_bss_info *bss_info); -void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, +void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u8 dialog_token, u16 start_seq_num, u16 agg_size, u16 timeout); -void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, +void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u16 initiator, u16 reason_code); -void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn); +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); -void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, +void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, u16 initiator, u16 reason); void sta_addba_resp_timer_expired(unsigned long data); -void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr); +void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); u64 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band); -void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt); void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); #ifdef CONFIG_MAC80211_MESH -void ieee80211_start_mesh(struct net_device *dev); +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); #else -static inline void ieee80211_start_mesh(struct net_device *dev) +static inline void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) {} #endif @@ -928,7 +935,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct vif_params *params); int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, enum ieee80211_if_types type); -void ieee80211_if_remove(struct net_device *dev); +void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); void ieee80211_remove_interfaces(struct ieee80211_local *local); /* tx handling */ @@ -946,7 +953,7 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, enum ieee80211_if_types type); int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, int rate, int erp, int short_preamble); -void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, +void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, struct ieee80211_hdr *hdr); #ifdef CONFIG_MAC80211_NOINLINE diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 610ed1d9893..4a623b8e91f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -56,7 +56,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev) case IEEE80211_IF_TYPE_MESH_POINT: /* Allow compiler to elide mesh_rmc_free call. */ if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rmc_free(dev); + mesh_rmc_free(sdata); /* fall through */ case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: @@ -241,15 +241,13 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, return ret; } -void ieee80211_if_remove(struct net_device *dev) +void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - ASSERT_RTNL(); list_del_rcu(&sdata->list); synchronize_rcu(); - unregister_netdevice(dev); + unregister_netdevice(sdata->dev); } /* diff --git a/net/mac80211/main.c b/net/mac80211/main.c index aa5a191598c..398ca66bdfc 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -187,9 +187,15 @@ static int ieee80211_open(struct net_device *dev) u32 changed = 0; int res; bool need_hw_reconfig = 0; + u8 null_addr[ETH_ALEN] = {0}; sdata = IEEE80211_DEV_TO_SUB_IF(dev); + /* fail early if user set an invalid address */ + if (compare_ether_addr(dev->dev_addr, null_addr) && + !is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + /* we hold the RTNL here so can safely walk the list */ list_for_each_entry(nsdata, &local->interfaces, list) { struct net_device *ndev = nsdata->dev; @@ -270,6 +276,36 @@ static int ieee80211_open(struct net_device *dev) ieee80211_led_radio(local, local->hw.conf.radio_enabled); } + /* + * Check all interfaces and copy the hopefully now-present + * MAC address to those that have the special null one. + */ + list_for_each_entry(nsdata, &local->interfaces, list) { + struct net_device *ndev = nsdata->dev; + + /* + * No need to check netif_running since we do not allow + * it to start up with this invalid address. + */ + if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) + memcpy(ndev->dev_addr, + local->hw.wiphy->perm_addr, + ETH_ALEN); + } + + if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) + memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, + ETH_ALEN); + + /* + * Validate the MAC address for this device. + */ + if (!is_valid_ether_addr(dev->dev_addr)) { + if (!local->open_count && local->ops->stop) + local->ops->stop(local_to_hw(local)); + return -EADDRNOTAVAIL; + } + switch (sdata->vif.type) { case IEEE80211_IF_TYPE_VLAN: /* no need to tell driver */ @@ -311,8 +347,8 @@ static int ieee80211_open(struct net_device *dev) goto err_stop; if (ieee80211_vif_is_mesh(&sdata->vif)) - ieee80211_start_mesh(sdata->dev); - changed |= ieee80211_reset_erp_info(dev); + ieee80211_start_mesh(sdata); + changed |= ieee80211_reset_erp_info(sdata); ieee80211_bss_info_change_notify(sdata, changed); ieee80211_enable_keys(sdata); @@ -412,7 +448,7 @@ static int ieee80211_stop(struct net_device *dev) list_for_each_entry_rcu(sta, &local->sta_list, list) { if (sta->sdata == sdata) - ieee80211_sta_tear_down_BA_sessions(dev, sta->addr); + ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); } rcu_read_unlock(); @@ -503,7 +539,7 @@ static int ieee80211_stop(struct net_device *dev) /* fall through */ case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: - sdata->u.sta.state = IEEE80211_DISABLED; + sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; memset(sdata->u.sta.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.sta.timer); /* @@ -670,7 +706,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; - ieee80211_send_addba_request(sta->sdata->dev, ra, tid, + ieee80211_send_addba_request(sta->sdata, ra, tid, sta->ampdu_mlme.tid_tx[tid]->dialog_token, sta->ampdu_mlme.tid_tx[tid]->ssn, 0x40, 5000); @@ -853,7 +889,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) } if (*state & HT_AGG_STATE_INITIATOR_MSK) - ieee80211_send_delba(sta->sdata->dev, ra, tid, + ieee80211_send_delba(sta->sdata, ra, tid, WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); agg_queue = sta->tid_to_tx_q[tid]; @@ -975,6 +1011,8 @@ void ieee80211_if_setup(struct net_device *dev) dev->open = ieee80211_open; dev->stop = ieee80211_stop; dev->destructor = free_netdev; + /* we will validate the address ourselves in ->open */ + dev->validate_addr = NULL; } /* everything else */ @@ -1162,10 +1200,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, changed); } -u32 ieee80211_reset_erp_info(struct net_device *dev) +u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - sdata->bss_conf.use_cts_prot = 0; sdata->bss_conf.use_short_preamble = 0; return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; @@ -1244,9 +1280,10 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, struct ieee80211_key *key, struct sk_buff *skb) { - int hdrlen, iv_len, mic_len; + unsigned int hdrlen, iv_len, mic_len; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (!key) goto no_key; @@ -1268,24 +1305,20 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, goto no_key; } - if (skb->len >= mic_len && + if (skb->len >= hdrlen + mic_len && !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) skb_trim(skb, skb->len - mic_len); - if (skb->len >= iv_len && skb->len > hdrlen) { + if (skb->len >= hdrlen + iv_len) { memmove(skb->data + iv_len, skb->data, hdrlen); - skb_pull(skb, iv_len); + hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); } no_key: - { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc = le16_to_cpu(hdr->frame_control); - if ((fc & 0x8C) == 0x88) /* QoS Control Field */ { - fc &= ~IEEE80211_STYPE_QOS_DATA; - hdr->frame_control = cpu_to_le16(fc); - memmove(skb->data + 2, skb->data, hdrlen - 2); - skb_pull(skb, 2); - } + if (ieee80211_is_data_qos(hdr->frame_control)) { + hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); + memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, + hdrlen - IEEE80211_QOS_CTL_LEN); + skb_pull(skb, IEEE80211_QOS_CTL_LEN); } } @@ -1403,7 +1436,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) tid = qc[0] & 0xf; ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) & IEEE80211_SCTL_SEQ); - ieee80211_send_bar(sta->sdata->dev, hdr->addr1, + ieee80211_send_bar(sta->sdata, hdr->addr1, tid, ssn); } } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b5933b27149..b631703bcc8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -39,14 +39,13 @@ void ieee80211s_stop(void) * mesh_matches_local - check if the config of a mesh point matches ours * * @ie: information elements of a management frame from the mesh peer - * @dev: local mesh interface + * @sdata: local mesh subif * * This function checks if the mesh configuration of a mesh point matches the * local mesh configuration, i.e. if both nodes belong to the same mesh network. */ -bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) +bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *sta = &sdata->u.sta; /* @@ -73,10 +72,8 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links * * @ie: information elements of a management frame from the mesh peer - * @dev: local mesh interface */ -bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, - struct net_device *dev) +bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) { return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0; } @@ -111,9 +108,8 @@ void mesh_ids_set_default(struct ieee80211_if_sta *sta) memcpy(sta->mesh_cc_id, def_id, 4); } -int mesh_rmc_init(struct net_device *dev) +int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int i; sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); @@ -125,9 +121,8 @@ int mesh_rmc_init(struct net_device *dev) return 0; } -void mesh_rmc_free(struct net_device *dev) +void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_rmc *rmc = sdata->u.sta.rmc; struct rmc_entry *p, *n; int i; @@ -158,9 +153,8 @@ void mesh_rmc_free(struct net_device *dev) * it. */ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, - struct net_device *dev) + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_rmc *rmc = sdata->u.sta.rmc; u32 seqnum = 0; int entries = 0; @@ -194,10 +188,9 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, return 0; } -void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) +void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; u8 *pos; int len, i, rate; @@ -262,10 +255,10 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) return; } -u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl) +u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) { /* Use last four bytes of hw addr and interface index as hash index */ - return jhash_2words(*(u32 *)(addr+2), dev->ifindex, tbl->hash_rnd) + return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) & tbl->hash_mask; } @@ -434,7 +427,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ifsta->preq_id = 0; ifsta->dsn = 0; atomic_set(&ifsta->mpaths, 0); - mesh_rmc_init(sdata->dev); + mesh_rmc_init(sdata); ifsta->last_preq = jiffies; /* Allocate all mesh structures when creating the first mesh interface. */ if (!mesh_allocated) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 7495fbb0d21..84ff5d828fd 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -47,7 +47,7 @@ enum mesh_path_flags { * struct mesh_path - mac80211 mesh path structure * * @dst: mesh path destination mac address - * @dev: mesh path device + * @sdata: mesh subif * @next_hop: mesh neighbor to which frames for this destination will be * forwarded * @timer: mesh path discovery timer @@ -64,14 +64,14 @@ enum mesh_path_flags { * @state_lock: mesh pat state lock * * - * The combination of dst and dev is unique in the mesh path table. Since the + * The combination of dst and sdata is unique in the mesh path table. Since the * next_hop STA is only protected by RCU as well, deleting the STA must also * remove/substitute the mesh_path structure and wait until that is no longer * reachable before destroying the STA completely. */ struct mesh_path { u8 dst[ETH_ALEN]; - struct net_device *dev; + struct ieee80211_sub_if_data *sdata; struct sta_info *next_hop; struct timer_list timer; struct sk_buff_head frame_queue; @@ -203,59 +203,66 @@ int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, struct ieee80211_sub_if_data *sdata); int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, - struct net_device *dev); -bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev); + struct ieee80211_sub_if_data *sdata); +bool mesh_matches_local(struct ieee802_11_elems *ie, + struct ieee80211_sub_if_data *sdata); void mesh_ids_set_default(struct ieee80211_if_sta *sta); -void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev); -void mesh_rmc_free(struct net_device *dev); -int mesh_rmc_init(struct net_device *dev); +void mesh_mgmt_ies_add(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); +int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); void ieee80211s_init(void); void ieee80211s_stop(void); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); /* Mesh paths */ -int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev); -void mesh_path_start_discovery(struct net_device *dev); -struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); -struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); +int mesh_nexthop_lookup(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); +struct mesh_path *mesh_path_lookup(u8 *dst, + struct ieee80211_sub_if_data *sdata); +struct mesh_path *mesh_path_lookup_by_idx(int idx, + struct ieee80211_sub_if_data *sdata); void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); -void mesh_path_expire(struct net_device *dev); -void mesh_path_flush(struct net_device *dev); -void mesh_rx_path_sel_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, - size_t len); -int mesh_path_add(u8 *dst, struct net_device *dev); +void mesh_path_expire(struct ieee80211_sub_if_data *sdata); +void mesh_path_flush(struct ieee80211_sub_if_data *sdata); +void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len); +int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); /* Mesh plinks */ -void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, - bool add); -bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, - struct net_device *dev); +void mesh_neighbour_update(u8 *hw_addr, u64 rates, + struct ieee80211_sub_if_data *sdata, bool add); +bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); void mesh_plink_broken(struct sta_info *sta); void mesh_plink_deactivate(struct sta_info *sta); int mesh_plink_open(struct sta_info *sta); int mesh_plink_close(struct sta_info *sta); void mesh_plink_block(struct sta_info *sta); -void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, - size_t len, struct ieee80211_rx_status *rx_status); +void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len, + struct ieee80211_rx_status *rx_status); /* Private interfaces */ /* Mesh tables */ struct mesh_table *mesh_table_alloc(int size_order); void mesh_table_free(struct mesh_table *tbl, bool free_leafs); struct mesh_table *mesh_table_grow(struct mesh_table *tbl); -u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl); +u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, + struct mesh_table *tbl); /* Mesh paths */ int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra, - struct net_device *dev); + struct ieee80211_sub_if_data *sdata); void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); void mesh_path_flush_pending(struct mesh_path *mpath); void mesh_path_tx_pending(struct mesh_path *mpath); int mesh_pathtbl_init(void); void mesh_pathtbl_unregister(void); -int mesh_path_del(u8 *addr, struct net_device *dev); +int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); void mesh_path_timer(unsigned long data); void mesh_path_flush_by_nexthop(struct sta_info *sta); -void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev); +void mesh_path_discard_frame(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); #ifdef CONFIG_MAC80211_MESH extern int mesh_allocated; diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 08aca446ca0..eeb0ce2d5d3 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -82,9 +82,9 @@ enum mpath_frame_type { static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime, - __le32 metric, __le32 preq_id, struct net_device *dev) + __le32 metric, __le32 preq_id, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); struct ieee80211_mgmt *mgmt; u8 *pos; @@ -99,11 +99,11 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; mgmt->u.action.u.mesh_action.action_code = action; @@ -149,7 +149,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return 0; } @@ -161,9 +161,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, * @ra: node this frame is addressed to */ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, - struct net_device *dev) + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); struct ieee80211_mgmt *mgmt; u8 *pos; @@ -178,11 +178,11 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); memcpy(mgmt->da, ra, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; mgmt->u.action.u.mesh_action.action_code = MPATH_PERR; @@ -198,7 +198,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return 0; } @@ -233,7 +233,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, /** * hwmp_route_info_get - Update routing info to originator and transmitter * - * @dev: local mesh interface + * @sdata: local mesh subif * @mgmt: mesh management frame * @hwmp_ie: hwmp information element (PREP or PREQ) * @@ -246,11 +246,11 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, * Notes: this function is the only place (besides user-provided info) where * path routing information is updated. */ -static u32 hwmp_route_info_get(struct net_device *dev, +static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *hwmp_ie) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct mesh_path *mpath; struct sta_info *sta; bool fresh_info; @@ -301,14 +301,14 @@ static u32 hwmp_route_info_get(struct net_device *dev, new_metric = MAX_METRIC; exp_time = TU_TO_EXP_TIME(orig_lifetime); - if (memcmp(orig_addr, dev->dev_addr, ETH_ALEN) == 0) { + if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { /* This MP is the originator, we are not interested in this * frame, except for updating transmitter's path info. */ process = false; fresh_info = false; } else { - mpath = mesh_path_lookup(orig_addr, dev); + mpath = mesh_path_lookup(orig_addr, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_FIXED) @@ -324,8 +324,8 @@ static u32 hwmp_route_info_get(struct net_device *dev, } } } else { - mesh_path_add(orig_addr, dev); - mpath = mesh_path_lookup(orig_addr, dev); + mesh_path_add(orig_addr, sdata); + mpath = mesh_path_lookup(orig_addr, sdata); if (!mpath) { rcu_read_unlock(); return 0; @@ -357,7 +357,7 @@ static u32 hwmp_route_info_get(struct net_device *dev, else { fresh_info = true; - mpath = mesh_path_lookup(ta, dev); + mpath = mesh_path_lookup(ta, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if ((mpath->flags & MESH_PATH_FIXED) || @@ -365,8 +365,8 @@ static u32 hwmp_route_info_get(struct net_device *dev, (last_hop_metric > mpath->metric))) fresh_info = false; } else { - mesh_path_add(ta, dev); - mpath = mesh_path_lookup(ta, dev); + mesh_path_add(ta, sdata); + mpath = mesh_path_lookup(ta, sdata); if (!mpath) { rcu_read_unlock(); return 0; @@ -392,10 +392,9 @@ static u32 hwmp_route_info_get(struct net_device *dev, return process ? new_metric : 0; } -static void hwmp_preq_frame_process(struct net_device *dev, +static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *preq_elem, u32 metric) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct mesh_path *mpath; u8 *dst_addr, *orig_addr; @@ -411,7 +410,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, orig_dsn = PREQ_IE_ORIG_DSN(preq_elem); dst_flags = PREQ_IE_DST_F(preq_elem); - if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) { + if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { forward = false; reply = true; metric = 0; @@ -423,7 +422,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, } } else { rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) { if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || DSN_LT(mpath->dsn, dst_dsn)) { @@ -451,7 +450,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, cpu_to_le32(dst_dsn), 0, orig_addr, cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), - 0, dev); + 0, sdata); else ifsta->mshstats.dropped_frames_ttl++; } @@ -472,20 +471,19 @@ static void hwmp_preq_frame_process(struct net_device *dev, hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, cpu_to_le32(orig_dsn), dst_flags, dst_addr, - cpu_to_le32(dst_dsn), dev->broadcast, + cpu_to_le32(dst_dsn), sdata->dev->broadcast, hopcount, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), cpu_to_le32(preq_id), - dev); + sdata); ifsta->mshstats.fwded_frames++; } } -static void hwmp_prep_frame_process(struct net_device *dev, +static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *prep_elem, u32 metric) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_path *mpath; u8 *dst_addr, *orig_addr; u8 ttl, hopcount, flags; @@ -499,7 +497,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, * replies */ dst_addr = PREP_IE_DST_ADDR(prep_elem); - if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) + if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) /* destination, no forwarding required */ return; @@ -510,7 +508,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, } rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) spin_lock_bh(&mpath->state_lock); else @@ -533,7 +531,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, cpu_to_le32(orig_dsn), 0, dst_addr, cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), - 0, dev); + 0, sdata); rcu_read_unlock(); sdata->u.sta.mshstats.fwded_frames++; return; @@ -544,7 +542,7 @@ fail: return; } -static void hwmp_perr_frame_process(struct net_device *dev, +static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *perr_elem) { struct mesh_path *mpath; @@ -555,7 +553,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, dst_addr = PERR_IE_DST_ADDR(perr_elem); dst_dsn = PERR_IE_DST_DSN(perr_elem); rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_ACTIVE && @@ -566,7 +564,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, mpath->dsn = dst_dsn; spin_unlock_bh(&mpath->state_lock); mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn), - dev->broadcast, dev); + sdata->dev->broadcast, sdata); } else spin_unlock_bh(&mpath->state_lock); } @@ -575,7 +573,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, -void mesh_rx_path_sel_frame(struct net_device *dev, +void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { @@ -592,25 +590,25 @@ void mesh_rx_path_sel_frame(struct net_device *dev, if (!elems.preq || elems.preq_len != 37) /* Right now we support just 1 destination and no AE */ return; - last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.preq); + last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq); if (!last_hop_metric) return; - hwmp_preq_frame_process(dev, mgmt, elems.preq, last_hop_metric); + hwmp_preq_frame_process(sdata, mgmt, elems.preq, last_hop_metric); break; case MPATH_PREP: if (!elems.prep || elems.prep_len != 31) /* Right now we support no AE */ return; - last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.prep); + last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep); if (!last_hop_metric) return; - hwmp_prep_frame_process(dev, mgmt, elems.prep, last_hop_metric); + hwmp_prep_frame_process(sdata, mgmt, elems.prep, last_hop_metric); break; case MPATH_PERR: if (!elems.perr || elems.perr_len != 12) /* Right now we support only one destination per PERR */ return; - hwmp_perr_frame_process(dev, mgmt, elems.perr); + hwmp_perr_frame_process(sdata, mgmt, elems.perr); default: return; } @@ -628,8 +626,7 @@ void mesh_rx_path_sel_frame(struct net_device *dev, */ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) { - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(mpath->dev); + struct ieee80211_sub_if_data *sdata = mpath->sdata; struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct mesh_preq_queue *preq_node; @@ -672,12 +669,10 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) /** * mesh_path_start_discovery - launch a path discovery from the PREQ queue * - * @dev: local mesh interface + * @sdata: local mesh subif */ -void mesh_path_start_discovery(struct net_device *dev) +void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct mesh_preq_queue *preq_node; struct mesh_path *mpath; @@ -699,7 +694,7 @@ void mesh_path_start_discovery(struct net_device *dev) spin_unlock(&ifsta->mesh_preq_queue_lock); rcu_read_lock(); - mpath = mesh_path_lookup(preq_node->dst, dev); + mpath = mesh_path_lookup(preq_node->dst, sdata); if (!mpath) goto enddiscovery; @@ -743,11 +738,11 @@ void mesh_path_start_discovery(struct net_device *dev) dst_flags = MP_F_RF; spin_unlock_bh(&mpath->state_lock); - mesh_path_sel_frame_tx(MPATH_PREQ, 0, dev->dev_addr, + mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, - cpu_to_le32(mpath->dsn), dev->broadcast, 0, + cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, ttl, cpu_to_le32(lifetime), 0, - cpu_to_le32(ifsta->preq_id++), dev); + cpu_to_le32(ifsta->preq_id++), sdata); mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); enddiscovery: @@ -759,7 +754,7 @@ enddiscovery: * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame * * @skb: 802.11 frame to be sent - * @dev: network device the frame will be sent through + * @sdata: network subif the frame will be sent through * @fwd_frame: true if this frame was originally from a different host * * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is @@ -767,9 +762,9 @@ enddiscovery: * sent when the path is resolved. This means the caller must not free the skb * in this case. */ -int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) +int mesh_nexthop_lookup(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sk_buff *skb_to_free = NULL; struct mesh_path *mpath; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; @@ -777,11 +772,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) int err = 0; rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (!mpath) { - mesh_path_add(dst_addr, dev); - mpath = mesh_path_lookup(dst_addr, dev); + mesh_path_add(dst_addr, sdata); + mpath = mesh_path_lookup(dst_addr, sdata); if (!mpath) { dev_kfree_skb(skb); sdata->u.sta.mshstats.dropped_frames_no_route++; @@ -793,7 +788,8 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) if (mpath->flags & MESH_PATH_ACTIVE) { if (time_after(jiffies, mpath->exp_time - msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) - && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN) + && !memcmp(sdata->dev->dev_addr, hdr->addr4, + ETH_ALEN) && !(mpath->flags & MESH_PATH_RESOLVING) && !(mpath->flags & MESH_PATH_FIXED)) { mesh_queue_preq(mpath, @@ -815,7 +811,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) skb_queue_tail(&mpath->frame_queue, skb); if (skb_to_free) - mesh_path_discard_frame(skb_to_free, dev); + mesh_path_discard_frame(skb_to_free, sdata); err = -ENOENT; } @@ -835,7 +831,7 @@ void mesh_path_timer(unsigned long data) if (!mpath) goto endmpathtimer; spin_lock_bh(&mpath->state_lock); - sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); + sdata = mpath->sdata; if (mpath->flags & MESH_PATH_RESOLVED || (!(mpath->flags & MESH_PATH_RESOLVING))) mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 838ee60492a..0a60f55f32a 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -9,7 +9,6 @@ #include <linux/etherdevice.h> #include <linux/list.h> -#include <linux/netdevice.h> #include <linux/random.h> #include <linux/spinlock.h> #include <linux/string.h> @@ -62,13 +61,13 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) /** * mesh_path_lookup - look up a path in the mesh path table * @dst: hardware address (ETH_ALEN length) of destination - * @dev: local interface + * @sdata: local subif * * Returns: pointer to the mesh path structure, or NULL if not found * * Locking: must be called within a read rcu section. */ -struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) +struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct hlist_node *n; @@ -78,10 +77,10 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) tbl = rcu_dereference(mesh_paths); - bucket = &tbl->hash_buckets[mesh_table_hash(dst, dev, tbl)]; + bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; hlist_for_each_entry_rcu(node, n, bucket, list) { mpath = node->mpath; - if (mpath->dev == dev && + if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) { if (MPATH_EXPIRED(mpath)) { spin_lock_bh(&mpath->state_lock); @@ -98,13 +97,13 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) /** * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index * @idx: index - * @dev: local interface, or NULL for all entries + * @sdata: local subif, or NULL for all entries * * Returns: pointer to the mesh path structure, or NULL if not found. * * Locking: must be called within a read rcu section. */ -struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) +struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata) { struct mpath_node *node; struct hlist_node *p; @@ -112,7 +111,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) int j = 0; for_each_mesh_entry(mesh_paths, p, node, i) { - if (dev && node->mpath->dev != dev) + if (sdata && node->mpath->sdata != sdata) continue; if (j++ == idx) { if (MPATH_EXPIRED(node->mpath)) { @@ -131,15 +130,14 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) /** * mesh_path_add - allocate and add a new path to the mesh path table * @addr: destination address of the path (ETH_ALEN length) - * @dev: local interface + * @sdata: local subif * * Returns: 0 on sucess * * State: the initial state of the new path is set to 0 */ -int mesh_path_add(u8 *dst, struct net_device *dev) +int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_path *mpath, *new_mpath; struct mpath_node *node, *new_node; struct hlist_head *bucket; @@ -148,7 +146,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) int err = 0; u32 hash_idx; - if (memcmp(dst, dev->dev_addr, ETH_ALEN) == 0) + if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) /* never add ourselves as neighbours */ return -ENOTSUPP; @@ -169,7 +167,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) read_lock(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); - new_mpath->dev = dev; + new_mpath->sdata = sdata; new_mpath->flags = 0; skb_queue_head_init(&new_mpath->frame_queue); new_node->mpath = new_mpath; @@ -179,7 +177,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) spin_lock_init(&new_mpath->state_lock); init_timer(&new_mpath->timer); - hash_idx = mesh_table_hash(dst, dev, mesh_paths); + hash_idx = mesh_table_hash(dst, sdata, mesh_paths); bucket = &mesh_paths->hash_buckets[hash_idx]; spin_lock(&mesh_paths->hashwlock[hash_idx]); @@ -187,7 +185,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) err = -EEXIST; hlist_for_each_entry(node, n, bucket, list) { mpath = node->mpath; - if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN) == 0) + if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) goto err_exists; } @@ -241,7 +239,7 @@ void mesh_plink_broken(struct sta_info *sta) struct mesh_path *mpath; struct mpath_node *node; struct hlist_node *p; - struct net_device *dev = sta->sdata->dev; + struct ieee80211_sub_if_data *sdata = sta->sdata; int i; rcu_read_lock(); @@ -256,7 +254,7 @@ void mesh_plink_broken(struct sta_info *sta) spin_unlock_bh(&mpath->state_lock); mesh_path_error_tx(mpath->dst, cpu_to_le32(mpath->dsn), - dev->broadcast, dev); + sdata->dev->broadcast, sdata); } else spin_unlock_bh(&mpath->state_lock); } @@ -284,11 +282,11 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) for_each_mesh_entry(mesh_paths, p, node, i) { mpath = node->mpath; if (mpath->next_hop == sta) - mesh_path_del(mpath->dst, mpath->dev); + mesh_path_del(mpath->dst, mpath->sdata); } } -void mesh_path_flush(struct net_device *dev) +void mesh_path_flush(struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct mpath_node *node; @@ -297,16 +295,15 @@ void mesh_path_flush(struct net_device *dev) for_each_mesh_entry(mesh_paths, p, node, i) { mpath = node->mpath; - if (mpath->dev == dev) - mesh_path_del(mpath->dst, mpath->dev); + if (mpath->sdata == sdata) + mesh_path_del(mpath->dst, mpath->sdata); } } static void mesh_path_node_reclaim(struct rcu_head *rp) { struct mpath_node *node = container_of(rp, struct mpath_node, rcu); - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(node->mpath->dev); + struct ieee80211_sub_if_data *sdata = node->mpath->sdata; del_timer_sync(&node->mpath->timer); atomic_dec(&sdata->u.sta.mpaths); @@ -318,11 +315,11 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) * mesh_path_del - delete a mesh path from the table * * @addr: dst address (ETH_ALEN length) - * @dev: local interface + * @sdata: local subif * * Returns: 0 if succesful */ -int mesh_path_del(u8 *addr, struct net_device *dev) +int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct mpath_node *node; @@ -332,13 +329,13 @@ int mesh_path_del(u8 *addr, struct net_device *dev) int err = 0; read_lock(&pathtbl_resize_lock); - hash_idx = mesh_table_hash(addr, dev, mesh_paths); + hash_idx = mesh_table_hash(addr, sdata, mesh_paths); bucket = &mesh_paths->hash_buckets[hash_idx]; spin_lock(&mesh_paths->hashwlock[hash_idx]); hlist_for_each_entry(node, n, bucket, list) { mpath = node->mpath; - if (mpath->dev == dev && + if (mpath->sdata == sdata && memcmp(addr, mpath->dst, ETH_ALEN) == 0) { spin_lock_bh(&mpath->state_lock); mpath->flags |= MESH_PATH_RESOLVING; @@ -378,29 +375,29 @@ void mesh_path_tx_pending(struct mesh_path *mpath) * mesh_path_discard_frame - discard a frame whose path could not be resolved * * @skb: frame to discard - * @dev: network device the frame was to be sent through + * @sdata: network subif the frame was to be sent through * * If the frame was beign forwarded from another MP, a PERR frame will be sent * to the precursor. * * Locking: the function must me called within a rcu_read_lock region */ -void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) +void mesh_path_discard_frame(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct mesh_path *mpath; u32 dsn = 0; - if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) { + if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) { u8 *ra, *da; da = hdr->addr3; ra = hdr->addr2; - mpath = mesh_path_lookup(da, dev); + mpath = mesh_path_lookup(da, sdata); if (mpath) dsn = ++mpath->dsn; - mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, dev); + mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, sdata); } kfree_skb(skb); @@ -416,14 +413,11 @@ void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) */ void mesh_path_flush_pending(struct mesh_path *mpath) { - struct ieee80211_sub_if_data *sdata; struct sk_buff *skb; - sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); - while ((skb = skb_dequeue(&mpath->frame_queue)) && (mpath->flags & MESH_PATH_ACTIVE)) - mesh_path_discard_frame(skb, mpath->dev); + mesh_path_discard_frame(skb, mpath->sdata); } /** @@ -472,7 +466,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) node = hlist_entry(p, struct mpath_node, list); mpath = node->mpath; new_node->mpath = mpath; - hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); + hash_idx = mesh_table_hash(mpath->dst, mpath->sdata, newtbl); hlist_add_head(&new_node->list, &newtbl->hash_buckets[hash_idx]); return 0; @@ -489,7 +483,7 @@ int mesh_pathtbl_init(void) return 0; } -void mesh_path_expire(struct net_device *dev) +void mesh_path_expire(struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct mpath_node *node; @@ -498,7 +492,7 @@ void mesh_path_expire(struct net_device *dev) read_lock(&pathtbl_resize_lock); for_each_mesh_entry(mesh_paths, p, node, i) { - if (node->mpath->dev != dev) + if (node->mpath->sdata != sdata) continue; mpath = node->mpath; spin_lock_bh(&mpath->state_lock); @@ -507,7 +501,7 @@ void mesh_path_expire(struct net_device *dev) time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) { spin_unlock_bh(&mpath->state_lock); - mesh_path_del(mpath->dst, mpath->dev); + mesh_path_del(mpath->dst, mpath->sdata); } else spin_unlock_bh(&mpath->state_lock); } diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 9efeb1f0702..7714b0e6e4d 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -144,10 +144,10 @@ void mesh_plink_deactivate(struct sta_info *sta) spin_unlock_bh(&sta->lock); } -static int mesh_plink_frame_tx(struct net_device *dev, +static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, __le16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); struct ieee80211_mgmt *mgmt; bool include_plid = false; @@ -163,10 +163,10 @@ static int mesh_plink_frame_tx(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = PLINK_CATEGORY; mgmt->u.action.u.plink_action.action_code = action; @@ -180,7 +180,7 @@ static int mesh_plink_frame_tx(struct net_device *dev, /* two-byte status code followed by two-byte AID */ memset(pos, 0, 4); } - mesh_mgmt_ies_add(skb, dev); + mesh_mgmt_ies_add(skb, sdata); } /* Add Peer Link Management element */ @@ -217,15 +217,14 @@ static int mesh_plink_frame_tx(struct net_device *dev, memcpy(pos, &reason, 2); } - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return 0; } -void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, +void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data *sdata, bool peer_accepting_plinks) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; rcu_read_lock(); @@ -257,7 +256,6 @@ static void mesh_plink_timer(unsigned long data) { struct sta_info *sta; __le16 llid, plid, reason; - struct net_device *dev = NULL; struct ieee80211_sub_if_data *sdata; #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG DECLARE_MAC_BUF(mac); @@ -282,7 +280,6 @@ static void mesh_plink_timer(unsigned long data) llid = sta->llid; plid = sta->plid; sdata = sta->sdata; - dev = sdata->dev; switch (sta->plink_state) { case PLINK_OPN_RCVD: @@ -299,7 +296,7 @@ static void mesh_plink_timer(unsigned long data) ++sta->plink_retries; mod_plink_timer(sta, sta->plink_timeout); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid, 0, 0); break; } @@ -312,7 +309,7 @@ static void mesh_plink_timer(unsigned long data) sta->plink_state = PLINK_HOLDING; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case PLINK_HOLDING: @@ -357,7 +354,7 @@ int mesh_plink_open(struct sta_info *sta) mpl_dbg("Mesh plink: starting establishment with %s\n", print_mac(mac, sta->addr)); - return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN, + return mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid, 0, 0); } @@ -403,15 +400,14 @@ int mesh_plink_close(struct sta_info *sta) llid = sta->llid; plid = sta->plid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); return 0; } -void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, +void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct ieee802_11_elems elems; struct sta_info *sta; @@ -478,7 +474,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, /* Now we will figure out the appropriate event... */ event = PLINK_UNDEFINED; - if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) { + if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { switch (ftype) { case PLINK_OPEN: event = OPN_RJCT; @@ -577,9 +573,9 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, sta->llid = llid; mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid, 0, 0); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; default: @@ -604,7 +600,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case OPN_ACPT: @@ -613,7 +609,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, sta->plid = plid; llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; case CNF_ACPT: @@ -646,13 +642,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; case CNF_ACPT: @@ -685,7 +681,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case OPN_ACPT: @@ -695,7 +691,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, spin_unlock_bh(&sta->lock); mpl_dbg("Mesh plink with %s ESTABLISHED\n", print_mac(mac, sta->addr)); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; default: @@ -714,13 +710,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; default: @@ -743,7 +739,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; reason = sta->reason; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; default: diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1e97fb9fb34..84999791a33 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -34,6 +34,7 @@ #include "led.h" #include "mesh.h" +#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 #define IEEE80211_AUTH_TIMEOUT (HZ / 5) #define IEEE80211_AUTH_MAX_TRIES 3 #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) @@ -73,19 +74,19 @@ #define IEEE80211_MIN_AMPDU_BUF 0x8 #define IEEE80211_MAX_AMPDU_BUF 0x40 -static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, +static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len); static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len); static void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_sta_bss *bss); -static int ieee80211_sta_find_ibss(struct net_device *dev, +static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); -static int ieee80211_sta_wep_configured(struct net_device *dev); -static int ieee80211_sta_start_scan(struct net_device *dev, +static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata); +static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); -static int ieee80211_sta_config_auth(struct net_device *dev, +static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); static void sta_rx_agg_session_timer_expired(unsigned long data); @@ -239,11 +240,10 @@ static int ecw2cw(int ecw) } -static void ieee80211_sta_def_wmm_params(struct net_device *dev, +static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_bss *bss, int ibss) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; int i, have_higher_than_11mbit = 0; @@ -281,11 +281,10 @@ static void ieee80211_sta_def_wmm_params(struct net_device *dev, } } -static void ieee80211_sta_wmm_params(struct net_device *dev, +static void ieee80211_sta_wmm_params(struct ieee80211_local *local, struct ieee80211_if_sta *ifsta, u8 *wmm_param, size_t wmm_param_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_tx_queue_params params; size_t left; int count; @@ -349,14 +348,14 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " "cWmin=%d cWmax=%d txop=%d\n", - dev->name, queue, aci, acm, params.aifs, params.cw_min, + local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, params.cw_max, params.txop); #endif /* TODO: handle ACM (block TX, fallback to next lowest allowed * AC for now) */ if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", dev->name, queue); + "parameters for queue %d\n", local->mdev->name, queue); } } } @@ -475,7 +474,7 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info( return 0; } -static void ieee80211_sta_send_associnfo(struct net_device *dev, +static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { char *buf; @@ -520,17 +519,16 @@ static void ieee80211_sta_send_associnfo(struct net_device *dev, memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = len; - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); + wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); kfree(buf); } -static void ieee80211_set_associated(struct net_device *dev, +static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, bool assoc) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct ieee80211_conf *conf = &local_to_hw(local)->conf; union iwreq_data wrqu; @@ -544,7 +542,7 @@ static void ieee80211_set_associated(struct net_device *dev, if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, conf->channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { @@ -568,12 +566,12 @@ static void ieee80211_set_associated(struct net_device *dev, ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_send_associnfo(dev, ifsta); + ieee80211_sta_send_associnfo(sdata, ifsta); } else { - netif_carrier_off(dev); - ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); + netif_carrier_off(sdata->dev); + ieee80211_sta_tear_down_BA_sessions(sdata, ifsta->bssid); ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; - changed |= ieee80211_reset_erp_info(dev); + changed |= ieee80211_reset_erp_info(sdata); sdata->bss_conf.assoc_ht = 0; sdata->bss_conf.ht_conf = NULL; @@ -588,27 +586,27 @@ static void ieee80211_set_associated(struct net_device *dev, ieee80211_bss_info_change_notify(sdata, changed); if (assoc) - netif_carrier_on(dev); + netif_carrier_on(sdata->dev); wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); } -static void ieee80211_set_disassoc(struct net_device *dev, +static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, int deauth) { - if (deauth) + if (deauth) { + ifsta->direct_probe_tries = 0; ifsta->auth_tries = 0; + } + ifsta->assoc_scan_tries = 0; ifsta->assoc_tries = 0; - ieee80211_set_associated(dev, ifsta, 0); + ieee80211_set_associated(sdata, ifsta, 0); } -void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt) { - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); skb->dev = sdata->local->mdev; skb_set_mac_header(skb, 0); skb_set_network_header(skb, 0); @@ -621,12 +619,12 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, } -static void ieee80211_send_auth(struct net_device *dev, +static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, int transaction, u8 *extra, size_t extra_len, int encrypt) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -634,19 +632,19 @@ static void ieee80211_send_auth(struct net_device *dev, sizeof(*mgmt) + 6 + extra_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for auth " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); memset(mgmt, 0, 24 + 6); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_AUTH); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_AUTH); if (encrypt) mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); @@ -655,11 +653,41 @@ static void ieee80211_send_auth(struct net_device *dev, if (extra) memcpy(skb_put(skb, extra_len), extra, extra_len); - ieee80211_sta_tx(dev, skb, encrypt); + ieee80211_sta_tx(sdata, skb, encrypt); +} + +static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) +{ + DECLARE_MAC_BUF(mac); + + ifsta->direct_probe_tries++; + if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { + printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; + return; + } + + printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", + sdata->dev->name, print_mac(mac, ifsta->bssid), + ifsta->direct_probe_tries); + + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; + + set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); + + /* Direct probe is sent to broadcast address as some APs + * will not answer to direct packet in unassociated state. + */ + ieee80211_send_probe_req(sdata, NULL, + ifsta->ssid, ifsta->ssid_len); + + mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); } -static void ieee80211_authenticate(struct net_device *dev, +static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { DECLARE_MAC_BUF(mac); @@ -668,16 +696,16 @@ static void ieee80211_authenticate(struct net_device *dev, if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: authentication with AP %s" " timed out\n", - dev->name, print_mac(mac, ifsta->bssid)); - ifsta->state = IEEE80211_DISABLED; + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - ifsta->state = IEEE80211_AUTHENTICATE; + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; printk(KERN_DEBUG "%s: authenticate with AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); - ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0); + ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); } @@ -703,10 +731,10 @@ static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, return count; } -static void ieee80211_send_assoc(struct net_device *dev, +static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, *ies; @@ -722,7 +750,7 @@ static void ieee80211_send_assoc(struct net_device *dev, ifsta->ssid_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -738,7 +766,7 @@ static void ieee80211_send_assoc(struct net_device *dev, capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { @@ -766,13 +794,13 @@ static void ieee80211_send_assoc(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { skb_put(skb, 10); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_REASSOC_REQ); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_REASSOC_REQ); mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); mgmt->u.reassoc_req.listen_interval = cpu_to_le16(local->hw.conf.listen_interval); @@ -780,8 +808,8 @@ static void ieee80211_send_assoc(struct net_device *dev, ETH_ALEN); } else { skb_put(skb, 4); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ASSOC_REQ); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ASSOC_REQ); mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); mgmt->u.reassoc_req.listen_interval = cpu_to_le16(local->hw.conf.listen_interval); @@ -907,21 +935,21 @@ static void ieee80211_send_assoc(struct net_device *dev, if (ifsta->assocreq_ies) memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_deauth(struct net_device *dev, +static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -929,28 +957,28 @@ static void ieee80211_send_deauth(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_DEAUTH); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_DEAUTH); skb_put(skb, 2); mgmt->u.deauth.reason_code = cpu_to_le16(reason); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_disassoc(struct net_device *dev, +static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -958,21 +986,21 @@ static void ieee80211_send_disassoc(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_DISASSOC); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_DISASSOC); skb_put(skb, 2); mgmt->u.disassoc.reason_code = cpu_to_le16(reason); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static int ieee80211_privacy_mismatch(struct net_device *dev, +static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; int bss_privacy; int wep_privacy; @@ -981,14 +1009,14 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) return 0; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (!bss) return 0; bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); - wep_privacy = !!ieee80211_sta_wep_configured(dev); + wep_privacy = !!ieee80211_sta_wep_configured(sdata); privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); ieee80211_rx_bss_put(local, bss); @@ -1000,7 +1028,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, } -static void ieee80211_associate(struct net_device *dev, +static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { DECLARE_MAC_BUF(mac); @@ -1009,31 +1037,31 @@ static void ieee80211_associate(struct net_device *dev, if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { printk(KERN_DEBUG "%s: association with AP %s" " timed out\n", - dev->name, print_mac(mac, ifsta->bssid)); - ifsta->state = IEEE80211_DISABLED; + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - ifsta->state = IEEE80211_ASSOCIATE; + ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; printk(KERN_DEBUG "%s: associate with AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); - if (ieee80211_privacy_mismatch(dev, ifsta)) { + sdata->dev->name, print_mac(mac, ifsta->bssid)); + if (ieee80211_privacy_mismatch(sdata, ifsta)) { printk(KERN_DEBUG "%s: mismatch in privacy configuration and " - "mixed-cell disabled - abort association\n", dev->name); - ifsta->state = IEEE80211_DISABLED; + "mixed-cell disabled - abort association\n", sdata->dev->name); + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - ieee80211_send_assoc(dev, ifsta); + ieee80211_send_assoc(sdata, ifsta); mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); } -static void ieee80211_associated(struct net_device *dev, +static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; int disassoc; DECLARE_MAC_BUF(mac); @@ -1043,14 +1071,14 @@ static void ieee80211_associated(struct net_device *dev, * for better APs. */ /* TODO: remove expired BSSes */ - ifsta->state = IEEE80211_ASSOCIATED; + ifsta->state = IEEE80211_STA_MLME_ASSOCIATED; rcu_read_lock(); sta = sta_info_get(local, ifsta->bssid); if (!sta) { printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); disassoc = 1; } else { disassoc = 0; @@ -1060,11 +1088,11 @@ static void ieee80211_associated(struct net_device *dev, printk(KERN_DEBUG "%s: No ProbeResp from " "current AP %s - assume out of " "range\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); disassoc = 1; sta_info_unlink(&sta); } else - ieee80211_send_probe_req(dev, ifsta->bssid, + ieee80211_send_probe_req(sdata, ifsta->bssid, local->scan_ssid, local->scan_ssid_len); ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; @@ -1073,7 +1101,7 @@ static void ieee80211_associated(struct net_device *dev, if (time_after(jiffies, ifsta->last_probe + IEEE80211_PROBE_INTERVAL)) { ifsta->last_probe = jiffies; - ieee80211_send_probe_req(dev, ifsta->bssid, + ieee80211_send_probe_req(sdata, ifsta->bssid, ifsta->ssid, ifsta->ssid_len); } @@ -1086,8 +1114,8 @@ static void ieee80211_associated(struct net_device *dev, sta_info_destroy(sta); if (disassoc) { - ifsta->state = IEEE80211_DISABLED; - ieee80211_set_associated(dev, ifsta, 0); + ifsta->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_set_associated(sdata, ifsta, 0); } else { mod_timer(&ifsta->timer, jiffies + IEEE80211_MONITORING_INTERVAL); @@ -1095,10 +1123,10 @@ static void ieee80211_associated(struct net_device *dev, } -static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, +static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1108,16 +1136,16 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "request\n", dev->name); + "request\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_PROBE_REQ); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_REQ); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (dst) { memcpy(mgmt->da, dst, ETH_ALEN); memcpy(mgmt->bssid, dst, ETH_ALEN); @@ -1152,13 +1180,12 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, *pos = rate->bitrate / 5; } - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static int ieee80211_sta_wep_configured(struct net_device *dev) +static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata || !sdata->default_key || sdata->default_key->conf.alg != ALG_WEP) return 0; @@ -1166,16 +1193,16 @@ static int ieee80211_sta_wep_configured(struct net_device *dev) } -static void ieee80211_auth_completed(struct net_device *dev, +static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - printk(KERN_DEBUG "%s: authenticated\n", dev->name); + printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); ifsta->flags |= IEEE80211_STA_AUTHENTICATED; - ieee80211_associate(dev, ifsta); + ieee80211_associate(sdata, ifsta); } -static void ieee80211_auth_challenge(struct net_device *dev, +static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1187,17 +1214,16 @@ static void ieee80211_auth_challenge(struct net_device *dev, ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); if (!elems.challenge) return; - ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2, + ieee80211_send_auth(sdata, ifsta, 3, elems.challenge - 2, elems.challenge_len + 2, 1); } -static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, +static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, u8 dialog_token, u16 status, u16 policy, u16 buf_size, u16 timeout) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u16 capab; @@ -1206,7 +1232,7 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer " - "for addba resp frame\n", dev->name); + "for addba resp frame\n", sdata->dev->name); return; } @@ -1214,13 +1240,13 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); mgmt->u.action.category = WLAN_CATEGORY_BACK; @@ -1235,17 +1261,16 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return; } -void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, +void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u8 dialog_token, u16 start_seq_num, u16 agg_size, u16 timeout) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1255,21 +1280,21 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer " - "for addba request frame\n", dev->name); + "for addba request frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); @@ -1287,14 +1312,13 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, mgmt->u.action.u.addba_req.start_seq_num = cpu_to_le16(start_seq_num << 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_sta_process_addba_request(struct net_device *dev, +static void ieee80211_sta_process_addba_request(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = &local->hw; struct ieee80211_conf *conf = &hw->conf; struct sta_info *sta; @@ -1426,16 +1450,15 @@ end: spin_unlock_bh(&sta->lock); end_no_lock: - ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, + ieee80211_send_addba_resp(sta->sdata, sta->addr, tid, dialog_token, status, 1, buf_size, timeout); rcu_read_unlock(); } -static void ieee80211_sta_process_addba_resp(struct net_device *dev, +static void ieee80211_sta_process_addba_resp(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = &local->hw; struct sta_info *sta; u16 capab; @@ -1497,11 +1520,10 @@ addba_resp_exit: rcu_read_unlock(); } -void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, +void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u16 initiator, u16 reason_code) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1511,7 +1533,7 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer " - "for delba frame\n", dev->name); + "for delba frame\n", sdata->dev->name); return; } @@ -1519,13 +1541,13 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); @@ -1537,12 +1559,12 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, mgmt->u.action.u.delba.params = cpu_to_le16(params); mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_bar *bar; u16 bar_control = 0; @@ -1550,29 +1572,29 @@ void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer for " - "bar frame\n", dev->name); + "bar frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); memset(bar, 0, sizeof(*bar)); - bar->frame_control = IEEE80211_FC(IEEE80211_FTYPE_CTL, - IEEE80211_STYPE_BACK_REQ); + bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_BACK_REQ); memcpy(bar->ra, ra, ETH_ALEN); - memcpy(bar->ta, dev->dev_addr, ETH_ALEN); + memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; bar_control |= (u16)(tid << 12); bar->control = cpu_to_le16(bar_control); bar->start_seq_num = cpu_to_le16(ssn); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, +void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 initiator, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_hw *hw = &local->hw; struct sta_info *sta; int ret, i; @@ -1620,7 +1642,7 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, /* check if this is a self generated aggregation halt */ if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) - ieee80211_send_delba(dev, ra, tid, 0, reason); + ieee80211_send_delba(sdata, ra, tid, 0, reason); /* free the reordering buffer */ for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { @@ -1641,10 +1663,10 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, } -static void ieee80211_sta_process_delba(struct net_device *dev, +static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; u16 tid, params; u16 initiator; @@ -1671,7 +1693,7 @@ static void ieee80211_sta_process_delba(struct net_device *dev, #endif /* CONFIG_MAC80211_HT_DEBUG */ if (initiator == WLAN_BACK_INITIATOR) - ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, + ieee80211_sta_stop_rx_ba_session(sdata, sta->addr, tid, WLAN_BACK_INITIATOR, 0); else { /* WLAN_BACK_RECIPIENT */ spin_lock_bh(&sta->lock); @@ -1758,31 +1780,31 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); #endif - ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, (u16)*ptid, WLAN_BACK_TIMER, WLAN_REASON_QSTA_TIMEOUT); } -void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) +void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int i; for (i = 0; i < STA_TID_NUM; i++) { ieee80211_stop_tx_ba_session(&local->hw, addr, i, WLAN_BACK_INITIATOR); - ieee80211_sta_stop_rx_ba_session(dev, addr, i, + ieee80211_sta_stop_rx_ba_session(sdata, addr, i, WLAN_BACK_RECIPIENT, WLAN_REASON_QSTA_LEAVE_QBSS); } } -static void ieee80211_send_refuse_measurement_request(struct net_device *dev, +static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, struct ieee80211_msrment_ie *request_ie, const u8 *da, const u8 *bssid, u8 dialog_token) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *msr_report; @@ -1791,7 +1813,7 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer for " - "measurement report frame\n", dev->name); + "measurement report frame\n", sdata->dev->name); return; } @@ -1799,9 +1821,9 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); memset(msr_report, 0, 24); memcpy(msr_report->da, da, ETH_ALEN); - memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); + memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(msr_report->bssid, bssid, ETH_ALEN); - msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, + msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); @@ -1821,10 +1843,10 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_sta_process_measurement_req(struct net_device *dev, +static void ieee80211_sta_process_measurement_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { @@ -1835,23 +1857,22 @@ static void ieee80211_sta_process_measurement_req(struct net_device *dev, * For now just refuse * TODO: Answer basic measurement as unmeasured */ - ieee80211_send_refuse_measurement_request(dev, + ieee80211_send_refuse_measurement_request(sdata, &mgmt->u.action.u.measurement.msr_elem, mgmt->sa, mgmt->bssid, mgmt->u.action.u.measurement.dialog_token); } -static void ieee80211_rx_mgmt_auth(struct net_device *dev, +static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); u16 auth_alg, auth_transaction, status_code; DECLARE_MAC_BUF(mac); - if (ifsta->state != IEEE80211_AUTHENTICATE && + if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return; @@ -1879,7 +1900,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, */ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) return; - ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0); + ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0); } if (auth_alg != ifsta->auth_alg || @@ -1912,7 +1933,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, algs[pos] == 0xff) continue; if (algs[pos] == WLAN_AUTH_SHARED_KEY && - !ieee80211_sta_wep_configured(dev)) + !ieee80211_sta_wep_configured(sdata)) continue; ifsta->auth_alg = algs[pos]; break; @@ -1924,19 +1945,19 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, switch (ifsta->auth_alg) { case WLAN_AUTH_OPEN: case WLAN_AUTH_LEAP: - ieee80211_auth_completed(dev, ifsta); + ieee80211_auth_completed(sdata, ifsta); break; case WLAN_AUTH_SHARED_KEY: if (ifsta->auth_transaction == 4) - ieee80211_auth_completed(dev, ifsta); + ieee80211_auth_completed(sdata, ifsta); else - ieee80211_auth_challenge(dev, ifsta, mgmt, len); + ieee80211_auth_challenge(sdata, ifsta, mgmt, len); break; } } -static void ieee80211_rx_mgmt_deauth(struct net_device *dev, +static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1953,22 +1974,22 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev, reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) - printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); + printk(KERN_DEBUG "%s: deauthenticated\n", sdata->dev->name); - if (ifsta->state == IEEE80211_AUTHENTICATE || - ifsta->state == IEEE80211_ASSOCIATE || - ifsta->state == IEEE80211_ASSOCIATED) { - ifsta->state = IEEE80211_AUTHENTICATE; + if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || + ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || + ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } - ieee80211_set_disassoc(dev, ifsta, 1); + ieee80211_set_disassoc(sdata, ifsta, 1); ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED; } -static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, +static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1985,15 +2006,15 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); if (ifsta->flags & IEEE80211_STA_ASSOCIATED) - printk(KERN_DEBUG "%s: disassociated\n", dev->name); + printk(KERN_DEBUG "%s: disassociated\n", sdata->dev->name); - if (ifsta->state == IEEE80211_ASSOCIATED) { - ifsta->state = IEEE80211_ASSOCIATE; + if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { + ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_set_disassoc(sdata, ifsta, 0); } @@ -2004,7 +2025,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, int reassoc) { struct ieee80211_local *local = sdata->local; - struct net_device *dev = sdata->dev; struct ieee80211_supported_band *sband; struct sta_info *sta; u64 rates, basic_rates; @@ -2019,7 +2039,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, /* AssocResp and ReassocResp have identical structure, so process both * of them in this function. */ - if (ifsta->state != IEEE80211_ASSOCIATE) + if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATE) return; if (len < 24 + 6) @@ -2034,12 +2054,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " "status=%d aid=%d)\n", - dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), + sdata->dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", - dev->name, status_code); + sdata->dev->name, status_code); /* if this was a reassociation, ensure we try a "full" * association next time. This works around some broken APs * which do not correctly reject reassociation requests. */ @@ -2049,7 +2069,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " - "set\n", dev->name, aid); + "set\n", sdata->dev->name, aid); aid &= ~(BIT(15) | BIT(14)); pos = mgmt->u.assoc_resp.variable; @@ -2057,11 +2077,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (!elems.supp_rates) { printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", - dev->name); + sdata->dev->name); return; } - printk(KERN_DEBUG "%s: associated\n", dev->name); + printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); ifsta->aid = aid; ifsta->ap_capab = capab_info; @@ -2082,11 +2102,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); if (!sta) { printk(KERN_DEBUG "%s: failed to alloc STA entry for" - " the AP\n", dev->name); + " the AP\n", sdata->dev->name); rcu_read_unlock(); return; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { @@ -2099,7 +2119,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, err = sta_info_insert(sta); if (err) { printk(KERN_DEBUG "%s: failed to insert STA entry for" - " the AP (error %d)\n", dev->name, err); + " the AP (error %d)\n", sdata->dev->name, err); rcu_read_unlock(); return; } @@ -2179,7 +2199,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (elems.wmm_param) { set_sta_flags(sta, WLAN_STA_WME); rcu_read_unlock(); - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); } else rcu_read_unlock(); @@ -2188,17 +2208,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, * ieee80211_set_associated() will tell the driver */ bss_conf->aid = aid; bss_conf->assoc_capability = capab_info; - ieee80211_set_associated(dev, ifsta, 1); + ieee80211_set_associated(sdata, ifsta, 1); - ieee80211_associated(dev, ifsta); + ieee80211_associated(sdata, ifsta); } /* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_add(struct net_device *dev, +static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, struct ieee80211_sta_bss *bss) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); u8 hash_idx; if (bss_mesh_cfg(bss)) @@ -2234,10 +2253,10 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; bss = kzalloc(sizeof(*bss), GFP_ATOMIC); @@ -2255,16 +2274,15 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(dev, bss); + __ieee80211_rx_bss_hash_add(local, bss); spin_unlock_bh(&local->sta_bss_lock); return bss; } static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; spin_lock_bh(&local->sta_bss_lock); @@ -2286,10 +2304,9 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, #ifdef CONFIG_MAC80211_MESH static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len, +ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int freq) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; spin_lock_bh(&local->sta_bss_lock); @@ -2311,10 +2328,9 @@ ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len, } static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, +ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int mesh_config_len, int freq) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; if (mesh_config_len != MESH_CFG_LEN) @@ -2348,7 +2364,7 @@ ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(dev, bss); + __ieee80211_rx_bss_hash_add(local, bss); spin_unlock_bh(&local->sta_bss_lock); return bss; } @@ -2399,23 +2415,20 @@ void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) } -static int ieee80211_sta_join_ibss(struct net_device *dev, +static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_sta_bss *bss) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int res, rates, i, j; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos; - struct ieee80211_sub_if_data *sdata; struct ieee80211_supported_band *sband; union iwreq_data wrqu; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - /* Remove possible STA entries from other IBSS networks. */ sta_info_flush_delayed(sdata); @@ -2433,7 +2446,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, sdata->drop_unencrypted = bss->capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - res = ieee80211_set_freq(dev, bss->freq); + res = ieee80211_set_freq(sdata, bss->freq); if (res) return res; @@ -2446,10 +2459,10 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_PROBE_RESP); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_RESP); memset(mgmt->da, 0xff, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->u.beacon.beacon_int = cpu_to_le16(local->hw.conf.beacon_int); @@ -2506,14 +2519,14 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, } ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; - ieee80211_sta_def_wmm_params(dev, bss, 1); + ieee80211_sta_def_wmm_params(sdata, bss, 1); - ifsta->state = IEEE80211_IBSS_JOINED; + ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); memset(&wrqu, 0, sizeof(wrqu)); memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); return res; } @@ -2555,35 +2568,31 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, } -static void ieee80211_rx_bss_info(struct net_device *dev, +static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status, - struct ieee802_11_elems *elems, - int beacon) + struct ieee802_11_elems *elems) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int freq, clen; struct ieee80211_sta_bss *bss; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); u64 beacon_timestamp, rx_timestamp; struct ieee80211_channel *channel; + bool beacon = ieee80211_is_beacon(mgmt->frame_control); DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); - if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN)) - return; /* ignore ProbeResp to foreign address */ - beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && - elems->mesh_config && mesh_matches_local(elems, dev)) { + elems->mesh_config && mesh_matches_local(elems, sdata)) { u64 rates = ieee80211_sta_get_rates(local, elems, rx_status->band); - mesh_neighbour_update(mgmt->sa, rates, dev, - mesh_peer_accepts_plinks(elems, dev)); + mesh_neighbour_update(mgmt->sa, rates, sdata, + mesh_peer_accepts_plinks(elems)); } rcu_read_lock(); @@ -2620,21 +2629,21 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #ifdef CONFIG_MAC80211_MESH if (elems->mesh_config) - bss = ieee80211_rx_mesh_bss_get(dev, elems->mesh_id, + bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, elems->mesh_id_len, elems->mesh_config, freq); else #endif - bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq, + bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, elems->ssid, elems->ssid_len); if (!bss) { #ifdef CONFIG_MAC80211_MESH if (elems->mesh_config) - bss = ieee80211_rx_mesh_bss_add(dev, elems->mesh_id, + bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, elems->mesh_id_len, elems->mesh_config, elems->mesh_config_len, freq); else #endif - bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq, + bss = ieee80211_rx_bss_add(sdata, mgmt->bssid, freq, elems->ssid, elems->ssid_len); if (!bss) return; @@ -2728,15 +2737,14 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->signal = rx_status->signal; bss->noise = rx_status->noise; bss->qual = rx_status->qual; - if (!beacon && !bss->probe_resp) - bss->probe_resp = true; - + if (!beacon) + bss->last_probe_resp = jiffies; /* * In STA mode, the remaining parameters should not be overridden * by beacons because they're not necessarily accurate there. */ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - bss->probe_resp && beacon) { + bss->last_probe_resp && beacon) { ieee80211_rx_bss_put(local, bss); return; } @@ -2871,10 +2879,10 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #ifndef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: beacon TSF higher than " "local TSF - IBSS merge with BSSID %s\n", - dev->name, print_mac(mac, mgmt->bssid)); + sdata->dev->name, print_mac(mac, mgmt->bssid)); #endif - ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss); - ieee80211_ibss_add_sta(dev, NULL, + ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); + ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, mgmt->sa, BIT(rx_status->rate_idx)); } @@ -2884,13 +2892,17 @@ static void ieee80211_rx_bss_info(struct net_device *dev, } -static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, +static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { size_t baselen; struct ieee802_11_elems elems; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + + if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) + return; /* ignore ProbeResp to foreign address */ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; if (baselen > len) @@ -2899,20 +2911,27 @@ static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, &elems); - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); + + /* direct probe may be part of the association flow */ + if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, + &ifsta->request)) { + printk(KERN_DEBUG "%s direct probe responded\n", + sdata->dev->name); + ieee80211_authenticate(sdata, ifsta); + } } -static void ieee80211_rx_mgmt_beacon(struct net_device *dev, +static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; size_t baselen; struct ieee802_11_elems elems; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_conf *conf = &local->hw.conf; u32 changed = 0; @@ -2923,9 +2942,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; ifsta = &sdata->u.sta; @@ -2934,7 +2952,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) return; - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); /* Do not send changes to driver if we are scanning. This removes @@ -2966,14 +2984,13 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, } -static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, +static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; int tx_last_beacon; struct sk_buff *skb; struct ieee80211_mgmt *resp; @@ -2985,7 +3002,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, #endif if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS || - ifsta->state != IEEE80211_IBSS_JOINED || + ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || len < 24 + 2 || !ifsta->probe_resp) return; @@ -2997,7 +3014,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID=" "%s (tx_last_beacon=%d)\n", - dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), + sdata->dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), print_mac(mac3, mgmt->bssid), tx_last_beacon); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ @@ -3015,7 +3032,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " "from %s\n", - dev->name, print_mac(mac, mgmt->sa)); + sdata->dev->name, print_mac(mac, mgmt->sa)); #endif return; } @@ -3035,19 +3052,18 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, memcpy(resp->da, mgmt->sa, ETH_ALEN); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", - dev->name, print_mac(mac, resp->da)); + sdata->dev->name, print_mac(mac, resp->da)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_rx_mgmt_action(struct net_device *dev, +static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (len < IEEE80211_MIN_ACTION_SIZE) return; @@ -3061,7 +3077,7 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.measurement))) break; - ieee80211_sta_process_measurement_req(dev, mgmt, len); + ieee80211_sta_process_measurement_req(sdata, mgmt, len); break; } break; @@ -3071,38 +3087,37 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.addba_req))) break; - ieee80211_sta_process_addba_request(dev, mgmt, len); + ieee80211_sta_process_addba_request(local, mgmt, len); break; case WLAN_ACTION_ADDBA_RESP: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.addba_resp))) break; - ieee80211_sta_process_addba_resp(dev, mgmt, len); + ieee80211_sta_process_addba_resp(local, mgmt, len); break; case WLAN_ACTION_DELBA: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.delba))) break; - ieee80211_sta_process_delba(dev, mgmt, len); + ieee80211_sta_process_delba(sdata, mgmt, len); break; } break; case PLINK_CATEGORY: if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rx_plink_frame(dev, mgmt, len, rx_status); + mesh_rx_plink_frame(sdata, mgmt, len, rx_status); break; case MESH_PATH_SEL_CATEGORY: if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rx_path_sel_frame(dev, mgmt, len); + mesh_rx_path_sel_frame(sdata, mgmt, len); break; } } -void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; struct ieee80211_mgmt *mgmt; u16 fc; @@ -3110,7 +3125,6 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, if (skb->len < 24) goto fail; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; mgmt = (struct ieee80211_mgmt *) skb->data; @@ -3137,16 +3151,14 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, } -static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, +static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_rx_status *rx_status; - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; struct ieee80211_mgmt *mgmt; u16 fc; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; rx_status = (struct ieee80211_rx_status *) skb->cb; @@ -3155,17 +3167,17 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_PROBE_REQ: - ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len, + ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_PROBE_RESP: - ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_BEACON: - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_AUTH: - ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_ASSOC_RESP: ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); @@ -3174,13 +3186,13 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); break; case IEEE80211_STYPE_DEAUTH: - ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_DISASSOC: - ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_ACTION: - ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_action(sdata, ifsta, mgmt, skb->len, rx_status); break; } @@ -3189,7 +3201,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, ieee80211_rx_result -ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, +ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { struct ieee80211_mgmt *mgmt; @@ -3208,13 +3220,13 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, return RX_DROP_MONITOR; if (ieee80211_is_probe_resp(fc)) { - ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); dev_kfree_skb(skb); return RX_QUEUED; } if (ieee80211_is_beacon(fc)) { - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); dev_kfree_skb(skb); return RX_QUEUED; } @@ -3223,12 +3235,11 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, } -static int ieee80211_sta_active_ibss(struct net_device *dev) +static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int active = 0; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -3247,9 +3258,9 @@ static int ieee80211_sta_active_ibss(struct net_device *dev) } -static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) +static void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta, *tmp; LIST_HEAD(tmp_list); DECLARE_MAC_BUF(mac); @@ -3260,7 +3271,7 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) if (time_after(jiffies, sta->last_rx + exp_time)) { #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: expiring inactive STA %s\n", - dev->name, print_mac(mac, sta->addr)); + sdata->dev->name, print_mac(mac, sta->addr)); #endif __sta_info_unlink(&sta); if (sta) @@ -3273,30 +3284,29 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) } -static void ieee80211_sta_merge_ibss(struct net_device *dev, +static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); - ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT); - if (ieee80211_sta_active_ibss(dev)) + ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); + if (ieee80211_sta_active_ibss(sdata)) return; printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " - "IBSS networks with same SSID (merge)\n", dev->name); - ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len); + "IBSS networks with same SSID (merge)\n", sdata->dev->name); + ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); } #ifdef CONFIG_MAC80211_MESH -static void ieee80211_mesh_housekeeping(struct net_device *dev, +static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); bool free_plinks; - ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); - mesh_path_expire(dev); + ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); + mesh_path_expire(sdata); free_plinks = mesh_plink_availables(sdata); if (free_plinks != sdata->u.sta.accepting_plinks) @@ -3307,12 +3317,11 @@ static void ieee80211_mesh_housekeeping(struct net_device *dev, } -void ieee80211_start_mesh(struct net_device *dev) +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_sta *ifsta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; - ifsta->state = IEEE80211_MESH_UP; + ifsta->state = IEEE80211_STA_MLME_MESH_UP; ieee80211_sta_timer((unsigned long)sdata); ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); } @@ -3324,7 +3333,7 @@ void ieee80211_sta_timer(unsigned long data) struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(&sdata->wdev); + struct ieee80211_local *local = sdata->local; set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); queue_work(local->hw.workqueue, &ifsta->work); @@ -3334,12 +3343,11 @@ void ieee80211_sta_work(struct work_struct *work) { struct ieee80211_sub_if_data *sdata = container_of(work, struct ieee80211_sub_if_data, u.sta.work); - struct net_device *dev = sdata->dev; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; struct sk_buff *skb; - if (!netif_running(dev)) + if (!netif_running(sdata->dev)) return; if (local->sta_sw_scanning || local->sta_hw_scanning) @@ -3352,53 +3360,57 @@ void ieee80211_sta_work(struct work_struct *work) ifsta = &sdata->u.sta; while ((skb = skb_dequeue(&ifsta->skb_queue))) - ieee80211_sta_rx_queued_mgmt(dev, skb); + ieee80211_sta_rx_queued_mgmt(sdata, skb); #ifdef CONFIG_MAC80211_MESH if (ifsta->preq_queue_len && time_after(jiffies, ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) - mesh_path_start_discovery(dev); + mesh_path_start_discovery(sdata); #endif - if (ifsta->state != IEEE80211_AUTHENTICATE && - ifsta->state != IEEE80211_ASSOCIATE && + if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && + ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && + ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { if (ifsta->scan_ssid_len) - ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len); + ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); else - ieee80211_sta_start_scan(dev, NULL, 0); + ieee80211_sta_start_scan(sdata, NULL, 0); return; } if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { - if (ieee80211_sta_config_auth(dev, ifsta)) + if (ieee80211_sta_config_auth(sdata, ifsta)) return; clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) return; switch (ifsta->state) { - case IEEE80211_DISABLED: + case IEEE80211_STA_MLME_DISABLED: + break; + case IEEE80211_STA_MLME_DIRECT_PROBE: + ieee80211_direct_probe(sdata, ifsta); break; - case IEEE80211_AUTHENTICATE: - ieee80211_authenticate(dev, ifsta); + case IEEE80211_STA_MLME_AUTHENTICATE: + ieee80211_authenticate(sdata, ifsta); break; - case IEEE80211_ASSOCIATE: - ieee80211_associate(dev, ifsta); + case IEEE80211_STA_MLME_ASSOCIATE: + ieee80211_associate(sdata, ifsta); break; - case IEEE80211_ASSOCIATED: - ieee80211_associated(dev, ifsta); + case IEEE80211_STA_MLME_ASSOCIATED: + ieee80211_associated(sdata, ifsta); break; - case IEEE80211_IBSS_SEARCH: - ieee80211_sta_find_ibss(dev, ifsta); + case IEEE80211_STA_MLME_IBSS_SEARCH: + ieee80211_sta_find_ibss(sdata, ifsta); break; - case IEEE80211_IBSS_JOINED: - ieee80211_sta_merge_ibss(dev, ifsta); + case IEEE80211_STA_MLME_IBSS_JOINED: + ieee80211_sta_merge_ibss(sdata, ifsta); break; #ifdef CONFIG_MAC80211_MESH - case IEEE80211_MESH_UP: - ieee80211_mesh_housekeeping(dev, ifsta); + case IEEE80211_STA_MLME_MESH_UP: + ieee80211_mesh_housekeeping(sdata, ifsta); break; #endif default: @@ -3406,20 +3418,20 @@ void ieee80211_sta_work(struct work_struct *work) break; } - if (ieee80211_privacy_mismatch(dev, ifsta)) { + if (ieee80211_privacy_mismatch(sdata, ifsta)) { printk(KERN_DEBUG "%s: privacy configuration mismatch and " - "mixed-cell disabled - disassociate\n", dev->name); + "mixed-cell disabled - disassociate\n", sdata->dev->name); - ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED); - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_send_disassoc(sdata, ifsta, WLAN_REASON_UNSPECIFIED); + ieee80211_set_disassoc(sdata, ifsta, 0); } } -static void ieee80211_sta_reset_auth(struct net_device *dev, +static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (local->ops->reset_tsf) { /* Reset own TSF to allow time synchronization work. */ @@ -3439,16 +3451,18 @@ static void ieee80211_sta_reset_auth(struct net_device *dev, ifsta->auth_alg = WLAN_AUTH_OPEN; ifsta->auth_transaction = -1; ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; - ifsta->auth_tries = ifsta->assoc_tries = 0; - netif_carrier_off(dev); + ifsta->assoc_scan_tries = 0; + ifsta->direct_probe_tries = 0; + ifsta->auth_tries = 0; + ifsta->assoc_tries = 0; + netif_carrier_off(sdata->dev); } -void ieee80211_sta_req_auth(struct net_device *dev, +void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; @@ -3492,11 +3506,10 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, return 0; } -static int ieee80211_sta_config_auth(struct net_device *dev, +static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss, *selected = NULL; int top_rssi = 0, freq; @@ -3535,38 +3548,48 @@ static int ieee80211_sta_config_auth(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); if (selected) { - ieee80211_set_freq(dev, selected->freq); + ieee80211_set_freq(sdata, selected->freq); if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) - ieee80211_sta_set_ssid(dev, selected->ssid, + ieee80211_sta_set_ssid(sdata, selected->ssid, selected->ssid_len); - ieee80211_sta_set_bssid(dev, selected->bssid); - ieee80211_sta_def_wmm_params(dev, selected, 0); + ieee80211_sta_set_bssid(sdata, selected->bssid); + ieee80211_sta_def_wmm_params(sdata, selected, 0); + + /* Send out direct probe if no probe resp was received or + * the one we have is outdated + */ + if (!selected->last_probe_resp || + time_after(jiffies, selected->last_probe_resp + + IEEE80211_SCAN_RESULT_EXPIRE)) + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; + else + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + ieee80211_rx_bss_put(local, selected); - ifsta->state = IEEE80211_AUTHENTICATE; - ieee80211_sta_reset_auth(dev, ifsta); + ieee80211_sta_reset_auth(sdata, ifsta); return 0; } else { - if (ifsta->state != IEEE80211_AUTHENTICATE) { + if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { + ifsta->assoc_scan_tries++; if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) - ieee80211_sta_start_scan(dev, NULL, 0); + ieee80211_sta_start_scan(sdata, NULL, 0); else - ieee80211_sta_start_scan(dev, ifsta->ssid, + ieee80211_sta_start_scan(sdata, ifsta->ssid, ifsta->ssid_len); - ifsta->state = IEEE80211_AUTHENTICATE; + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); } else - ifsta->state = IEEE80211_DISABLED; + ifsta->state = IEEE80211_STA_MLME_DISABLED; } return -1; } -static int ieee80211_sta_create_ibss(struct net_device *dev, +static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_supported_band *sband; u8 bssid[ETH_ALEN], *pos; int i; @@ -3582,15 +3605,15 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, * random number generator get different BSSID. */ get_random_bytes(bssid, ETH_ALEN); for (i = 0; i < ETH_ALEN; i++) - bssid[i] ^= dev->dev_addr[i]; + bssid[i] ^= sdata->dev->dev_addr[i]; bssid[0] &= ~0x01; bssid[0] |= 0x02; #endif printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", - dev->name, print_mac(mac, bssid)); + sdata->dev->name, print_mac(mac, bssid)); - bss = ieee80211_rx_bss_add(dev, bssid, + bss = ieee80211_rx_bss_add(sdata, bssid, local->hw.conf.channel->center_freq, sdata->u.sta.ssid, sdata->u.sta.ssid_len); if (!bss) @@ -3617,16 +3640,16 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, *pos++ = (u8) (rate / 5); } - ret = ieee80211_sta_join_ibss(dev, ifsta, bss); + ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); ieee80211_rx_bss_put(local, bss); return ret; } -static int ieee80211_sta_find_ibss(struct net_device *dev, +static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; int found = 0; u8 bssid[ETH_ALEN]; @@ -3637,10 +3660,10 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, if (ifsta->ssid_len == 0) return -EINVAL; - active_ibss = ieee80211_sta_active_ibss(dev); + active_ibss = ieee80211_sta_active_ibss(sdata); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", - dev->name, active_ibss); + sdata->dev->name, active_ibss); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ spin_lock_bh(&local->sta_bss_lock); list_for_each_entry(bss, &local->sta_bss_list, list) { @@ -3675,15 +3698,15 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, else search_freq = local->hw.conf.channel->center_freq; - bss = ieee80211_rx_bss_get(dev, bssid, search_freq, + bss = ieee80211_rx_bss_get(local, bssid, search_freq, ifsta->ssid, ifsta->ssid_len); if (!bss) goto dont_join; printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" " based on configured SSID\n", - dev->name, print_mac(mac, bssid)); - ret = ieee80211_sta_join_ibss(dev, ifsta, bss); + sdata->dev->name, print_mac(mac, bssid)); + ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); ieee80211_rx_bss_put(local, bss); return ret; } @@ -3694,17 +3717,17 @@ dont_join: #endif /* CONFIG_MAC80211_IBSS_DEBUG */ /* Selected IBSS not found in current scan results - try to scan */ - if (ifsta->state == IEEE80211_IBSS_JOINED && - !ieee80211_sta_active_ibss(dev)) { + if (ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED && + !ieee80211_sta_active_ibss(sdata)) { mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); } else if (time_after(jiffies, local->last_scan_completed + IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " - "join\n", dev->name); - return ieee80211_sta_req_scan(dev, ifsta->ssid, + "join\n", sdata->dev->name); + return ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); - } else if (ifsta->state != IEEE80211_IBSS_JOINED) { + } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; if (time_after(jiffies, ifsta->ibss_join_req + @@ -3712,10 +3735,10 @@ dont_join: if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) && (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS))) - return ieee80211_sta_create_ibss(dev, ifsta); + return ieee80211_sta_create_ibss(sdata, ifsta); if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) { printk(KERN_DEBUG "%s: IBSS not allowed on" - " %d MHz\n", dev->name, + " %d MHz\n", sdata->dev->name, local->hw.conf.channel->center_freq); } @@ -3724,7 +3747,7 @@ dont_join: interval = IEEE80211_SCAN_INTERVAL_SLOW; } - ifsta->state = IEEE80211_IBSS_SEARCH; + ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; mod_timer(&ifsta->timer, jiffies + interval); return 0; } @@ -3733,9 +3756,8 @@ dont_join: } -int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) +int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta; int res; @@ -3759,7 +3781,7 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); if (res) { printk(KERN_DEBUG "%s: Failed to config new SSID to " - "the low-level driver\n", dev->name); + "the low-level driver\n", sdata->dev->name); return res; } } @@ -3772,17 +3794,16 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { ifsta->ibss_join_req = jiffies; - ifsta->state = IEEE80211_IBSS_SEARCH; - return ieee80211_sta_find_ibss(dev, ifsta); + ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; + return ieee80211_sta_find_ibss(sdata, ifsta); } return 0; } -int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) +int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; memcpy(ssid, ifsta->ssid, ifsta->ssid_len); *len = ifsta->ssid_len; @@ -3790,13 +3811,11 @@ int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) } -int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) +int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) { - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; int res; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { @@ -3809,7 +3828,7 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); if (res) { printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", dev->name); + "the low-level driver\n", sdata->dev->name); return res; } } @@ -3850,7 +3869,7 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_tx(sdata->dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } @@ -3922,9 +3941,9 @@ done: if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || - (!(ifsta->state == IEEE80211_IBSS_JOINED) && - !ieee80211_sta_active_ibss(dev))) - ieee80211_sta_find_ibss(dev, ifsta); + (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && + !ieee80211_sta_active_ibss(sdata))) + ieee80211_sta_find_ibss(sdata, ifsta); } } EXPORT_SYMBOL(ieee80211_scan_completed); @@ -4013,7 +4032,7 @@ void ieee80211_sta_scan_work(struct work_struct *work) if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) break; - ieee80211_send_probe_req(dev, NULL, local->scan_ssid, + ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, local->scan_ssid_len); next_delay = IEEE80211_CHANNEL_TIME; break; @@ -4025,10 +4044,10 @@ void ieee80211_sta_scan_work(struct work_struct *work) } -static int ieee80211_sta_start_scan(struct net_device *dev, +static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, u8 *ssid, size_t ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = scan_sdata->local; struct ieee80211_sub_if_data *sdata; if (ssid_len > IEEE80211_MAX_SSID_LEN) @@ -4052,7 +4071,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, */ if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_dev == dev) + if (local->scan_dev == scan_sdata->dev) return 0; return -EBUSY; } @@ -4062,7 +4081,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, ssid, ssid_len); if (!rc) { local->sta_hw_scanning = 1; - local->scan_dev = dev; + local->scan_dev = scan_sdata->dev; } return rc; } @@ -4086,7 +4105,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, local->scan_state = SCAN_SET_CHANNEL; local->scan_channel_idx = 0; local->scan_band = IEEE80211_BAND_2GHZ; - local->scan_dev = dev; + local->scan_dev = scan_sdata->dev; netif_addr_lock_bh(local->mdev); local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; @@ -4105,17 +4124,16 @@ static int ieee80211_sta_start_scan(struct net_device *dev, } -int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) +int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) - return ieee80211_sta_start_scan(dev, ssid, ssid_len); + return ieee80211_sta_start_scan(sdata, ssid, ssid_len); if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_dev == dev) + if (local->scan_dev == sdata->dev) return 0; return -EBUSY; } @@ -4129,12 +4147,11 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) } static char * -ieee80211_sta_scan_result(struct net_device *dev, +ieee80211_sta_scan_result(struct ieee80211_local *local, struct iw_request_info *info, struct ieee80211_sta_bss *bss, char *current_ev, char *end_buf) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct iw_event iwe; if (time_after(jiffies, @@ -4321,11 +4338,10 @@ ieee80211_sta_scan_result(struct net_device *dev, } -int ieee80211_sta_scan_results(struct net_device *dev, +int ieee80211_sta_scan_results(struct ieee80211_local *local, struct iw_request_info *info, char *buf, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); char *current_ev = buf; char *end_buf = buf + len; struct ieee80211_sta_bss *bss; @@ -4336,7 +4352,7 @@ int ieee80211_sta_scan_results(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); return -E2BIG; } - current_ev = ieee80211_sta_scan_result(dev, info, bss, + current_ev = ieee80211_sta_scan_result(local, info, bss, current_ev, end_buf); } spin_unlock_bh(&local->sta_bss_lock); @@ -4344,9 +4360,8 @@ int ieee80211_sta_scan_results(struct net_device *dev, } -int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; kfree(ifsta->extra_ie); @@ -4366,13 +4381,12 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) } -struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, +struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u8 *bssid, u8 *addr, u64 supp_rates) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); DECLARE_MAC_BUF(mac); int band = local->hw.conf.channel->band; @@ -4381,7 +4395,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: No room for a new IBSS STA " - "entry %s\n", dev->name, print_mac(mac, addr)); + "entry %s\n", sdata->dev->name, print_mac(mac, addr)); } return NULL; } @@ -4391,7 +4405,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", - wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name); + wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name); #endif sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); @@ -4414,31 +4428,29 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, } -int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason) +int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", - dev->name, reason); + sdata->dev->name, reason); if (sdata->vif.type != IEEE80211_IF_TYPE_STA && sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return -EINVAL; - ieee80211_send_deauth(dev, ifsta, reason); - ieee80211_set_disassoc(dev, ifsta, 1); + ieee80211_send_deauth(sdata, ifsta, reason); + ieee80211_set_disassoc(sdata, ifsta, 1); return 0; } -int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) +int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", - dev->name, reason); + sdata->dev->name, reason); if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return -EINVAL; @@ -4446,8 +4458,8 @@ int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) return -1; - ieee80211_send_disassoc(dev, ifsta, reason); - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_send_disassoc(sdata, ifsta, reason); + ieee80211_set_disassoc(sdata, ifsta, 0); return 0; } @@ -4464,7 +4476,7 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, if (sdata->vif.type != IEEE80211_IF_TYPE_STA) continue; - ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); } rcu_read_unlock(); break; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6db85450519..fd83ef760a3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -143,6 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, /* IEEE80211_RADIOTAP_FLAGS */ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) *pos |= IEEE80211_RADIOTAP_F_FCS; + if (status->flag & RX_FLAG_SHORTPRE) + *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; pos++; /* IEEE80211_RADIOTAP_RATE */ @@ -155,8 +157,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, if (status->band == IEEE80211_BAND_5GHZ) *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ); + else if (rate->flags & IEEE80211_RATE_ERP_G) + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_2GHZ); else - *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_DYN | + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ); pos += 2; @@ -399,11 +404,11 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) struct sk_buff *skb = rx->skb; if (unlikely(local->sta_hw_scanning)) - return ieee80211_sta_rx_scan(rx->dev, skb, rx->status); + return ieee80211_sta_rx_scan(rx->sdata, skb, rx->status); if (unlikely(local->sta_sw_scanning)) { /* drop all the other packets during a software scan anyway */ - if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status) + if (ieee80211_sta_rx_scan(rx->sdata, skb, rx->status) != RX_QUEUED) dev_kfree_skb(skb); return RX_QUEUED; @@ -461,7 +466,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (ieee80211_is_data(hdr->frame_control) && is_multicast_ether_addr(hdr->addr1) && - mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev)) + mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) return RX_DROP_MONITOR; #undef msh_h_get @@ -816,7 +821,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, static inline struct ieee80211_fragment_entry * ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, - u16 fc, unsigned int frag, unsigned int seq, + unsigned int frag, unsigned int seq, int rx_queue, struct ieee80211_hdr *hdr) { struct ieee80211_fragment_entry *entry; @@ -825,7 +830,6 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, idx = sdata->fragment_next; for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { struct ieee80211_hdr *f_hdr; - u16 f_fc; idx--; if (idx < 0) @@ -837,10 +841,13 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, entry->last_frag + 1 != frag) continue; - f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data; - f_fc = le16_to_cpu(f_hdr->frame_control); + f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data; - if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) || + /* + * Check ftype and addresses are equal, else check next fragment + */ + if (((hdr->frame_control ^ f_hdr->frame_control) & + cpu_to_le16(IEEE80211_FCTL_FTYPE)) || compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 || compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0) continue; @@ -860,16 +867,18 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) { struct ieee80211_hdr *hdr; u16 sc; + __le16 fc; unsigned int frag, seq; struct ieee80211_fragment_entry *entry; struct sk_buff *skb; DECLARE_MAC_BUF(mac); - hdr = (struct ieee80211_hdr *) rx->skb->data; + hdr = (struct ieee80211_hdr *)rx->skb->data; + fc = hdr->frame_control; sc = le16_to_cpu(hdr->seq_ctrl); frag = sc & IEEE80211_SCTL_FRAG; - if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) || + if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || (rx->skb)->len < 24 || is_multicast_ether_addr(hdr->addr1))) { /* not fragmented */ @@ -884,7 +893,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) entry = ieee80211_reassemble_add(rx->sdata, frag, seq, rx->queue, &(rx->skb)); if (rx->key && rx->key->conf.alg == ALG_CCMP && - (rx->fc & IEEE80211_FCTL_PROTECTED)) { + ieee80211_has_protected(fc)) { /* Store CCMP PN so that we can verify that the next * fragment has a sequential PN value. */ entry->ccmp = 1; @@ -898,8 +907,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) /* This is a fragment for a frame that should already be pending in * fragment cache. Add this fragment to the end of the pending entry. */ - entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq, - rx->queue, hdr); + entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); if (!entry) { I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); return RX_DROP_MONITOR; @@ -924,11 +932,11 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) memcpy(entry->last_pn, pn, CCMP_PN_LEN); } - skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc)); + skb_pull(rx->skb, ieee80211_hdrlen(fc)); __skb_queue_tail(&entry->skb_list, rx->skb); entry->last_frag = frag; entry->extra_len += rx->skb->len; - if (rx->fc & IEEE80211_FCTL_MOREFRAGS) { + if (ieee80211_has_morefrags(fc)) { rx->skb = NULL; return RX_QUEUED; } @@ -968,10 +976,9 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) struct sk_buff *skb; int no_pending_pkts; DECLARE_MAC_BUF(mac); + __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; - if (likely(!rx->sta || - (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL || - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL || + if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || !(rx->flags & IEEE80211_RX_RA_MATCH))) return RX_CONTINUE; @@ -1050,7 +1057,6 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); /* change frame type to non QOS */ - rx->fc &= ~IEEE80211_STYPE_QOS_DATA; hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); return RX_CONTINUE; @@ -1067,7 +1073,7 @@ ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) } static int -ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx) +ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) { /* * Pass through unencrypted frames if the hardware has @@ -1077,9 +1083,8 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx) return 0; /* Drop unencrypted frames if key is set. */ - if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && - (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && + if (unlikely(!ieee80211_has_protected(fc) && + !ieee80211_is_nullfunc(fc) && (rx->key || rx->sdata->drop_unencrypted))) return -EACCES; @@ -1091,7 +1096,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) { struct net_device *dev = rx->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - u16 fc, hdrlen, ethertype; + u16 hdrlen, ethertype; u8 *payload; u8 dst[ETH_ALEN]; u8 src[ETH_ALEN] __aligned(2); @@ -1102,12 +1107,10 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) DECLARE_MAC_BUF(mac3); DECLARE_MAC_BUF(mac4); - fc = rx->fc; - - if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) return -1; - hdrlen = ieee80211_get_hdrlen(fc); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (ieee80211_vif_is_mesh(&sdata->vif)) hdrlen += ieee80211_get_mesh_hdrlen( @@ -1122,41 +1125,28 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) * 1 0 BSSID SA DA n/a * 1 1 RA TA DA SA */ + memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); + memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); - switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { - case IEEE80211_FCTL_TODS: - /* BSSID SA DA */ - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - + switch (hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { + case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP && sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) return -1; break; - case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): - /* RA TA DA SA */ - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr4, ETH_ALEN); - - if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS && + case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): + if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS && sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) return -1; break; - case IEEE80211_FCTL_FROMDS: - /* DA BSSID SA */ - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr3, ETH_ALEN); - + case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): if (sdata->vif.type != IEEE80211_IF_TYPE_STA || (is_multicast_ether_addr(dst) && !compare_ether_addr(src, dev->dev_addr))) return -1; break; - case 0: - /* DA SA BSSID */ - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - + case __constant_cpu_to_le16(0): if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return -1; break; @@ -1193,7 +1183,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) /* * requires that rx->skb is a frame with ethernet header */ -static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx) +static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) { static const u8 pae_group_addr[ETH_ALEN] __aligned(2) = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; @@ -1209,7 +1199,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx) return true; if (ieee80211_802_1x_port_control(rx) || - ieee80211_drop_unencrypted(rx)) + ieee80211_drop_unencrypted(rx, fc)) return false; return true; @@ -1279,20 +1269,21 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) { struct net_device *dev = rx->dev; struct ieee80211_local *local = rx->local; - u16 fc, ethertype; + u16 ethertype; u8 *payload; struct sk_buff *skb = rx->skb, *frame = NULL; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; const struct ethhdr *eth; int remaining, err; u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; DECLARE_MAC_BUF(mac); - fc = rx->fc; - if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) + if (unlikely(!ieee80211_is_data(fc))) return RX_CONTINUE; - if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) + if (unlikely(!ieee80211_is_data_present(fc))) return RX_DROP_MONITOR; if (!(rx->flags & IEEE80211_RX_AMSDU)) @@ -1374,7 +1365,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); } - if (!ieee80211_frame_allowed(rx)) { + if (!ieee80211_frame_allowed(rx, fc)) { if (skb == frame) /* last frame */ return RX_DROP_UNUSABLE; dev_kfree_skb(frame); @@ -1448,21 +1439,21 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_data(struct ieee80211_rx_data *rx) { struct net_device *dev = rx->dev; - u16 fc; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; + __le16 fc = hdr->frame_control; int err; - fc = rx->fc; - if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) + if (unlikely(!ieee80211_is_data(hdr->frame_control))) return RX_CONTINUE; - if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) return RX_DROP_MONITOR; err = ieee80211_data_to_8023(rx); if (unlikely(err)) return RX_DROP_UNUSABLE; - if (!ieee80211_frame_allowed(rx)) + if (!ieee80211_frame_allowed(rx, fc)) return RX_DROP_MONITOR; rx->skb->dev = dev; @@ -1532,7 +1523,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) sdata->vif.type == IEEE80211_IF_TYPE_IBSS || sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) && !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) - ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status); + ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); else return RX_DROP_MONITOR; @@ -1579,7 +1570,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, !ieee80211_is_auth(hdr->frame_control)) goto ignore; - mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); + mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); ignore: dev_kfree_skb(rx->skb); rx->skb = NULL; @@ -1753,7 +1744,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, return 0; if (ieee80211_is_beacon(hdr->frame_control)) { if (!rx->sta) - rx->sta = ieee80211_ibss_add_sta(sdata->dev, + rx->sta = ieee80211_ibss_add_sta(sdata, rx->skb, bssid, hdr->addr2, BIT(rx->status->rate_idx)); return 1; @@ -1769,7 +1760,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, return 0; rx->flags &= ~IEEE80211_RX_RA_MATCH; } else if (!rx->sta) - rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb, + rx->sta = ieee80211_ibss_add_sta(sdata, rx->skb, bssid, hdr->addr2, BIT(rx->status->rate_idx)); break; @@ -1827,23 +1818,20 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct ieee80211_sub_if_data *sdata; struct ieee80211_hdr *hdr; struct ieee80211_rx_data rx; - u16 type; int prepares; struct ieee80211_sub_if_data *prev = NULL; struct sk_buff *skb_new; u8 *bssid; - hdr = (struct ieee80211_hdr *) skb->data; + hdr = (struct ieee80211_hdr *)skb->data; memset(&rx, 0, sizeof(rx)); rx.skb = skb; rx.local = local; rx.status = status; rx.rate = rate; - rx.fc = le16_to_cpu(hdr->frame_control); - type = rx.fc & IEEE80211_FCTL_FTYPE; - if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) + if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) local->dot11ReceivedFragmentCount++; rx.sta = sta_info_get(local, hdr->addr2); @@ -1904,14 +1892,12 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, prev->dev->name); continue; } - rx.fc = le16_to_cpu(hdr->frame_control); ieee80211_invoke_rx_handlers(prev, &rx, skb_new); prev = sdata; } - if (prev) { - rx.fc = le16_to_cpu(hdr->frame_control); + if (prev) ieee80211_invoke_rx_handlers(prev, &rx, skb); - } else + else dev_kfree_skb(skb); } @@ -2080,7 +2066,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, /* if this mpdu is fragmented - terminate rx aggregation session */ sc = le16_to_cpu(hdr->seq_ctrl); if (sc & IEEE80211_SCTL_FRAG) { - ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); ret = 1; goto end_reorder; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4788f7b91f4..c413d4836af 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -82,6 +82,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, struct ieee80211_rate *txrate; struct ieee80211_local *local = tx->local; struct ieee80211_supported_band *sband; + struct ieee80211_hdr *hdr; sband = local->hw.wiphy->bands[tx->channel->band]; txrate = &sband->bitrates[tx->rate_idx]; @@ -107,8 +108,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, * at the highest possible rate belonging to the PHY rates in the * BSSBasicRateSet */ - - if ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) { + hdr = (struct ieee80211_hdr *)tx->skb->data; + if (ieee80211_is_ctl(hdr->frame_control)) { /* TODO: These control frames are not currently sent by * 80211.o, but should they be implemented, this function * needs to be updated to support duration field calculation. @@ -213,9 +214,8 @@ static int inline is_ieee80211_device(struct net_device *dev, static ieee80211_tx_result debug_noinline ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) { -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); u32 sta_flags; @@ -223,8 +223,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) return TX_CONTINUE; if (unlikely(tx->local->sta_sw_scanning) && - ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || - (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ)) + !ieee80211_is_probe_req(hdr->frame_control)) return TX_DROP; if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) @@ -238,7 +237,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) if (likely(tx->flags & IEEE80211_TX_UNICAST)) { if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { + ieee80211_is_data(hdr->frame_control))) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG DECLARE_MAC_BUF(mac); printk(KERN_DEBUG "%s: dropped data frame to not " @@ -249,7 +248,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) return TX_DROP; } } else { - if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && + if (unlikely(ieee80211_is_data(hdr->frame_control) && tx->local->num_sta == 0 && tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) { /* @@ -315,6 +314,7 @@ static ieee80211_tx_result ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; /* * broadcast/multicast frame @@ -329,7 +329,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) return TX_CONTINUE; /* no buffering for ordered frames */ - if (tx->fc & IEEE80211_FCTL_ORDER) + if (ieee80211_has_order(hdr->frame_control)) return TX_CONTINUE; /* no stations in PS mode */ @@ -367,12 +367,11 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) { struct sta_info *sta = tx->sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; u32 staflags; DECLARE_MAC_BUF(mac); - if (unlikely(!sta || - ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && - (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP))) + if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control))) return TX_CONTINUE; staflags = get_sta_flags(sta); @@ -437,7 +436,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) { struct ieee80211_key *key; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - u16 fc = tx->fc; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; if (unlikely(tx->skb->do_not_encrypt)) tx->key = NULL; @@ -454,22 +453,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) tx->key = NULL; if (tx->key) { - u16 ftype, stype; - tx->key->tx_rx_count++; /* TODO: add threshold stuff again */ switch (tx->key->conf.alg) { case ALG_WEP: - ftype = fc & IEEE80211_FCTL_FTYPE; - stype = fc & IEEE80211_FCTL_STYPE; - - if (ftype == IEEE80211_FTYPE_MGMT && - stype == IEEE80211_STYPE_AUTH) + if (ieee80211_is_auth(hdr->frame_control)) break; case ALG_TKIP: case ALG_CCMP: - if (!WLAN_FC_DATA_PRESENT(fc)) + if (!ieee80211_is_data_present(hdr->frame_control)) tx->key = NULL; break; } @@ -1000,7 +993,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, hdr = (struct ieee80211_hdr *) skb->data; tx->sta = sta_info_get(local, hdr->addr1); - tx->fc = le16_to_cpu(hdr->frame_control); if (is_multicast_ether_addr(hdr->addr1)) { tx->flags &= ~IEEE80211_TX_UNICAST; @@ -1025,7 +1017,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; - hdrlen = ieee80211_get_hdrlen(tx->fc); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; tx->ethertype = (pos[0] << 8) | pos[1]; @@ -1335,7 +1327,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, if (is_multicast_ether_addr(hdr->addr3)) memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); else - if (mesh_nexthop_lookup(skb, odev)) + if (mesh_nexthop_lookup(skb, osdata)) return 0; if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, @@ -1889,8 +1881,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, goto out; hdr = (struct ieee80211_hdr *) skb->data; - hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_BEACON); + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_BEACON); num_beacons = &ifsta->num_beacons; } else if (ieee80211_vif_is_mesh(&sdata->vif)) { @@ -1916,7 +1908,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, *pos++ = WLAN_EID_SSID; *pos++ = 0x0; - mesh_mgmt_ies_add(skb, sdata->dev); + mesh_mgmt_ies_add(skb, sdata); num_beacons = &sdata->u.sta.num_beacons; } else { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0d463c80c40..f40c060341a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -91,45 +91,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, return NULL; } -int ieee80211_get_hdrlen(u16 fc) -{ - int hdrlen = 24; - - switch (fc & IEEE80211_FCTL_FTYPE) { - case IEEE80211_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen = 30; /* Addr4 */ - /* - * The QoS Control field is two bytes and its presence is - * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to - * hdrlen if that bit is set. - * This works by masking out the bit and shifting it to - * bit position 1 so the result has the value 0 or 2. - */ - hdrlen += (fc & IEEE80211_STYPE_QOS_DATA) - >> (ilog2(IEEE80211_STYPE_QOS_DATA)-1); - break; - case IEEE80211_FTYPE_CTL: - /* - * ACK and CTS are 10 bytes, all others 16. To see how - * to get this condition consider - * subtype mask: 0b0000000011110000 (0x00F0) - * ACK subtype: 0b0000000011010000 (0x00D0) - * CTS subtype: 0b0000000011000000 (0x00C0) - * bits that matter: ^^^ (0x00E0) - * value of those: 0b0000000011000000 (0x00C0) - */ - if ((fc & 0xE0) == 0xC0) - hdrlen = 10; - else - hdrlen = 16; - break; - } - - return hdrlen; -} -EXPORT_SYMBOL(ieee80211_get_hdrlen); - unsigned int ieee80211_hdrlen(__le16 fc) { unsigned int hdrlen = 24; @@ -386,6 +347,13 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw) } EXPORT_SYMBOL(ieee80211_stop_queues); +int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) +{ + struct ieee80211_local *local = hw_to_local(hw); + return __netif_subqueue_stopped(local->mdev, queue); +} +EXPORT_SYMBOL(ieee80211_queue_stopped); + void ieee80211_wake_queues(struct ieee80211_hw *hw) { int i; diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 5c2bf0a3d4d..376c84987e4 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -228,11 +228,10 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, return -1; hdrlen = ieee80211_hdrlen(hdr->frame_control); - - if (skb->len < 8 + hdrlen) + if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN) return -1; - len = skb->len - hdrlen - 8; + len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN; keyidx = skb->data[hdrlen + 3] >> 6; @@ -292,9 +291,10 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) ieee80211_rx_result ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) { - if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && - ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; + + if (!ieee80211_is_data(hdr->frame_control) && + !ieee80211_is_auth(hdr->frame_control)) return RX_CONTINUE; if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { @@ -303,7 +303,7 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) { ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); /* remove ICV */ - skb_trim(rx->skb, rx->skb->len - 4); + skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); } return RX_CONTINUE; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 34fa8ed1e78..beae664ab48 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -27,22 +27,19 @@ #include "aes_ccm.h" -static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, +static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr, int idx, int alg, int remove, int set_tx_key, const u8 *_key, size_t key_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; struct ieee80211_key *key; - struct ieee80211_sub_if_data *sdata; int err; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", - dev->name, idx); + sdata->dev->name, idx); return -EINVAL; } @@ -127,11 +124,11 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, if (sdata->vif.type == IEEE80211_IF_TYPE_STA || sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length); + int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); if (ret) return ret; sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; - ieee80211_sta_req_auth(dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); return 0; } @@ -333,12 +330,11 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, return 0; } -int ieee80211_set_freq(struct net_device *dev, int freqMHz) +int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) { int ret = -EINVAL; struct ieee80211_channel *chan; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); @@ -346,7 +342,7 @@ int ieee80211_set_freq(struct net_device *dev, int freqMHz) if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && chan->flags & IEEE80211_CHAN_NO_IBSS) { printk(KERN_DEBUG "%s: IBSS not allowed on frequency " - "%d MHz\n", dev->name, chan->center_freq); + "%d MHz\n", sdata->dev->name, chan->center_freq); return ret; } local->oper_channel = chan; @@ -379,14 +375,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, IEEE80211_STA_AUTO_CHANNEL_SEL; return 0; } else - return ieee80211_set_freq(dev, + return ieee80211_set_freq(sdata, ieee80211_channel_to_frequency(freq->m)); } else { int i, div = 1000000; for (i = 0; i < freq->e; i++) div /= 10; if (div > 0) - return ieee80211_set_freq(dev, freq->m / div); + return ieee80211_set_freq(sdata, freq->m / div); else return -EINVAL; } @@ -432,10 +428,10 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; else sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL; - ret = ieee80211_sta_set_ssid(dev, ssid, len); + ret = ieee80211_sta_set_ssid(sdata, ssid, len); if (ret) return ret; - ieee80211_sta_req_auth(dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); return 0; } @@ -460,7 +456,7 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == IEEE80211_IF_TYPE_STA || sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - int res = ieee80211_sta_get_ssid(dev, ssid, &len); + int res = ieee80211_sta_get_ssid(sdata, ssid, &len); if (res == 0) { data->length = len; data->flags = 1; @@ -504,10 +500,10 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL; else sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; - ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data); + ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data); if (ret) return ret; - ieee80211_sta_req_auth(dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); return 0; } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { /* @@ -539,8 +535,8 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == IEEE80211_IF_TYPE_STA || sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - if (sdata->u.sta.state == IEEE80211_ASSOCIATED || - sdata->u.sta.state == IEEE80211_IBSS_JOINED) { + if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED || + sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) { ap_addr->sa_family = ARPHRD_ETHER; memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN); return 0; @@ -584,7 +580,7 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, ssid_len = req->essid_len; } - return ieee80211_sta_req_scan(dev, ssid, ssid_len); + return ieee80211_sta_req_scan(sdata, ssid, ssid_len); } @@ -594,11 +590,14 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, { int res; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (local->sta_sw_scanning || local->sta_hw_scanning) return -EAGAIN; - res = ieee80211_sta_scan_results(dev, info, extra, data->length); + res = ieee80211_sta_scan_results(local, info, extra, data->length); if (res >= 0) { data->length = res; return 0; @@ -894,10 +893,10 @@ static int ieee80211_ioctl_siwmlme(struct net_device *dev, switch (mlme->cmd) { case IW_MLME_DEAUTH: /* TODO: mlme->addr.sa_data */ - return ieee80211_sta_deauthenticate(dev, mlme->reason_code); + return ieee80211_sta_deauthenticate(sdata, mlme->reason_code); case IW_MLME_DISASSOC: /* TODO: mlme->addr.sa_data */ - return ieee80211_sta_disassociate(dev, mlme->reason_code); + return ieee80211_sta_disassociate(sdata, mlme->reason_code); default: return -EOPNOTSUPP; } @@ -938,7 +937,7 @@ static int ieee80211_ioctl_siwencode(struct net_device *dev, } return ieee80211_set_encryption( - dev, bcaddr, + sdata, bcaddr, idx, alg, remove, !sdata->default_key, keybuf, erq->length); @@ -1184,7 +1183,7 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev, } else idx--; - return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg, + return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, remove, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 04de28c071a..465e274df7c 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h @@ -14,8 +14,6 @@ #include <linux/netdevice.h> #include "ieee80211_i.h" -#define QOS_CONTROL_LEN 2 - #define QOS_CONTROL_ACK_POLICY_NORMAL 0 #define QOS_CONTROL_ACK_POLICY_NOACK 1 diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 2f33df0dccc..78021780b88 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -127,7 +127,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_UNUSABLE; - mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx, + mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, (void *) skb->data); return RX_DROP_UNUSABLE; } diff --git a/net/rfkill/rfkill-input.h b/net/rfkill/rfkill-input.h index f63d0504568..bbfa646157c 100644 --- a/net/rfkill/rfkill-input.h +++ b/net/rfkill/rfkill-input.h @@ -13,5 +13,6 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state); void rfkill_epo(void); +void rfkill_restore_states(void); #endif /* __RFKILL_INPUT_H */ diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 35a9994e233..47e0b2d232e 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -44,7 +44,13 @@ module_param_named(default_state, rfkill_default_state, uint, 0444); MODULE_PARM_DESC(default_state, "Default initial state for all radio types, 0 = radio off"); -static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX]; +struct rfkill_gsw_state { + enum rfkill_state current_state; + enum rfkill_state default_state; +}; + +static struct rfkill_gsw_state rfkill_global_states[RFKILL_TYPE_MAX]; +static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list); @@ -195,6 +201,8 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, * BLOCK even a transmitter that is already in state * RFKILL_STATE_HARD_BLOCKED */ break; + default: + return -EINVAL; } if (force || state != rfkill->state) { @@ -213,22 +221,25 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, } /** - * rfkill_switch_all - Toggle state of all switches of given type + * __rfkill_switch_all - Toggle state of all switches of given type * @type: type of interfaces to be affected * @state: the new state * * This function toggles the state of all switches of given type, * unless a specific switch is claimed by userspace (in which case, * that switch is left alone) or suspended. + * + * Caller must have acquired rfkill_mutex. */ -void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) +static void __rfkill_switch_all(const enum rfkill_type type, + const enum rfkill_state state) { struct rfkill *rfkill; - mutex_lock(&rfkill_mutex); - - rfkill_states[type] = state; + if (unlikely(state >= RFKILL_STATE_MAX)) + return; + rfkill_global_states[type].current_state = state; list_for_each_entry(rfkill, &rfkill_list, node) { if ((!rfkill->user_claim) && (rfkill->type == type)) { mutex_lock(&rfkill->mutex); @@ -236,7 +247,20 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) mutex_unlock(&rfkill->mutex); } } +} +/** + * rfkill_switch_all - Toggle state of all switches of given type + * @type: type of interfaces to be affected + * @state: the new state + * + * Acquires rfkill_mutex and calls __rfkill_switch_all(@type, @state). + * Please refer to __rfkill_switch_all() for details. + */ +void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) +{ + mutex_lock(&rfkill_mutex); + __rfkill_switch_all(type, state); mutex_unlock(&rfkill_mutex); } EXPORT_SYMBOL(rfkill_switch_all); @@ -246,10 +270,14 @@ EXPORT_SYMBOL(rfkill_switch_all); * * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, * ignoring everything in its path but rfkill_mutex and rfkill->mutex. + * + * The global state before the EPO is saved and can be restored later + * using rfkill_restore_states(). */ void rfkill_epo(void) { struct rfkill *rfkill; + int i; mutex_lock(&rfkill_mutex); list_for_each_entry(rfkill, &rfkill_list, node) { @@ -257,11 +285,35 @@ void rfkill_epo(void) rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); mutex_unlock(&rfkill->mutex); } + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + rfkill_global_states[i].default_state = + rfkill_global_states[i].current_state; + rfkill_global_states[i].current_state = + RFKILL_STATE_SOFT_BLOCKED; + } mutex_unlock(&rfkill_mutex); } EXPORT_SYMBOL_GPL(rfkill_epo); /** + * rfkill_restore_states - restore global states + * + * Restore (and sync switches to) the global state from the + * states in rfkill_default_states. This can undo the effects of + * a call to rfkill_epo(). + */ +void rfkill_restore_states(void) +{ + int i; + + mutex_lock(&rfkill_mutex); + for (i = 0; i < RFKILL_TYPE_MAX; i++) + __rfkill_switch_all(i, rfkill_global_states[i].default_state); + mutex_unlock(&rfkill_mutex); +} +EXPORT_SYMBOL_GPL(rfkill_restore_states); + +/** * rfkill_force_state - Force the internal rfkill radio state * @rfkill: pointer to the rfkill class to modify. * @state: the current radio state the class should be forced to. @@ -282,9 +334,7 @@ int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) { enum rfkill_state oldstate; - if (state != RFKILL_STATE_SOFT_BLOCKED && - state != RFKILL_STATE_UNBLOCKED && - state != RFKILL_STATE_HARD_BLOCKED) + if (unlikely(state >= RFKILL_STATE_MAX)) return -EINVAL; mutex_lock(&rfkill->mutex); @@ -406,8 +456,8 @@ static ssize_t rfkill_claim_store(struct device *dev, if (!claim) { mutex_lock(&rfkill->mutex); rfkill_toggle_radio(rfkill, - rfkill_states[rfkill->type], - 0); + rfkill_global_states[rfkill->type].current_state, + 0); mutex_unlock(&rfkill->mutex); } rfkill->user_claim = claim; @@ -525,17 +575,53 @@ static struct class rfkill_class = { .dev_uevent = rfkill_dev_uevent, }; +static int rfkill_check_duplicity(const struct rfkill *rfkill) +{ + struct rfkill *p; + unsigned long seen[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; + + memset(seen, 0, sizeof(seen)); + + list_for_each_entry(p, &rfkill_list, node) { + if (p == rfkill) { + WARN_ON(1); + return -EEXIST; + } + set_bit(p->type, seen); + } + + /* 0: first switch of its kind */ + return test_bit(rfkill->type, seen); +} + static int rfkill_add_switch(struct rfkill *rfkill) { + int error; + mutex_lock(&rfkill_mutex); - rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); + error = rfkill_check_duplicity(rfkill); + if (error < 0) + goto unlock_out; + + if (!error) { + /* lock default after first use */ + set_bit(rfkill->type, rfkill_states_lockdflt); + rfkill_global_states[rfkill->type].current_state = + rfkill_global_states[rfkill->type].default_state; + } + + rfkill_toggle_radio(rfkill, + rfkill_global_states[rfkill->type].current_state, + 0); list_add_tail(&rfkill->node, &rfkill_list); + error = 0; +unlock_out: mutex_unlock(&rfkill_mutex); - return 0; + return error; } static void rfkill_remove_switch(struct rfkill *rfkill) @@ -562,7 +648,8 @@ static void rfkill_remove_switch(struct rfkill *rfkill) * NOTE: If registration fails the structure shoudl be freed by calling * rfkill_free() otherwise rfkill_unregister() should be used. */ -struct rfkill *rfkill_allocate(struct device *parent, enum rfkill_type type) +struct rfkill * __must_check rfkill_allocate(struct device *parent, + enum rfkill_type type) { struct rfkill *rfkill; struct device *dev; @@ -633,7 +720,7 @@ static void rfkill_led_trigger_unregister(struct rfkill *rfkill) * structure needs to be registered. Immediately from registration the * switch driver should be able to service calls to toggle_radio. */ -int rfkill_register(struct rfkill *rfkill) +int __must_check rfkill_register(struct rfkill *rfkill) { static atomic_t rfkill_no = ATOMIC_INIT(0); struct device *dev = &rfkill->dev; @@ -643,6 +730,8 @@ int rfkill_register(struct rfkill *rfkill) return -EINVAL; if (rfkill->type >= RFKILL_TYPE_MAX) return -EINVAL; + if (rfkill->state >= RFKILL_STATE_MAX) + return -EINVAL; snprintf(dev->bus_id, sizeof(dev->bus_id), "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1); @@ -683,6 +772,53 @@ void rfkill_unregister(struct rfkill *rfkill) } EXPORT_SYMBOL(rfkill_unregister); +/** + * rfkill_set_default - set initial value for a switch type + * @type - the type of switch to set the default state of + * @state - the new default state for that group of switches + * + * Sets the initial state rfkill should use for a given type. + * The following initial states are allowed: RFKILL_STATE_SOFT_BLOCKED + * and RFKILL_STATE_UNBLOCKED. + * + * This function is meant to be used by platform drivers for platforms + * that can save switch state across power down/reboot. + * + * The default state for each switch type can be changed exactly once. + * After a switch of that type is registered, the default state cannot + * be changed anymore. This guards against multiple drivers it the + * same platform trying to set the initial switch default state, which + * is not allowed. + * + * Returns -EPERM if the state has already been set once or is in use, + * so drivers likely want to either ignore or at most printk(KERN_NOTICE) + * if this function returns -EPERM. + * + * Returns 0 if the new default state was set, or an error if it + * could not be set. + */ +int rfkill_set_default(enum rfkill_type type, enum rfkill_state state) +{ + int error; + + if (type >= RFKILL_TYPE_MAX || + (state != RFKILL_STATE_SOFT_BLOCKED && + state != RFKILL_STATE_UNBLOCKED)) + return -EINVAL; + + mutex_lock(&rfkill_mutex); + + if (!test_and_set_bit(type, rfkill_states_lockdflt)) { + rfkill_global_states[type].default_state = state; + error = 0; + } else + error = -EPERM; + + mutex_unlock(&rfkill_mutex); + return error; +} +EXPORT_SYMBOL_GPL(rfkill_set_default); + /* * Rfkill module initialization/deinitialization. */ @@ -696,8 +832,8 @@ static int __init rfkill_init(void) rfkill_default_state != RFKILL_STATE_UNBLOCKED) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(rfkill_states); i++) - rfkill_states[i] = rfkill_default_state; + for (i = 0; i < RFKILL_TYPE_MAX; i++) + rfkill_global_states[i].default_state = rfkill_default_state; error = class_register(&rfkill_class); if (error) { diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 9372ec41ce8..45f442d7de4 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -332,7 +332,7 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) if (!s || tsize != s->tsize || (!tab && tsize > 0)) return ERR_PTR(-EINVAL); - spin_lock_bh(&qdisc_stab_lock); + spin_lock(&qdisc_stab_lock); list_for_each_entry(stab, &qdisc_stab_list, list) { if (memcmp(&stab->szopts, s, sizeof(*s))) @@ -340,11 +340,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16))) continue; stab->refcnt++; - spin_unlock_bh(&qdisc_stab_lock); + spin_unlock(&qdisc_stab_lock); return stab; } - spin_unlock_bh(&qdisc_stab_lock); + spin_unlock(&qdisc_stab_lock); stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL); if (!stab) @@ -355,9 +355,9 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) if (tsize > 0) memcpy(stab->data, tab, tsize * sizeof(u16)); - spin_lock_bh(&qdisc_stab_lock); + spin_lock(&qdisc_stab_lock); list_add_tail(&stab->list, &qdisc_stab_list); - spin_unlock_bh(&qdisc_stab_lock); + spin_unlock(&qdisc_stab_lock); return stab; } @@ -367,14 +367,14 @@ void qdisc_put_stab(struct qdisc_size_table *tab) if (!tab) return; - spin_lock_bh(&qdisc_stab_lock); + spin_lock(&qdisc_stab_lock); if (--tab->refcnt == 0) { list_del(&tab->list); kfree(tab); } - spin_unlock_bh(&qdisc_stab_lock); + spin_unlock(&qdisc_stab_lock); } EXPORT_SYMBOL(qdisc_put_stab); @@ -444,6 +444,10 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires) { ktime_t time; + if (test_bit(__QDISC_STATE_DEACTIVATED, + &qdisc_root_sleeping(wd->qdisc)->state)) + return; + wd->qdisc->flags |= TCQ_F_THROTTLED; time = ktime_set(0, 0); time = ktime_add_ns(time, PSCHED_US2NS(expires)); diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 47ef492c4ff..8fa90d68ec6 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -521,6 +521,10 @@ static void cbq_ovl_delay(struct cbq_class *cl) struct cbq_sched_data *q = qdisc_priv(cl->qdisc); psched_tdiff_t delay = cl->undertime - q->now; + if (test_bit(__QDISC_STATE_DEACTIVATED, + &qdisc_root_sleeping(cl->qdisc)->state)) + return; + if (!cl->delayed) { psched_time_t sched = q->now; ktime_t expires; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index e39a0cdef18..4c8d9f45ce0 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -103,6 +103,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, /* Initialize the CHUNKS parameter */ auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; + auth_chunks->param_hdr.length = htons(sizeof(sctp_paramhdr_t)); /* If the Add-IP functionality is enabled, we must * authenticate, ASCONF and ASCONF-ACK chunks @@ -110,8 +111,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, if (sctp_addip_enable) { auth_chunks->chunks[0] = SCTP_CID_ASCONF; auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; - auth_chunks->param_hdr.length = - htons(sizeof(sctp_paramhdr_t) + 2); + auth_chunks->param_hdr.length += htons(2); } } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index dbb79adf8f3..bb5c9ef1304 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3055,6 +3055,9 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, { struct sctp_authchunk val; + if (!sctp_auth_enable) + return -EACCES; + if (optlen != sizeof(struct sctp_authchunk)) return -EINVAL; if (copy_from_user(&val, optval, optlen)) @@ -3085,6 +3088,9 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, struct sctp_hmacalgo *hmacs; int err; + if (!sctp_auth_enable) + return -EACCES; + if (optlen < sizeof(struct sctp_hmacalgo)) return -EINVAL; @@ -3123,6 +3129,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk, struct sctp_association *asoc; int ret; + if (!sctp_auth_enable) + return -EACCES; + if (optlen <= sizeof(struct sctp_authkey)) return -EINVAL; @@ -3160,6 +3169,9 @@ static int sctp_setsockopt_active_key(struct sock *sk, struct sctp_authkeyid val; struct sctp_association *asoc; + if (!sctp_auth_enable) + return -EACCES; + if (optlen != sizeof(struct sctp_authkeyid)) return -EINVAL; if (copy_from_user(&val, optval, optlen)) @@ -3185,6 +3197,9 @@ static int sctp_setsockopt_del_key(struct sock *sk, struct sctp_authkeyid val; struct sctp_association *asoc; + if (!sctp_auth_enable) + return -EACCES; + if (optlen != sizeof(struct sctp_authkeyid)) return -EINVAL; if (copy_from_user(&val, optval, optlen)) @@ -5197,19 +5212,29 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, char __user *optval, int __user *optlen) { + struct sctp_hmacalgo __user *p = (void __user *)optval; struct sctp_hmac_algo_param *hmacs; - __u16 param_len; + __u16 data_len = 0; + u32 num_idents; + + if (!sctp_auth_enable) + return -EACCES; hmacs = sctp_sk(sk)->ep->auth_hmacs_list; - param_len = ntohs(hmacs->param_hdr.length); + data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); - if (len < param_len) + if (len < sizeof(struct sctp_hmacalgo) + data_len) return -EINVAL; + + len = sizeof(struct sctp_hmacalgo) + data_len; + num_idents = data_len / sizeof(u16); + if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, hmacs->hmac_ids, len)) + if (put_user(num_idents, &p->shmac_num_idents)) + return -EFAULT; + if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len)) return -EFAULT; - return 0; } @@ -5219,6 +5244,9 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, struct sctp_authkeyid val; struct sctp_association *asoc; + if (!sctp_auth_enable) + return -EACCES; + if (len < sizeof(struct sctp_authkeyid)) return -EINVAL; if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) @@ -5233,6 +5261,12 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, else val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; + len = sizeof(struct sctp_authkeyid); + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &val, len)) + return -EFAULT; + return 0; } @@ -5243,13 +5277,16 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, struct sctp_authchunks val; struct sctp_association *asoc; struct sctp_chunks_param *ch; - u32 num_chunks; + u32 num_chunks = 0; char __user *to; - if (len <= sizeof(struct sctp_authchunks)) + if (!sctp_auth_enable) + return -EACCES; + + if (len < sizeof(struct sctp_authchunks)) return -EINVAL; - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) return -EFAULT; to = p->gauth_chunks; @@ -5258,20 +5295,21 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, return -EINVAL; ch = asoc->peer.peer_chunks; + if (!ch) + goto num; /* See if the user provided enough room for all the data */ num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); if (len < num_chunks) return -EINVAL; - len = num_chunks; - if (put_user(len, optlen)) + if (copy_to_user(to, ch->chunks, num_chunks)) return -EFAULT; +num: + len = sizeof(struct sctp_authchunks) + num_chunks; + if (put_user(len, optlen)) return -EFAULT; if (put_user(num_chunks, &p->gauth_number_of_chunks)) return -EFAULT; - if (copy_to_user(to, ch->chunks, len)) - return -EFAULT; - return 0; } @@ -5282,13 +5320,16 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, struct sctp_authchunks val; struct sctp_association *asoc; struct sctp_chunks_param *ch; - u32 num_chunks; + u32 num_chunks = 0; char __user *to; - if (len <= sizeof(struct sctp_authchunks)) + if (!sctp_auth_enable) + return -EACCES; + + if (len < sizeof(struct sctp_authchunks)) return -EINVAL; - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) return -EFAULT; to = p->gauth_chunks; @@ -5301,17 +5342,21 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, else ch = sctp_sk(sk)->ep->auth_chunk_list; + if (!ch) + goto num; + num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); - if (len < num_chunks) + if (len < sizeof(struct sctp_authchunks) + num_chunks) return -EINVAL; - len = num_chunks; + if (copy_to_user(to, ch->chunks, num_chunks)) + return -EFAULT; +num: + len = sizeof(struct sctp_authchunks) + num_chunks; if (put_user(len, optlen)) return -EFAULT; if (put_user(num_chunks, &p->gauth_number_of_chunks)) return -EFAULT; - if (copy_to_user(to, ch->chunks, len)) - return -EFAULT; return 0; } |