diff options
Diffstat (limited to 'net')
151 files changed, 6886 insertions, 3423 deletions
diff --git a/net/802/psnap.c b/net/802/psnap.c index 70980baeb682..bdbffa3cb043 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c | |||
@@ -51,7 +51,7 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, | |||
51 | int rc = 1; | 51 | int rc = 1; |
52 | struct datalink_proto *proto; | 52 | struct datalink_proto *proto; |
53 | static struct packet_type snap_packet_type = { | 53 | static struct packet_type snap_packet_type = { |
54 | .type = __constant_htons(ETH_P_SNAP), | 54 | .type = cpu_to_be16(ETH_P_SNAP), |
55 | }; | 55 | }; |
56 | 56 | ||
57 | if (unlikely(!pskb_may_pull(skb, 5))) | 57 | if (unlikely(!pskb_may_pull(skb, 5))) |
@@ -95,15 +95,16 @@ static int snap_request(struct datalink_proto *dl, | |||
95 | EXPORT_SYMBOL(register_snap_client); | 95 | EXPORT_SYMBOL(register_snap_client); |
96 | EXPORT_SYMBOL(unregister_snap_client); | 96 | EXPORT_SYMBOL(unregister_snap_client); |
97 | 97 | ||
98 | static char snap_err_msg[] __initdata = | 98 | static const char snap_err_msg[] __initconst = |
99 | KERN_CRIT "SNAP - unable to register with 802.2\n"; | 99 | KERN_CRIT "SNAP - unable to register with 802.2\n"; |
100 | 100 | ||
101 | static int __init snap_init(void) | 101 | static int __init snap_init(void) |
102 | { | 102 | { |
103 | snap_sap = llc_sap_open(0xAA, snap_rcv); | 103 | snap_sap = llc_sap_open(0xAA, snap_rcv); |
104 | 104 | if (!snap_sap) { | |
105 | if (!snap_sap) | ||
106 | printk(snap_err_msg); | 105 | printk(snap_err_msg); |
106 | return -EBUSY; | ||
107 | } | ||
107 | 108 | ||
108 | return 0; | 109 | return 0; |
109 | } | 110 | } |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 41e8f65bd3f0..4163ea65bf41 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -52,7 +52,7 @@ static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; | |||
52 | static const char vlan_buggyright[] = "David S. Miller <davem@redhat.com>"; | 52 | static const char vlan_buggyright[] = "David S. Miller <davem@redhat.com>"; |
53 | 53 | ||
54 | static struct packet_type vlan_packet_type = { | 54 | static struct packet_type vlan_packet_type = { |
55 | .type = __constant_htons(ETH_P_8021Q), | 55 | .type = cpu_to_be16(ETH_P_8021Q), |
56 | .func = vlan_skb_recv, /* VLAN receive method */ | 56 | .func = vlan_skb_recv, /* VLAN receive method */ |
57 | }; | 57 | }; |
58 | 58 | ||
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index e9db889d6222..70435af153f2 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
@@ -85,7 +85,9 @@ static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, | |||
85 | goto drop; | 85 | goto drop; |
86 | 86 | ||
87 | for (p = napi->gro_list; p; p = p->next) { | 87 | for (p = napi->gro_list; p; p = p->next) { |
88 | NAPI_GRO_CB(p)->same_flow = p->dev == skb->dev; | 88 | NAPI_GRO_CB(p)->same_flow = |
89 | p->dev == skb->dev && !compare_ether_header( | ||
90 | skb_mac_header(p), skb_gro_mac_header(skb)); | ||
89 | NAPI_GRO_CB(p)->flush = 0; | 91 | NAPI_GRO_CB(p)->flush = 0; |
90 | } | 92 | } |
91 | 93 | ||
@@ -98,22 +100,9 @@ drop: | |||
98 | int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, | 100 | int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, |
99 | unsigned int vlan_tci, struct sk_buff *skb) | 101 | unsigned int vlan_tci, struct sk_buff *skb) |
100 | { | 102 | { |
101 | int err = NET_RX_SUCCESS; | 103 | skb_gro_reset_offset(skb); |
102 | 104 | ||
103 | switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { | 105 | return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb); |
104 | case -1: | ||
105 | return netif_receive_skb(skb); | ||
106 | |||
107 | case 2: | ||
108 | err = NET_RX_DROP; | ||
109 | /* fall through */ | ||
110 | |||
111 | case 1: | ||
112 | kfree_skb(skb); | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | return err; | ||
117 | } | 106 | } |
118 | EXPORT_SYMBOL(vlan_gro_receive); | 107 | EXPORT_SYMBOL(vlan_gro_receive); |
119 | 108 | ||
@@ -121,27 +110,11 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, | |||
121 | unsigned int vlan_tci, struct napi_gro_fraginfo *info) | 110 | unsigned int vlan_tci, struct napi_gro_fraginfo *info) |
122 | { | 111 | { |
123 | struct sk_buff *skb = napi_fraginfo_skb(napi, info); | 112 | struct sk_buff *skb = napi_fraginfo_skb(napi, info); |
124 | int err = NET_RX_DROP; | ||
125 | 113 | ||
126 | if (!skb) | 114 | if (!skb) |
127 | goto out; | 115 | return NET_RX_DROP; |
128 | |||
129 | err = NET_RX_SUCCESS; | ||
130 | |||
131 | switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { | ||
132 | case -1: | ||
133 | return netif_receive_skb(skb); | ||
134 | |||
135 | case 2: | ||
136 | err = NET_RX_DROP; | ||
137 | /* fall through */ | ||
138 | |||
139 | case 1: | ||
140 | napi_reuse_skb(napi, skb); | ||
141 | break; | ||
142 | } | ||
143 | 116 | ||
144 | out: | 117 | return napi_frags_finish(napi, skb, |
145 | return err; | 118 | vlan_gro_common(napi, grp, vlan_tci, skb)); |
146 | } | 119 | } |
147 | EXPORT_SYMBOL(vlan_gro_frags); | 120 | EXPORT_SYMBOL(vlan_gro_frags); |
diff --git a/net/Kconfig b/net/Kconfig index cdb8fdef6c4a..a12bae0e3fe9 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -185,6 +185,7 @@ source "net/x25/Kconfig" | |||
185 | source "net/lapb/Kconfig" | 185 | source "net/lapb/Kconfig" |
186 | source "net/econet/Kconfig" | 186 | source "net/econet/Kconfig" |
187 | source "net/wanrouter/Kconfig" | 187 | source "net/wanrouter/Kconfig" |
188 | source "net/phonet/Kconfig" | ||
188 | source "net/sched/Kconfig" | 189 | source "net/sched/Kconfig" |
189 | source "net/dcb/Kconfig" | 190 | source "net/dcb/Kconfig" |
190 | 191 | ||
@@ -229,7 +230,6 @@ source "net/can/Kconfig" | |||
229 | source "net/irda/Kconfig" | 230 | source "net/irda/Kconfig" |
230 | source "net/bluetooth/Kconfig" | 231 | source "net/bluetooth/Kconfig" |
231 | source "net/rxrpc/Kconfig" | 232 | source "net/rxrpc/Kconfig" |
232 | source "net/phonet/Kconfig" | ||
233 | 233 | ||
234 | config FIB_RULES | 234 | config FIB_RULES |
235 | bool | 235 | bool |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 5abce07fb50a..510a6782da8f 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -1861,12 +1861,12 @@ static struct notifier_block ddp_notifier = { | |||
1861 | }; | 1861 | }; |
1862 | 1862 | ||
1863 | static struct packet_type ltalk_packet_type = { | 1863 | static struct packet_type ltalk_packet_type = { |
1864 | .type = __constant_htons(ETH_P_LOCALTALK), | 1864 | .type = cpu_to_be16(ETH_P_LOCALTALK), |
1865 | .func = ltalk_rcv, | 1865 | .func = ltalk_rcv, |
1866 | }; | 1866 | }; |
1867 | 1867 | ||
1868 | static struct packet_type ppptalk_packet_type = { | 1868 | static struct packet_type ppptalk_packet_type = { |
1869 | .type = __constant_htons(ETH_P_PPPTALK), | 1869 | .type = cpu_to_be16(ETH_P_PPPTALK), |
1870 | .func = atalk_rcv, | 1870 | .func = atalk_rcv, |
1871 | }; | 1871 | }; |
1872 | 1872 | ||
diff --git a/net/appletalk/dev.c b/net/appletalk/dev.c index d856a62ab50f..72277d70c980 100644 --- a/net/appletalk/dev.c +++ b/net/appletalk/dev.c | |||
@@ -9,22 +9,20 @@ | |||
9 | #include <linux/if_arp.h> | 9 | #include <linux/if_arp.h> |
10 | #include <linux/if_ltalk.h> | 10 | #include <linux/if_ltalk.h> |
11 | 11 | ||
12 | #ifdef CONFIG_COMPAT_NET_DEV_OPS | ||
12 | static int ltalk_change_mtu(struct net_device *dev, int mtu) | 13 | static int ltalk_change_mtu(struct net_device *dev, int mtu) |
13 | { | 14 | { |
14 | return -EINVAL; | 15 | return -EINVAL; |
15 | } | 16 | } |
16 | 17 | #endif | |
17 | static int ltalk_mac_addr(struct net_device *dev, void *addr) | ||
18 | { | ||
19 | return -EINVAL; | ||
20 | } | ||
21 | 18 | ||
22 | static void ltalk_setup(struct net_device *dev) | 19 | static void ltalk_setup(struct net_device *dev) |
23 | { | 20 | { |
24 | /* Fill in the fields of the device structure with localtalk-generic values. */ | 21 | /* Fill in the fields of the device structure with localtalk-generic values. */ |
25 | 22 | ||
23 | #ifdef CONFIG_COMPAT_NET_DEV_OPS | ||
26 | dev->change_mtu = ltalk_change_mtu; | 24 | dev->change_mtu = ltalk_change_mtu; |
27 | dev->set_mac_address = ltalk_mac_addr; | 25 | #endif |
28 | 26 | ||
29 | dev->type = ARPHRD_LOCALTLK; | 27 | dev->type = ARPHRD_LOCALTLK; |
30 | dev->hard_header_len = LTALK_HLEN; | 28 | dev->hard_header_len = LTALK_HLEN; |
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index ea9438fc6855..334fcd4a4ea4 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -83,7 +83,6 @@ struct br2684_dev { | |||
83 | struct list_head br2684_devs; | 83 | struct list_head br2684_devs; |
84 | int number; | 84 | int number; |
85 | struct list_head brvccs; /* one device <=> one vcc (before xmas) */ | 85 | struct list_head brvccs; /* one device <=> one vcc (before xmas) */ |
86 | struct net_device_stats stats; | ||
87 | int mac_was_set; | 86 | int mac_was_set; |
88 | enum br2684_payload payload; | 87 | enum br2684_payload payload; |
89 | }; | 88 | }; |
@@ -148,9 +147,10 @@ static struct net_device *br2684_find_dev(const struct br2684_if_spec *s) | |||
148 | * the way for multiple vcc's per itf. Returns true if we can send, | 147 | * the way for multiple vcc's per itf. Returns true if we can send, |
149 | * otherwise false | 148 | * otherwise false |
150 | */ | 149 | */ |
151 | static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, | 150 | static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev, |
152 | struct br2684_vcc *brvcc) | 151 | struct br2684_vcc *brvcc) |
153 | { | 152 | { |
153 | struct br2684_dev *brdev = BRPRIV(dev); | ||
154 | struct atm_vcc *atmvcc; | 154 | struct atm_vcc *atmvcc; |
155 | int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2; | 155 | int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2; |
156 | 156 | ||
@@ -211,8 +211,8 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, | |||
211 | } | 211 | } |
212 | atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); | 212 | atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); |
213 | ATM_SKB(skb)->atm_options = atmvcc->atm_options; | 213 | ATM_SKB(skb)->atm_options = atmvcc->atm_options; |
214 | brdev->stats.tx_packets++; | 214 | dev->stats.tx_packets++; |
215 | brdev->stats.tx_bytes += skb->len; | 215 | dev->stats.tx_bytes += skb->len; |
216 | atmvcc->send(atmvcc, skb); | 216 | atmvcc->send(atmvcc, skb); |
217 | return 1; | 217 | return 1; |
218 | } | 218 | } |
@@ -233,14 +233,14 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
233 | brvcc = pick_outgoing_vcc(skb, brdev); | 233 | brvcc = pick_outgoing_vcc(skb, brdev); |
234 | if (brvcc == NULL) { | 234 | if (brvcc == NULL) { |
235 | pr_debug("no vcc attached to dev %s\n", dev->name); | 235 | pr_debug("no vcc attached to dev %s\n", dev->name); |
236 | brdev->stats.tx_errors++; | 236 | dev->stats.tx_errors++; |
237 | brdev->stats.tx_carrier_errors++; | 237 | dev->stats.tx_carrier_errors++; |
238 | /* netif_stop_queue(dev); */ | 238 | /* netif_stop_queue(dev); */ |
239 | dev_kfree_skb(skb); | 239 | dev_kfree_skb(skb); |
240 | read_unlock(&devs_lock); | 240 | read_unlock(&devs_lock); |
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
243 | if (!br2684_xmit_vcc(skb, brdev, brvcc)) { | 243 | if (!br2684_xmit_vcc(skb, dev, brvcc)) { |
244 | /* | 244 | /* |
245 | * We should probably use netif_*_queue() here, but that | 245 | * We should probably use netif_*_queue() here, but that |
246 | * involves added complication. We need to walk before | 246 | * involves added complication. We need to walk before |
@@ -248,27 +248,20 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
248 | * | 248 | * |
249 | * Don't free here! this pointer might be no longer valid! | 249 | * Don't free here! this pointer might be no longer valid! |
250 | */ | 250 | */ |
251 | brdev->stats.tx_errors++; | 251 | dev->stats.tx_errors++; |
252 | brdev->stats.tx_fifo_errors++; | 252 | dev->stats.tx_fifo_errors++; |
253 | } | 253 | } |
254 | read_unlock(&devs_lock); | 254 | read_unlock(&devs_lock); |
255 | return 0; | 255 | return 0; |
256 | } | 256 | } |
257 | 257 | ||
258 | static struct net_device_stats *br2684_get_stats(struct net_device *dev) | ||
259 | { | ||
260 | pr_debug("br2684_get_stats\n"); | ||
261 | return &BRPRIV(dev)->stats; | ||
262 | } | ||
263 | |||
264 | /* | 258 | /* |
265 | * We remember when the MAC gets set, so we don't override it later with | 259 | * We remember when the MAC gets set, so we don't override it later with |
266 | * the ESI of the ATM card of the first VC | 260 | * the ESI of the ATM card of the first VC |
267 | */ | 261 | */ |
268 | static int (*my_eth_mac_addr) (struct net_device *, void *); | ||
269 | static int br2684_mac_addr(struct net_device *dev, void *p) | 262 | static int br2684_mac_addr(struct net_device *dev, void *p) |
270 | { | 263 | { |
271 | int err = my_eth_mac_addr(dev, p); | 264 | int err = eth_mac_addr(dev, p); |
272 | if (!err) | 265 | if (!err) |
273 | BRPRIV(dev)->mac_was_set = 1; | 266 | BRPRIV(dev)->mac_was_set = 1; |
274 | return err; | 267 | return err; |
@@ -430,17 +423,17 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
430 | /* sigh, interface is down? */ | 423 | /* sigh, interface is down? */ |
431 | if (unlikely(!(net_dev->flags & IFF_UP))) | 424 | if (unlikely(!(net_dev->flags & IFF_UP))) |
432 | goto dropped; | 425 | goto dropped; |
433 | brdev->stats.rx_packets++; | 426 | net_dev->stats.rx_packets++; |
434 | brdev->stats.rx_bytes += skb->len; | 427 | net_dev->stats.rx_bytes += skb->len; |
435 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); | 428 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); |
436 | netif_rx(skb); | 429 | netif_rx(skb); |
437 | return; | 430 | return; |
438 | 431 | ||
439 | dropped: | 432 | dropped: |
440 | brdev->stats.rx_dropped++; | 433 | net_dev->stats.rx_dropped++; |
441 | goto free_skb; | 434 | goto free_skb; |
442 | error: | 435 | error: |
443 | brdev->stats.rx_errors++; | 436 | net_dev->stats.rx_errors++; |
444 | free_skb: | 437 | free_skb: |
445 | dev_kfree_skb(skb); | 438 | dev_kfree_skb(skb); |
446 | return; | 439 | return; |
@@ -531,8 +524,8 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
531 | 524 | ||
532 | skb->next = skb->prev = NULL; | 525 | skb->next = skb->prev = NULL; |
533 | br2684_push(atmvcc, skb); | 526 | br2684_push(atmvcc, skb); |
534 | BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; | 527 | skb->dev->stats.rx_bytes -= skb->len; |
535 | BRPRIV(skb->dev)->stats.rx_packets--; | 528 | skb->dev->stats.rx_packets--; |
536 | 529 | ||
537 | skb = next; | 530 | skb = next; |
538 | } | 531 | } |
@@ -544,17 +537,20 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
544 | return err; | 537 | return err; |
545 | } | 538 | } |
546 | 539 | ||
540 | static const struct net_device_ops br2684_netdev_ops = { | ||
541 | .ndo_start_xmit = br2684_start_xmit, | ||
542 | .ndo_set_mac_address = br2684_mac_addr, | ||
543 | .ndo_change_mtu = eth_change_mtu, | ||
544 | .ndo_validate_addr = eth_validate_addr, | ||
545 | }; | ||
546 | |||
547 | static void br2684_setup(struct net_device *netdev) | 547 | static void br2684_setup(struct net_device *netdev) |
548 | { | 548 | { |
549 | struct br2684_dev *brdev = BRPRIV(netdev); | 549 | struct br2684_dev *brdev = BRPRIV(netdev); |
550 | 550 | ||
551 | ether_setup(netdev); | 551 | ether_setup(netdev); |
552 | brdev->net_dev = netdev; | ||
553 | 552 | ||
554 | my_eth_mac_addr = netdev->set_mac_address; | 553 | netdev->netdev_ops = &br2684_netdev_ops; |
555 | netdev->set_mac_address = br2684_mac_addr; | ||
556 | netdev->hard_start_xmit = br2684_start_xmit; | ||
557 | netdev->get_stats = br2684_get_stats; | ||
558 | 554 | ||
559 | INIT_LIST_HEAD(&brdev->brvccs); | 555 | INIT_LIST_HEAD(&brdev->brvccs); |
560 | } | 556 | } |
@@ -565,10 +561,8 @@ static void br2684_setup_routed(struct net_device *netdev) | |||
565 | brdev->net_dev = netdev; | 561 | brdev->net_dev = netdev; |
566 | 562 | ||
567 | netdev->hard_header_len = 0; | 563 | netdev->hard_header_len = 0; |
568 | my_eth_mac_addr = netdev->set_mac_address; | 564 | |
569 | netdev->set_mac_address = br2684_mac_addr; | 565 | netdev->netdev_ops = &br2684_netdev_ops; |
570 | netdev->hard_start_xmit = br2684_start_xmit; | ||
571 | netdev->get_stats = br2684_get_stats; | ||
572 | netdev->addr_len = 0; | 566 | netdev->addr_len = 0; |
573 | netdev->mtu = 1500; | 567 | netdev->mtu = 1500; |
574 | netdev->type = ARPHRD_PPP; | 568 | netdev->type = ARPHRD_PPP; |
diff --git a/net/atm/clip.c b/net/atm/clip.c index 2d33a83be799..da42fd06b61f 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -214,15 +214,15 @@ static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
214 | skb->protocol = ((__be16 *) skb->data)[3]; | 214 | skb->protocol = ((__be16 *) skb->data)[3]; |
215 | skb_pull(skb, RFC1483LLC_LEN); | 215 | skb_pull(skb, RFC1483LLC_LEN); |
216 | if (skb->protocol == htons(ETH_P_ARP)) { | 216 | if (skb->protocol == htons(ETH_P_ARP)) { |
217 | PRIV(skb->dev)->stats.rx_packets++; | 217 | skb->dev->stats.rx_packets++; |
218 | PRIV(skb->dev)->stats.rx_bytes += skb->len; | 218 | skb->dev->stats.rx_bytes += skb->len; |
219 | clip_arp_rcv(skb); | 219 | clip_arp_rcv(skb); |
220 | return; | 220 | return; |
221 | } | 221 | } |
222 | } | 222 | } |
223 | clip_vcc->last_use = jiffies; | 223 | clip_vcc->last_use = jiffies; |
224 | PRIV(skb->dev)->stats.rx_packets++; | 224 | skb->dev->stats.rx_packets++; |
225 | PRIV(skb->dev)->stats.rx_bytes += skb->len; | 225 | skb->dev->stats.rx_bytes += skb->len; |
226 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); | 226 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); |
227 | netif_rx(skb); | 227 | netif_rx(skb); |
228 | } | 228 | } |
@@ -372,7 +372,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
372 | if (!skb->dst) { | 372 | if (!skb->dst) { |
373 | printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n"); | 373 | printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n"); |
374 | dev_kfree_skb(skb); | 374 | dev_kfree_skb(skb); |
375 | clip_priv->stats.tx_dropped++; | 375 | dev->stats.tx_dropped++; |
376 | return 0; | 376 | return 0; |
377 | } | 377 | } |
378 | if (!skb->dst->neighbour) { | 378 | if (!skb->dst->neighbour) { |
@@ -380,13 +380,13 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
380 | skb->dst->neighbour = clip_find_neighbour(skb->dst, 1); | 380 | skb->dst->neighbour = clip_find_neighbour(skb->dst, 1); |
381 | if (!skb->dst->neighbour) { | 381 | if (!skb->dst->neighbour) { |
382 | dev_kfree_skb(skb); /* lost that one */ | 382 | dev_kfree_skb(skb); /* lost that one */ |
383 | clip_priv->stats.tx_dropped++; | 383 | dev->stats.tx_dropped++; |
384 | return 0; | 384 | return 0; |
385 | } | 385 | } |
386 | #endif | 386 | #endif |
387 | printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n"); | 387 | printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n"); |
388 | dev_kfree_skb(skb); | 388 | dev_kfree_skb(skb); |
389 | clip_priv->stats.tx_dropped++; | 389 | dev->stats.tx_dropped++; |
390 | return 0; | 390 | return 0; |
391 | } | 391 | } |
392 | entry = NEIGH2ENTRY(skb->dst->neighbour); | 392 | entry = NEIGH2ENTRY(skb->dst->neighbour); |
@@ -400,7 +400,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
400 | skb_queue_tail(&entry->neigh->arp_queue, skb); | 400 | skb_queue_tail(&entry->neigh->arp_queue, skb); |
401 | else { | 401 | else { |
402 | dev_kfree_skb(skb); | 402 | dev_kfree_skb(skb); |
403 | clip_priv->stats.tx_dropped++; | 403 | dev->stats.tx_dropped++; |
404 | } | 404 | } |
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
@@ -423,8 +423,8 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
423 | printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n"); | 423 | printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n"); |
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | clip_priv->stats.tx_packets++; | 426 | dev->stats.tx_packets++; |
427 | clip_priv->stats.tx_bytes += skb->len; | 427 | dev->stats.tx_bytes += skb->len; |
428 | vcc->send(vcc, skb); | 428 | vcc->send(vcc, skb); |
429 | if (atm_may_send(vcc, 0)) { | 429 | if (atm_may_send(vcc, 0)) { |
430 | entry->vccs->xoff = 0; | 430 | entry->vccs->xoff = 0; |
@@ -443,11 +443,6 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
443 | return 0; | 443 | return 0; |
444 | } | 444 | } |
445 | 445 | ||
446 | static struct net_device_stats *clip_get_stats(struct net_device *dev) | ||
447 | { | ||
448 | return &PRIV(dev)->stats; | ||
449 | } | ||
450 | |||
451 | static int clip_mkip(struct atm_vcc *vcc, int timeout) | 446 | static int clip_mkip(struct atm_vcc *vcc, int timeout) |
452 | { | 447 | { |
453 | struct clip_vcc *clip_vcc; | 448 | struct clip_vcc *clip_vcc; |
@@ -501,8 +496,8 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) | |||
501 | 496 | ||
502 | skb_get(skb); | 497 | skb_get(skb); |
503 | clip_push(vcc, skb); | 498 | clip_push(vcc, skb); |
504 | PRIV(skb->dev)->stats.rx_packets--; | 499 | skb->dev->stats.rx_packets--; |
505 | PRIV(skb->dev)->stats.rx_bytes -= len; | 500 | skb->dev->stats.rx_bytes -= len; |
506 | kfree_skb(skb); | 501 | kfree_skb(skb); |
507 | } | 502 | } |
508 | 503 | ||
@@ -561,7 +556,6 @@ static void clip_setup(struct net_device *dev) | |||
561 | { | 556 | { |
562 | dev->hard_start_xmit = clip_start_xmit; | 557 | dev->hard_start_xmit = clip_start_xmit; |
563 | /* sg_xmit ... */ | 558 | /* sg_xmit ... */ |
564 | dev->get_stats = clip_get_stats; | ||
565 | dev->type = ARPHRD_ATM; | 559 | dev->type = ARPHRD_ATM; |
566 | dev->hard_header_len = RFC1483LLC_LEN; | 560 | dev->hard_header_len = RFC1483LLC_LEN; |
567 | dev->mtu = RFC1626_MTU; | 561 | dev->mtu = RFC1626_MTU; |
diff --git a/net/atm/lec.c b/net/atm/lec.c index e5e301550e8a..c0cba9a037e8 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -62,7 +62,6 @@ static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; | |||
62 | static int lec_open(struct net_device *dev); | 62 | static int lec_open(struct net_device *dev); |
63 | static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev); | 63 | static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev); |
64 | static int lec_close(struct net_device *dev); | 64 | static int lec_close(struct net_device *dev); |
65 | static struct net_device_stats *lec_get_stats(struct net_device *dev); | ||
66 | static void lec_init(struct net_device *dev); | 65 | static void lec_init(struct net_device *dev); |
67 | static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, | 66 | static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, |
68 | const unsigned char *mac_addr); | 67 | const unsigned char *mac_addr); |
@@ -218,28 +217,28 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc) | |||
218 | 217 | ||
219 | static int lec_open(struct net_device *dev) | 218 | static int lec_open(struct net_device *dev) |
220 | { | 219 | { |
221 | struct lec_priv *priv = netdev_priv(dev); | ||
222 | |||
223 | netif_start_queue(dev); | 220 | netif_start_queue(dev); |
224 | memset(&priv->stats, 0, sizeof(struct net_device_stats)); | 221 | memset(&dev->stats, 0, sizeof(struct net_device_stats)); |
225 | 222 | ||
226 | return 0; | 223 | return 0; |
227 | } | 224 | } |
228 | 225 | ||
229 | static __inline__ void | 226 | static void |
230 | lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv) | 227 | lec_send(struct atm_vcc *vcc, struct sk_buff *skb) |
231 | { | 228 | { |
229 | struct net_device *dev = skb->dev; | ||
230 | |||
232 | ATM_SKB(skb)->vcc = vcc; | 231 | ATM_SKB(skb)->vcc = vcc; |
233 | ATM_SKB(skb)->atm_options = vcc->atm_options; | 232 | ATM_SKB(skb)->atm_options = vcc->atm_options; |
234 | 233 | ||
235 | atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); | 234 | atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); |
236 | if (vcc->send(vcc, skb) < 0) { | 235 | if (vcc->send(vcc, skb) < 0) { |
237 | priv->stats.tx_dropped++; | 236 | dev->stats.tx_dropped++; |
238 | return; | 237 | return; |
239 | } | 238 | } |
240 | 239 | ||
241 | priv->stats.tx_packets++; | 240 | dev->stats.tx_packets++; |
242 | priv->stats.tx_bytes += skb->len; | 241 | dev->stats.tx_bytes += skb->len; |
243 | } | 242 | } |
244 | 243 | ||
245 | static void lec_tx_timeout(struct net_device *dev) | 244 | static void lec_tx_timeout(struct net_device *dev) |
@@ -270,7 +269,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
270 | pr_debug("lec_start_xmit called\n"); | 269 | pr_debug("lec_start_xmit called\n"); |
271 | if (!priv->lecd) { | 270 | if (!priv->lecd) { |
272 | printk("%s:No lecd attached\n", dev->name); | 271 | printk("%s:No lecd attached\n", dev->name); |
273 | priv->stats.tx_errors++; | 272 | dev->stats.tx_errors++; |
274 | netif_stop_queue(dev); | 273 | netif_stop_queue(dev); |
275 | return -EUNATCH; | 274 | return -EUNATCH; |
276 | } | 275 | } |
@@ -345,7 +344,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
345 | GFP_ATOMIC); | 344 | GFP_ATOMIC); |
346 | dev_kfree_skb(skb); | 345 | dev_kfree_skb(skb); |
347 | if (skb2 == NULL) { | 346 | if (skb2 == NULL) { |
348 | priv->stats.tx_dropped++; | 347 | dev->stats.tx_dropped++; |
349 | return 0; | 348 | return 0; |
350 | } | 349 | } |
351 | skb = skb2; | 350 | skb = skb2; |
@@ -380,7 +379,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
380 | ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", | 379 | ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", |
381 | dev->name); | 380 | dev->name); |
382 | pr_debug("MAC address %pM\n", lec_h->h_dest); | 381 | pr_debug("MAC address %pM\n", lec_h->h_dest); |
383 | priv->stats.tx_dropped++; | 382 | dev->stats.tx_dropped++; |
384 | dev_kfree_skb(skb); | 383 | dev_kfree_skb(skb); |
385 | } | 384 | } |
386 | goto out; | 385 | goto out; |
@@ -392,10 +391,10 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
392 | while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { | 391 | while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { |
393 | pr_debug("lec.c: emptying tx queue, "); | 392 | pr_debug("lec.c: emptying tx queue, "); |
394 | pr_debug("MAC address %pM\n", lec_h->h_dest); | 393 | pr_debug("MAC address %pM\n", lec_h->h_dest); |
395 | lec_send(vcc, skb2, priv); | 394 | lec_send(vcc, skb2); |
396 | } | 395 | } |
397 | 396 | ||
398 | lec_send(vcc, skb, priv); | 397 | lec_send(vcc, skb); |
399 | 398 | ||
400 | if (!atm_may_send(vcc, 0)) { | 399 | if (!atm_may_send(vcc, 0)) { |
401 | struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); | 400 | struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); |
@@ -427,15 +426,6 @@ static int lec_close(struct net_device *dev) | |||
427 | return 0; | 426 | return 0; |
428 | } | 427 | } |
429 | 428 | ||
430 | /* | ||
431 | * Get the current statistics. | ||
432 | * This may be called with the card open or closed. | ||
433 | */ | ||
434 | static struct net_device_stats *lec_get_stats(struct net_device *dev) | ||
435 | { | ||
436 | return &((struct lec_priv *)netdev_priv(dev))->stats; | ||
437 | } | ||
438 | |||
439 | static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) | 429 | static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) |
440 | { | 430 | { |
441 | unsigned long flags; | 431 | unsigned long flags; |
@@ -677,17 +667,19 @@ static void lec_set_multicast_list(struct net_device *dev) | |||
677 | return; | 667 | return; |
678 | } | 668 | } |
679 | 669 | ||
670 | static const struct net_device_ops lec_netdev_ops = { | ||
671 | .ndo_open = lec_open, | ||
672 | .ndo_stop = lec_close, | ||
673 | .ndo_start_xmit = lec_start_xmit, | ||
674 | .ndo_change_mtu = lec_change_mtu, | ||
675 | .ndo_tx_timeout = lec_tx_timeout, | ||
676 | .ndo_set_multicast_list = lec_set_multicast_list, | ||
677 | }; | ||
678 | |||
679 | |||
680 | static void lec_init(struct net_device *dev) | 680 | static void lec_init(struct net_device *dev) |
681 | { | 681 | { |
682 | dev->change_mtu = lec_change_mtu; | 682 | dev->netdev_ops = &lec_netdev_ops; |
683 | dev->open = lec_open; | ||
684 | dev->stop = lec_close; | ||
685 | dev->hard_start_xmit = lec_start_xmit; | ||
686 | dev->tx_timeout = lec_tx_timeout; | ||
687 | |||
688 | dev->get_stats = lec_get_stats; | ||
689 | dev->set_multicast_list = lec_set_multicast_list; | ||
690 | dev->do_ioctl = NULL; | ||
691 | printk("%s: Initialized!\n", dev->name); | 683 | printk("%s: Initialized!\n", dev->name); |
692 | } | 684 | } |
693 | 685 | ||
@@ -810,8 +802,8 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
810 | else | 802 | else |
811 | #endif | 803 | #endif |
812 | skb->protocol = eth_type_trans(skb, dev); | 804 | skb->protocol = eth_type_trans(skb, dev); |
813 | priv->stats.rx_packets++; | 805 | dev->stats.rx_packets++; |
814 | priv->stats.rx_bytes += skb->len; | 806 | dev->stats.rx_bytes += skb->len; |
815 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); | 807 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); |
816 | netif_rx(skb); | 808 | netif_rx(skb); |
817 | } | 809 | } |
@@ -1887,7 +1879,7 @@ restart: | |||
1887 | lec_arp_hold(entry); | 1879 | lec_arp_hold(entry); |
1888 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 1880 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
1889 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) | 1881 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) |
1890 | lec_send(vcc, skb, entry->priv); | 1882 | lec_send(vcc, skb); |
1891 | entry->last_used = jiffies; | 1883 | entry->last_used = jiffies; |
1892 | entry->status = ESI_FORWARD_DIRECT; | 1884 | entry->status = ESI_FORWARD_DIRECT; |
1893 | lec_arp_put(entry); | 1885 | lec_arp_put(entry); |
@@ -2305,7 +2297,7 @@ restart: | |||
2305 | lec_arp_hold(entry); | 2297 | lec_arp_hold(entry); |
2306 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2298 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2307 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) | 2299 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) |
2308 | lec_send(vcc, skb, entry->priv); | 2300 | lec_send(vcc, skb); |
2309 | entry->last_used = jiffies; | 2301 | entry->last_used = jiffies; |
2310 | entry->status = ESI_FORWARD_DIRECT; | 2302 | entry->status = ESI_FORWARD_DIRECT; |
2311 | lec_arp_put(entry); | 2303 | lec_arp_put(entry); |
diff --git a/net/atm/lec.h b/net/atm/lec.h index 0d376682c1a3..9d14d196cc1d 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h | |||
@@ -69,7 +69,6 @@ struct lane2_ops { | |||
69 | #define LEC_ARP_TABLE_SIZE 16 | 69 | #define LEC_ARP_TABLE_SIZE 16 |
70 | 70 | ||
71 | struct lec_priv { | 71 | struct lec_priv { |
72 | struct net_device_stats stats; | ||
73 | unsigned short lecid; /* Lecid of this client */ | 72 | unsigned short lecid; /* Lecid of this client */ |
74 | struct hlist_head lec_arp_empty_ones; | 73 | struct hlist_head lec_arp_empty_ones; |
75 | /* Used for storing VCC's that don't have a MAC address attached yet */ | 74 | /* Used for storing VCC's that don't have a MAC address attached yet */ |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 00d9e5e13158..d127fd3ba5c6 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -1986,7 +1986,7 @@ static const struct proto_ops ax25_proto_ops = { | |||
1986 | * Called by socket.c on kernel start up | 1986 | * Called by socket.c on kernel start up |
1987 | */ | 1987 | */ |
1988 | static struct packet_type ax25_packet_type = { | 1988 | static struct packet_type ax25_packet_type = { |
1989 | .type = __constant_htons(ETH_P_AX25), | 1989 | .type = cpu_to_be16(ETH_P_AX25), |
1990 | .dev = NULL, /* All devices */ | 1990 | .dev = NULL, /* All devices */ |
1991 | .func = ax25_kiss_rcv, | 1991 | .func = ax25_kiss_rcv, |
1992 | }; | 1992 | }; |
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index 8443af57a374..71338f112108 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c | |||
@@ -61,27 +61,24 @@ void ax25_protocol_release(unsigned int pid) | |||
61 | 61 | ||
62 | write_lock_bh(&protocol_list_lock); | 62 | write_lock_bh(&protocol_list_lock); |
63 | protocol = protocol_list; | 63 | protocol = protocol_list; |
64 | if (protocol == NULL) { | 64 | if (protocol == NULL) |
65 | write_unlock_bh(&protocol_list_lock); | 65 | goto out; |
66 | return; | ||
67 | } | ||
68 | 66 | ||
69 | if (protocol->pid == pid) { | 67 | if (protocol->pid == pid) { |
70 | protocol_list = protocol->next; | 68 | protocol_list = protocol->next; |
71 | write_unlock_bh(&protocol_list_lock); | 69 | goto out; |
72 | return; | ||
73 | } | 70 | } |
74 | 71 | ||
75 | while (protocol != NULL && protocol->next != NULL) { | 72 | while (protocol != NULL && protocol->next != NULL) { |
76 | if (protocol->next->pid == pid) { | 73 | if (protocol->next->pid == pid) { |
77 | s = protocol->next; | 74 | s = protocol->next; |
78 | protocol->next = protocol->next->next; | 75 | protocol->next = protocol->next->next; |
79 | write_unlock_bh(&protocol_list_lock); | 76 | goto out; |
80 | return; | ||
81 | } | 77 | } |
82 | 78 | ||
83 | protocol = protocol->next; | 79 | protocol = protocol->next; |
84 | } | 80 | } |
81 | out: | ||
85 | write_unlock_bh(&protocol_list_lock); | 82 | write_unlock_bh(&protocol_list_lock); |
86 | } | 83 | } |
87 | 84 | ||
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index cf754ace0b75..3953ac4214c8 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -107,7 +107,7 @@ static void fake_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
107 | 107 | ||
108 | static struct dst_ops fake_dst_ops = { | 108 | static struct dst_ops fake_dst_ops = { |
109 | .family = AF_INET, | 109 | .family = AF_INET, |
110 | .protocol = __constant_htons(ETH_P_IP), | 110 | .protocol = cpu_to_be16(ETH_P_IP), |
111 | .update_pmtu = fake_update_pmtu, | 111 | .update_pmtu = fake_update_pmtu, |
112 | .entries = ATOMIC_INIT(0), | 112 | .entries = ATOMIC_INIT(0), |
113 | }; | 113 | }; |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index ba7be195803c..fcffb3fb1177 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -98,7 +98,8 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port) | |||
98 | kfree_skb(skb); | 98 | kfree_skb(skb); |
99 | goto errout; | 99 | goto errout; |
100 | } | 100 | } |
101 | err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); | 101 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); |
102 | return; | ||
102 | errout: | 103 | errout: |
103 | if (err < 0) | 104 | if (err < 0) |
104 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | 105 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); |
diff --git a/net/can/af_can.c b/net/can/af_can.c index fa417ca6cbe6..d90e8dd975fc 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
@@ -828,7 +828,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, | |||
828 | */ | 828 | */ |
829 | 829 | ||
830 | static struct packet_type can_packet __read_mostly = { | 830 | static struct packet_type can_packet __read_mostly = { |
831 | .type = __constant_htons(ETH_P_CAN), | 831 | .type = cpu_to_be16(ETH_P_CAN), |
832 | .dev = NULL, | 832 | .dev = NULL, |
833 | .func = can_rcv, | 833 | .func = can_rcv, |
834 | }; | 834 | }; |
diff --git a/net/can/raw.c b/net/can/raw.c index 0703cba4bf9f..6aa154e806ae 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -648,6 +648,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
648 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); | 648 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); |
649 | if (err < 0) | 649 | if (err < 0) |
650 | goto free_skb; | 650 | goto free_skb; |
651 | err = sock_tx_timestamp(msg, sk, skb_tx(skb)); | ||
652 | if (err < 0) | ||
653 | goto free_skb; | ||
651 | skb->dev = dev; | 654 | skb->dev = dev; |
652 | skb->sk = sk; | 655 | skb->sk = sk; |
653 | 656 | ||
diff --git a/net/compat.c b/net/compat.c index a3a2ba0fac08..8d739053afe4 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -216,7 +216,7 @@ Efault: | |||
216 | int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) | 216 | int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) |
217 | { | 217 | { |
218 | struct compat_timeval ctv; | 218 | struct compat_timeval ctv; |
219 | struct compat_timespec cts; | 219 | struct compat_timespec cts[3]; |
220 | struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; | 220 | struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; |
221 | struct compat_cmsghdr cmhdr; | 221 | struct compat_cmsghdr cmhdr; |
222 | int cmlen; | 222 | int cmlen; |
@@ -233,12 +233,17 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat | |||
233 | data = &ctv; | 233 | data = &ctv; |
234 | len = sizeof(ctv); | 234 | len = sizeof(ctv); |
235 | } | 235 | } |
236 | if (level == SOL_SOCKET && type == SCM_TIMESTAMPNS) { | 236 | if (level == SOL_SOCKET && |
237 | (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) { | ||
238 | int count = type == SCM_TIMESTAMPNS ? 1 : 3; | ||
239 | int i; | ||
237 | struct timespec *ts = (struct timespec *)data; | 240 | struct timespec *ts = (struct timespec *)data; |
238 | cts.tv_sec = ts->tv_sec; | 241 | for (i = 0; i < count; i++) { |
239 | cts.tv_nsec = ts->tv_nsec; | 242 | cts[i].tv_sec = ts[i].tv_sec; |
243 | cts[i].tv_nsec = ts[i].tv_nsec; | ||
244 | } | ||
240 | data = &cts; | 245 | data = &cts; |
241 | len = sizeof(cts); | 246 | len = sizeof(cts[0]) * count; |
242 | } | 247 | } |
243 | 248 | ||
244 | cmlen = CMSG_COMPAT_LEN(len); | 249 | cmlen = CMSG_COMPAT_LEN(len); |
@@ -455,7 +460,7 @@ int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | |||
455 | struct timeval tv; | 460 | struct timeval tv; |
456 | 461 | ||
457 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 462 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
458 | sock_enable_timestamp(sk); | 463 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
459 | tv = ktime_to_timeval(sk->sk_stamp); | 464 | tv = ktime_to_timeval(sk->sk_stamp); |
460 | if (tv.tv_sec == -1) | 465 | if (tv.tv_sec == -1) |
461 | return err; | 466 | return err; |
@@ -479,7 +484,7 @@ int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *usersta | |||
479 | struct timespec ts; | 484 | struct timespec ts; |
480 | 485 | ||
481 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 486 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
482 | sock_enable_timestamp(sk); | 487 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
483 | ts = ktime_to_timespec(sk->sk_stamp); | 488 | ts = ktime_to_timespec(sk->sk_stamp); |
484 | if (ts.tv_sec == -1) | 489 | if (ts.tv_sec == -1) |
485 | return err; | 490 | return err; |
diff --git a/net/core/dev.c b/net/core/dev.c index a17e00662363..ac6ab12d3297 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -135,6 +135,14 @@ | |||
135 | /* This should be increased if a protocol with a bigger head is added. */ | 135 | /* This should be increased if a protocol with a bigger head is added. */ |
136 | #define GRO_MAX_HEAD (MAX_HEADER + 128) | 136 | #define GRO_MAX_HEAD (MAX_HEADER + 128) |
137 | 137 | ||
138 | enum { | ||
139 | GRO_MERGED, | ||
140 | GRO_MERGED_FREE, | ||
141 | GRO_HELD, | ||
142 | GRO_NORMAL, | ||
143 | GRO_DROP, | ||
144 | }; | ||
145 | |||
138 | /* | 146 | /* |
139 | * The list of packet types we will receive (as opposed to discard) | 147 | * The list of packet types we will receive (as opposed to discard) |
140 | * and the routines to invoke. | 148 | * and the routines to invoke. |
@@ -1668,6 +1676,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
1668 | struct netdev_queue *txq) | 1676 | struct netdev_queue *txq) |
1669 | { | 1677 | { |
1670 | const struct net_device_ops *ops = dev->netdev_ops; | 1678 | const struct net_device_ops *ops = dev->netdev_ops; |
1679 | int rc; | ||
1671 | 1680 | ||
1672 | prefetch(&dev->netdev_ops->ndo_start_xmit); | 1681 | prefetch(&dev->netdev_ops->ndo_start_xmit); |
1673 | if (likely(!skb->next)) { | 1682 | if (likely(!skb->next)) { |
@@ -1681,13 +1690,27 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
1681 | goto gso; | 1690 | goto gso; |
1682 | } | 1691 | } |
1683 | 1692 | ||
1684 | return ops->ndo_start_xmit(skb, dev); | 1693 | rc = ops->ndo_start_xmit(skb, dev); |
1694 | /* | ||
1695 | * TODO: if skb_orphan() was called by | ||
1696 | * dev->hard_start_xmit() (for example, the unmodified | ||
1697 | * igb driver does that; bnx2 doesn't), then | ||
1698 | * skb_tx_software_timestamp() will be unable to send | ||
1699 | * back the time stamp. | ||
1700 | * | ||
1701 | * How can this be prevented? Always create another | ||
1702 | * reference to the socket before calling | ||
1703 | * dev->hard_start_xmit()? Prevent that skb_orphan() | ||
1704 | * does anything in dev->hard_start_xmit() by clearing | ||
1705 | * the skb destructor before the call and restoring it | ||
1706 | * afterwards, then doing the skb_orphan() ourselves? | ||
1707 | */ | ||
1708 | return rc; | ||
1685 | } | 1709 | } |
1686 | 1710 | ||
1687 | gso: | 1711 | gso: |
1688 | do { | 1712 | do { |
1689 | struct sk_buff *nskb = skb->next; | 1713 | struct sk_buff *nskb = skb->next; |
1690 | int rc; | ||
1691 | 1714 | ||
1692 | skb->next = nskb->next; | 1715 | skb->next = nskb->next; |
1693 | nskb->next = NULL; | 1716 | nskb->next = NULL; |
@@ -1708,56 +1731,20 @@ out_kfree_skb: | |||
1708 | return 0; | 1731 | return 0; |
1709 | } | 1732 | } |
1710 | 1733 | ||
1711 | static u32 simple_tx_hashrnd; | 1734 | static u32 skb_tx_hashrnd; |
1712 | static int simple_tx_hashrnd_initialized = 0; | ||
1713 | 1735 | ||
1714 | static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) | 1736 | static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb) |
1715 | { | 1737 | { |
1716 | u32 addr1, addr2, ports; | 1738 | u32 hash; |
1717 | u32 hash, ihl; | ||
1718 | u8 ip_proto = 0; | ||
1719 | |||
1720 | if (unlikely(!simple_tx_hashrnd_initialized)) { | ||
1721 | get_random_bytes(&simple_tx_hashrnd, 4); | ||
1722 | simple_tx_hashrnd_initialized = 1; | ||
1723 | } | ||
1724 | |||
1725 | switch (skb->protocol) { | ||
1726 | case htons(ETH_P_IP): | ||
1727 | if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) | ||
1728 | ip_proto = ip_hdr(skb)->protocol; | ||
1729 | addr1 = ip_hdr(skb)->saddr; | ||
1730 | addr2 = ip_hdr(skb)->daddr; | ||
1731 | ihl = ip_hdr(skb)->ihl; | ||
1732 | break; | ||
1733 | case htons(ETH_P_IPV6): | ||
1734 | ip_proto = ipv6_hdr(skb)->nexthdr; | ||
1735 | addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3]; | ||
1736 | addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3]; | ||
1737 | ihl = (40 >> 2); | ||
1738 | break; | ||
1739 | default: | ||
1740 | return 0; | ||
1741 | } | ||
1742 | 1739 | ||
1740 | if (skb_rx_queue_recorded(skb)) { | ||
1741 | hash = skb_get_rx_queue(skb); | ||
1742 | } else if (skb->sk && skb->sk->sk_hash) { | ||
1743 | hash = skb->sk->sk_hash; | ||
1744 | } else | ||
1745 | hash = skb->protocol; | ||
1743 | 1746 | ||
1744 | switch (ip_proto) { | 1747 | hash = jhash_1word(hash, skb_tx_hashrnd); |
1745 | case IPPROTO_TCP: | ||
1746 | case IPPROTO_UDP: | ||
1747 | case IPPROTO_DCCP: | ||
1748 | case IPPROTO_ESP: | ||
1749 | case IPPROTO_AH: | ||
1750 | case IPPROTO_SCTP: | ||
1751 | case IPPROTO_UDPLITE: | ||
1752 | ports = *((u32 *) (skb_network_header(skb) + (ihl * 4))); | ||
1753 | break; | ||
1754 | |||
1755 | default: | ||
1756 | ports = 0; | ||
1757 | break; | ||
1758 | } | ||
1759 | |||
1760 | hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd); | ||
1761 | 1748 | ||
1762 | return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); | 1749 | return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); |
1763 | } | 1750 | } |
@@ -1771,7 +1758,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, | |||
1771 | if (ops->ndo_select_queue) | 1758 | if (ops->ndo_select_queue) |
1772 | queue_index = ops->ndo_select_queue(dev, skb); | 1759 | queue_index = ops->ndo_select_queue(dev, skb); |
1773 | else if (dev->real_num_tx_queues > 1) | 1760 | else if (dev->real_num_tx_queues > 1) |
1774 | queue_index = simple_tx_hash(dev, skb); | 1761 | queue_index = skb_tx_hash(dev, skb); |
1775 | 1762 | ||
1776 | skb_set_queue_mapping(skb, queue_index); | 1763 | skb_set_queue_mapping(skb, queue_index); |
1777 | return netdev_get_tx_queue(dev, queue_index); | 1764 | return netdev_get_tx_queue(dev, queue_index); |
@@ -2267,12 +2254,6 @@ int netif_receive_skb(struct sk_buff *skb) | |||
2267 | 2254 | ||
2268 | rcu_read_lock(); | 2255 | rcu_read_lock(); |
2269 | 2256 | ||
2270 | /* Don't receive packets in an exiting network namespace */ | ||
2271 | if (!net_alive(dev_net(skb->dev))) { | ||
2272 | kfree_skb(skb); | ||
2273 | goto out; | ||
2274 | } | ||
2275 | |||
2276 | #ifdef CONFIG_NET_CLS_ACT | 2257 | #ifdef CONFIG_NET_CLS_ACT |
2277 | if (skb->tc_verd & TC_NCLS) { | 2258 | if (skb->tc_verd & TC_NCLS) { |
2278 | skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); | 2259 | skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); |
@@ -2303,6 +2284,8 @@ ncls: | |||
2303 | if (!skb) | 2284 | if (!skb) |
2304 | goto out; | 2285 | goto out; |
2305 | 2286 | ||
2287 | skb_orphan(skb); | ||
2288 | |||
2306 | type = skb->protocol; | 2289 | type = skb->protocol; |
2307 | list_for_each_entry_rcu(ptype, | 2290 | list_for_each_entry_rcu(ptype, |
2308 | &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { | 2291 | &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { |
@@ -2372,7 +2355,6 @@ static int napi_gro_complete(struct sk_buff *skb) | |||
2372 | 2355 | ||
2373 | out: | 2356 | out: |
2374 | skb_shinfo(skb)->gso_size = 0; | 2357 | skb_shinfo(skb)->gso_size = 0; |
2375 | __skb_push(skb, -skb_network_offset(skb)); | ||
2376 | return netif_receive_skb(skb); | 2358 | return netif_receive_skb(skb); |
2377 | } | 2359 | } |
2378 | 2360 | ||
@@ -2386,20 +2368,40 @@ void napi_gro_flush(struct napi_struct *napi) | |||
2386 | napi_gro_complete(skb); | 2368 | napi_gro_complete(skb); |
2387 | } | 2369 | } |
2388 | 2370 | ||
2371 | napi->gro_count = 0; | ||
2389 | napi->gro_list = NULL; | 2372 | napi->gro_list = NULL; |
2390 | } | 2373 | } |
2391 | EXPORT_SYMBOL(napi_gro_flush); | 2374 | EXPORT_SYMBOL(napi_gro_flush); |
2392 | 2375 | ||
2376 | void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) | ||
2377 | { | ||
2378 | unsigned int offset = skb_gro_offset(skb); | ||
2379 | |||
2380 | hlen += offset; | ||
2381 | if (hlen <= skb_headlen(skb)) | ||
2382 | return skb->data + offset; | ||
2383 | |||
2384 | if (unlikely(!skb_shinfo(skb)->nr_frags || | ||
2385 | skb_shinfo(skb)->frags[0].size <= | ||
2386 | hlen - skb_headlen(skb) || | ||
2387 | PageHighMem(skb_shinfo(skb)->frags[0].page))) | ||
2388 | return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; | ||
2389 | |||
2390 | return page_address(skb_shinfo(skb)->frags[0].page) + | ||
2391 | skb_shinfo(skb)->frags[0].page_offset + | ||
2392 | offset - skb_headlen(skb); | ||
2393 | } | ||
2394 | EXPORT_SYMBOL(skb_gro_header); | ||
2395 | |||
2393 | int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | 2396 | int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) |
2394 | { | 2397 | { |
2395 | struct sk_buff **pp = NULL; | 2398 | struct sk_buff **pp = NULL; |
2396 | struct packet_type *ptype; | 2399 | struct packet_type *ptype; |
2397 | __be16 type = skb->protocol; | 2400 | __be16 type = skb->protocol; |
2398 | struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK]; | 2401 | struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK]; |
2399 | int count = 0; | ||
2400 | int same_flow; | 2402 | int same_flow; |
2401 | int mac_len; | 2403 | int mac_len; |
2402 | int free; | 2404 | int ret; |
2403 | 2405 | ||
2404 | if (!(skb->dev->features & NETIF_F_GRO)) | 2406 | if (!(skb->dev->features & NETIF_F_GRO)) |
2405 | goto normal; | 2407 | goto normal; |
@@ -2409,30 +2411,16 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
2409 | 2411 | ||
2410 | rcu_read_lock(); | 2412 | rcu_read_lock(); |
2411 | list_for_each_entry_rcu(ptype, head, list) { | 2413 | list_for_each_entry_rcu(ptype, head, list) { |
2412 | struct sk_buff *p; | ||
2413 | |||
2414 | if (ptype->type != type || ptype->dev || !ptype->gro_receive) | 2414 | if (ptype->type != type || ptype->dev || !ptype->gro_receive) |
2415 | continue; | 2415 | continue; |
2416 | 2416 | ||
2417 | skb_reset_network_header(skb); | 2417 | skb_set_network_header(skb, skb_gro_offset(skb)); |
2418 | mac_len = skb->network_header - skb->mac_header; | 2418 | mac_len = skb->network_header - skb->mac_header; |
2419 | skb->mac_len = mac_len; | 2419 | skb->mac_len = mac_len; |
2420 | NAPI_GRO_CB(skb)->same_flow = 0; | 2420 | NAPI_GRO_CB(skb)->same_flow = 0; |
2421 | NAPI_GRO_CB(skb)->flush = 0; | 2421 | NAPI_GRO_CB(skb)->flush = 0; |
2422 | NAPI_GRO_CB(skb)->free = 0; | 2422 | NAPI_GRO_CB(skb)->free = 0; |
2423 | 2423 | ||
2424 | for (p = napi->gro_list; p; p = p->next) { | ||
2425 | count++; | ||
2426 | |||
2427 | if (!NAPI_GRO_CB(p)->same_flow) | ||
2428 | continue; | ||
2429 | |||
2430 | if (p->mac_len != mac_len || | ||
2431 | memcmp(skb_mac_header(p), skb_mac_header(skb), | ||
2432 | mac_len)) | ||
2433 | NAPI_GRO_CB(p)->same_flow = 0; | ||
2434 | } | ||
2435 | |||
2436 | pp = ptype->gro_receive(&napi->gro_list, skb); | 2424 | pp = ptype->gro_receive(&napi->gro_list, skb); |
2437 | break; | 2425 | break; |
2438 | } | 2426 | } |
@@ -2442,7 +2430,7 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
2442 | goto normal; | 2430 | goto normal; |
2443 | 2431 | ||
2444 | same_flow = NAPI_GRO_CB(skb)->same_flow; | 2432 | same_flow = NAPI_GRO_CB(skb)->same_flow; |
2445 | free = NAPI_GRO_CB(skb)->free; | 2433 | ret = NAPI_GRO_CB(skb)->free ? GRO_MERGED_FREE : GRO_MERGED; |
2446 | 2434 | ||
2447 | if (pp) { | 2435 | if (pp) { |
2448 | struct sk_buff *nskb = *pp; | 2436 | struct sk_buff *nskb = *pp; |
@@ -2450,27 +2438,35 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
2450 | *pp = nskb->next; | 2438 | *pp = nskb->next; |
2451 | nskb->next = NULL; | 2439 | nskb->next = NULL; |
2452 | napi_gro_complete(nskb); | 2440 | napi_gro_complete(nskb); |
2453 | count--; | 2441 | napi->gro_count--; |
2454 | } | 2442 | } |
2455 | 2443 | ||
2456 | if (same_flow) | 2444 | if (same_flow) |
2457 | goto ok; | 2445 | goto ok; |
2458 | 2446 | ||
2459 | if (NAPI_GRO_CB(skb)->flush || count >= MAX_GRO_SKBS) { | 2447 | if (NAPI_GRO_CB(skb)->flush || napi->gro_count >= MAX_GRO_SKBS) |
2460 | __skb_push(skb, -skb_network_offset(skb)); | ||
2461 | goto normal; | 2448 | goto normal; |
2462 | } | ||
2463 | 2449 | ||
2450 | napi->gro_count++; | ||
2464 | NAPI_GRO_CB(skb)->count = 1; | 2451 | NAPI_GRO_CB(skb)->count = 1; |
2465 | skb_shinfo(skb)->gso_size = skb->len; | 2452 | skb_shinfo(skb)->gso_size = skb_gro_len(skb); |
2466 | skb->next = napi->gro_list; | 2453 | skb->next = napi->gro_list; |
2467 | napi->gro_list = skb; | 2454 | napi->gro_list = skb; |
2455 | ret = GRO_HELD; | ||
2456 | |||
2457 | pull: | ||
2458 | if (unlikely(!pskb_may_pull(skb, skb_gro_offset(skb)))) { | ||
2459 | if (napi->gro_list == skb) | ||
2460 | napi->gro_list = skb->next; | ||
2461 | ret = GRO_DROP; | ||
2462 | } | ||
2468 | 2463 | ||
2469 | ok: | 2464 | ok: |
2470 | return free; | 2465 | return ret; |
2471 | 2466 | ||
2472 | normal: | 2467 | normal: |
2473 | return -1; | 2468 | ret = GRO_NORMAL; |
2469 | goto pull; | ||
2474 | } | 2470 | } |
2475 | EXPORT_SYMBOL(dev_gro_receive); | 2471 | EXPORT_SYMBOL(dev_gro_receive); |
2476 | 2472 | ||
@@ -2479,25 +2475,40 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
2479 | struct sk_buff *p; | 2475 | struct sk_buff *p; |
2480 | 2476 | ||
2481 | for (p = napi->gro_list; p; p = p->next) { | 2477 | for (p = napi->gro_list; p; p = p->next) { |
2482 | NAPI_GRO_CB(p)->same_flow = 1; | 2478 | NAPI_GRO_CB(p)->same_flow = !compare_ether_header( |
2479 | skb_mac_header(p), skb_gro_mac_header(skb)); | ||
2483 | NAPI_GRO_CB(p)->flush = 0; | 2480 | NAPI_GRO_CB(p)->flush = 0; |
2484 | } | 2481 | } |
2485 | 2482 | ||
2486 | return dev_gro_receive(napi, skb); | 2483 | return dev_gro_receive(napi, skb); |
2487 | } | 2484 | } |
2488 | 2485 | ||
2489 | int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | 2486 | int napi_skb_finish(int ret, struct sk_buff *skb) |
2490 | { | 2487 | { |
2491 | switch (__napi_gro_receive(napi, skb)) { | 2488 | int err = NET_RX_SUCCESS; |
2492 | case -1: | 2489 | |
2490 | switch (ret) { | ||
2491 | case GRO_NORMAL: | ||
2493 | return netif_receive_skb(skb); | 2492 | return netif_receive_skb(skb); |
2494 | 2493 | ||
2495 | case 1: | 2494 | case GRO_DROP: |
2495 | err = NET_RX_DROP; | ||
2496 | /* fall through */ | ||
2497 | |||
2498 | case GRO_MERGED_FREE: | ||
2496 | kfree_skb(skb); | 2499 | kfree_skb(skb); |
2497 | break; | 2500 | break; |
2498 | } | 2501 | } |
2499 | 2502 | ||
2500 | return NET_RX_SUCCESS; | 2503 | return err; |
2504 | } | ||
2505 | EXPORT_SYMBOL(napi_skb_finish); | ||
2506 | |||
2507 | int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | ||
2508 | { | ||
2509 | skb_gro_reset_offset(skb); | ||
2510 | |||
2511 | return napi_skb_finish(__napi_gro_receive(napi, skb), skb); | ||
2501 | } | 2512 | } |
2502 | EXPORT_SYMBOL(napi_gro_receive); | 2513 | EXPORT_SYMBOL(napi_gro_receive); |
2503 | 2514 | ||
@@ -2515,6 +2526,9 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, | |||
2515 | { | 2526 | { |
2516 | struct net_device *dev = napi->dev; | 2527 | struct net_device *dev = napi->dev; |
2517 | struct sk_buff *skb = napi->skb; | 2528 | struct sk_buff *skb = napi->skb; |
2529 | struct ethhdr *eth; | ||
2530 | skb_frag_t *frag; | ||
2531 | int i; | ||
2518 | 2532 | ||
2519 | napi->skb = NULL; | 2533 | napi->skb = NULL; |
2520 | 2534 | ||
@@ -2527,20 +2541,36 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, | |||
2527 | } | 2541 | } |
2528 | 2542 | ||
2529 | BUG_ON(info->nr_frags > MAX_SKB_FRAGS); | 2543 | BUG_ON(info->nr_frags > MAX_SKB_FRAGS); |
2544 | frag = &info->frags[info->nr_frags - 1]; | ||
2545 | |||
2546 | for (i = skb_shinfo(skb)->nr_frags; i < info->nr_frags; i++) { | ||
2547 | skb_fill_page_desc(skb, i, frag->page, frag->page_offset, | ||
2548 | frag->size); | ||
2549 | frag++; | ||
2550 | } | ||
2530 | skb_shinfo(skb)->nr_frags = info->nr_frags; | 2551 | skb_shinfo(skb)->nr_frags = info->nr_frags; |
2531 | memcpy(skb_shinfo(skb)->frags, info->frags, sizeof(info->frags)); | ||
2532 | 2552 | ||
2533 | skb->data_len = info->len; | 2553 | skb->data_len = info->len; |
2534 | skb->len += info->len; | 2554 | skb->len += info->len; |
2535 | skb->truesize += info->len; | 2555 | skb->truesize += info->len; |
2536 | 2556 | ||
2537 | if (!pskb_may_pull(skb, ETH_HLEN)) { | 2557 | skb_reset_mac_header(skb); |
2558 | skb_gro_reset_offset(skb); | ||
2559 | |||
2560 | eth = skb_gro_header(skb, sizeof(*eth)); | ||
2561 | if (!eth) { | ||
2538 | napi_reuse_skb(napi, skb); | 2562 | napi_reuse_skb(napi, skb); |
2539 | skb = NULL; | 2563 | skb = NULL; |
2540 | goto out; | 2564 | goto out; |
2541 | } | 2565 | } |
2542 | 2566 | ||
2543 | skb->protocol = eth_type_trans(skb, dev); | 2567 | skb_gro_pull(skb, sizeof(*eth)); |
2568 | |||
2569 | /* | ||
2570 | * This works because the only protocols we care about don't require | ||
2571 | * special handling. We'll fix it up properly at the end. | ||
2572 | */ | ||
2573 | skb->protocol = eth->h_proto; | ||
2544 | 2574 | ||
2545 | skb->ip_summed = info->ip_summed; | 2575 | skb->ip_summed = info->ip_summed; |
2546 | skb->csum = info->csum; | 2576 | skb->csum = info->csum; |
@@ -2550,29 +2580,43 @@ out: | |||
2550 | } | 2580 | } |
2551 | EXPORT_SYMBOL(napi_fraginfo_skb); | 2581 | EXPORT_SYMBOL(napi_fraginfo_skb); |
2552 | 2582 | ||
2553 | int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) | 2583 | int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) |
2554 | { | 2584 | { |
2555 | struct sk_buff *skb = napi_fraginfo_skb(napi, info); | 2585 | int err = NET_RX_SUCCESS; |
2556 | int err = NET_RX_DROP; | ||
2557 | 2586 | ||
2558 | if (!skb) | 2587 | switch (ret) { |
2559 | goto out; | 2588 | case GRO_NORMAL: |
2589 | case GRO_HELD: | ||
2590 | skb->protocol = eth_type_trans(skb, napi->dev); | ||
2560 | 2591 | ||
2561 | err = NET_RX_SUCCESS; | 2592 | if (ret == GRO_NORMAL) |
2593 | return netif_receive_skb(skb); | ||
2562 | 2594 | ||
2563 | switch (__napi_gro_receive(napi, skb)) { | 2595 | skb_gro_pull(skb, -ETH_HLEN); |
2564 | case -1: | 2596 | break; |
2565 | return netif_receive_skb(skb); | ||
2566 | 2597 | ||
2567 | case 0: | 2598 | case GRO_DROP: |
2568 | goto out; | 2599 | err = NET_RX_DROP; |
2569 | } | 2600 | /* fall through */ |
2570 | 2601 | ||
2571 | napi_reuse_skb(napi, skb); | 2602 | case GRO_MERGED_FREE: |
2603 | napi_reuse_skb(napi, skb); | ||
2604 | break; | ||
2605 | } | ||
2572 | 2606 | ||
2573 | out: | ||
2574 | return err; | 2607 | return err; |
2575 | } | 2608 | } |
2609 | EXPORT_SYMBOL(napi_frags_finish); | ||
2610 | |||
2611 | int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) | ||
2612 | { | ||
2613 | struct sk_buff *skb = napi_fraginfo_skb(napi, info); | ||
2614 | |||
2615 | if (!skb) | ||
2616 | return NET_RX_DROP; | ||
2617 | |||
2618 | return napi_frags_finish(napi, skb, __napi_gro_receive(napi, skb)); | ||
2619 | } | ||
2576 | EXPORT_SYMBOL(napi_gro_frags); | 2620 | EXPORT_SYMBOL(napi_gro_frags); |
2577 | 2621 | ||
2578 | static int process_backlog(struct napi_struct *napi, int quota) | 2622 | static int process_backlog(struct napi_struct *napi, int quota) |
@@ -2652,6 +2696,7 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi, | |||
2652 | int (*poll)(struct napi_struct *, int), int weight) | 2696 | int (*poll)(struct napi_struct *, int), int weight) |
2653 | { | 2697 | { |
2654 | INIT_LIST_HEAD(&napi->poll_list); | 2698 | INIT_LIST_HEAD(&napi->poll_list); |
2699 | napi->gro_count = 0; | ||
2655 | napi->gro_list = NULL; | 2700 | napi->gro_list = NULL; |
2656 | napi->skb = NULL; | 2701 | napi->skb = NULL; |
2657 | napi->poll = poll; | 2702 | napi->poll = poll; |
@@ -2680,6 +2725,7 @@ void netif_napi_del(struct napi_struct *napi) | |||
2680 | } | 2725 | } |
2681 | 2726 | ||
2682 | napi->gro_list = NULL; | 2727 | napi->gro_list = NULL; |
2728 | napi->gro_count = 0; | ||
2683 | } | 2729 | } |
2684 | EXPORT_SYMBOL(netif_napi_del); | 2730 | EXPORT_SYMBOL(netif_napi_del); |
2685 | 2731 | ||
@@ -3948,6 +3994,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
3948 | cmd == SIOCSMIIREG || | 3994 | cmd == SIOCSMIIREG || |
3949 | cmd == SIOCBRADDIF || | 3995 | cmd == SIOCBRADDIF || |
3950 | cmd == SIOCBRDELIF || | 3996 | cmd == SIOCBRDELIF || |
3997 | cmd == SIOCSHWTSTAMP || | ||
3951 | cmd == SIOCWANDEV) { | 3998 | cmd == SIOCWANDEV) { |
3952 | err = -EOPNOTSUPP; | 3999 | err = -EOPNOTSUPP; |
3953 | if (ops->ndo_do_ioctl) { | 4000 | if (ops->ndo_do_ioctl) { |
@@ -4102,6 +4149,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
4102 | case SIOCBONDCHANGEACTIVE: | 4149 | case SIOCBONDCHANGEACTIVE: |
4103 | case SIOCBRADDIF: | 4150 | case SIOCBRADDIF: |
4104 | case SIOCBRDELIF: | 4151 | case SIOCBRDELIF: |
4152 | case SIOCSHWTSTAMP: | ||
4105 | if (!capable(CAP_NET_ADMIN)) | 4153 | if (!capable(CAP_NET_ADMIN)) |
4106 | return -EPERM; | 4154 | return -EPERM; |
4107 | /* fall through */ | 4155 | /* fall through */ |
@@ -5185,6 +5233,7 @@ static int __init net_dev_init(void) | |||
5185 | queue->backlog.poll = process_backlog; | 5233 | queue->backlog.poll = process_backlog; |
5186 | queue->backlog.weight = weight_p; | 5234 | queue->backlog.weight = weight_p; |
5187 | queue->backlog.gro_list = NULL; | 5235 | queue->backlog.gro_list = NULL; |
5236 | queue->backlog.gro_count = 0; | ||
5188 | } | 5237 | } |
5189 | 5238 | ||
5190 | dev_boot_phase = 0; | 5239 | dev_boot_phase = 0; |
@@ -5217,6 +5266,14 @@ out: | |||
5217 | 5266 | ||
5218 | subsys_initcall(net_dev_init); | 5267 | subsys_initcall(net_dev_init); |
5219 | 5268 | ||
5269 | static int __init initialize_hashrnd(void) | ||
5270 | { | ||
5271 | get_random_bytes(&skb_tx_hashrnd, sizeof(skb_tx_hashrnd)); | ||
5272 | return 0; | ||
5273 | } | ||
5274 | |||
5275 | late_initcall_sync(initialize_hashrnd); | ||
5276 | |||
5220 | EXPORT_SYMBOL(__dev_get_by_index); | 5277 | EXPORT_SYMBOL(__dev_get_by_index); |
5221 | EXPORT_SYMBOL(__dev_get_by_name); | 5278 | EXPORT_SYMBOL(__dev_get_by_name); |
5222 | EXPORT_SYMBOL(__dev_remove_pack); | 5279 | EXPORT_SYMBOL(__dev_remove_pack); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 947710a36ced..244ca56dffac 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -209,34 +209,62 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) | |||
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | 211 | ||
212 | static int ethtool_set_rxhash(struct net_device *dev, void __user *useraddr) | 212 | static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) |
213 | { | 213 | { |
214 | struct ethtool_rxnfc cmd; | 214 | struct ethtool_rxnfc cmd; |
215 | 215 | ||
216 | if (!dev->ethtool_ops->set_rxhash) | 216 | if (!dev->ethtool_ops->set_rxnfc) |
217 | return -EOPNOTSUPP; | 217 | return -EOPNOTSUPP; |
218 | 218 | ||
219 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) | 219 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) |
220 | return -EFAULT; | 220 | return -EFAULT; |
221 | 221 | ||
222 | return dev->ethtool_ops->set_rxhash(dev, &cmd); | 222 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); |
223 | } | 223 | } |
224 | 224 | ||
225 | static int ethtool_get_rxhash(struct net_device *dev, void __user *useraddr) | 225 | static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) |
226 | { | 226 | { |
227 | struct ethtool_rxnfc info; | 227 | struct ethtool_rxnfc info; |
228 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
229 | int ret; | ||
230 | void *rule_buf = NULL; | ||
228 | 231 | ||
229 | if (!dev->ethtool_ops->get_rxhash) | 232 | if (!ops->get_rxnfc) |
230 | return -EOPNOTSUPP; | 233 | return -EOPNOTSUPP; |
231 | 234 | ||
232 | if (copy_from_user(&info, useraddr, sizeof(info))) | 235 | if (copy_from_user(&info, useraddr, sizeof(info))) |
233 | return -EFAULT; | 236 | return -EFAULT; |
234 | 237 | ||
235 | dev->ethtool_ops->get_rxhash(dev, &info); | 238 | if (info.cmd == ETHTOOL_GRXCLSRLALL) { |
239 | if (info.rule_cnt > 0) { | ||
240 | rule_buf = kmalloc(info.rule_cnt * sizeof(u32), | ||
241 | GFP_USER); | ||
242 | if (!rule_buf) | ||
243 | return -ENOMEM; | ||
244 | } | ||
245 | } | ||
236 | 246 | ||
247 | ret = ops->get_rxnfc(dev, &info, rule_buf); | ||
248 | if (ret < 0) | ||
249 | goto err_out; | ||
250 | |||
251 | ret = -EFAULT; | ||
237 | if (copy_to_user(useraddr, &info, sizeof(info))) | 252 | if (copy_to_user(useraddr, &info, sizeof(info))) |
238 | return -EFAULT; | 253 | goto err_out; |
239 | return 0; | 254 | |
255 | if (rule_buf) { | ||
256 | useraddr += offsetof(struct ethtool_rxnfc, rule_locs); | ||
257 | if (copy_to_user(useraddr, rule_buf, | ||
258 | info.rule_cnt * sizeof(u32))) | ||
259 | goto err_out; | ||
260 | } | ||
261 | ret = 0; | ||
262 | |||
263 | err_out: | ||
264 | if (rule_buf) | ||
265 | kfree(rule_buf); | ||
266 | |||
267 | return ret; | ||
240 | } | 268 | } |
241 | 269 | ||
242 | static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) | 270 | static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) |
@@ -901,6 +929,10 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
901 | case ETHTOOL_GFLAGS: | 929 | case ETHTOOL_GFLAGS: |
902 | case ETHTOOL_GPFLAGS: | 930 | case ETHTOOL_GPFLAGS: |
903 | case ETHTOOL_GRXFH: | 931 | case ETHTOOL_GRXFH: |
932 | case ETHTOOL_GRXRINGS: | ||
933 | case ETHTOOL_GRXCLSRLCNT: | ||
934 | case ETHTOOL_GRXCLSRULE: | ||
935 | case ETHTOOL_GRXCLSRLALL: | ||
904 | break; | 936 | break; |
905 | default: | 937 | default: |
906 | if (!capable(CAP_NET_ADMIN)) | 938 | if (!capable(CAP_NET_ADMIN)) |
@@ -1052,10 +1084,16 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1052 | dev->ethtool_ops->set_priv_flags); | 1084 | dev->ethtool_ops->set_priv_flags); |
1053 | break; | 1085 | break; |
1054 | case ETHTOOL_GRXFH: | 1086 | case ETHTOOL_GRXFH: |
1055 | rc = ethtool_get_rxhash(dev, useraddr); | 1087 | case ETHTOOL_GRXRINGS: |
1088 | case ETHTOOL_GRXCLSRLCNT: | ||
1089 | case ETHTOOL_GRXCLSRULE: | ||
1090 | case ETHTOOL_GRXCLSRLALL: | ||
1091 | rc = ethtool_get_rxnfc(dev, useraddr); | ||
1056 | break; | 1092 | break; |
1057 | case ETHTOOL_SRXFH: | 1093 | case ETHTOOL_SRXFH: |
1058 | rc = ethtool_set_rxhash(dev, useraddr); | 1094 | case ETHTOOL_SRXCLSRLDEL: |
1095 | case ETHTOOL_SRXCLSRLINS: | ||
1096 | rc = ethtool_set_rxnfc(dev, useraddr); | ||
1059 | break; | 1097 | break; |
1060 | case ETHTOOL_GGRO: | 1098 | case ETHTOOL_GGRO: |
1061 | rc = ethtool_get_gro(dev, useraddr); | 1099 | rc = ethtool_get_gro(dev, useraddr); |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 32b3a0152d7a..98691e1466b8 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -588,7 +588,8 @@ static void notify_rule_change(int event, struct fib_rule *rule, | |||
588 | goto errout; | 588 | goto errout; |
589 | } | 589 | } |
590 | 590 | ||
591 | err = rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL); | 591 | rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL); |
592 | return; | ||
592 | errout: | 593 | errout: |
593 | if (err < 0) | 594 | if (err < 0) |
594 | rtnl_set_sk_err(net, ops->nlgroup, err); | 595 | rtnl_set_sk_err(net, ops->nlgroup, err); |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 278a142d1047..e1144cb94b99 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -2534,7 +2534,8 @@ static void __neigh_notify(struct neighbour *n, int type, int flags) | |||
2534 | kfree_skb(skb); | 2534 | kfree_skb(skb); |
2535 | goto errout; | 2535 | goto errout; |
2536 | } | 2536 | } |
2537 | err = rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); | 2537 | rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); |
2538 | return; | ||
2538 | errout: | 2539 | errout: |
2539 | if (err < 0) | 2540 | if (err < 0) |
2540 | rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); | 2541 | rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 2adb1a7d361f..e3bebd36f053 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -157,9 +157,6 @@ static void cleanup_net(struct work_struct *work) | |||
157 | struct pernet_operations *ops; | 157 | struct pernet_operations *ops; |
158 | struct net *net; | 158 | struct net *net; |
159 | 159 | ||
160 | /* Be very certain incoming network packets will not find us */ | ||
161 | rcu_barrier(); | ||
162 | |||
163 | net = container_of(work, struct net, work); | 160 | net = container_of(work, struct net, work); |
164 | 161 | ||
165 | mutex_lock(&net_mutex); | 162 | mutex_lock(&net_mutex); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 790dd205bb5d..d78030f88bd0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -455,8 +455,8 @@ int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid) | |||
455 | return nlmsg_unicast(rtnl, skb, pid); | 455 | return nlmsg_unicast(rtnl, skb, pid); |
456 | } | 456 | } |
457 | 457 | ||
458 | int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, | 458 | void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, |
459 | struct nlmsghdr *nlh, gfp_t flags) | 459 | struct nlmsghdr *nlh, gfp_t flags) |
460 | { | 460 | { |
461 | struct sock *rtnl = net->rtnl; | 461 | struct sock *rtnl = net->rtnl; |
462 | int report = 0; | 462 | int report = 0; |
@@ -464,7 +464,7 @@ int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, | |||
464 | if (nlh) | 464 | if (nlh) |
465 | report = nlmsg_report(nlh); | 465 | report = nlmsg_report(nlh); |
466 | 466 | ||
467 | return nlmsg_notify(rtnl, skb, pid, group, report, flags); | 467 | nlmsg_notify(rtnl, skb, pid, group, report, flags); |
468 | } | 468 | } |
469 | 469 | ||
470 | void rtnl_set_sk_err(struct net *net, u32 group, int error) | 470 | void rtnl_set_sk_err(struct net *net, u32 group, int error) |
@@ -1246,7 +1246,8 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) | |||
1246 | kfree_skb(skb); | 1246 | kfree_skb(skb); |
1247 | goto errout; | 1247 | goto errout; |
1248 | } | 1248 | } |
1249 | err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); | 1249 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); |
1250 | return; | ||
1250 | errout: | 1251 | errout: |
1251 | if (err < 0) | 1252 | if (err < 0) |
1252 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | 1253 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c6a6b166f8d6..33640d99c8ed 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/rtnetlink.h> | 55 | #include <linux/rtnetlink.h> |
56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
57 | #include <linux/scatterlist.h> | 57 | #include <linux/scatterlist.h> |
58 | #include <linux/errqueue.h> | ||
58 | 59 | ||
59 | #include <net/protocol.h> | 60 | #include <net/protocol.h> |
60 | #include <net/dst.h> | 61 | #include <net/dst.h> |
@@ -123,6 +124,7 @@ void skb_over_panic(struct sk_buff *skb, int sz, void *here) | |||
123 | skb->dev ? skb->dev->name : "<NULL>"); | 124 | skb->dev ? skb->dev->name : "<NULL>"); |
124 | BUG(); | 125 | BUG(); |
125 | } | 126 | } |
127 | EXPORT_SYMBOL(skb_over_panic); | ||
126 | 128 | ||
127 | /** | 129 | /** |
128 | * skb_under_panic - private function | 130 | * skb_under_panic - private function |
@@ -142,6 +144,7 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) | |||
142 | skb->dev ? skb->dev->name : "<NULL>"); | 144 | skb->dev ? skb->dev->name : "<NULL>"); |
143 | BUG(); | 145 | BUG(); |
144 | } | 146 | } |
147 | EXPORT_SYMBOL(skb_under_panic); | ||
145 | 148 | ||
146 | /* Allocate a new skbuff. We do this ourselves so we can fill in a few | 149 | /* Allocate a new skbuff. We do this ourselves so we can fill in a few |
147 | * 'private' fields and also do memory statistics to find all the | 150 | * 'private' fields and also do memory statistics to find all the |
@@ -205,7 +208,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
205 | shinfo->gso_segs = 0; | 208 | shinfo->gso_segs = 0; |
206 | shinfo->gso_type = 0; | 209 | shinfo->gso_type = 0; |
207 | shinfo->ip6_frag_id = 0; | 210 | shinfo->ip6_frag_id = 0; |
211 | shinfo->tx_flags.flags = 0; | ||
208 | shinfo->frag_list = NULL; | 212 | shinfo->frag_list = NULL; |
213 | memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); | ||
209 | 214 | ||
210 | if (fclone) { | 215 | if (fclone) { |
211 | struct sk_buff *child = skb + 1; | 216 | struct sk_buff *child = skb + 1; |
@@ -223,6 +228,7 @@ nodata: | |||
223 | skb = NULL; | 228 | skb = NULL; |
224 | goto out; | 229 | goto out; |
225 | } | 230 | } |
231 | EXPORT_SYMBOL(__alloc_skb); | ||
226 | 232 | ||
227 | /** | 233 | /** |
228 | * __netdev_alloc_skb - allocate an skbuff for rx on a specific device | 234 | * __netdev_alloc_skb - allocate an skbuff for rx on a specific device |
@@ -250,6 +256,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, | |||
250 | } | 256 | } |
251 | return skb; | 257 | return skb; |
252 | } | 258 | } |
259 | EXPORT_SYMBOL(__netdev_alloc_skb); | ||
253 | 260 | ||
254 | struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask) | 261 | struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask) |
255 | { | 262 | { |
@@ -418,6 +425,7 @@ void __kfree_skb(struct sk_buff *skb) | |||
418 | skb_release_all(skb); | 425 | skb_release_all(skb); |
419 | kfree_skbmem(skb); | 426 | kfree_skbmem(skb); |
420 | } | 427 | } |
428 | EXPORT_SYMBOL(__kfree_skb); | ||
421 | 429 | ||
422 | /** | 430 | /** |
423 | * kfree_skb - free an sk_buff | 431 | * kfree_skb - free an sk_buff |
@@ -436,6 +444,7 @@ void kfree_skb(struct sk_buff *skb) | |||
436 | return; | 444 | return; |
437 | __kfree_skb(skb); | 445 | __kfree_skb(skb); |
438 | } | 446 | } |
447 | EXPORT_SYMBOL(kfree_skb); | ||
439 | 448 | ||
440 | /** | 449 | /** |
441 | * skb_recycle_check - check if skb can be reused for receive | 450 | * skb_recycle_check - check if skb can be reused for receive |
@@ -605,6 +614,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
605 | 614 | ||
606 | return __skb_clone(n, skb); | 615 | return __skb_clone(n, skb); |
607 | } | 616 | } |
617 | EXPORT_SYMBOL(skb_clone); | ||
608 | 618 | ||
609 | static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | 619 | static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) |
610 | { | 620 | { |
@@ -671,7 +681,7 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) | |||
671 | copy_skb_header(n, skb); | 681 | copy_skb_header(n, skb); |
672 | return n; | 682 | return n; |
673 | } | 683 | } |
674 | 684 | EXPORT_SYMBOL(skb_copy); | |
675 | 685 | ||
676 | /** | 686 | /** |
677 | * pskb_copy - create copy of an sk_buff with private head. | 687 | * pskb_copy - create copy of an sk_buff with private head. |
@@ -730,6 +740,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) | |||
730 | out: | 740 | out: |
731 | return n; | 741 | return n; |
732 | } | 742 | } |
743 | EXPORT_SYMBOL(pskb_copy); | ||
733 | 744 | ||
734 | /** | 745 | /** |
735 | * pskb_expand_head - reallocate header of &sk_buff | 746 | * pskb_expand_head - reallocate header of &sk_buff |
@@ -813,6 +824,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
813 | nodata: | 824 | nodata: |
814 | return -ENOMEM; | 825 | return -ENOMEM; |
815 | } | 826 | } |
827 | EXPORT_SYMBOL(pskb_expand_head); | ||
816 | 828 | ||
817 | /* Make private copy of skb with writable head and some headroom */ | 829 | /* Make private copy of skb with writable head and some headroom */ |
818 | 830 | ||
@@ -833,7 +845,7 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) | |||
833 | } | 845 | } |
834 | return skb2; | 846 | return skb2; |
835 | } | 847 | } |
836 | 848 | EXPORT_SYMBOL(skb_realloc_headroom); | |
837 | 849 | ||
838 | /** | 850 | /** |
839 | * skb_copy_expand - copy and expand sk_buff | 851 | * skb_copy_expand - copy and expand sk_buff |
@@ -898,6 +910,7 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, | |||
898 | 910 | ||
899 | return n; | 911 | return n; |
900 | } | 912 | } |
913 | EXPORT_SYMBOL(skb_copy_expand); | ||
901 | 914 | ||
902 | /** | 915 | /** |
903 | * skb_pad - zero pad the tail of an skb | 916 | * skb_pad - zero pad the tail of an skb |
@@ -943,6 +956,7 @@ free_skb: | |||
943 | kfree_skb(skb); | 956 | kfree_skb(skb); |
944 | return err; | 957 | return err; |
945 | } | 958 | } |
959 | EXPORT_SYMBOL(skb_pad); | ||
946 | 960 | ||
947 | /** | 961 | /** |
948 | * skb_put - add data to a buffer | 962 | * skb_put - add data to a buffer |
@@ -1100,6 +1114,7 @@ done: | |||
1100 | 1114 | ||
1101 | return 0; | 1115 | return 0; |
1102 | } | 1116 | } |
1117 | EXPORT_SYMBOL(___pskb_trim); | ||
1103 | 1118 | ||
1104 | /** | 1119 | /** |
1105 | * __pskb_pull_tail - advance tail of skb header | 1120 | * __pskb_pull_tail - advance tail of skb header |
@@ -1238,6 +1253,7 @@ pull_pages: | |||
1238 | 1253 | ||
1239 | return skb_tail_pointer(skb); | 1254 | return skb_tail_pointer(skb); |
1240 | } | 1255 | } |
1256 | EXPORT_SYMBOL(__pskb_pull_tail); | ||
1241 | 1257 | ||
1242 | /* Copy some data bits from skb to kernel buffer. */ | 1258 | /* Copy some data bits from skb to kernel buffer. */ |
1243 | 1259 | ||
@@ -1315,6 +1331,7 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) | |||
1315 | fault: | 1331 | fault: |
1316 | return -EFAULT; | 1332 | return -EFAULT; |
1317 | } | 1333 | } |
1334 | EXPORT_SYMBOL(skb_copy_bits); | ||
1318 | 1335 | ||
1319 | /* | 1336 | /* |
1320 | * Callback from splice_to_pipe(), if we need to release some pages | 1337 | * Callback from splice_to_pipe(), if we need to release some pages |
@@ -1325,14 +1342,39 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) | |||
1325 | put_page(spd->pages[i]); | 1342 | put_page(spd->pages[i]); |
1326 | } | 1343 | } |
1327 | 1344 | ||
1328 | static inline struct page *linear_to_page(struct page *page, unsigned int len, | 1345 | static inline struct page *linear_to_page(struct page *page, unsigned int *len, |
1329 | unsigned int offset) | 1346 | unsigned int *offset, |
1347 | struct sk_buff *skb) | ||
1330 | { | 1348 | { |
1331 | struct page *p = alloc_pages(GFP_KERNEL, 0); | 1349 | struct sock *sk = skb->sk; |
1350 | struct page *p = sk->sk_sndmsg_page; | ||
1351 | unsigned int off; | ||
1332 | 1352 | ||
1333 | if (!p) | 1353 | if (!p) { |
1334 | return NULL; | 1354 | new_page: |
1335 | memcpy(page_address(p) + offset, page_address(page) + offset, len); | 1355 | p = sk->sk_sndmsg_page = alloc_pages(sk->sk_allocation, 0); |
1356 | if (!p) | ||
1357 | return NULL; | ||
1358 | |||
1359 | off = sk->sk_sndmsg_off = 0; | ||
1360 | /* hold one ref to this page until it's full */ | ||
1361 | } else { | ||
1362 | unsigned int mlen; | ||
1363 | |||
1364 | off = sk->sk_sndmsg_off; | ||
1365 | mlen = PAGE_SIZE - off; | ||
1366 | if (mlen < 64 && mlen < *len) { | ||
1367 | put_page(p); | ||
1368 | goto new_page; | ||
1369 | } | ||
1370 | |||
1371 | *len = min_t(unsigned int, *len, mlen); | ||
1372 | } | ||
1373 | |||
1374 | memcpy(page_address(p) + off, page_address(page) + *offset, *len); | ||
1375 | sk->sk_sndmsg_off += *len; | ||
1376 | *offset = off; | ||
1377 | get_page(p); | ||
1336 | 1378 | ||
1337 | return p; | 1379 | return p; |
1338 | } | 1380 | } |
@@ -1341,21 +1383,21 @@ static inline struct page *linear_to_page(struct page *page, unsigned int len, | |||
1341 | * Fill page/offset/length into spd, if it can hold more pages. | 1383 | * Fill page/offset/length into spd, if it can hold more pages. |
1342 | */ | 1384 | */ |
1343 | static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, | 1385 | static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, |
1344 | unsigned int len, unsigned int offset, | 1386 | unsigned int *len, unsigned int offset, |
1345 | struct sk_buff *skb, int linear) | 1387 | struct sk_buff *skb, int linear) |
1346 | { | 1388 | { |
1347 | if (unlikely(spd->nr_pages == PIPE_BUFFERS)) | 1389 | if (unlikely(spd->nr_pages == PIPE_BUFFERS)) |
1348 | return 1; | 1390 | return 1; |
1349 | 1391 | ||
1350 | if (linear) { | 1392 | if (linear) { |
1351 | page = linear_to_page(page, len, offset); | 1393 | page = linear_to_page(page, len, &offset, skb); |
1352 | if (!page) | 1394 | if (!page) |
1353 | return 1; | 1395 | return 1; |
1354 | } else | 1396 | } else |
1355 | get_page(page); | 1397 | get_page(page); |
1356 | 1398 | ||
1357 | spd->pages[spd->nr_pages] = page; | 1399 | spd->pages[spd->nr_pages] = page; |
1358 | spd->partial[spd->nr_pages].len = len; | 1400 | spd->partial[spd->nr_pages].len = *len; |
1359 | spd->partial[spd->nr_pages].offset = offset; | 1401 | spd->partial[spd->nr_pages].offset = offset; |
1360 | spd->nr_pages++; | 1402 | spd->nr_pages++; |
1361 | 1403 | ||
@@ -1365,8 +1407,13 @@ static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, | |||
1365 | static inline void __segment_seek(struct page **page, unsigned int *poff, | 1407 | static inline void __segment_seek(struct page **page, unsigned int *poff, |
1366 | unsigned int *plen, unsigned int off) | 1408 | unsigned int *plen, unsigned int off) |
1367 | { | 1409 | { |
1410 | unsigned long n; | ||
1411 | |||
1368 | *poff += off; | 1412 | *poff += off; |
1369 | *page += *poff / PAGE_SIZE; | 1413 | n = *poff / PAGE_SIZE; |
1414 | if (n) | ||
1415 | *page = nth_page(*page, n); | ||
1416 | |||
1370 | *poff = *poff % PAGE_SIZE; | 1417 | *poff = *poff % PAGE_SIZE; |
1371 | *plen -= off; | 1418 | *plen -= off; |
1372 | } | 1419 | } |
@@ -1397,7 +1444,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff, | |||
1397 | /* the linear region may spread across several pages */ | 1444 | /* the linear region may spread across several pages */ |
1398 | flen = min_t(unsigned int, flen, PAGE_SIZE - poff); | 1445 | flen = min_t(unsigned int, flen, PAGE_SIZE - poff); |
1399 | 1446 | ||
1400 | if (spd_fill_page(spd, page, flen, poff, skb, linear)) | 1447 | if (spd_fill_page(spd, page, &flen, poff, skb, linear)) |
1401 | return 1; | 1448 | return 1; |
1402 | 1449 | ||
1403 | __segment_seek(&page, &poff, &plen, flen); | 1450 | __segment_seek(&page, &poff, &plen, flen); |
@@ -1590,7 +1637,6 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) | |||
1590 | fault: | 1637 | fault: |
1591 | return -EFAULT; | 1638 | return -EFAULT; |
1592 | } | 1639 | } |
1593 | |||
1594 | EXPORT_SYMBOL(skb_store_bits); | 1640 | EXPORT_SYMBOL(skb_store_bits); |
1595 | 1641 | ||
1596 | /* Checksum skb data. */ | 1642 | /* Checksum skb data. */ |
@@ -1667,6 +1713,7 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, | |||
1667 | 1713 | ||
1668 | return csum; | 1714 | return csum; |
1669 | } | 1715 | } |
1716 | EXPORT_SYMBOL(skb_checksum); | ||
1670 | 1717 | ||
1671 | /* Both of above in one bottle. */ | 1718 | /* Both of above in one bottle. */ |
1672 | 1719 | ||
@@ -1748,6 +1795,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, | |||
1748 | BUG_ON(len); | 1795 | BUG_ON(len); |
1749 | return csum; | 1796 | return csum; |
1750 | } | 1797 | } |
1798 | EXPORT_SYMBOL(skb_copy_and_csum_bits); | ||
1751 | 1799 | ||
1752 | void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) | 1800 | void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) |
1753 | { | 1801 | { |
@@ -1774,6 +1822,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) | |||
1774 | *((__sum16 *)(to + csstuff)) = csum_fold(csum); | 1822 | *((__sum16 *)(to + csstuff)) = csum_fold(csum); |
1775 | } | 1823 | } |
1776 | } | 1824 | } |
1825 | EXPORT_SYMBOL(skb_copy_and_csum_dev); | ||
1777 | 1826 | ||
1778 | /** | 1827 | /** |
1779 | * skb_dequeue - remove from the head of the queue | 1828 | * skb_dequeue - remove from the head of the queue |
@@ -1794,6 +1843,7 @@ struct sk_buff *skb_dequeue(struct sk_buff_head *list) | |||
1794 | spin_unlock_irqrestore(&list->lock, flags); | 1843 | spin_unlock_irqrestore(&list->lock, flags); |
1795 | return result; | 1844 | return result; |
1796 | } | 1845 | } |
1846 | EXPORT_SYMBOL(skb_dequeue); | ||
1797 | 1847 | ||
1798 | /** | 1848 | /** |
1799 | * skb_dequeue_tail - remove from the tail of the queue | 1849 | * skb_dequeue_tail - remove from the tail of the queue |
@@ -1813,6 +1863,7 @@ struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list) | |||
1813 | spin_unlock_irqrestore(&list->lock, flags); | 1863 | spin_unlock_irqrestore(&list->lock, flags); |
1814 | return result; | 1864 | return result; |
1815 | } | 1865 | } |
1866 | EXPORT_SYMBOL(skb_dequeue_tail); | ||
1816 | 1867 | ||
1817 | /** | 1868 | /** |
1818 | * skb_queue_purge - empty a list | 1869 | * skb_queue_purge - empty a list |
@@ -1828,6 +1879,7 @@ void skb_queue_purge(struct sk_buff_head *list) | |||
1828 | while ((skb = skb_dequeue(list)) != NULL) | 1879 | while ((skb = skb_dequeue(list)) != NULL) |
1829 | kfree_skb(skb); | 1880 | kfree_skb(skb); |
1830 | } | 1881 | } |
1882 | EXPORT_SYMBOL(skb_queue_purge); | ||
1831 | 1883 | ||
1832 | /** | 1884 | /** |
1833 | * skb_queue_head - queue a buffer at the list head | 1885 | * skb_queue_head - queue a buffer at the list head |
@@ -1848,6 +1900,7 @@ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) | |||
1848 | __skb_queue_head(list, newsk); | 1900 | __skb_queue_head(list, newsk); |
1849 | spin_unlock_irqrestore(&list->lock, flags); | 1901 | spin_unlock_irqrestore(&list->lock, flags); |
1850 | } | 1902 | } |
1903 | EXPORT_SYMBOL(skb_queue_head); | ||
1851 | 1904 | ||
1852 | /** | 1905 | /** |
1853 | * skb_queue_tail - queue a buffer at the list tail | 1906 | * skb_queue_tail - queue a buffer at the list tail |
@@ -1868,6 +1921,7 @@ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) | |||
1868 | __skb_queue_tail(list, newsk); | 1921 | __skb_queue_tail(list, newsk); |
1869 | spin_unlock_irqrestore(&list->lock, flags); | 1922 | spin_unlock_irqrestore(&list->lock, flags); |
1870 | } | 1923 | } |
1924 | EXPORT_SYMBOL(skb_queue_tail); | ||
1871 | 1925 | ||
1872 | /** | 1926 | /** |
1873 | * skb_unlink - remove a buffer from a list | 1927 | * skb_unlink - remove a buffer from a list |
@@ -1887,6 +1941,7 @@ void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) | |||
1887 | __skb_unlink(skb, list); | 1941 | __skb_unlink(skb, list); |
1888 | spin_unlock_irqrestore(&list->lock, flags); | 1942 | spin_unlock_irqrestore(&list->lock, flags); |
1889 | } | 1943 | } |
1944 | EXPORT_SYMBOL(skb_unlink); | ||
1890 | 1945 | ||
1891 | /** | 1946 | /** |
1892 | * skb_append - append a buffer | 1947 | * skb_append - append a buffer |
@@ -1906,7 +1961,7 @@ void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head | |||
1906 | __skb_queue_after(list, old, newsk); | 1961 | __skb_queue_after(list, old, newsk); |
1907 | spin_unlock_irqrestore(&list->lock, flags); | 1962 | spin_unlock_irqrestore(&list->lock, flags); |
1908 | } | 1963 | } |
1909 | 1964 | EXPORT_SYMBOL(skb_append); | |
1910 | 1965 | ||
1911 | /** | 1966 | /** |
1912 | * skb_insert - insert a buffer | 1967 | * skb_insert - insert a buffer |
@@ -1928,6 +1983,7 @@ void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head | |||
1928 | __skb_insert(newsk, old->prev, old, list); | 1983 | __skb_insert(newsk, old->prev, old, list); |
1929 | spin_unlock_irqrestore(&list->lock, flags); | 1984 | spin_unlock_irqrestore(&list->lock, flags); |
1930 | } | 1985 | } |
1986 | EXPORT_SYMBOL(skb_insert); | ||
1931 | 1987 | ||
1932 | static inline void skb_split_inside_header(struct sk_buff *skb, | 1988 | static inline void skb_split_inside_header(struct sk_buff *skb, |
1933 | struct sk_buff* skb1, | 1989 | struct sk_buff* skb1, |
@@ -2006,6 +2062,7 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len) | |||
2006 | else /* Second chunk has no header, nothing to copy. */ | 2062 | else /* Second chunk has no header, nothing to copy. */ |
2007 | skb_split_no_header(skb, skb1, len, pos); | 2063 | skb_split_no_header(skb, skb1, len, pos); |
2008 | } | 2064 | } |
2065 | EXPORT_SYMBOL(skb_split); | ||
2009 | 2066 | ||
2010 | /* Shifting from/to a cloned skb is a no-go. | 2067 | /* Shifting from/to a cloned skb is a no-go. |
2011 | * | 2068 | * |
@@ -2168,6 +2225,7 @@ void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from, | |||
2168 | st->frag_idx = st->stepped_offset = 0; | 2225 | st->frag_idx = st->stepped_offset = 0; |
2169 | st->frag_data = NULL; | 2226 | st->frag_data = NULL; |
2170 | } | 2227 | } |
2228 | EXPORT_SYMBOL(skb_prepare_seq_read); | ||
2171 | 2229 | ||
2172 | /** | 2230 | /** |
2173 | * skb_seq_read - Sequentially read skb data | 2231 | * skb_seq_read - Sequentially read skb data |
@@ -2255,6 +2313,7 @@ next_skb: | |||
2255 | 2313 | ||
2256 | return 0; | 2314 | return 0; |
2257 | } | 2315 | } |
2316 | EXPORT_SYMBOL(skb_seq_read); | ||
2258 | 2317 | ||
2259 | /** | 2318 | /** |
2260 | * skb_abort_seq_read - Abort a sequential read of skb data | 2319 | * skb_abort_seq_read - Abort a sequential read of skb data |
@@ -2268,6 +2327,7 @@ void skb_abort_seq_read(struct skb_seq_state *st) | |||
2268 | if (st->frag_data) | 2327 | if (st->frag_data) |
2269 | kunmap_skb_frag(st->frag_data); | 2328 | kunmap_skb_frag(st->frag_data); |
2270 | } | 2329 | } |
2330 | EXPORT_SYMBOL(skb_abort_seq_read); | ||
2271 | 2331 | ||
2272 | #define TS_SKB_CB(state) ((struct skb_seq_state *) &((state)->cb)) | 2332 | #define TS_SKB_CB(state) ((struct skb_seq_state *) &((state)->cb)) |
2273 | 2333 | ||
@@ -2310,6 +2370,7 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, | |||
2310 | ret = textsearch_find(config, state); | 2370 | ret = textsearch_find(config, state); |
2311 | return (ret <= to - from ? ret : UINT_MAX); | 2371 | return (ret <= to - from ? ret : UINT_MAX); |
2312 | } | 2372 | } |
2373 | EXPORT_SYMBOL(skb_find_text); | ||
2313 | 2374 | ||
2314 | /** | 2375 | /** |
2315 | * skb_append_datato_frags: - append the user data to a skb | 2376 | * skb_append_datato_frags: - append the user data to a skb |
@@ -2382,6 +2443,7 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, | |||
2382 | 2443 | ||
2383 | return 0; | 2444 | return 0; |
2384 | } | 2445 | } |
2446 | EXPORT_SYMBOL(skb_append_datato_frags); | ||
2385 | 2447 | ||
2386 | /** | 2448 | /** |
2387 | * skb_pull_rcsum - pull skb and update receive checksum | 2449 | * skb_pull_rcsum - pull skb and update receive checksum |
@@ -2569,7 +2631,6 @@ err: | |||
2569 | } | 2631 | } |
2570 | return ERR_PTR(err); | 2632 | return ERR_PTR(err); |
2571 | } | 2633 | } |
2572 | |||
2573 | EXPORT_SYMBOL_GPL(skb_segment); | 2634 | EXPORT_SYMBOL_GPL(skb_segment); |
2574 | 2635 | ||
2575 | int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | 2636 | int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) |
@@ -2577,17 +2638,23 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2577 | struct sk_buff *p = *head; | 2638 | struct sk_buff *p = *head; |
2578 | struct sk_buff *nskb; | 2639 | struct sk_buff *nskb; |
2579 | unsigned int headroom; | 2640 | unsigned int headroom; |
2580 | unsigned int hlen = p->data - skb_mac_header(p); | 2641 | unsigned int len = skb_gro_len(skb); |
2581 | unsigned int len = skb->len; | ||
2582 | 2642 | ||
2583 | if (hlen + p->len + len >= 65536) | 2643 | if (p->len + len >= 65536) |
2584 | return -E2BIG; | 2644 | return -E2BIG; |
2585 | 2645 | ||
2586 | if (skb_shinfo(p)->frag_list) | 2646 | if (skb_shinfo(p)->frag_list) |
2587 | goto merge; | 2647 | goto merge; |
2588 | else if (!skb_headlen(p) && !skb_headlen(skb) && | 2648 | else if (skb_headlen(skb) <= skb_gro_offset(skb)) { |
2589 | skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags < | 2649 | if (skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags > |
2590 | MAX_SKB_FRAGS) { | 2650 | MAX_SKB_FRAGS) |
2651 | return -E2BIG; | ||
2652 | |||
2653 | skb_shinfo(skb)->frags[0].page_offset += | ||
2654 | skb_gro_offset(skb) - skb_headlen(skb); | ||
2655 | skb_shinfo(skb)->frags[0].size -= | ||
2656 | skb_gro_offset(skb) - skb_headlen(skb); | ||
2657 | |||
2591 | memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags, | 2658 | memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags, |
2592 | skb_shinfo(skb)->frags, | 2659 | skb_shinfo(skb)->frags, |
2593 | skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t)); | 2660 | skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t)); |
@@ -2604,7 +2671,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2604 | } | 2671 | } |
2605 | 2672 | ||
2606 | headroom = skb_headroom(p); | 2673 | headroom = skb_headroom(p); |
2607 | nskb = netdev_alloc_skb(p->dev, headroom); | 2674 | nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p)); |
2608 | if (unlikely(!nskb)) | 2675 | if (unlikely(!nskb)) |
2609 | return -ENOMEM; | 2676 | return -ENOMEM; |
2610 | 2677 | ||
@@ -2612,12 +2679,15 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2612 | nskb->mac_len = p->mac_len; | 2679 | nskb->mac_len = p->mac_len; |
2613 | 2680 | ||
2614 | skb_reserve(nskb, headroom); | 2681 | skb_reserve(nskb, headroom); |
2682 | __skb_put(nskb, skb_gro_offset(p)); | ||
2615 | 2683 | ||
2616 | skb_set_mac_header(nskb, -hlen); | 2684 | skb_set_mac_header(nskb, skb_mac_header(p) - p->data); |
2617 | skb_set_network_header(nskb, skb_network_offset(p)); | 2685 | skb_set_network_header(nskb, skb_network_offset(p)); |
2618 | skb_set_transport_header(nskb, skb_transport_offset(p)); | 2686 | skb_set_transport_header(nskb, skb_transport_offset(p)); |
2619 | 2687 | ||
2620 | memcpy(skb_mac_header(nskb), skb_mac_header(p), hlen); | 2688 | __skb_pull(p, skb_gro_offset(p)); |
2689 | memcpy(skb_mac_header(nskb), skb_mac_header(p), | ||
2690 | p->data - skb_mac_header(p)); | ||
2621 | 2691 | ||
2622 | *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p); | 2692 | *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p); |
2623 | skb_shinfo(nskb)->frag_list = p; | 2693 | skb_shinfo(nskb)->frag_list = p; |
@@ -2636,6 +2706,17 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2636 | p = nskb; | 2706 | p = nskb; |
2637 | 2707 | ||
2638 | merge: | 2708 | merge: |
2709 | if (skb_gro_offset(skb) > skb_headlen(skb)) { | ||
2710 | skb_shinfo(skb)->frags[0].page_offset += | ||
2711 | skb_gro_offset(skb) - skb_headlen(skb); | ||
2712 | skb_shinfo(skb)->frags[0].size -= | ||
2713 | skb_gro_offset(skb) - skb_headlen(skb); | ||
2714 | skb_gro_reset_offset(skb); | ||
2715 | skb_gro_pull(skb, skb_headlen(skb)); | ||
2716 | } | ||
2717 | |||
2718 | __skb_pull(skb, skb_gro_offset(skb)); | ||
2719 | |||
2639 | p->prev->next = skb; | 2720 | p->prev->next = skb; |
2640 | p->prev = skb; | 2721 | p->prev = skb; |
2641 | skb_header_release(skb); | 2722 | skb_header_release(skb); |
@@ -2747,6 +2828,7 @@ int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int le | |||
2747 | 2828 | ||
2748 | return nsg; | 2829 | return nsg; |
2749 | } | 2830 | } |
2831 | EXPORT_SYMBOL_GPL(skb_to_sgvec); | ||
2750 | 2832 | ||
2751 | /** | 2833 | /** |
2752 | * skb_cow_data - Check that a socket buffer's data buffers are writable | 2834 | * skb_cow_data - Check that a socket buffer's data buffers are writable |
@@ -2856,6 +2938,45 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) | |||
2856 | 2938 | ||
2857 | return elt; | 2939 | return elt; |
2858 | } | 2940 | } |
2941 | EXPORT_SYMBOL_GPL(skb_cow_data); | ||
2942 | |||
2943 | void skb_tstamp_tx(struct sk_buff *orig_skb, | ||
2944 | struct skb_shared_hwtstamps *hwtstamps) | ||
2945 | { | ||
2946 | struct sock *sk = orig_skb->sk; | ||
2947 | struct sock_exterr_skb *serr; | ||
2948 | struct sk_buff *skb; | ||
2949 | int err; | ||
2950 | |||
2951 | if (!sk) | ||
2952 | return; | ||
2953 | |||
2954 | skb = skb_clone(orig_skb, GFP_ATOMIC); | ||
2955 | if (!skb) | ||
2956 | return; | ||
2957 | |||
2958 | if (hwtstamps) { | ||
2959 | *skb_hwtstamps(skb) = | ||
2960 | *hwtstamps; | ||
2961 | } else { | ||
2962 | /* | ||
2963 | * no hardware time stamps available, | ||
2964 | * so keep the skb_shared_tx and only | ||
2965 | * store software time stamp | ||
2966 | */ | ||
2967 | skb->tstamp = ktime_get_real(); | ||
2968 | } | ||
2969 | |||
2970 | serr = SKB_EXT_ERR(skb); | ||
2971 | memset(serr, 0, sizeof(*serr)); | ||
2972 | serr->ee.ee_errno = ENOMSG; | ||
2973 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | ||
2974 | err = sock_queue_err_skb(sk, skb); | ||
2975 | if (err) | ||
2976 | kfree_skb(skb); | ||
2977 | } | ||
2978 | EXPORT_SYMBOL_GPL(skb_tstamp_tx); | ||
2979 | |||
2859 | 2980 | ||
2860 | /** | 2981 | /** |
2861 | * skb_partial_csum_set - set up and verify partial csum values for packet | 2982 | * skb_partial_csum_set - set up and verify partial csum values for packet |
@@ -2884,6 +3005,7 @@ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off) | |||
2884 | skb->csum_offset = off; | 3005 | skb->csum_offset = off; |
2885 | return true; | 3006 | return true; |
2886 | } | 3007 | } |
3008 | EXPORT_SYMBOL_GPL(skb_partial_csum_set); | ||
2887 | 3009 | ||
2888 | void __skb_warn_lro_forwarding(const struct sk_buff *skb) | 3010 | void __skb_warn_lro_forwarding(const struct sk_buff *skb) |
2889 | { | 3011 | { |
@@ -2891,42 +3013,4 @@ void __skb_warn_lro_forwarding(const struct sk_buff *skb) | |||
2891 | pr_warning("%s: received packets cannot be forwarded" | 3013 | pr_warning("%s: received packets cannot be forwarded" |
2892 | " while LRO is enabled\n", skb->dev->name); | 3014 | " while LRO is enabled\n", skb->dev->name); |
2893 | } | 3015 | } |
2894 | |||
2895 | EXPORT_SYMBOL(___pskb_trim); | ||
2896 | EXPORT_SYMBOL(__kfree_skb); | ||
2897 | EXPORT_SYMBOL(kfree_skb); | ||
2898 | EXPORT_SYMBOL(__pskb_pull_tail); | ||
2899 | EXPORT_SYMBOL(__alloc_skb); | ||
2900 | EXPORT_SYMBOL(__netdev_alloc_skb); | ||
2901 | EXPORT_SYMBOL(pskb_copy); | ||
2902 | EXPORT_SYMBOL(pskb_expand_head); | ||
2903 | EXPORT_SYMBOL(skb_checksum); | ||
2904 | EXPORT_SYMBOL(skb_clone); | ||
2905 | EXPORT_SYMBOL(skb_copy); | ||
2906 | EXPORT_SYMBOL(skb_copy_and_csum_bits); | ||
2907 | EXPORT_SYMBOL(skb_copy_and_csum_dev); | ||
2908 | EXPORT_SYMBOL(skb_copy_bits); | ||
2909 | EXPORT_SYMBOL(skb_copy_expand); | ||
2910 | EXPORT_SYMBOL(skb_over_panic); | ||
2911 | EXPORT_SYMBOL(skb_pad); | ||
2912 | EXPORT_SYMBOL(skb_realloc_headroom); | ||
2913 | EXPORT_SYMBOL(skb_under_panic); | ||
2914 | EXPORT_SYMBOL(skb_dequeue); | ||
2915 | EXPORT_SYMBOL(skb_dequeue_tail); | ||
2916 | EXPORT_SYMBOL(skb_insert); | ||
2917 | EXPORT_SYMBOL(skb_queue_purge); | ||
2918 | EXPORT_SYMBOL(skb_queue_head); | ||
2919 | EXPORT_SYMBOL(skb_queue_tail); | ||
2920 | EXPORT_SYMBOL(skb_unlink); | ||
2921 | EXPORT_SYMBOL(skb_append); | ||
2922 | EXPORT_SYMBOL(skb_split); | ||
2923 | EXPORT_SYMBOL(skb_prepare_seq_read); | ||
2924 | EXPORT_SYMBOL(skb_seq_read); | ||
2925 | EXPORT_SYMBOL(skb_abort_seq_read); | ||
2926 | EXPORT_SYMBOL(skb_find_text); | ||
2927 | EXPORT_SYMBOL(skb_append_datato_frags); | ||
2928 | EXPORT_SYMBOL(__skb_warn_lro_forwarding); | 3016 | EXPORT_SYMBOL(__skb_warn_lro_forwarding); |
2929 | |||
2930 | EXPORT_SYMBOL_GPL(skb_to_sgvec); | ||
2931 | EXPORT_SYMBOL_GPL(skb_cow_data); | ||
2932 | EXPORT_SYMBOL_GPL(skb_partial_csum_set); | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 5f97caa158e8..8ee734ea5229 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -120,6 +120,7 @@ | |||
120 | #include <net/net_namespace.h> | 120 | #include <net/net_namespace.h> |
121 | #include <net/request_sock.h> | 121 | #include <net/request_sock.h> |
122 | #include <net/sock.h> | 122 | #include <net/sock.h> |
123 | #include <linux/net_tstamp.h> | ||
123 | #include <net/xfrm.h> | 124 | #include <net/xfrm.h> |
124 | #include <linux/ipsec.h> | 125 | #include <linux/ipsec.h> |
125 | 126 | ||
@@ -255,11 +256,14 @@ static void sock_warn_obsolete_bsdism(const char *name) | |||
255 | } | 256 | } |
256 | } | 257 | } |
257 | 258 | ||
258 | static void sock_disable_timestamp(struct sock *sk) | 259 | static void sock_disable_timestamp(struct sock *sk, int flag) |
259 | { | 260 | { |
260 | if (sock_flag(sk, SOCK_TIMESTAMP)) { | 261 | if (sock_flag(sk, flag)) { |
261 | sock_reset_flag(sk, SOCK_TIMESTAMP); | 262 | sock_reset_flag(sk, flag); |
262 | net_disable_timestamp(); | 263 | if (!sock_flag(sk, SOCK_TIMESTAMP) && |
264 | !sock_flag(sk, SOCK_TIMESTAMPING_RX_SOFTWARE)) { | ||
265 | net_disable_timestamp(); | ||
266 | } | ||
263 | } | 267 | } |
264 | } | 268 | } |
265 | 269 | ||
@@ -614,13 +618,38 @@ set_rcvbuf: | |||
614 | else | 618 | else |
615 | sock_set_flag(sk, SOCK_RCVTSTAMPNS); | 619 | sock_set_flag(sk, SOCK_RCVTSTAMPNS); |
616 | sock_set_flag(sk, SOCK_RCVTSTAMP); | 620 | sock_set_flag(sk, SOCK_RCVTSTAMP); |
617 | sock_enable_timestamp(sk); | 621 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
618 | } else { | 622 | } else { |
619 | sock_reset_flag(sk, SOCK_RCVTSTAMP); | 623 | sock_reset_flag(sk, SOCK_RCVTSTAMP); |
620 | sock_reset_flag(sk, SOCK_RCVTSTAMPNS); | 624 | sock_reset_flag(sk, SOCK_RCVTSTAMPNS); |
621 | } | 625 | } |
622 | break; | 626 | break; |
623 | 627 | ||
628 | case SO_TIMESTAMPING: | ||
629 | if (val & ~SOF_TIMESTAMPING_MASK) { | ||
630 | ret = EINVAL; | ||
631 | break; | ||
632 | } | ||
633 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, | ||
634 | val & SOF_TIMESTAMPING_TX_HARDWARE); | ||
635 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE, | ||
636 | val & SOF_TIMESTAMPING_TX_SOFTWARE); | ||
637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_RX_HARDWARE, | ||
638 | val & SOF_TIMESTAMPING_RX_HARDWARE); | ||
639 | if (val & SOF_TIMESTAMPING_RX_SOFTWARE) | ||
640 | sock_enable_timestamp(sk, | ||
641 | SOCK_TIMESTAMPING_RX_SOFTWARE); | ||
642 | else | ||
643 | sock_disable_timestamp(sk, | ||
644 | SOCK_TIMESTAMPING_RX_SOFTWARE); | ||
645 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_SOFTWARE, | ||
646 | val & SOF_TIMESTAMPING_SOFTWARE); | ||
647 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE, | ||
648 | val & SOF_TIMESTAMPING_SYS_HARDWARE); | ||
649 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE, | ||
650 | val & SOF_TIMESTAMPING_RAW_HARDWARE); | ||
651 | break; | ||
652 | |||
624 | case SO_RCVLOWAT: | 653 | case SO_RCVLOWAT: |
625 | if (val < 0) | 654 | if (val < 0) |
626 | val = INT_MAX; | 655 | val = INT_MAX; |
@@ -768,6 +797,24 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | |||
768 | v.val = sock_flag(sk, SOCK_RCVTSTAMPNS); | 797 | v.val = sock_flag(sk, SOCK_RCVTSTAMPNS); |
769 | break; | 798 | break; |
770 | 799 | ||
800 | case SO_TIMESTAMPING: | ||
801 | v.val = 0; | ||
802 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) | ||
803 | v.val |= SOF_TIMESTAMPING_TX_HARDWARE; | ||
804 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) | ||
805 | v.val |= SOF_TIMESTAMPING_TX_SOFTWARE; | ||
806 | if (sock_flag(sk, SOCK_TIMESTAMPING_RX_HARDWARE)) | ||
807 | v.val |= SOF_TIMESTAMPING_RX_HARDWARE; | ||
808 | if (sock_flag(sk, SOCK_TIMESTAMPING_RX_SOFTWARE)) | ||
809 | v.val |= SOF_TIMESTAMPING_RX_SOFTWARE; | ||
810 | if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) | ||
811 | v.val |= SOF_TIMESTAMPING_SOFTWARE; | ||
812 | if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE)) | ||
813 | v.val |= SOF_TIMESTAMPING_SYS_HARDWARE; | ||
814 | if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE)) | ||
815 | v.val |= SOF_TIMESTAMPING_RAW_HARDWARE; | ||
816 | break; | ||
817 | |||
771 | case SO_RCVTIMEO: | 818 | case SO_RCVTIMEO: |
772 | lv=sizeof(struct timeval); | 819 | lv=sizeof(struct timeval); |
773 | if (sk->sk_rcvtimeo == MAX_SCHEDULE_TIMEOUT) { | 820 | if (sk->sk_rcvtimeo == MAX_SCHEDULE_TIMEOUT) { |
@@ -969,7 +1016,8 @@ void sk_free(struct sock *sk) | |||
969 | rcu_assign_pointer(sk->sk_filter, NULL); | 1016 | rcu_assign_pointer(sk->sk_filter, NULL); |
970 | } | 1017 | } |
971 | 1018 | ||
972 | sock_disable_timestamp(sk); | 1019 | sock_disable_timestamp(sk, SOCK_TIMESTAMP); |
1020 | sock_disable_timestamp(sk, SOCK_TIMESTAMPING_RX_SOFTWARE); | ||
973 | 1021 | ||
974 | if (atomic_read(&sk->sk_omem_alloc)) | 1022 | if (atomic_read(&sk->sk_omem_alloc)) |
975 | printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n", | 1023 | printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n", |
@@ -1255,10 +1303,9 @@ static long sock_wait_for_wmem(struct sock * sk, long timeo) | |||
1255 | * Generic send/receive buffer handlers | 1303 | * Generic send/receive buffer handlers |
1256 | */ | 1304 | */ |
1257 | 1305 | ||
1258 | static struct sk_buff *sock_alloc_send_pskb(struct sock *sk, | 1306 | struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, |
1259 | unsigned long header_len, | 1307 | unsigned long data_len, int noblock, |
1260 | unsigned long data_len, | 1308 | int *errcode) |
1261 | int noblock, int *errcode) | ||
1262 | { | 1309 | { |
1263 | struct sk_buff *skb; | 1310 | struct sk_buff *skb; |
1264 | gfp_t gfp_mask; | 1311 | gfp_t gfp_mask; |
@@ -1338,6 +1385,7 @@ failure: | |||
1338 | *errcode = err; | 1385 | *errcode = err; |
1339 | return NULL; | 1386 | return NULL; |
1340 | } | 1387 | } |
1388 | EXPORT_SYMBOL(sock_alloc_send_pskb); | ||
1341 | 1389 | ||
1342 | struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, | 1390 | struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, |
1343 | int noblock, int *errcode) | 1391 | int noblock, int *errcode) |
@@ -1786,7 +1834,7 @@ int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | |||
1786 | { | 1834 | { |
1787 | struct timeval tv; | 1835 | struct timeval tv; |
1788 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 1836 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
1789 | sock_enable_timestamp(sk); | 1837 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
1790 | tv = ktime_to_timeval(sk->sk_stamp); | 1838 | tv = ktime_to_timeval(sk->sk_stamp); |
1791 | if (tv.tv_sec == -1) | 1839 | if (tv.tv_sec == -1) |
1792 | return -ENOENT; | 1840 | return -ENOENT; |
@@ -1802,7 +1850,7 @@ int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) | |||
1802 | { | 1850 | { |
1803 | struct timespec ts; | 1851 | struct timespec ts; |
1804 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 1852 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
1805 | sock_enable_timestamp(sk); | 1853 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
1806 | ts = ktime_to_timespec(sk->sk_stamp); | 1854 | ts = ktime_to_timespec(sk->sk_stamp); |
1807 | if (ts.tv_sec == -1) | 1855 | if (ts.tv_sec == -1) |
1808 | return -ENOENT; | 1856 | return -ENOENT; |
@@ -1814,11 +1862,20 @@ int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) | |||
1814 | } | 1862 | } |
1815 | EXPORT_SYMBOL(sock_get_timestampns); | 1863 | EXPORT_SYMBOL(sock_get_timestampns); |
1816 | 1864 | ||
1817 | void sock_enable_timestamp(struct sock *sk) | 1865 | void sock_enable_timestamp(struct sock *sk, int flag) |
1818 | { | 1866 | { |
1819 | if (!sock_flag(sk, SOCK_TIMESTAMP)) { | 1867 | if (!sock_flag(sk, flag)) { |
1820 | sock_set_flag(sk, SOCK_TIMESTAMP); | 1868 | sock_set_flag(sk, flag); |
1821 | net_enable_timestamp(); | 1869 | /* |
1870 | * we just set one of the two flags which require net | ||
1871 | * time stamping, but time stamping might have been on | ||
1872 | * already because of the other one | ||
1873 | */ | ||
1874 | if (!sock_flag(sk, | ||
1875 | flag == SOCK_TIMESTAMP ? | ||
1876 | SOCK_TIMESTAMPING_RX_SOFTWARE : | ||
1877 | SOCK_TIMESTAMP)) | ||
1878 | net_enable_timestamp(); | ||
1822 | } | 1879 | } |
1823 | } | 1880 | } |
1824 | 1881 | ||
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index f2230fc168e1..08a569ff02d1 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -42,9 +42,11 @@ | |||
42 | extern int dccp_debug; | 42 | extern int dccp_debug; |
43 | #define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a) | 43 | #define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a) |
44 | #define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a) | 44 | #define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a) |
45 | #define dccp_debug(fmt, a...) dccp_pr_debug_cat(KERN_DEBUG fmt, ##a) | ||
45 | #else | 46 | #else |
46 | #define dccp_pr_debug(format, a...) | 47 | #define dccp_pr_debug(format, a...) |
47 | #define dccp_pr_debug_cat(format, a...) | 48 | #define dccp_pr_debug_cat(format, a...) |
49 | #define dccp_debug(format, a...) | ||
48 | #endif | 50 | #endif |
49 | 51 | ||
50 | extern struct inet_hashinfo dccp_hashinfo; | 52 | extern struct inet_hashinfo dccp_hashinfo; |
@@ -95,9 +97,6 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo); | |||
95 | extern int sysctl_dccp_request_retries; | 97 | extern int sysctl_dccp_request_retries; |
96 | extern int sysctl_dccp_retries1; | 98 | extern int sysctl_dccp_retries1; |
97 | extern int sysctl_dccp_retries2; | 99 | extern int sysctl_dccp_retries2; |
98 | extern int sysctl_dccp_feat_sequence_window; | ||
99 | extern int sysctl_dccp_feat_rx_ccid; | ||
100 | extern int sysctl_dccp_feat_tx_ccid; | ||
101 | extern int sysctl_dccp_tx_qlen; | 100 | extern int sysctl_dccp_tx_qlen; |
102 | extern int sysctl_dccp_sync_ratelimit; | 101 | extern int sysctl_dccp_sync_ratelimit; |
103 | 102 | ||
@@ -409,23 +408,21 @@ static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack, | |||
409 | static inline void dccp_update_gsr(struct sock *sk, u64 seq) | 408 | static inline void dccp_update_gsr(struct sock *sk, u64 seq) |
410 | { | 409 | { |
411 | struct dccp_sock *dp = dccp_sk(sk); | 410 | struct dccp_sock *dp = dccp_sk(sk); |
412 | const struct dccp_minisock *dmsk = dccp_msk(sk); | ||
413 | 411 | ||
414 | dp->dccps_gsr = seq; | 412 | dp->dccps_gsr = seq; |
415 | dccp_set_seqno(&dp->dccps_swl, | 413 | /* Sequence validity window depends on remote Sequence Window (7.5.1) */ |
416 | dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4)); | 414 | dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4); |
417 | dccp_set_seqno(&dp->dccps_swh, | 415 | dp->dccps_swh = ADD48(dp->dccps_gsr, (3 * dp->dccps_r_seq_win) / 4); |
418 | dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4); | ||
419 | } | 416 | } |
420 | 417 | ||
421 | static inline void dccp_update_gss(struct sock *sk, u64 seq) | 418 | static inline void dccp_update_gss(struct sock *sk, u64 seq) |
422 | { | 419 | { |
423 | struct dccp_sock *dp = dccp_sk(sk); | 420 | struct dccp_sock *dp = dccp_sk(sk); |
424 | 421 | ||
425 | dp->dccps_awh = dp->dccps_gss = seq; | 422 | dp->dccps_gss = seq; |
426 | dccp_set_seqno(&dp->dccps_awl, | 423 | /* Ack validity window depends on local Sequence Window value (7.5.1) */ |
427 | (dp->dccps_gss - | 424 | dp->dccps_awl = SUB48(ADD48(dp->dccps_gss, 1), dp->dccps_l_seq_win); |
428 | dccp_msk(sk)->dccpms_sequence_window + 1)); | 425 | dp->dccps_awh = dp->dccps_gss; |
429 | } | 426 | } |
430 | 427 | ||
431 | static inline int dccp_ack_pending(const struct sock *sk) | 428 | static inline int dccp_ack_pending(const struct sock *sk) |
diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 4152308958ab..b04160a2eea5 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c | |||
@@ -25,6 +25,11 @@ | |||
25 | #include "ccid.h" | 25 | #include "ccid.h" |
26 | #include "feat.h" | 26 | #include "feat.h" |
27 | 27 | ||
28 | /* feature-specific sysctls - initialised to the defaults from RFC 4340, 6.4 */ | ||
29 | unsigned long sysctl_dccp_sequence_window __read_mostly = 100; | ||
30 | int sysctl_dccp_rx_ccid __read_mostly = 2, | ||
31 | sysctl_dccp_tx_ccid __read_mostly = 2; | ||
32 | |||
28 | /* | 33 | /* |
29 | * Feature activation handlers. | 34 | * Feature activation handlers. |
30 | * | 35 | * |
@@ -51,8 +56,17 @@ static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx) | |||
51 | 56 | ||
52 | static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx) | 57 | static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx) |
53 | { | 58 | { |
54 | if (!rx) | 59 | struct dccp_sock *dp = dccp_sk(sk); |
55 | dccp_msk(sk)->dccpms_sequence_window = seq_win; | 60 | |
61 | if (rx) { | ||
62 | dp->dccps_r_seq_win = seq_win; | ||
63 | /* propagate changes to update SWL/SWH */ | ||
64 | dccp_update_gsr(sk, dp->dccps_gsr); | ||
65 | } else { | ||
66 | dp->dccps_l_seq_win = seq_win; | ||
67 | /* propagate changes to update AWL */ | ||
68 | dccp_update_gss(sk, dp->dccps_gss); | ||
69 | } | ||
56 | return 0; | 70 | return 0; |
57 | } | 71 | } |
58 | 72 | ||
@@ -194,6 +208,100 @@ static int dccp_feat_default_value(u8 feat_num) | |||
194 | return idx < 0 ? 0 : dccp_feat_table[idx].default_value; | 208 | return idx < 0 ? 0 : dccp_feat_table[idx].default_value; |
195 | } | 209 | } |
196 | 210 | ||
211 | /* | ||
212 | * Debugging and verbose-printing section | ||
213 | */ | ||
214 | static const char *dccp_feat_fname(const u8 feat) | ||
215 | { | ||
216 | static const char *feature_names[] = { | ||
217 | [DCCPF_RESERVED] = "Reserved", | ||
218 | [DCCPF_CCID] = "CCID", | ||
219 | [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", | ||
220 | [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", | ||
221 | [DCCPF_ECN_INCAPABLE] = "ECN Incapable", | ||
222 | [DCCPF_ACK_RATIO] = "Ack Ratio", | ||
223 | [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", | ||
224 | [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", | ||
225 | [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", | ||
226 | [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", | ||
227 | }; | ||
228 | if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC) | ||
229 | return feature_names[DCCPF_RESERVED]; | ||
230 | |||
231 | if (feat == DCCPF_SEND_LEV_RATE) | ||
232 | return "Send Loss Event Rate"; | ||
233 | if (feat >= DCCPF_MIN_CCID_SPECIFIC) | ||
234 | return "CCID-specific"; | ||
235 | |||
236 | return feature_names[feat]; | ||
237 | } | ||
238 | |||
239 | static const char *dccp_feat_sname[] = { "DEFAULT", "INITIALISING", "CHANGING", | ||
240 | "UNSTABLE", "STABLE" }; | ||
241 | |||
242 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
243 | static const char *dccp_feat_oname(const u8 opt) | ||
244 | { | ||
245 | switch (opt) { | ||
246 | case DCCPO_CHANGE_L: return "Change_L"; | ||
247 | case DCCPO_CONFIRM_L: return "Confirm_L"; | ||
248 | case DCCPO_CHANGE_R: return "Change_R"; | ||
249 | case DCCPO_CONFIRM_R: return "Confirm_R"; | ||
250 | } | ||
251 | return NULL; | ||
252 | } | ||
253 | |||
254 | static void dccp_feat_printval(u8 feat_num, dccp_feat_val const *val) | ||
255 | { | ||
256 | u8 i, type = dccp_feat_type(feat_num); | ||
257 | |||
258 | if (val == NULL || (type == FEAT_SP && val->sp.vec == NULL)) | ||
259 | dccp_pr_debug_cat("(NULL)"); | ||
260 | else if (type == FEAT_SP) | ||
261 | for (i = 0; i < val->sp.len; i++) | ||
262 | dccp_pr_debug_cat("%s%u", i ? " " : "", val->sp.vec[i]); | ||
263 | else if (type == FEAT_NN) | ||
264 | dccp_pr_debug_cat("%llu", (unsigned long long)val->nn); | ||
265 | else | ||
266 | dccp_pr_debug_cat("unknown type %u", type); | ||
267 | } | ||
268 | |||
269 | static void dccp_feat_printvals(u8 feat_num, u8 *list, u8 len) | ||
270 | { | ||
271 | u8 type = dccp_feat_type(feat_num); | ||
272 | dccp_feat_val fval = { .sp.vec = list, .sp.len = len }; | ||
273 | |||
274 | if (type == FEAT_NN) | ||
275 | fval.nn = dccp_decode_value_var(list, len); | ||
276 | dccp_feat_printval(feat_num, &fval); | ||
277 | } | ||
278 | |||
279 | static void dccp_feat_print_entry(struct dccp_feat_entry const *entry) | ||
280 | { | ||
281 | dccp_debug(" * %s %s = ", entry->is_local ? "local" : "remote", | ||
282 | dccp_feat_fname(entry->feat_num)); | ||
283 | dccp_feat_printval(entry->feat_num, &entry->val); | ||
284 | dccp_pr_debug_cat(", state=%s %s\n", dccp_feat_sname[entry->state], | ||
285 | entry->needs_confirm ? "(Confirm pending)" : ""); | ||
286 | } | ||
287 | |||
288 | #define dccp_feat_print_opt(opt, feat, val, len, mandatory) do { \ | ||
289 | dccp_pr_debug("%s(%s, ", dccp_feat_oname(opt), dccp_feat_fname(feat));\ | ||
290 | dccp_feat_printvals(feat, val, len); \ | ||
291 | dccp_pr_debug_cat(") %s\n", mandatory ? "!" : ""); } while (0) | ||
292 | |||
293 | #define dccp_feat_print_fnlist(fn_list) { \ | ||
294 | const struct dccp_feat_entry *___entry; \ | ||
295 | \ | ||
296 | dccp_pr_debug("List Dump:\n"); \ | ||
297 | list_for_each_entry(___entry, fn_list, node) \ | ||
298 | dccp_feat_print_entry(___entry); \ | ||
299 | } | ||
300 | #else /* ! CONFIG_IP_DCCP_DEBUG */ | ||
301 | #define dccp_feat_print_opt(opt, feat, val, len, mandatory) | ||
302 | #define dccp_feat_print_fnlist(fn_list) | ||
303 | #endif | ||
304 | |||
197 | static int __dccp_feat_activate(struct sock *sk, const int idx, | 305 | static int __dccp_feat_activate(struct sock *sk, const int idx, |
198 | const bool is_local, dccp_feat_val const *fval) | 306 | const bool is_local, dccp_feat_val const *fval) |
199 | { | 307 | { |
@@ -226,6 +334,10 @@ static int __dccp_feat_activate(struct sock *sk, const int idx, | |||
226 | /* Location is RX if this is a local-RX or remote-TX feature */ | 334 | /* Location is RX if this is a local-RX or remote-TX feature */ |
227 | rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX)); | 335 | rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX)); |
228 | 336 | ||
337 | dccp_debug(" -> activating %s %s, %sval=%llu\n", rx ? "RX" : "TX", | ||
338 | dccp_feat_fname(dccp_feat_table[idx].feat_num), | ||
339 | fval ? "" : "default ", (unsigned long long)val); | ||
340 | |||
229 | return dccp_feat_table[idx].activation_hdlr(sk, val, rx); | 341 | return dccp_feat_table[idx].activation_hdlr(sk, val, rx); |
230 | } | 342 | } |
231 | 343 | ||
@@ -530,6 +642,7 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq, | |||
530 | return -1; | 642 | return -1; |
531 | } | 643 | } |
532 | } | 644 | } |
645 | dccp_feat_print_opt(opt, pos->feat_num, ptr, len, 0); | ||
533 | 646 | ||
534 | if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt)) | 647 | if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt)) |
535 | return -1; | 648 | return -1; |
@@ -783,6 +896,7 @@ int dccp_feat_finalise_settings(struct dccp_sock *dp) | |||
783 | while (i--) | 896 | while (i--) |
784 | if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i)) | 897 | if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i)) |
785 | return -1; | 898 | return -1; |
899 | dccp_feat_print_fnlist(fn); | ||
786 | return 0; | 900 | return 0; |
787 | } | 901 | } |
788 | 902 | ||
@@ -901,6 +1015,8 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt, | |||
901 | if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */ | 1015 | if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */ |
902 | goto unknown_feature_or_value; | 1016 | goto unknown_feature_or_value; |
903 | 1017 | ||
1018 | dccp_feat_print_opt(opt, feat, val, len, is_mandatory); | ||
1019 | |||
904 | /* | 1020 | /* |
905 | * Negotiation of NN features: Change R is invalid, so there is no | 1021 | * Negotiation of NN features: Change R is invalid, so there is no |
906 | * simultaneous negotiation; hence we do not look up in the list. | 1022 | * simultaneous negotiation; hence we do not look up in the list. |
@@ -1006,6 +1122,8 @@ static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt, | |||
1006 | const bool local = (opt == DCCPO_CONFIRM_R); | 1122 | const bool local = (opt == DCCPO_CONFIRM_R); |
1007 | struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local); | 1123 | struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local); |
1008 | 1124 | ||
1125 | dccp_feat_print_opt(opt, feat, val, len, is_mandatory); | ||
1126 | |||
1009 | if (entry == NULL) { /* nothing queued: ignore or handle error */ | 1127 | if (entry == NULL) { /* nothing queued: ignore or handle error */ |
1010 | if (is_mandatory && type == FEAT_UNKNOWN) | 1128 | if (is_mandatory && type == FEAT_UNKNOWN) |
1011 | return DCCP_RESET_CODE_MANDATORY_ERROR; | 1129 | return DCCP_RESET_CODE_MANDATORY_ERROR; |
@@ -1115,23 +1233,70 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
1115 | return 0; /* ignore FN options in all other states */ | 1233 | return 0; /* ignore FN options in all other states */ |
1116 | } | 1234 | } |
1117 | 1235 | ||
1236 | /** | ||
1237 | * dccp_feat_init - Seed feature negotiation with host-specific defaults | ||
1238 | * This initialises global defaults, depending on the value of the sysctls. | ||
1239 | * These can later be overridden by registering changes via setsockopt calls. | ||
1240 | * The last link in the chain is finalise_settings, to make sure that between | ||
1241 | * here and the start of actual feature negotiation no inconsistencies enter. | ||
1242 | * | ||
1243 | * All features not appearing below use either defaults or are otherwise | ||
1244 | * later adjusted through dccp_feat_finalise_settings(). | ||
1245 | */ | ||
1118 | int dccp_feat_init(struct sock *sk) | 1246 | int dccp_feat_init(struct sock *sk) |
1119 | { | 1247 | { |
1120 | struct dccp_sock *dp = dccp_sk(sk); | 1248 | struct list_head *fn = &dccp_sk(sk)->dccps_featneg; |
1121 | struct dccp_minisock *dmsk = dccp_msk(sk); | 1249 | u8 on = 1, off = 0; |
1122 | int rc; | 1250 | int rc; |
1251 | struct { | ||
1252 | u8 *val; | ||
1253 | u8 len; | ||
1254 | } tx, rx; | ||
1255 | |||
1256 | /* Non-negotiable (NN) features */ | ||
1257 | rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0, | ||
1258 | sysctl_dccp_sequence_window); | ||
1259 | if (rc) | ||
1260 | return rc; | ||
1261 | |||
1262 | /* Server-priority (SP) features */ | ||
1263 | |||
1264 | /* Advertise that short seqnos are not supported (7.6.1) */ | ||
1265 | rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1); | ||
1266 | if (rc) | ||
1267 | return rc; | ||
1123 | 1268 | ||
1124 | INIT_LIST_HEAD(&dmsk->dccpms_pending); /* XXX no longer used */ | 1269 | /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */ |
1125 | INIT_LIST_HEAD(&dmsk->dccpms_conf); /* XXX no longer used */ | 1270 | rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1); |
1271 | if (rc) | ||
1272 | return rc; | ||
1273 | |||
1274 | /* | ||
1275 | * We advertise the available list of CCIDs and reorder according to | ||
1276 | * preferences, to avoid failure resulting from negotiating different | ||
1277 | * singleton values (which always leads to failure). | ||
1278 | * These settings can still (later) be overridden via sockopts. | ||
1279 | */ | ||
1280 | if (ccid_get_builtin_ccids(&tx.val, &tx.len) || | ||
1281 | ccid_get_builtin_ccids(&rx.val, &rx.len)) | ||
1282 | return -ENOBUFS; | ||
1283 | |||
1284 | if (!dccp_feat_prefer(sysctl_dccp_tx_ccid, tx.val, tx.len) || | ||
1285 | !dccp_feat_prefer(sysctl_dccp_rx_ccid, rx.val, rx.len)) | ||
1286 | goto free_ccid_lists; | ||
1287 | |||
1288 | rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len); | ||
1289 | if (rc) | ||
1290 | goto free_ccid_lists; | ||
1291 | |||
1292 | rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len); | ||
1126 | 1293 | ||
1127 | /* Ack ratio */ | 1294 | free_ccid_lists: |
1128 | rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0, | 1295 | kfree(tx.val); |
1129 | dp->dccps_l_ack_ratio); | 1296 | kfree(rx.val); |
1130 | return rc; | 1297 | return rc; |
1131 | } | 1298 | } |
1132 | 1299 | ||
1133 | EXPORT_SYMBOL_GPL(dccp_feat_init); | ||
1134 | |||
1135 | int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) | 1300 | int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) |
1136 | { | 1301 | { |
1137 | struct dccp_sock *dp = dccp_sk(sk); | 1302 | struct dccp_sock *dp = dccp_sk(sk); |
@@ -1156,9 +1321,10 @@ int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) | |||
1156 | goto activation_failed; | 1321 | goto activation_failed; |
1157 | } | 1322 | } |
1158 | if (cur->state != FEAT_STABLE) { | 1323 | if (cur->state != FEAT_STABLE) { |
1159 | DCCP_CRIT("Negotiation of %s %u failed in state %u", | 1324 | DCCP_CRIT("Negotiation of %s %s failed in state %s", |
1160 | cur->is_local ? "local" : "remote", | 1325 | cur->is_local ? "local" : "remote", |
1161 | cur->feat_num, cur->state); | 1326 | dccp_feat_fname(cur->feat_num), |
1327 | dccp_feat_sname[cur->state]); | ||
1162 | goto activation_failed; | 1328 | goto activation_failed; |
1163 | } | 1329 | } |
1164 | fvals[idx][cur->is_local] = &cur->val; | 1330 | fvals[idx][cur->is_local] = &cur->val; |
@@ -1199,43 +1365,3 @@ activation_failed: | |||
1199 | dp->dccps_hc_rx_ackvec = NULL; | 1365 | dp->dccps_hc_rx_ackvec = NULL; |
1200 | return -1; | 1366 | return -1; |
1201 | } | 1367 | } |
1202 | |||
1203 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
1204 | const char *dccp_feat_typename(const u8 type) | ||
1205 | { | ||
1206 | switch(type) { | ||
1207 | case DCCPO_CHANGE_L: return("ChangeL"); | ||
1208 | case DCCPO_CONFIRM_L: return("ConfirmL"); | ||
1209 | case DCCPO_CHANGE_R: return("ChangeR"); | ||
1210 | case DCCPO_CONFIRM_R: return("ConfirmR"); | ||
1211 | /* the following case must not appear in feature negotation */ | ||
1212 | default: dccp_pr_debug("unknown type %d [BUG!]\n", type); | ||
1213 | } | ||
1214 | return NULL; | ||
1215 | } | ||
1216 | |||
1217 | const char *dccp_feat_name(const u8 feat) | ||
1218 | { | ||
1219 | static const char *feature_names[] = { | ||
1220 | [DCCPF_RESERVED] = "Reserved", | ||
1221 | [DCCPF_CCID] = "CCID", | ||
1222 | [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", | ||
1223 | [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", | ||
1224 | [DCCPF_ECN_INCAPABLE] = "ECN Incapable", | ||
1225 | [DCCPF_ACK_RATIO] = "Ack Ratio", | ||
1226 | [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", | ||
1227 | [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", | ||
1228 | [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", | ||
1229 | [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", | ||
1230 | }; | ||
1231 | if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC) | ||
1232 | return feature_names[DCCPF_RESERVED]; | ||
1233 | |||
1234 | if (feat == DCCPF_SEND_LEV_RATE) | ||
1235 | return "Send Loss Event Rate"; | ||
1236 | if (feat >= DCCPF_MIN_CCID_SPECIFIC) | ||
1237 | return "CCID-specific"; | ||
1238 | |||
1239 | return feature_names[feat]; | ||
1240 | } | ||
1241 | #endif /* CONFIG_IP_DCCP_DEBUG */ | ||
diff --git a/net/dccp/feat.h b/net/dccp/feat.h index 9b46e2a7866e..f96721619def 100644 --- a/net/dccp/feat.h +++ b/net/dccp/feat.h | |||
@@ -100,26 +100,21 @@ struct ccid_dependency { | |||
100 | u8 val; | 100 | u8 val; |
101 | }; | 101 | }; |
102 | 102 | ||
103 | #ifdef CONFIG_IP_DCCP_DEBUG | 103 | /* |
104 | extern const char *dccp_feat_typename(const u8 type); | 104 | * Sysctls to seed defaults for feature negotiation |
105 | extern const char *dccp_feat_name(const u8 feat); | 105 | */ |
106 | 106 | extern unsigned long sysctl_dccp_sequence_window; | |
107 | static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val) | 107 | extern int sysctl_dccp_rx_ccid; |
108 | { | 108 | extern int sysctl_dccp_tx_ccid; |
109 | dccp_pr_debug("%s(%s (%d), %d)\n", dccp_feat_typename(type), | ||
110 | dccp_feat_name(feat), feat, val); | ||
111 | } | ||
112 | #else | ||
113 | #define dccp_feat_debug(type, feat, val) | ||
114 | #endif /* CONFIG_IP_DCCP_DEBUG */ | ||
115 | 109 | ||
110 | extern int dccp_feat_init(struct sock *sk); | ||
111 | extern void dccp_feat_initialise_sysctls(void); | ||
116 | extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, | 112 | extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, |
117 | u8 const *list, u8 len); | 113 | u8 const *list, u8 len); |
118 | extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val); | 114 | extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val); |
119 | extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *, | 115 | extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *, |
120 | u8 mand, u8 opt, u8 feat, u8 *val, u8 len); | 116 | u8 mand, u8 opt, u8 feat, u8 *val, u8 len); |
121 | extern int dccp_feat_clone_list(struct list_head const *, struct list_head *); | 117 | extern int dccp_feat_clone_list(struct list_head const *, struct list_head *); |
122 | extern int dccp_feat_init(struct sock *sk); | ||
123 | 118 | ||
124 | /* | 119 | /* |
125 | * Encoding variable-length options and their maximum length. | 120 | * Encoding variable-length options and their maximum length. |
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 6821ae33dd37..5ca49cec95f5 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
@@ -42,11 +42,6 @@ struct inet_timewait_death_row dccp_death_row = { | |||
42 | 42 | ||
43 | EXPORT_SYMBOL_GPL(dccp_death_row); | 43 | EXPORT_SYMBOL_GPL(dccp_death_row); |
44 | 44 | ||
45 | void dccp_minisock_init(struct dccp_minisock *dmsk) | ||
46 | { | ||
47 | dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window; | ||
48 | } | ||
49 | |||
50 | void dccp_time_wait(struct sock *sk, int state, int timeo) | 45 | void dccp_time_wait(struct sock *sk, int state, int timeo) |
51 | { | 46 | { |
52 | struct inet_timewait_sock *tw = NULL; | 47 | struct inet_timewait_sock *tw = NULL; |
@@ -110,7 +105,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk, | |||
110 | struct dccp_request_sock *dreq = dccp_rsk(req); | 105 | struct dccp_request_sock *dreq = dccp_rsk(req); |
111 | struct inet_connection_sock *newicsk = inet_csk(newsk); | 106 | struct inet_connection_sock *newicsk = inet_csk(newsk); |
112 | struct dccp_sock *newdp = dccp_sk(newsk); | 107 | struct dccp_sock *newdp = dccp_sk(newsk); |
113 | struct dccp_minisock *newdmsk = dccp_msk(newsk); | ||
114 | 108 | ||
115 | newdp->dccps_role = DCCP_ROLE_SERVER; | 109 | newdp->dccps_role = DCCP_ROLE_SERVER; |
116 | newdp->dccps_hc_rx_ackvec = NULL; | 110 | newdp->dccps_hc_rx_ackvec = NULL; |
@@ -128,10 +122,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk, | |||
128 | * Initialize S.GAR := S.ISS | 122 | * Initialize S.GAR := S.ISS |
129 | * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies | 123 | * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies |
130 | */ | 124 | */ |
131 | |||
132 | /* See dccp_v4_conn_request */ | ||
133 | newdmsk->dccpms_sequence_window = req->rcv_wnd; | ||
134 | |||
135 | newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss; | 125 | newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss; |
136 | dccp_update_gss(newsk, dreq->dreq_iss); | 126 | dccp_update_gss(newsk, dreq->dreq_iss); |
137 | 127 | ||
@@ -290,7 +280,6 @@ int dccp_reqsk_init(struct request_sock *req, | |||
290 | inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; | 280 | inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; |
291 | inet_rsk(req)->loc_port = dccp_hdr(skb)->dccph_dport; | 281 | inet_rsk(req)->loc_port = dccp_hdr(skb)->dccph_dport; |
292 | inet_rsk(req)->acked = 0; | 282 | inet_rsk(req)->acked = 0; |
293 | req->rcv_wnd = sysctl_dccp_feat_sequence_window; | ||
294 | dreq->dreq_timestamp_echo = 0; | 283 | dreq->dreq_timestamp_echo = 0; |
295 | 284 | ||
296 | /* inherit feature negotiation options from listening socket */ | 285 | /* inherit feature negotiation options from listening socket */ |
diff --git a/net/dccp/options.c b/net/dccp/options.c index 7b1165c21f51..1b08cae9c65b 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -23,10 +23,6 @@ | |||
23 | #include "dccp.h" | 23 | #include "dccp.h" |
24 | #include "feat.h" | 24 | #include "feat.h" |
25 | 25 | ||
26 | int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW; | ||
27 | int sysctl_dccp_feat_rx_ccid = DCCPF_INITIAL_CCID; | ||
28 | int sysctl_dccp_feat_tx_ccid = DCCPF_INITIAL_CCID; | ||
29 | |||
30 | u64 dccp_decode_value_var(const u8 *bf, const u8 len) | 26 | u64 dccp_decode_value_var(const u8 *bf, const u8 len) |
31 | { | 27 | { |
32 | u64 value = 0; | 28 | u64 value = 0; |
@@ -502,10 +498,6 @@ int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat, | |||
502 | *to++ = *val; | 498 | *to++ = *val; |
503 | if (len) | 499 | if (len) |
504 | memcpy(to, val, len); | 500 | memcpy(to, val, len); |
505 | |||
506 | dccp_pr_debug("%s(%s (%d), ...), length %d\n", | ||
507 | dccp_feat_typename(type), | ||
508 | dccp_feat_name(feat), feat, len); | ||
509 | return 0; | 501 | return 0; |
510 | } | 502 | } |
511 | 503 | ||
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 945b4d5d23b3..314a1b5c033c 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -174,8 +174,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) | |||
174 | struct dccp_sock *dp = dccp_sk(sk); | 174 | struct dccp_sock *dp = dccp_sk(sk); |
175 | struct inet_connection_sock *icsk = inet_csk(sk); | 175 | struct inet_connection_sock *icsk = inet_csk(sk); |
176 | 176 | ||
177 | dccp_minisock_init(&dp->dccps_minisock); | ||
178 | |||
179 | icsk->icsk_rto = DCCP_TIMEOUT_INIT; | 177 | icsk->icsk_rto = DCCP_TIMEOUT_INIT; |
180 | icsk->icsk_syn_retries = sysctl_dccp_request_retries; | 178 | icsk->icsk_syn_retries = sysctl_dccp_request_retries; |
181 | sk->sk_state = DCCP_CLOSED; | 179 | sk->sk_state = DCCP_CLOSED; |
diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c index 018e210875e1..a5a1856234e7 100644 --- a/net/dccp/sysctl.c +++ b/net/dccp/sysctl.c | |||
@@ -18,55 +18,72 @@ | |||
18 | #error This file should not be compiled without CONFIG_SYSCTL defined | 18 | #error This file should not be compiled without CONFIG_SYSCTL defined |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | /* Boundary values */ | ||
22 | static int zero = 0, | ||
23 | u8_max = 0xFF; | ||
24 | static unsigned long seqw_min = 32; | ||
25 | |||
21 | static struct ctl_table dccp_default_table[] = { | 26 | static struct ctl_table dccp_default_table[] = { |
22 | { | 27 | { |
23 | .procname = "seq_window", | 28 | .procname = "seq_window", |
24 | .data = &sysctl_dccp_feat_sequence_window, | 29 | .data = &sysctl_dccp_sequence_window, |
25 | .maxlen = sizeof(sysctl_dccp_feat_sequence_window), | 30 | .maxlen = sizeof(sysctl_dccp_sequence_window), |
26 | .mode = 0644, | 31 | .mode = 0644, |
27 | .proc_handler = proc_dointvec, | 32 | .proc_handler = proc_doulongvec_minmax, |
33 | .extra1 = &seqw_min, /* RFC 4340, 7.5.2 */ | ||
28 | }, | 34 | }, |
29 | { | 35 | { |
30 | .procname = "rx_ccid", | 36 | .procname = "rx_ccid", |
31 | .data = &sysctl_dccp_feat_rx_ccid, | 37 | .data = &sysctl_dccp_rx_ccid, |
32 | .maxlen = sizeof(sysctl_dccp_feat_rx_ccid), | 38 | .maxlen = sizeof(sysctl_dccp_rx_ccid), |
33 | .mode = 0644, | 39 | .mode = 0644, |
34 | .proc_handler = proc_dointvec, | 40 | .proc_handler = proc_dointvec_minmax, |
41 | .extra1 = &zero, | ||
42 | .extra2 = &u8_max, /* RFC 4340, 10. */ | ||
35 | }, | 43 | }, |
36 | { | 44 | { |
37 | .procname = "tx_ccid", | 45 | .procname = "tx_ccid", |
38 | .data = &sysctl_dccp_feat_tx_ccid, | 46 | .data = &sysctl_dccp_tx_ccid, |
39 | .maxlen = sizeof(sysctl_dccp_feat_tx_ccid), | 47 | .maxlen = sizeof(sysctl_dccp_tx_ccid), |
40 | .mode = 0644, | 48 | .mode = 0644, |
41 | .proc_handler = proc_dointvec, | 49 | .proc_handler = proc_dointvec_minmax, |
50 | .extra1 = &zero, | ||
51 | .extra2 = &u8_max, /* RFC 4340, 10. */ | ||
42 | }, | 52 | }, |
43 | { | 53 | { |
44 | .procname = "request_retries", | 54 | .procname = "request_retries", |
45 | .data = &sysctl_dccp_request_retries, | 55 | .data = &sysctl_dccp_request_retries, |
46 | .maxlen = sizeof(sysctl_dccp_request_retries), | 56 | .maxlen = sizeof(sysctl_dccp_request_retries), |
47 | .mode = 0644, | 57 | .mode = 0644, |
48 | .proc_handler = proc_dointvec, | 58 | .proc_handler = proc_dointvec_minmax, |
59 | .extra1 = &zero, | ||
60 | .extra2 = &u8_max, | ||
49 | }, | 61 | }, |
50 | { | 62 | { |
51 | .procname = "retries1", | 63 | .procname = "retries1", |
52 | .data = &sysctl_dccp_retries1, | 64 | .data = &sysctl_dccp_retries1, |
53 | .maxlen = sizeof(sysctl_dccp_retries1), | 65 | .maxlen = sizeof(sysctl_dccp_retries1), |
54 | .mode = 0644, | 66 | .mode = 0644, |
55 | .proc_handler = proc_dointvec, | 67 | .proc_handler = proc_dointvec_minmax, |
68 | .extra1 = &zero, | ||
69 | .extra2 = &u8_max, | ||
56 | }, | 70 | }, |
57 | { | 71 | { |
58 | .procname = "retries2", | 72 | .procname = "retries2", |
59 | .data = &sysctl_dccp_retries2, | 73 | .data = &sysctl_dccp_retries2, |
60 | .maxlen = sizeof(sysctl_dccp_retries2), | 74 | .maxlen = sizeof(sysctl_dccp_retries2), |
61 | .mode = 0644, | 75 | .mode = 0644, |
62 | .proc_handler = proc_dointvec, | 76 | .proc_handler = proc_dointvec_minmax, |
77 | .extra1 = &zero, | ||
78 | .extra2 = &u8_max, | ||
63 | }, | 79 | }, |
64 | { | 80 | { |
65 | .procname = "tx_qlen", | 81 | .procname = "tx_qlen", |
66 | .data = &sysctl_dccp_tx_qlen, | 82 | .data = &sysctl_dccp_tx_qlen, |
67 | .maxlen = sizeof(sysctl_dccp_tx_qlen), | 83 | .maxlen = sizeof(sysctl_dccp_tx_qlen), |
68 | .mode = 0644, | 84 | .mode = 0644, |
69 | .proc_handler = proc_dointvec, | 85 | .proc_handler = proc_dointvec_minmax, |
86 | .extra1 = &zero, | ||
70 | }, | 87 | }, |
71 | { | 88 | { |
72 | .procname = "sync_ratelimit", | 89 | .procname = "sync_ratelimit", |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index cf0e18499297..12bf7d4c16c6 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -2113,7 +2113,7 @@ static struct notifier_block dn_dev_notifier = { | |||
2113 | extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); | 2113 | extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); |
2114 | 2114 | ||
2115 | static struct packet_type dn_dix_packet_type = { | 2115 | static struct packet_type dn_dix_packet_type = { |
2116 | .type = __constant_htons(ETH_P_DNA_RT), | 2116 | .type = cpu_to_be16(ETH_P_DNA_RT), |
2117 | .dev = NULL, /* All devices */ | 2117 | .dev = NULL, /* All devices */ |
2118 | .func = dn_route_rcv, | 2118 | .func = dn_route_rcv, |
2119 | }; | 2119 | }; |
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index daf2b98b15fe..e457769bf7a7 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
@@ -769,7 +769,8 @@ static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa) | |||
769 | kfree_skb(skb); | 769 | kfree_skb(skb); |
770 | goto errout; | 770 | goto errout; |
771 | } | 771 | } |
772 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL); | 772 | rtnl_notify(skb, &init_net, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL); |
773 | return; | ||
773 | errout: | 774 | errout: |
774 | if (err < 0) | 775 | if (err < 0) |
775 | rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_IFADDR, err); | 776 | rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_IFADDR, err); |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index c754670b7fca..5130dee0b384 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -124,7 +124,7 @@ int decnet_dst_gc_interval = 2; | |||
124 | 124 | ||
125 | static struct dst_ops dn_dst_ops = { | 125 | static struct dst_ops dn_dst_ops = { |
126 | .family = PF_DECnet, | 126 | .family = PF_DECnet, |
127 | .protocol = __constant_htons(ETH_P_DNA_RT), | 127 | .protocol = cpu_to_be16(ETH_P_DNA_RT), |
128 | .gc_thresh = 128, | 128 | .gc_thresh = 128, |
129 | .gc = dn_dst_gc, | 129 | .gc = dn_dst_gc, |
130 | .check = dn_dst_check, | 130 | .check = dn_dst_check, |
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 69ad9280c693..67054b0d550f 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c | |||
@@ -375,7 +375,8 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id, | |||
375 | kfree_skb(skb); | 375 | kfree_skb(skb); |
376 | goto errout; | 376 | goto errout; |
377 | } | 377 | } |
378 | err = rtnl_notify(skb, &init_net, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); | 378 | rtnl_notify(skb, &init_net, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); |
379 | return; | ||
379 | errout: | 380 | errout: |
380 | if (err < 0) | 381 | if (err < 0) |
381 | rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_ROUTE, err); | 382 | rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_ROUTE, err); |
diff --git a/net/dsa/mv88e6123_61_65.c b/net/dsa/mv88e6123_61_65.c index ec8c6a0482d3..100318722214 100644 --- a/net/dsa/mv88e6123_61_65.c +++ b/net/dsa/mv88e6123_61_65.c | |||
@@ -394,7 +394,7 @@ static int mv88e6123_61_65_get_sset_count(struct dsa_switch *ds) | |||
394 | } | 394 | } |
395 | 395 | ||
396 | static struct dsa_switch_driver mv88e6123_61_65_switch_driver = { | 396 | static struct dsa_switch_driver mv88e6123_61_65_switch_driver = { |
397 | .tag_protocol = __constant_htons(ETH_P_EDSA), | 397 | .tag_protocol = cpu_to_be16(ETH_P_EDSA), |
398 | .priv_size = sizeof(struct mv88e6xxx_priv_state), | 398 | .priv_size = sizeof(struct mv88e6xxx_priv_state), |
399 | .probe = mv88e6123_61_65_probe, | 399 | .probe = mv88e6123_61_65_probe, |
400 | .setup = mv88e6123_61_65_setup, | 400 | .setup = mv88e6123_61_65_setup, |
diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index 374d46a01265..70fae2444cb6 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c | |||
@@ -353,7 +353,7 @@ static int mv88e6131_get_sset_count(struct dsa_switch *ds) | |||
353 | } | 353 | } |
354 | 354 | ||
355 | static struct dsa_switch_driver mv88e6131_switch_driver = { | 355 | static struct dsa_switch_driver mv88e6131_switch_driver = { |
356 | .tag_protocol = __constant_htons(ETH_P_DSA), | 356 | .tag_protocol = cpu_to_be16(ETH_P_DSA), |
357 | .priv_size = sizeof(struct mv88e6xxx_priv_state), | 357 | .priv_size = sizeof(struct mv88e6xxx_priv_state), |
358 | .probe = mv88e6131_probe, | 358 | .probe = mv88e6131_probe, |
359 | .setup = mv88e6131_setup, | 359 | .setup = mv88e6131_setup, |
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index f99a019b939e..63e532a69fdb 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c | |||
@@ -176,7 +176,7 @@ out: | |||
176 | } | 176 | } |
177 | 177 | ||
178 | static struct packet_type dsa_packet_type = { | 178 | static struct packet_type dsa_packet_type = { |
179 | .type = __constant_htons(ETH_P_DSA), | 179 | .type = cpu_to_be16(ETH_P_DSA), |
180 | .func = dsa_rcv, | 180 | .func = dsa_rcv, |
181 | }; | 181 | }; |
182 | 182 | ||
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c index 328ec957f786..6197f9a7ef42 100644 --- a/net/dsa/tag_edsa.c +++ b/net/dsa/tag_edsa.c | |||
@@ -195,7 +195,7 @@ out: | |||
195 | } | 195 | } |
196 | 196 | ||
197 | static struct packet_type edsa_packet_type = { | 197 | static struct packet_type edsa_packet_type = { |
198 | .type = __constant_htons(ETH_P_EDSA), | 198 | .type = cpu_to_be16(ETH_P_EDSA), |
199 | .func = edsa_rcv, | 199 | .func = edsa_rcv, |
200 | }; | 200 | }; |
201 | 201 | ||
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index b59132878ad1..d7e7f424ff0c 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c | |||
@@ -112,7 +112,7 @@ out: | |||
112 | } | 112 | } |
113 | 113 | ||
114 | static struct packet_type trailer_packet_type = { | 114 | static struct packet_type trailer_packet_type = { |
115 | .type = __constant_htons(ETH_P_TRAILER), | 115 | .type = cpu_to_be16(ETH_P_TRAILER), |
116 | .func = trailer_rcv, | 116 | .func = trailer_rcv, |
117 | }; | 117 | }; |
118 | 118 | ||
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 8789d2bb1b06..7bf35582f656 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
@@ -1103,7 +1103,7 @@ drop: | |||
1103 | } | 1103 | } |
1104 | 1104 | ||
1105 | static struct packet_type econet_packet_type = { | 1105 | static struct packet_type econet_packet_type = { |
1106 | .type = __constant_htons(ETH_P_ECONET), | 1106 | .type = cpu_to_be16(ETH_P_ECONET), |
1107 | .func = econet_rcv, | 1107 | .func = econet_rcv, |
1108 | }; | 1108 | }; |
1109 | 1109 | ||
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 691268f3a359..b2cf91e4ccaa 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -35,7 +35,7 @@ config IP_ADVANCED_ROUTER | |||
35 | 35 | ||
36 | at boot time after the /proc file system has been mounted. | 36 | at boot time after the /proc file system has been mounted. |
37 | 37 | ||
38 | If you turn on IP forwarding, you will also get the rp_filter, which | 38 | If you turn on IP forwarding, you should consider the rp_filter, which |
39 | automatically rejects incoming packets if the routing table entry | 39 | automatically rejects incoming packets if the routing table entry |
40 | for their source address doesn't match the network interface they're | 40 | for their source address doesn't match the network interface they're |
41 | arriving on. This has security advantages because it prevents the | 41 | arriving on. This has security advantages because it prevents the |
@@ -46,12 +46,16 @@ config IP_ADVANCED_ROUTER | |||
46 | rp_filter on use: | 46 | rp_filter on use: |
47 | 47 | ||
48 | echo 1 > /proc/sys/net/ipv4/conf/<device>/rp_filter | 48 | echo 1 > /proc/sys/net/ipv4/conf/<device>/rp_filter |
49 | or | 49 | and |
50 | echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter | 50 | echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter |
51 | 51 | ||
52 | Note that some distributions enable it in startup scripts. | ||
53 | For details about rp_filter strict and loose mode read | ||
54 | <file:Documentation/networking/ip-sysctl.txt>. | ||
55 | |||
52 | If unsure, say N here. | 56 | If unsure, say N here. |
53 | 57 | ||
54 | choice | 58 | choice |
55 | prompt "Choose IP: FIB lookup algorithm (choose FIB_HASH if unsure)" | 59 | prompt "Choose IP: FIB lookup algorithm (choose FIB_HASH if unsure)" |
56 | depends on IP_ADVANCED_ROUTER | 60 | depends on IP_ADVANCED_ROUTER |
57 | default ASK_IP_FIB_HASH | 61 | default ASK_IP_FIB_HASH |
@@ -59,27 +63,29 @@ choice | |||
59 | config ASK_IP_FIB_HASH | 63 | config ASK_IP_FIB_HASH |
60 | bool "FIB_HASH" | 64 | bool "FIB_HASH" |
61 | ---help--- | 65 | ---help--- |
62 | Current FIB is very proven and good enough for most users. | 66 | Current FIB is very proven and good enough for most users. |
63 | 67 | ||
64 | config IP_FIB_TRIE | 68 | config IP_FIB_TRIE |
65 | bool "FIB_TRIE" | 69 | bool "FIB_TRIE" |
66 | ---help--- | 70 | ---help--- |
67 | Use new experimental LC-trie as FIB lookup algorithm. | 71 | Use new experimental LC-trie as FIB lookup algorithm. |
68 | This improves lookup performance if you have a large | 72 | This improves lookup performance if you have a large |
69 | number of routes. | 73 | number of routes. |
70 | 74 | ||
71 | LC-trie is a longest matching prefix lookup algorithm which | 75 | LC-trie is a longest matching prefix lookup algorithm which |
72 | performs better than FIB_HASH for large routing tables. | 76 | performs better than FIB_HASH for large routing tables. |
73 | But, it consumes more memory and is more complex. | 77 | But, it consumes more memory and is more complex. |
74 | 78 | ||
75 | LC-trie is described in: | 79 | LC-trie is described in: |
76 | 80 | ||
77 | IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson | 81 | IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson |
78 | IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999 | 82 | IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, |
79 | An experimental study of compression methods for dynamic tries | 83 | June 1999 |
80 | Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. | 84 | |
81 | http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/ | 85 | An experimental study of compression methods for dynamic tries |
82 | 86 | Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. | |
87 | http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/ | ||
88 | |||
83 | endchoice | 89 | endchoice |
84 | 90 | ||
85 | config IP_FIB_HASH | 91 | config IP_FIB_HASH |
@@ -191,7 +197,7 @@ config IP_PNP_RARP | |||
191 | <file:Documentation/filesystems/nfsroot.txt> for details. | 197 | <file:Documentation/filesystems/nfsroot.txt> for details. |
192 | 198 | ||
193 | # not yet ready.. | 199 | # not yet ready.. |
194 | # bool ' IP: ARP support' CONFIG_IP_PNP_ARP | 200 | # bool ' IP: ARP support' CONFIG_IP_PNP_ARP |
195 | config NET_IPIP | 201 | config NET_IPIP |
196 | tristate "IP: tunneling" | 202 | tristate "IP: tunneling" |
197 | select INET_TUNNEL | 203 | select INET_TUNNEL |
@@ -361,7 +367,7 @@ config INET_IPCOMP | |||
361 | ---help--- | 367 | ---help--- |
362 | Support for IP Payload Compression Protocol (IPComp) (RFC3173), | 368 | Support for IP Payload Compression Protocol (IPComp) (RFC3173), |
363 | typically needed for IPsec. | 369 | typically needed for IPsec. |
364 | 370 | ||
365 | If unsure, say Y. | 371 | If unsure, say Y. |
366 | 372 | ||
367 | config INET_XFRM_TUNNEL | 373 | config INET_XFRM_TUNNEL |
@@ -415,7 +421,7 @@ config INET_DIAG | |||
415 | Support for INET (TCP, DCCP, etc) socket monitoring interface used by | 421 | Support for INET (TCP, DCCP, etc) socket monitoring interface used by |
416 | native Linux tools such as ss. ss is included in iproute2, currently | 422 | native Linux tools such as ss. ss is included in iproute2, currently |
417 | downloadable at <http://linux-net.osdl.org/index.php/Iproute2>. | 423 | downloadable at <http://linux-net.osdl.org/index.php/Iproute2>. |
418 | 424 | ||
419 | If unsure, say Y. | 425 | If unsure, say Y. |
420 | 426 | ||
421 | config INET_TCP_DIAG | 427 | config INET_TCP_DIAG |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 743f5542d65a..627be4dc7fb0 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -369,7 +369,6 @@ lookup_protocol: | |||
369 | sock_init_data(sock, sk); | 369 | sock_init_data(sock, sk); |
370 | 370 | ||
371 | sk->sk_destruct = inet_sock_destruct; | 371 | sk->sk_destruct = inet_sock_destruct; |
372 | sk->sk_family = PF_INET; | ||
373 | sk->sk_protocol = protocol; | 372 | sk->sk_protocol = protocol; |
374 | sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | 373 | sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; |
375 | 374 | ||
@@ -1253,10 +1252,10 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1253 | int proto; | 1252 | int proto; |
1254 | int id; | 1253 | int id; |
1255 | 1254 | ||
1256 | if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) | 1255 | iph = skb_gro_header(skb, sizeof(*iph)); |
1256 | if (unlikely(!iph)) | ||
1257 | goto out; | 1257 | goto out; |
1258 | 1258 | ||
1259 | iph = ip_hdr(skb); | ||
1260 | proto = iph->protocol & (MAX_INET_PROTOS - 1); | 1259 | proto = iph->protocol & (MAX_INET_PROTOS - 1); |
1261 | 1260 | ||
1262 | rcu_read_lock(); | 1261 | rcu_read_lock(); |
@@ -1264,13 +1263,13 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1264 | if (!ops || !ops->gro_receive) | 1263 | if (!ops || !ops->gro_receive) |
1265 | goto out_unlock; | 1264 | goto out_unlock; |
1266 | 1265 | ||
1267 | if (iph->version != 4 || iph->ihl != 5) | 1266 | if (*(u8 *)iph != 0x45) |
1268 | goto out_unlock; | 1267 | goto out_unlock; |
1269 | 1268 | ||
1270 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) | 1269 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) |
1271 | goto out_unlock; | 1270 | goto out_unlock; |
1272 | 1271 | ||
1273 | flush = ntohs(iph->tot_len) != skb->len || | 1272 | flush = ntohs(iph->tot_len) != skb_gro_len(skb) || |
1274 | iph->frag_off != htons(IP_DF); | 1273 | iph->frag_off != htons(IP_DF); |
1275 | id = ntohs(iph->id); | 1274 | id = ntohs(iph->id); |
1276 | 1275 | ||
@@ -1282,24 +1281,25 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1282 | 1281 | ||
1283 | iph2 = ip_hdr(p); | 1282 | iph2 = ip_hdr(p); |
1284 | 1283 | ||
1285 | if (iph->protocol != iph2->protocol || | 1284 | if ((iph->protocol ^ iph2->protocol) | |
1286 | iph->tos != iph2->tos || | 1285 | (iph->tos ^ iph2->tos) | |
1287 | memcmp(&iph->saddr, &iph2->saddr, 8)) { | 1286 | (iph->saddr ^ iph2->saddr) | |
1287 | (iph->daddr ^ iph2->daddr)) { | ||
1288 | NAPI_GRO_CB(p)->same_flow = 0; | 1288 | NAPI_GRO_CB(p)->same_flow = 0; |
1289 | continue; | 1289 | continue; |
1290 | } | 1290 | } |
1291 | 1291 | ||
1292 | /* All fields must match except length and checksum. */ | 1292 | /* All fields must match except length and checksum. */ |
1293 | NAPI_GRO_CB(p)->flush |= | 1293 | NAPI_GRO_CB(p)->flush |= |
1294 | memcmp(&iph->frag_off, &iph2->frag_off, 4) || | 1294 | (iph->ttl ^ iph2->ttl) | |
1295 | (u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) != id; | 1295 | ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id); |
1296 | 1296 | ||
1297 | NAPI_GRO_CB(p)->flush |= flush; | 1297 | NAPI_GRO_CB(p)->flush |= flush; |
1298 | } | 1298 | } |
1299 | 1299 | ||
1300 | NAPI_GRO_CB(skb)->flush |= flush; | 1300 | NAPI_GRO_CB(skb)->flush |= flush; |
1301 | __skb_pull(skb, sizeof(*iph)); | 1301 | skb_gro_pull(skb, sizeof(*iph)); |
1302 | skb_reset_transport_header(skb); | 1302 | skb_set_transport_header(skb, skb_gro_offset(skb)); |
1303 | 1303 | ||
1304 | pp = ops->gro_receive(head, skb); | 1304 | pp = ops->gro_receive(head, skb); |
1305 | 1305 | ||
@@ -1501,7 +1501,7 @@ static int ipv4_proc_init(void); | |||
1501 | */ | 1501 | */ |
1502 | 1502 | ||
1503 | static struct packet_type ip_packet_type = { | 1503 | static struct packet_type ip_packet_type = { |
1504 | .type = __constant_htons(ETH_P_IP), | 1504 | .type = cpu_to_be16(ETH_P_IP), |
1505 | .func = ip_rcv, | 1505 | .func = ip_rcv, |
1506 | .gso_send_check = inet_gso_send_check, | 1506 | .gso_send_check = inet_gso_send_check, |
1507 | .gso_segment = inet_gso_segment, | 1507 | .gso_segment = inet_gso_segment, |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 29a74c01d8de..3f6b7354699b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -1226,7 +1226,7 @@ void arp_ifdown(struct net_device *dev) | |||
1226 | */ | 1226 | */ |
1227 | 1227 | ||
1228 | static struct packet_type arp_packet_type = { | 1228 | static struct packet_type arp_packet_type = { |
1229 | .type = __constant_htons(ETH_P_ARP), | 1229 | .type = cpu_to_be16(ETH_P_ARP), |
1230 | .func = arp_rcv, | 1230 | .func = arp_rcv, |
1231 | }; | 1231 | }; |
1232 | 1232 | ||
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 309997edc8a5..126bb911880f 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -1075,6 +1075,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
1075 | } | 1075 | } |
1076 | } | 1076 | } |
1077 | ip_mc_up(in_dev); | 1077 | ip_mc_up(in_dev); |
1078 | /* fall through */ | ||
1079 | case NETDEV_CHANGEADDR: | ||
1080 | if (IN_DEV_ARP_NOTIFY(in_dev)) | ||
1081 | arp_send(ARPOP_REQUEST, ETH_P_ARP, | ||
1082 | in_dev->ifa_list->ifa_address, | ||
1083 | dev, | ||
1084 | in_dev->ifa_list->ifa_address, | ||
1085 | NULL, dev->dev_addr, NULL); | ||
1078 | break; | 1086 | break; |
1079 | case NETDEV_DOWN: | 1087 | case NETDEV_DOWN: |
1080 | ip_mc_down(in_dev); | 1088 | ip_mc_down(in_dev); |
@@ -1208,7 +1216,8 @@ static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh, | |||
1208 | kfree_skb(skb); | 1216 | kfree_skb(skb); |
1209 | goto errout; | 1217 | goto errout; |
1210 | } | 1218 | } |
1211 | err = rtnl_notify(skb, net, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); | 1219 | rtnl_notify(skb, net, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); |
1220 | return; | ||
1212 | errout: | 1221 | errout: |
1213 | if (err < 0) | 1222 | if (err < 0) |
1214 | rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err); | 1223 | rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err); |
@@ -1439,6 +1448,7 @@ static struct devinet_sysctl_table { | |||
1439 | DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"), | 1448 | DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"), |
1440 | DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"), | 1449 | DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"), |
1441 | DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"), | 1450 | DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"), |
1451 | DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"), | ||
1442 | 1452 | ||
1443 | DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"), | 1453 | DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"), |
1444 | DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"), | 1454 | DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"), |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 741e4fa3e474..cafcc49d0993 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -275,7 +275,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
275 | fib_res_put(&res); | 275 | fib_res_put(&res); |
276 | if (no_addr) | 276 | if (no_addr) |
277 | goto last_resort; | 277 | goto last_resort; |
278 | if (rpf) | 278 | if (rpf == 1) |
279 | goto e_inval; | 279 | goto e_inval; |
280 | fl.oif = dev->ifindex; | 280 | fl.oif = dev->ifindex; |
281 | 281 | ||
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 4817dea3bc73..f831df500907 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -322,8 +322,9 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, | |||
322 | kfree_skb(skb); | 322 | kfree_skb(skb); |
323 | goto errout; | 323 | goto errout; |
324 | } | 324 | } |
325 | err = rtnl_notify(skb, info->nl_net, info->pid, RTNLGRP_IPV4_ROUTE, | 325 | rtnl_notify(skb, info->nl_net, info->pid, RTNLGRP_IPV4_ROUTE, |
326 | info->nlh, GFP_KERNEL); | 326 | info->nlh, GFP_KERNEL); |
327 | return; | ||
327 | errout: | 328 | errout: |
328 | if (err < 0) | 329 | if (err < 0) |
329 | rtnl_set_sk_err(info->nl_net, RTNLGRP_IPV4_ROUTE, err); | 330 | rtnl_set_sk_err(info->nl_net, RTNLGRP_IPV4_ROUTE, err); |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 705b33b184a3..3f50807237e0 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -375,6 +375,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
375 | inet->tos = ip_hdr(skb)->tos; | 375 | inet->tos = ip_hdr(skb)->tos; |
376 | daddr = ipc.addr = rt->rt_src; | 376 | daddr = ipc.addr = rt->rt_src; |
377 | ipc.opt = NULL; | 377 | ipc.opt = NULL; |
378 | ipc.shtx.flags = 0; | ||
378 | if (icmp_param->replyopts.optlen) { | 379 | if (icmp_param->replyopts.optlen) { |
379 | ipc.opt = &icmp_param->replyopts; | 380 | ipc.opt = &icmp_param->replyopts; |
380 | if (ipc.opt->srr) | 381 | if (ipc.opt->srr) |
@@ -532,6 +533,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
532 | inet_sk(sk)->tos = tos; | 533 | inet_sk(sk)->tos = tos; |
533 | ipc.addr = iph->saddr; | 534 | ipc.addr = iph->saddr; |
534 | ipc.opt = &icmp_param.replyopts; | 535 | ipc.opt = &icmp_param.replyopts; |
536 | ipc.shtx.flags = 0; | ||
535 | 537 | ||
536 | { | 538 | { |
537 | struct flowi fl = { | 539 | struct flowi fl = { |
@@ -1205,7 +1207,7 @@ static struct pernet_operations __net_initdata icmp_sk_ops = { | |||
1205 | 1207 | ||
1206 | int __init icmp_init(void) | 1208 | int __init icmp_init(void) |
1207 | { | 1209 | { |
1208 | return register_pernet_device(&icmp_sk_ops); | 1210 | return register_pernet_subsys(&icmp_sk_ops); |
1209 | } | 1211 | } |
1210 | 1212 | ||
1211 | EXPORT_SYMBOL(icmp_err_convert); | 1213 | EXPORT_SYMBOL(icmp_err_convert); |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index f26ab38680de..22cd19ee44e5 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -93,24 +93,40 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) | |||
93 | struct inet_bind_hashbucket *head; | 93 | struct inet_bind_hashbucket *head; |
94 | struct hlist_node *node; | 94 | struct hlist_node *node; |
95 | struct inet_bind_bucket *tb; | 95 | struct inet_bind_bucket *tb; |
96 | int ret; | 96 | int ret, attempts = 5; |
97 | struct net *net = sock_net(sk); | 97 | struct net *net = sock_net(sk); |
98 | int smallest_size = -1, smallest_rover; | ||
98 | 99 | ||
99 | local_bh_disable(); | 100 | local_bh_disable(); |
100 | if (!snum) { | 101 | if (!snum) { |
101 | int remaining, rover, low, high; | 102 | int remaining, rover, low, high; |
102 | 103 | ||
104 | again: | ||
103 | inet_get_local_port_range(&low, &high); | 105 | inet_get_local_port_range(&low, &high); |
104 | remaining = (high - low) + 1; | 106 | remaining = (high - low) + 1; |
105 | rover = net_random() % remaining + low; | 107 | smallest_rover = rover = net_random() % remaining + low; |
106 | 108 | ||
109 | smallest_size = -1; | ||
107 | do { | 110 | do { |
108 | head = &hashinfo->bhash[inet_bhashfn(net, rover, | 111 | head = &hashinfo->bhash[inet_bhashfn(net, rover, |
109 | hashinfo->bhash_size)]; | 112 | hashinfo->bhash_size)]; |
110 | spin_lock(&head->lock); | 113 | spin_lock(&head->lock); |
111 | inet_bind_bucket_for_each(tb, node, &head->chain) | 114 | inet_bind_bucket_for_each(tb, node, &head->chain) |
112 | if (ib_net(tb) == net && tb->port == rover) | 115 | if (ib_net(tb) == net && tb->port == rover) { |
116 | if (tb->fastreuse > 0 && | ||
117 | sk->sk_reuse && | ||
118 | sk->sk_state != TCP_LISTEN && | ||
119 | (tb->num_owners < smallest_size || smallest_size == -1)) { | ||
120 | smallest_size = tb->num_owners; | ||
121 | smallest_rover = rover; | ||
122 | if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) { | ||
123 | spin_unlock(&head->lock); | ||
124 | snum = smallest_rover; | ||
125 | goto have_snum; | ||
126 | } | ||
127 | } | ||
113 | goto next; | 128 | goto next; |
129 | } | ||
114 | break; | 130 | break; |
115 | next: | 131 | next: |
116 | spin_unlock(&head->lock); | 132 | spin_unlock(&head->lock); |
@@ -125,14 +141,19 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) | |||
125 | * the top level, not from the 'break;' statement. | 141 | * the top level, not from the 'break;' statement. |
126 | */ | 142 | */ |
127 | ret = 1; | 143 | ret = 1; |
128 | if (remaining <= 0) | 144 | if (remaining <= 0) { |
145 | if (smallest_size != -1) { | ||
146 | snum = smallest_rover; | ||
147 | goto have_snum; | ||
148 | } | ||
129 | goto fail; | 149 | goto fail; |
130 | 150 | } | |
131 | /* OK, here is the one we will use. HEAD is | 151 | /* OK, here is the one we will use. HEAD is |
132 | * non-NULL and we hold it's mutex. | 152 | * non-NULL and we hold it's mutex. |
133 | */ | 153 | */ |
134 | snum = rover; | 154 | snum = rover; |
135 | } else { | 155 | } else { |
156 | have_snum: | ||
136 | head = &hashinfo->bhash[inet_bhashfn(net, snum, | 157 | head = &hashinfo->bhash[inet_bhashfn(net, snum, |
137 | hashinfo->bhash_size)]; | 158 | hashinfo->bhash_size)]; |
138 | spin_lock(&head->lock); | 159 | spin_lock(&head->lock); |
@@ -145,12 +166,19 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) | |||
145 | tb_found: | 166 | tb_found: |
146 | if (!hlist_empty(&tb->owners)) { | 167 | if (!hlist_empty(&tb->owners)) { |
147 | if (tb->fastreuse > 0 && | 168 | if (tb->fastreuse > 0 && |
148 | sk->sk_reuse && sk->sk_state != TCP_LISTEN) { | 169 | sk->sk_reuse && sk->sk_state != TCP_LISTEN && |
170 | smallest_size == -1) { | ||
149 | goto success; | 171 | goto success; |
150 | } else { | 172 | } else { |
151 | ret = 1; | 173 | ret = 1; |
152 | if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) | 174 | if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { |
175 | if (sk->sk_reuse && sk->sk_state != TCP_LISTEN && | ||
176 | smallest_size != -1 && --attempts >= 0) { | ||
177 | spin_unlock(&head->lock); | ||
178 | goto again; | ||
179 | } | ||
153 | goto fail_unlock; | 180 | goto fail_unlock; |
181 | } | ||
154 | } | 182 | } |
155 | } | 183 | } |
156 | tb_not_found: | 184 | tb_not_found: |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 6a1045da48d2..625cc5f64c94 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -38,6 +38,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep, | |||
38 | write_pnet(&tb->ib_net, hold_net(net)); | 38 | write_pnet(&tb->ib_net, hold_net(net)); |
39 | tb->port = snum; | 39 | tb->port = snum; |
40 | tb->fastreuse = 0; | 40 | tb->fastreuse = 0; |
41 | tb->num_owners = 0; | ||
41 | INIT_HLIST_HEAD(&tb->owners); | 42 | INIT_HLIST_HEAD(&tb->owners); |
42 | hlist_add_head(&tb->node, &head->chain); | 43 | hlist_add_head(&tb->node, &head->chain); |
43 | } | 44 | } |
@@ -59,8 +60,13 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket | |||
59 | void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, | 60 | void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, |
60 | const unsigned short snum) | 61 | const unsigned short snum) |
61 | { | 62 | { |
63 | struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; | ||
64 | |||
65 | atomic_inc(&hashinfo->bsockets); | ||
66 | |||
62 | inet_sk(sk)->num = snum; | 67 | inet_sk(sk)->num = snum; |
63 | sk_add_bind_node(sk, &tb->owners); | 68 | sk_add_bind_node(sk, &tb->owners); |
69 | tb->num_owners++; | ||
64 | inet_csk(sk)->icsk_bind_hash = tb; | 70 | inet_csk(sk)->icsk_bind_hash = tb; |
65 | } | 71 | } |
66 | 72 | ||
@@ -75,9 +81,12 @@ static void __inet_put_port(struct sock *sk) | |||
75 | struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; | 81 | struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; |
76 | struct inet_bind_bucket *tb; | 82 | struct inet_bind_bucket *tb; |
77 | 83 | ||
84 | atomic_dec(&hashinfo->bsockets); | ||
85 | |||
78 | spin_lock(&head->lock); | 86 | spin_lock(&head->lock); |
79 | tb = inet_csk(sk)->icsk_bind_hash; | 87 | tb = inet_csk(sk)->icsk_bind_hash; |
80 | __sk_del_bind_node(sk); | 88 | __sk_del_bind_node(sk); |
89 | tb->num_owners--; | ||
81 | inet_csk(sk)->icsk_bind_hash = NULL; | 90 | inet_csk(sk)->icsk_bind_hash = NULL; |
82 | inet_sk(sk)->num = 0; | 91 | inet_sk(sk)->num = 0; |
83 | inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb); | 92 | inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb); |
@@ -444,9 +453,9 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, | |||
444 | */ | 453 | */ |
445 | inet_bind_bucket_for_each(tb, node, &head->chain) { | 454 | inet_bind_bucket_for_each(tb, node, &head->chain) { |
446 | if (ib_net(tb) == net && tb->port == port) { | 455 | if (ib_net(tb) == net && tb->port == port) { |
447 | WARN_ON(hlist_empty(&tb->owners)); | ||
448 | if (tb->fastreuse >= 0) | 456 | if (tb->fastreuse >= 0) |
449 | goto next_port; | 457 | goto next_port; |
458 | WARN_ON(hlist_empty(&tb->owners)); | ||
450 | if (!check_established(death_row, sk, | 459 | if (!check_established(death_row, sk, |
451 | port, &tw)) | 460 | port, &tw)) |
452 | goto ok; | 461 | goto ok; |
@@ -523,6 +532,7 @@ void inet_hashinfo_init(struct inet_hashinfo *h) | |||
523 | { | 532 | { |
524 | int i; | 533 | int i; |
525 | 534 | ||
535 | atomic_set(&h->bsockets, 0); | ||
526 | for (i = 0; i < INET_LHTABLE_SIZE; i++) { | 536 | for (i = 0; i < INET_LHTABLE_SIZE; i++) { |
527 | spin_lock_init(&h->listening_hash[i].lock); | 537 | spin_lock_init(&h->listening_hash[i].lock); |
528 | INIT_HLIST_NULLS_HEAD(&h->listening_hash[i].head, | 538 | INIT_HLIST_NULLS_HEAD(&h->listening_hash[i].head, |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 0101521f366b..e62510d5ea5a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -164,67 +164,124 @@ static DEFINE_RWLOCK(ipgre_lock); | |||
164 | 164 | ||
165 | /* Given src, dst and key, find appropriate for input tunnel. */ | 165 | /* Given src, dst and key, find appropriate for input tunnel. */ |
166 | 166 | ||
167 | static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net, | 167 | static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, |
168 | __be32 remote, __be32 local, | 168 | __be32 remote, __be32 local, |
169 | __be32 key, __be16 gre_proto) | 169 | __be32 key, __be16 gre_proto) |
170 | { | 170 | { |
171 | struct net *net = dev_net(dev); | ||
172 | int link = dev->ifindex; | ||
171 | unsigned h0 = HASH(remote); | 173 | unsigned h0 = HASH(remote); |
172 | unsigned h1 = HASH(key); | 174 | unsigned h1 = HASH(key); |
173 | struct ip_tunnel *t; | 175 | struct ip_tunnel *t, *cand = NULL; |
174 | struct ip_tunnel *t2 = NULL; | ||
175 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); | 176 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); |
176 | int dev_type = (gre_proto == htons(ETH_P_TEB)) ? | 177 | int dev_type = (gre_proto == htons(ETH_P_TEB)) ? |
177 | ARPHRD_ETHER : ARPHRD_IPGRE; | 178 | ARPHRD_ETHER : ARPHRD_IPGRE; |
179 | int score, cand_score = 4; | ||
178 | 180 | ||
179 | for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { | 181 | for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { |
180 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { | 182 | if (local != t->parms.iph.saddr || |
181 | if (t->parms.i_key == key && t->dev->flags & IFF_UP) { | 183 | remote != t->parms.iph.daddr || |
182 | if (t->dev->type == dev_type) | 184 | key != t->parms.i_key || |
183 | return t; | 185 | !(t->dev->flags & IFF_UP)) |
184 | if (t->dev->type == ARPHRD_IPGRE && !t2) | 186 | continue; |
185 | t2 = t; | 187 | |
186 | } | 188 | if (t->dev->type != ARPHRD_IPGRE && |
189 | t->dev->type != dev_type) | ||
190 | continue; | ||
191 | |||
192 | score = 0; | ||
193 | if (t->parms.link != link) | ||
194 | score |= 1; | ||
195 | if (t->dev->type != dev_type) | ||
196 | score |= 2; | ||
197 | if (score == 0) | ||
198 | return t; | ||
199 | |||
200 | if (score < cand_score) { | ||
201 | cand = t; | ||
202 | cand_score = score; | ||
187 | } | 203 | } |
188 | } | 204 | } |
189 | 205 | ||
190 | for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { | 206 | for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { |
191 | if (remote == t->parms.iph.daddr) { | 207 | if (remote != t->parms.iph.daddr || |
192 | if (t->parms.i_key == key && t->dev->flags & IFF_UP) { | 208 | key != t->parms.i_key || |
193 | if (t->dev->type == dev_type) | 209 | !(t->dev->flags & IFF_UP)) |
194 | return t; | 210 | continue; |
195 | if (t->dev->type == ARPHRD_IPGRE && !t2) | 211 | |
196 | t2 = t; | 212 | if (t->dev->type != ARPHRD_IPGRE && |
197 | } | 213 | t->dev->type != dev_type) |
214 | continue; | ||
215 | |||
216 | score = 0; | ||
217 | if (t->parms.link != link) | ||
218 | score |= 1; | ||
219 | if (t->dev->type != dev_type) | ||
220 | score |= 2; | ||
221 | if (score == 0) | ||
222 | return t; | ||
223 | |||
224 | if (score < cand_score) { | ||
225 | cand = t; | ||
226 | cand_score = score; | ||
198 | } | 227 | } |
199 | } | 228 | } |
200 | 229 | ||
201 | for (t = ign->tunnels_l[h1]; t; t = t->next) { | 230 | for (t = ign->tunnels_l[h1]; t; t = t->next) { |
202 | if (local == t->parms.iph.saddr || | 231 | if ((local != t->parms.iph.saddr && |
203 | (local == t->parms.iph.daddr && | 232 | (local != t->parms.iph.daddr || |
204 | ipv4_is_multicast(local))) { | 233 | !ipv4_is_multicast(local))) || |
205 | if (t->parms.i_key == key && t->dev->flags & IFF_UP) { | 234 | key != t->parms.i_key || |
206 | if (t->dev->type == dev_type) | 235 | !(t->dev->flags & IFF_UP)) |
207 | return t; | 236 | continue; |
208 | if (t->dev->type == ARPHRD_IPGRE && !t2) | 237 | |
209 | t2 = t; | 238 | if (t->dev->type != ARPHRD_IPGRE && |
210 | } | 239 | t->dev->type != dev_type) |
240 | continue; | ||
241 | |||
242 | score = 0; | ||
243 | if (t->parms.link != link) | ||
244 | score |= 1; | ||
245 | if (t->dev->type != dev_type) | ||
246 | score |= 2; | ||
247 | if (score == 0) | ||
248 | return t; | ||
249 | |||
250 | if (score < cand_score) { | ||
251 | cand = t; | ||
252 | cand_score = score; | ||
211 | } | 253 | } |
212 | } | 254 | } |
213 | 255 | ||
214 | for (t = ign->tunnels_wc[h1]; t; t = t->next) { | 256 | for (t = ign->tunnels_wc[h1]; t; t = t->next) { |
215 | if (t->parms.i_key == key && t->dev->flags & IFF_UP) { | 257 | if (t->parms.i_key != key || |
216 | if (t->dev->type == dev_type) | 258 | !(t->dev->flags & IFF_UP)) |
217 | return t; | 259 | continue; |
218 | if (t->dev->type == ARPHRD_IPGRE && !t2) | 260 | |
219 | t2 = t; | 261 | if (t->dev->type != ARPHRD_IPGRE && |
262 | t->dev->type != dev_type) | ||
263 | continue; | ||
264 | |||
265 | score = 0; | ||
266 | if (t->parms.link != link) | ||
267 | score |= 1; | ||
268 | if (t->dev->type != dev_type) | ||
269 | score |= 2; | ||
270 | if (score == 0) | ||
271 | return t; | ||
272 | |||
273 | if (score < cand_score) { | ||
274 | cand = t; | ||
275 | cand_score = score; | ||
220 | } | 276 | } |
221 | } | 277 | } |
222 | 278 | ||
223 | if (t2) | 279 | if (cand != NULL) |
224 | return t2; | 280 | return cand; |
225 | 281 | ||
226 | if (ign->fb_tunnel_dev->flags&IFF_UP) | 282 | if (ign->fb_tunnel_dev->flags & IFF_UP) |
227 | return netdev_priv(ign->fb_tunnel_dev); | 283 | return netdev_priv(ign->fb_tunnel_dev); |
284 | |||
228 | return NULL; | 285 | return NULL; |
229 | } | 286 | } |
230 | 287 | ||
@@ -284,6 +341,7 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net, | |||
284 | __be32 remote = parms->iph.daddr; | 341 | __be32 remote = parms->iph.daddr; |
285 | __be32 local = parms->iph.saddr; | 342 | __be32 local = parms->iph.saddr; |
286 | __be32 key = parms->i_key; | 343 | __be32 key = parms->i_key; |
344 | int link = parms->link; | ||
287 | struct ip_tunnel *t, **tp; | 345 | struct ip_tunnel *t, **tp; |
288 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); | 346 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); |
289 | 347 | ||
@@ -291,6 +349,7 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net, | |||
291 | if (local == t->parms.iph.saddr && | 349 | if (local == t->parms.iph.saddr && |
292 | remote == t->parms.iph.daddr && | 350 | remote == t->parms.iph.daddr && |
293 | key == t->parms.i_key && | 351 | key == t->parms.i_key && |
352 | link == t->parms.link && | ||
294 | type == t->dev->type) | 353 | type == t->dev->type) |
295 | break; | 354 | break; |
296 | 355 | ||
@@ -421,7 +480,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
421 | } | 480 | } |
422 | 481 | ||
423 | read_lock(&ipgre_lock); | 482 | read_lock(&ipgre_lock); |
424 | t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr, | 483 | t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr, |
425 | flags & GRE_KEY ? | 484 | flags & GRE_KEY ? |
426 | *(((__be32 *)p) + (grehlen / 4) - 1) : 0, | 485 | *(((__be32 *)p) + (grehlen / 4) - 1) : 0, |
427 | p[1]); | 486 | p[1]); |
@@ -432,7 +491,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
432 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 491 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |
433 | goto out; | 492 | goto out; |
434 | 493 | ||
435 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) | 494 | if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) |
436 | t->err_count++; | 495 | t->err_count++; |
437 | else | 496 | else |
438 | t->err_count = 1; | 497 | t->err_count = 1; |
@@ -518,7 +577,7 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
518 | gre_proto = *(__be16 *)(h + 2); | 577 | gre_proto = *(__be16 *)(h + 2); |
519 | 578 | ||
520 | read_lock(&ipgre_lock); | 579 | read_lock(&ipgre_lock); |
521 | if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev), | 580 | if ((tunnel = ipgre_tunnel_lookup(skb->dev, |
522 | iph->saddr, iph->daddr, key, | 581 | iph->saddr, iph->daddr, key, |
523 | gre_proto))) { | 582 | gre_proto))) { |
524 | struct net_device_stats *stats = &tunnel->dev->stats; | 583 | struct net_device_stats *stats = &tunnel->dev->stats; |
@@ -744,7 +803,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
744 | #endif | 803 | #endif |
745 | 804 | ||
746 | if (tunnel->err_count > 0) { | 805 | if (tunnel->err_count > 0) { |
747 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { | 806 | if (time_before(jiffies, |
807 | tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { | ||
748 | tunnel->err_count--; | 808 | tunnel->err_count--; |
749 | 809 | ||
750 | dst_link_failure(skb); | 810 | dst_link_failure(skb); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8ebe86dd72af..3e7e910c7c0f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -935,6 +935,10 @@ alloc_new_skb: | |||
935 | sk->sk_allocation); | 935 | sk->sk_allocation); |
936 | if (unlikely(skb == NULL)) | 936 | if (unlikely(skb == NULL)) |
937 | err = -ENOBUFS; | 937 | err = -ENOBUFS; |
938 | else | ||
939 | /* only the initial fragment is | ||
940 | time stamped */ | ||
941 | ipc->shtx.flags = 0; | ||
938 | } | 942 | } |
939 | if (skb == NULL) | 943 | if (skb == NULL) |
940 | goto error; | 944 | goto error; |
@@ -945,6 +949,7 @@ alloc_new_skb: | |||
945 | skb->ip_summed = csummode; | 949 | skb->ip_summed = csummode; |
946 | skb->csum = 0; | 950 | skb->csum = 0; |
947 | skb_reserve(skb, hh_len); | 951 | skb_reserve(skb, hh_len); |
952 | *skb_tx(skb) = ipc->shtx; | ||
948 | 953 | ||
949 | /* | 954 | /* |
950 | * Find where to start putting bytes. | 955 | * Find where to start putting bytes. |
@@ -1364,6 +1369,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar | |||
1364 | 1369 | ||
1365 | daddr = ipc.addr = rt->rt_src; | 1370 | daddr = ipc.addr = rt->rt_src; |
1366 | ipc.opt = NULL; | 1371 | ipc.opt = NULL; |
1372 | ipc.shtx.flags = 0; | ||
1367 | 1373 | ||
1368 | if (replyopts.opt.optlen) { | 1374 | if (replyopts.opt.optlen) { |
1369 | ipc.opt = &replyopts.opt; | 1375 | ipc.opt = &replyopts.opt; |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index d722013c1cae..90d22ae0a419 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -100,8 +100,8 @@ | |||
100 | #define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers | 100 | #define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers |
101 | - '3' from resolv.h */ | 101 | - '3' from resolv.h */ |
102 | 102 | ||
103 | #define NONE __constant_htonl(INADDR_NONE) | 103 | #define NONE cpu_to_be32(INADDR_NONE) |
104 | #define ANY __constant_htonl(INADDR_ANY) | 104 | #define ANY cpu_to_be32(INADDR_ANY) |
105 | 105 | ||
106 | /* | 106 | /* |
107 | * Public IP configuration | 107 | * Public IP configuration |
@@ -406,7 +406,7 @@ static int __init ic_defaults(void) | |||
406 | static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); | 406 | static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); |
407 | 407 | ||
408 | static struct packet_type rarp_packet_type __initdata = { | 408 | static struct packet_type rarp_packet_type __initdata = { |
409 | .type = __constant_htons(ETH_P_RARP), | 409 | .type = cpu_to_be16(ETH_P_RARP), |
410 | .func = ic_rarp_recv, | 410 | .func = ic_rarp_recv, |
411 | }; | 411 | }; |
412 | 412 | ||
@@ -568,7 +568,7 @@ struct bootp_pkt { /* BOOTP packet format */ | |||
568 | static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); | 568 | static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); |
569 | 569 | ||
570 | static struct packet_type bootp_packet_type __initdata = { | 570 | static struct packet_type bootp_packet_type __initdata = { |
571 | .type = __constant_htons(ETH_P_IP), | 571 | .type = cpu_to_be16(ETH_P_IP), |
572 | .func = ic_bootp_recv, | 572 | .func = ic_bootp_recv, |
573 | }; | 573 | }; |
574 | 574 | ||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 5079dfbc6f38..9054139795af 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -327,7 +327,7 @@ static int ipip_err(struct sk_buff *skb, u32 info) | |||
327 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 327 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |
328 | goto out; | 328 | goto out; |
329 | 329 | ||
330 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) | 330 | if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) |
331 | t->err_count++; | 331 | t->err_count++; |
332 | else | 332 | else |
333 | t->err_count = 1; | 333 | t->err_count = 1; |
@@ -466,7 +466,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
466 | } | 466 | } |
467 | 467 | ||
468 | if (tunnel->err_count > 0) { | 468 | if (tunnel->err_count > 0) { |
469 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { | 469 | if (time_before(jiffies, |
470 | tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { | ||
470 | tunnel->err_count--; | 471 | tunnel->err_count--; |
471 | dst_link_failure(skb); | 472 | dst_link_failure(skb); |
472 | } else | 473 | } else |
@@ -750,7 +751,7 @@ static struct xfrm_tunnel ipip_handler = { | |||
750 | .priority = 1, | 751 | .priority = 1, |
751 | }; | 752 | }; |
752 | 753 | ||
753 | static char banner[] __initdata = | 754 | static const char banner[] __initconst = |
754 | KERN_INFO "IPv4 over IPv4 tunneling driver\n"; | 755 | KERN_INFO "IPv4 over IPv4 tunneling driver\n"; |
755 | 756 | ||
756 | static void ipip_destroy_tunnels(struct ipip_net *ipn) | 757 | static void ipip_destroy_tunnels(struct ipip_net *ipn) |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 14666449dc1c..13e9dd3012b3 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -67,9 +67,6 @@ | |||
67 | #define CONFIG_IP_PIMSM 1 | 67 | #define CONFIG_IP_PIMSM 1 |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | static struct sock *mroute_socket; | ||
71 | |||
72 | |||
73 | /* Big lock, protecting vif table, mrt cache and mroute socket state. | 70 | /* Big lock, protecting vif table, mrt cache and mroute socket state. |
74 | Note that the changes are semaphored via rtnl_lock. | 71 | Note that the changes are semaphored via rtnl_lock. |
75 | */ | 72 | */ |
@@ -80,18 +77,9 @@ static DEFINE_RWLOCK(mrt_lock); | |||
80 | * Multicast router control variables | 77 | * Multicast router control variables |
81 | */ | 78 | */ |
82 | 79 | ||
83 | static struct vif_device vif_table[MAXVIFS]; /* Devices */ | 80 | #define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL) |
84 | static int maxvif; | ||
85 | |||
86 | #define VIF_EXISTS(idx) (vif_table[idx].dev != NULL) | ||
87 | |||
88 | static int mroute_do_assert; /* Set in PIM assert */ | ||
89 | static int mroute_do_pim; | ||
90 | |||
91 | static struct mfc_cache *mfc_cache_array[MFC_LINES]; /* Forwarding cache */ | ||
92 | 81 | ||
93 | static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ | 82 | static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ |
94 | static atomic_t cache_resolve_queue_len; /* Size of unresolved */ | ||
95 | 83 | ||
96 | /* Special spinlock for queue of unresolved entries */ | 84 | /* Special spinlock for queue of unresolved entries */ |
97 | static DEFINE_SPINLOCK(mfc_unres_lock); | 85 | static DEFINE_SPINLOCK(mfc_unres_lock); |
@@ -107,7 +95,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock); | |||
107 | static struct kmem_cache *mrt_cachep __read_mostly; | 95 | static struct kmem_cache *mrt_cachep __read_mostly; |
108 | 96 | ||
109 | static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local); | 97 | static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local); |
110 | static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert); | 98 | static int ipmr_cache_report(struct net *net, |
99 | struct sk_buff *pkt, vifi_t vifi, int assert); | ||
111 | static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); | 100 | static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); |
112 | 101 | ||
113 | #ifdef CONFIG_IP_PIMSM_V2 | 102 | #ifdef CONFIG_IP_PIMSM_V2 |
@@ -120,9 +109,11 @@ static struct timer_list ipmr_expire_timer; | |||
120 | 109 | ||
121 | static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) | 110 | static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) |
122 | { | 111 | { |
112 | struct net *net = dev_net(dev); | ||
113 | |||
123 | dev_close(dev); | 114 | dev_close(dev); |
124 | 115 | ||
125 | dev = __dev_get_by_name(&init_net, "tunl0"); | 116 | dev = __dev_get_by_name(net, "tunl0"); |
126 | if (dev) { | 117 | if (dev) { |
127 | const struct net_device_ops *ops = dev->netdev_ops; | 118 | const struct net_device_ops *ops = dev->netdev_ops; |
128 | struct ifreq ifr; | 119 | struct ifreq ifr; |
@@ -148,11 +139,11 @@ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) | |||
148 | } | 139 | } |
149 | 140 | ||
150 | static | 141 | static |
151 | struct net_device *ipmr_new_tunnel(struct vifctl *v) | 142 | struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v) |
152 | { | 143 | { |
153 | struct net_device *dev; | 144 | struct net_device *dev; |
154 | 145 | ||
155 | dev = __dev_get_by_name(&init_net, "tunl0"); | 146 | dev = __dev_get_by_name(net, "tunl0"); |
156 | 147 | ||
157 | if (dev) { | 148 | if (dev) { |
158 | const struct net_device_ops *ops = dev->netdev_ops; | 149 | const struct net_device_ops *ops = dev->netdev_ops; |
@@ -181,7 +172,8 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v) | |||
181 | 172 | ||
182 | dev = NULL; | 173 | dev = NULL; |
183 | 174 | ||
184 | if (err == 0 && (dev = __dev_get_by_name(&init_net, p.name)) != NULL) { | 175 | if (err == 0 && |
176 | (dev = __dev_get_by_name(net, p.name)) != NULL) { | ||
185 | dev->flags |= IFF_MULTICAST; | 177 | dev->flags |= IFF_MULTICAST; |
186 | 178 | ||
187 | in_dev = __in_dev_get_rtnl(dev); | 179 | in_dev = __in_dev_get_rtnl(dev); |
@@ -209,14 +201,15 @@ failure: | |||
209 | 201 | ||
210 | #ifdef CONFIG_IP_PIMSM | 202 | #ifdef CONFIG_IP_PIMSM |
211 | 203 | ||
212 | static int reg_vif_num = -1; | ||
213 | |||
214 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | 204 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) |
215 | { | 205 | { |
206 | struct net *net = dev_net(dev); | ||
207 | |||
216 | read_lock(&mrt_lock); | 208 | read_lock(&mrt_lock); |
217 | dev->stats.tx_bytes += skb->len; | 209 | dev->stats.tx_bytes += skb->len; |
218 | dev->stats.tx_packets++; | 210 | dev->stats.tx_packets++; |
219 | ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT); | 211 | ipmr_cache_report(net, skb, net->ipv4.mroute_reg_vif_num, |
212 | IGMPMSG_WHOLEPKT); | ||
220 | read_unlock(&mrt_lock); | 213 | read_unlock(&mrt_lock); |
221 | kfree_skb(skb); | 214 | kfree_skb(skb); |
222 | return 0; | 215 | return 0; |
@@ -283,16 +276,16 @@ failure: | |||
283 | * @notify: Set to 1, if the caller is a notifier_call | 276 | * @notify: Set to 1, if the caller is a notifier_call |
284 | */ | 277 | */ |
285 | 278 | ||
286 | static int vif_delete(int vifi, int notify) | 279 | static int vif_delete(struct net *net, int vifi, int notify) |
287 | { | 280 | { |
288 | struct vif_device *v; | 281 | struct vif_device *v; |
289 | struct net_device *dev; | 282 | struct net_device *dev; |
290 | struct in_device *in_dev; | 283 | struct in_device *in_dev; |
291 | 284 | ||
292 | if (vifi < 0 || vifi >= maxvif) | 285 | if (vifi < 0 || vifi >= net->ipv4.maxvif) |
293 | return -EADDRNOTAVAIL; | 286 | return -EADDRNOTAVAIL; |
294 | 287 | ||
295 | v = &vif_table[vifi]; | 288 | v = &net->ipv4.vif_table[vifi]; |
296 | 289 | ||
297 | write_lock_bh(&mrt_lock); | 290 | write_lock_bh(&mrt_lock); |
298 | dev = v->dev; | 291 | dev = v->dev; |
@@ -304,17 +297,17 @@ static int vif_delete(int vifi, int notify) | |||
304 | } | 297 | } |
305 | 298 | ||
306 | #ifdef CONFIG_IP_PIMSM | 299 | #ifdef CONFIG_IP_PIMSM |
307 | if (vifi == reg_vif_num) | 300 | if (vifi == net->ipv4.mroute_reg_vif_num) |
308 | reg_vif_num = -1; | 301 | net->ipv4.mroute_reg_vif_num = -1; |
309 | #endif | 302 | #endif |
310 | 303 | ||
311 | if (vifi+1 == maxvif) { | 304 | if (vifi+1 == net->ipv4.maxvif) { |
312 | int tmp; | 305 | int tmp; |
313 | for (tmp=vifi-1; tmp>=0; tmp--) { | 306 | for (tmp=vifi-1; tmp>=0; tmp--) { |
314 | if (VIF_EXISTS(tmp)) | 307 | if (VIF_EXISTS(net, tmp)) |
315 | break; | 308 | break; |
316 | } | 309 | } |
317 | maxvif = tmp+1; | 310 | net->ipv4.maxvif = tmp+1; |
318 | } | 311 | } |
319 | 312 | ||
320 | write_unlock_bh(&mrt_lock); | 313 | write_unlock_bh(&mrt_lock); |
@@ -333,6 +326,12 @@ static int vif_delete(int vifi, int notify) | |||
333 | return 0; | 326 | return 0; |
334 | } | 327 | } |
335 | 328 | ||
329 | static inline void ipmr_cache_free(struct mfc_cache *c) | ||
330 | { | ||
331 | release_net(mfc_net(c)); | ||
332 | kmem_cache_free(mrt_cachep, c); | ||
333 | } | ||
334 | |||
336 | /* Destroy an unresolved cache entry, killing queued skbs | 335 | /* Destroy an unresolved cache entry, killing queued skbs |
337 | and reporting error to netlink readers. | 336 | and reporting error to netlink readers. |
338 | */ | 337 | */ |
@@ -341,8 +340,9 @@ static void ipmr_destroy_unres(struct mfc_cache *c) | |||
341 | { | 340 | { |
342 | struct sk_buff *skb; | 341 | struct sk_buff *skb; |
343 | struct nlmsgerr *e; | 342 | struct nlmsgerr *e; |
343 | struct net *net = mfc_net(c); | ||
344 | 344 | ||
345 | atomic_dec(&cache_resolve_queue_len); | 345 | atomic_dec(&net->ipv4.cache_resolve_queue_len); |
346 | 346 | ||
347 | while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { | 347 | while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { |
348 | if (ip_hdr(skb)->version == 0) { | 348 | if (ip_hdr(skb)->version == 0) { |
@@ -354,12 +354,12 @@ static void ipmr_destroy_unres(struct mfc_cache *c) | |||
354 | e->error = -ETIMEDOUT; | 354 | e->error = -ETIMEDOUT; |
355 | memset(&e->msg, 0, sizeof(e->msg)); | 355 | memset(&e->msg, 0, sizeof(e->msg)); |
356 | 356 | ||
357 | rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid); | 357 | rtnl_unicast(skb, net, NETLINK_CB(skb).pid); |
358 | } else | 358 | } else |
359 | kfree_skb(skb); | 359 | kfree_skb(skb); |
360 | } | 360 | } |
361 | 361 | ||
362 | kmem_cache_free(mrt_cachep, c); | 362 | ipmr_cache_free(c); |
363 | } | 363 | } |
364 | 364 | ||
365 | 365 | ||
@@ -376,7 +376,7 @@ static void ipmr_expire_process(unsigned long dummy) | |||
376 | return; | 376 | return; |
377 | } | 377 | } |
378 | 378 | ||
379 | if (atomic_read(&cache_resolve_queue_len) == 0) | 379 | if (mfc_unres_queue == NULL) |
380 | goto out; | 380 | goto out; |
381 | 381 | ||
382 | now = jiffies; | 382 | now = jiffies; |
@@ -397,7 +397,7 @@ static void ipmr_expire_process(unsigned long dummy) | |||
397 | ipmr_destroy_unres(c); | 397 | ipmr_destroy_unres(c); |
398 | } | 398 | } |
399 | 399 | ||
400 | if (atomic_read(&cache_resolve_queue_len)) | 400 | if (mfc_unres_queue != NULL) |
401 | mod_timer(&ipmr_expire_timer, jiffies + expires); | 401 | mod_timer(&ipmr_expire_timer, jiffies + expires); |
402 | 402 | ||
403 | out: | 403 | out: |
@@ -409,13 +409,15 @@ out: | |||
409 | static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) | 409 | static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) |
410 | { | 410 | { |
411 | int vifi; | 411 | int vifi; |
412 | struct net *net = mfc_net(cache); | ||
412 | 413 | ||
413 | cache->mfc_un.res.minvif = MAXVIFS; | 414 | cache->mfc_un.res.minvif = MAXVIFS; |
414 | cache->mfc_un.res.maxvif = 0; | 415 | cache->mfc_un.res.maxvif = 0; |
415 | memset(cache->mfc_un.res.ttls, 255, MAXVIFS); | 416 | memset(cache->mfc_un.res.ttls, 255, MAXVIFS); |
416 | 417 | ||
417 | for (vifi=0; vifi<maxvif; vifi++) { | 418 | for (vifi = 0; vifi < net->ipv4.maxvif; vifi++) { |
418 | if (VIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) { | 419 | if (VIF_EXISTS(net, vifi) && |
420 | ttls[vifi] && ttls[vifi] < 255) { | ||
419 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; | 421 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; |
420 | if (cache->mfc_un.res.minvif > vifi) | 422 | if (cache->mfc_un.res.minvif > vifi) |
421 | cache->mfc_un.res.minvif = vifi; | 423 | cache->mfc_un.res.minvif = vifi; |
@@ -425,16 +427,16 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) | |||
425 | } | 427 | } |
426 | } | 428 | } |
427 | 429 | ||
428 | static int vif_add(struct vifctl *vifc, int mrtsock) | 430 | static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) |
429 | { | 431 | { |
430 | int vifi = vifc->vifc_vifi; | 432 | int vifi = vifc->vifc_vifi; |
431 | struct vif_device *v = &vif_table[vifi]; | 433 | struct vif_device *v = &net->ipv4.vif_table[vifi]; |
432 | struct net_device *dev; | 434 | struct net_device *dev; |
433 | struct in_device *in_dev; | 435 | struct in_device *in_dev; |
434 | int err; | 436 | int err; |
435 | 437 | ||
436 | /* Is vif busy ? */ | 438 | /* Is vif busy ? */ |
437 | if (VIF_EXISTS(vifi)) | 439 | if (VIF_EXISTS(net, vifi)) |
438 | return -EADDRINUSE; | 440 | return -EADDRINUSE; |
439 | 441 | ||
440 | switch (vifc->vifc_flags) { | 442 | switch (vifc->vifc_flags) { |
@@ -444,7 +446,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
444 | * Special Purpose VIF in PIM | 446 | * Special Purpose VIF in PIM |
445 | * All the packets will be sent to the daemon | 447 | * All the packets will be sent to the daemon |
446 | */ | 448 | */ |
447 | if (reg_vif_num >= 0) | 449 | if (net->ipv4.mroute_reg_vif_num >= 0) |
448 | return -EADDRINUSE; | 450 | return -EADDRINUSE; |
449 | dev = ipmr_reg_vif(); | 451 | dev = ipmr_reg_vif(); |
450 | if (!dev) | 452 | if (!dev) |
@@ -458,7 +460,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
458 | break; | 460 | break; |
459 | #endif | 461 | #endif |
460 | case VIFF_TUNNEL: | 462 | case VIFF_TUNNEL: |
461 | dev = ipmr_new_tunnel(vifc); | 463 | dev = ipmr_new_tunnel(net, vifc); |
462 | if (!dev) | 464 | if (!dev) |
463 | return -ENOBUFS; | 465 | return -ENOBUFS; |
464 | err = dev_set_allmulti(dev, 1); | 466 | err = dev_set_allmulti(dev, 1); |
@@ -469,7 +471,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
469 | } | 471 | } |
470 | break; | 472 | break; |
471 | case 0: | 473 | case 0: |
472 | dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr); | 474 | dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr); |
473 | if (!dev) | 475 | if (!dev) |
474 | return -EADDRNOTAVAIL; | 476 | return -EADDRNOTAVAIL; |
475 | err = dev_set_allmulti(dev, 1); | 477 | err = dev_set_allmulti(dev, 1); |
@@ -510,20 +512,22 @@ static int vif_add(struct vifctl *vifc, int mrtsock) | |||
510 | v->dev = dev; | 512 | v->dev = dev; |
511 | #ifdef CONFIG_IP_PIMSM | 513 | #ifdef CONFIG_IP_PIMSM |
512 | if (v->flags&VIFF_REGISTER) | 514 | if (v->flags&VIFF_REGISTER) |
513 | reg_vif_num = vifi; | 515 | net->ipv4.mroute_reg_vif_num = vifi; |
514 | #endif | 516 | #endif |
515 | if (vifi+1 > maxvif) | 517 | if (vifi+1 > net->ipv4.maxvif) |
516 | maxvif = vifi+1; | 518 | net->ipv4.maxvif = vifi+1; |
517 | write_unlock_bh(&mrt_lock); | 519 | write_unlock_bh(&mrt_lock); |
518 | return 0; | 520 | return 0; |
519 | } | 521 | } |
520 | 522 | ||
521 | static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) | 523 | static struct mfc_cache *ipmr_cache_find(struct net *net, |
524 | __be32 origin, | ||
525 | __be32 mcastgrp) | ||
522 | { | 526 | { |
523 | int line = MFC_HASH(mcastgrp, origin); | 527 | int line = MFC_HASH(mcastgrp, origin); |
524 | struct mfc_cache *c; | 528 | struct mfc_cache *c; |
525 | 529 | ||
526 | for (c=mfc_cache_array[line]; c; c = c->next) { | 530 | for (c = net->ipv4.mfc_cache_array[line]; c; c = c->next) { |
527 | if (c->mfc_origin==origin && c->mfc_mcastgrp==mcastgrp) | 531 | if (c->mfc_origin==origin && c->mfc_mcastgrp==mcastgrp) |
528 | break; | 532 | break; |
529 | } | 533 | } |
@@ -533,22 +537,24 @@ static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) | |||
533 | /* | 537 | /* |
534 | * Allocate a multicast cache entry | 538 | * Allocate a multicast cache entry |
535 | */ | 539 | */ |
536 | static struct mfc_cache *ipmr_cache_alloc(void) | 540 | static struct mfc_cache *ipmr_cache_alloc(struct net *net) |
537 | { | 541 | { |
538 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); | 542 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); |
539 | if (c == NULL) | 543 | if (c == NULL) |
540 | return NULL; | 544 | return NULL; |
541 | c->mfc_un.res.minvif = MAXVIFS; | 545 | c->mfc_un.res.minvif = MAXVIFS; |
546 | mfc_net_set(c, net); | ||
542 | return c; | 547 | return c; |
543 | } | 548 | } |
544 | 549 | ||
545 | static struct mfc_cache *ipmr_cache_alloc_unres(void) | 550 | static struct mfc_cache *ipmr_cache_alloc_unres(struct net *net) |
546 | { | 551 | { |
547 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); | 552 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); |
548 | if (c == NULL) | 553 | if (c == NULL) |
549 | return NULL; | 554 | return NULL; |
550 | skb_queue_head_init(&c->mfc_un.unres.unresolved); | 555 | skb_queue_head_init(&c->mfc_un.unres.unresolved); |
551 | c->mfc_un.unres.expires = jiffies + 10*HZ; | 556 | c->mfc_un.unres.expires = jiffies + 10*HZ; |
557 | mfc_net_set(c, net); | ||
552 | return c; | 558 | return c; |
553 | } | 559 | } |
554 | 560 | ||
@@ -581,7 +587,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) | |||
581 | memset(&e->msg, 0, sizeof(e->msg)); | 587 | memset(&e->msg, 0, sizeof(e->msg)); |
582 | } | 588 | } |
583 | 589 | ||
584 | rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid); | 590 | rtnl_unicast(skb, mfc_net(c), NETLINK_CB(skb).pid); |
585 | } else | 591 | } else |
586 | ip_mr_forward(skb, c, 0); | 592 | ip_mr_forward(skb, c, 0); |
587 | } | 593 | } |
@@ -594,7 +600,8 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) | |||
594 | * Called under mrt_lock. | 600 | * Called under mrt_lock. |
595 | */ | 601 | */ |
596 | 602 | ||
597 | static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | 603 | static int ipmr_cache_report(struct net *net, |
604 | struct sk_buff *pkt, vifi_t vifi, int assert) | ||
598 | { | 605 | { |
599 | struct sk_buff *skb; | 606 | struct sk_buff *skb; |
600 | const int ihl = ip_hdrlen(pkt); | 607 | const int ihl = ip_hdrlen(pkt); |
@@ -626,7 +633,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | |||
626 | memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr)); | 633 | memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr)); |
627 | msg->im_msgtype = IGMPMSG_WHOLEPKT; | 634 | msg->im_msgtype = IGMPMSG_WHOLEPKT; |
628 | msg->im_mbz = 0; | 635 | msg->im_mbz = 0; |
629 | msg->im_vif = reg_vif_num; | 636 | msg->im_vif = net->ipv4.mroute_reg_vif_num; |
630 | ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; | 637 | ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; |
631 | ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + | 638 | ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + |
632 | sizeof(struct iphdr)); | 639 | sizeof(struct iphdr)); |
@@ -658,7 +665,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | |||
658 | skb->transport_header = skb->network_header; | 665 | skb->transport_header = skb->network_header; |
659 | } | 666 | } |
660 | 667 | ||
661 | if (mroute_socket == NULL) { | 668 | if (net->ipv4.mroute_sk == NULL) { |
662 | kfree_skb(skb); | 669 | kfree_skb(skb); |
663 | return -EINVAL; | 670 | return -EINVAL; |
664 | } | 671 | } |
@@ -666,7 +673,8 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | |||
666 | /* | 673 | /* |
667 | * Deliver to mrouted | 674 | * Deliver to mrouted |
668 | */ | 675 | */ |
669 | if ((ret = sock_queue_rcv_skb(mroute_socket, skb))<0) { | 676 | ret = sock_queue_rcv_skb(net->ipv4.mroute_sk, skb); |
677 | if (ret < 0) { | ||
670 | if (net_ratelimit()) | 678 | if (net_ratelimit()) |
671 | printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n"); | 679 | printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n"); |
672 | kfree_skb(skb); | 680 | kfree_skb(skb); |
@@ -680,7 +688,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | |||
680 | */ | 688 | */ |
681 | 689 | ||
682 | static int | 690 | static int |
683 | ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | 691 | ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) |
684 | { | 692 | { |
685 | int err; | 693 | int err; |
686 | struct mfc_cache *c; | 694 | struct mfc_cache *c; |
@@ -688,7 +696,8 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | |||
688 | 696 | ||
689 | spin_lock_bh(&mfc_unres_lock); | 697 | spin_lock_bh(&mfc_unres_lock); |
690 | for (c=mfc_unres_queue; c; c=c->next) { | 698 | for (c=mfc_unres_queue; c; c=c->next) { |
691 | if (c->mfc_mcastgrp == iph->daddr && | 699 | if (net_eq(mfc_net(c), net) && |
700 | c->mfc_mcastgrp == iph->daddr && | ||
692 | c->mfc_origin == iph->saddr) | 701 | c->mfc_origin == iph->saddr) |
693 | break; | 702 | break; |
694 | } | 703 | } |
@@ -698,8 +707,8 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | |||
698 | * Create a new entry if allowable | 707 | * Create a new entry if allowable |
699 | */ | 708 | */ |
700 | 709 | ||
701 | if (atomic_read(&cache_resolve_queue_len) >= 10 || | 710 | if (atomic_read(&net->ipv4.cache_resolve_queue_len) >= 10 || |
702 | (c=ipmr_cache_alloc_unres())==NULL) { | 711 | (c = ipmr_cache_alloc_unres(net)) == NULL) { |
703 | spin_unlock_bh(&mfc_unres_lock); | 712 | spin_unlock_bh(&mfc_unres_lock); |
704 | 713 | ||
705 | kfree_skb(skb); | 714 | kfree_skb(skb); |
@@ -716,18 +725,19 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | |||
716 | /* | 725 | /* |
717 | * Reflect first query at mrouted. | 726 | * Reflect first query at mrouted. |
718 | */ | 727 | */ |
719 | if ((err = ipmr_cache_report(skb, vifi, IGMPMSG_NOCACHE))<0) { | 728 | err = ipmr_cache_report(net, skb, vifi, IGMPMSG_NOCACHE); |
729 | if (err < 0) { | ||
720 | /* If the report failed throw the cache entry | 730 | /* If the report failed throw the cache entry |
721 | out - Brad Parker | 731 | out - Brad Parker |
722 | */ | 732 | */ |
723 | spin_unlock_bh(&mfc_unres_lock); | 733 | spin_unlock_bh(&mfc_unres_lock); |
724 | 734 | ||
725 | kmem_cache_free(mrt_cachep, c); | 735 | ipmr_cache_free(c); |
726 | kfree_skb(skb); | 736 | kfree_skb(skb); |
727 | return err; | 737 | return err; |
728 | } | 738 | } |
729 | 739 | ||
730 | atomic_inc(&cache_resolve_queue_len); | 740 | atomic_inc(&net->ipv4.cache_resolve_queue_len); |
731 | c->next = mfc_unres_queue; | 741 | c->next = mfc_unres_queue; |
732 | mfc_unres_queue = c; | 742 | mfc_unres_queue = c; |
733 | 743 | ||
@@ -753,35 +763,37 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | |||
753 | * MFC cache manipulation by user space mroute daemon | 763 | * MFC cache manipulation by user space mroute daemon |
754 | */ | 764 | */ |
755 | 765 | ||
756 | static int ipmr_mfc_delete(struct mfcctl *mfc) | 766 | static int ipmr_mfc_delete(struct net *net, struct mfcctl *mfc) |
757 | { | 767 | { |
758 | int line; | 768 | int line; |
759 | struct mfc_cache *c, **cp; | 769 | struct mfc_cache *c, **cp; |
760 | 770 | ||
761 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); | 771 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); |
762 | 772 | ||
763 | for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { | 773 | for (cp = &net->ipv4.mfc_cache_array[line]; |
774 | (c = *cp) != NULL; cp = &c->next) { | ||
764 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && | 775 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && |
765 | c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { | 776 | c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { |
766 | write_lock_bh(&mrt_lock); | 777 | write_lock_bh(&mrt_lock); |
767 | *cp = c->next; | 778 | *cp = c->next; |
768 | write_unlock_bh(&mrt_lock); | 779 | write_unlock_bh(&mrt_lock); |
769 | 780 | ||
770 | kmem_cache_free(mrt_cachep, c); | 781 | ipmr_cache_free(c); |
771 | return 0; | 782 | return 0; |
772 | } | 783 | } |
773 | } | 784 | } |
774 | return -ENOENT; | 785 | return -ENOENT; |
775 | } | 786 | } |
776 | 787 | ||
777 | static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) | 788 | static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock) |
778 | { | 789 | { |
779 | int line; | 790 | int line; |
780 | struct mfc_cache *uc, *c, **cp; | 791 | struct mfc_cache *uc, *c, **cp; |
781 | 792 | ||
782 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); | 793 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); |
783 | 794 | ||
784 | for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { | 795 | for (cp = &net->ipv4.mfc_cache_array[line]; |
796 | (c = *cp) != NULL; cp = &c->next) { | ||
785 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && | 797 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && |
786 | c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) | 798 | c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) |
787 | break; | 799 | break; |
@@ -800,7 +812,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) | |||
800 | if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) | 812 | if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) |
801 | return -EINVAL; | 813 | return -EINVAL; |
802 | 814 | ||
803 | c = ipmr_cache_alloc(); | 815 | c = ipmr_cache_alloc(net); |
804 | if (c == NULL) | 816 | if (c == NULL) |
805 | return -ENOMEM; | 817 | return -ENOMEM; |
806 | 818 | ||
@@ -812,8 +824,8 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) | |||
812 | c->mfc_flags |= MFC_STATIC; | 824 | c->mfc_flags |= MFC_STATIC; |
813 | 825 | ||
814 | write_lock_bh(&mrt_lock); | 826 | write_lock_bh(&mrt_lock); |
815 | c->next = mfc_cache_array[line]; | 827 | c->next = net->ipv4.mfc_cache_array[line]; |
816 | mfc_cache_array[line] = c; | 828 | net->ipv4.mfc_cache_array[line] = c; |
817 | write_unlock_bh(&mrt_lock); | 829 | write_unlock_bh(&mrt_lock); |
818 | 830 | ||
819 | /* | 831 | /* |
@@ -823,19 +835,21 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) | |||
823 | spin_lock_bh(&mfc_unres_lock); | 835 | spin_lock_bh(&mfc_unres_lock); |
824 | for (cp = &mfc_unres_queue; (uc=*cp) != NULL; | 836 | for (cp = &mfc_unres_queue; (uc=*cp) != NULL; |
825 | cp = &uc->next) { | 837 | cp = &uc->next) { |
826 | if (uc->mfc_origin == c->mfc_origin && | 838 | if (net_eq(mfc_net(uc), net) && |
839 | uc->mfc_origin == c->mfc_origin && | ||
827 | uc->mfc_mcastgrp == c->mfc_mcastgrp) { | 840 | uc->mfc_mcastgrp == c->mfc_mcastgrp) { |
828 | *cp = uc->next; | 841 | *cp = uc->next; |
829 | if (atomic_dec_and_test(&cache_resolve_queue_len)) | 842 | atomic_dec(&net->ipv4.cache_resolve_queue_len); |
830 | del_timer(&ipmr_expire_timer); | ||
831 | break; | 843 | break; |
832 | } | 844 | } |
833 | } | 845 | } |
846 | if (mfc_unres_queue == NULL) | ||
847 | del_timer(&ipmr_expire_timer); | ||
834 | spin_unlock_bh(&mfc_unres_lock); | 848 | spin_unlock_bh(&mfc_unres_lock); |
835 | 849 | ||
836 | if (uc) { | 850 | if (uc) { |
837 | ipmr_cache_resolve(uc, c); | 851 | ipmr_cache_resolve(uc, c); |
838 | kmem_cache_free(mrt_cachep, uc); | 852 | ipmr_cache_free(uc); |
839 | } | 853 | } |
840 | return 0; | 854 | return 0; |
841 | } | 855 | } |
@@ -844,16 +858,16 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) | |||
844 | * Close the multicast socket, and clear the vif tables etc | 858 | * Close the multicast socket, and clear the vif tables etc |
845 | */ | 859 | */ |
846 | 860 | ||
847 | static void mroute_clean_tables(struct sock *sk) | 861 | static void mroute_clean_tables(struct net *net) |
848 | { | 862 | { |
849 | int i; | 863 | int i; |
850 | 864 | ||
851 | /* | 865 | /* |
852 | * Shut down all active vif entries | 866 | * Shut down all active vif entries |
853 | */ | 867 | */ |
854 | for (i=0; i<maxvif; i++) { | 868 | for (i = 0; i < net->ipv4.maxvif; i++) { |
855 | if (!(vif_table[i].flags&VIFF_STATIC)) | 869 | if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC)) |
856 | vif_delete(i, 0); | 870 | vif_delete(net, i, 0); |
857 | } | 871 | } |
858 | 872 | ||
859 | /* | 873 | /* |
@@ -862,7 +876,7 @@ static void mroute_clean_tables(struct sock *sk) | |||
862 | for (i=0; i<MFC_LINES; i++) { | 876 | for (i=0; i<MFC_LINES; i++) { |
863 | struct mfc_cache *c, **cp; | 877 | struct mfc_cache *c, **cp; |
864 | 878 | ||
865 | cp = &mfc_cache_array[i]; | 879 | cp = &net->ipv4.mfc_cache_array[i]; |
866 | while ((c = *cp) != NULL) { | 880 | while ((c = *cp) != NULL) { |
867 | if (c->mfc_flags&MFC_STATIC) { | 881 | if (c->mfc_flags&MFC_STATIC) { |
868 | cp = &c->next; | 882 | cp = &c->next; |
@@ -872,22 +886,23 @@ static void mroute_clean_tables(struct sock *sk) | |||
872 | *cp = c->next; | 886 | *cp = c->next; |
873 | write_unlock_bh(&mrt_lock); | 887 | write_unlock_bh(&mrt_lock); |
874 | 888 | ||
875 | kmem_cache_free(mrt_cachep, c); | 889 | ipmr_cache_free(c); |
876 | } | 890 | } |
877 | } | 891 | } |
878 | 892 | ||
879 | if (atomic_read(&cache_resolve_queue_len) != 0) { | 893 | if (atomic_read(&net->ipv4.cache_resolve_queue_len) != 0) { |
880 | struct mfc_cache *c; | 894 | struct mfc_cache *c, **cp; |
881 | 895 | ||
882 | spin_lock_bh(&mfc_unres_lock); | 896 | spin_lock_bh(&mfc_unres_lock); |
883 | while (mfc_unres_queue != NULL) { | 897 | cp = &mfc_unres_queue; |
884 | c = mfc_unres_queue; | 898 | while ((c = *cp) != NULL) { |
885 | mfc_unres_queue = c->next; | 899 | if (!net_eq(mfc_net(c), net)) { |
886 | spin_unlock_bh(&mfc_unres_lock); | 900 | cp = &c->next; |
901 | continue; | ||
902 | } | ||
903 | *cp = c->next; | ||
887 | 904 | ||
888 | ipmr_destroy_unres(c); | 905 | ipmr_destroy_unres(c); |
889 | |||
890 | spin_lock_bh(&mfc_unres_lock); | ||
891 | } | 906 | } |
892 | spin_unlock_bh(&mfc_unres_lock); | 907 | spin_unlock_bh(&mfc_unres_lock); |
893 | } | 908 | } |
@@ -895,15 +910,17 @@ static void mroute_clean_tables(struct sock *sk) | |||
895 | 910 | ||
896 | static void mrtsock_destruct(struct sock *sk) | 911 | static void mrtsock_destruct(struct sock *sk) |
897 | { | 912 | { |
913 | struct net *net = sock_net(sk); | ||
914 | |||
898 | rtnl_lock(); | 915 | rtnl_lock(); |
899 | if (sk == mroute_socket) { | 916 | if (sk == net->ipv4.mroute_sk) { |
900 | IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--; | 917 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)--; |
901 | 918 | ||
902 | write_lock_bh(&mrt_lock); | 919 | write_lock_bh(&mrt_lock); |
903 | mroute_socket = NULL; | 920 | net->ipv4.mroute_sk = NULL; |
904 | write_unlock_bh(&mrt_lock); | 921 | write_unlock_bh(&mrt_lock); |
905 | 922 | ||
906 | mroute_clean_tables(sk); | 923 | mroute_clean_tables(net); |
907 | } | 924 | } |
908 | rtnl_unlock(); | 925 | rtnl_unlock(); |
909 | } | 926 | } |
@@ -920,9 +937,10 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
920 | int ret; | 937 | int ret; |
921 | struct vifctl vif; | 938 | struct vifctl vif; |
922 | struct mfcctl mfc; | 939 | struct mfcctl mfc; |
940 | struct net *net = sock_net(sk); | ||
923 | 941 | ||
924 | if (optname != MRT_INIT) { | 942 | if (optname != MRT_INIT) { |
925 | if (sk != mroute_socket && !capable(CAP_NET_ADMIN)) | 943 | if (sk != net->ipv4.mroute_sk && !capable(CAP_NET_ADMIN)) |
926 | return -EACCES; | 944 | return -EACCES; |
927 | } | 945 | } |
928 | 946 | ||
@@ -935,7 +953,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
935 | return -ENOPROTOOPT; | 953 | return -ENOPROTOOPT; |
936 | 954 | ||
937 | rtnl_lock(); | 955 | rtnl_lock(); |
938 | if (mroute_socket) { | 956 | if (net->ipv4.mroute_sk) { |
939 | rtnl_unlock(); | 957 | rtnl_unlock(); |
940 | return -EADDRINUSE; | 958 | return -EADDRINUSE; |
941 | } | 959 | } |
@@ -943,15 +961,15 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
943 | ret = ip_ra_control(sk, 1, mrtsock_destruct); | 961 | ret = ip_ra_control(sk, 1, mrtsock_destruct); |
944 | if (ret == 0) { | 962 | if (ret == 0) { |
945 | write_lock_bh(&mrt_lock); | 963 | write_lock_bh(&mrt_lock); |
946 | mroute_socket = sk; | 964 | net->ipv4.mroute_sk = sk; |
947 | write_unlock_bh(&mrt_lock); | 965 | write_unlock_bh(&mrt_lock); |
948 | 966 | ||
949 | IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++; | 967 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; |
950 | } | 968 | } |
951 | rtnl_unlock(); | 969 | rtnl_unlock(); |
952 | return ret; | 970 | return ret; |
953 | case MRT_DONE: | 971 | case MRT_DONE: |
954 | if (sk != mroute_socket) | 972 | if (sk != net->ipv4.mroute_sk) |
955 | return -EACCES; | 973 | return -EACCES; |
956 | return ip_ra_control(sk, 0, NULL); | 974 | return ip_ra_control(sk, 0, NULL); |
957 | case MRT_ADD_VIF: | 975 | case MRT_ADD_VIF: |
@@ -964,9 +982,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
964 | return -ENFILE; | 982 | return -ENFILE; |
965 | rtnl_lock(); | 983 | rtnl_lock(); |
966 | if (optname == MRT_ADD_VIF) { | 984 | if (optname == MRT_ADD_VIF) { |
967 | ret = vif_add(&vif, sk==mroute_socket); | 985 | ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk); |
968 | } else { | 986 | } else { |
969 | ret = vif_delete(vif.vifc_vifi, 0); | 987 | ret = vif_delete(net, vif.vifc_vifi, 0); |
970 | } | 988 | } |
971 | rtnl_unlock(); | 989 | rtnl_unlock(); |
972 | return ret; | 990 | return ret; |
@@ -983,9 +1001,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
983 | return -EFAULT; | 1001 | return -EFAULT; |
984 | rtnl_lock(); | 1002 | rtnl_lock(); |
985 | if (optname == MRT_DEL_MFC) | 1003 | if (optname == MRT_DEL_MFC) |
986 | ret = ipmr_mfc_delete(&mfc); | 1004 | ret = ipmr_mfc_delete(net, &mfc); |
987 | else | 1005 | else |
988 | ret = ipmr_mfc_add(&mfc, sk==mroute_socket); | 1006 | ret = ipmr_mfc_add(net, &mfc, sk == net->ipv4.mroute_sk); |
989 | rtnl_unlock(); | 1007 | rtnl_unlock(); |
990 | return ret; | 1008 | return ret; |
991 | /* | 1009 | /* |
@@ -996,7 +1014,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
996 | int v; | 1014 | int v; |
997 | if (get_user(v,(int __user *)optval)) | 1015 | if (get_user(v,(int __user *)optval)) |
998 | return -EFAULT; | 1016 | return -EFAULT; |
999 | mroute_do_assert=(v)?1:0; | 1017 | net->ipv4.mroute_do_assert = (v) ? 1 : 0; |
1000 | return 0; | 1018 | return 0; |
1001 | } | 1019 | } |
1002 | #ifdef CONFIG_IP_PIMSM | 1020 | #ifdef CONFIG_IP_PIMSM |
@@ -1010,11 +1028,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
1010 | 1028 | ||
1011 | rtnl_lock(); | 1029 | rtnl_lock(); |
1012 | ret = 0; | 1030 | ret = 0; |
1013 | if (v != mroute_do_pim) { | 1031 | if (v != net->ipv4.mroute_do_pim) { |
1014 | mroute_do_pim = v; | 1032 | net->ipv4.mroute_do_pim = v; |
1015 | mroute_do_assert = v; | 1033 | net->ipv4.mroute_do_assert = v; |
1016 | #ifdef CONFIG_IP_PIMSM_V2 | 1034 | #ifdef CONFIG_IP_PIMSM_V2 |
1017 | if (mroute_do_pim) | 1035 | if (net->ipv4.mroute_do_pim) |
1018 | ret = inet_add_protocol(&pim_protocol, | 1036 | ret = inet_add_protocol(&pim_protocol, |
1019 | IPPROTO_PIM); | 1037 | IPPROTO_PIM); |
1020 | else | 1038 | else |
@@ -1045,6 +1063,7 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int | |||
1045 | { | 1063 | { |
1046 | int olr; | 1064 | int olr; |
1047 | int val; | 1065 | int val; |
1066 | struct net *net = sock_net(sk); | ||
1048 | 1067 | ||
1049 | if (optname != MRT_VERSION && | 1068 | if (optname != MRT_VERSION && |
1050 | #ifdef CONFIG_IP_PIMSM | 1069 | #ifdef CONFIG_IP_PIMSM |
@@ -1066,10 +1085,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int | |||
1066 | val = 0x0305; | 1085 | val = 0x0305; |
1067 | #ifdef CONFIG_IP_PIMSM | 1086 | #ifdef CONFIG_IP_PIMSM |
1068 | else if (optname == MRT_PIM) | 1087 | else if (optname == MRT_PIM) |
1069 | val = mroute_do_pim; | 1088 | val = net->ipv4.mroute_do_pim; |
1070 | #endif | 1089 | #endif |
1071 | else | 1090 | else |
1072 | val = mroute_do_assert; | 1091 | val = net->ipv4.mroute_do_assert; |
1073 | if (copy_to_user(optval, &val, olr)) | 1092 | if (copy_to_user(optval, &val, olr)) |
1074 | return -EFAULT; | 1093 | return -EFAULT; |
1075 | return 0; | 1094 | return 0; |
@@ -1085,16 +1104,17 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1085 | struct sioc_vif_req vr; | 1104 | struct sioc_vif_req vr; |
1086 | struct vif_device *vif; | 1105 | struct vif_device *vif; |
1087 | struct mfc_cache *c; | 1106 | struct mfc_cache *c; |
1107 | struct net *net = sock_net(sk); | ||
1088 | 1108 | ||
1089 | switch (cmd) { | 1109 | switch (cmd) { |
1090 | case SIOCGETVIFCNT: | 1110 | case SIOCGETVIFCNT: |
1091 | if (copy_from_user(&vr, arg, sizeof(vr))) | 1111 | if (copy_from_user(&vr, arg, sizeof(vr))) |
1092 | return -EFAULT; | 1112 | return -EFAULT; |
1093 | if (vr.vifi >= maxvif) | 1113 | if (vr.vifi >= net->ipv4.maxvif) |
1094 | return -EINVAL; | 1114 | return -EINVAL; |
1095 | read_lock(&mrt_lock); | 1115 | read_lock(&mrt_lock); |
1096 | vif=&vif_table[vr.vifi]; | 1116 | vif = &net->ipv4.vif_table[vr.vifi]; |
1097 | if (VIF_EXISTS(vr.vifi)) { | 1117 | if (VIF_EXISTS(net, vr.vifi)) { |
1098 | vr.icount = vif->pkt_in; | 1118 | vr.icount = vif->pkt_in; |
1099 | vr.ocount = vif->pkt_out; | 1119 | vr.ocount = vif->pkt_out; |
1100 | vr.ibytes = vif->bytes_in; | 1120 | vr.ibytes = vif->bytes_in; |
@@ -1112,7 +1132,7 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1112 | return -EFAULT; | 1132 | return -EFAULT; |
1113 | 1133 | ||
1114 | read_lock(&mrt_lock); | 1134 | read_lock(&mrt_lock); |
1115 | c = ipmr_cache_find(sr.src.s_addr, sr.grp.s_addr); | 1135 | c = ipmr_cache_find(net, sr.src.s_addr, sr.grp.s_addr); |
1116 | if (c) { | 1136 | if (c) { |
1117 | sr.pktcnt = c->mfc_un.res.pkt; | 1137 | sr.pktcnt = c->mfc_un.res.pkt; |
1118 | sr.bytecnt = c->mfc_un.res.bytes; | 1138 | sr.bytecnt = c->mfc_un.res.bytes; |
@@ -1134,18 +1154,19 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1134 | static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr) | 1154 | static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr) |
1135 | { | 1155 | { |
1136 | struct net_device *dev = ptr; | 1156 | struct net_device *dev = ptr; |
1157 | struct net *net = dev_net(dev); | ||
1137 | struct vif_device *v; | 1158 | struct vif_device *v; |
1138 | int ct; | 1159 | int ct; |
1139 | 1160 | ||
1140 | if (!net_eq(dev_net(dev), &init_net)) | 1161 | if (!net_eq(dev_net(dev), net)) |
1141 | return NOTIFY_DONE; | 1162 | return NOTIFY_DONE; |
1142 | 1163 | ||
1143 | if (event != NETDEV_UNREGISTER) | 1164 | if (event != NETDEV_UNREGISTER) |
1144 | return NOTIFY_DONE; | 1165 | return NOTIFY_DONE; |
1145 | v=&vif_table[0]; | 1166 | v = &net->ipv4.vif_table[0]; |
1146 | for (ct=0; ct<maxvif; ct++,v++) { | 1167 | for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) { |
1147 | if (v->dev == dev) | 1168 | if (v->dev == dev) |
1148 | vif_delete(ct, 1); | 1169 | vif_delete(net, ct, 1); |
1149 | } | 1170 | } |
1150 | return NOTIFY_DONE; | 1171 | return NOTIFY_DONE; |
1151 | } | 1172 | } |
@@ -1205,8 +1226,9 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) | |||
1205 | 1226 | ||
1206 | static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | 1227 | static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) |
1207 | { | 1228 | { |
1229 | struct net *net = mfc_net(c); | ||
1208 | const struct iphdr *iph = ip_hdr(skb); | 1230 | const struct iphdr *iph = ip_hdr(skb); |
1209 | struct vif_device *vif = &vif_table[vifi]; | 1231 | struct vif_device *vif = &net->ipv4.vif_table[vifi]; |
1210 | struct net_device *dev; | 1232 | struct net_device *dev; |
1211 | struct rtable *rt; | 1233 | struct rtable *rt; |
1212 | int encap = 0; | 1234 | int encap = 0; |
@@ -1220,9 +1242,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1220 | vif->bytes_out += skb->len; | 1242 | vif->bytes_out += skb->len; |
1221 | vif->dev->stats.tx_bytes += skb->len; | 1243 | vif->dev->stats.tx_bytes += skb->len; |
1222 | vif->dev->stats.tx_packets++; | 1244 | vif->dev->stats.tx_packets++; |
1223 | ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT); | 1245 | ipmr_cache_report(net, skb, vifi, IGMPMSG_WHOLEPKT); |
1224 | kfree_skb(skb); | 1246 | goto out_free; |
1225 | return; | ||
1226 | } | 1247 | } |
1227 | #endif | 1248 | #endif |
1228 | 1249 | ||
@@ -1233,7 +1254,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1233 | .saddr = vif->local, | 1254 | .saddr = vif->local, |
1234 | .tos = RT_TOS(iph->tos) } }, | 1255 | .tos = RT_TOS(iph->tos) } }, |
1235 | .proto = IPPROTO_IPIP }; | 1256 | .proto = IPPROTO_IPIP }; |
1236 | if (ip_route_output_key(&init_net, &rt, &fl)) | 1257 | if (ip_route_output_key(net, &rt, &fl)) |
1237 | goto out_free; | 1258 | goto out_free; |
1238 | encap = sizeof(struct iphdr); | 1259 | encap = sizeof(struct iphdr); |
1239 | } else { | 1260 | } else { |
@@ -1242,7 +1263,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1242 | { .daddr = iph->daddr, | 1263 | { .daddr = iph->daddr, |
1243 | .tos = RT_TOS(iph->tos) } }, | 1264 | .tos = RT_TOS(iph->tos) } }, |
1244 | .proto = IPPROTO_IPIP }; | 1265 | .proto = IPPROTO_IPIP }; |
1245 | if (ip_route_output_key(&init_net, &rt, &fl)) | 1266 | if (ip_route_output_key(net, &rt, &fl)) |
1246 | goto out_free; | 1267 | goto out_free; |
1247 | } | 1268 | } |
1248 | 1269 | ||
@@ -1306,9 +1327,10 @@ out_free: | |||
1306 | 1327 | ||
1307 | static int ipmr_find_vif(struct net_device *dev) | 1328 | static int ipmr_find_vif(struct net_device *dev) |
1308 | { | 1329 | { |
1330 | struct net *net = dev_net(dev); | ||
1309 | int ct; | 1331 | int ct; |
1310 | for (ct=maxvif-1; ct>=0; ct--) { | 1332 | for (ct = net->ipv4.maxvif-1; ct >= 0; ct--) { |
1311 | if (vif_table[ct].dev == dev) | 1333 | if (net->ipv4.vif_table[ct].dev == dev) |
1312 | break; | 1334 | break; |
1313 | } | 1335 | } |
1314 | return ct; | 1336 | return ct; |
@@ -1320,6 +1342,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1320 | { | 1342 | { |
1321 | int psend = -1; | 1343 | int psend = -1; |
1322 | int vif, ct; | 1344 | int vif, ct; |
1345 | struct net *net = mfc_net(cache); | ||
1323 | 1346 | ||
1324 | vif = cache->mfc_parent; | 1347 | vif = cache->mfc_parent; |
1325 | cache->mfc_un.res.pkt++; | 1348 | cache->mfc_un.res.pkt++; |
@@ -1328,7 +1351,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1328 | /* | 1351 | /* |
1329 | * Wrong interface: drop packet and (maybe) send PIM assert. | 1352 | * Wrong interface: drop packet and (maybe) send PIM assert. |
1330 | */ | 1353 | */ |
1331 | if (vif_table[vif].dev != skb->dev) { | 1354 | if (net->ipv4.vif_table[vif].dev != skb->dev) { |
1332 | int true_vifi; | 1355 | int true_vifi; |
1333 | 1356 | ||
1334 | if (skb->rtable->fl.iif == 0) { | 1357 | if (skb->rtable->fl.iif == 0) { |
@@ -1349,23 +1372,24 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1349 | cache->mfc_un.res.wrong_if++; | 1372 | cache->mfc_un.res.wrong_if++; |
1350 | true_vifi = ipmr_find_vif(skb->dev); | 1373 | true_vifi = ipmr_find_vif(skb->dev); |
1351 | 1374 | ||
1352 | if (true_vifi >= 0 && mroute_do_assert && | 1375 | if (true_vifi >= 0 && net->ipv4.mroute_do_assert && |
1353 | /* pimsm uses asserts, when switching from RPT to SPT, | 1376 | /* pimsm uses asserts, when switching from RPT to SPT, |
1354 | so that we cannot check that packet arrived on an oif. | 1377 | so that we cannot check that packet arrived on an oif. |
1355 | It is bad, but otherwise we would need to move pretty | 1378 | It is bad, but otherwise we would need to move pretty |
1356 | large chunk of pimd to kernel. Ough... --ANK | 1379 | large chunk of pimd to kernel. Ough... --ANK |
1357 | */ | 1380 | */ |
1358 | (mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) && | 1381 | (net->ipv4.mroute_do_pim || |
1382 | cache->mfc_un.res.ttls[true_vifi] < 255) && | ||
1359 | time_after(jiffies, | 1383 | time_after(jiffies, |
1360 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { | 1384 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { |
1361 | cache->mfc_un.res.last_assert = jiffies; | 1385 | cache->mfc_un.res.last_assert = jiffies; |
1362 | ipmr_cache_report(skb, true_vifi, IGMPMSG_WRONGVIF); | 1386 | ipmr_cache_report(net, skb, true_vifi, IGMPMSG_WRONGVIF); |
1363 | } | 1387 | } |
1364 | goto dont_forward; | 1388 | goto dont_forward; |
1365 | } | 1389 | } |
1366 | 1390 | ||
1367 | vif_table[vif].pkt_in++; | 1391 | net->ipv4.vif_table[vif].pkt_in++; |
1368 | vif_table[vif].bytes_in += skb->len; | 1392 | net->ipv4.vif_table[vif].bytes_in += skb->len; |
1369 | 1393 | ||
1370 | /* | 1394 | /* |
1371 | * Forward the frame | 1395 | * Forward the frame |
@@ -1405,6 +1429,7 @@ dont_forward: | |||
1405 | int ip_mr_input(struct sk_buff *skb) | 1429 | int ip_mr_input(struct sk_buff *skb) |
1406 | { | 1430 | { |
1407 | struct mfc_cache *cache; | 1431 | struct mfc_cache *cache; |
1432 | struct net *net = dev_net(skb->dev); | ||
1408 | int local = skb->rtable->rt_flags&RTCF_LOCAL; | 1433 | int local = skb->rtable->rt_flags&RTCF_LOCAL; |
1409 | 1434 | ||
1410 | /* Packet is looped back after forward, it should not be | 1435 | /* Packet is looped back after forward, it should not be |
@@ -1425,9 +1450,9 @@ int ip_mr_input(struct sk_buff *skb) | |||
1425 | that we can forward NO IGMP messages. | 1450 | that we can forward NO IGMP messages. |
1426 | */ | 1451 | */ |
1427 | read_lock(&mrt_lock); | 1452 | read_lock(&mrt_lock); |
1428 | if (mroute_socket) { | 1453 | if (net->ipv4.mroute_sk) { |
1429 | nf_reset(skb); | 1454 | nf_reset(skb); |
1430 | raw_rcv(mroute_socket, skb); | 1455 | raw_rcv(net->ipv4.mroute_sk, skb); |
1431 | read_unlock(&mrt_lock); | 1456 | read_unlock(&mrt_lock); |
1432 | return 0; | 1457 | return 0; |
1433 | } | 1458 | } |
@@ -1436,7 +1461,7 @@ int ip_mr_input(struct sk_buff *skb) | |||
1436 | } | 1461 | } |
1437 | 1462 | ||
1438 | read_lock(&mrt_lock); | 1463 | read_lock(&mrt_lock); |
1439 | cache = ipmr_cache_find(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); | 1464 | cache = ipmr_cache_find(net, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); |
1440 | 1465 | ||
1441 | /* | 1466 | /* |
1442 | * No usable cache entry | 1467 | * No usable cache entry |
@@ -1456,7 +1481,7 @@ int ip_mr_input(struct sk_buff *skb) | |||
1456 | 1481 | ||
1457 | vif = ipmr_find_vif(skb->dev); | 1482 | vif = ipmr_find_vif(skb->dev); |
1458 | if (vif >= 0) { | 1483 | if (vif >= 0) { |
1459 | int err = ipmr_cache_unresolved(vif, skb); | 1484 | int err = ipmr_cache_unresolved(net, vif, skb); |
1460 | read_unlock(&mrt_lock); | 1485 | read_unlock(&mrt_lock); |
1461 | 1486 | ||
1462 | return err; | 1487 | return err; |
@@ -1487,6 +1512,7 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) | |||
1487 | { | 1512 | { |
1488 | struct net_device *reg_dev = NULL; | 1513 | struct net_device *reg_dev = NULL; |
1489 | struct iphdr *encap; | 1514 | struct iphdr *encap; |
1515 | struct net *net = dev_net(skb->dev); | ||
1490 | 1516 | ||
1491 | encap = (struct iphdr *)(skb_transport_header(skb) + pimlen); | 1517 | encap = (struct iphdr *)(skb_transport_header(skb) + pimlen); |
1492 | /* | 1518 | /* |
@@ -1501,8 +1527,8 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) | |||
1501 | return 1; | 1527 | return 1; |
1502 | 1528 | ||
1503 | read_lock(&mrt_lock); | 1529 | read_lock(&mrt_lock); |
1504 | if (reg_vif_num >= 0) | 1530 | if (net->ipv4.mroute_reg_vif_num >= 0) |
1505 | reg_dev = vif_table[reg_vif_num].dev; | 1531 | reg_dev = net->ipv4.vif_table[net->ipv4.mroute_reg_vif_num].dev; |
1506 | if (reg_dev) | 1532 | if (reg_dev) |
1507 | dev_hold(reg_dev); | 1533 | dev_hold(reg_dev); |
1508 | read_unlock(&mrt_lock); | 1534 | read_unlock(&mrt_lock); |
@@ -1537,13 +1563,14 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) | |||
1537 | int pim_rcv_v1(struct sk_buff * skb) | 1563 | int pim_rcv_v1(struct sk_buff * skb) |
1538 | { | 1564 | { |
1539 | struct igmphdr *pim; | 1565 | struct igmphdr *pim; |
1566 | struct net *net = dev_net(skb->dev); | ||
1540 | 1567 | ||
1541 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) | 1568 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) |
1542 | goto drop; | 1569 | goto drop; |
1543 | 1570 | ||
1544 | pim = igmp_hdr(skb); | 1571 | pim = igmp_hdr(skb); |
1545 | 1572 | ||
1546 | if (!mroute_do_pim || | 1573 | if (!net->ipv4.mroute_do_pim || |
1547 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) | 1574 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) |
1548 | goto drop; | 1575 | goto drop; |
1549 | 1576 | ||
@@ -1583,7 +1610,8 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) | |||
1583 | { | 1610 | { |
1584 | int ct; | 1611 | int ct; |
1585 | struct rtnexthop *nhp; | 1612 | struct rtnexthop *nhp; |
1586 | struct net_device *dev = vif_table[c->mfc_parent].dev; | 1613 | struct net *net = mfc_net(c); |
1614 | struct net_device *dev = net->ipv4.vif_table[c->mfc_parent].dev; | ||
1587 | u8 *b = skb_tail_pointer(skb); | 1615 | u8 *b = skb_tail_pointer(skb); |
1588 | struct rtattr *mp_head; | 1616 | struct rtattr *mp_head; |
1589 | 1617 | ||
@@ -1599,7 +1627,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) | |||
1599 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); | 1627 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); |
1600 | nhp->rtnh_flags = 0; | 1628 | nhp->rtnh_flags = 0; |
1601 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; | 1629 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; |
1602 | nhp->rtnh_ifindex = vif_table[ct].dev->ifindex; | 1630 | nhp->rtnh_ifindex = net->ipv4.vif_table[ct].dev->ifindex; |
1603 | nhp->rtnh_len = sizeof(*nhp); | 1631 | nhp->rtnh_len = sizeof(*nhp); |
1604 | } | 1632 | } |
1605 | } | 1633 | } |
@@ -1613,14 +1641,15 @@ rtattr_failure: | |||
1613 | return -EMSGSIZE; | 1641 | return -EMSGSIZE; |
1614 | } | 1642 | } |
1615 | 1643 | ||
1616 | int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) | 1644 | int ipmr_get_route(struct net *net, |
1645 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) | ||
1617 | { | 1646 | { |
1618 | int err; | 1647 | int err; |
1619 | struct mfc_cache *cache; | 1648 | struct mfc_cache *cache; |
1620 | struct rtable *rt = skb->rtable; | 1649 | struct rtable *rt = skb->rtable; |
1621 | 1650 | ||
1622 | read_lock(&mrt_lock); | 1651 | read_lock(&mrt_lock); |
1623 | cache = ipmr_cache_find(rt->rt_src, rt->rt_dst); | 1652 | cache = ipmr_cache_find(net, rt->rt_src, rt->rt_dst); |
1624 | 1653 | ||
1625 | if (cache == NULL) { | 1654 | if (cache == NULL) { |
1626 | struct sk_buff *skb2; | 1655 | struct sk_buff *skb2; |
@@ -1651,7 +1680,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) | |||
1651 | iph->saddr = rt->rt_src; | 1680 | iph->saddr = rt->rt_src; |
1652 | iph->daddr = rt->rt_dst; | 1681 | iph->daddr = rt->rt_dst; |
1653 | iph->version = 0; | 1682 | iph->version = 0; |
1654 | err = ipmr_cache_unresolved(vif, skb2); | 1683 | err = ipmr_cache_unresolved(net, vif, skb2); |
1655 | read_unlock(&mrt_lock); | 1684 | read_unlock(&mrt_lock); |
1656 | return err; | 1685 | return err; |
1657 | } | 1686 | } |
@@ -1668,17 +1697,19 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) | |||
1668 | * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif | 1697 | * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif |
1669 | */ | 1698 | */ |
1670 | struct ipmr_vif_iter { | 1699 | struct ipmr_vif_iter { |
1700 | struct seq_net_private p; | ||
1671 | int ct; | 1701 | int ct; |
1672 | }; | 1702 | }; |
1673 | 1703 | ||
1674 | static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter, | 1704 | static struct vif_device *ipmr_vif_seq_idx(struct net *net, |
1705 | struct ipmr_vif_iter *iter, | ||
1675 | loff_t pos) | 1706 | loff_t pos) |
1676 | { | 1707 | { |
1677 | for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) { | 1708 | for (iter->ct = 0; iter->ct < net->ipv4.maxvif; ++iter->ct) { |
1678 | if (!VIF_EXISTS(iter->ct)) | 1709 | if (!VIF_EXISTS(net, iter->ct)) |
1679 | continue; | 1710 | continue; |
1680 | if (pos-- == 0) | 1711 | if (pos-- == 0) |
1681 | return &vif_table[iter->ct]; | 1712 | return &net->ipv4.vif_table[iter->ct]; |
1682 | } | 1713 | } |
1683 | return NULL; | 1714 | return NULL; |
1684 | } | 1715 | } |
@@ -1686,23 +1717,26 @@ static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter, | |||
1686 | static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos) | 1717 | static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos) |
1687 | __acquires(mrt_lock) | 1718 | __acquires(mrt_lock) |
1688 | { | 1719 | { |
1720 | struct net *net = seq_file_net(seq); | ||
1721 | |||
1689 | read_lock(&mrt_lock); | 1722 | read_lock(&mrt_lock); |
1690 | return *pos ? ipmr_vif_seq_idx(seq->private, *pos - 1) | 1723 | return *pos ? ipmr_vif_seq_idx(net, seq->private, *pos - 1) |
1691 | : SEQ_START_TOKEN; | 1724 | : SEQ_START_TOKEN; |
1692 | } | 1725 | } |
1693 | 1726 | ||
1694 | static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 1727 | static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
1695 | { | 1728 | { |
1696 | struct ipmr_vif_iter *iter = seq->private; | 1729 | struct ipmr_vif_iter *iter = seq->private; |
1730 | struct net *net = seq_file_net(seq); | ||
1697 | 1731 | ||
1698 | ++*pos; | 1732 | ++*pos; |
1699 | if (v == SEQ_START_TOKEN) | 1733 | if (v == SEQ_START_TOKEN) |
1700 | return ipmr_vif_seq_idx(iter, 0); | 1734 | return ipmr_vif_seq_idx(net, iter, 0); |
1701 | 1735 | ||
1702 | while (++iter->ct < maxvif) { | 1736 | while (++iter->ct < net->ipv4.maxvif) { |
1703 | if (!VIF_EXISTS(iter->ct)) | 1737 | if (!VIF_EXISTS(net, iter->ct)) |
1704 | continue; | 1738 | continue; |
1705 | return &vif_table[iter->ct]; | 1739 | return &net->ipv4.vif_table[iter->ct]; |
1706 | } | 1740 | } |
1707 | return NULL; | 1741 | return NULL; |
1708 | } | 1742 | } |
@@ -1715,6 +1749,8 @@ static void ipmr_vif_seq_stop(struct seq_file *seq, void *v) | |||
1715 | 1749 | ||
1716 | static int ipmr_vif_seq_show(struct seq_file *seq, void *v) | 1750 | static int ipmr_vif_seq_show(struct seq_file *seq, void *v) |
1717 | { | 1751 | { |
1752 | struct net *net = seq_file_net(seq); | ||
1753 | |||
1718 | if (v == SEQ_START_TOKEN) { | 1754 | if (v == SEQ_START_TOKEN) { |
1719 | seq_puts(seq, | 1755 | seq_puts(seq, |
1720 | "Interface BytesIn PktsIn BytesOut PktsOut Flags Local Remote\n"); | 1756 | "Interface BytesIn PktsIn BytesOut PktsOut Flags Local Remote\n"); |
@@ -1724,7 +1760,7 @@ static int ipmr_vif_seq_show(struct seq_file *seq, void *v) | |||
1724 | 1760 | ||
1725 | seq_printf(seq, | 1761 | seq_printf(seq, |
1726 | "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n", | 1762 | "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n", |
1727 | vif - vif_table, | 1763 | vif - net->ipv4.vif_table, |
1728 | name, vif->bytes_in, vif->pkt_in, | 1764 | name, vif->bytes_in, vif->pkt_in, |
1729 | vif->bytes_out, vif->pkt_out, | 1765 | vif->bytes_out, vif->pkt_out, |
1730 | vif->flags, vif->local, vif->remote); | 1766 | vif->flags, vif->local, vif->remote); |
@@ -1741,8 +1777,8 @@ static const struct seq_operations ipmr_vif_seq_ops = { | |||
1741 | 1777 | ||
1742 | static int ipmr_vif_open(struct inode *inode, struct file *file) | 1778 | static int ipmr_vif_open(struct inode *inode, struct file *file) |
1743 | { | 1779 | { |
1744 | return seq_open_private(file, &ipmr_vif_seq_ops, | 1780 | return seq_open_net(inode, file, &ipmr_vif_seq_ops, |
1745 | sizeof(struct ipmr_vif_iter)); | 1781 | sizeof(struct ipmr_vif_iter)); |
1746 | } | 1782 | } |
1747 | 1783 | ||
1748 | static const struct file_operations ipmr_vif_fops = { | 1784 | static const struct file_operations ipmr_vif_fops = { |
@@ -1750,23 +1786,26 @@ static const struct file_operations ipmr_vif_fops = { | |||
1750 | .open = ipmr_vif_open, | 1786 | .open = ipmr_vif_open, |
1751 | .read = seq_read, | 1787 | .read = seq_read, |
1752 | .llseek = seq_lseek, | 1788 | .llseek = seq_lseek, |
1753 | .release = seq_release_private, | 1789 | .release = seq_release_net, |
1754 | }; | 1790 | }; |
1755 | 1791 | ||
1756 | struct ipmr_mfc_iter { | 1792 | struct ipmr_mfc_iter { |
1793 | struct seq_net_private p; | ||
1757 | struct mfc_cache **cache; | 1794 | struct mfc_cache **cache; |
1758 | int ct; | 1795 | int ct; |
1759 | }; | 1796 | }; |
1760 | 1797 | ||
1761 | 1798 | ||
1762 | static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) | 1799 | static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net, |
1800 | struct ipmr_mfc_iter *it, loff_t pos) | ||
1763 | { | 1801 | { |
1764 | struct mfc_cache *mfc; | 1802 | struct mfc_cache *mfc; |
1765 | 1803 | ||
1766 | it->cache = mfc_cache_array; | 1804 | it->cache = net->ipv4.mfc_cache_array; |
1767 | read_lock(&mrt_lock); | 1805 | read_lock(&mrt_lock); |
1768 | for (it->ct = 0; it->ct < MFC_LINES; it->ct++) | 1806 | for (it->ct = 0; it->ct < MFC_LINES; it->ct++) |
1769 | for (mfc = mfc_cache_array[it->ct]; mfc; mfc = mfc->next) | 1807 | for (mfc = net->ipv4.mfc_cache_array[it->ct]; |
1808 | mfc; mfc = mfc->next) | ||
1770 | if (pos-- == 0) | 1809 | if (pos-- == 0) |
1771 | return mfc; | 1810 | return mfc; |
1772 | read_unlock(&mrt_lock); | 1811 | read_unlock(&mrt_lock); |
@@ -1774,7 +1813,8 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) | |||
1774 | it->cache = &mfc_unres_queue; | 1813 | it->cache = &mfc_unres_queue; |
1775 | spin_lock_bh(&mfc_unres_lock); | 1814 | spin_lock_bh(&mfc_unres_lock); |
1776 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) | 1815 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) |
1777 | if (pos-- == 0) | 1816 | if (net_eq(mfc_net(mfc), net) && |
1817 | pos-- == 0) | ||
1778 | return mfc; | 1818 | return mfc; |
1779 | spin_unlock_bh(&mfc_unres_lock); | 1819 | spin_unlock_bh(&mfc_unres_lock); |
1780 | 1820 | ||
@@ -1786,9 +1826,11 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) | |||
1786 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) | 1826 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) |
1787 | { | 1827 | { |
1788 | struct ipmr_mfc_iter *it = seq->private; | 1828 | struct ipmr_mfc_iter *it = seq->private; |
1829 | struct net *net = seq_file_net(seq); | ||
1830 | |||
1789 | it->cache = NULL; | 1831 | it->cache = NULL; |
1790 | it->ct = 0; | 1832 | it->ct = 0; |
1791 | return *pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1) | 1833 | return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) |
1792 | : SEQ_START_TOKEN; | 1834 | : SEQ_START_TOKEN; |
1793 | } | 1835 | } |
1794 | 1836 | ||
@@ -1796,11 +1838,12 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1796 | { | 1838 | { |
1797 | struct mfc_cache *mfc = v; | 1839 | struct mfc_cache *mfc = v; |
1798 | struct ipmr_mfc_iter *it = seq->private; | 1840 | struct ipmr_mfc_iter *it = seq->private; |
1841 | struct net *net = seq_file_net(seq); | ||
1799 | 1842 | ||
1800 | ++*pos; | 1843 | ++*pos; |
1801 | 1844 | ||
1802 | if (v == SEQ_START_TOKEN) | 1845 | if (v == SEQ_START_TOKEN) |
1803 | return ipmr_mfc_seq_idx(seq->private, 0); | 1846 | return ipmr_mfc_seq_idx(net, seq->private, 0); |
1804 | 1847 | ||
1805 | if (mfc->next) | 1848 | if (mfc->next) |
1806 | return mfc->next; | 1849 | return mfc->next; |
@@ -1808,10 +1851,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1808 | if (it->cache == &mfc_unres_queue) | 1851 | if (it->cache == &mfc_unres_queue) |
1809 | goto end_of_list; | 1852 | goto end_of_list; |
1810 | 1853 | ||
1811 | BUG_ON(it->cache != mfc_cache_array); | 1854 | BUG_ON(it->cache != net->ipv4.mfc_cache_array); |
1812 | 1855 | ||
1813 | while (++it->ct < MFC_LINES) { | 1856 | while (++it->ct < MFC_LINES) { |
1814 | mfc = mfc_cache_array[it->ct]; | 1857 | mfc = net->ipv4.mfc_cache_array[it->ct]; |
1815 | if (mfc) | 1858 | if (mfc) |
1816 | return mfc; | 1859 | return mfc; |
1817 | } | 1860 | } |
@@ -1823,6 +1866,8 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1823 | 1866 | ||
1824 | spin_lock_bh(&mfc_unres_lock); | 1867 | spin_lock_bh(&mfc_unres_lock); |
1825 | mfc = mfc_unres_queue; | 1868 | mfc = mfc_unres_queue; |
1869 | while (mfc && !net_eq(mfc_net(mfc), net)) | ||
1870 | mfc = mfc->next; | ||
1826 | if (mfc) | 1871 | if (mfc) |
1827 | return mfc; | 1872 | return mfc; |
1828 | 1873 | ||
@@ -1836,16 +1881,18 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1836 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) | 1881 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) |
1837 | { | 1882 | { |
1838 | struct ipmr_mfc_iter *it = seq->private; | 1883 | struct ipmr_mfc_iter *it = seq->private; |
1884 | struct net *net = seq_file_net(seq); | ||
1839 | 1885 | ||
1840 | if (it->cache == &mfc_unres_queue) | 1886 | if (it->cache == &mfc_unres_queue) |
1841 | spin_unlock_bh(&mfc_unres_lock); | 1887 | spin_unlock_bh(&mfc_unres_lock); |
1842 | else if (it->cache == mfc_cache_array) | 1888 | else if (it->cache == net->ipv4.mfc_cache_array) |
1843 | read_unlock(&mrt_lock); | 1889 | read_unlock(&mrt_lock); |
1844 | } | 1890 | } |
1845 | 1891 | ||
1846 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | 1892 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) |
1847 | { | 1893 | { |
1848 | int n; | 1894 | int n; |
1895 | struct net *net = seq_file_net(seq); | ||
1849 | 1896 | ||
1850 | if (v == SEQ_START_TOKEN) { | 1897 | if (v == SEQ_START_TOKEN) { |
1851 | seq_puts(seq, | 1898 | seq_puts(seq, |
@@ -1866,9 +1913,9 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
1866 | mfc->mfc_un.res.wrong_if); | 1913 | mfc->mfc_un.res.wrong_if); |
1867 | for (n = mfc->mfc_un.res.minvif; | 1914 | for (n = mfc->mfc_un.res.minvif; |
1868 | n < mfc->mfc_un.res.maxvif; n++ ) { | 1915 | n < mfc->mfc_un.res.maxvif; n++ ) { |
1869 | if (VIF_EXISTS(n) | 1916 | if (VIF_EXISTS(net, n) && |
1870 | && mfc->mfc_un.res.ttls[n] < 255) | 1917 | mfc->mfc_un.res.ttls[n] < 255) |
1871 | seq_printf(seq, | 1918 | seq_printf(seq, |
1872 | " %2d:%-3d", | 1919 | " %2d:%-3d", |
1873 | n, mfc->mfc_un.res.ttls[n]); | 1920 | n, mfc->mfc_un.res.ttls[n]); |
1874 | } | 1921 | } |
@@ -1892,8 +1939,8 @@ static const struct seq_operations ipmr_mfc_seq_ops = { | |||
1892 | 1939 | ||
1893 | static int ipmr_mfc_open(struct inode *inode, struct file *file) | 1940 | static int ipmr_mfc_open(struct inode *inode, struct file *file) |
1894 | { | 1941 | { |
1895 | return seq_open_private(file, &ipmr_mfc_seq_ops, | 1942 | return seq_open_net(inode, file, &ipmr_mfc_seq_ops, |
1896 | sizeof(struct ipmr_mfc_iter)); | 1943 | sizeof(struct ipmr_mfc_iter)); |
1897 | } | 1944 | } |
1898 | 1945 | ||
1899 | static const struct file_operations ipmr_mfc_fops = { | 1946 | static const struct file_operations ipmr_mfc_fops = { |
@@ -1901,7 +1948,7 @@ static const struct file_operations ipmr_mfc_fops = { | |||
1901 | .open = ipmr_mfc_open, | 1948 | .open = ipmr_mfc_open, |
1902 | .read = seq_read, | 1949 | .read = seq_read, |
1903 | .llseek = seq_lseek, | 1950 | .llseek = seq_lseek, |
1904 | .release = seq_release_private, | 1951 | .release = seq_release_net, |
1905 | }; | 1952 | }; |
1906 | #endif | 1953 | #endif |
1907 | 1954 | ||
@@ -1915,6 +1962,65 @@ static struct net_protocol pim_protocol = { | |||
1915 | /* | 1962 | /* |
1916 | * Setup for IP multicast routing | 1963 | * Setup for IP multicast routing |
1917 | */ | 1964 | */ |
1965 | static int __net_init ipmr_net_init(struct net *net) | ||
1966 | { | ||
1967 | int err = 0; | ||
1968 | |||
1969 | net->ipv4.vif_table = kcalloc(MAXVIFS, sizeof(struct vif_device), | ||
1970 | GFP_KERNEL); | ||
1971 | if (!net->ipv4.vif_table) { | ||
1972 | err = -ENOMEM; | ||
1973 | goto fail; | ||
1974 | } | ||
1975 | |||
1976 | /* Forwarding cache */ | ||
1977 | net->ipv4.mfc_cache_array = kcalloc(MFC_LINES, | ||
1978 | sizeof(struct mfc_cache *), | ||
1979 | GFP_KERNEL); | ||
1980 | if (!net->ipv4.mfc_cache_array) { | ||
1981 | err = -ENOMEM; | ||
1982 | goto fail_mfc_cache; | ||
1983 | } | ||
1984 | |||
1985 | #ifdef CONFIG_IP_PIMSM | ||
1986 | net->ipv4.mroute_reg_vif_num = -1; | ||
1987 | #endif | ||
1988 | |||
1989 | #ifdef CONFIG_PROC_FS | ||
1990 | err = -ENOMEM; | ||
1991 | if (!proc_net_fops_create(net, "ip_mr_vif", 0, &ipmr_vif_fops)) | ||
1992 | goto proc_vif_fail; | ||
1993 | if (!proc_net_fops_create(net, "ip_mr_cache", 0, &ipmr_mfc_fops)) | ||
1994 | goto proc_cache_fail; | ||
1995 | #endif | ||
1996 | return 0; | ||
1997 | |||
1998 | #ifdef CONFIG_PROC_FS | ||
1999 | proc_cache_fail: | ||
2000 | proc_net_remove(net, "ip_mr_vif"); | ||
2001 | proc_vif_fail: | ||
2002 | kfree(net->ipv4.mfc_cache_array); | ||
2003 | #endif | ||
2004 | fail_mfc_cache: | ||
2005 | kfree(net->ipv4.vif_table); | ||
2006 | fail: | ||
2007 | return err; | ||
2008 | } | ||
2009 | |||
2010 | static void __net_exit ipmr_net_exit(struct net *net) | ||
2011 | { | ||
2012 | #ifdef CONFIG_PROC_FS | ||
2013 | proc_net_remove(net, "ip_mr_cache"); | ||
2014 | proc_net_remove(net, "ip_mr_vif"); | ||
2015 | #endif | ||
2016 | kfree(net->ipv4.mfc_cache_array); | ||
2017 | kfree(net->ipv4.vif_table); | ||
2018 | } | ||
2019 | |||
2020 | static struct pernet_operations ipmr_net_ops = { | ||
2021 | .init = ipmr_net_init, | ||
2022 | .exit = ipmr_net_exit, | ||
2023 | }; | ||
1918 | 2024 | ||
1919 | int __init ip_mr_init(void) | 2025 | int __init ip_mr_init(void) |
1920 | { | 2026 | { |
@@ -1927,26 +2033,20 @@ int __init ip_mr_init(void) | |||
1927 | if (!mrt_cachep) | 2033 | if (!mrt_cachep) |
1928 | return -ENOMEM; | 2034 | return -ENOMEM; |
1929 | 2035 | ||
2036 | err = register_pernet_subsys(&ipmr_net_ops); | ||
2037 | if (err) | ||
2038 | goto reg_pernet_fail; | ||
2039 | |||
1930 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); | 2040 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); |
1931 | err = register_netdevice_notifier(&ip_mr_notifier); | 2041 | err = register_netdevice_notifier(&ip_mr_notifier); |
1932 | if (err) | 2042 | if (err) |
1933 | goto reg_notif_fail; | 2043 | goto reg_notif_fail; |
1934 | #ifdef CONFIG_PROC_FS | ||
1935 | err = -ENOMEM; | ||
1936 | if (!proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops)) | ||
1937 | goto proc_vif_fail; | ||
1938 | if (!proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops)) | ||
1939 | goto proc_cache_fail; | ||
1940 | #endif | ||
1941 | return 0; | 2044 | return 0; |
1942 | #ifdef CONFIG_PROC_FS | 2045 | |
1943 | proc_cache_fail: | ||
1944 | proc_net_remove(&init_net, "ip_mr_vif"); | ||
1945 | proc_vif_fail: | ||
1946 | unregister_netdevice_notifier(&ip_mr_notifier); | ||
1947 | #endif | ||
1948 | reg_notif_fail: | 2046 | reg_notif_fail: |
1949 | del_timer(&ipmr_expire_timer); | 2047 | del_timer(&ipmr_expire_timer); |
2048 | unregister_pernet_subsys(&ipmr_net_ops); | ||
2049 | reg_pernet_fail: | ||
1950 | kmem_cache_destroy(mrt_cachep); | 2050 | kmem_cache_destroy(mrt_cachep); |
1951 | return err; | 2051 | return err; |
1952 | } | 2052 | } |
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 182f845de92f..d9521f6f9ed0 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c | |||
@@ -1292,7 +1292,7 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = { | |||
1292 | .expect_policy = &snmp_exp_policy, | 1292 | .expect_policy = &snmp_exp_policy, |
1293 | .name = "snmp", | 1293 | .name = "snmp", |
1294 | .tuple.src.l3num = AF_INET, | 1294 | .tuple.src.l3num = AF_INET, |
1295 | .tuple.src.u.udp.port = __constant_htons(SNMP_PORT), | 1295 | .tuple.src.u.udp.port = cpu_to_be16(SNMP_PORT), |
1296 | .tuple.dst.protonum = IPPROTO_UDP, | 1296 | .tuple.dst.protonum = IPPROTO_UDP, |
1297 | }; | 1297 | }; |
1298 | 1298 | ||
@@ -1302,7 +1302,7 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { | |||
1302 | .expect_policy = &snmp_exp_policy, | 1302 | .expect_policy = &snmp_exp_policy, |
1303 | .name = "snmp_trap", | 1303 | .name = "snmp_trap", |
1304 | .tuple.src.l3num = AF_INET, | 1304 | .tuple.src.l3num = AF_INET, |
1305 | .tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT), | 1305 | .tuple.src.u.udp.port = cpu_to_be16(SNMP_TRAP_PORT), |
1306 | .tuple.dst.protonum = IPPROTO_UDP, | 1306 | .tuple.dst.protonum = IPPROTO_UDP, |
1307 | }; | 1307 | }; |
1308 | 1308 | ||
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index eb62e58bff79..cf0cdeeb1db0 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -54,8 +54,8 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) | |||
54 | int orphans, sockets; | 54 | int orphans, sockets; |
55 | 55 | ||
56 | local_bh_disable(); | 56 | local_bh_disable(); |
57 | orphans = percpu_counter_sum_positive(&tcp_orphan_count), | 57 | orphans = percpu_counter_sum_positive(&tcp_orphan_count); |
58 | sockets = percpu_counter_sum_positive(&tcp_sockets_allocated), | 58 | sockets = percpu_counter_sum_positive(&tcp_sockets_allocated); |
59 | local_bh_enable(); | 59 | local_bh_enable(); |
60 | 60 | ||
61 | socket_seq_show(seq); | 61 | socket_seq_show(seq); |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index dff8bc4e0fac..f774651f0a47 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -493,6 +493,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
493 | 493 | ||
494 | ipc.addr = inet->saddr; | 494 | ipc.addr = inet->saddr; |
495 | ipc.opt = NULL; | 495 | ipc.opt = NULL; |
496 | ipc.shtx.flags = 0; | ||
496 | ipc.oif = sk->sk_bound_dev_if; | 497 | ipc.oif = sk->sk_bound_dev_if; |
497 | 498 | ||
498 | if (msg->msg_controllen) { | 499 | if (msg->msg_controllen) { |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 97f71153584f..5caee609be06 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -151,7 +151,7 @@ static void rt_emergency_hash_rebuild(struct net *net); | |||
151 | 151 | ||
152 | static struct dst_ops ipv4_dst_ops = { | 152 | static struct dst_ops ipv4_dst_ops = { |
153 | .family = AF_INET, | 153 | .family = AF_INET, |
154 | .protocol = __constant_htons(ETH_P_IP), | 154 | .protocol = cpu_to_be16(ETH_P_IP), |
155 | .gc = rt_garbage_collect, | 155 | .gc = rt_garbage_collect, |
156 | .check = ipv4_dst_check, | 156 | .check = ipv4_dst_check, |
157 | .destroy = ipv4_dst_destroy, | 157 | .destroy = ipv4_dst_destroy, |
@@ -2696,7 +2696,7 @@ static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
2696 | 2696 | ||
2697 | static struct dst_ops ipv4_dst_blackhole_ops = { | 2697 | static struct dst_ops ipv4_dst_blackhole_ops = { |
2698 | .family = AF_INET, | 2698 | .family = AF_INET, |
2699 | .protocol = __constant_htons(ETH_P_IP), | 2699 | .protocol = cpu_to_be16(ETH_P_IP), |
2700 | .destroy = ipv4_dst_destroy, | 2700 | .destroy = ipv4_dst_destroy, |
2701 | .check = ipv4_dst_check, | 2701 | .check = ipv4_dst_check, |
2702 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, | 2702 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, |
@@ -2779,7 +2779,8 @@ int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp) | |||
2779 | return ip_route_output_flow(net, rp, flp, NULL, 0); | 2779 | return ip_route_output_flow(net, rp, flp, NULL, 0); |
2780 | } | 2780 | } |
2781 | 2781 | ||
2782 | static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | 2782 | static int rt_fill_info(struct net *net, |
2783 | struct sk_buff *skb, u32 pid, u32 seq, int event, | ||
2783 | int nowait, unsigned int flags) | 2784 | int nowait, unsigned int flags) |
2784 | { | 2785 | { |
2785 | struct rtable *rt = skb->rtable; | 2786 | struct rtable *rt = skb->rtable; |
@@ -2844,8 +2845,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | |||
2844 | __be32 dst = rt->rt_dst; | 2845 | __be32 dst = rt->rt_dst; |
2845 | 2846 | ||
2846 | if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) && | 2847 | if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) && |
2847 | IPV4_DEVCONF_ALL(&init_net, MC_FORWARDING)) { | 2848 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { |
2848 | int err = ipmr_get_route(skb, r, nowait); | 2849 | int err = ipmr_get_route(net, skb, r, nowait); |
2849 | if (err <= 0) { | 2850 | if (err <= 0) { |
2850 | if (!nowait) { | 2851 | if (!nowait) { |
2851 | if (err == 0) | 2852 | if (err == 0) |
@@ -2950,7 +2951,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2950 | if (rtm->rtm_flags & RTM_F_NOTIFY) | 2951 | if (rtm->rtm_flags & RTM_F_NOTIFY) |
2951 | rt->rt_flags |= RTCF_NOTIFY; | 2952 | rt->rt_flags |= RTCF_NOTIFY; |
2952 | 2953 | ||
2953 | err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, | 2954 | err = rt_fill_info(net, skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, |
2954 | RTM_NEWROUTE, 0, 0); | 2955 | RTM_NEWROUTE, 0, 0); |
2955 | if (err <= 0) | 2956 | if (err <= 0) |
2956 | goto errout_free; | 2957 | goto errout_free; |
@@ -2988,7 +2989,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
2988 | if (rt_is_expired(rt)) | 2989 | if (rt_is_expired(rt)) |
2989 | continue; | 2990 | continue; |
2990 | skb->dst = dst_clone(&rt->u.dst); | 2991 | skb->dst = dst_clone(&rt->u.dst); |
2991 | if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid, | 2992 | if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid, |
2992 | cb->nlh->nlmsg_seq, RTM_NEWROUTE, | 2993 | cb->nlh->nlmsg_seq, RTM_NEWROUTE, |
2993 | 1, NLM_F_MULTI) <= 0) { | 2994 | 1, NLM_F_MULTI) <= 0) { |
2994 | dst_release(xchg(&skb->dst, NULL)); | 2995 | dst_release(xchg(&skb->dst, NULL)); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 76b148bcb0dc..90b2f3c192ff 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2478,23 +2478,23 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2478 | struct tcphdr *th2; | 2478 | struct tcphdr *th2; |
2479 | unsigned int thlen; | 2479 | unsigned int thlen; |
2480 | unsigned int flags; | 2480 | unsigned int flags; |
2481 | unsigned int total; | ||
2482 | unsigned int mss = 1; | 2481 | unsigned int mss = 1; |
2483 | int flush = 1; | 2482 | int flush = 1; |
2483 | int i; | ||
2484 | 2484 | ||
2485 | if (!pskb_may_pull(skb, sizeof(*th))) | 2485 | th = skb_gro_header(skb, sizeof(*th)); |
2486 | if (unlikely(!th)) | ||
2486 | goto out; | 2487 | goto out; |
2487 | 2488 | ||
2488 | th = tcp_hdr(skb); | ||
2489 | thlen = th->doff * 4; | 2489 | thlen = th->doff * 4; |
2490 | if (thlen < sizeof(*th)) | 2490 | if (thlen < sizeof(*th)) |
2491 | goto out; | 2491 | goto out; |
2492 | 2492 | ||
2493 | if (!pskb_may_pull(skb, thlen)) | 2493 | th = skb_gro_header(skb, thlen); |
2494 | if (unlikely(!th)) | ||
2494 | goto out; | 2495 | goto out; |
2495 | 2496 | ||
2496 | th = tcp_hdr(skb); | 2497 | skb_gro_pull(skb, thlen); |
2497 | __skb_pull(skb, thlen); | ||
2498 | 2498 | ||
2499 | flags = tcp_flag_word(th); | 2499 | flags = tcp_flag_word(th); |
2500 | 2500 | ||
@@ -2504,7 +2504,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2504 | 2504 | ||
2505 | th2 = tcp_hdr(p); | 2505 | th2 = tcp_hdr(p); |
2506 | 2506 | ||
2507 | if (th->source != th2->source || th->dest != th2->dest) { | 2507 | if ((th->source ^ th2->source) | (th->dest ^ th2->dest)) { |
2508 | NAPI_GRO_CB(p)->same_flow = 0; | 2508 | NAPI_GRO_CB(p)->same_flow = 0; |
2509 | continue; | 2509 | continue; |
2510 | } | 2510 | } |
@@ -2519,14 +2519,15 @@ found: | |||
2519 | flush |= flags & TCP_FLAG_CWR; | 2519 | flush |= flags & TCP_FLAG_CWR; |
2520 | flush |= (flags ^ tcp_flag_word(th2)) & | 2520 | flush |= (flags ^ tcp_flag_word(th2)) & |
2521 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); | 2521 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); |
2522 | flush |= th->ack_seq != th2->ack_seq || th->window != th2->window; | 2522 | flush |= (th->ack_seq ^ th2->ack_seq) | (th->window ^ th2->window); |
2523 | flush |= memcmp(th + 1, th2 + 1, thlen - sizeof(*th)); | 2523 | for (i = sizeof(*th); !flush && i < thlen; i += 4) |
2524 | flush |= *(u32 *)((u8 *)th + i) ^ | ||
2525 | *(u32 *)((u8 *)th2 + i); | ||
2524 | 2526 | ||
2525 | total = p->len; | ||
2526 | mss = skb_shinfo(p)->gso_size; | 2527 | mss = skb_shinfo(p)->gso_size; |
2527 | 2528 | ||
2528 | flush |= skb->len > mss || skb->len <= 0; | 2529 | flush |= (skb_gro_len(skb) > mss) | !skb_gro_len(skb); |
2529 | flush |= ntohl(th2->seq) + total != ntohl(th->seq); | 2530 | flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); |
2530 | 2531 | ||
2531 | if (flush || skb_gro_receive(head, skb)) { | 2532 | if (flush || skb_gro_receive(head, skb)) { |
2532 | mss = 1; | 2533 | mss = 1; |
@@ -2538,7 +2539,7 @@ found: | |||
2538 | tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); | 2539 | tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); |
2539 | 2540 | ||
2540 | out_check_final: | 2541 | out_check_final: |
2541 | flush = skb->len < mss; | 2542 | flush = skb_gro_len(skb) < mss; |
2542 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | | 2543 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | |
2543 | TCP_FLAG_SYN | TCP_FLAG_FIN); | 2544 | TCP_FLAG_SYN | TCP_FLAG_FIN); |
2544 | 2545 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 19d7b429a262..a7381205bbfc 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -2355,7 +2355,7 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2355 | 2355 | ||
2356 | switch (skb->ip_summed) { | 2356 | switch (skb->ip_summed) { |
2357 | case CHECKSUM_COMPLETE: | 2357 | case CHECKSUM_COMPLETE: |
2358 | if (!tcp_v4_check(skb->len, iph->saddr, iph->daddr, | 2358 | if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr, |
2359 | skb->csum)) { | 2359 | skb->csum)) { |
2360 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 2360 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
2361 | break; | 2361 | break; |
@@ -2443,7 +2443,7 @@ static struct pernet_operations __net_initdata tcp_sk_ops = { | |||
2443 | void __init tcp_v4_init(void) | 2443 | void __init tcp_v4_init(void) |
2444 | { | 2444 | { |
2445 | inet_hashinfo_init(&tcp_hashinfo); | 2445 | inet_hashinfo_init(&tcp_hashinfo); |
2446 | if (register_pernet_device(&tcp_sk_ops)) | 2446 | if (register_pernet_subsys(&tcp_sk_ops)) |
2447 | panic("Failed to create the TCP control socket.\n"); | 2447 | panic("Failed to create the TCP control socket.\n"); |
2448 | } | 2448 | } |
2449 | 2449 | ||
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index da2c3b8794f2..f6f61b3e677b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -663,10 +663,14 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
663 | th->urg_ptr = 0; | 663 | th->urg_ptr = 0; |
664 | 664 | ||
665 | /* The urg_mode check is necessary during a below snd_una win probe */ | 665 | /* The urg_mode check is necessary during a below snd_una win probe */ |
666 | if (unlikely(tcp_urg_mode(tp) && | 666 | if (unlikely(tcp_urg_mode(tp) && before(tcb->seq, tp->snd_up))) { |
667 | between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF))) { | 667 | if (before(tp->snd_up, tcb->seq + 0x10000)) { |
668 | th->urg_ptr = htons(tp->snd_up - tcb->seq); | 668 | th->urg_ptr = htons(tp->snd_up - tcb->seq); |
669 | th->urg = 1; | 669 | th->urg = 1; |
670 | } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { | ||
671 | th->urg_ptr = 0xFFFF; | ||
672 | th->urg = 1; | ||
673 | } | ||
670 | } | 674 | } |
671 | 675 | ||
672 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); | 676 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c47c989cb1fb..4bd178a111d5 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
596 | return -EOPNOTSUPP; | 596 | return -EOPNOTSUPP; |
597 | 597 | ||
598 | ipc.opt = NULL; | 598 | ipc.opt = NULL; |
599 | ipc.shtx.flags = 0; | ||
599 | 600 | ||
600 | if (up->pending) { | 601 | if (up->pending) { |
601 | /* | 602 | /* |
@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
643 | ipc.addr = inet->saddr; | 644 | ipc.addr = inet->saddr; |
644 | 645 | ||
645 | ipc.oif = sk->sk_bound_dev_if; | 646 | ipc.oif = sk->sk_bound_dev_if; |
647 | err = sock_tx_timestamp(msg, sk, &ipc.shtx); | ||
648 | if (err) | ||
649 | return err; | ||
646 | if (msg->msg_controllen) { | 650 | if (msg->msg_controllen) { |
647 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); | 651 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); |
648 | if (err) | 652 | if (err) |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 2ad24ba31f9d..60d918c96a4f 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -241,7 +241,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
241 | 241 | ||
242 | static struct dst_ops xfrm4_dst_ops = { | 242 | static struct dst_ops xfrm4_dst_ops = { |
243 | .family = AF_INET, | 243 | .family = AF_INET, |
244 | .protocol = __constant_htons(ETH_P_IP), | 244 | .protocol = cpu_to_be16(ETH_P_IP), |
245 | .gc = xfrm4_garbage_collect, | 245 | .gc = xfrm4_garbage_collect, |
246 | .update_pmtu = xfrm4_update_pmtu, | 246 | .update_pmtu = xfrm4_update_pmtu, |
247 | .destroy = xfrm4_dst_destroy, | 247 | .destroy = xfrm4_dst_destroy, |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f9afb452249c..f8f76d6e21cb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2224,10 +2224,24 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg) | |||
2224 | return err; | 2224 | return err; |
2225 | } | 2225 | } |
2226 | 2226 | ||
2227 | static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | ||
2228 | int plen, int scope) | ||
2229 | { | ||
2230 | struct inet6_ifaddr *ifp; | ||
2231 | |||
2232 | ifp = ipv6_add_addr(idev, addr, plen, scope, IFA_F_PERMANENT); | ||
2233 | if (!IS_ERR(ifp)) { | ||
2234 | spin_lock_bh(&ifp->lock); | ||
2235 | ifp->flags &= ~IFA_F_TENTATIVE; | ||
2236 | spin_unlock_bh(&ifp->lock); | ||
2237 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | ||
2238 | in6_ifa_put(ifp); | ||
2239 | } | ||
2240 | } | ||
2241 | |||
2227 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | 2242 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) |
2228 | static void sit_add_v4_addrs(struct inet6_dev *idev) | 2243 | static void sit_add_v4_addrs(struct inet6_dev *idev) |
2229 | { | 2244 | { |
2230 | struct inet6_ifaddr * ifp; | ||
2231 | struct in6_addr addr; | 2245 | struct in6_addr addr; |
2232 | struct net_device *dev; | 2246 | struct net_device *dev; |
2233 | struct net *net = dev_net(idev->dev); | 2247 | struct net *net = dev_net(idev->dev); |
@@ -2246,14 +2260,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2246 | } | 2260 | } |
2247 | 2261 | ||
2248 | if (addr.s6_addr32[3]) { | 2262 | if (addr.s6_addr32[3]) { |
2249 | ifp = ipv6_add_addr(idev, &addr, 128, scope, IFA_F_PERMANENT); | 2263 | add_addr(idev, &addr, 128, scope); |
2250 | if (!IS_ERR(ifp)) { | ||
2251 | spin_lock_bh(&ifp->lock); | ||
2252 | ifp->flags &= ~IFA_F_TENTATIVE; | ||
2253 | spin_unlock_bh(&ifp->lock); | ||
2254 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | ||
2255 | in6_ifa_put(ifp); | ||
2256 | } | ||
2257 | return; | 2264 | return; |
2258 | } | 2265 | } |
2259 | 2266 | ||
@@ -2281,15 +2288,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2281 | else | 2288 | else |
2282 | plen = 96; | 2289 | plen = 96; |
2283 | 2290 | ||
2284 | ifp = ipv6_add_addr(idev, &addr, plen, flag, | 2291 | add_addr(idev, &addr, plen, flag); |
2285 | IFA_F_PERMANENT); | ||
2286 | if (!IS_ERR(ifp)) { | ||
2287 | spin_lock_bh(&ifp->lock); | ||
2288 | ifp->flags &= ~IFA_F_TENTATIVE; | ||
2289 | spin_unlock_bh(&ifp->lock); | ||
2290 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | ||
2291 | in6_ifa_put(ifp); | ||
2292 | } | ||
2293 | } | 2292 | } |
2294 | } | 2293 | } |
2295 | } | 2294 | } |
@@ -2299,7 +2298,6 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2299 | static void init_loopback(struct net_device *dev) | 2298 | static void init_loopback(struct net_device *dev) |
2300 | { | 2299 | { |
2301 | struct inet6_dev *idev; | 2300 | struct inet6_dev *idev; |
2302 | struct inet6_ifaddr * ifp; | ||
2303 | 2301 | ||
2304 | /* ::1 */ | 2302 | /* ::1 */ |
2305 | 2303 | ||
@@ -2310,14 +2308,7 @@ static void init_loopback(struct net_device *dev) | |||
2310 | return; | 2308 | return; |
2311 | } | 2309 | } |
2312 | 2310 | ||
2313 | ifp = ipv6_add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT); | 2311 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); |
2314 | if (!IS_ERR(ifp)) { | ||
2315 | spin_lock_bh(&ifp->lock); | ||
2316 | ifp->flags &= ~IFA_F_TENTATIVE; | ||
2317 | spin_unlock_bh(&ifp->lock); | ||
2318 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | ||
2319 | in6_ifa_put(ifp); | ||
2320 | } | ||
2321 | } | 2312 | } |
2322 | 2313 | ||
2323 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) | 2314 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) |
@@ -3647,7 +3638,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | |||
3647 | kfree_skb(skb); | 3638 | kfree_skb(skb); |
3648 | goto errout; | 3639 | goto errout; |
3649 | } | 3640 | } |
3650 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3641 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3642 | return; | ||
3651 | errout: | 3643 | errout: |
3652 | if (err < 0) | 3644 | if (err < 0) |
3653 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); | 3645 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
@@ -3858,7 +3850,8 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
3858 | kfree_skb(skb); | 3850 | kfree_skb(skb); |
3859 | goto errout; | 3851 | goto errout; |
3860 | } | 3852 | } |
3861 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3853 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3854 | return; | ||
3862 | errout: | 3855 | errout: |
3863 | if (err < 0) | 3856 | if (err < 0) |
3864 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); | 3857 | rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); |
@@ -3928,7 +3921,8 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3928 | kfree_skb(skb); | 3921 | kfree_skb(skb); |
3929 | goto errout; | 3922 | goto errout; |
3930 | } | 3923 | } |
3931 | err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); | 3924 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); |
3925 | return; | ||
3932 | errout: | 3926 | errout: |
3933 | if (err < 0) | 3927 | if (err < 0) |
3934 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); | 3928 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index c802bc1658a8..fa2ac7ee662f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -799,24 +799,34 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
799 | int proto; | 799 | int proto; |
800 | __wsum csum; | 800 | __wsum csum; |
801 | 801 | ||
802 | if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) | 802 | iph = skb_gro_header(skb, sizeof(*iph)); |
803 | if (unlikely(!iph)) | ||
803 | goto out; | 804 | goto out; |
804 | 805 | ||
805 | iph = ipv6_hdr(skb); | 806 | skb_gro_pull(skb, sizeof(*iph)); |
806 | __skb_pull(skb, sizeof(*iph)); | 807 | skb_set_transport_header(skb, skb_gro_offset(skb)); |
807 | 808 | ||
808 | flush += ntohs(iph->payload_len) != skb->len; | 809 | flush += ntohs(iph->payload_len) != skb_gro_len(skb); |
809 | 810 | ||
810 | rcu_read_lock(); | 811 | rcu_read_lock(); |
811 | proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr); | 812 | proto = iph->nexthdr; |
812 | iph = ipv6_hdr(skb); | ||
813 | IPV6_GRO_CB(skb)->proto = proto; | ||
814 | ops = rcu_dereference(inet6_protos[proto]); | 813 | ops = rcu_dereference(inet6_protos[proto]); |
815 | if (!ops || !ops->gro_receive) | 814 | if (!ops || !ops->gro_receive) { |
816 | goto out_unlock; | 815 | __pskb_pull(skb, skb_gro_offset(skb)); |
816 | proto = ipv6_gso_pull_exthdrs(skb, proto); | ||
817 | skb_gro_pull(skb, -skb_transport_offset(skb)); | ||
818 | skb_reset_transport_header(skb); | ||
819 | __skb_push(skb, skb_gro_offset(skb)); | ||
820 | |||
821 | if (!ops || !ops->gro_receive) | ||
822 | goto out_unlock; | ||
823 | |||
824 | iph = ipv6_hdr(skb); | ||
825 | } | ||
826 | |||
827 | IPV6_GRO_CB(skb)->proto = proto; | ||
817 | 828 | ||
818 | flush--; | 829 | flush--; |
819 | skb_reset_transport_header(skb); | ||
820 | nlen = skb_network_header_len(skb); | 830 | nlen = skb_network_header_len(skb); |
821 | 831 | ||
822 | for (p = *head; p; p = p->next) { | 832 | for (p = *head; p; p = p->next) { |
@@ -880,7 +890,7 @@ out_unlock: | |||
880 | } | 890 | } |
881 | 891 | ||
882 | static struct packet_type ipv6_packet_type = { | 892 | static struct packet_type ipv6_packet_type = { |
883 | .type = __constant_htons(ETH_P_IPV6), | 893 | .type = cpu_to_be16(ETH_P_IPV6), |
884 | .func = ipv6_rcv, | 894 | .func = ipv6_rcv, |
885 | .gso_send_check = ipv6_gso_send_check, | 895 | .gso_send_check = ipv6_gso_send_check, |
886 | .gso_segment = ipv6_gso_segment, | 896 | .gso_segment = ipv6_gso_segment, |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 40f324655e24..d31df0f4bc9a 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -218,8 +218,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
218 | if (opt) | 218 | if (opt) |
219 | sock_kfree_s(sk, opt, opt->tot_len); | 219 | sock_kfree_s(sk, opt, opt->tot_len); |
220 | pktopt = xchg(&np->pktoptions, NULL); | 220 | pktopt = xchg(&np->pktoptions, NULL); |
221 | if (pktopt) | 221 | kfree_skb(pktopt); |
222 | kfree_skb(pktopt); | ||
223 | 222 | ||
224 | sk->sk_destruct = inet_sock_destruct; | 223 | sk->sk_destruct = inet_sock_destruct; |
225 | /* | 224 | /* |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3e2970841bd8..9f061d1adbc2 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1095,11 +1095,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | |||
1095 | &ipv6_hdr(ra)->saddr); | 1095 | &ipv6_hdr(ra)->saddr); |
1096 | nlmsg_end(skb, nlh); | 1096 | nlmsg_end(skb, nlh); |
1097 | 1097 | ||
1098 | err = rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, | 1098 | rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL, GFP_ATOMIC); |
1099 | GFP_ATOMIC); | ||
1100 | if (err < 0) | ||
1101 | goto errout; | ||
1102 | |||
1103 | return; | 1099 | return; |
1104 | 1100 | ||
1105 | nla_put_failure: | 1101 | nla_put_failure: |
@@ -1538,13 +1534,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1538 | if (rt->rt6i_flags & RTF_GATEWAY) { | 1534 | if (rt->rt6i_flags & RTF_GATEWAY) { |
1539 | ND_PRINTK2(KERN_WARNING | 1535 | ND_PRINTK2(KERN_WARNING |
1540 | "ICMPv6 Redirect: destination is not a neighbour.\n"); | 1536 | "ICMPv6 Redirect: destination is not a neighbour.\n"); |
1541 | dst_release(dst); | 1537 | goto release; |
1542 | return; | ||
1543 | } | ||
1544 | if (!xrlim_allow(dst, 1*HZ)) { | ||
1545 | dst_release(dst); | ||
1546 | return; | ||
1547 | } | 1538 | } |
1539 | if (!xrlim_allow(dst, 1*HZ)) | ||
1540 | goto release; | ||
1548 | 1541 | ||
1549 | if (dev->addr_len) { | 1542 | if (dev->addr_len) { |
1550 | read_lock_bh(&neigh->lock); | 1543 | read_lock_bh(&neigh->lock); |
@@ -1570,8 +1563,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1570 | ND_PRINTK0(KERN_ERR | 1563 | ND_PRINTK0(KERN_ERR |
1571 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", | 1564 | "ICMPv6 Redirect: %s() failed to allocate an skb.\n", |
1572 | __func__); | 1565 | __func__); |
1573 | dst_release(dst); | 1566 | goto release; |
1574 | return; | ||
1575 | } | 1567 | } |
1576 | 1568 | ||
1577 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); | 1569 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); |
@@ -1631,6 +1623,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1631 | 1623 | ||
1632 | if (likely(idev != NULL)) | 1624 | if (likely(idev != NULL)) |
1633 | in6_dev_put(idev); | 1625 | in6_dev_put(idev); |
1626 | return; | ||
1627 | |||
1628 | release: | ||
1629 | dst_release(dst); | ||
1634 | } | 1630 | } |
1635 | 1631 | ||
1636 | static void pndisc_redo(struct sk_buff *skb) | 1632 | static void pndisc_redo(struct sk_buff *skb) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9c574235c905..1394ddb6e35c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -98,7 +98,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
98 | 98 | ||
99 | static struct dst_ops ip6_dst_ops_template = { | 99 | static struct dst_ops ip6_dst_ops_template = { |
100 | .family = AF_INET6, | 100 | .family = AF_INET6, |
101 | .protocol = __constant_htons(ETH_P_IPV6), | 101 | .protocol = cpu_to_be16(ETH_P_IPV6), |
102 | .gc = ip6_dst_gc, | 102 | .gc = ip6_dst_gc, |
103 | .gc_thresh = 1024, | 103 | .gc_thresh = 1024, |
104 | .check = ip6_dst_check, | 104 | .check = ip6_dst_check, |
@@ -117,7 +117,7 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
117 | 117 | ||
118 | static struct dst_ops ip6_dst_blackhole_ops = { | 118 | static struct dst_ops ip6_dst_blackhole_ops = { |
119 | .family = AF_INET6, | 119 | .family = AF_INET6, |
120 | .protocol = __constant_htons(ETH_P_IPV6), | 120 | .protocol = cpu_to_be16(ETH_P_IPV6), |
121 | .destroy = ip6_dst_destroy, | 121 | .destroy = ip6_dst_destroy, |
122 | .check = ip6_dst_check, | 122 | .check = ip6_dst_check, |
123 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 123 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
@@ -2400,8 +2400,9 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2400 | kfree_skb(skb); | 2400 | kfree_skb(skb); |
2401 | goto errout; | 2401 | goto errout; |
2402 | } | 2402 | } |
2403 | err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, | 2403 | rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, |
2404 | info->nlh, gfp_any()); | 2404 | info->nlh, gfp_any()); |
2405 | return; | ||
2405 | errout: | 2406 | errout: |
2406 | if (err < 0) | 2407 | if (err < 0) |
2407 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); | 2408 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index d3467e563f02..26915effb3bc 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -454,7 +454,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
454 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 454 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |
455 | goto out; | 455 | goto out; |
456 | 456 | ||
457 | if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) | 457 | if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) |
458 | t->err_count++; | 458 | t->err_count++; |
459 | else | 459 | else |
460 | t->err_count = 1; | 460 | t->err_count = 1; |
@@ -658,7 +658,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
658 | } | 658 | } |
659 | 659 | ||
660 | if (tunnel->err_count > 0) { | 660 | if (tunnel->err_count > 0) { |
661 | if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) { | 661 | if (time_before(jiffies, |
662 | tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { | ||
662 | tunnel->err_count--; | 663 | tunnel->err_count--; |
663 | dst_link_failure(skb); | 664 | dst_link_failure(skb); |
664 | } else | 665 | } else |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e5b85d45bee8..4b5aa1854260 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -533,8 +533,7 @@ static inline void syn_flood_warning(struct sk_buff *skb) | |||
533 | 533 | ||
534 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 534 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
535 | { | 535 | { |
536 | if (inet6_rsk(req)->pktopts) | 536 | kfree_skb(inet6_rsk(req)->pktopts); |
537 | kfree_skb(inet6_rsk(req)->pktopts); | ||
538 | } | 537 | } |
539 | 538 | ||
540 | #ifdef CONFIG_TCP_MD5SIG | 539 | #ifdef CONFIG_TCP_MD5SIG |
@@ -948,7 +947,7 @@ struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
948 | 947 | ||
949 | switch (skb->ip_summed) { | 948 | switch (skb->ip_summed) { |
950 | case CHECKSUM_COMPLETE: | 949 | case CHECKSUM_COMPLETE: |
951 | if (!tcp_v6_check(skb->len, &iph->saddr, &iph->daddr, | 950 | if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, |
952 | skb->csum)) { | 951 | skb->csum)) { |
953 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 952 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
954 | break; | 953 | break; |
@@ -1611,8 +1610,7 @@ ipv6_pktoptions: | |||
1611 | } | 1610 | } |
1612 | } | 1611 | } |
1613 | 1612 | ||
1614 | if (opt_skb) | 1613 | kfree_skb(opt_skb); |
1615 | kfree_skb(opt_skb); | ||
1616 | return 0; | 1614 | return 0; |
1617 | } | 1615 | } |
1618 | 1616 | ||
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 97ab068e8ccc..b4b16a43f277 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -272,7 +272,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
272 | 272 | ||
273 | static struct dst_ops xfrm6_dst_ops = { | 273 | static struct dst_ops xfrm6_dst_ops = { |
274 | .family = AF_INET6, | 274 | .family = AF_INET6, |
275 | .protocol = __constant_htons(ETH_P_IPV6), | 275 | .protocol = cpu_to_be16(ETH_P_IPV6), |
276 | .gc = xfrm6_garbage_collect, | 276 | .gc = xfrm6_garbage_collect, |
277 | .update_pmtu = xfrm6_update_pmtu, | 277 | .update_pmtu = xfrm6_update_pmtu, |
278 | .destroy = xfrm6_dst_destroy, | 278 | .destroy = xfrm6_dst_destroy, |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 0e685b05496e..f417b77fa0e1 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -69,7 +69,7 @@ __xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass) | |||
69 | 69 | ||
70 | for (i = 0; i < n; i++) { | 70 | for (i = 0; i < n; i++) { |
71 | dst[count[class[i] - 1]++] = src[i]; | 71 | dst[count[class[i] - 1]++] = src[i]; |
72 | src[i] = 0; | 72 | src[i] = NULL; |
73 | } | 73 | } |
74 | 74 | ||
75 | return 0; | 75 | return 0; |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index b6e70f92e7fb..43d0ffc6d565 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -1959,12 +1959,12 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { | |||
1959 | SOCKOPS_WRAP(ipx_dgram, PF_IPX); | 1959 | SOCKOPS_WRAP(ipx_dgram, PF_IPX); |
1960 | 1960 | ||
1961 | static struct packet_type ipx_8023_packet_type = { | 1961 | static struct packet_type ipx_8023_packet_type = { |
1962 | .type = __constant_htons(ETH_P_802_3), | 1962 | .type = cpu_to_be16(ETH_P_802_3), |
1963 | .func = ipx_rcv, | 1963 | .func = ipx_rcv, |
1964 | }; | 1964 | }; |
1965 | 1965 | ||
1966 | static struct packet_type ipx_dix_packet_type = { | 1966 | static struct packet_type ipx_dix_packet_type = { |
1967 | .type = __constant_htons(ETH_P_IPX), | 1967 | .type = cpu_to_be16(ETH_P_IPX), |
1968 | .func = ipx_rcv, | 1968 | .func = ipx_rcv, |
1969 | }; | 1969 | }; |
1970 | 1970 | ||
diff --git a/net/irda/irmod.c b/net/irda/irmod.c index 4c487a883725..1bb607f2f5c7 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c | |||
@@ -56,7 +56,7 @@ EXPORT_SYMBOL(irda_debug); | |||
56 | * Tell the kernel how IrDA packets should be handled. | 56 | * Tell the kernel how IrDA packets should be handled. |
57 | */ | 57 | */ |
58 | static struct packet_type irda_packet_type = { | 58 | static struct packet_type irda_packet_type = { |
59 | .type = __constant_htons(ETH_P_IRDA), | 59 | .type = cpu_to_be16(ETH_P_IRDA), |
60 | .func = irlap_driver_rcv, /* Packet type handler irlap_frame.c */ | 60 | .func = irlap_driver_rcv, /* Packet type handler irlap_frame.c */ |
61 | }; | 61 | }; |
62 | 62 | ||
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 56fd85ab358e..febae702685c 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -1118,11 +1118,11 @@ static const struct proto_ops llc_ui_ops = { | |||
1118 | .sendpage = sock_no_sendpage, | 1118 | .sendpage = sock_no_sendpage, |
1119 | }; | 1119 | }; |
1120 | 1120 | ||
1121 | static char llc_proc_err_msg[] __initdata = | 1121 | static const char llc_proc_err_msg[] __initconst = |
1122 | KERN_CRIT "LLC: Unable to register the proc_fs entries\n"; | 1122 | KERN_CRIT "LLC: Unable to register the proc_fs entries\n"; |
1123 | static char llc_sysctl_err_msg[] __initdata = | 1123 | static const char llc_sysctl_err_msg[] __initconst = |
1124 | KERN_CRIT "LLC: Unable to register the sysctl entries\n"; | 1124 | KERN_CRIT "LLC: Unable to register the sysctl entries\n"; |
1125 | static char llc_sock_err_msg[] __initdata = | 1125 | static const char llc_sock_err_msg[] __initconst = |
1126 | KERN_CRIT "LLC: Unable to register the network family\n"; | 1126 | KERN_CRIT "LLC: Unable to register the network family\n"; |
1127 | 1127 | ||
1128 | static int __init llc2_init(void) | 1128 | static int __init llc2_init(void) |
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 50d5b10e23a2..a7fe1adc378d 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c | |||
@@ -148,12 +148,12 @@ void llc_sap_close(struct llc_sap *sap) | |||
148 | } | 148 | } |
149 | 149 | ||
150 | static struct packet_type llc_packet_type = { | 150 | static struct packet_type llc_packet_type = { |
151 | .type = __constant_htons(ETH_P_802_2), | 151 | .type = cpu_to_be16(ETH_P_802_2), |
152 | .func = llc_rcv, | 152 | .func = llc_rcv, |
153 | }; | 153 | }; |
154 | 154 | ||
155 | static struct packet_type llc_tr_packet_type = { | 155 | static struct packet_type llc_tr_packet_type = { |
156 | .type = __constant_htons(ETH_P_TR_802_2), | 156 | .type = cpu_to_be16(ETH_P_TR_802_2), |
157 | .func = llc_rcv, | 157 | .func = llc_rcv, |
158 | }; | 158 | }; |
159 | 159 | ||
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 7d4971aa443f..3503a3d21318 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -8,13 +8,14 @@ mac80211-y := \ | |||
8 | wep.o \ | 8 | wep.o \ |
9 | wpa.o \ | 9 | wpa.o \ |
10 | scan.o \ | 10 | scan.o \ |
11 | ht.o \ | 11 | ht.o agg-tx.o agg-rx.o \ |
12 | mlme.o \ | 12 | mlme.o \ |
13 | iface.o \ | 13 | iface.o \ |
14 | rate.o \ | 14 | rate.o \ |
15 | michael.o \ | 15 | michael.o \ |
16 | tkip.o \ | 16 | tkip.o \ |
17 | aes_ccm.o \ | 17 | aes_ccm.o \ |
18 | aes_cmac.o \ | ||
18 | cfg.o \ | 19 | cfg.o \ |
19 | rx.o \ | 20 | rx.o \ |
20 | spectmgmt.o \ | 21 | spectmgmt.o \ |
@@ -37,6 +38,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ | |||
37 | mesh_plink.o \ | 38 | mesh_plink.o \ |
38 | mesh_hwmp.o | 39 | mesh_hwmp.o |
39 | 40 | ||
41 | mac80211-$(CONFIG_PM) += pm.o | ||
42 | |||
40 | # objects for PID algorithm | 43 | # objects for PID algorithm |
41 | rc80211_pid-y := rc80211_pid_algo.o | 44 | rc80211_pid-y := rc80211_pid_algo.o |
42 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o | 45 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c new file mode 100644 index 000000000000..3d097b3d7b62 --- /dev/null +++ b/net/mac80211/aes_cmac.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * AES-128-CMAC with TLen 16 for IEEE 802.11w BIP | ||
3 | * Copyright 2008, Jouni Malinen <j@w1.fi> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/crypto.h> | ||
13 | #include <linux/err.h> | ||
14 | |||
15 | #include <net/mac80211.h> | ||
16 | #include "key.h" | ||
17 | #include "aes_cmac.h" | ||
18 | |||
19 | #define AES_BLOCK_SIZE 16 | ||
20 | #define AES_CMAC_KEY_LEN 16 | ||
21 | #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ | ||
22 | #define AAD_LEN 20 | ||
23 | |||
24 | |||
25 | static void gf_mulx(u8 *pad) | ||
26 | { | ||
27 | int i, carry; | ||
28 | |||
29 | carry = pad[0] & 0x80; | ||
30 | for (i = 0; i < AES_BLOCK_SIZE - 1; i++) | ||
31 | pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); | ||
32 | pad[AES_BLOCK_SIZE - 1] <<= 1; | ||
33 | if (carry) | ||
34 | pad[AES_BLOCK_SIZE - 1] ^= 0x87; | ||
35 | } | ||
36 | |||
37 | |||
38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch, | ||
39 | size_t num_elem, | ||
40 | const u8 *addr[], const size_t *len, u8 *mac) | ||
41 | { | ||
42 | u8 *cbc, *pad; | ||
43 | const u8 *pos, *end; | ||
44 | size_t i, e, left, total_len; | ||
45 | |||
46 | cbc = scratch; | ||
47 | pad = scratch + AES_BLOCK_SIZE; | ||
48 | |||
49 | memset(cbc, 0, AES_BLOCK_SIZE); | ||
50 | |||
51 | total_len = 0; | ||
52 | for (e = 0; e < num_elem; e++) | ||
53 | total_len += len[e]; | ||
54 | left = total_len; | ||
55 | |||
56 | e = 0; | ||
57 | pos = addr[0]; | ||
58 | end = pos + len[0]; | ||
59 | |||
60 | while (left >= AES_BLOCK_SIZE) { | ||
61 | for (i = 0; i < AES_BLOCK_SIZE; i++) { | ||
62 | cbc[i] ^= *pos++; | ||
63 | if (pos >= end) { | ||
64 | e++; | ||
65 | pos = addr[e]; | ||
66 | end = pos + len[e]; | ||
67 | } | ||
68 | } | ||
69 | if (left > AES_BLOCK_SIZE) | ||
70 | crypto_cipher_encrypt_one(tfm, cbc, cbc); | ||
71 | left -= AES_BLOCK_SIZE; | ||
72 | } | ||
73 | |||
74 | memset(pad, 0, AES_BLOCK_SIZE); | ||
75 | crypto_cipher_encrypt_one(tfm, pad, pad); | ||
76 | gf_mulx(pad); | ||
77 | |||
78 | if (left || total_len == 0) { | ||
79 | for (i = 0; i < left; i++) { | ||
80 | cbc[i] ^= *pos++; | ||
81 | if (pos >= end) { | ||
82 | e++; | ||
83 | pos = addr[e]; | ||
84 | end = pos + len[e]; | ||
85 | } | ||
86 | } | ||
87 | cbc[left] ^= 0x80; | ||
88 | gf_mulx(pad); | ||
89 | } | ||
90 | |||
91 | for (i = 0; i < AES_BLOCK_SIZE; i++) | ||
92 | pad[i] ^= cbc[i]; | ||
93 | crypto_cipher_encrypt_one(tfm, pad, pad); | ||
94 | memcpy(mac, pad, CMAC_TLEN); | ||
95 | } | ||
96 | |||
97 | |||
98 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, | ||
99 | const u8 *data, size_t data_len, u8 *mic) | ||
100 | { | ||
101 | const u8 *addr[3]; | ||
102 | size_t len[3]; | ||
103 | u8 zero[CMAC_TLEN]; | ||
104 | |||
105 | memset(zero, 0, CMAC_TLEN); | ||
106 | addr[0] = aad; | ||
107 | len[0] = AAD_LEN; | ||
108 | addr[1] = data; | ||
109 | len[1] = data_len - CMAC_TLEN; | ||
110 | addr[2] = zero; | ||
111 | len[2] = CMAC_TLEN; | ||
112 | |||
113 | aes_128_cmac_vector(tfm, scratch, 3, addr, len, mic); | ||
114 | } | ||
115 | |||
116 | |||
117 | struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) | ||
118 | { | ||
119 | struct crypto_cipher *tfm; | ||
120 | |||
121 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | ||
122 | if (IS_ERR(tfm)) | ||
123 | return NULL; | ||
124 | |||
125 | crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); | ||
126 | |||
127 | return tfm; | ||
128 | } | ||
129 | |||
130 | |||
131 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) | ||
132 | { | ||
133 | if (tfm) | ||
134 | crypto_free_cipher(tfm); | ||
135 | } | ||
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h new file mode 100644 index 000000000000..0eb9a4831508 --- /dev/null +++ b/net/mac80211/aes_cmac.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * Copyright 2008, Jouni Malinen <j@w1.fi> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef AES_CMAC_H | ||
10 | #define AES_CMAC_H | ||
11 | |||
12 | #include <linux/crypto.h> | ||
13 | |||
14 | struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); | ||
15 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, | ||
16 | const u8 *data, size_t data_len, u8 *mic); | ||
17 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); | ||
18 | |||
19 | #endif /* AES_CMAC_H */ | ||
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c new file mode 100644 index 000000000000..3112bfd441b6 --- /dev/null +++ b/net/mac80211/agg-rx.c | |||
@@ -0,0 +1,302 @@ | |||
1 | /* | ||
2 | * HT handling | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2007-2008, Intel Corporation | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/ieee80211.h> | ||
17 | #include <net/mac80211.h> | ||
18 | #include "ieee80211_i.h" | ||
19 | |||
20 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | ||
21 | u16 initiator, u16 reason) | ||
22 | { | ||
23 | struct ieee80211_local *local = sta->local; | ||
24 | struct ieee80211_hw *hw = &local->hw; | ||
25 | int i; | ||
26 | |||
27 | /* check if TID is in operational state */ | ||
28 | spin_lock_bh(&sta->lock); | ||
29 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) { | ||
30 | spin_unlock_bh(&sta->lock); | ||
31 | return; | ||
32 | } | ||
33 | |||
34 | sta->ampdu_mlme.tid_state_rx[tid] = | ||
35 | HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
36 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
37 | spin_unlock_bh(&sta->lock); | ||
38 | |||
39 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
40 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", | ||
41 | sta->sta.addr, tid); | ||
42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
43 | |||
44 | if (local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, | ||
45 | &sta->sta, tid, NULL)) | ||
46 | printk(KERN_DEBUG "HW problem - can not stop rx " | ||
47 | "aggregation for tid %d\n", tid); | ||
48 | |||
49 | /* shutdown timer has not expired */ | ||
50 | if (initiator != WLAN_BACK_TIMER) | ||
51 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
52 | |||
53 | /* check if this is a self generated aggregation halt */ | ||
54 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | ||
55 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | ||
56 | tid, 0, reason); | ||
57 | |||
58 | /* free the reordering buffer */ | ||
59 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | ||
60 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | ||
61 | /* release the reordered frames */ | ||
62 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | ||
63 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | ||
64 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | spin_lock_bh(&sta->lock); | ||
69 | /* free resources */ | ||
70 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | ||
71 | |||
72 | if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { | ||
73 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
74 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
75 | } | ||
76 | |||
77 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
78 | spin_unlock_bh(&sta->lock); | ||
79 | } | ||
80 | |||
81 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | ||
82 | u16 initiator, u16 reason) | ||
83 | { | ||
84 | struct ieee80211_local *local = sdata->local; | ||
85 | struct sta_info *sta; | ||
86 | |||
87 | /* stop HW Rx aggregation. ampdu_action existence | ||
88 | * already verified in session init so we add the BUG_ON */ | ||
89 | BUG_ON(!local->ops->ampdu_action); | ||
90 | |||
91 | rcu_read_lock(); | ||
92 | |||
93 | sta = sta_info_get(local, ra); | ||
94 | if (!sta) { | ||
95 | rcu_read_unlock(); | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | __ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); | ||
100 | |||
101 | rcu_read_unlock(); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * After accepting the AddBA Request we activated a timer, | ||
106 | * resetting it after each frame that arrives from the originator. | ||
107 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | ||
108 | */ | ||
109 | static void sta_rx_agg_session_timer_expired(unsigned long data) | ||
110 | { | ||
111 | /* not an elegant detour, but there is no choice as the timer passes | ||
112 | * only one argument, and various sta_info are needed here, so init | ||
113 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
114 | * array gives the sta through container_of */ | ||
115 | u8 *ptid = (u8 *)data; | ||
116 | u8 *timer_to_id = ptid - *ptid; | ||
117 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
118 | timer_to_tid[0]); | ||
119 | |||
120 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
121 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | ||
122 | #endif | ||
123 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | ||
124 | (u16)*ptid, WLAN_BACK_TIMER, | ||
125 | WLAN_REASON_QSTA_TIMEOUT); | ||
126 | } | ||
127 | |||
128 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | ||
129 | u8 dialog_token, u16 status, u16 policy, | ||
130 | u16 buf_size, u16 timeout) | ||
131 | { | ||
132 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
133 | struct ieee80211_local *local = sdata->local; | ||
134 | struct sk_buff *skb; | ||
135 | struct ieee80211_mgmt *mgmt; | ||
136 | u16 capab; | ||
137 | |||
138 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
139 | |||
140 | if (!skb) { | ||
141 | printk(KERN_DEBUG "%s: failed to allocate buffer " | ||
142 | "for addba resp frame\n", sdata->dev->name); | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
147 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
148 | memset(mgmt, 0, 24); | ||
149 | memcpy(mgmt->da, da, ETH_ALEN); | ||
150 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
151 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
152 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
153 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
154 | else | ||
155 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
156 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
157 | IEEE80211_STYPE_ACTION); | ||
158 | |||
159 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); | ||
160 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
161 | mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; | ||
162 | mgmt->u.action.u.addba_resp.dialog_token = dialog_token; | ||
163 | |||
164 | capab = (u16)(policy << 1); /* bit 1 aggregation policy */ | ||
165 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
166 | capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ | ||
167 | |||
168 | mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); | ||
169 | mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); | ||
170 | mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); | ||
171 | |||
172 | ieee80211_tx_skb(sdata, skb, 1); | ||
173 | } | ||
174 | |||
175 | void ieee80211_process_addba_request(struct ieee80211_local *local, | ||
176 | struct sta_info *sta, | ||
177 | struct ieee80211_mgmt *mgmt, | ||
178 | size_t len) | ||
179 | { | ||
180 | struct ieee80211_hw *hw = &local->hw; | ||
181 | struct ieee80211_conf *conf = &hw->conf; | ||
182 | struct tid_ampdu_rx *tid_agg_rx; | ||
183 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | ||
184 | u8 dialog_token; | ||
185 | int ret = -EOPNOTSUPP; | ||
186 | |||
187 | /* extract session parameters from addba request frame */ | ||
188 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | ||
189 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | ||
190 | start_seq_num = | ||
191 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
192 | |||
193 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
194 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
195 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
196 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
197 | |||
198 | status = WLAN_STATUS_REQUEST_DECLINED; | ||
199 | |||
200 | /* sanity check for incoming parameters: | ||
201 | * check if configuration can support the BA policy | ||
202 | * and if buffer size does not exceeds max value */ | ||
203 | /* XXX: check own ht delayed BA capability?? */ | ||
204 | if (((ba_policy != 1) | ||
205 | && (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) | ||
206 | || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { | ||
207 | status = WLAN_STATUS_INVALID_QOS_PARAM; | ||
208 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
209 | if (net_ratelimit()) | ||
210 | printk(KERN_DEBUG "AddBA Req with bad params from " | ||
211 | "%pM on tid %u. policy %d, buffer size %d\n", | ||
212 | mgmt->sa, tid, ba_policy, | ||
213 | buf_size); | ||
214 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
215 | goto end_no_lock; | ||
216 | } | ||
217 | /* determine default buffer size */ | ||
218 | if (buf_size == 0) { | ||
219 | struct ieee80211_supported_band *sband; | ||
220 | |||
221 | sband = local->hw.wiphy->bands[conf->channel->band]; | ||
222 | buf_size = IEEE80211_MIN_AMPDU_BUF; | ||
223 | buf_size = buf_size << sband->ht_cap.ampdu_factor; | ||
224 | } | ||
225 | |||
226 | |||
227 | /* examine state machine */ | ||
228 | spin_lock_bh(&sta->lock); | ||
229 | |||
230 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | ||
231 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
232 | if (net_ratelimit()) | ||
233 | printk(KERN_DEBUG "unexpected AddBA Req from " | ||
234 | "%pM on tid %u\n", | ||
235 | mgmt->sa, tid); | ||
236 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
237 | goto end; | ||
238 | } | ||
239 | |||
240 | /* prepare A-MPDU MLME for Rx aggregation */ | ||
241 | sta->ampdu_mlme.tid_rx[tid] = | ||
242 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | ||
243 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
244 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
245 | if (net_ratelimit()) | ||
246 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
247 | tid); | ||
248 | #endif | ||
249 | goto end; | ||
250 | } | ||
251 | /* rx timer */ | ||
252 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
253 | sta_rx_agg_session_timer_expired; | ||
254 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
255 | (unsigned long)&sta->timer_to_tid[tid]; | ||
256 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
257 | |||
258 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
259 | |||
260 | /* prepare reordering buffer */ | ||
261 | tid_agg_rx->reorder_buf = | ||
262 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); | ||
263 | if (!tid_agg_rx->reorder_buf) { | ||
264 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
265 | if (net_ratelimit()) | ||
266 | printk(KERN_ERR "can not allocate reordering buffer " | ||
267 | "to tid %d\n", tid); | ||
268 | #endif | ||
269 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
270 | goto end; | ||
271 | } | ||
272 | |||
273 | if (local->ops->ampdu_action) | ||
274 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, | ||
275 | &sta->sta, tid, &start_seq_num); | ||
276 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
277 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | ||
278 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
279 | |||
280 | if (ret) { | ||
281 | kfree(tid_agg_rx->reorder_buf); | ||
282 | kfree(tid_agg_rx); | ||
283 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
284 | goto end; | ||
285 | } | ||
286 | |||
287 | /* change state and send addba resp */ | ||
288 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | ||
289 | tid_agg_rx->dialog_token = dialog_token; | ||
290 | tid_agg_rx->ssn = start_seq_num; | ||
291 | tid_agg_rx->head_seq_num = start_seq_num; | ||
292 | tid_agg_rx->buf_size = buf_size; | ||
293 | tid_agg_rx->timeout = timeout; | ||
294 | tid_agg_rx->stored_mpdu_num = 0; | ||
295 | status = WLAN_STATUS_SUCCESS; | ||
296 | end: | ||
297 | spin_unlock_bh(&sta->lock); | ||
298 | |||
299 | end_no_lock: | ||
300 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, | ||
301 | dialog_token, status, 1, buf_size, timeout); | ||
302 | } | ||
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c new file mode 100644 index 000000000000..1232d9f01ca9 --- /dev/null +++ b/net/mac80211/agg-tx.c | |||
@@ -0,0 +1,636 @@ | |||
1 | /* | ||
2 | * HT handling | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2007-2009, Intel Corporation | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/ieee80211.h> | ||
17 | #include <net/mac80211.h> | ||
18 | #include "ieee80211_i.h" | ||
19 | #include "wme.h" | ||
20 | |||
21 | /** | ||
22 | * DOC: TX aggregation | ||
23 | * | ||
24 | * Aggregation on the TX side requires setting the hardware flag | ||
25 | * %IEEE80211_HW_AMPDU_AGGREGATION as well as, if present, the @ampdu_queues | ||
26 | * hardware parameter to the number of hardware AMPDU queues. If there are no | ||
27 | * hardware queues then the driver will (currently) have to do all frame | ||
28 | * buffering. | ||
29 | * | ||
30 | * When TX aggregation is started by some subsystem (usually the rate control | ||
31 | * algorithm would be appropriate) by calling the | ||
32 | * ieee80211_start_tx_ba_session() function, the driver will be notified via | ||
33 | * its @ampdu_action function, with the %IEEE80211_AMPDU_TX_START action. | ||
34 | * | ||
35 | * In response to that, the driver is later required to call the | ||
36 | * ieee80211_start_tx_ba_cb() (or ieee80211_start_tx_ba_cb_irqsafe()) | ||
37 | * function, which will start the aggregation session. | ||
38 | * | ||
39 | * Similarly, when the aggregation session is stopped by | ||
40 | * ieee80211_stop_tx_ba_session(), the driver's @ampdu_action function will | ||
41 | * be called with the action %IEEE80211_AMPDU_TX_STOP. In this case, the | ||
42 | * call must not fail, and the driver must later call ieee80211_stop_tx_ba_cb() | ||
43 | * (or ieee80211_stop_tx_ba_cb_irqsafe()). | ||
44 | */ | ||
45 | |||
46 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | ||
47 | const u8 *da, u16 tid, | ||
48 | u8 dialog_token, u16 start_seq_num, | ||
49 | u16 agg_size, u16 timeout) | ||
50 | { | ||
51 | struct ieee80211_local *local = sdata->local; | ||
52 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
53 | struct sk_buff *skb; | ||
54 | struct ieee80211_mgmt *mgmt; | ||
55 | u16 capab; | ||
56 | |||
57 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
58 | |||
59 | if (!skb) { | ||
60 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
61 | "for addba request frame\n", sdata->dev->name); | ||
62 | return; | ||
63 | } | ||
64 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
65 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
66 | memset(mgmt, 0, 24); | ||
67 | memcpy(mgmt->da, da, ETH_ALEN); | ||
68 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
69 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
70 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
71 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
72 | else | ||
73 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
74 | |||
75 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
76 | IEEE80211_STYPE_ACTION); | ||
77 | |||
78 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); | ||
79 | |||
80 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
81 | mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; | ||
82 | |||
83 | mgmt->u.action.u.addba_req.dialog_token = dialog_token; | ||
84 | capab = (u16)(1 << 1); /* bit 1 aggregation policy */ | ||
85 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
86 | capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ | ||
87 | |||
88 | mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); | ||
89 | |||
90 | mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); | ||
91 | mgmt->u.action.u.addba_req.start_seq_num = | ||
92 | cpu_to_le16(start_seq_num << 4); | ||
93 | |||
94 | ieee80211_tx_skb(sdata, skb, 1); | ||
95 | } | ||
96 | |||
97 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) | ||
98 | { | ||
99 | struct ieee80211_local *local = sdata->local; | ||
100 | struct sk_buff *skb; | ||
101 | struct ieee80211_bar *bar; | ||
102 | u16 bar_control = 0; | ||
103 | |||
104 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | ||
105 | if (!skb) { | ||
106 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
107 | "bar frame\n", sdata->dev->name); | ||
108 | return; | ||
109 | } | ||
110 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
111 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | ||
112 | memset(bar, 0, sizeof(*bar)); | ||
113 | bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | ||
114 | IEEE80211_STYPE_BACK_REQ); | ||
115 | memcpy(bar->ra, ra, ETH_ALEN); | ||
116 | memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); | ||
117 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | ||
118 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | ||
119 | bar_control |= (u16)(tid << 12); | ||
120 | bar->control = cpu_to_le16(bar_control); | ||
121 | bar->start_seq_num = cpu_to_le16(ssn); | ||
122 | |||
123 | ieee80211_tx_skb(sdata, skb, 0); | ||
124 | } | ||
125 | |||
126 | static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | ||
127 | enum ieee80211_back_parties initiator) | ||
128 | { | ||
129 | struct ieee80211_local *local = sta->local; | ||
130 | int ret; | ||
131 | u8 *state; | ||
132 | |||
133 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
134 | |||
135 | if (local->hw.ampdu_queues) | ||
136 | ieee80211_stop_queue(&local->hw, sta->tid_to_tx_q[tid]); | ||
137 | |||
138 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
139 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
140 | |||
141 | ret = local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_STOP, | ||
142 | &sta->sta, tid, NULL); | ||
143 | |||
144 | /* HW shall not deny going back to legacy */ | ||
145 | if (WARN_ON(ret)) { | ||
146 | *state = HT_AGG_STATE_OPERATIONAL; | ||
147 | if (local->hw.ampdu_queues) | ||
148 | ieee80211_wake_queue(&local->hw, sta->tid_to_tx_q[tid]); | ||
149 | } | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * After sending add Block Ack request we activated a timer until | ||
156 | * add Block Ack response will arrive from the recipient. | ||
157 | * If this timer expires sta_addba_resp_timer_expired will be executed. | ||
158 | */ | ||
159 | static void sta_addba_resp_timer_expired(unsigned long data) | ||
160 | { | ||
161 | /* not an elegant detour, but there is no choice as the timer passes | ||
162 | * only one argument, and both sta_info and TID are needed, so init | ||
163 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
164 | * array gives the sta through container_of */ | ||
165 | u16 tid = *(u8 *)data; | ||
166 | struct sta_info *sta = container_of((void *)data, | ||
167 | struct sta_info, timer_to_tid[tid]); | ||
168 | u8 *state; | ||
169 | |||
170 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
171 | |||
172 | /* check if the TID waits for addBA response */ | ||
173 | spin_lock_bh(&sta->lock); | ||
174 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
175 | spin_unlock_bh(&sta->lock); | ||
176 | *state = HT_AGG_STATE_IDLE; | ||
177 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
178 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | ||
179 | "expecting addBA response there", tid); | ||
180 | #endif | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
185 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | ||
186 | #endif | ||
187 | |||
188 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); | ||
189 | spin_unlock_bh(&sta->lock); | ||
190 | } | ||
191 | |||
192 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
193 | { | ||
194 | struct ieee80211_local *local = hw_to_local(hw); | ||
195 | struct sta_info *sta; | ||
196 | struct ieee80211_sub_if_data *sdata; | ||
197 | u16 start_seq_num; | ||
198 | u8 *state; | ||
199 | int ret = 0; | ||
200 | |||
201 | if (WARN_ON(!local->ops->ampdu_action)) | ||
202 | return -EINVAL; | ||
203 | |||
204 | if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) | ||
205 | return -EINVAL; | ||
206 | |||
207 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
208 | printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", | ||
209 | ra, tid); | ||
210 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
211 | |||
212 | rcu_read_lock(); | ||
213 | |||
214 | sta = sta_info_get(local, ra); | ||
215 | if (!sta) { | ||
216 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
217 | printk(KERN_DEBUG "Could not find the station\n"); | ||
218 | #endif | ||
219 | ret = -ENOENT; | ||
220 | goto exit; | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * The aggregation code is not prepared to handle | ||
225 | * anything but STA/AP due to the BSSID handling. | ||
226 | * IBSS could work in the code but isn't supported | ||
227 | * by drivers or the standard. | ||
228 | */ | ||
229 | if (sta->sdata->vif.type != NL80211_IFTYPE_STATION && | ||
230 | sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
231 | sta->sdata->vif.type != NL80211_IFTYPE_AP) { | ||
232 | ret = -EINVAL; | ||
233 | goto exit; | ||
234 | } | ||
235 | |||
236 | spin_lock_bh(&sta->lock); | ||
237 | |||
238 | /* we have tried too many times, receiver does not want A-MPDU */ | ||
239 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | ||
240 | ret = -EBUSY; | ||
241 | goto err_unlock_sta; | ||
242 | } | ||
243 | |||
244 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
245 | /* check if the TID is not in aggregation flow already */ | ||
246 | if (*state != HT_AGG_STATE_IDLE) { | ||
247 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
248 | printk(KERN_DEBUG "BA request denied - session is not " | ||
249 | "idle on tid %u\n", tid); | ||
250 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
251 | ret = -EAGAIN; | ||
252 | goto err_unlock_sta; | ||
253 | } | ||
254 | |||
255 | /* prepare A-MPDU MLME for Tx aggregation */ | ||
256 | sta->ampdu_mlme.tid_tx[tid] = | ||
257 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | ||
258 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
259 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
260 | if (net_ratelimit()) | ||
261 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
262 | tid); | ||
263 | #endif | ||
264 | ret = -ENOMEM; | ||
265 | goto err_unlock_sta; | ||
266 | } | ||
267 | /* Tx timer */ | ||
268 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | ||
269 | sta_addba_resp_timer_expired; | ||
270 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | ||
271 | (unsigned long)&sta->timer_to_tid[tid]; | ||
272 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
273 | |||
274 | if (hw->ampdu_queues) { | ||
275 | /* create a new queue for this aggregation */ | ||
276 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | ||
277 | |||
278 | /* case no queue is available to aggregation | ||
279 | * don't switch to aggregation */ | ||
280 | if (ret) { | ||
281 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
282 | printk(KERN_DEBUG "BA request denied - " | ||
283 | "queue unavailable for tid %d\n", tid); | ||
284 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
285 | goto err_unlock_queue; | ||
286 | } | ||
287 | } | ||
288 | sdata = sta->sdata; | ||
289 | |||
290 | /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the | ||
291 | * call back right away, it must see that the flow has begun */ | ||
292 | *state |= HT_ADDBA_REQUESTED_MSK; | ||
293 | |||
294 | /* This is slightly racy because the queue isn't stopped */ | ||
295 | start_seq_num = sta->tid_seq[tid]; | ||
296 | |||
297 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, | ||
298 | &sta->sta, tid, &start_seq_num); | ||
299 | |||
300 | if (ret) { | ||
301 | /* No need to requeue the packets in the agg queue, since we | ||
302 | * held the tx lock: no packet could be enqueued to the newly | ||
303 | * allocated queue */ | ||
304 | if (hw->ampdu_queues) | ||
305 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | ||
306 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
307 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
308 | " tid %d\n", tid); | ||
309 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
310 | *state = HT_AGG_STATE_IDLE; | ||
311 | goto err_unlock_queue; | ||
312 | } | ||
313 | |||
314 | /* Will put all the packets in the new SW queue */ | ||
315 | if (hw->ampdu_queues) | ||
316 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | ||
317 | spin_unlock_bh(&sta->lock); | ||
318 | |||
319 | /* send an addBA request */ | ||
320 | sta->ampdu_mlme.dialog_token_allocator++; | ||
321 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = | ||
322 | sta->ampdu_mlme.dialog_token_allocator; | ||
323 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | ||
324 | |||
325 | |||
326 | ieee80211_send_addba_request(sta->sdata, ra, tid, | ||
327 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | ||
328 | sta->ampdu_mlme.tid_tx[tid]->ssn, | ||
329 | 0x40, 5000); | ||
330 | /* activate the timer for the recipient's addBA response */ | ||
331 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | ||
332 | jiffies + ADDBA_RESP_INTERVAL; | ||
333 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
334 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
335 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
336 | #endif | ||
337 | goto exit; | ||
338 | |||
339 | err_unlock_queue: | ||
340 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
341 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
342 | ret = -EBUSY; | ||
343 | err_unlock_sta: | ||
344 | spin_unlock_bh(&sta->lock); | ||
345 | exit: | ||
346 | rcu_read_unlock(); | ||
347 | return ret; | ||
348 | } | ||
349 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | ||
350 | |||
351 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
352 | { | ||
353 | struct ieee80211_local *local = hw_to_local(hw); | ||
354 | struct sta_info *sta; | ||
355 | u8 *state; | ||
356 | |||
357 | if (tid >= STA_TID_NUM) { | ||
358 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
359 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
360 | tid, STA_TID_NUM); | ||
361 | #endif | ||
362 | return; | ||
363 | } | ||
364 | |||
365 | rcu_read_lock(); | ||
366 | sta = sta_info_get(local, ra); | ||
367 | if (!sta) { | ||
368 | rcu_read_unlock(); | ||
369 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
370 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | ||
371 | #endif | ||
372 | return; | ||
373 | } | ||
374 | |||
375 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
376 | spin_lock_bh(&sta->lock); | ||
377 | |||
378 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
379 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
380 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | ||
381 | *state); | ||
382 | #endif | ||
383 | spin_unlock_bh(&sta->lock); | ||
384 | rcu_read_unlock(); | ||
385 | return; | ||
386 | } | ||
387 | |||
388 | WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); | ||
389 | |||
390 | *state |= HT_ADDBA_DRV_READY_MSK; | ||
391 | |||
392 | if (*state == HT_AGG_STATE_OPERATIONAL) { | ||
393 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
394 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | ||
395 | #endif | ||
396 | if (hw->ampdu_queues) | ||
397 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
398 | } | ||
399 | spin_unlock_bh(&sta->lock); | ||
400 | rcu_read_unlock(); | ||
401 | } | ||
402 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | ||
403 | |||
404 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
405 | const u8 *ra, u16 tid) | ||
406 | { | ||
407 | struct ieee80211_local *local = hw_to_local(hw); | ||
408 | struct ieee80211_ra_tid *ra_tid; | ||
409 | struct sk_buff *skb = dev_alloc_skb(0); | ||
410 | |||
411 | if (unlikely(!skb)) { | ||
412 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
413 | if (net_ratelimit()) | ||
414 | printk(KERN_WARNING "%s: Not enough memory, " | ||
415 | "dropping start BA session", skb->dev->name); | ||
416 | #endif | ||
417 | return; | ||
418 | } | ||
419 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
420 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
421 | ra_tid->tid = tid; | ||
422 | |||
423 | skb->pkt_type = IEEE80211_ADDBA_MSG; | ||
424 | skb_queue_tail(&local->skb_queue, skb); | ||
425 | tasklet_schedule(&local->tasklet); | ||
426 | } | ||
427 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | ||
428 | |||
429 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | ||
430 | enum ieee80211_back_parties initiator) | ||
431 | { | ||
432 | u8 *state; | ||
433 | int ret; | ||
434 | |||
435 | /* check if the TID is in aggregation */ | ||
436 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
437 | spin_lock_bh(&sta->lock); | ||
438 | |||
439 | if (*state != HT_AGG_STATE_OPERATIONAL) { | ||
440 | ret = -ENOENT; | ||
441 | goto unlock; | ||
442 | } | ||
443 | |||
444 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
445 | printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", | ||
446 | sta->sta.addr, tid); | ||
447 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
448 | |||
449 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator); | ||
450 | |||
451 | unlock: | ||
452 | spin_unlock_bh(&sta->lock); | ||
453 | return ret; | ||
454 | } | ||
455 | |||
456 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | ||
457 | u8 *ra, u16 tid, | ||
458 | enum ieee80211_back_parties initiator) | ||
459 | { | ||
460 | struct ieee80211_local *local = hw_to_local(hw); | ||
461 | struct sta_info *sta; | ||
462 | int ret = 0; | ||
463 | |||
464 | if (WARN_ON(!local->ops->ampdu_action)) | ||
465 | return -EINVAL; | ||
466 | |||
467 | if (tid >= STA_TID_NUM) | ||
468 | return -EINVAL; | ||
469 | |||
470 | rcu_read_lock(); | ||
471 | sta = sta_info_get(local, ra); | ||
472 | if (!sta) { | ||
473 | rcu_read_unlock(); | ||
474 | return -ENOENT; | ||
475 | } | ||
476 | |||
477 | ret = __ieee80211_stop_tx_ba_session(sta, tid, initiator); | ||
478 | rcu_read_unlock(); | ||
479 | return ret; | ||
480 | } | ||
481 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | ||
482 | |||
483 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | ||
484 | { | ||
485 | struct ieee80211_local *local = hw_to_local(hw); | ||
486 | struct sta_info *sta; | ||
487 | u8 *state; | ||
488 | int agg_queue; | ||
489 | |||
490 | if (tid >= STA_TID_NUM) { | ||
491 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
492 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
493 | tid, STA_TID_NUM); | ||
494 | #endif | ||
495 | return; | ||
496 | } | ||
497 | |||
498 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
499 | printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n", | ||
500 | ra, tid); | ||
501 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
502 | |||
503 | rcu_read_lock(); | ||
504 | sta = sta_info_get(local, ra); | ||
505 | if (!sta) { | ||
506 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
507 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | ||
508 | #endif | ||
509 | rcu_read_unlock(); | ||
510 | return; | ||
511 | } | ||
512 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
513 | |||
514 | /* NOTE: no need to use sta->lock in this state check, as | ||
515 | * ieee80211_stop_tx_ba_session will let only one stop call to | ||
516 | * pass through per sta/tid | ||
517 | */ | ||
518 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | ||
519 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
520 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | ||
521 | #endif | ||
522 | rcu_read_unlock(); | ||
523 | return; | ||
524 | } | ||
525 | |||
526 | if (*state & HT_AGG_STATE_INITIATOR_MSK) | ||
527 | ieee80211_send_delba(sta->sdata, ra, tid, | ||
528 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | ||
529 | |||
530 | if (hw->ampdu_queues) { | ||
531 | agg_queue = sta->tid_to_tx_q[tid]; | ||
532 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); | ||
533 | |||
534 | /* We just requeued the all the frames that were in the | ||
535 | * removed queue, and since we might miss a softirq we do | ||
536 | * netif_schedule_queue. ieee80211_wake_queue is not used | ||
537 | * here as this queue is not necessarily stopped | ||
538 | */ | ||
539 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, | ||
540 | agg_queue)); | ||
541 | } | ||
542 | spin_lock_bh(&sta->lock); | ||
543 | *state = HT_AGG_STATE_IDLE; | ||
544 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
545 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
546 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
547 | spin_unlock_bh(&sta->lock); | ||
548 | |||
549 | rcu_read_unlock(); | ||
550 | } | ||
551 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | ||
552 | |||
553 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
554 | const u8 *ra, u16 tid) | ||
555 | { | ||
556 | struct ieee80211_local *local = hw_to_local(hw); | ||
557 | struct ieee80211_ra_tid *ra_tid; | ||
558 | struct sk_buff *skb = dev_alloc_skb(0); | ||
559 | |||
560 | if (unlikely(!skb)) { | ||
561 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
562 | if (net_ratelimit()) | ||
563 | printk(KERN_WARNING "%s: Not enough memory, " | ||
564 | "dropping stop BA session", skb->dev->name); | ||
565 | #endif | ||
566 | return; | ||
567 | } | ||
568 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
569 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
570 | ra_tid->tid = tid; | ||
571 | |||
572 | skb->pkt_type = IEEE80211_DELBA_MSG; | ||
573 | skb_queue_tail(&local->skb_queue, skb); | ||
574 | tasklet_schedule(&local->tasklet); | ||
575 | } | ||
576 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); | ||
577 | |||
578 | |||
579 | void ieee80211_process_addba_resp(struct ieee80211_local *local, | ||
580 | struct sta_info *sta, | ||
581 | struct ieee80211_mgmt *mgmt, | ||
582 | size_t len) | ||
583 | { | ||
584 | struct ieee80211_hw *hw = &local->hw; | ||
585 | u16 capab; | ||
586 | u16 tid, start_seq_num; | ||
587 | u8 *state; | ||
588 | |||
589 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | ||
590 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
591 | |||
592 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
593 | |||
594 | spin_lock_bh(&sta->lock); | ||
595 | |||
596 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
597 | spin_unlock_bh(&sta->lock); | ||
598 | return; | ||
599 | } | ||
600 | |||
601 | if (mgmt->u.action.u.addba_resp.dialog_token != | ||
602 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | ||
603 | spin_unlock_bh(&sta->lock); | ||
604 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
605 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | ||
606 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
607 | return; | ||
608 | } | ||
609 | |||
610 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
611 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
612 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | ||
613 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
614 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | ||
615 | == WLAN_STATUS_SUCCESS) { | ||
616 | *state |= HT_ADDBA_RECEIVED_MSK; | ||
617 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
618 | |||
619 | if (*state == HT_AGG_STATE_OPERATIONAL && | ||
620 | local->hw.ampdu_queues) | ||
621 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
622 | |||
623 | if (local->ops->ampdu_action) { | ||
624 | (void)local->ops->ampdu_action(hw, | ||
625 | IEEE80211_AMPDU_TX_RESUME, | ||
626 | &sta->sta, tid, &start_seq_num); | ||
627 | } | ||
628 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
629 | printk(KERN_DEBUG "Resuming TX aggregation for tid %d\n", tid); | ||
630 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
631 | } else { | ||
632 | sta->ampdu_mlme.addba_req_num[tid]++; | ||
633 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); | ||
634 | } | ||
635 | spin_unlock_bh(&sta->lock); | ||
636 | } | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9d4e4d846ec1..c8d969be440b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -133,6 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
133 | case WLAN_CIPHER_SUITE_CCMP: | 133 | case WLAN_CIPHER_SUITE_CCMP: |
134 | alg = ALG_CCMP; | 134 | alg = ALG_CCMP; |
135 | break; | 135 | break; |
136 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
137 | alg = ALG_AES_CMAC; | ||
138 | break; | ||
136 | default: | 139 | default: |
137 | return -EINVAL; | 140 | return -EINVAL; |
138 | } | 141 | } |
@@ -275,6 +278,17 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
275 | else | 278 | else |
276 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | 279 | params.cipher = WLAN_CIPHER_SUITE_WEP104; |
277 | break; | 280 | break; |
281 | case ALG_AES_CMAC: | ||
282 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | ||
283 | seq[0] = key->u.aes_cmac.tx_pn[5]; | ||
284 | seq[1] = key->u.aes_cmac.tx_pn[4]; | ||
285 | seq[2] = key->u.aes_cmac.tx_pn[3]; | ||
286 | seq[3] = key->u.aes_cmac.tx_pn[2]; | ||
287 | seq[4] = key->u.aes_cmac.tx_pn[1]; | ||
288 | seq[5] = key->u.aes_cmac.tx_pn[0]; | ||
289 | params.seq = seq; | ||
290 | params.seq_len = 6; | ||
291 | break; | ||
278 | } | 292 | } |
279 | 293 | ||
280 | params.key = key->conf.key; | 294 | params.key = key->conf.key; |
@@ -304,6 +318,22 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
304 | return 0; | 318 | return 0; |
305 | } | 319 | } |
306 | 320 | ||
321 | static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, | ||
322 | struct net_device *dev, | ||
323 | u8 key_idx) | ||
324 | { | ||
325 | struct ieee80211_sub_if_data *sdata; | ||
326 | |||
327 | rcu_read_lock(); | ||
328 | |||
329 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
330 | ieee80211_set_default_mgmt_key(sdata, key_idx); | ||
331 | |||
332 | rcu_read_unlock(); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
307 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 337 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
308 | { | 338 | { |
309 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 339 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -493,7 +523,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
493 | 523 | ||
494 | kfree(old); | 524 | kfree(old); |
495 | 525 | ||
496 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 526 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | |
527 | IEEE80211_IFCC_BEACON_ENABLED); | ||
497 | } | 528 | } |
498 | 529 | ||
499 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 530 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
@@ -553,7 +584,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
553 | synchronize_rcu(); | 584 | synchronize_rcu(); |
554 | kfree(old); | 585 | kfree(old); |
555 | 586 | ||
556 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 587 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); |
557 | } | 588 | } |
558 | 589 | ||
559 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ | 590 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ |
@@ -630,6 +661,10 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
630 | sta->flags &= ~WLAN_STA_WME; | 661 | sta->flags &= ~WLAN_STA_WME; |
631 | if (params->station_flags & STATION_FLAG_WME) | 662 | if (params->station_flags & STATION_FLAG_WME) |
632 | sta->flags |= WLAN_STA_WME; | 663 | sta->flags |= WLAN_STA_WME; |
664 | |||
665 | sta->flags &= ~WLAN_STA_MFP; | ||
666 | if (params->station_flags & STATION_FLAG_MFP) | ||
667 | sta->flags |= WLAN_STA_MFP; | ||
633 | spin_unlock_bh(&sta->lock); | 668 | spin_unlock_bh(&sta->lock); |
634 | } | 669 | } |
635 | 670 | ||
@@ -1141,6 +1176,126 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1141 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1176 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1142 | } | 1177 | } |
1143 | 1178 | ||
1179 | static int set_mgmt_extra_ie_sta(struct ieee80211_sub_if_data *sdata, | ||
1180 | u8 subtype, u8 *ies, size_t ies_len) | ||
1181 | { | ||
1182 | struct ieee80211_local *local = sdata->local; | ||
1183 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
1184 | |||
1185 | switch (subtype) { | ||
1186 | case IEEE80211_STYPE_PROBE_REQ >> 4: | ||
1187 | if (local->ops->hw_scan) | ||
1188 | break; | ||
1189 | kfree(ifsta->ie_probereq); | ||
1190 | ifsta->ie_probereq = ies; | ||
1191 | ifsta->ie_probereq_len = ies_len; | ||
1192 | return 0; | ||
1193 | case IEEE80211_STYPE_PROBE_RESP >> 4: | ||
1194 | kfree(ifsta->ie_proberesp); | ||
1195 | ifsta->ie_proberesp = ies; | ||
1196 | ifsta->ie_proberesp_len = ies_len; | ||
1197 | return 0; | ||
1198 | case IEEE80211_STYPE_AUTH >> 4: | ||
1199 | kfree(ifsta->ie_auth); | ||
1200 | ifsta->ie_auth = ies; | ||
1201 | ifsta->ie_auth_len = ies_len; | ||
1202 | return 0; | ||
1203 | case IEEE80211_STYPE_ASSOC_REQ >> 4: | ||
1204 | kfree(ifsta->ie_assocreq); | ||
1205 | ifsta->ie_assocreq = ies; | ||
1206 | ifsta->ie_assocreq_len = ies_len; | ||
1207 | return 0; | ||
1208 | case IEEE80211_STYPE_REASSOC_REQ >> 4: | ||
1209 | kfree(ifsta->ie_reassocreq); | ||
1210 | ifsta->ie_reassocreq = ies; | ||
1211 | ifsta->ie_reassocreq_len = ies_len; | ||
1212 | return 0; | ||
1213 | case IEEE80211_STYPE_DEAUTH >> 4: | ||
1214 | kfree(ifsta->ie_deauth); | ||
1215 | ifsta->ie_deauth = ies; | ||
1216 | ifsta->ie_deauth_len = ies_len; | ||
1217 | return 0; | ||
1218 | case IEEE80211_STYPE_DISASSOC >> 4: | ||
1219 | kfree(ifsta->ie_disassoc); | ||
1220 | ifsta->ie_disassoc = ies; | ||
1221 | ifsta->ie_disassoc_len = ies_len; | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | return -EOPNOTSUPP; | ||
1226 | } | ||
1227 | |||
1228 | static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy, | ||
1229 | struct net_device *dev, | ||
1230 | struct mgmt_extra_ie_params *params) | ||
1231 | { | ||
1232 | struct ieee80211_sub_if_data *sdata; | ||
1233 | u8 *ies; | ||
1234 | size_t ies_len; | ||
1235 | int ret = -EOPNOTSUPP; | ||
1236 | |||
1237 | if (params->ies) { | ||
1238 | ies = kmemdup(params->ies, params->ies_len, GFP_KERNEL); | ||
1239 | if (ies == NULL) | ||
1240 | return -ENOMEM; | ||
1241 | ies_len = params->ies_len; | ||
1242 | } else { | ||
1243 | ies = NULL; | ||
1244 | ies_len = 0; | ||
1245 | } | ||
1246 | |||
1247 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1248 | |||
1249 | switch (sdata->vif.type) { | ||
1250 | case NL80211_IFTYPE_STATION: | ||
1251 | case NL80211_IFTYPE_ADHOC: | ||
1252 | ret = set_mgmt_extra_ie_sta(sdata, params->subtype, | ||
1253 | ies, ies_len); | ||
1254 | break; | ||
1255 | default: | ||
1256 | ret = -EOPNOTSUPP; | ||
1257 | break; | ||
1258 | } | ||
1259 | |||
1260 | if (ret) | ||
1261 | kfree(ies); | ||
1262 | return ret; | ||
1263 | } | ||
1264 | |||
1265 | #ifdef CONFIG_PM | ||
1266 | static int ieee80211_suspend(struct wiphy *wiphy) | ||
1267 | { | ||
1268 | return __ieee80211_suspend(wiphy_priv(wiphy)); | ||
1269 | } | ||
1270 | |||
1271 | static int ieee80211_resume(struct wiphy *wiphy) | ||
1272 | { | ||
1273 | return __ieee80211_resume(wiphy_priv(wiphy)); | ||
1274 | } | ||
1275 | #else | ||
1276 | #define ieee80211_suspend NULL | ||
1277 | #define ieee80211_resume NULL | ||
1278 | #endif | ||
1279 | |||
1280 | static int ieee80211_scan(struct wiphy *wiphy, | ||
1281 | struct net_device *dev, | ||
1282 | struct cfg80211_scan_request *req) | ||
1283 | { | ||
1284 | struct ieee80211_sub_if_data *sdata; | ||
1285 | |||
1286 | if (!netif_running(dev)) | ||
1287 | return -ENETDOWN; | ||
1288 | |||
1289 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1290 | |||
1291 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
1292 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
1293 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
1294 | return -EOPNOTSUPP; | ||
1295 | |||
1296 | return ieee80211_request_scan(sdata, req); | ||
1297 | } | ||
1298 | |||
1144 | struct cfg80211_ops mac80211_config_ops = { | 1299 | struct cfg80211_ops mac80211_config_ops = { |
1145 | .add_virtual_intf = ieee80211_add_iface, | 1300 | .add_virtual_intf = ieee80211_add_iface, |
1146 | .del_virtual_intf = ieee80211_del_iface, | 1301 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1149,6 +1304,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1149 | .del_key = ieee80211_del_key, | 1304 | .del_key = ieee80211_del_key, |
1150 | .get_key = ieee80211_get_key, | 1305 | .get_key = ieee80211_get_key, |
1151 | .set_default_key = ieee80211_config_default_key, | 1306 | .set_default_key = ieee80211_config_default_key, |
1307 | .set_default_mgmt_key = ieee80211_config_default_mgmt_key, | ||
1152 | .add_beacon = ieee80211_add_beacon, | 1308 | .add_beacon = ieee80211_add_beacon, |
1153 | .set_beacon = ieee80211_set_beacon, | 1309 | .set_beacon = ieee80211_set_beacon, |
1154 | .del_beacon = ieee80211_del_beacon, | 1310 | .del_beacon = ieee80211_del_beacon, |
@@ -1169,4 +1325,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1169 | .change_bss = ieee80211_change_bss, | 1325 | .change_bss = ieee80211_change_bss, |
1170 | .set_txq_params = ieee80211_set_txq_params, | 1326 | .set_txq_params = ieee80211_set_txq_params, |
1171 | .set_channel = ieee80211_set_channel, | 1327 | .set_channel = ieee80211_set_channel, |
1328 | .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie, | ||
1329 | .suspend = ieee80211_suspend, | ||
1330 | .resume = ieee80211_resume, | ||
1331 | .scan = ieee80211_scan, | ||
1172 | }; | 1332 | }; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 2697a2fe608f..e37f557de3f3 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -57,11 +57,62 @@ DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", | |||
57 | local->hw.conf.long_frame_max_tx_count); | 57 | local->hw.conf.long_frame_max_tx_count); |
58 | DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", | 58 | DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", |
59 | local->total_ps_buffered); | 59 | local->total_ps_buffered); |
60 | DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x", | 60 | DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", |
61 | local->wep_iv & 0xffffff); | 61 | local->wep_iv & 0xffffff); |
62 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", | 62 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", |
63 | local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>"); | 63 | local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>"); |
64 | 64 | ||
65 | static ssize_t tsf_read(struct file *file, char __user *user_buf, | ||
66 | size_t count, loff_t *ppos) | ||
67 | { | ||
68 | struct ieee80211_local *local = file->private_data; | ||
69 | u64 tsf = 0; | ||
70 | char buf[100]; | ||
71 | |||
72 | if (local->ops->get_tsf) | ||
73 | tsf = local->ops->get_tsf(local_to_hw(local)); | ||
74 | |||
75 | snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf); | ||
76 | |||
77 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); | ||
78 | } | ||
79 | |||
80 | static ssize_t tsf_write(struct file *file, | ||
81 | const char __user *user_buf, | ||
82 | size_t count, loff_t *ppos) | ||
83 | { | ||
84 | struct ieee80211_local *local = file->private_data; | ||
85 | unsigned long long tsf; | ||
86 | char buf[100]; | ||
87 | size_t len; | ||
88 | |||
89 | len = min(count, sizeof(buf) - 1); | ||
90 | if (copy_from_user(buf, user_buf, len)) | ||
91 | return -EFAULT; | ||
92 | buf[len] = '\0'; | ||
93 | |||
94 | if (strncmp(buf, "reset", 5) == 0) { | ||
95 | if (local->ops->reset_tsf) { | ||
96 | local->ops->reset_tsf(local_to_hw(local)); | ||
97 | printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); | ||
98 | } | ||
99 | } else { | ||
100 | tsf = simple_strtoul(buf, NULL, 0); | ||
101 | if (local->ops->set_tsf) { | ||
102 | local->ops->set_tsf(local_to_hw(local), tsf); | ||
103 | printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | return count; | ||
108 | } | ||
109 | |||
110 | static const struct file_operations tsf_ops = { | ||
111 | .read = tsf_read, | ||
112 | .write = tsf_write, | ||
113 | .open = mac80211_open_file_generic | ||
114 | }; | ||
115 | |||
65 | /* statistics stuff */ | 116 | /* statistics stuff */ |
66 | 117 | ||
67 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ | 118 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ |
@@ -136,8 +187,6 @@ DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u", | |||
136 | local->dot11MulticastReceivedFrameCount); | 187 | local->dot11MulticastReceivedFrameCount); |
137 | DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u", | 188 | DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u", |
138 | local->dot11TransmittedFrameCount); | 189 | local->dot11TransmittedFrameCount); |
139 | DEBUGFS_STATS_FILE(wep_undecryptable_count, 20, "%u", | ||
140 | local->dot11WEPUndecryptableCount); | ||
141 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 190 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
142 | DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u", | 191 | DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u", |
143 | local->tx_handlers_drop); | 192 | local->tx_handlers_drop); |
@@ -204,6 +253,7 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
204 | DEBUGFS_ADD(long_retry_limit); | 253 | DEBUGFS_ADD(long_retry_limit); |
205 | DEBUGFS_ADD(total_ps_buffered); | 254 | DEBUGFS_ADD(total_ps_buffered); |
206 | DEBUGFS_ADD(wep_iv); | 255 | DEBUGFS_ADD(wep_iv); |
256 | DEBUGFS_ADD(tsf); | ||
207 | 257 | ||
208 | statsd = debugfs_create_dir("statistics", phyd); | 258 | statsd = debugfs_create_dir("statistics", phyd); |
209 | local->debugfs.statistics = statsd; | 259 | local->debugfs.statistics = statsd; |
@@ -221,7 +271,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
221 | DEBUGFS_STATS_ADD(received_fragment_count); | 271 | DEBUGFS_STATS_ADD(received_fragment_count); |
222 | DEBUGFS_STATS_ADD(multicast_received_frame_count); | 272 | DEBUGFS_STATS_ADD(multicast_received_frame_count); |
223 | DEBUGFS_STATS_ADD(transmitted_frame_count); | 273 | DEBUGFS_STATS_ADD(transmitted_frame_count); |
224 | DEBUGFS_STATS_ADD(wep_undecryptable_count); | ||
225 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 274 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
226 | DEBUGFS_STATS_ADD(tx_handlers_drop); | 275 | DEBUGFS_STATS_ADD(tx_handlers_drop); |
227 | DEBUGFS_STATS_ADD(tx_handlers_queued); | 276 | DEBUGFS_STATS_ADD(tx_handlers_queued); |
@@ -258,6 +307,7 @@ void debugfs_hw_del(struct ieee80211_local *local) | |||
258 | DEBUGFS_DEL(long_retry_limit); | 307 | DEBUGFS_DEL(long_retry_limit); |
259 | DEBUGFS_DEL(total_ps_buffered); | 308 | DEBUGFS_DEL(total_ps_buffered); |
260 | DEBUGFS_DEL(wep_iv); | 309 | DEBUGFS_DEL(wep_iv); |
310 | DEBUGFS_DEL(tsf); | ||
261 | 311 | ||
262 | DEBUGFS_STATS_DEL(transmitted_fragment_count); | 312 | DEBUGFS_STATS_DEL(transmitted_fragment_count); |
263 | DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); | 313 | DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); |
@@ -268,7 +318,6 @@ void debugfs_hw_del(struct ieee80211_local *local) | |||
268 | DEBUGFS_STATS_DEL(received_fragment_count); | 318 | DEBUGFS_STATS_DEL(received_fragment_count); |
269 | DEBUGFS_STATS_DEL(multicast_received_frame_count); | 319 | DEBUGFS_STATS_DEL(multicast_received_frame_count); |
270 | DEBUGFS_STATS_DEL(transmitted_frame_count); | 320 | DEBUGFS_STATS_DEL(transmitted_frame_count); |
271 | DEBUGFS_STATS_DEL(wep_undecryptable_count); | ||
272 | DEBUGFS_STATS_DEL(num_scans); | 321 | DEBUGFS_STATS_DEL(num_scans); |
273 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 322 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
274 | DEBUGFS_STATS_DEL(tx_handlers_drop); | 323 | DEBUGFS_STATS_DEL(tx_handlers_drop); |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 6424ac565ae0..99c752588b30 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -76,6 +76,9 @@ static ssize_t key_algorithm_read(struct file *file, | |||
76 | case ALG_CCMP: | 76 | case ALG_CCMP: |
77 | alg = "CCMP\n"; | 77 | alg = "CCMP\n"; |
78 | break; | 78 | break; |
79 | case ALG_AES_CMAC: | ||
80 | alg = "AES-128-CMAC\n"; | ||
81 | break; | ||
79 | default: | 82 | default: |
80 | return 0; | 83 | return 0; |
81 | } | 84 | } |
@@ -105,6 +108,12 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | |||
105 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 108 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
106 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); | 109 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); |
107 | break; | 110 | break; |
111 | case ALG_AES_CMAC: | ||
112 | tpn = key->u.aes_cmac.tx_pn; | ||
113 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | ||
114 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], | ||
115 | tpn[5]); | ||
116 | break; | ||
108 | default: | 117 | default: |
109 | return 0; | 118 | return 0; |
110 | } | 119 | } |
@@ -142,6 +151,14 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
142 | } | 151 | } |
143 | len = p - buf; | 152 | len = p - buf; |
144 | break; | 153 | break; |
154 | case ALG_AES_CMAC: | ||
155 | rpn = key->u.aes_cmac.rx_pn; | ||
156 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
157 | "%02x%02x%02x%02x%02x%02x\n", | ||
158 | rpn[0], rpn[1], rpn[2], | ||
159 | rpn[3], rpn[4], rpn[5]); | ||
160 | len = p - buf; | ||
161 | break; | ||
145 | default: | 162 | default: |
146 | return 0; | 163 | return 0; |
147 | } | 164 | } |
@@ -156,13 +173,40 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf, | |||
156 | char buf[20]; | 173 | char buf[20]; |
157 | int len; | 174 | int len; |
158 | 175 | ||
159 | if (key->conf.alg != ALG_CCMP) | 176 | switch (key->conf.alg) { |
177 | case ALG_CCMP: | ||
178 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); | ||
179 | break; | ||
180 | case ALG_AES_CMAC: | ||
181 | len = scnprintf(buf, sizeof(buf), "%u\n", | ||
182 | key->u.aes_cmac.replays); | ||
183 | break; | ||
184 | default: | ||
160 | return 0; | 185 | return 0; |
161 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); | 186 | } |
162 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | 187 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); |
163 | } | 188 | } |
164 | KEY_OPS(replays); | 189 | KEY_OPS(replays); |
165 | 190 | ||
191 | static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, | ||
192 | size_t count, loff_t *ppos) | ||
193 | { | ||
194 | struct ieee80211_key *key = file->private_data; | ||
195 | char buf[20]; | ||
196 | int len; | ||
197 | |||
198 | switch (key->conf.alg) { | ||
199 | case ALG_AES_CMAC: | ||
200 | len = scnprintf(buf, sizeof(buf), "%u\n", | ||
201 | key->u.aes_cmac.icverrors); | ||
202 | break; | ||
203 | default: | ||
204 | return 0; | ||
205 | } | ||
206 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | ||
207 | } | ||
208 | KEY_OPS(icverrors); | ||
209 | |||
166 | static ssize_t key_key_read(struct file *file, char __user *userbuf, | 210 | static ssize_t key_key_read(struct file *file, char __user *userbuf, |
167 | size_t count, loff_t *ppos) | 211 | size_t count, loff_t *ppos) |
168 | { | 212 | { |
@@ -222,6 +266,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) | |||
222 | DEBUGFS_ADD(tx_spec); | 266 | DEBUGFS_ADD(tx_spec); |
223 | DEBUGFS_ADD(rx_spec); | 267 | DEBUGFS_ADD(rx_spec); |
224 | DEBUGFS_ADD(replays); | 268 | DEBUGFS_ADD(replays); |
269 | DEBUGFS_ADD(icverrors); | ||
225 | DEBUGFS_ADD(key); | 270 | DEBUGFS_ADD(key); |
226 | DEBUGFS_ADD(ifindex); | 271 | DEBUGFS_ADD(ifindex); |
227 | }; | 272 | }; |
@@ -243,6 +288,7 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | |||
243 | DEBUGFS_DEL(tx_spec); | 288 | DEBUGFS_DEL(tx_spec); |
244 | DEBUGFS_DEL(rx_spec); | 289 | DEBUGFS_DEL(rx_spec); |
245 | DEBUGFS_DEL(replays); | 290 | DEBUGFS_DEL(replays); |
291 | DEBUGFS_DEL(icverrors); | ||
246 | DEBUGFS_DEL(key); | 292 | DEBUGFS_DEL(key); |
247 | DEBUGFS_DEL(ifindex); | 293 | DEBUGFS_DEL(ifindex); |
248 | 294 | ||
@@ -280,6 +326,35 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) | |||
280 | sdata->common_debugfs.default_key = NULL; | 326 | sdata->common_debugfs.default_key = NULL; |
281 | } | 327 | } |
282 | 328 | ||
329 | void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | ||
330 | { | ||
331 | char buf[50]; | ||
332 | struct ieee80211_key *key; | ||
333 | |||
334 | if (!sdata->debugfsdir) | ||
335 | return; | ||
336 | |||
337 | /* this is running under the key lock */ | ||
338 | |||
339 | key = sdata->default_mgmt_key; | ||
340 | if (key) { | ||
341 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | ||
342 | sdata->common_debugfs.default_mgmt_key = | ||
343 | debugfs_create_symlink("default_mgmt_key", | ||
344 | sdata->debugfsdir, buf); | ||
345 | } else | ||
346 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | ||
347 | } | ||
348 | |||
349 | void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata) | ||
350 | { | ||
351 | if (!sdata) | ||
352 | return; | ||
353 | |||
354 | debugfs_remove(sdata->common_debugfs.default_mgmt_key); | ||
355 | sdata->common_debugfs.default_mgmt_key = NULL; | ||
356 | } | ||
357 | |||
283 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, | 358 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, |
284 | struct sta_info *sta) | 359 | struct sta_info *sta) |
285 | { | 360 | { |
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h index b1a3754ee240..54717b4e1371 100644 --- a/net/mac80211/debugfs_key.h +++ b/net/mac80211/debugfs_key.h | |||
@@ -6,6 +6,10 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key); | |||
6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); | 6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); |
7 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); | 7 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); |
8 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); | 8 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); |
9 | void ieee80211_debugfs_key_add_mgmt_default( | ||
10 | struct ieee80211_sub_if_data *sdata); | ||
11 | void ieee80211_debugfs_key_remove_mgmt_default( | ||
12 | struct ieee80211_sub_if_data *sdata); | ||
9 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, | 13 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, |
10 | struct sta_info *sta); | 14 | struct sta_info *sta); |
11 | #else | 15 | #else |
@@ -19,6 +23,12 @@ static inline void ieee80211_debugfs_key_add_default( | |||
19 | static inline void ieee80211_debugfs_key_remove_default( | 23 | static inline void ieee80211_debugfs_key_remove_default( |
20 | struct ieee80211_sub_if_data *sdata) | 24 | struct ieee80211_sub_if_data *sdata) |
21 | {} | 25 | {} |
26 | static inline void ieee80211_debugfs_key_add_mgmt_default( | ||
27 | struct ieee80211_sub_if_data *sdata) | ||
28 | {} | ||
29 | static inline void ieee80211_debugfs_key_remove_mgmt_default( | ||
30 | struct ieee80211_sub_if_data *sdata) | ||
31 | {} | ||
22 | static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, | 32 | static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, |
23 | struct sta_info *sta) | 33 | struct sta_info *sta) |
24 | {} | 34 | {} |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index a2fbe0131312..90230c718b5b 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -67,14 +67,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
67 | char buf[100]; | 67 | char buf[100]; |
68 | struct sta_info *sta = file->private_data; | 68 | struct sta_info *sta = file->private_data; |
69 | u32 staflags = get_sta_flags(sta); | 69 | u32 staflags = get_sta_flags(sta); |
70 | int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s", | 70 | int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s", |
71 | staflags & WLAN_STA_AUTH ? "AUTH\n" : "", | 71 | staflags & WLAN_STA_AUTH ? "AUTH\n" : "", |
72 | staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", | 72 | staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", |
73 | staflags & WLAN_STA_PS ? "PS\n" : "", | 73 | staflags & WLAN_STA_PS ? "PS\n" : "", |
74 | staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", | 74 | staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", |
75 | staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", | 75 | staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", |
76 | staflags & WLAN_STA_WME ? "WME\n" : "", | 76 | staflags & WLAN_STA_WME ? "WME\n" : "", |
77 | staflags & WLAN_STA_WDS ? "WDS\n" : ""); | 77 | staflags & WLAN_STA_WDS ? "WDS\n" : "", |
78 | staflags & WLAN_STA_MFP ? "MFP\n" : ""); | ||
78 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 79 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
79 | } | 80 | } |
80 | STA_OPS(flags); | 81 | STA_OPS(flags); |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index c5c0c5271096..82ea0b63a386 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include <net/wireless.h> | 17 | #include <net/wireless.h> |
18 | #include <net/mac80211.h> | 18 | #include <net/mac80211.h> |
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "sta_info.h" | ||
21 | #include "wme.h" | ||
22 | 20 | ||
23 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 21 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, |
24 | struct ieee80211_ht_cap *ht_cap_ie, | 22 | struct ieee80211_ht_cap *ht_cap_ie, |
@@ -130,14 +128,15 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
130 | } | 128 | } |
131 | } | 129 | } |
132 | 130 | ||
133 | ht_changed = local->hw.conf.ht.enabled != enable_ht || | 131 | ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || |
134 | channel_type != local->hw.conf.ht.channel_type; | 132 | channel_type != local->hw.conf.channel_type; |
135 | 133 | ||
136 | local->oper_channel_type = channel_type; | 134 | local->oper_channel_type = channel_type; |
137 | local->hw.conf.ht.enabled = enable_ht; | ||
138 | 135 | ||
139 | if (ht_changed) | 136 | if (ht_changed) { |
140 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); | 137 | /* channel_type change automatically detected */ |
138 | ieee80211_hw_config(local, 0); | ||
139 | } | ||
141 | 140 | ||
142 | /* disable HT */ | 141 | /* disable HT */ |
143 | if (!enable_ht) | 142 | if (!enable_ht) |
@@ -154,105 +153,20 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
154 | return changed; | 153 | return changed; |
155 | } | 154 | } |
156 | 155 | ||
157 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | 156 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta) |
158 | const u8 *da, u16 tid, | ||
159 | u8 dialog_token, u16 start_seq_num, | ||
160 | u16 agg_size, u16 timeout) | ||
161 | { | 157 | { |
162 | struct ieee80211_local *local = sdata->local; | 158 | int i; |
163 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
164 | struct sk_buff *skb; | ||
165 | struct ieee80211_mgmt *mgmt; | ||
166 | u16 capab; | ||
167 | |||
168 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
169 | |||
170 | if (!skb) { | ||
171 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
172 | "for addba request frame\n", sdata->dev->name); | ||
173 | return; | ||
174 | } | ||
175 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
176 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
177 | memset(mgmt, 0, 24); | ||
178 | memcpy(mgmt->da, da, ETH_ALEN); | ||
179 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
180 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
181 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
182 | else | ||
183 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
184 | |||
185 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
186 | IEEE80211_STYPE_ACTION); | ||
187 | |||
188 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); | ||
189 | |||
190 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
191 | mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; | ||
192 | |||
193 | mgmt->u.action.u.addba_req.dialog_token = dialog_token; | ||
194 | capab = (u16)(1 << 1); /* bit 1 aggregation policy */ | ||
195 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
196 | capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ | ||
197 | |||
198 | mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); | ||
199 | |||
200 | mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); | ||
201 | mgmt->u.action.u.addba_req.start_seq_num = | ||
202 | cpu_to_le16(start_seq_num << 4); | ||
203 | |||
204 | ieee80211_tx_skb(sdata, skb, 0); | ||
205 | } | ||
206 | |||
207 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | ||
208 | u8 dialog_token, u16 status, u16 policy, | ||
209 | u16 buf_size, u16 timeout) | ||
210 | { | ||
211 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
212 | struct ieee80211_local *local = sdata->local; | ||
213 | struct sk_buff *skb; | ||
214 | struct ieee80211_mgmt *mgmt; | ||
215 | u16 capab; | ||
216 | |||
217 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
218 | 159 | ||
219 | if (!skb) { | 160 | for (i = 0; i < STA_TID_NUM; i++) { |
220 | printk(KERN_DEBUG "%s: failed to allocate buffer " | 161 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR); |
221 | "for addba resp frame\n", sdata->dev->name); | 162 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, |
222 | return; | 163 | WLAN_REASON_QSTA_LEAVE_QBSS); |
223 | } | 164 | } |
224 | |||
225 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
226 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
227 | memset(mgmt, 0, 24); | ||
228 | memcpy(mgmt->da, da, ETH_ALEN); | ||
229 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
230 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
231 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
232 | else | ||
233 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
234 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
235 | IEEE80211_STYPE_ACTION); | ||
236 | |||
237 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); | ||
238 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
239 | mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; | ||
240 | mgmt->u.action.u.addba_resp.dialog_token = dialog_token; | ||
241 | |||
242 | capab = (u16)(policy << 1); /* bit 1 aggregation policy */ | ||
243 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
244 | capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ | ||
245 | |||
246 | mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); | ||
247 | mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); | ||
248 | mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); | ||
249 | |||
250 | ieee80211_tx_skb(sdata, skb, 0); | ||
251 | } | 165 | } |
252 | 166 | ||
253 | static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | 167 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, |
254 | const u8 *da, u16 tid, | 168 | const u8 *da, u16 tid, |
255 | u16 initiator, u16 reason_code) | 169 | u16 initiator, u16 reason_code) |
256 | { | 170 | { |
257 | struct ieee80211_local *local = sdata->local; | 171 | struct ieee80211_local *local = sdata->local; |
258 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 172 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
@@ -273,7 +187,8 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
273 | memset(mgmt, 0, 24); | 187 | memset(mgmt, 0, 24); |
274 | memcpy(mgmt->da, da, ETH_ALEN); | 188 | memcpy(mgmt->da, da, ETH_ALEN); |
275 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 189 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
276 | if (sdata->vif.type == NL80211_IFTYPE_AP) | 190 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
191 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
277 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 192 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); |
278 | else | 193 | else |
279 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 194 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
@@ -290,770 +205,7 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
290 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 205 | mgmt->u.action.u.delba.params = cpu_to_le16(params); |
291 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 206 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); |
292 | 207 | ||
293 | ieee80211_tx_skb(sdata, skb, 0); | 208 | ieee80211_tx_skb(sdata, skb, 1); |
294 | } | ||
295 | |||
296 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) | ||
297 | { | ||
298 | struct ieee80211_local *local = sdata->local; | ||
299 | struct sk_buff *skb; | ||
300 | struct ieee80211_bar *bar; | ||
301 | u16 bar_control = 0; | ||
302 | |||
303 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | ||
304 | if (!skb) { | ||
305 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
306 | "bar frame\n", sdata->dev->name); | ||
307 | return; | ||
308 | } | ||
309 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
310 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | ||
311 | memset(bar, 0, sizeof(*bar)); | ||
312 | bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | ||
313 | IEEE80211_STYPE_BACK_REQ); | ||
314 | memcpy(bar->ra, ra, ETH_ALEN); | ||
315 | memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); | ||
316 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | ||
317 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | ||
318 | bar_control |= (u16)(tid << 12); | ||
319 | bar->control = cpu_to_le16(bar_control); | ||
320 | bar->start_seq_num = cpu_to_le16(ssn); | ||
321 | |||
322 | ieee80211_tx_skb(sdata, skb, 0); | ||
323 | } | ||
324 | |||
325 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | ||
326 | u16 initiator, u16 reason) | ||
327 | { | ||
328 | struct ieee80211_local *local = sdata->local; | ||
329 | struct ieee80211_hw *hw = &local->hw; | ||
330 | struct sta_info *sta; | ||
331 | int ret, i; | ||
332 | |||
333 | rcu_read_lock(); | ||
334 | |||
335 | sta = sta_info_get(local, ra); | ||
336 | if (!sta) { | ||
337 | rcu_read_unlock(); | ||
338 | return; | ||
339 | } | ||
340 | |||
341 | /* check if TID is in operational state */ | ||
342 | spin_lock_bh(&sta->lock); | ||
343 | if (sta->ampdu_mlme.tid_state_rx[tid] | ||
344 | != HT_AGG_STATE_OPERATIONAL) { | ||
345 | spin_unlock_bh(&sta->lock); | ||
346 | rcu_read_unlock(); | ||
347 | return; | ||
348 | } | ||
349 | sta->ampdu_mlme.tid_state_rx[tid] = | ||
350 | HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
351 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
352 | spin_unlock_bh(&sta->lock); | ||
353 | |||
354 | /* stop HW Rx aggregation. ampdu_action existence | ||
355 | * already verified in session init so we add the BUG_ON */ | ||
356 | BUG_ON(!local->ops->ampdu_action); | ||
357 | |||
358 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
359 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", | ||
360 | ra, tid); | ||
361 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
362 | |||
363 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, | ||
364 | &sta->sta, tid, NULL); | ||
365 | if (ret) | ||
366 | printk(KERN_DEBUG "HW problem - can not stop rx " | ||
367 | "aggregation for tid %d\n", tid); | ||
368 | |||
369 | /* shutdown timer has not expired */ | ||
370 | if (initiator != WLAN_BACK_TIMER) | ||
371 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
372 | |||
373 | /* check if this is a self generated aggregation halt */ | ||
374 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | ||
375 | ieee80211_send_delba(sdata, ra, tid, 0, reason); | ||
376 | |||
377 | /* free the reordering buffer */ | ||
378 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | ||
379 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | ||
380 | /* release the reordered frames */ | ||
381 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | ||
382 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | ||
383 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | ||
384 | } | ||
385 | } | ||
386 | /* free resources */ | ||
387 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | ||
388 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
389 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
390 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
391 | |||
392 | rcu_read_unlock(); | ||
393 | } | ||
394 | |||
395 | |||
396 | /* | ||
397 | * After sending add Block Ack request we activated a timer until | ||
398 | * add Block Ack response will arrive from the recipient. | ||
399 | * If this timer expires sta_addba_resp_timer_expired will be executed. | ||
400 | */ | ||
401 | static void sta_addba_resp_timer_expired(unsigned long data) | ||
402 | { | ||
403 | /* not an elegant detour, but there is no choice as the timer passes | ||
404 | * only one argument, and both sta_info and TID are needed, so init | ||
405 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
406 | * array gives the sta through container_of */ | ||
407 | u16 tid = *(u8 *)data; | ||
408 | struct sta_info *temp_sta = container_of((void *)data, | ||
409 | struct sta_info, timer_to_tid[tid]); | ||
410 | |||
411 | struct ieee80211_local *local = temp_sta->local; | ||
412 | struct ieee80211_hw *hw = &local->hw; | ||
413 | struct sta_info *sta; | ||
414 | u8 *state; | ||
415 | |||
416 | rcu_read_lock(); | ||
417 | |||
418 | sta = sta_info_get(local, temp_sta->sta.addr); | ||
419 | if (!sta) { | ||
420 | rcu_read_unlock(); | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
425 | /* check if the TID waits for addBA response */ | ||
426 | spin_lock_bh(&sta->lock); | ||
427 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
428 | spin_unlock_bh(&sta->lock); | ||
429 | *state = HT_AGG_STATE_IDLE; | ||
430 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
431 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | ||
432 | "expecting addBA response there", tid); | ||
433 | #endif | ||
434 | goto timer_expired_exit; | ||
435 | } | ||
436 | |||
437 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
438 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | ||
439 | #endif | ||
440 | |||
441 | /* go through the state check in stop_BA_session */ | ||
442 | *state = HT_AGG_STATE_OPERATIONAL; | ||
443 | spin_unlock_bh(&sta->lock); | ||
444 | ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid, | ||
445 | WLAN_BACK_INITIATOR); | ||
446 | |||
447 | timer_expired_exit: | ||
448 | rcu_read_unlock(); | ||
449 | } | ||
450 | |||
451 | void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) | ||
452 | { | ||
453 | struct ieee80211_local *local = sdata->local; | ||
454 | int i; | ||
455 | |||
456 | for (i = 0; i < STA_TID_NUM; i++) { | ||
457 | ieee80211_stop_tx_ba_session(&local->hw, addr, i, | ||
458 | WLAN_BACK_INITIATOR); | ||
459 | ieee80211_sta_stop_rx_ba_session(sdata, addr, i, | ||
460 | WLAN_BACK_RECIPIENT, | ||
461 | WLAN_REASON_QSTA_LEAVE_QBSS); | ||
462 | } | ||
463 | } | ||
464 | |||
465 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
466 | { | ||
467 | struct ieee80211_local *local = hw_to_local(hw); | ||
468 | struct sta_info *sta; | ||
469 | struct ieee80211_sub_if_data *sdata; | ||
470 | u16 start_seq_num; | ||
471 | u8 *state; | ||
472 | int ret = 0; | ||
473 | |||
474 | if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) | ||
475 | return -EINVAL; | ||
476 | |||
477 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
478 | printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", | ||
479 | ra, tid); | ||
480 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
481 | |||
482 | rcu_read_lock(); | ||
483 | |||
484 | sta = sta_info_get(local, ra); | ||
485 | if (!sta) { | ||
486 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
487 | printk(KERN_DEBUG "Could not find the station\n"); | ||
488 | #endif | ||
489 | ret = -ENOENT; | ||
490 | goto exit; | ||
491 | } | ||
492 | |||
493 | spin_lock_bh(&sta->lock); | ||
494 | |||
495 | /* we have tried too many times, receiver does not want A-MPDU */ | ||
496 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | ||
497 | ret = -EBUSY; | ||
498 | goto err_unlock_sta; | ||
499 | } | ||
500 | |||
501 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
502 | /* check if the TID is not in aggregation flow already */ | ||
503 | if (*state != HT_AGG_STATE_IDLE) { | ||
504 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
505 | printk(KERN_DEBUG "BA request denied - session is not " | ||
506 | "idle on tid %u\n", tid); | ||
507 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
508 | ret = -EAGAIN; | ||
509 | goto err_unlock_sta; | ||
510 | } | ||
511 | |||
512 | /* prepare A-MPDU MLME for Tx aggregation */ | ||
513 | sta->ampdu_mlme.tid_tx[tid] = | ||
514 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | ||
515 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
516 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
517 | if (net_ratelimit()) | ||
518 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
519 | tid); | ||
520 | #endif | ||
521 | ret = -ENOMEM; | ||
522 | goto err_unlock_sta; | ||
523 | } | ||
524 | /* Tx timer */ | ||
525 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | ||
526 | sta_addba_resp_timer_expired; | ||
527 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | ||
528 | (unsigned long)&sta->timer_to_tid[tid]; | ||
529 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
530 | |||
531 | if (hw->ampdu_queues) { | ||
532 | /* create a new queue for this aggregation */ | ||
533 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | ||
534 | |||
535 | /* case no queue is available to aggregation | ||
536 | * don't switch to aggregation */ | ||
537 | if (ret) { | ||
538 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
539 | printk(KERN_DEBUG "BA request denied - " | ||
540 | "queue unavailable for tid %d\n", tid); | ||
541 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
542 | goto err_unlock_queue; | ||
543 | } | ||
544 | } | ||
545 | sdata = sta->sdata; | ||
546 | |||
547 | /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the | ||
548 | * call back right away, it must see that the flow has begun */ | ||
549 | *state |= HT_ADDBA_REQUESTED_MSK; | ||
550 | |||
551 | /* This is slightly racy because the queue isn't stopped */ | ||
552 | start_seq_num = sta->tid_seq[tid]; | ||
553 | |||
554 | if (local->ops->ampdu_action) | ||
555 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, | ||
556 | &sta->sta, tid, &start_seq_num); | ||
557 | |||
558 | if (ret) { | ||
559 | /* No need to requeue the packets in the agg queue, since we | ||
560 | * held the tx lock: no packet could be enqueued to the newly | ||
561 | * allocated queue */ | ||
562 | if (hw->ampdu_queues) | ||
563 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | ||
564 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
565 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
566 | " tid %d\n", tid); | ||
567 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
568 | *state = HT_AGG_STATE_IDLE; | ||
569 | goto err_unlock_queue; | ||
570 | } | ||
571 | |||
572 | /* Will put all the packets in the new SW queue */ | ||
573 | if (hw->ampdu_queues) | ||
574 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | ||
575 | spin_unlock_bh(&sta->lock); | ||
576 | |||
577 | /* send an addBA request */ | ||
578 | sta->ampdu_mlme.dialog_token_allocator++; | ||
579 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = | ||
580 | sta->ampdu_mlme.dialog_token_allocator; | ||
581 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | ||
582 | |||
583 | |||
584 | ieee80211_send_addba_request(sta->sdata, ra, tid, | ||
585 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | ||
586 | sta->ampdu_mlme.tid_tx[tid]->ssn, | ||
587 | 0x40, 5000); | ||
588 | /* activate the timer for the recipient's addBA response */ | ||
589 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | ||
590 | jiffies + ADDBA_RESP_INTERVAL; | ||
591 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
592 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
593 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
594 | #endif | ||
595 | goto exit; | ||
596 | |||
597 | err_unlock_queue: | ||
598 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
599 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
600 | ret = -EBUSY; | ||
601 | err_unlock_sta: | ||
602 | spin_unlock_bh(&sta->lock); | ||
603 | exit: | ||
604 | rcu_read_unlock(); | ||
605 | return ret; | ||
606 | } | ||
607 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | ||
608 | |||
609 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | ||
610 | u8 *ra, u16 tid, | ||
611 | enum ieee80211_back_parties initiator) | ||
612 | { | ||
613 | struct ieee80211_local *local = hw_to_local(hw); | ||
614 | struct sta_info *sta; | ||
615 | u8 *state; | ||
616 | int ret = 0; | ||
617 | |||
618 | if (tid >= STA_TID_NUM) | ||
619 | return -EINVAL; | ||
620 | |||
621 | rcu_read_lock(); | ||
622 | sta = sta_info_get(local, ra); | ||
623 | if (!sta) { | ||
624 | rcu_read_unlock(); | ||
625 | return -ENOENT; | ||
626 | } | ||
627 | |||
628 | /* check if the TID is in aggregation */ | ||
629 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
630 | spin_lock_bh(&sta->lock); | ||
631 | |||
632 | if (*state != HT_AGG_STATE_OPERATIONAL) { | ||
633 | ret = -ENOENT; | ||
634 | goto stop_BA_exit; | ||
635 | } | ||
636 | |||
637 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
638 | printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", | ||
639 | ra, tid); | ||
640 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
641 | |||
642 | if (hw->ampdu_queues) | ||
643 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | ||
644 | |||
645 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
646 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
647 | |||
648 | if (local->ops->ampdu_action) | ||
649 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, | ||
650 | &sta->sta, tid, NULL); | ||
651 | |||
652 | /* case HW denied going back to legacy */ | ||
653 | if (ret) { | ||
654 | WARN_ON(ret != -EBUSY); | ||
655 | *state = HT_AGG_STATE_OPERATIONAL; | ||
656 | if (hw->ampdu_queues) | ||
657 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
658 | goto stop_BA_exit; | ||
659 | } | ||
660 | |||
661 | stop_BA_exit: | ||
662 | spin_unlock_bh(&sta->lock); | ||
663 | rcu_read_unlock(); | ||
664 | return ret; | ||
665 | } | ||
666 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | ||
667 | |||
668 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
669 | { | ||
670 | struct ieee80211_local *local = hw_to_local(hw); | ||
671 | struct sta_info *sta; | ||
672 | u8 *state; | ||
673 | |||
674 | if (tid >= STA_TID_NUM) { | ||
675 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
676 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
677 | tid, STA_TID_NUM); | ||
678 | #endif | ||
679 | return; | ||
680 | } | ||
681 | |||
682 | rcu_read_lock(); | ||
683 | sta = sta_info_get(local, ra); | ||
684 | if (!sta) { | ||
685 | rcu_read_unlock(); | ||
686 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
687 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | ||
688 | #endif | ||
689 | return; | ||
690 | } | ||
691 | |||
692 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
693 | spin_lock_bh(&sta->lock); | ||
694 | |||
695 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
696 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
697 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | ||
698 | *state); | ||
699 | #endif | ||
700 | spin_unlock_bh(&sta->lock); | ||
701 | rcu_read_unlock(); | ||
702 | return; | ||
703 | } | ||
704 | |||
705 | WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); | ||
706 | |||
707 | *state |= HT_ADDBA_DRV_READY_MSK; | ||
708 | |||
709 | if (*state == HT_AGG_STATE_OPERATIONAL) { | ||
710 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
711 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | ||
712 | #endif | ||
713 | if (hw->ampdu_queues) | ||
714 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
715 | } | ||
716 | spin_unlock_bh(&sta->lock); | ||
717 | rcu_read_unlock(); | ||
718 | } | ||
719 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | ||
720 | |||
721 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | ||
722 | { | ||
723 | struct ieee80211_local *local = hw_to_local(hw); | ||
724 | struct sta_info *sta; | ||
725 | u8 *state; | ||
726 | int agg_queue; | ||
727 | |||
728 | if (tid >= STA_TID_NUM) { | ||
729 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
730 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
731 | tid, STA_TID_NUM); | ||
732 | #endif | ||
733 | return; | ||
734 | } | ||
735 | |||
736 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
737 | printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n", | ||
738 | ra, tid); | ||
739 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
740 | |||
741 | rcu_read_lock(); | ||
742 | sta = sta_info_get(local, ra); | ||
743 | if (!sta) { | ||
744 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
745 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | ||
746 | #endif | ||
747 | rcu_read_unlock(); | ||
748 | return; | ||
749 | } | ||
750 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
751 | |||
752 | /* NOTE: no need to use sta->lock in this state check, as | ||
753 | * ieee80211_stop_tx_ba_session will let only one stop call to | ||
754 | * pass through per sta/tid | ||
755 | */ | ||
756 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | ||
757 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
758 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | ||
759 | #endif | ||
760 | rcu_read_unlock(); | ||
761 | return; | ||
762 | } | ||
763 | |||
764 | if (*state & HT_AGG_STATE_INITIATOR_MSK) | ||
765 | ieee80211_send_delba(sta->sdata, ra, tid, | ||
766 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | ||
767 | |||
768 | if (hw->ampdu_queues) { | ||
769 | agg_queue = sta->tid_to_tx_q[tid]; | ||
770 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); | ||
771 | |||
772 | /* We just requeued the all the frames that were in the | ||
773 | * removed queue, and since we might miss a softirq we do | ||
774 | * netif_schedule_queue. ieee80211_wake_queue is not used | ||
775 | * here as this queue is not necessarily stopped | ||
776 | */ | ||
777 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, | ||
778 | agg_queue)); | ||
779 | } | ||
780 | spin_lock_bh(&sta->lock); | ||
781 | *state = HT_AGG_STATE_IDLE; | ||
782 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
783 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
784 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
785 | spin_unlock_bh(&sta->lock); | ||
786 | |||
787 | rcu_read_unlock(); | ||
788 | } | ||
789 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | ||
790 | |||
791 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
792 | const u8 *ra, u16 tid) | ||
793 | { | ||
794 | struct ieee80211_local *local = hw_to_local(hw); | ||
795 | struct ieee80211_ra_tid *ra_tid; | ||
796 | struct sk_buff *skb = dev_alloc_skb(0); | ||
797 | |||
798 | if (unlikely(!skb)) { | ||
799 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
800 | if (net_ratelimit()) | ||
801 | printk(KERN_WARNING "%s: Not enough memory, " | ||
802 | "dropping start BA session", skb->dev->name); | ||
803 | #endif | ||
804 | return; | ||
805 | } | ||
806 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
807 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
808 | ra_tid->tid = tid; | ||
809 | |||
810 | skb->pkt_type = IEEE80211_ADDBA_MSG; | ||
811 | skb_queue_tail(&local->skb_queue, skb); | ||
812 | tasklet_schedule(&local->tasklet); | ||
813 | } | ||
814 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | ||
815 | |||
816 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
817 | const u8 *ra, u16 tid) | ||
818 | { | ||
819 | struct ieee80211_local *local = hw_to_local(hw); | ||
820 | struct ieee80211_ra_tid *ra_tid; | ||
821 | struct sk_buff *skb = dev_alloc_skb(0); | ||
822 | |||
823 | if (unlikely(!skb)) { | ||
824 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
825 | if (net_ratelimit()) | ||
826 | printk(KERN_WARNING "%s: Not enough memory, " | ||
827 | "dropping stop BA session", skb->dev->name); | ||
828 | #endif | ||
829 | return; | ||
830 | } | ||
831 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
832 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
833 | ra_tid->tid = tid; | ||
834 | |||
835 | skb->pkt_type = IEEE80211_DELBA_MSG; | ||
836 | skb_queue_tail(&local->skb_queue, skb); | ||
837 | tasklet_schedule(&local->tasklet); | ||
838 | } | ||
839 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); | ||
840 | |||
841 | /* | ||
842 | * After accepting the AddBA Request we activated a timer, | ||
843 | * resetting it after each frame that arrives from the originator. | ||
844 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | ||
845 | */ | ||
846 | static void sta_rx_agg_session_timer_expired(unsigned long data) | ||
847 | { | ||
848 | /* not an elegant detour, but there is no choice as the timer passes | ||
849 | * only one argument, and various sta_info are needed here, so init | ||
850 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
851 | * array gives the sta through container_of */ | ||
852 | u8 *ptid = (u8 *)data; | ||
853 | u8 *timer_to_id = ptid - *ptid; | ||
854 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
855 | timer_to_tid[0]); | ||
856 | |||
857 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
858 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | ||
859 | #endif | ||
860 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | ||
861 | (u16)*ptid, WLAN_BACK_TIMER, | ||
862 | WLAN_REASON_QSTA_TIMEOUT); | ||
863 | } | ||
864 | |||
865 | void ieee80211_process_addba_request(struct ieee80211_local *local, | ||
866 | struct sta_info *sta, | ||
867 | struct ieee80211_mgmt *mgmt, | ||
868 | size_t len) | ||
869 | { | ||
870 | struct ieee80211_hw *hw = &local->hw; | ||
871 | struct ieee80211_conf *conf = &hw->conf; | ||
872 | struct tid_ampdu_rx *tid_agg_rx; | ||
873 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | ||
874 | u8 dialog_token; | ||
875 | int ret = -EOPNOTSUPP; | ||
876 | |||
877 | /* extract session parameters from addba request frame */ | ||
878 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | ||
879 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | ||
880 | start_seq_num = | ||
881 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
882 | |||
883 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
884 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
885 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
886 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
887 | |||
888 | status = WLAN_STATUS_REQUEST_DECLINED; | ||
889 | |||
890 | /* sanity check for incoming parameters: | ||
891 | * check if configuration can support the BA policy | ||
892 | * and if buffer size does not exceeds max value */ | ||
893 | /* XXX: check own ht delayed BA capability?? */ | ||
894 | if (((ba_policy != 1) | ||
895 | && (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) | ||
896 | || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { | ||
897 | status = WLAN_STATUS_INVALID_QOS_PARAM; | ||
898 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
899 | if (net_ratelimit()) | ||
900 | printk(KERN_DEBUG "AddBA Req with bad params from " | ||
901 | "%pM on tid %u. policy %d, buffer size %d\n", | ||
902 | mgmt->sa, tid, ba_policy, | ||
903 | buf_size); | ||
904 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
905 | goto end_no_lock; | ||
906 | } | ||
907 | /* determine default buffer size */ | ||
908 | if (buf_size == 0) { | ||
909 | struct ieee80211_supported_band *sband; | ||
910 | |||
911 | sband = local->hw.wiphy->bands[conf->channel->band]; | ||
912 | buf_size = IEEE80211_MIN_AMPDU_BUF; | ||
913 | buf_size = buf_size << sband->ht_cap.ampdu_factor; | ||
914 | } | ||
915 | |||
916 | |||
917 | /* examine state machine */ | ||
918 | spin_lock_bh(&sta->lock); | ||
919 | |||
920 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | ||
921 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
922 | if (net_ratelimit()) | ||
923 | printk(KERN_DEBUG "unexpected AddBA Req from " | ||
924 | "%pM on tid %u\n", | ||
925 | mgmt->sa, tid); | ||
926 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
927 | goto end; | ||
928 | } | ||
929 | |||
930 | /* prepare A-MPDU MLME for Rx aggregation */ | ||
931 | sta->ampdu_mlme.tid_rx[tid] = | ||
932 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | ||
933 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
934 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
935 | if (net_ratelimit()) | ||
936 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
937 | tid); | ||
938 | #endif | ||
939 | goto end; | ||
940 | } | ||
941 | /* rx timer */ | ||
942 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
943 | sta_rx_agg_session_timer_expired; | ||
944 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
945 | (unsigned long)&sta->timer_to_tid[tid]; | ||
946 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
947 | |||
948 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
949 | |||
950 | /* prepare reordering buffer */ | ||
951 | tid_agg_rx->reorder_buf = | ||
952 | kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC); | ||
953 | if (!tid_agg_rx->reorder_buf) { | ||
954 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
955 | if (net_ratelimit()) | ||
956 | printk(KERN_ERR "can not allocate reordering buffer " | ||
957 | "to tid %d\n", tid); | ||
958 | #endif | ||
959 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
960 | goto end; | ||
961 | } | ||
962 | memset(tid_agg_rx->reorder_buf, 0, | ||
963 | buf_size * sizeof(struct sk_buff *)); | ||
964 | |||
965 | if (local->ops->ampdu_action) | ||
966 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, | ||
967 | &sta->sta, tid, &start_seq_num); | ||
968 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
969 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | ||
970 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
971 | |||
972 | if (ret) { | ||
973 | kfree(tid_agg_rx->reorder_buf); | ||
974 | kfree(tid_agg_rx); | ||
975 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
976 | goto end; | ||
977 | } | ||
978 | |||
979 | /* change state and send addba resp */ | ||
980 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | ||
981 | tid_agg_rx->dialog_token = dialog_token; | ||
982 | tid_agg_rx->ssn = start_seq_num; | ||
983 | tid_agg_rx->head_seq_num = start_seq_num; | ||
984 | tid_agg_rx->buf_size = buf_size; | ||
985 | tid_agg_rx->timeout = timeout; | ||
986 | tid_agg_rx->stored_mpdu_num = 0; | ||
987 | status = WLAN_STATUS_SUCCESS; | ||
988 | end: | ||
989 | spin_unlock_bh(&sta->lock); | ||
990 | |||
991 | end_no_lock: | ||
992 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, | ||
993 | dialog_token, status, 1, buf_size, timeout); | ||
994 | } | ||
995 | |||
996 | void ieee80211_process_addba_resp(struct ieee80211_local *local, | ||
997 | struct sta_info *sta, | ||
998 | struct ieee80211_mgmt *mgmt, | ||
999 | size_t len) | ||
1000 | { | ||
1001 | struct ieee80211_hw *hw = &local->hw; | ||
1002 | u16 capab; | ||
1003 | u16 tid, start_seq_num; | ||
1004 | u8 *state; | ||
1005 | |||
1006 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | ||
1007 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
1008 | |||
1009 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
1010 | |||
1011 | spin_lock_bh(&sta->lock); | ||
1012 | |||
1013 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
1014 | spin_unlock_bh(&sta->lock); | ||
1015 | return; | ||
1016 | } | ||
1017 | |||
1018 | if (mgmt->u.action.u.addba_resp.dialog_token != | ||
1019 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | ||
1020 | spin_unlock_bh(&sta->lock); | ||
1021 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1022 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | ||
1023 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1024 | return; | ||
1025 | } | ||
1026 | |||
1027 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
1028 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1029 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | ||
1030 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1031 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | ||
1032 | == WLAN_STATUS_SUCCESS) { | ||
1033 | *state |= HT_ADDBA_RECEIVED_MSK; | ||
1034 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
1035 | |||
1036 | if (*state == HT_AGG_STATE_OPERATIONAL && | ||
1037 | local->hw.ampdu_queues) | ||
1038 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
1039 | |||
1040 | if (local->ops->ampdu_action) { | ||
1041 | (void)local->ops->ampdu_action(hw, | ||
1042 | IEEE80211_AMPDU_TX_RESUME, | ||
1043 | &sta->sta, tid, &start_seq_num); | ||
1044 | } | ||
1045 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1046 | printk(KERN_DEBUG "Resuming TX aggregation for tid %d\n", tid); | ||
1047 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1048 | spin_unlock_bh(&sta->lock); | ||
1049 | } else { | ||
1050 | sta->ampdu_mlme.addba_req_num[tid]++; | ||
1051 | /* this will allow the state check in stop_BA_session */ | ||
1052 | *state = HT_AGG_STATE_OPERATIONAL; | ||
1053 | spin_unlock_bh(&sta->lock); | ||
1054 | ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid, | ||
1055 | WLAN_BACK_INITIATOR); | ||
1056 | } | ||
1057 | } | 209 | } |
1058 | 210 | ||
1059 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 211 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f3eec989662b..2cb743ed9f9c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -43,7 +43,7 @@ struct ieee80211_local; | |||
43 | 43 | ||
44 | /* Required encryption head and tailroom */ | 44 | /* Required encryption head and tailroom */ |
45 | #define IEEE80211_ENCRYPT_HEADROOM 8 | 45 | #define IEEE80211_ENCRYPT_HEADROOM 8 |
46 | #define IEEE80211_ENCRYPT_TAILROOM 12 | 46 | #define IEEE80211_ENCRYPT_TAILROOM 18 |
47 | 47 | ||
48 | /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent | 48 | /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent |
49 | * reception of at least three fragmented frames. This limit can be increased | 49 | * reception of at least three fragmented frames. This limit can be increased |
@@ -57,6 +57,8 @@ struct ieee80211_local; | |||
57 | */ | 57 | */ |
58 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | 58 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) |
59 | 59 | ||
60 | #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) | ||
61 | |||
60 | struct ieee80211_fragment_entry { | 62 | struct ieee80211_fragment_entry { |
61 | unsigned long first_frag_time; | 63 | unsigned long first_frag_time; |
62 | unsigned int seq; | 64 | unsigned int seq; |
@@ -70,43 +72,36 @@ struct ieee80211_fragment_entry { | |||
70 | 72 | ||
71 | 73 | ||
72 | struct ieee80211_bss { | 74 | struct ieee80211_bss { |
73 | struct list_head list; | 75 | /* Yes, this is a hack */ |
74 | struct ieee80211_bss *hnext; | 76 | struct cfg80211_bss cbss; |
75 | size_t ssid_len; | ||
76 | 77 | ||
77 | atomic_t users; | 78 | /* don't want to look up all the time */ |
78 | 79 | size_t ssid_len; | |
79 | u8 bssid[ETH_ALEN]; | ||
80 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 80 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
81 | |||
81 | u8 dtim_period; | 82 | u8 dtim_period; |
82 | u16 capability; /* host byte order */ | 83 | |
83 | enum ieee80211_band band; | ||
84 | int freq; | ||
85 | int signal, noise, qual; | ||
86 | u8 *ies; /* all information elements from the last Beacon or Probe | ||
87 | * Response frames; note Beacon frame is not allowed to | ||
88 | * override values from Probe Response */ | ||
89 | size_t ies_len; | ||
90 | bool wmm_used; | 84 | bool wmm_used; |
85 | |||
86 | unsigned long last_probe_resp; | ||
87 | |||
91 | #ifdef CONFIG_MAC80211_MESH | 88 | #ifdef CONFIG_MAC80211_MESH |
92 | u8 *mesh_id; | 89 | u8 *mesh_id; |
93 | size_t mesh_id_len; | 90 | size_t mesh_id_len; |
94 | u8 *mesh_cfg; | 91 | u8 *mesh_cfg; |
95 | #endif | 92 | #endif |
93 | |||
96 | #define IEEE80211_MAX_SUPP_RATES 32 | 94 | #define IEEE80211_MAX_SUPP_RATES 32 |
97 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 95 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
98 | size_t supp_rates_len; | 96 | size_t supp_rates_len; |
99 | u64 timestamp; | ||
100 | int beacon_int; | ||
101 | 97 | ||
102 | unsigned long last_probe_resp; | 98 | /* |
103 | unsigned long last_update; | 99 | * During assocation, we save an ERP value from a probe response so |
104 | |||
105 | /* during assocation, we save an ERP value from a probe response so | ||
106 | * that we can feed ERP info to the driver when handling the | 100 | * that we can feed ERP info to the driver when handling the |
107 | * association completes. these fields probably won't be up-to-date | 101 | * association completes. these fields probably won't be up-to-date |
108 | * otherwise, you probably don't want to use them. */ | 102 | * otherwise, you probably don't want to use them. |
109 | int has_erp_value; | 103 | */ |
104 | bool has_erp_value; | ||
110 | u8 erp_value; | 105 | u8 erp_value; |
111 | }; | 106 | }; |
112 | 107 | ||
@@ -258,6 +253,9 @@ struct mesh_preq_queue { | |||
258 | #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) | 253 | #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) |
259 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) | 254 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) |
260 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) | 255 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) |
256 | #define IEEE80211_STA_TKIP_WEP_USED BIT(14) | ||
257 | #define IEEE80211_STA_CSA_RECEIVED BIT(15) | ||
258 | #define IEEE80211_STA_MFP_ENABLED BIT(16) | ||
261 | /* flags for MLME request */ | 259 | /* flags for MLME request */ |
262 | #define IEEE80211_STA_REQ_SCAN 0 | 260 | #define IEEE80211_STA_REQ_SCAN 0 |
263 | #define IEEE80211_STA_REQ_DIRECT_PROBE 1 | 261 | #define IEEE80211_STA_REQ_DIRECT_PROBE 1 |
@@ -282,13 +280,13 @@ enum ieee80211_sta_mlme_state { | |||
282 | 280 | ||
283 | struct ieee80211_if_sta { | 281 | struct ieee80211_if_sta { |
284 | struct timer_list timer; | 282 | struct timer_list timer; |
283 | struct timer_list chswitch_timer; | ||
285 | struct work_struct work; | 284 | struct work_struct work; |
285 | struct work_struct chswitch_work; | ||
286 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; | 286 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; |
287 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 287 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
288 | enum ieee80211_sta_mlme_state state; | 288 | enum ieee80211_sta_mlme_state state; |
289 | size_t ssid_len; | 289 | size_t ssid_len; |
290 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | ||
291 | size_t scan_ssid_len; | ||
292 | u16 aid; | 290 | u16 aid; |
293 | u16 ap_capab, capab; | 291 | u16 ap_capab, capab; |
294 | u8 *extra_ie; /* to be added to the end of AssocReq */ | 292 | u8 *extra_ie; /* to be added to the end of AssocReq */ |
@@ -315,11 +313,33 @@ struct ieee80211_if_sta { | |||
315 | int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ | 313 | int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ |
316 | int auth_transaction; | 314 | int auth_transaction; |
317 | 315 | ||
316 | enum { | ||
317 | IEEE80211_MFP_DISABLED, | ||
318 | IEEE80211_MFP_OPTIONAL, | ||
319 | IEEE80211_MFP_REQUIRED | ||
320 | } mfp; /* management frame protection */ | ||
321 | |||
318 | unsigned long ibss_join_req; | 322 | unsigned long ibss_join_req; |
319 | struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ | 323 | struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ |
320 | u32 supp_rates_bits[IEEE80211_NUM_BANDS]; | 324 | u32 supp_rates_bits[IEEE80211_NUM_BANDS]; |
321 | 325 | ||
322 | int wmm_last_param_set; | 326 | int wmm_last_param_set; |
327 | |||
328 | /* Extra IE data for management frames */ | ||
329 | u8 *ie_probereq; | ||
330 | size_t ie_probereq_len; | ||
331 | u8 *ie_proberesp; | ||
332 | size_t ie_proberesp_len; | ||
333 | u8 *ie_auth; | ||
334 | size_t ie_auth_len; | ||
335 | u8 *ie_assocreq; | ||
336 | size_t ie_assocreq_len; | ||
337 | u8 *ie_reassocreq; | ||
338 | size_t ie_reassocreq_len; | ||
339 | u8 *ie_deauth; | ||
340 | size_t ie_deauth_len; | ||
341 | u8 *ie_disassoc; | ||
342 | size_t ie_disassoc_len; | ||
323 | }; | 343 | }; |
324 | 344 | ||
325 | struct ieee80211_if_mesh { | 345 | struct ieee80211_if_mesh { |
@@ -404,8 +424,10 @@ struct ieee80211_sub_if_data { | |||
404 | unsigned int fragment_next; | 424 | unsigned int fragment_next; |
405 | 425 | ||
406 | #define NUM_DEFAULT_KEYS 4 | 426 | #define NUM_DEFAULT_KEYS 4 |
407 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; | 427 | #define NUM_DEFAULT_MGMT_KEYS 2 |
428 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | ||
408 | struct ieee80211_key *default_key; | 429 | struct ieee80211_key *default_key; |
430 | struct ieee80211_key *default_mgmt_key; | ||
409 | 431 | ||
410 | u16 sequence_number; | 432 | u16 sequence_number; |
411 | 433 | ||
@@ -477,6 +499,7 @@ struct ieee80211_sub_if_data { | |||
477 | } debugfs; | 499 | } debugfs; |
478 | struct { | 500 | struct { |
479 | struct dentry *default_key; | 501 | struct dentry *default_key; |
502 | struct dentry *default_mgmt_key; | ||
480 | } common_debugfs; | 503 | } common_debugfs; |
481 | 504 | ||
482 | #ifdef CONFIG_MAC80211_MESH | 505 | #ifdef CONFIG_MAC80211_MESH |
@@ -541,6 +564,7 @@ enum { | |||
541 | enum queue_stop_reason { | 564 | enum queue_stop_reason { |
542 | IEEE80211_QUEUE_STOP_REASON_DRIVER, | 565 | IEEE80211_QUEUE_STOP_REASON_DRIVER, |
543 | IEEE80211_QUEUE_STOP_REASON_PS, | 566 | IEEE80211_QUEUE_STOP_REASON_PS, |
567 | IEEE80211_QUEUE_STOP_REASON_CSA | ||
544 | }; | 568 | }; |
545 | 569 | ||
546 | /* maximum number of hardware queues we support. */ | 570 | /* maximum number of hardware queues we support. */ |
@@ -568,7 +592,6 @@ struct ieee80211_local { | |||
568 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; | 592 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; |
569 | unsigned int filter_flags; /* FIF_* */ | 593 | unsigned int filter_flags; /* FIF_* */ |
570 | struct iw_statistics wstats; | 594 | struct iw_statistics wstats; |
571 | u8 wstats_flags; | ||
572 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 595 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
573 | int tx_headroom; /* required headroom for hardware/radiotap */ | 596 | int tx_headroom; /* required headroom for hardware/radiotap */ |
574 | 597 | ||
@@ -612,7 +635,9 @@ struct ieee80211_local { | |||
612 | struct crypto_blkcipher *wep_rx_tfm; | 635 | struct crypto_blkcipher *wep_rx_tfm; |
613 | u32 wep_iv; | 636 | u32 wep_iv; |
614 | 637 | ||
638 | /* see iface.c */ | ||
615 | struct list_head interfaces; | 639 | struct list_head interfaces; |
640 | struct mutex iflist_mtx; | ||
616 | 641 | ||
617 | /* | 642 | /* |
618 | * Key lock, protects sdata's key_list and sta_info's | 643 | * Key lock, protects sdata's key_list and sta_info's |
@@ -623,20 +648,18 @@ struct ieee80211_local { | |||
623 | 648 | ||
624 | /* Scanning and BSS list */ | 649 | /* Scanning and BSS list */ |
625 | bool sw_scanning, hw_scanning; | 650 | bool sw_scanning, hw_scanning; |
651 | struct cfg80211_ssid scan_ssid; | ||
652 | struct cfg80211_scan_request int_scan_req; | ||
653 | struct cfg80211_scan_request *scan_req; | ||
654 | struct ieee80211_channel *scan_channel; | ||
626 | int scan_channel_idx; | 655 | int scan_channel_idx; |
627 | enum ieee80211_band scan_band; | ||
628 | 656 | ||
629 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; | 657 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; |
630 | unsigned long last_scan_completed; | 658 | unsigned long last_scan_completed; |
631 | struct delayed_work scan_work; | 659 | struct delayed_work scan_work; |
632 | struct ieee80211_sub_if_data *scan_sdata; | 660 | struct ieee80211_sub_if_data *scan_sdata; |
633 | struct ieee80211_channel *oper_channel, *scan_channel; | ||
634 | enum nl80211_channel_type oper_channel_type; | 661 | enum nl80211_channel_type oper_channel_type; |
635 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 662 | struct ieee80211_channel *oper_channel, *csa_channel; |
636 | size_t scan_ssid_len; | ||
637 | struct list_head bss_list; | ||
638 | struct ieee80211_bss *bss_hash[STA_HASH_SIZE]; | ||
639 | spinlock_t bss_lock; | ||
640 | 663 | ||
641 | /* SNMP counters */ | 664 | /* SNMP counters */ |
642 | /* dot11CountersTable */ | 665 | /* dot11CountersTable */ |
@@ -649,7 +672,6 @@ struct ieee80211_local { | |||
649 | u32 dot11ReceivedFragmentCount; | 672 | u32 dot11ReceivedFragmentCount; |
650 | u32 dot11MulticastReceivedFrameCount; | 673 | u32 dot11MulticastReceivedFrameCount; |
651 | u32 dot11TransmittedFrameCount; | 674 | u32 dot11TransmittedFrameCount; |
652 | u32 dot11WEPUndecryptableCount; | ||
653 | 675 | ||
654 | #ifdef CONFIG_MAC80211_LEDS | 676 | #ifdef CONFIG_MAC80211_LEDS |
655 | int tx_led_counter, rx_led_counter; | 677 | int tx_led_counter, rx_led_counter; |
@@ -696,11 +718,14 @@ struct ieee80211_local { | |||
696 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ | 718 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ |
697 | 719 | ||
698 | bool powersave; | 720 | bool powersave; |
699 | int dynamic_ps_timeout; | 721 | bool pspolling; |
700 | struct work_struct dynamic_ps_enable_work; | 722 | struct work_struct dynamic_ps_enable_work; |
701 | struct work_struct dynamic_ps_disable_work; | 723 | struct work_struct dynamic_ps_disable_work; |
702 | struct timer_list dynamic_ps_timer; | 724 | struct timer_list dynamic_ps_timer; |
703 | 725 | ||
726 | int user_power_level; /* in dBm */ | ||
727 | int power_constr_level; /* in dBm */ | ||
728 | |||
704 | #ifdef CONFIG_MAC80211_DEBUGFS | 729 | #ifdef CONFIG_MAC80211_DEBUGFS |
705 | struct local_debugfsdentries { | 730 | struct local_debugfsdentries { |
706 | struct dentry *rcdir; | 731 | struct dentry *rcdir; |
@@ -712,6 +737,7 @@ struct ieee80211_local { | |||
712 | struct dentry *long_retry_limit; | 737 | struct dentry *long_retry_limit; |
713 | struct dentry *total_ps_buffered; | 738 | struct dentry *total_ps_buffered; |
714 | struct dentry *wep_iv; | 739 | struct dentry *wep_iv; |
740 | struct dentry *tsf; | ||
715 | struct dentry *statistics; | 741 | struct dentry *statistics; |
716 | struct local_debugfsdentries_statsdentries { | 742 | struct local_debugfsdentries_statsdentries { |
717 | struct dentry *transmitted_fragment_count; | 743 | struct dentry *transmitted_fragment_count; |
@@ -805,6 +831,7 @@ struct ieee802_11_elems { | |||
805 | u8 *country_elem; | 831 | u8 *country_elem; |
806 | u8 *pwr_constr_elem; | 832 | u8 *pwr_constr_elem; |
807 | u8 *quiet_elem; /* first quite element */ | 833 | u8 *quiet_elem; /* first quite element */ |
834 | u8 *timeout_int; | ||
808 | 835 | ||
809 | /* length of them, respectively */ | 836 | /* length of them, respectively */ |
810 | u8 ssid_len; | 837 | u8 ssid_len; |
@@ -832,6 +859,7 @@ struct ieee802_11_elems { | |||
832 | u8 pwr_constr_elem_len; | 859 | u8 pwr_constr_elem_len; |
833 | u8 quiet_elem_len; | 860 | u8 quiet_elem_len; |
834 | u8 num_of_quiet_elem; /* can be more the one */ | 861 | u8 num_of_quiet_elem; /* can be more the one */ |
862 | u8 timeout_int_len; | ||
835 | }; | 863 | }; |
836 | 864 | ||
837 | static inline struct ieee80211_local *hw_to_local( | 865 | static inline struct ieee80211_local *hw_to_local( |
@@ -875,19 +903,21 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); | |||
875 | void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, | 903 | void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, |
876 | struct ieee80211_if_sta *ifsta); | 904 | struct ieee80211_if_sta *ifsta); |
877 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 905 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
878 | u8 *bssid, u8 *addr, u64 supp_rates); | 906 | u8 *bssid, u8 *addr, u32 supp_rates); |
879 | int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); | 907 | int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); |
880 | int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); | 908 | int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); |
881 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); | 909 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
882 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 910 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
883 | struct ieee802_11_elems *elems, | 911 | struct ieee802_11_elems *elems, |
884 | enum ieee80211_band band); | 912 | enum ieee80211_band band); |
885 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 913 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
886 | u8 *ssid, size_t ssid_len); | 914 | u8 *ssid, size_t ssid_len); |
915 | void ieee80211_send_pspoll(struct ieee80211_local *local, | ||
916 | struct ieee80211_sub_if_data *sdata); | ||
887 | 917 | ||
888 | /* scan/BSS handling */ | 918 | /* scan/BSS handling */ |
889 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 919 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
890 | u8 *ssid, size_t ssid_len); | 920 | struct cfg80211_scan_request *req); |
891 | int ieee80211_scan_results(struct ieee80211_local *local, | 921 | int ieee80211_scan_results(struct ieee80211_local *local, |
892 | struct iw_request_info *info, | 922 | struct iw_request_info *info, |
893 | char *buf, size_t len); | 923 | char *buf, size_t len); |
@@ -895,29 +925,27 @@ ieee80211_rx_result | |||
895 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, | 925 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, |
896 | struct sk_buff *skb, | 926 | struct sk_buff *skb, |
897 | struct ieee80211_rx_status *rx_status); | 927 | struct ieee80211_rx_status *rx_status); |
898 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); | ||
899 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); | ||
900 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, | 928 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, |
901 | char *ie, size_t len); | 929 | char *ie, size_t len); |
902 | 930 | ||
903 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | 931 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); |
904 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | 932 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, |
905 | u8 *ssid, size_t ssid_len); | 933 | struct cfg80211_scan_request *req); |
906 | struct ieee80211_bss * | 934 | struct ieee80211_bss * |
907 | ieee80211_bss_info_update(struct ieee80211_local *local, | 935 | ieee80211_bss_info_update(struct ieee80211_local *local, |
908 | struct ieee80211_rx_status *rx_status, | 936 | struct ieee80211_rx_status *rx_status, |
909 | struct ieee80211_mgmt *mgmt, | 937 | struct ieee80211_mgmt *mgmt, |
910 | size_t len, | 938 | size_t len, |
911 | struct ieee802_11_elems *elems, | 939 | struct ieee802_11_elems *elems, |
912 | int freq, bool beacon); | 940 | struct ieee80211_channel *channel, |
913 | struct ieee80211_bss * | 941 | bool beacon); |
914 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | ||
915 | u8 *ssid, u8 ssid_len); | ||
916 | struct ieee80211_bss * | 942 | struct ieee80211_bss * |
917 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | 943 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, |
918 | u8 *ssid, u8 ssid_len); | 944 | u8 *ssid, u8 ssid_len); |
919 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 945 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
920 | struct ieee80211_bss *bss); | 946 | struct ieee80211_bss *bss); |
947 | void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid, | ||
948 | int freq, u8 *ssid, u8 ssid_len); | ||
921 | 949 | ||
922 | /* interface handling */ | 950 | /* interface handling */ |
923 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 951 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
@@ -943,10 +971,15 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
943 | struct ieee80211_ht_info *hti, | 971 | struct ieee80211_ht_info *hti, |
944 | u16 ap_ht_cap_flags); | 972 | u16 ap_ht_cap_flags); |
945 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); | 973 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); |
974 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | ||
975 | const u8 *da, u16 tid, | ||
976 | u16 initiator, u16 reason_code); | ||
946 | 977 | ||
947 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | 978 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, |
948 | u16 tid, u16 initiator, u16 reason); | 979 | u16 tid, u16 initiator, u16 reason); |
949 | void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); | 980 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
981 | u16 initiator, u16 reason); | ||
982 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); | ||
950 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 983 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
951 | struct sta_info *sta, | 984 | struct sta_info *sta, |
952 | struct ieee80211_mgmt *mgmt, size_t len); | 985 | struct ieee80211_mgmt *mgmt, size_t len); |
@@ -959,10 +992,25 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
959 | struct ieee80211_mgmt *mgmt, | 992 | struct ieee80211_mgmt *mgmt, |
960 | size_t len); | 993 | size_t len); |
961 | 994 | ||
995 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | ||
996 | enum ieee80211_back_parties initiator); | ||
997 | |||
962 | /* Spectrum management */ | 998 | /* Spectrum management */ |
963 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 999 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
964 | struct ieee80211_mgmt *mgmt, | 1000 | struct ieee80211_mgmt *mgmt, |
965 | size_t len); | 1001 | size_t len); |
1002 | void ieee80211_chswitch_timer(unsigned long data); | ||
1003 | void ieee80211_chswitch_work(struct work_struct *work); | ||
1004 | void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, | ||
1005 | struct ieee80211_channel_sw_ie *sw_elem, | ||
1006 | struct ieee80211_bss *bss); | ||
1007 | void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | ||
1008 | u16 capab_info, u8 *pwr_constr_elem, | ||
1009 | u8 pwr_constr_elem_len); | ||
1010 | |||
1011 | /* Suspend/resume */ | ||
1012 | int __ieee80211_suspend(struct ieee80211_hw *hw); | ||
1013 | int __ieee80211_resume(struct ieee80211_hw *hw); | ||
966 | 1014 | ||
967 | /* utility functions/constants */ | 1015 | /* utility functions/constants */ |
968 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 1016 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
@@ -980,12 +1028,15 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
980 | void ieee802_11_parse_elems(u8 *start, size_t len, | 1028 | void ieee802_11_parse_elems(u8 *start, size_t len, |
981 | struct ieee802_11_elems *elems); | 1029 | struct ieee802_11_elems *elems); |
982 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); | 1030 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); |
983 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | 1031 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
984 | enum ieee80211_band band); | 1032 | enum ieee80211_band band); |
985 | 1033 | ||
986 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); | 1034 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); |
987 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); | 1035 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); |
988 | void ieee80211_dynamic_ps_timer(unsigned long data); | 1036 | void ieee80211_dynamic_ps_timer(unsigned long data); |
1037 | void ieee80211_send_nullfunc(struct ieee80211_local *local, | ||
1038 | struct ieee80211_sub_if_data *sdata, | ||
1039 | int powersave); | ||
989 | 1040 | ||
990 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1041 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
991 | enum queue_stop_reason reason); | 1042 | enum queue_stop_reason reason); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b9074824862a..df94b9365264 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -21,6 +21,23 @@ | |||
21 | #include "mesh.h" | 21 | #include "mesh.h" |
22 | #include "led.h" | 22 | #include "led.h" |
23 | 23 | ||
24 | /** | ||
25 | * DOC: Interface list locking | ||
26 | * | ||
27 | * The interface list in each struct ieee80211_local is protected | ||
28 | * three-fold: | ||
29 | * | ||
30 | * (1) modifications may only be done under the RTNL | ||
31 | * (2) modifications and readers are protected against each other by | ||
32 | * the iflist_mtx. | ||
33 | * (3) modifications are done in an RCU manner so atomic readers | ||
34 | * can traverse the list in RCU-safe blocks. | ||
35 | * | ||
36 | * As a consequence, reads (traversals) of the list can be protected | ||
37 | * by either the RTNL, the iflist_mtx or RCU. | ||
38 | */ | ||
39 | |||
40 | |||
24 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | 41 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) |
25 | { | 42 | { |
26 | int meshhdrlen; | 43 | int meshhdrlen; |
@@ -345,8 +362,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
345 | 362 | ||
346 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 363 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
347 | if (sta->sdata == sdata) | 364 | if (sta->sdata == sdata) |
348 | ieee80211_sta_tear_down_BA_sessions(sdata, | 365 | ieee80211_sta_tear_down_BA_sessions(sta); |
349 | sta->sta.addr); | ||
350 | } | 366 | } |
351 | 367 | ||
352 | rcu_read_unlock(); | 368 | rcu_read_unlock(); |
@@ -383,6 +399,8 @@ static int ieee80211_stop(struct net_device *dev) | |||
383 | atomic_dec(&local->iff_promiscs); | 399 | atomic_dec(&local->iff_promiscs); |
384 | 400 | ||
385 | dev_mc_unsync(local->mdev, dev); | 401 | dev_mc_unsync(local->mdev, dev); |
402 | del_timer_sync(&local->dynamic_ps_timer); | ||
403 | cancel_work_sync(&local->dynamic_ps_enable_work); | ||
386 | 404 | ||
387 | /* APs need special treatment */ | 405 | /* APs need special treatment */ |
388 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 406 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
@@ -441,6 +459,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
441 | WLAN_REASON_DEAUTH_LEAVING); | 459 | WLAN_REASON_DEAUTH_LEAVING); |
442 | 460 | ||
443 | memset(sdata->u.sta.bssid, 0, ETH_ALEN); | 461 | memset(sdata->u.sta.bssid, 0, ETH_ALEN); |
462 | del_timer_sync(&sdata->u.sta.chswitch_timer); | ||
444 | del_timer_sync(&sdata->u.sta.timer); | 463 | del_timer_sync(&sdata->u.sta.timer); |
445 | /* | 464 | /* |
446 | * If the timer fired while we waited for it, it will have | 465 | * If the timer fired while we waited for it, it will have |
@@ -450,6 +469,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
450 | * it no longer is. | 469 | * it no longer is. |
451 | */ | 470 | */ |
452 | cancel_work_sync(&sdata->u.sta.work); | 471 | cancel_work_sync(&sdata->u.sta.work); |
472 | cancel_work_sync(&sdata->u.sta.chswitch_work); | ||
453 | /* | 473 | /* |
454 | * When we get here, the interface is marked down. | 474 | * When we get here, the interface is marked down. |
455 | * Call synchronize_rcu() to wait for the RX path | 475 | * Call synchronize_rcu() to wait for the RX path |
@@ -459,7 +479,8 @@ static int ieee80211_stop(struct net_device *dev) | |||
459 | synchronize_rcu(); | 479 | synchronize_rcu(); |
460 | skb_queue_purge(&sdata->u.sta.skb_queue); | 480 | skb_queue_purge(&sdata->u.sta.skb_queue); |
461 | 481 | ||
462 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; | 482 | sdata->u.sta.flags &= ~(IEEE80211_STA_PRIVACY_INVOKED | |
483 | IEEE80211_STA_TKIP_WEP_USED); | ||
463 | kfree(sdata->u.sta.extra_ie); | 484 | kfree(sdata->u.sta.extra_ie); |
464 | sdata->u.sta.extra_ie = NULL; | 485 | sdata->u.sta.extra_ie = NULL; |
465 | sdata->u.sta.extra_ie_len = 0; | 486 | sdata->u.sta.extra_ie_len = 0; |
@@ -501,7 +522,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
501 | * scan event to userspace -- the scan is incomplete. | 522 | * scan event to userspace -- the scan is incomplete. |
502 | */ | 523 | */ |
503 | if (local->sw_scanning) | 524 | if (local->sw_scanning) |
504 | ieee80211_scan_completed(&local->hw); | 525 | ieee80211_scan_completed(&local->hw, true); |
505 | } | 526 | } |
506 | 527 | ||
507 | conf.vif = &sdata->vif; | 528 | conf.vif = &sdata->vif; |
@@ -569,19 +590,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
569 | dev_mc_sync(local->mdev, dev); | 590 | dev_mc_sync(local->mdev, dev); |
570 | } | 591 | } |
571 | 592 | ||
572 | static void ieee80211_if_setup(struct net_device *dev) | ||
573 | { | ||
574 | ether_setup(dev); | ||
575 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
576 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
577 | dev->set_multicast_list = ieee80211_set_multicast_list; | ||
578 | dev->change_mtu = ieee80211_change_mtu; | ||
579 | dev->open = ieee80211_open; | ||
580 | dev->stop = ieee80211_stop; | ||
581 | dev->destructor = free_netdev; | ||
582 | /* we will validate the address ourselves in ->open */ | ||
583 | dev->validate_addr = NULL; | ||
584 | } | ||
585 | /* | 593 | /* |
586 | * Called when the netdev is removed or, by the code below, before | 594 | * Called when the netdev is removed or, by the code below, before |
587 | * the interface type changes. | 595 | * the interface type changes. |
@@ -627,6 +635,13 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
627 | kfree(sdata->u.sta.assocreq_ies); | 635 | kfree(sdata->u.sta.assocreq_ies); |
628 | kfree(sdata->u.sta.assocresp_ies); | 636 | kfree(sdata->u.sta.assocresp_ies); |
629 | kfree_skb(sdata->u.sta.probe_resp); | 637 | kfree_skb(sdata->u.sta.probe_resp); |
638 | kfree(sdata->u.sta.ie_probereq); | ||
639 | kfree(sdata->u.sta.ie_proberesp); | ||
640 | kfree(sdata->u.sta.ie_auth); | ||
641 | kfree(sdata->u.sta.ie_assocreq); | ||
642 | kfree(sdata->u.sta.ie_reassocreq); | ||
643 | kfree(sdata->u.sta.ie_deauth); | ||
644 | kfree(sdata->u.sta.ie_disassoc); | ||
630 | break; | 645 | break; |
631 | case NL80211_IFTYPE_WDS: | 646 | case NL80211_IFTYPE_WDS: |
632 | case NL80211_IFTYPE_AP_VLAN: | 647 | case NL80211_IFTYPE_AP_VLAN: |
@@ -642,6 +657,34 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
642 | WARN_ON(flushed); | 657 | WARN_ON(flushed); |
643 | } | 658 | } |
644 | 659 | ||
660 | static const struct net_device_ops ieee80211_dataif_ops = { | ||
661 | .ndo_open = ieee80211_open, | ||
662 | .ndo_stop = ieee80211_stop, | ||
663 | .ndo_uninit = ieee80211_teardown_sdata, | ||
664 | .ndo_start_xmit = ieee80211_subif_start_xmit, | ||
665 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | ||
666 | .ndo_change_mtu = ieee80211_change_mtu, | ||
667 | .ndo_set_mac_address = eth_mac_addr, | ||
668 | }; | ||
669 | |||
670 | static const struct net_device_ops ieee80211_monitorif_ops = { | ||
671 | .ndo_open = ieee80211_open, | ||
672 | .ndo_stop = ieee80211_stop, | ||
673 | .ndo_uninit = ieee80211_teardown_sdata, | ||
674 | .ndo_start_xmit = ieee80211_monitor_start_xmit, | ||
675 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | ||
676 | .ndo_change_mtu = ieee80211_change_mtu, | ||
677 | .ndo_set_mac_address = eth_mac_addr, | ||
678 | }; | ||
679 | |||
680 | static void ieee80211_if_setup(struct net_device *dev) | ||
681 | { | ||
682 | ether_setup(dev); | ||
683 | dev->netdev_ops = &ieee80211_dataif_ops; | ||
684 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
685 | dev->destructor = free_netdev; | ||
686 | } | ||
687 | |||
645 | /* | 688 | /* |
646 | * Helper function to initialise an interface to a specific type. | 689 | * Helper function to initialise an interface to a specific type. |
647 | */ | 690 | */ |
@@ -653,7 +696,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
653 | 696 | ||
654 | /* and set some type-dependent values */ | 697 | /* and set some type-dependent values */ |
655 | sdata->vif.type = type; | 698 | sdata->vif.type = type; |
656 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; | 699 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; |
657 | sdata->wdev.iftype = type; | 700 | sdata->wdev.iftype = type; |
658 | 701 | ||
659 | /* only monitor differs */ | 702 | /* only monitor differs */ |
@@ -674,7 +717,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
674 | break; | 717 | break; |
675 | case NL80211_IFTYPE_MONITOR: | 718 | case NL80211_IFTYPE_MONITOR: |
676 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; | 719 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; |
677 | sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; | 720 | sdata->dev->netdev_ops = &ieee80211_monitorif_ops; |
678 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | | 721 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | |
679 | MONITOR_FLAG_OTHER_BSS; | 722 | MONITOR_FLAG_OTHER_BSS; |
680 | break; | 723 | break; |
@@ -780,15 +823,15 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
780 | if (ret) | 823 | if (ret) |
781 | goto fail; | 824 | goto fail; |
782 | 825 | ||
783 | ndev->uninit = ieee80211_teardown_sdata; | ||
784 | |||
785 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 826 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
786 | params && params->mesh_id_len) | 827 | params && params->mesh_id_len) |
787 | ieee80211_sdata_set_mesh_id(sdata, | 828 | ieee80211_sdata_set_mesh_id(sdata, |
788 | params->mesh_id_len, | 829 | params->mesh_id_len, |
789 | params->mesh_id); | 830 | params->mesh_id); |
790 | 831 | ||
832 | mutex_lock(&local->iflist_mtx); | ||
791 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 833 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
834 | mutex_unlock(&local->iflist_mtx); | ||
792 | 835 | ||
793 | if (new_dev) | 836 | if (new_dev) |
794 | *new_dev = ndev; | 837 | *new_dev = ndev; |
@@ -804,7 +847,10 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | |||
804 | { | 847 | { |
805 | ASSERT_RTNL(); | 848 | ASSERT_RTNL(); |
806 | 849 | ||
850 | mutex_lock(&sdata->local->iflist_mtx); | ||
807 | list_del_rcu(&sdata->list); | 851 | list_del_rcu(&sdata->list); |
852 | mutex_unlock(&sdata->local->iflist_mtx); | ||
853 | |||
808 | synchronize_rcu(); | 854 | synchronize_rcu(); |
809 | unregister_netdevice(sdata->dev); | 855 | unregister_netdevice(sdata->dev); |
810 | } | 856 | } |
@@ -820,7 +866,16 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
820 | ASSERT_RTNL(); | 866 | ASSERT_RTNL(); |
821 | 867 | ||
822 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 868 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
869 | /* | ||
870 | * we cannot hold the iflist_mtx across unregister_netdevice, | ||
871 | * but we only need to hold it for list modifications to lock | ||
872 | * out readers since we're under the RTNL here as all other | ||
873 | * writers. | ||
874 | */ | ||
875 | mutex_lock(&local->iflist_mtx); | ||
823 | list_del(&sdata->list); | 876 | list_del(&sdata->list); |
877 | mutex_unlock(&local->iflist_mtx); | ||
878 | |||
824 | unregister_netdevice(sdata->dev); | 879 | unregister_netdevice(sdata->dev); |
825 | } | 880 | } |
826 | } | 881 | } |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 999f7aa42326..19b480de4bbc 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "debugfs_key.h" | 19 | #include "debugfs_key.h" |
20 | #include "aes_ccm.h" | 20 | #include "aes_ccm.h" |
21 | #include "aes_cmac.h" | ||
21 | 22 | ||
22 | 23 | ||
23 | /** | 24 | /** |
@@ -47,7 +48,6 @@ | |||
47 | */ | 48 | */ |
48 | 49 | ||
49 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 50 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
50 | static const u8 zero_addr[ETH_ALEN]; | ||
51 | 51 | ||
52 | /* key mutex: used to synchronise todo runners */ | 52 | /* key mutex: used to synchronise todo runners */ |
53 | static DEFINE_MUTEX(key_mutex); | 53 | static DEFINE_MUTEX(key_mutex); |
@@ -108,29 +108,18 @@ static void assert_key_lock(void) | |||
108 | WARN_ON(!mutex_is_locked(&key_mutex)); | 108 | WARN_ON(!mutex_is_locked(&key_mutex)); |
109 | } | 109 | } |
110 | 110 | ||
111 | static const u8 *get_mac_for_key(struct ieee80211_key *key) | 111 | static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) |
112 | { | 112 | { |
113 | const u8 *addr = bcast_addr; | ||
114 | |||
115 | /* | ||
116 | * If we're an AP we won't ever receive frames with a non-WEP | ||
117 | * group key so we tell the driver that by using the zero MAC | ||
118 | * address to indicate a transmit-only key. | ||
119 | */ | ||
120 | if (key->conf.alg != ALG_WEP && | ||
121 | (key->sdata->vif.type == NL80211_IFTYPE_AP || | ||
122 | key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | ||
123 | addr = zero_addr; | ||
124 | |||
125 | if (key->sta) | 113 | if (key->sta) |
126 | addr = key->sta->sta.addr; | 114 | return &key->sta->sta; |
127 | 115 | ||
128 | return addr; | 116 | return NULL; |
129 | } | 117 | } |
130 | 118 | ||
131 | static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | 119 | static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) |
132 | { | 120 | { |
133 | const u8 *addr; | 121 | struct ieee80211_sub_if_data *sdata; |
122 | struct ieee80211_sta *sta; | ||
134 | int ret; | 123 | int ret; |
135 | 124 | ||
136 | assert_key_lock(); | 125 | assert_key_lock(); |
@@ -139,11 +128,16 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
139 | if (!key->local->ops->set_key) | 128 | if (!key->local->ops->set_key) |
140 | return; | 129 | return; |
141 | 130 | ||
142 | addr = get_mac_for_key(key); | 131 | sta = get_sta_for_key(key); |
132 | |||
133 | sdata = key->sdata; | ||
134 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
135 | sdata = container_of(sdata->bss, | ||
136 | struct ieee80211_sub_if_data, | ||
137 | u.ap); | ||
143 | 138 | ||
144 | ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, | 139 | ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, |
145 | key->sdata->dev->dev_addr, addr, | 140 | &sdata->vif, sta, &key->conf); |
146 | &key->conf); | ||
147 | 141 | ||
148 | if (!ret) { | 142 | if (!ret) { |
149 | spin_lock(&todo_lock); | 143 | spin_lock(&todo_lock); |
@@ -155,12 +149,13 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
155 | printk(KERN_ERR "mac80211-%s: failed to set key " | 149 | printk(KERN_ERR "mac80211-%s: failed to set key " |
156 | "(%d, %pM) to hardware (%d)\n", | 150 | "(%d, %pM) to hardware (%d)\n", |
157 | wiphy_name(key->local->hw.wiphy), | 151 | wiphy_name(key->local->hw.wiphy), |
158 | key->conf.keyidx, addr, ret); | 152 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
159 | } | 153 | } |
160 | 154 | ||
161 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | 155 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) |
162 | { | 156 | { |
163 | const u8 *addr; | 157 | struct ieee80211_sub_if_data *sdata; |
158 | struct ieee80211_sta *sta; | ||
164 | int ret; | 159 | int ret; |
165 | 160 | ||
166 | assert_key_lock(); | 161 | assert_key_lock(); |
@@ -176,17 +171,22 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
176 | } | 171 | } |
177 | spin_unlock(&todo_lock); | 172 | spin_unlock(&todo_lock); |
178 | 173 | ||
179 | addr = get_mac_for_key(key); | 174 | sta = get_sta_for_key(key); |
175 | sdata = key->sdata; | ||
176 | |||
177 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
178 | sdata = container_of(sdata->bss, | ||
179 | struct ieee80211_sub_if_data, | ||
180 | u.ap); | ||
180 | 181 | ||
181 | ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, | 182 | ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, |
182 | key->sdata->dev->dev_addr, addr, | 183 | &sdata->vif, sta, &key->conf); |
183 | &key->conf); | ||
184 | 184 | ||
185 | if (ret) | 185 | if (ret) |
186 | printk(KERN_ERR "mac80211-%s: failed to remove key " | 186 | printk(KERN_ERR "mac80211-%s: failed to remove key " |
187 | "(%d, %pM) from hardware (%d)\n", | 187 | "(%d, %pM) from hardware (%d)\n", |
188 | wiphy_name(key->local->hw.wiphy), | 188 | wiphy_name(key->local->hw.wiphy), |
189 | key->conf.keyidx, addr, ret); | 189 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
190 | 190 | ||
191 | spin_lock(&todo_lock); | 191 | spin_lock(&todo_lock); |
192 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 192 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
@@ -216,13 +216,38 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) | |||
216 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | 216 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
217 | } | 217 | } |
218 | 218 | ||
219 | static void | ||
220 | __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) | ||
221 | { | ||
222 | struct ieee80211_key *key = NULL; | ||
223 | |||
224 | if (idx >= NUM_DEFAULT_KEYS && | ||
225 | idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
226 | key = sdata->keys[idx]; | ||
227 | |||
228 | rcu_assign_pointer(sdata->default_mgmt_key, key); | ||
229 | |||
230 | if (key) | ||
231 | add_todo(key, KEY_FLAG_TODO_DEFMGMTKEY); | ||
232 | } | ||
233 | |||
234 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | ||
235 | int idx) | ||
236 | { | ||
237 | unsigned long flags; | ||
238 | |||
239 | spin_lock_irqsave(&sdata->local->key_lock, flags); | ||
240 | __ieee80211_set_default_mgmt_key(sdata, idx); | ||
241 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | ||
242 | } | ||
243 | |||
219 | 244 | ||
220 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | 245 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, |
221 | struct sta_info *sta, | 246 | struct sta_info *sta, |
222 | struct ieee80211_key *old, | 247 | struct ieee80211_key *old, |
223 | struct ieee80211_key *new) | 248 | struct ieee80211_key *new) |
224 | { | 249 | { |
225 | int idx, defkey; | 250 | int idx, defkey, defmgmtkey; |
226 | 251 | ||
227 | if (new) | 252 | if (new) |
228 | list_add(&new->list, &sdata->key_list); | 253 | list_add(&new->list, &sdata->key_list); |
@@ -238,13 +263,19 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
238 | idx = new->conf.keyidx; | 263 | idx = new->conf.keyidx; |
239 | 264 | ||
240 | defkey = old && sdata->default_key == old; | 265 | defkey = old && sdata->default_key == old; |
266 | defmgmtkey = old && sdata->default_mgmt_key == old; | ||
241 | 267 | ||
242 | if (defkey && !new) | 268 | if (defkey && !new) |
243 | __ieee80211_set_default_key(sdata, -1); | 269 | __ieee80211_set_default_key(sdata, -1); |
270 | if (defmgmtkey && !new) | ||
271 | __ieee80211_set_default_mgmt_key(sdata, -1); | ||
244 | 272 | ||
245 | rcu_assign_pointer(sdata->keys[idx], new); | 273 | rcu_assign_pointer(sdata->keys[idx], new); |
246 | if (defkey && new) | 274 | if (defkey && new) |
247 | __ieee80211_set_default_key(sdata, new->conf.keyidx); | 275 | __ieee80211_set_default_key(sdata, new->conf.keyidx); |
276 | if (defmgmtkey && new) | ||
277 | __ieee80211_set_default_mgmt_key(sdata, | ||
278 | new->conf.keyidx); | ||
248 | } | 279 | } |
249 | 280 | ||
250 | if (old) { | 281 | if (old) { |
@@ -263,7 +294,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
263 | { | 294 | { |
264 | struct ieee80211_key *key; | 295 | struct ieee80211_key *key; |
265 | 296 | ||
266 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS); | 297 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); |
267 | 298 | ||
268 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); | 299 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); |
269 | if (!key) | 300 | if (!key) |
@@ -292,6 +323,10 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
292 | key->conf.iv_len = CCMP_HDR_LEN; | 323 | key->conf.iv_len = CCMP_HDR_LEN; |
293 | key->conf.icv_len = CCMP_MIC_LEN; | 324 | key->conf.icv_len = CCMP_MIC_LEN; |
294 | break; | 325 | break; |
326 | case ALG_AES_CMAC: | ||
327 | key->conf.iv_len = 0; | ||
328 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | ||
329 | break; | ||
295 | } | 330 | } |
296 | memcpy(key->conf.key, key_data, key_len); | 331 | memcpy(key->conf.key, key_data, key_len); |
297 | INIT_LIST_HEAD(&key->list); | 332 | INIT_LIST_HEAD(&key->list); |
@@ -309,6 +344,19 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
309 | } | 344 | } |
310 | } | 345 | } |
311 | 346 | ||
347 | if (alg == ALG_AES_CMAC) { | ||
348 | /* | ||
349 | * Initialize AES key state here as an optimization so that | ||
350 | * it does not need to be initialized for every packet. | ||
351 | */ | ||
352 | key->u.aes_cmac.tfm = | ||
353 | ieee80211_aes_cmac_key_setup(key_data); | ||
354 | if (!key->u.aes_cmac.tfm) { | ||
355 | kfree(key); | ||
356 | return NULL; | ||
357 | } | ||
358 | } | ||
359 | |||
312 | return key; | 360 | return key; |
313 | } | 361 | } |
314 | 362 | ||
@@ -462,6 +510,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
462 | 510 | ||
463 | if (key->conf.alg == ALG_CCMP) | 511 | if (key->conf.alg == ALG_CCMP) |
464 | ieee80211_aes_key_free(key->u.ccmp.tfm); | 512 | ieee80211_aes_key_free(key->u.ccmp.tfm); |
513 | if (key->conf.alg == ALG_AES_CMAC) | ||
514 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | ||
465 | ieee80211_debugfs_key_remove(key); | 515 | ieee80211_debugfs_key_remove(key); |
466 | 516 | ||
467 | kfree(key); | 517 | kfree(key); |
@@ -484,6 +534,7 @@ static void __ieee80211_key_todo(void) | |||
484 | list_del_init(&key->todo); | 534 | list_del_init(&key->todo); |
485 | todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | | 535 | todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | |
486 | KEY_FLAG_TODO_DEFKEY | | 536 | KEY_FLAG_TODO_DEFKEY | |
537 | KEY_FLAG_TODO_DEFMGMTKEY | | ||
487 | KEY_FLAG_TODO_HWACCEL_ADD | | 538 | KEY_FLAG_TODO_HWACCEL_ADD | |
488 | KEY_FLAG_TODO_HWACCEL_REMOVE | | 539 | KEY_FLAG_TODO_HWACCEL_REMOVE | |
489 | KEY_FLAG_TODO_DELETE); | 540 | KEY_FLAG_TODO_DELETE); |
@@ -501,6 +552,11 @@ static void __ieee80211_key_todo(void) | |||
501 | ieee80211_debugfs_key_add_default(key->sdata); | 552 | ieee80211_debugfs_key_add_default(key->sdata); |
502 | work_done = true; | 553 | work_done = true; |
503 | } | 554 | } |
555 | if (todoflags & KEY_FLAG_TODO_DEFMGMTKEY) { | ||
556 | ieee80211_debugfs_key_remove_mgmt_default(key->sdata); | ||
557 | ieee80211_debugfs_key_add_mgmt_default(key->sdata); | ||
558 | work_done = true; | ||
559 | } | ||
504 | if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { | 560 | if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { |
505 | ieee80211_key_enable_hw_accel(key); | 561 | ieee80211_key_enable_hw_accel(key); |
506 | work_done = true; | 562 | work_done = true; |
@@ -536,6 +592,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | |||
536 | ieee80211_key_lock(); | 592 | ieee80211_key_lock(); |
537 | 593 | ||
538 | ieee80211_debugfs_key_remove_default(sdata); | 594 | ieee80211_debugfs_key_remove_default(sdata); |
595 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | ||
539 | 596 | ||
540 | spin_lock_irqsave(&sdata->local->key_lock, flags); | 597 | spin_lock_irqsave(&sdata->local->key_lock, flags); |
541 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 598 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 425816e0996c..215d3ef42a4f 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -46,6 +46,8 @@ struct sta_info; | |||
46 | * acceleration. | 46 | * acceleration. |
47 | * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. | 47 | * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. |
48 | * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. | 48 | * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. |
49 | * @KEY_FLAG_TODO_DEFMGMTKEY: Key is default management key and debugfs needs | ||
50 | * to be updated. | ||
49 | */ | 51 | */ |
50 | enum ieee80211_internal_key_flags { | 52 | enum ieee80211_internal_key_flags { |
51 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), | 53 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), |
@@ -54,6 +56,7 @@ enum ieee80211_internal_key_flags { | |||
54 | KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3), | 56 | KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3), |
55 | KEY_FLAG_TODO_DEFKEY = BIT(4), | 57 | KEY_FLAG_TODO_DEFKEY = BIT(4), |
56 | KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), | 58 | KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), |
59 | KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), | ||
57 | }; | 60 | }; |
58 | 61 | ||
59 | struct tkip_ctx { | 62 | struct tkip_ctx { |
@@ -96,6 +99,16 @@ struct ieee80211_key { | |||
96 | u8 tx_crypto_buf[6 * AES_BLOCK_LEN]; | 99 | u8 tx_crypto_buf[6 * AES_BLOCK_LEN]; |
97 | u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; | 100 | u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; |
98 | } ccmp; | 101 | } ccmp; |
102 | struct { | ||
103 | u8 tx_pn[6]; | ||
104 | u8 rx_pn[6]; | ||
105 | struct crypto_cipher *tfm; | ||
106 | u32 replays; /* dot11RSNAStatsCMACReplays */ | ||
107 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ | ||
108 | /* scratch buffers for virt_to_page() (crypto API) */ | ||
109 | u8 tx_crypto_buf[2 * AES_BLOCK_LEN]; | ||
110 | u8 rx_crypto_buf[2 * AES_BLOCK_LEN]; | ||
111 | } aes_cmac; | ||
99 | } u; | 112 | } u; |
100 | 113 | ||
101 | /* number of times this key has been used */ | 114 | /* number of times this key has been used */ |
@@ -114,6 +127,7 @@ struct ieee80211_key { | |||
114 | struct dentry *tx_spec; | 127 | struct dentry *tx_spec; |
115 | struct dentry *rx_spec; | 128 | struct dentry *rx_spec; |
116 | struct dentry *replays; | 129 | struct dentry *replays; |
130 | struct dentry *icverrors; | ||
117 | struct dentry *key; | 131 | struct dentry *key; |
118 | struct dentry *ifindex; | 132 | struct dentry *ifindex; |
119 | int cnt; | 133 | int cnt; |
@@ -140,6 +154,8 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
140 | struct sta_info *sta); | 154 | struct sta_info *sta); |
141 | void ieee80211_key_free(struct ieee80211_key *key); | 155 | void ieee80211_key_free(struct ieee80211_key *key); |
142 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); | 156 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); |
157 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | ||
158 | int idx); | ||
143 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 159 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
144 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 160 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
145 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); | 161 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 24b14363d6e7..5667f4e8067f 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -168,7 +168,6 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | |||
168 | return 0; | 168 | return 0; |
169 | 169 | ||
170 | memset(&conf, 0, sizeof(conf)); | 170 | memset(&conf, 0, sizeof(conf)); |
171 | conf.changed = changed; | ||
172 | 171 | ||
173 | if (sdata->vif.type == NL80211_IFTYPE_STATION || | 172 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
174 | sdata->vif.type == NL80211_IFTYPE_ADHOC) | 173 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
@@ -176,16 +175,59 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | |||
176 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | 175 | else if (sdata->vif.type == NL80211_IFTYPE_AP) |
177 | conf.bssid = sdata->dev->dev_addr; | 176 | conf.bssid = sdata->dev->dev_addr; |
178 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 177 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
179 | u8 zero[ETH_ALEN] = { 0 }; | 178 | static const u8 zero[ETH_ALEN] = { 0 }; |
180 | conf.bssid = zero; | 179 | conf.bssid = zero; |
181 | } else { | 180 | } else { |
182 | WARN_ON(1); | 181 | WARN_ON(1); |
183 | return -EINVAL; | 182 | return -EINVAL; |
184 | } | 183 | } |
185 | 184 | ||
185 | switch (sdata->vif.type) { | ||
186 | case NL80211_IFTYPE_AP: | ||
187 | case NL80211_IFTYPE_ADHOC: | ||
188 | case NL80211_IFTYPE_MESH_POINT: | ||
189 | break; | ||
190 | default: | ||
191 | /* do not warn to simplify caller in scan.c */ | ||
192 | changed &= ~IEEE80211_IFCC_BEACON_ENABLED; | ||
193 | if (WARN_ON(changed & IEEE80211_IFCC_BEACON)) | ||
194 | return -EINVAL; | ||
195 | changed &= ~IEEE80211_IFCC_BEACON; | ||
196 | break; | ||
197 | } | ||
198 | |||
199 | if (changed & IEEE80211_IFCC_BEACON_ENABLED) { | ||
200 | if (local->sw_scanning) { | ||
201 | conf.enable_beacon = false; | ||
202 | } else { | ||
203 | /* | ||
204 | * Beacon should be enabled, but AP mode must | ||
205 | * check whether there is a beacon configured. | ||
206 | */ | ||
207 | switch (sdata->vif.type) { | ||
208 | case NL80211_IFTYPE_AP: | ||
209 | conf.enable_beacon = | ||
210 | !!rcu_dereference(sdata->u.ap.beacon); | ||
211 | break; | ||
212 | case NL80211_IFTYPE_ADHOC: | ||
213 | conf.enable_beacon = !!sdata->u.sta.probe_resp; | ||
214 | break; | ||
215 | case NL80211_IFTYPE_MESH_POINT: | ||
216 | conf.enable_beacon = true; | ||
217 | break; | ||
218 | default: | ||
219 | /* not reached */ | ||
220 | WARN_ON(1); | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | |||
186 | if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) | 226 | if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) |
187 | return -EINVAL; | 227 | return -EINVAL; |
188 | 228 | ||
229 | conf.changed = changed; | ||
230 | |||
189 | return local->ops->config_interface(local_to_hw(local), | 231 | return local->ops->config_interface(local_to_hw(local), |
190 | &sdata->vif, &conf); | 232 | &sdata->vif, &conf); |
191 | } | 233 | } |
@@ -208,26 +250,22 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
208 | } | 250 | } |
209 | 251 | ||
210 | if (chan != local->hw.conf.channel || | 252 | if (chan != local->hw.conf.channel || |
211 | channel_type != local->hw.conf.ht.channel_type) { | 253 | channel_type != local->hw.conf.channel_type) { |
212 | local->hw.conf.channel = chan; | 254 | local->hw.conf.channel = chan; |
213 | local->hw.conf.ht.channel_type = channel_type; | 255 | local->hw.conf.channel_type = channel_type; |
214 | switch (channel_type) { | ||
215 | case NL80211_CHAN_NO_HT: | ||
216 | local->hw.conf.ht.enabled = false; | ||
217 | break; | ||
218 | case NL80211_CHAN_HT20: | ||
219 | case NL80211_CHAN_HT40MINUS: | ||
220 | case NL80211_CHAN_HT40PLUS: | ||
221 | local->hw.conf.ht.enabled = true; | ||
222 | break; | ||
223 | } | ||
224 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 256 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
225 | } | 257 | } |
226 | 258 | ||
227 | if (!local->hw.conf.power_level) | 259 | if (local->sw_scanning) |
228 | power = chan->max_power; | 260 | power = chan->max_power; |
229 | else | 261 | else |
230 | power = min(chan->max_power, local->hw.conf.power_level); | 262 | power = local->power_constr_level ? |
263 | (chan->max_power - local->power_constr_level) : | ||
264 | chan->max_power; | ||
265 | |||
266 | if (local->user_power_level) | ||
267 | power = min(power, local->user_power_level); | ||
268 | |||
231 | if (local->hw.conf.power_level != power) { | 269 | if (local->hw.conf.power_level != power) { |
232 | changed |= IEEE80211_CONF_CHANGE_POWER; | 270 | changed |= IEEE80211_CONF_CHANGE_POWER; |
233 | local->hw.conf.power_level = power; | 271 | local->hw.conf.power_level = power; |
@@ -695,6 +733,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
695 | return NULL; | 733 | return NULL; |
696 | 734 | ||
697 | wiphy->privid = mac80211_wiphy_privid; | 735 | wiphy->privid = mac80211_wiphy_privid; |
736 | wiphy->max_scan_ssids = 4; | ||
737 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ | ||
738 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - | ||
739 | sizeof(struct cfg80211_bss); | ||
698 | 740 | ||
699 | local = wiphy_priv(wiphy); | 741 | local = wiphy_priv(wiphy); |
700 | local->hw.wiphy = wiphy; | 742 | local->hw.wiphy = wiphy; |
@@ -722,6 +764,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
722 | local->hw.conf.radio_enabled = true; | 764 | local->hw.conf.radio_enabled = true; |
723 | 765 | ||
724 | INIT_LIST_HEAD(&local->interfaces); | 766 | INIT_LIST_HEAD(&local->interfaces); |
767 | mutex_init(&local->iflist_mtx); | ||
725 | 768 | ||
726 | spin_lock_init(&local->key_lock); | 769 | spin_lock_init(&local->key_lock); |
727 | 770 | ||
@@ -754,6 +797,23 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
754 | } | 797 | } |
755 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 798 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
756 | 799 | ||
800 | static const struct net_device_ops ieee80211_master_ops = { | ||
801 | .ndo_start_xmit = ieee80211_master_start_xmit, | ||
802 | .ndo_open = ieee80211_master_open, | ||
803 | .ndo_stop = ieee80211_master_stop, | ||
804 | .ndo_set_multicast_list = ieee80211_master_set_multicast_list, | ||
805 | .ndo_select_queue = ieee80211_select_queue, | ||
806 | }; | ||
807 | |||
808 | static void ieee80211_master_setup(struct net_device *mdev) | ||
809 | { | ||
810 | mdev->type = ARPHRD_IEEE80211; | ||
811 | mdev->netdev_ops = &ieee80211_master_ops; | ||
812 | mdev->header_ops = &ieee80211_header_ops; | ||
813 | mdev->tx_queue_len = 1000; | ||
814 | mdev->addr_len = ETH_ALEN; | ||
815 | } | ||
816 | |||
757 | int ieee80211_register_hw(struct ieee80211_hw *hw) | 817 | int ieee80211_register_hw(struct ieee80211_hw *hw) |
758 | { | 818 | { |
759 | struct ieee80211_local *local = hw_to_local(hw); | 819 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -761,25 +821,33 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
761 | enum ieee80211_band band; | 821 | enum ieee80211_band band; |
762 | struct net_device *mdev; | 822 | struct net_device *mdev; |
763 | struct ieee80211_master_priv *mpriv; | 823 | struct ieee80211_master_priv *mpriv; |
824 | int channels, i, j; | ||
764 | 825 | ||
765 | /* | 826 | /* |
766 | * generic code guarantees at least one band, | 827 | * generic code guarantees at least one band, |
767 | * set this very early because much code assumes | 828 | * set this very early because much code assumes |
768 | * that hw.conf.channel is assigned | 829 | * that hw.conf.channel is assigned |
769 | */ | 830 | */ |
831 | channels = 0; | ||
770 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 832 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
771 | struct ieee80211_supported_band *sband; | 833 | struct ieee80211_supported_band *sband; |
772 | 834 | ||
773 | sband = local->hw.wiphy->bands[band]; | 835 | sband = local->hw.wiphy->bands[band]; |
774 | if (sband) { | 836 | if (sband && !local->oper_channel) { |
775 | /* init channel we're on */ | 837 | /* init channel we're on */ |
776 | local->hw.conf.channel = | 838 | local->hw.conf.channel = |
777 | local->oper_channel = | 839 | local->oper_channel = |
778 | local->scan_channel = &sband->channels[0]; | 840 | local->scan_channel = &sband->channels[0]; |
779 | break; | ||
780 | } | 841 | } |
842 | if (sband) | ||
843 | channels += sband->n_channels; | ||
781 | } | 844 | } |
782 | 845 | ||
846 | local->int_scan_req.n_channels = channels; | ||
847 | local->int_scan_req.channels = kzalloc(sizeof(void *) * channels, GFP_KERNEL); | ||
848 | if (!local->int_scan_req.channels) | ||
849 | return -ENOMEM; | ||
850 | |||
783 | /* if low-level driver supports AP, we also support VLAN */ | 851 | /* if low-level driver supports AP, we also support VLAN */ |
784 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) | 852 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) |
785 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | 853 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); |
@@ -789,7 +857,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
789 | 857 | ||
790 | result = wiphy_register(local->hw.wiphy); | 858 | result = wiphy_register(local->hw.wiphy); |
791 | if (result < 0) | 859 | if (result < 0) |
792 | return result; | 860 | goto fail_wiphy_register; |
793 | 861 | ||
794 | /* | 862 | /* |
795 | * We use the number of queues for feature tests (QoS, HT) internally | 863 | * We use the number of queues for feature tests (QoS, HT) internally |
@@ -803,7 +871,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
803 | hw->ampdu_queues = 0; | 871 | hw->ampdu_queues = 0; |
804 | 872 | ||
805 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), | 873 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), |
806 | "wmaster%d", ether_setup, | 874 | "wmaster%d", ieee80211_master_setup, |
807 | ieee80211_num_queues(hw)); | 875 | ieee80211_num_queues(hw)); |
808 | if (!mdev) | 876 | if (!mdev) |
809 | goto fail_mdev_alloc; | 877 | goto fail_mdev_alloc; |
@@ -812,17 +880,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
812 | mpriv->local = local; | 880 | mpriv->local = local; |
813 | local->mdev = mdev; | 881 | local->mdev = mdev; |
814 | 882 | ||
815 | ieee80211_rx_bss_list_init(local); | ||
816 | |||
817 | mdev->hard_start_xmit = ieee80211_master_start_xmit; | ||
818 | mdev->open = ieee80211_master_open; | ||
819 | mdev->stop = ieee80211_master_stop; | ||
820 | mdev->type = ARPHRD_IEEE80211; | ||
821 | mdev->header_ops = &ieee80211_header_ops; | ||
822 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | ||
823 | |||
824 | local->hw.workqueue = | 883 | local->hw.workqueue = |
825 | create_freezeable_workqueue(wiphy_name(local->hw.wiphy)); | 884 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); |
826 | if (!local->hw.workqueue) { | 885 | if (!local->hw.workqueue) { |
827 | result = -ENOMEM; | 886 | result = -ENOMEM; |
828 | goto fail_workqueue; | 887 | goto fail_workqueue; |
@@ -846,15 +905,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
846 | 905 | ||
847 | local->hw.conf.listen_interval = local->hw.max_listen_interval; | 906 | local->hw.conf.listen_interval = local->hw.max_listen_interval; |
848 | 907 | ||
849 | local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | | ||
850 | IEEE80211_HW_SIGNAL_DB | | ||
851 | IEEE80211_HW_SIGNAL_DBM) ? | ||
852 | IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; | ||
853 | local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ? | ||
854 | IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID; | ||
855 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
856 | local->wstats_flags |= IW_QUAL_DBM; | ||
857 | |||
858 | result = sta_info_start(local); | 908 | result = sta_info_start(local); |
859 | if (result < 0) | 909 | if (result < 0) |
860 | goto fail_sta_info; | 910 | goto fail_sta_info; |
@@ -887,8 +937,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
887 | goto fail_wep; | 937 | goto fail_wep; |
888 | } | 938 | } |
889 | 939 | ||
890 | local->mdev->select_queue = ieee80211_select_queue; | ||
891 | |||
892 | /* add one default STA interface if supported */ | 940 | /* add one default STA interface if supported */ |
893 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { | 941 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { |
894 | result = ieee80211_if_add(local, "wlan%d", NULL, | 942 | result = ieee80211_if_add(local, "wlan%d", NULL, |
@@ -902,6 +950,20 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
902 | 950 | ||
903 | ieee80211_led_init(local); | 951 | ieee80211_led_init(local); |
904 | 952 | ||
953 | /* alloc internal scan request */ | ||
954 | i = 0; | ||
955 | local->int_scan_req.ssids = &local->scan_ssid; | ||
956 | local->int_scan_req.n_ssids = 1; | ||
957 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
958 | if (!hw->wiphy->bands[band]) | ||
959 | continue; | ||
960 | for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) { | ||
961 | local->int_scan_req.channels[i] = | ||
962 | &hw->wiphy->bands[band]->channels[j]; | ||
963 | i++; | ||
964 | } | ||
965 | } | ||
966 | |||
905 | return 0; | 967 | return 0; |
906 | 968 | ||
907 | fail_wep: | 969 | fail_wep: |
@@ -920,6 +982,8 @@ fail_workqueue: | |||
920 | free_netdev(local->mdev); | 982 | free_netdev(local->mdev); |
921 | fail_mdev_alloc: | 983 | fail_mdev_alloc: |
922 | wiphy_unregister(local->hw.wiphy); | 984 | wiphy_unregister(local->hw.wiphy); |
985 | fail_wiphy_register: | ||
986 | kfree(local->int_scan_req.channels); | ||
923 | return result; | 987 | return result; |
924 | } | 988 | } |
925 | EXPORT_SYMBOL(ieee80211_register_hw); | 989 | EXPORT_SYMBOL(ieee80211_register_hw); |
@@ -947,7 +1011,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
947 | 1011 | ||
948 | rtnl_unlock(); | 1012 | rtnl_unlock(); |
949 | 1013 | ||
950 | ieee80211_rx_bss_list_deinit(local); | ||
951 | ieee80211_clear_tx_pending(local); | 1014 | ieee80211_clear_tx_pending(local); |
952 | sta_info_stop(local); | 1015 | sta_info_stop(local); |
953 | rate_control_deinitialize(local); | 1016 | rate_control_deinitialize(local); |
@@ -965,6 +1028,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
965 | ieee80211_wep_free(local); | 1028 | ieee80211_wep_free(local); |
966 | ieee80211_led_exit(local); | 1029 | ieee80211_led_exit(local); |
967 | free_netdev(local->mdev); | 1030 | free_netdev(local->mdev); |
1031 | kfree(local->int_scan_req.channels); | ||
968 | } | 1032 | } |
969 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 1033 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
970 | 1034 | ||
@@ -972,6 +1036,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
972 | { | 1036 | { |
973 | struct ieee80211_local *local = hw_to_local(hw); | 1037 | struct ieee80211_local *local = hw_to_local(hw); |
974 | 1038 | ||
1039 | mutex_destroy(&local->iflist_mtx); | ||
1040 | |||
975 | wiphy_free(local->hw.wiphy); | 1041 | wiphy_free(local->hw.wiphy); |
976 | } | 1042 | } |
977 | EXPORT_SYMBOL(ieee80211_free_hw); | 1043 | EXPORT_SYMBOL(ieee80211_free_hw); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 82f568e94365..9a3e5de0410a 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -275,16 +275,6 @@ u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_t | |||
275 | & tbl->hash_mask; | 275 | & tbl->hash_mask; |
276 | } | 276 | } |
277 | 277 | ||
278 | u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len) | ||
279 | { | ||
280 | if (!mesh_id_len) | ||
281 | return 1; | ||
282 | else if (mesh_id_len == 1) | ||
283 | return (u8) mesh_id[0]; | ||
284 | else | ||
285 | return (u8) (mesh_id[0] + 2 * mesh_id[1]); | ||
286 | } | ||
287 | |||
288 | struct mesh_table *mesh_table_alloc(int size_order) | 278 | struct mesh_table *mesh_table_alloc(int size_order) |
289 | { | 279 | { |
290 | int i; | 280 | int i; |
@@ -442,7 +432,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
442 | 432 | ||
443 | ifmsh->housekeeping = true; | 433 | ifmsh->housekeeping = true; |
444 | queue_work(local->hw.workqueue, &ifmsh->work); | 434 | queue_work(local->hw.workqueue, &ifmsh->work); |
445 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 435 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | |
436 | IEEE80211_IFCC_BEACON_ENABLED); | ||
446 | } | 437 | } |
447 | 438 | ||
448 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 439 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
@@ -476,7 +467,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
476 | struct ieee80211_local *local = sdata->local; | 467 | struct ieee80211_local *local = sdata->local; |
477 | struct ieee802_11_elems elems; | 468 | struct ieee802_11_elems elems; |
478 | struct ieee80211_channel *channel; | 469 | struct ieee80211_channel *channel; |
479 | u64 supp_rates = 0; | 470 | u32 supp_rates = 0; |
480 | size_t baselen; | 471 | size_t baselen; |
481 | int freq; | 472 | int freq; |
482 | enum ieee80211_band band = rx_status->band; | 473 | enum ieee80211_band band = rx_status->band; |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index c197ab545e54..d891d7ddccd7 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -24,15 +24,15 @@ | |||
24 | * | 24 | * |
25 | * | 25 | * |
26 | * | 26 | * |
27 | * @MESH_PATH_ACTIVE: the mesh path is can be used for forwarding | 27 | * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding |
28 | * @MESH_PATH_RESOLVED: the discovery process is running for this mesh path | 28 | * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path |
29 | * @MESH_PATH_DSN_VALID: the mesh path contains a valid destination sequence | 29 | * @MESH_PATH_DSN_VALID: the mesh path contains a valid destination sequence |
30 | * number | 30 | * number |
31 | * @MESH_PATH_FIXED: the mesh path has been manually set and should not be | 31 | * @MESH_PATH_FIXED: the mesh path has been manually set and should not be |
32 | * modified | 32 | * modified |
33 | * @MESH_PATH_RESOLVED: the mesh path can has been resolved | 33 | * @MESH_PATH_RESOLVED: the mesh path can has been resolved |
34 | * | 34 | * |
35 | * MESH_PATH_RESOLVED and MESH_PATH_DELETE are used by the mesh path timer to | 35 | * MESH_PATH_RESOLVED is used by the mesh path timer to |
36 | * decide when to stop or cancel the mesh path discovery. | 36 | * decide when to stop or cancel the mesh path discovery. |
37 | */ | 37 | */ |
38 | enum mesh_path_flags { | 38 | enum mesh_path_flags { |
@@ -196,7 +196,6 @@ struct mesh_rmc { | |||
196 | 196 | ||
197 | /* Public interfaces */ | 197 | /* Public interfaces */ |
198 | /* Various */ | 198 | /* Various */ |
199 | u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len); | ||
200 | int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); | 199 | int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); |
201 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 200 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
202 | struct ieee80211_sub_if_data *sdata); | 201 | struct ieee80211_sub_if_data *sdata); |
@@ -236,14 +235,13 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | |||
236 | struct ieee80211_mgmt *mgmt, size_t len); | 235 | struct ieee80211_mgmt *mgmt, size_t len); |
237 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); | 236 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); |
238 | /* Mesh plinks */ | 237 | /* Mesh plinks */ |
239 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, | 238 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, |
240 | struct ieee80211_sub_if_data *sdata, bool add); | 239 | struct ieee80211_sub_if_data *sdata, bool add); |
241 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 240 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
242 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 241 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
243 | void mesh_plink_broken(struct sta_info *sta); | 242 | void mesh_plink_broken(struct sta_info *sta); |
244 | void mesh_plink_deactivate(struct sta_info *sta); | 243 | void mesh_plink_deactivate(struct sta_info *sta); |
245 | int mesh_plink_open(struct sta_info *sta); | 244 | int mesh_plink_open(struct sta_info *sta); |
246 | int mesh_plink_close(struct sta_info *sta); | ||
247 | void mesh_plink_block(struct sta_info *sta); | 245 | void mesh_plink_block(struct sta_info *sta); |
248 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | 246 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, |
249 | struct ieee80211_mgmt *mgmt, size_t len, | 247 | struct ieee80211_mgmt *mgmt, size_t len, |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 71fe60961230..60b35accda91 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -58,7 +58,6 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae) | |||
58 | #define PERR_IE_DST_ADDR(x) (x + 2) | 58 | #define PERR_IE_DST_ADDR(x) (x + 2) |
59 | #define PERR_IE_DST_DSN(x) u32_field_get(x, 8, 0); | 59 | #define PERR_IE_DST_DSN(x) u32_field_get(x, 8, 0); |
60 | 60 | ||
61 | #define TU_TO_EXP_TIME(x) (jiffies + msecs_to_jiffies(x * 1024 / 1000)) | ||
62 | #define MSEC_TO_TU(x) (x*1000/1024) | 61 | #define MSEC_TO_TU(x) (x*1000/1024) |
63 | #define DSN_GT(x, y) ((long) (y) - (long) (x) < 0) | 62 | #define DSN_GT(x, y) ((long) (y) - (long) (x) < 0) |
64 | #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) | 63 | #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) |
@@ -149,7 +148,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
149 | pos += ETH_ALEN; | 148 | pos += ETH_ALEN; |
150 | memcpy(pos, &dst_dsn, 4); | 149 | memcpy(pos, &dst_dsn, 4); |
151 | 150 | ||
152 | ieee80211_tx_skb(sdata, skb, 0); | 151 | ieee80211_tx_skb(sdata, skb, 1); |
153 | return 0; | 152 | return 0; |
154 | } | 153 | } |
155 | 154 | ||
@@ -198,7 +197,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, | |||
198 | pos += ETH_ALEN; | 197 | pos += ETH_ALEN; |
199 | memcpy(pos, &dst_dsn, 4); | 198 | memcpy(pos, &dst_dsn, 4); |
200 | 199 | ||
201 | ieee80211_tx_skb(sdata, skb, 0); | 200 | ieee80211_tx_skb(sdata, skb, 1); |
202 | return 0; | 201 | return 0; |
203 | } | 202 | } |
204 | 203 | ||
@@ -759,7 +758,7 @@ enddiscovery: | |||
759 | } | 758 | } |
760 | 759 | ||
761 | /** | 760 | /** |
762 | * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame | 761 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame |
763 | * | 762 | * |
764 | * @skb: 802.11 frame to be sent | 763 | * @skb: 802.11 frame to be sent |
765 | * @sdata: network subif the frame will be sent through | 764 | * @sdata: network subif the frame will be sent through |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 1159bdb4119c..a8bbdeca013a 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -93,7 +93,7 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) | |||
93 | * on it in the lifecycle management section! | 93 | * on it in the lifecycle management section! |
94 | */ | 94 | */ |
95 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | 95 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, |
96 | u8 *hw_addr, u64 rates) | 96 | u8 *hw_addr, u32 rates) |
97 | { | 97 | { |
98 | struct ieee80211_local *local = sdata->local; | 98 | struct ieee80211_local *local = sdata->local; |
99 | struct sta_info *sta; | 99 | struct sta_info *sta; |
@@ -218,11 +218,11 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
218 | memcpy(pos, &reason, 2); | 218 | memcpy(pos, &reason, 2); |
219 | } | 219 | } |
220 | 220 | ||
221 | ieee80211_tx_skb(sdata, skb, 0); | 221 | ieee80211_tx_skb(sdata, skb, 1); |
222 | return 0; | 222 | return 0; |
223 | } | 223 | } |
224 | 224 | ||
225 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data *sdata, | 225 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, |
226 | bool peer_accepting_plinks) | 226 | bool peer_accepting_plinks) |
227 | { | 227 | { |
228 | struct ieee80211_local *local = sdata->local; | 228 | struct ieee80211_local *local = sdata->local; |
@@ -361,36 +361,6 @@ void mesh_plink_block(struct sta_info *sta) | |||
361 | spin_unlock_bh(&sta->lock); | 361 | spin_unlock_bh(&sta->lock); |
362 | } | 362 | } |
363 | 363 | ||
364 | int mesh_plink_close(struct sta_info *sta) | ||
365 | { | ||
366 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
367 | __le16 llid, plid, reason; | ||
368 | |||
369 | mpl_dbg("Mesh plink: closing link with %pM\n", sta->sta.addr); | ||
370 | spin_lock_bh(&sta->lock); | ||
371 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); | ||
372 | reason = sta->reason; | ||
373 | |||
374 | if (sta->plink_state == PLINK_LISTEN || | ||
375 | sta->plink_state == PLINK_BLOCKED) { | ||
376 | mesh_plink_fsm_restart(sta); | ||
377 | spin_unlock_bh(&sta->lock); | ||
378 | return 0; | ||
379 | } else if (sta->plink_state == PLINK_ESTAB) { | ||
380 | __mesh_plink_deactivate(sta); | ||
381 | /* The timer should not be running */ | ||
382 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | ||
383 | } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) | ||
384 | sta->ignore_plink_timer = true; | ||
385 | |||
386 | sta->plink_state = PLINK_HOLDING; | ||
387 | llid = sta->llid; | ||
388 | plid = sta->plid; | ||
389 | spin_unlock_bh(&sta->lock); | ||
390 | mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->sta.addr, llid, | ||
391 | plid, reason); | ||
392 | return 0; | ||
393 | } | ||
394 | 364 | ||
395 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, | 365 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, |
396 | size_t len, struct ieee80211_rx_status *rx_status) | 366 | size_t len, struct ieee80211_rx_status *rx_status) |
@@ -477,7 +447,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
477 | spin_lock_bh(&sta->lock); | 447 | spin_lock_bh(&sta->lock); |
478 | } else if (!sta) { | 448 | } else if (!sta) { |
479 | /* ftype == PLINK_OPEN */ | 449 | /* ftype == PLINK_OPEN */ |
480 | u64 rates; | 450 | u32 rates; |
481 | if (!mesh_plink_free_count(sdata)) { | 451 | if (!mesh_plink_free_count(sdata)) { |
482 | mpl_dbg("Mesh plink error: no more free plinks\n"); | 452 | mpl_dbg("Mesh plink error: no more free plinks\n"); |
483 | rcu_read_unlock(); | 453 | rcu_read_unlock(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2b890af01ba4..fbb766afe599 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * BSS client mode implementation | 2 | * BSS client mode implementation |
3 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | 3 | * Copyright 2003-2008, Jouni Malinen <j@w1.fi> |
4 | * Copyright 2004, Instant802 Networks, Inc. | 4 | * Copyright 2004, Instant802 Networks, Inc. |
5 | * Copyright 2005, Devicescape Software, Inc. | 5 | * Copyright 2005, Devicescape Software, Inc. |
6 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 6 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
@@ -55,10 +55,10 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie) | |||
55 | { | 55 | { |
56 | u8 *end, *pos; | 56 | u8 *end, *pos; |
57 | 57 | ||
58 | pos = bss->ies; | 58 | pos = bss->cbss.information_elements; |
59 | if (pos == NULL) | 59 | if (pos == NULL) |
60 | return NULL; | 60 | return NULL; |
61 | end = pos + bss->ies_len; | 61 | end = pos + bss->cbss.len_information_elements; |
62 | 62 | ||
63 | while (pos + 1 < end) { | 63 | while (pos + 1 < end) { |
64 | if (pos + 2 + pos[1] > end) | 64 | if (pos + 2 + pos[1] > end) |
@@ -73,7 +73,7 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie) | |||
73 | 73 | ||
74 | static int ieee80211_compatible_rates(struct ieee80211_bss *bss, | 74 | static int ieee80211_compatible_rates(struct ieee80211_bss *bss, |
75 | struct ieee80211_supported_band *sband, | 75 | struct ieee80211_supported_band *sband, |
76 | u64 *rates) | 76 | u32 *rates) |
77 | { | 77 | { |
78 | int i, j, count; | 78 | int i, j, count; |
79 | *rates = 0; | 79 | *rates = 0; |
@@ -93,14 +93,14 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss, | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /* also used by mesh code */ | 95 | /* also used by mesh code */ |
96 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 96 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
97 | struct ieee802_11_elems *elems, | 97 | struct ieee802_11_elems *elems, |
98 | enum ieee80211_band band) | 98 | enum ieee80211_band band) |
99 | { | 99 | { |
100 | struct ieee80211_supported_band *sband; | 100 | struct ieee80211_supported_band *sband; |
101 | struct ieee80211_rate *bitrates; | 101 | struct ieee80211_rate *bitrates; |
102 | size_t num_rates; | 102 | size_t num_rates; |
103 | u64 supp_rates; | 103 | u32 supp_rates; |
104 | int i, j; | 104 | int i, j; |
105 | sband = local->hw.wiphy->bands[band]; | 105 | sband = local->hw.wiphy->bands[band]; |
106 | 106 | ||
@@ -131,6 +131,12 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
131 | 131 | ||
132 | /* frame sending functions */ | 132 | /* frame sending functions */ |
133 | 133 | ||
134 | static void add_extra_ies(struct sk_buff *skb, u8 *ies, size_t ies_len) | ||
135 | { | ||
136 | if (ies) | ||
137 | memcpy(skb_put(skb, ies_len), ies, ies_len); | ||
138 | } | ||
139 | |||
134 | /* also used by scanning code */ | 140 | /* also used by scanning code */ |
135 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 141 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
136 | u8 *ssid, size_t ssid_len) | 142 | u8 *ssid, size_t ssid_len) |
@@ -142,7 +148,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
142 | u8 *pos, *supp_rates, *esupp_rates = NULL; | 148 | u8 *pos, *supp_rates, *esupp_rates = NULL; |
143 | int i; | 149 | int i; |
144 | 150 | ||
145 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); | 151 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + |
152 | sdata->u.sta.ie_probereq_len); | ||
146 | if (!skb) { | 153 | if (!skb) { |
147 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | 154 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " |
148 | "request\n", sdata->dev->name); | 155 | "request\n", sdata->dev->name); |
@@ -189,6 +196,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
189 | *pos = rate->bitrate / 5; | 196 | *pos = rate->bitrate / 5; |
190 | } | 197 | } |
191 | 198 | ||
199 | add_extra_ies(skb, sdata->u.sta.ie_probereq, | ||
200 | sdata->u.sta.ie_probereq_len); | ||
201 | |||
192 | ieee80211_tx_skb(sdata, skb, 0); | 202 | ieee80211_tx_skb(sdata, skb, 0); |
193 | } | 203 | } |
194 | 204 | ||
@@ -202,7 +212,8 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
202 | struct ieee80211_mgmt *mgmt; | 212 | struct ieee80211_mgmt *mgmt; |
203 | 213 | ||
204 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 214 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
205 | sizeof(*mgmt) + 6 + extra_len); | 215 | sizeof(*mgmt) + 6 + extra_len + |
216 | sdata->u.sta.ie_auth_len); | ||
206 | if (!skb) { | 217 | if (!skb) { |
207 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " | 218 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " |
208 | "frame\n", sdata->dev->name); | 219 | "frame\n", sdata->dev->name); |
@@ -225,6 +236,7 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
225 | mgmt->u.auth.status_code = cpu_to_le16(0); | 236 | mgmt->u.auth.status_code = cpu_to_le16(0); |
226 | if (extra) | 237 | if (extra) |
227 | memcpy(skb_put(skb, extra_len), extra, extra_len); | 238 | memcpy(skb_put(skb, extra_len), extra, extra_len); |
239 | add_extra_ies(skb, sdata->u.sta.ie_auth, sdata->u.sta.ie_auth_len); | ||
228 | 240 | ||
229 | ieee80211_tx_skb(sdata, skb, encrypt); | 241 | ieee80211_tx_skb(sdata, skb, encrypt); |
230 | } | 242 | } |
@@ -235,17 +247,26 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
235 | struct ieee80211_local *local = sdata->local; | 247 | struct ieee80211_local *local = sdata->local; |
236 | struct sk_buff *skb; | 248 | struct sk_buff *skb; |
237 | struct ieee80211_mgmt *mgmt; | 249 | struct ieee80211_mgmt *mgmt; |
238 | u8 *pos, *ies, *ht_ie; | 250 | u8 *pos, *ies, *ht_ie, *e_ies; |
239 | int i, len, count, rates_len, supp_rates_len; | 251 | int i, len, count, rates_len, supp_rates_len; |
240 | u16 capab; | 252 | u16 capab; |
241 | struct ieee80211_bss *bss; | 253 | struct ieee80211_bss *bss; |
242 | int wmm = 0; | 254 | int wmm = 0; |
243 | struct ieee80211_supported_band *sband; | 255 | struct ieee80211_supported_band *sband; |
244 | u64 rates = 0; | 256 | u32 rates = 0; |
257 | size_t e_ies_len; | ||
258 | |||
259 | if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { | ||
260 | e_ies = sdata->u.sta.ie_reassocreq; | ||
261 | e_ies_len = sdata->u.sta.ie_reassocreq_len; | ||
262 | } else { | ||
263 | e_ies = sdata->u.sta.ie_assocreq; | ||
264 | e_ies_len = sdata->u.sta.ie_assocreq_len; | ||
265 | } | ||
245 | 266 | ||
246 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 267 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
247 | sizeof(*mgmt) + 200 + ifsta->extra_ie_len + | 268 | sizeof(*mgmt) + 200 + ifsta->extra_ie_len + |
248 | ifsta->ssid_len); | 269 | ifsta->ssid_len + e_ies_len); |
249 | if (!skb) { | 270 | if (!skb) { |
250 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | 271 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " |
251 | "frame\n", sdata->dev->name); | 272 | "frame\n", sdata->dev->name); |
@@ -268,7 +289,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
268 | local->hw.conf.channel->center_freq, | 289 | local->hw.conf.channel->center_freq, |
269 | ifsta->ssid, ifsta->ssid_len); | 290 | ifsta->ssid, ifsta->ssid_len); |
270 | if (bss) { | 291 | if (bss) { |
271 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 292 | if (bss->cbss.capability & WLAN_CAPABILITY_PRIVACY) |
272 | capab |= WLAN_CAPABILITY_PRIVACY; | 293 | capab |= WLAN_CAPABILITY_PRIVACY; |
273 | if (bss->wmm_used) | 294 | if (bss->wmm_used) |
274 | wmm = 1; | 295 | wmm = 1; |
@@ -279,7 +300,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
279 | * b-only mode) */ | 300 | * b-only mode) */ |
280 | rates_len = ieee80211_compatible_rates(bss, sband, &rates); | 301 | rates_len = ieee80211_compatible_rates(bss, sband, &rates); |
281 | 302 | ||
282 | if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && | 303 | if ((bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && |
283 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | 304 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) |
284 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | 305 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; |
285 | 306 | ||
@@ -391,10 +412,17 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
391 | } | 412 | } |
392 | 413 | ||
393 | /* wmm support is a must to HT */ | 414 | /* wmm support is a must to HT */ |
415 | /* | ||
416 | * IEEE802.11n does not allow TKIP/WEP as pairwise | ||
417 | * ciphers in HT mode. We still associate in non-ht | ||
418 | * mode (11a/b/g) if any one of these ciphers is | ||
419 | * configured as pairwise. | ||
420 | */ | ||
394 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && | 421 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && |
395 | sband->ht_cap.ht_supported && | 422 | sband->ht_cap.ht_supported && |
396 | (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) && | 423 | (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) && |
397 | ht_ie[1] >= sizeof(struct ieee80211_ht_info)) { | 424 | ht_ie[1] >= sizeof(struct ieee80211_ht_info) && |
425 | (!(ifsta->flags & IEEE80211_STA_TKIP_WEP_USED))) { | ||
398 | struct ieee80211_ht_info *ht_info = | 426 | struct ieee80211_ht_info *ht_info = |
399 | (struct ieee80211_ht_info *)(ht_ie + 2); | 427 | (struct ieee80211_ht_info *)(ht_ie + 2); |
400 | u16 cap = sband->ht_cap.cap; | 428 | u16 cap = sband->ht_cap.cap; |
@@ -429,6 +457,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
429 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 457 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
430 | } | 458 | } |
431 | 459 | ||
460 | add_extra_ies(skb, e_ies, e_ies_len); | ||
461 | |||
432 | kfree(ifsta->assocreq_ies); | 462 | kfree(ifsta->assocreq_ies); |
433 | ifsta->assocreq_ies_len = (skb->data + skb->len) - ies; | 463 | ifsta->assocreq_ies_len = (skb->data + skb->len) - ies; |
434 | ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL); | 464 | ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL); |
@@ -446,8 +476,19 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
446 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 476 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
447 | struct sk_buff *skb; | 477 | struct sk_buff *skb; |
448 | struct ieee80211_mgmt *mgmt; | 478 | struct ieee80211_mgmt *mgmt; |
479 | u8 *ies; | ||
480 | size_t ies_len; | ||
481 | |||
482 | if (stype == IEEE80211_STYPE_DEAUTH) { | ||
483 | ies = sdata->u.sta.ie_deauth; | ||
484 | ies_len = sdata->u.sta.ie_deauth_len; | ||
485 | } else { | ||
486 | ies = sdata->u.sta.ie_disassoc; | ||
487 | ies_len = sdata->u.sta.ie_disassoc_len; | ||
488 | } | ||
449 | 489 | ||
450 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 490 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + |
491 | ies_len); | ||
451 | if (!skb) { | 492 | if (!skb) { |
452 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | 493 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
453 | "deauth/disassoc frame\n", sdata->dev->name); | 494 | "deauth/disassoc frame\n", sdata->dev->name); |
@@ -465,19 +506,55 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
465 | /* u.deauth.reason_code == u.disassoc.reason_code */ | 506 | /* u.deauth.reason_code == u.disassoc.reason_code */ |
466 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); | 507 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); |
467 | 508 | ||
509 | add_extra_ies(skb, ies, ies_len); | ||
510 | |||
511 | ieee80211_tx_skb(sdata, skb, ifsta->flags & IEEE80211_STA_MFP_ENABLED); | ||
512 | } | ||
513 | |||
514 | void ieee80211_send_pspoll(struct ieee80211_local *local, | ||
515 | struct ieee80211_sub_if_data *sdata) | ||
516 | { | ||
517 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
518 | struct ieee80211_pspoll *pspoll; | ||
519 | struct sk_buff *skb; | ||
520 | u16 fc; | ||
521 | |||
522 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); | ||
523 | if (!skb) { | ||
524 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | ||
525 | "pspoll frame\n", sdata->dev->name); | ||
526 | return; | ||
527 | } | ||
528 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
529 | |||
530 | pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll)); | ||
531 | memset(pspoll, 0, sizeof(*pspoll)); | ||
532 | fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM; | ||
533 | pspoll->frame_control = cpu_to_le16(fc); | ||
534 | pspoll->aid = cpu_to_le16(ifsta->aid); | ||
535 | |||
536 | /* aid in PS-Poll has its two MSBs each set to 1 */ | ||
537 | pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); | ||
538 | |||
539 | memcpy(pspoll->bssid, ifsta->bssid, ETH_ALEN); | ||
540 | memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN); | ||
541 | |||
468 | ieee80211_tx_skb(sdata, skb, 0); | 542 | ieee80211_tx_skb(sdata, skb, 0); |
543 | |||
544 | return; | ||
469 | } | 545 | } |
470 | 546 | ||
471 | /* MLME */ | 547 | /* MLME */ |
472 | static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 548 | static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
473 | struct ieee80211_bss *bss) | 549 | const size_t supp_rates_len, |
550 | const u8 *supp_rates) | ||
474 | { | 551 | { |
475 | struct ieee80211_local *local = sdata->local; | 552 | struct ieee80211_local *local = sdata->local; |
476 | int i, have_higher_than_11mbit = 0; | 553 | int i, have_higher_than_11mbit = 0; |
477 | 554 | ||
478 | /* cf. IEEE 802.11 9.2.12 */ | 555 | /* cf. IEEE 802.11 9.2.12 */ |
479 | for (i = 0; i < bss->supp_rates_len; i++) | 556 | for (i = 0; i < supp_rates_len; i++) |
480 | if ((bss->supp_rates[i] & 0x7f) * 5 > 110) | 557 | if ((supp_rates[i] & 0x7f) * 5 > 110) |
481 | have_higher_than_11mbit = 1; | 558 | have_higher_than_11mbit = 1; |
482 | 559 | ||
483 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 560 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && |
@@ -568,6 +645,27 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
568 | } | 645 | } |
569 | } | 646 | } |
570 | 647 | ||
648 | static bool ieee80211_check_tim(struct ieee802_11_elems *elems, u16 aid) | ||
649 | { | ||
650 | u8 mask; | ||
651 | u8 index, indexn1, indexn2; | ||
652 | struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim; | ||
653 | |||
654 | aid &= 0x3fff; | ||
655 | index = aid / 8; | ||
656 | mask = 1 << (aid & 7); | ||
657 | |||
658 | indexn1 = tim->bitmap_ctrl & 0xfe; | ||
659 | indexn2 = elems->tim_len + indexn1 - 4; | ||
660 | |||
661 | if (index < indexn1 || index > indexn2) | ||
662 | return false; | ||
663 | |||
664 | index -= indexn1; | ||
665 | |||
666 | return !!(tim->virtual_map[index] & mask); | ||
667 | } | ||
668 | |||
571 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | 669 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
572 | u16 capab, bool erp_valid, u8 erp) | 670 | u16 capab, bool erp_valid, u8 erp) |
573 | { | 671 | { |
@@ -710,20 +808,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
710 | bss_info_changed |= BSS_CHANGED_ASSOC; | 808 | bss_info_changed |= BSS_CHANGED_ASSOC; |
711 | ifsta->flags |= IEEE80211_STA_ASSOCIATED; | 809 | ifsta->flags |= IEEE80211_STA_ASSOCIATED; |
712 | 810 | ||
713 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
714 | return; | ||
715 | |||
716 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, | 811 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
717 | conf->channel->center_freq, | 812 | conf->channel->center_freq, |
718 | ifsta->ssid, ifsta->ssid_len); | 813 | ifsta->ssid, ifsta->ssid_len); |
719 | if (bss) { | 814 | if (bss) { |
720 | /* set timing information */ | 815 | /* set timing information */ |
721 | sdata->vif.bss_conf.beacon_int = bss->beacon_int; | 816 | sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval; |
722 | sdata->vif.bss_conf.timestamp = bss->timestamp; | 817 | sdata->vif.bss_conf.timestamp = bss->cbss.tsf; |
723 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; | 818 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; |
724 | 819 | ||
725 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 820 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
726 | bss->capability, bss->has_erp_value, bss->erp_value); | 821 | bss->cbss.capability, bss->has_erp_value, bss->erp_value); |
727 | 822 | ||
728 | ieee80211_rx_bss_put(local, bss); | 823 | ieee80211_rx_bss_put(local, bss); |
729 | } | 824 | } |
@@ -745,13 +840,16 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
745 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 840 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
746 | 841 | ||
747 | if (local->powersave) { | 842 | if (local->powersave) { |
748 | if (local->dynamic_ps_timeout > 0) | 843 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) && |
844 | local->hw.conf.dynamic_ps_timeout > 0) { | ||
749 | mod_timer(&local->dynamic_ps_timer, jiffies + | 845 | mod_timer(&local->dynamic_ps_timer, jiffies + |
750 | msecs_to_jiffies(local->dynamic_ps_timeout)); | 846 | msecs_to_jiffies( |
751 | else { | 847 | local->hw.conf.dynamic_ps_timeout)); |
848 | } else { | ||
849 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | ||
850 | ieee80211_send_nullfunc(local, sdata, 1); | ||
752 | conf->flags |= IEEE80211_CONF_PS; | 851 | conf->flags |= IEEE80211_CONF_PS; |
753 | ieee80211_hw_config(local, | 852 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
754 | IEEE80211_CONF_CHANGE_PS); | ||
755 | } | 853 | } |
756 | } | 854 | } |
757 | 855 | ||
@@ -770,6 +868,14 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
770 | sdata->dev->name, ifsta->bssid); | 868 | sdata->dev->name, ifsta->bssid); |
771 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 869 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
772 | ieee80211_sta_send_apinfo(sdata, ifsta); | 870 | ieee80211_sta_send_apinfo(sdata, ifsta); |
871 | |||
872 | /* | ||
873 | * Most likely AP is not in the range so remove the | ||
874 | * bss information associated to the AP | ||
875 | */ | ||
876 | ieee80211_rx_bss_remove(sdata, ifsta->bssid, | ||
877 | sdata->local->hw.conf.channel->center_freq, | ||
878 | ifsta->ssid, ifsta->ssid_len); | ||
773 | return; | 879 | return; |
774 | } | 880 | } |
775 | 881 | ||
@@ -801,6 +907,9 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
801 | sdata->dev->name, ifsta->bssid); | 907 | sdata->dev->name, ifsta->bssid); |
802 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 908 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
803 | ieee80211_sta_send_apinfo(sdata, ifsta); | 909 | ieee80211_sta_send_apinfo(sdata, ifsta); |
910 | ieee80211_rx_bss_remove(sdata, ifsta->bssid, | ||
911 | sdata->local->hw.conf.channel->center_freq, | ||
912 | ifsta->ssid, ifsta->ssid_len); | ||
804 | return; | 913 | return; |
805 | } | 914 | } |
806 | 915 | ||
@@ -843,7 +952,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
843 | netif_tx_stop_all_queues(sdata->dev); | 952 | netif_tx_stop_all_queues(sdata->dev); |
844 | netif_carrier_off(sdata->dev); | 953 | netif_carrier_off(sdata->dev); |
845 | 954 | ||
846 | ieee80211_sta_tear_down_BA_sessions(sdata, sta->sta.addr); | 955 | ieee80211_sta_tear_down_BA_sessions(sta); |
847 | 956 | ||
848 | if (self_disconnected) { | 957 | if (self_disconnected) { |
849 | if (deauth) | 958 | if (deauth) |
@@ -863,14 +972,19 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
863 | 972 | ||
864 | ieee80211_sta_send_apinfo(sdata, ifsta); | 973 | ieee80211_sta_send_apinfo(sdata, ifsta); |
865 | 974 | ||
866 | if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) | 975 | if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) { |
867 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 976 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
977 | ieee80211_rx_bss_remove(sdata, ifsta->bssid, | ||
978 | sdata->local->hw.conf.channel->center_freq, | ||
979 | ifsta->ssid, ifsta->ssid_len); | ||
980 | } | ||
868 | 981 | ||
869 | rcu_read_unlock(); | 982 | rcu_read_unlock(); |
870 | 983 | ||
871 | local->hw.conf.ht.enabled = false; | 984 | /* channel(_type) changes are handled by ieee80211_hw_config */ |
872 | local->oper_channel_type = NL80211_CHAN_NO_HT; | 985 | local->oper_channel_type = NL80211_CHAN_NO_HT; |
873 | config_changed |= IEEE80211_CONF_CHANGE_HT; | 986 | |
987 | local->power_constr_level = 0; | ||
874 | 988 | ||
875 | del_timer_sync(&local->dynamic_ps_timer); | 989 | del_timer_sync(&local->dynamic_ps_timer); |
876 | cancel_work_sync(&local->dynamic_ps_enable_work); | 990 | cancel_work_sync(&local->dynamic_ps_enable_work); |
@@ -924,7 +1038,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, | |||
924 | if (!bss) | 1038 | if (!bss) |
925 | return 0; | 1039 | return 0; |
926 | 1040 | ||
927 | bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); | 1041 | bss_privacy = !!(bss->cbss.capability & WLAN_CAPABILITY_PRIVACY); |
928 | wep_privacy = !!ieee80211_sta_wep_configured(sdata); | 1042 | wep_privacy = !!ieee80211_sta_wep_configured(sdata); |
929 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); | 1043 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); |
930 | 1044 | ||
@@ -946,6 +1060,9 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
946 | sdata->dev->name, ifsta->bssid); | 1060 | sdata->dev->name, ifsta->bssid); |
947 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 1061 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
948 | ieee80211_sta_send_apinfo(sdata, ifsta); | 1062 | ieee80211_sta_send_apinfo(sdata, ifsta); |
1063 | ieee80211_rx_bss_remove(sdata, ifsta->bssid, | ||
1064 | sdata->local->hw.conf.channel->center_freq, | ||
1065 | ifsta->ssid, ifsta->ssid_len); | ||
949 | return; | 1066 | return; |
950 | } | 1067 | } |
951 | 1068 | ||
@@ -1049,6 +1166,30 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | |||
1049 | elems.challenge_len + 2, 1); | 1166 | elems.challenge_len + 2, 1); |
1050 | } | 1167 | } |
1051 | 1168 | ||
1169 | static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | ||
1170 | struct ieee80211_if_sta *ifsta, | ||
1171 | struct ieee80211_mgmt *mgmt, | ||
1172 | size_t len) | ||
1173 | { | ||
1174 | u16 auth_alg, auth_transaction, status_code; | ||
1175 | |||
1176 | if (len < 24 + 6) | ||
1177 | return; | ||
1178 | |||
1179 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
1180 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
1181 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | ||
1182 | |||
1183 | /* | ||
1184 | * IEEE 802.11 standard does not require authentication in IBSS | ||
1185 | * networks and most implementations do not seem to use it. | ||
1186 | * However, try to reply to authentication attempts if someone | ||
1187 | * has actually implemented this. | ||
1188 | */ | ||
1189 | if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) | ||
1190 | ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0); | ||
1191 | } | ||
1192 | |||
1052 | static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | 1193 | static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, |
1053 | struct ieee80211_if_sta *ifsta, | 1194 | struct ieee80211_if_sta *ifsta, |
1054 | struct ieee80211_mgmt *mgmt, | 1195 | struct ieee80211_mgmt *mgmt, |
@@ -1056,37 +1197,22 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1056 | { | 1197 | { |
1057 | u16 auth_alg, auth_transaction, status_code; | 1198 | u16 auth_alg, auth_transaction, status_code; |
1058 | 1199 | ||
1059 | if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && | 1200 | if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE) |
1060 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
1061 | return; | 1201 | return; |
1062 | 1202 | ||
1063 | if (len < 24 + 6) | 1203 | if (len < 24 + 6) |
1064 | return; | 1204 | return; |
1065 | 1205 | ||
1066 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && | 1206 | if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) |
1067 | memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) | ||
1068 | return; | 1207 | return; |
1069 | 1208 | ||
1070 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && | 1209 | if (memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) |
1071 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) | ||
1072 | return; | 1210 | return; |
1073 | 1211 | ||
1074 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | 1212 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); |
1075 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | 1213 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); |
1076 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | 1214 | status_code = le16_to_cpu(mgmt->u.auth.status_code); |
1077 | 1215 | ||
1078 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
1079 | /* | ||
1080 | * IEEE 802.11 standard does not require authentication in IBSS | ||
1081 | * networks and most implementations do not seem to use it. | ||
1082 | * However, try to reply to authentication attempts if someone | ||
1083 | * has actually implemented this. | ||
1084 | */ | ||
1085 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | ||
1086 | return; | ||
1087 | ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0); | ||
1088 | } | ||
1089 | |||
1090 | if (auth_alg != ifsta->auth_alg || | 1216 | if (auth_alg != ifsta->auth_alg || |
1091 | auth_transaction != ifsta->auth_transaction) | 1217 | auth_transaction != ifsta->auth_transaction) |
1092 | return; | 1218 | return; |
@@ -1211,7 +1337,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1211 | struct ieee80211_local *local = sdata->local; | 1337 | struct ieee80211_local *local = sdata->local; |
1212 | struct ieee80211_supported_band *sband; | 1338 | struct ieee80211_supported_band *sband; |
1213 | struct sta_info *sta; | 1339 | struct sta_info *sta; |
1214 | u64 rates, basic_rates; | 1340 | u32 rates, basic_rates; |
1215 | u16 capab_info, status_code, aid; | 1341 | u16 capab_info, status_code, aid; |
1216 | struct ieee802_11_elems elems; | 1342 | struct ieee802_11_elems elems; |
1217 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 1343 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
@@ -1242,6 +1368,24 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1242 | sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, | 1368 | sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, |
1243 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | 1369 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
1244 | 1370 | ||
1371 | pos = mgmt->u.assoc_resp.variable; | ||
1372 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1373 | |||
1374 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && | ||
1375 | elems.timeout_int && elems.timeout_int_len == 5 && | ||
1376 | elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { | ||
1377 | u32 tu, ms; | ||
1378 | tu = get_unaligned_le32(elems.timeout_int + 1); | ||
1379 | ms = tu * 1024 / 1000; | ||
1380 | printk(KERN_DEBUG "%s: AP rejected association temporarily; " | ||
1381 | "comeback duration %u TU (%u ms)\n", | ||
1382 | sdata->dev->name, tu, ms); | ||
1383 | if (ms > IEEE80211_ASSOC_TIMEOUT) | ||
1384 | mod_timer(&ifsta->timer, | ||
1385 | jiffies + msecs_to_jiffies(ms)); | ||
1386 | return; | ||
1387 | } | ||
1388 | |||
1245 | if (status_code != WLAN_STATUS_SUCCESS) { | 1389 | if (status_code != WLAN_STATUS_SUCCESS) { |
1246 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", | 1390 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", |
1247 | sdata->dev->name, status_code); | 1391 | sdata->dev->name, status_code); |
@@ -1257,9 +1401,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1257 | "set\n", sdata->dev->name, aid); | 1401 | "set\n", sdata->dev->name, aid); |
1258 | aid &= ~(BIT(15) | BIT(14)); | 1402 | aid &= ~(BIT(15) | BIT(14)); |
1259 | 1403 | ||
1260 | pos = mgmt->u.assoc_resp.variable; | ||
1261 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1262 | |||
1263 | if (!elems.supp_rates) { | 1404 | if (!elems.supp_rates) { |
1264 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 1405 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", |
1265 | sdata->dev->name); | 1406 | sdata->dev->name); |
@@ -1281,8 +1422,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1281 | /* Add STA entry for the AP */ | 1422 | /* Add STA entry for the AP */ |
1282 | sta = sta_info_get(local, ifsta->bssid); | 1423 | sta = sta_info_get(local, ifsta->bssid); |
1283 | if (!sta) { | 1424 | if (!sta) { |
1284 | struct ieee80211_bss *bss; | ||
1285 | |||
1286 | newsta = true; | 1425 | newsta = true; |
1287 | 1426 | ||
1288 | sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); | 1427 | sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); |
@@ -1292,15 +1431,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1292 | rcu_read_unlock(); | 1431 | rcu_read_unlock(); |
1293 | return; | 1432 | return; |
1294 | } | 1433 | } |
1295 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, | ||
1296 | local->hw.conf.channel->center_freq, | ||
1297 | ifsta->ssid, ifsta->ssid_len); | ||
1298 | if (bss) { | ||
1299 | sta->last_signal = bss->signal; | ||
1300 | sta->last_qual = bss->qual; | ||
1301 | sta->last_noise = bss->noise; | ||
1302 | ieee80211_rx_bss_put(local, bss); | ||
1303 | } | ||
1304 | 1434 | ||
1305 | /* update new sta with its last rx activity */ | 1435 | /* update new sta with its last rx activity */ |
1306 | sta->last_rx = jiffies; | 1436 | sta->last_rx = jiffies; |
@@ -1375,6 +1505,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1375 | 1505 | ||
1376 | rate_control_rate_init(sta); | 1506 | rate_control_rate_init(sta); |
1377 | 1507 | ||
1508 | if (ifsta->flags & IEEE80211_STA_MFP_ENABLED) | ||
1509 | set_sta_flags(sta, WLAN_STA_MFP); | ||
1510 | |||
1378 | if (elems.wmm_param) | 1511 | if (elems.wmm_param) |
1379 | set_sta_flags(sta, WLAN_STA_WME); | 1512 | set_sta_flags(sta, WLAN_STA_WME); |
1380 | 1513 | ||
@@ -1409,49 +1542,61 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1409 | } | 1542 | } |
1410 | 1543 | ||
1411 | 1544 | ||
1412 | static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 1545 | static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
1413 | struct ieee80211_if_sta *ifsta, | 1546 | struct ieee80211_if_sta *ifsta, |
1414 | struct ieee80211_bss *bss) | 1547 | const u8 *bssid, const int beacon_int, |
1548 | const int freq, | ||
1549 | const size_t supp_rates_len, | ||
1550 | const u8 *supp_rates, | ||
1551 | const u16 capability) | ||
1415 | { | 1552 | { |
1416 | struct ieee80211_local *local = sdata->local; | 1553 | struct ieee80211_local *local = sdata->local; |
1417 | int res, rates, i, j; | 1554 | int res = 0, rates, i, j; |
1418 | struct sk_buff *skb; | 1555 | struct sk_buff *skb; |
1419 | struct ieee80211_mgmt *mgmt; | 1556 | struct ieee80211_mgmt *mgmt; |
1420 | u8 *pos; | 1557 | u8 *pos; |
1421 | struct ieee80211_supported_band *sband; | 1558 | struct ieee80211_supported_band *sband; |
1422 | union iwreq_data wrqu; | 1559 | union iwreq_data wrqu; |
1423 | 1560 | ||
1424 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 1561 | if (local->ops->reset_tsf) { |
1562 | /* Reset own TSF to allow time synchronization work. */ | ||
1563 | local->ops->reset_tsf(local_to_hw(local)); | ||
1564 | } | ||
1565 | |||
1566 | if ((ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) && | ||
1567 | memcmp(ifsta->bssid, bssid, ETH_ALEN) == 0) | ||
1568 | return res; | ||
1569 | |||
1570 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + | ||
1571 | sdata->u.sta.ie_proberesp_len); | ||
1425 | if (!skb) { | 1572 | if (!skb) { |
1426 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | 1573 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " |
1427 | "response\n", sdata->dev->name); | 1574 | "response\n", sdata->dev->name); |
1428 | return -ENOMEM; | 1575 | return -ENOMEM; |
1429 | } | 1576 | } |
1430 | 1577 | ||
1431 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1578 | if (!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) { |
1432 | 1579 | /* Remove possible STA entries from other IBSS networks. */ | |
1433 | /* Remove possible STA entries from other IBSS networks. */ | 1580 | sta_info_flush_delayed(sdata); |
1434 | sta_info_flush_delayed(sdata); | ||
1435 | |||
1436 | if (local->ops->reset_tsf) { | ||
1437 | /* Reset own TSF to allow time synchronization work. */ | ||
1438 | local->ops->reset_tsf(local_to_hw(local)); | ||
1439 | } | 1581 | } |
1440 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); | 1582 | |
1583 | memcpy(ifsta->bssid, bssid, ETH_ALEN); | ||
1441 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | 1584 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); |
1442 | if (res) | 1585 | if (res) |
1443 | return res; | 1586 | return res; |
1444 | 1587 | ||
1445 | local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10; | 1588 | local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10; |
1446 | 1589 | ||
1447 | sdata->drop_unencrypted = bss->capability & | 1590 | sdata->drop_unencrypted = capability & |
1448 | WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 1591 | WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
1449 | 1592 | ||
1450 | res = ieee80211_set_freq(sdata, bss->freq); | 1593 | res = ieee80211_set_freq(sdata, freq); |
1451 | 1594 | ||
1452 | if (res) | 1595 | if (res) |
1453 | return res; | 1596 | return res; |
1454 | 1597 | ||
1598 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1599 | |||
1455 | /* Build IBSS probe response */ | 1600 | /* Build IBSS probe response */ |
1456 | 1601 | ||
1457 | skb_reserve(skb, local->hw.extra_tx_headroom); | 1602 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -1460,33 +1605,32 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1460 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 1605 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
1461 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 1606 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
1462 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 1607 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1463 | IEEE80211_STYPE_PROBE_RESP); | 1608 | IEEE80211_STYPE_PROBE_RESP); |
1464 | memset(mgmt->da, 0xff, ETH_ALEN); | 1609 | memset(mgmt->da, 0xff, ETH_ALEN); |
1465 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 1610 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
1466 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 1611 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
1467 | mgmt->u.beacon.beacon_int = | 1612 | mgmt->u.beacon.beacon_int = |
1468 | cpu_to_le16(local->hw.conf.beacon_int); | 1613 | cpu_to_le16(local->hw.conf.beacon_int); |
1469 | mgmt->u.beacon.timestamp = cpu_to_le64(bss->timestamp); | 1614 | mgmt->u.beacon.capab_info = cpu_to_le16(capability); |
1470 | mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability); | ||
1471 | 1615 | ||
1472 | pos = skb_put(skb, 2 + ifsta->ssid_len); | 1616 | pos = skb_put(skb, 2 + ifsta->ssid_len); |
1473 | *pos++ = WLAN_EID_SSID; | 1617 | *pos++ = WLAN_EID_SSID; |
1474 | *pos++ = ifsta->ssid_len; | 1618 | *pos++ = ifsta->ssid_len; |
1475 | memcpy(pos, ifsta->ssid, ifsta->ssid_len); | 1619 | memcpy(pos, ifsta->ssid, ifsta->ssid_len); |
1476 | 1620 | ||
1477 | rates = bss->supp_rates_len; | 1621 | rates = supp_rates_len; |
1478 | if (rates > 8) | 1622 | if (rates > 8) |
1479 | rates = 8; | 1623 | rates = 8; |
1480 | pos = skb_put(skb, 2 + rates); | 1624 | pos = skb_put(skb, 2 + rates); |
1481 | *pos++ = WLAN_EID_SUPP_RATES; | 1625 | *pos++ = WLAN_EID_SUPP_RATES; |
1482 | *pos++ = rates; | 1626 | *pos++ = rates; |
1483 | memcpy(pos, bss->supp_rates, rates); | 1627 | memcpy(pos, supp_rates, rates); |
1484 | 1628 | ||
1485 | if (bss->band == IEEE80211_BAND_2GHZ) { | 1629 | if (sband->band == IEEE80211_BAND_2GHZ) { |
1486 | pos = skb_put(skb, 2 + 1); | 1630 | pos = skb_put(skb, 2 + 1); |
1487 | *pos++ = WLAN_EID_DS_PARAMS; | 1631 | *pos++ = WLAN_EID_DS_PARAMS; |
1488 | *pos++ = 1; | 1632 | *pos++ = 1; |
1489 | *pos++ = ieee80211_frequency_to_channel(bss->freq); | 1633 | *pos++ = ieee80211_frequency_to_channel(freq); |
1490 | } | 1634 | } |
1491 | 1635 | ||
1492 | pos = skb_put(skb, 2 + 2); | 1636 | pos = skb_put(skb, 2 + 2); |
@@ -1496,43 +1640,59 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1496 | *pos++ = 0; | 1640 | *pos++ = 0; |
1497 | *pos++ = 0; | 1641 | *pos++ = 0; |
1498 | 1642 | ||
1499 | if (bss->supp_rates_len > 8) { | 1643 | if (supp_rates_len > 8) { |
1500 | rates = bss->supp_rates_len - 8; | 1644 | rates = supp_rates_len - 8; |
1501 | pos = skb_put(skb, 2 + rates); | 1645 | pos = skb_put(skb, 2 + rates); |
1502 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 1646 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
1503 | *pos++ = rates; | 1647 | *pos++ = rates; |
1504 | memcpy(pos, &bss->supp_rates[8], rates); | 1648 | memcpy(pos, &supp_rates[8], rates); |
1505 | } | 1649 | } |
1506 | 1650 | ||
1651 | add_extra_ies(skb, sdata->u.sta.ie_proberesp, | ||
1652 | sdata->u.sta.ie_proberesp_len); | ||
1653 | |||
1507 | ifsta->probe_resp = skb; | 1654 | ifsta->probe_resp = skb; |
1508 | 1655 | ||
1509 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 1656 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | |
1657 | IEEE80211_IFCC_BEACON_ENABLED); | ||
1510 | 1658 | ||
1511 | 1659 | ||
1512 | rates = 0; | 1660 | rates = 0; |
1513 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1661 | for (i = 0; i < supp_rates_len; i++) { |
1514 | for (i = 0; i < bss->supp_rates_len; i++) { | 1662 | int bitrate = (supp_rates[i] & 0x7f) * 5; |
1515 | int bitrate = (bss->supp_rates[i] & 0x7f) * 5; | ||
1516 | for (j = 0; j < sband->n_bitrates; j++) | 1663 | for (j = 0; j < sband->n_bitrates; j++) |
1517 | if (sband->bitrates[j].bitrate == bitrate) | 1664 | if (sband->bitrates[j].bitrate == bitrate) |
1518 | rates |= BIT(j); | 1665 | rates |= BIT(j); |
1519 | } | 1666 | } |
1520 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | 1667 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; |
1521 | 1668 | ||
1522 | ieee80211_sta_def_wmm_params(sdata, bss); | 1669 | ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates); |
1523 | 1670 | ||
1671 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; | ||
1524 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; | 1672 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; |
1525 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 1673 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
1526 | 1674 | ||
1527 | ieee80211_led_assoc(local, true); | 1675 | ieee80211_led_assoc(local, true); |
1528 | 1676 | ||
1529 | memset(&wrqu, 0, sizeof(wrqu)); | 1677 | memset(&wrqu, 0, sizeof(wrqu)); |
1530 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 1678 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); |
1531 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); | 1679 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); |
1532 | 1680 | ||
1533 | return res; | 1681 | return res; |
1534 | } | 1682 | } |
1535 | 1683 | ||
1684 | static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | ||
1685 | struct ieee80211_if_sta *ifsta, | ||
1686 | struct ieee80211_bss *bss) | ||
1687 | { | ||
1688 | return __ieee80211_sta_join_ibss(sdata, ifsta, | ||
1689 | bss->cbss.bssid, | ||
1690 | bss->cbss.beacon_interval, | ||
1691 | bss->cbss.channel->center_freq, | ||
1692 | bss->supp_rates_len, bss->supp_rates, | ||
1693 | bss->cbss.capability); | ||
1694 | } | ||
1695 | |||
1536 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 1696 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
1537 | struct ieee80211_mgmt *mgmt, | 1697 | struct ieee80211_mgmt *mgmt, |
1538 | size_t len, | 1698 | size_t len, |
@@ -1546,7 +1706,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1546 | struct sta_info *sta; | 1706 | struct sta_info *sta; |
1547 | struct ieee80211_channel *channel; | 1707 | struct ieee80211_channel *channel; |
1548 | u64 beacon_timestamp, rx_timestamp; | 1708 | u64 beacon_timestamp, rx_timestamp; |
1549 | u64 supp_rates = 0; | 1709 | u32 supp_rates = 0; |
1550 | enum ieee80211_band band = rx_status->band; | 1710 | enum ieee80211_band band = rx_status->band; |
1551 | 1711 | ||
1552 | if (elems->ds_params && elems->ds_params_len == 1) | 1712 | if (elems->ds_params && elems->ds_params_len == 1) |
@@ -1567,7 +1727,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1567 | 1727 | ||
1568 | sta = sta_info_get(local, mgmt->sa); | 1728 | sta = sta_info_get(local, mgmt->sa); |
1569 | if (sta) { | 1729 | if (sta) { |
1570 | u64 prev_rates; | 1730 | u32 prev_rates; |
1571 | 1731 | ||
1572 | prev_rates = sta->sta.supp_rates[band]; | 1732 | prev_rates = sta->sta.supp_rates[band]; |
1573 | /* make sure mandatory rates are always added */ | 1733 | /* make sure mandatory rates are always added */ |
@@ -1593,80 +1753,99 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1593 | } | 1753 | } |
1594 | 1754 | ||
1595 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 1755 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
1596 | freq, beacon); | 1756 | channel, beacon); |
1597 | if (!bss) | 1757 | if (!bss) |
1598 | return; | 1758 | return; |
1599 | 1759 | ||
1760 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && | ||
1761 | (memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0)) { | ||
1762 | struct ieee80211_channel_sw_ie *sw_elem = | ||
1763 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; | ||
1764 | ieee80211_process_chanswitch(sdata, sw_elem, bss); | ||
1765 | } | ||
1766 | |||
1600 | /* was just updated in ieee80211_bss_info_update */ | 1767 | /* was just updated in ieee80211_bss_info_update */ |
1601 | beacon_timestamp = bss->timestamp; | 1768 | beacon_timestamp = bss->cbss.tsf; |
1602 | 1769 | ||
1603 | /* | 1770 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1604 | * In STA mode, the remaining parameters should not be overridden | 1771 | goto put_bss; |
1605 | * by beacons because they're not necessarily accurate there. | ||
1606 | */ | ||
1607 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
1608 | bss->last_probe_resp && beacon) { | ||
1609 | ieee80211_rx_bss_put(local, bss); | ||
1610 | return; | ||
1611 | } | ||
1612 | 1772 | ||
1613 | /* check if we need to merge IBSS */ | 1773 | /* check if we need to merge IBSS */ |
1614 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon && | 1774 | |
1615 | bss->capability & WLAN_CAPABILITY_IBSS && | 1775 | /* merge only on beacons (???) */ |
1616 | bss->freq == local->oper_channel->center_freq && | 1776 | if (!beacon) |
1617 | elems->ssid_len == sdata->u.sta.ssid_len && | 1777 | goto put_bss; |
1778 | |||
1779 | /* we use a fixed BSSID */ | ||
1780 | if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) | ||
1781 | goto put_bss; | ||
1782 | |||
1783 | /* not an IBSS */ | ||
1784 | if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS)) | ||
1785 | goto put_bss; | ||
1786 | |||
1787 | /* different channel */ | ||
1788 | if (bss->cbss.channel != local->oper_channel) | ||
1789 | goto put_bss; | ||
1790 | |||
1791 | /* different SSID */ | ||
1792 | if (elems->ssid_len != sdata->u.sta.ssid_len || | ||
1618 | memcmp(elems->ssid, sdata->u.sta.ssid, | 1793 | memcmp(elems->ssid, sdata->u.sta.ssid, |
1619 | sdata->u.sta.ssid_len) == 0) { | 1794 | sdata->u.sta.ssid_len)) |
1620 | if (rx_status->flag & RX_FLAG_TSFT) { | 1795 | goto put_bss; |
1621 | /* in order for correct IBSS merging we need mactime | 1796 | |
1622 | * | 1797 | if (rx_status->flag & RX_FLAG_TSFT) { |
1623 | * since mactime is defined as the time the first data | 1798 | /* |
1624 | * symbol of the frame hits the PHY, and the timestamp | 1799 | * For correct IBSS merging we need mactime; since mactime is |
1625 | * of the beacon is defined as "the time that the data | 1800 | * defined as the time the first data symbol of the frame hits |
1626 | * symbol containing the first bit of the timestamp is | 1801 | * the PHY, and the timestamp of the beacon is defined as "the |
1627 | * transmitted to the PHY plus the transmitting STA’s | 1802 | * time that the data symbol containing the first bit of the |
1628 | * delays through its local PHY from the MAC-PHY | 1803 | * timestamp is transmitted to the PHY plus the transmitting |
1629 | * interface to its interface with the WM" | 1804 | * STA's delays through its local PHY from the MAC-PHY |
1630 | * (802.11 11.1.2) - equals the time this bit arrives at | 1805 | * interface to its interface with the WM" (802.11 11.1.2) |
1631 | * the receiver - we have to take into account the | 1806 | * - equals the time this bit arrives at the receiver - we have |
1632 | * offset between the two. | 1807 | * to take into account the offset between the two. |
1633 | * e.g: at 1 MBit that means mactime is 192 usec earlier | 1808 | * |
1634 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. | 1809 | * E.g. at 1 MBit that means mactime is 192 usec earlier |
1635 | */ | 1810 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. |
1636 | int rate; | 1811 | */ |
1637 | if (rx_status->flag & RX_FLAG_HT) { | 1812 | int rate; |
1638 | rate = 65; /* TODO: HT rates */ | 1813 | |
1639 | } else { | 1814 | if (rx_status->flag & RX_FLAG_HT) |
1640 | rate = local->hw.wiphy->bands[band]-> | 1815 | rate = 65; /* TODO: HT rates */ |
1641 | bitrates[rx_status->rate_idx].bitrate; | ||
1642 | } | ||
1643 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | ||
1644 | } else if (local && local->ops && local->ops->get_tsf) | ||
1645 | /* second best option: get current TSF */ | ||
1646 | rx_timestamp = local->ops->get_tsf(local_to_hw(local)); | ||
1647 | else | 1816 | else |
1648 | /* can't merge without knowing the TSF */ | 1817 | rate = local->hw.wiphy->bands[band]-> |
1649 | rx_timestamp = -1LLU; | 1818 | bitrates[rx_status->rate_idx].bitrate; |
1819 | |||
1820 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | ||
1821 | } else if (local && local->ops && local->ops->get_tsf) | ||
1822 | /* second best option: get current TSF */ | ||
1823 | rx_timestamp = local->ops->get_tsf(local_to_hw(local)); | ||
1824 | else | ||
1825 | /* can't merge without knowing the TSF */ | ||
1826 | rx_timestamp = -1LLU; | ||
1827 | |||
1650 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1828 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1651 | printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" | 1829 | printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" |
1652 | "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", | 1830 | "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", |
1653 | mgmt->sa, mgmt->bssid, | 1831 | mgmt->sa, mgmt->bssid, |
1654 | (unsigned long long)rx_timestamp, | 1832 | (unsigned long long)rx_timestamp, |
1655 | (unsigned long long)beacon_timestamp, | 1833 | (unsigned long long)beacon_timestamp, |
1656 | (unsigned long long)(rx_timestamp - beacon_timestamp), | 1834 | (unsigned long long)(rx_timestamp - beacon_timestamp), |
1657 | jiffies); | 1835 | jiffies); |
1658 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 1836 | #endif |
1659 | if (beacon_timestamp > rx_timestamp) { | 1837 | |
1838 | if (beacon_timestamp > rx_timestamp) { | ||
1660 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1839 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1661 | printk(KERN_DEBUG "%s: beacon TSF higher than " | 1840 | printk(KERN_DEBUG "%s: beacon TSF higher than " |
1662 | "local TSF - IBSS merge with BSSID %pM\n", | 1841 | "local TSF - IBSS merge with BSSID %pM\n", |
1663 | sdata->dev->name, mgmt->bssid); | 1842 | sdata->dev->name, mgmt->bssid); |
1664 | #endif | 1843 | #endif |
1665 | ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); | 1844 | ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); |
1666 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); | 1845 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); |
1667 | } | ||
1668 | } | 1846 | } |
1669 | 1847 | ||
1848 | put_bss: | ||
1670 | ieee80211_rx_bss_put(local, bss); | 1849 | ieee80211_rx_bss_put(local, bss); |
1671 | } | 1850 | } |
1672 | 1851 | ||
@@ -1712,7 +1891,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1712 | struct ieee802_11_elems elems; | 1891 | struct ieee802_11_elems elems; |
1713 | struct ieee80211_local *local = sdata->local; | 1892 | struct ieee80211_local *local = sdata->local; |
1714 | u32 changed = 0; | 1893 | u32 changed = 0; |
1715 | bool erp_valid; | 1894 | bool erp_valid, directed_tim; |
1716 | u8 erp_value = 0; | 1895 | u8 erp_value = 0; |
1717 | 1896 | ||
1718 | /* Process beacon from the current BSS */ | 1897 | /* Process beacon from the current BSS */ |
@@ -1732,9 +1911,37 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1732 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) | 1911 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) |
1733 | return; | 1912 | return; |
1734 | 1913 | ||
1914 | if (rx_status->freq != local->hw.conf.channel->center_freq) | ||
1915 | return; | ||
1916 | |||
1735 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, | 1917 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, |
1736 | elems.wmm_param_len); | 1918 | elems.wmm_param_len); |
1737 | 1919 | ||
1920 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK && | ||
1921 | local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1922 | directed_tim = ieee80211_check_tim(&elems, ifsta->aid); | ||
1923 | |||
1924 | if (directed_tim) { | ||
1925 | if (local->hw.conf.dynamic_ps_timeout > 0) { | ||
1926 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
1927 | ieee80211_hw_config(local, | ||
1928 | IEEE80211_CONF_CHANGE_PS); | ||
1929 | ieee80211_send_nullfunc(local, sdata, 0); | ||
1930 | } else { | ||
1931 | local->pspolling = true; | ||
1932 | |||
1933 | /* | ||
1934 | * Here is assumed that the driver will be | ||
1935 | * able to send ps-poll frame and receive a | ||
1936 | * response even though power save mode is | ||
1937 | * enabled, but some drivers might require | ||
1938 | * to disable power save here. This needs | ||
1939 | * to be investigated. | ||
1940 | */ | ||
1941 | ieee80211_send_pspoll(local, sdata); | ||
1942 | } | ||
1943 | } | ||
1944 | } | ||
1738 | 1945 | ||
1739 | if (elems.erp_info && elems.erp_info_len >= 1) { | 1946 | if (elems.erp_info && elems.erp_info_len >= 1) { |
1740 | erp_valid = true; | 1947 | erp_valid = true; |
@@ -1778,6 +1985,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1778 | * for the BSSID we are associated to */ | 1985 | * for the BSSID we are associated to */ |
1779 | regulatory_hint_11d(local->hw.wiphy, | 1986 | regulatory_hint_11d(local->hw.wiphy, |
1780 | elems.country_elem, elems.country_elem_len); | 1987 | elems.country_elem, elems.country_elem_len); |
1988 | |||
1989 | /* TODO: IBSS also needs this */ | ||
1990 | if (elems.pwr_constr_elem) | ||
1991 | ieee80211_handle_pwr_constr(sdata, | ||
1992 | le16_to_cpu(mgmt->u.probe_resp.capab_info), | ||
1993 | elems.pwr_constr_elem, | ||
1994 | elems.pwr_constr_elem_len); | ||
1781 | } | 1995 | } |
1782 | 1996 | ||
1783 | ieee80211_bss_info_change_notify(sdata, changed); | 1997 | ieee80211_bss_info_change_notify(sdata, changed); |
@@ -1787,8 +2001,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1787 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | 2001 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, |
1788 | struct ieee80211_if_sta *ifsta, | 2002 | struct ieee80211_if_sta *ifsta, |
1789 | struct ieee80211_mgmt *mgmt, | 2003 | struct ieee80211_mgmt *mgmt, |
1790 | size_t len, | 2004 | size_t len) |
1791 | struct ieee80211_rx_status *rx_status) | ||
1792 | { | 2005 | { |
1793 | struct ieee80211_local *local = sdata->local; | 2006 | struct ieee80211_local *local = sdata->local; |
1794 | int tx_last_beacon; | 2007 | int tx_last_beacon; |
@@ -1796,8 +2009,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1796 | struct ieee80211_mgmt *resp; | 2009 | struct ieee80211_mgmt *resp; |
1797 | u8 *pos, *end; | 2010 | u8 *pos, *end; |
1798 | 2011 | ||
1799 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC || | 2012 | if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || |
1800 | ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || | ||
1801 | len < 24 + 2 || !ifsta->probe_resp) | 2013 | len < 24 + 2 || !ifsta->probe_resp) |
1802 | return; | 2014 | return; |
1803 | 2015 | ||
@@ -1901,32 +2113,54 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1901 | mgmt = (struct ieee80211_mgmt *) skb->data; | 2113 | mgmt = (struct ieee80211_mgmt *) skb->data; |
1902 | fc = le16_to_cpu(mgmt->frame_control); | 2114 | fc = le16_to_cpu(mgmt->frame_control); |
1903 | 2115 | ||
1904 | switch (fc & IEEE80211_FCTL_STYPE) { | 2116 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
1905 | case IEEE80211_STYPE_PROBE_REQ: | 2117 | switch (fc & IEEE80211_FCTL_STYPE) { |
1906 | ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len, | 2118 | case IEEE80211_STYPE_PROBE_REQ: |
1907 | rx_status); | 2119 | ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, |
1908 | break; | 2120 | skb->len); |
1909 | case IEEE80211_STYPE_PROBE_RESP: | 2121 | break; |
1910 | ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); | 2122 | case IEEE80211_STYPE_PROBE_RESP: |
1911 | break; | 2123 | ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, |
1912 | case IEEE80211_STYPE_BEACON: | 2124 | rx_status); |
1913 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); | 2125 | break; |
1914 | break; | 2126 | case IEEE80211_STYPE_BEACON: |
1915 | case IEEE80211_STYPE_AUTH: | 2127 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, |
1916 | ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); | 2128 | rx_status); |
1917 | break; | 2129 | break; |
1918 | case IEEE80211_STYPE_ASSOC_RESP: | 2130 | case IEEE80211_STYPE_AUTH: |
1919 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); | 2131 | ieee80211_rx_mgmt_auth_ibss(sdata, ifsta, mgmt, |
1920 | break; | 2132 | skb->len); |
1921 | case IEEE80211_STYPE_REASSOC_RESP: | 2133 | break; |
1922 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); | 2134 | } |
1923 | break; | 2135 | } else { /* NL80211_IFTYPE_STATION */ |
1924 | case IEEE80211_STYPE_DEAUTH: | 2136 | switch (fc & IEEE80211_FCTL_STYPE) { |
1925 | ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); | 2137 | case IEEE80211_STYPE_PROBE_RESP: |
1926 | break; | 2138 | ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, |
1927 | case IEEE80211_STYPE_DISASSOC: | 2139 | rx_status); |
1928 | ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); | 2140 | break; |
1929 | break; | 2141 | case IEEE80211_STYPE_BEACON: |
2142 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, | ||
2143 | rx_status); | ||
2144 | break; | ||
2145 | case IEEE80211_STYPE_AUTH: | ||
2146 | ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); | ||
2147 | break; | ||
2148 | case IEEE80211_STYPE_ASSOC_RESP: | ||
2149 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, | ||
2150 | skb->len, 0); | ||
2151 | break; | ||
2152 | case IEEE80211_STYPE_REASSOC_RESP: | ||
2153 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, | ||
2154 | skb->len, 1); | ||
2155 | break; | ||
2156 | case IEEE80211_STYPE_DEAUTH: | ||
2157 | ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); | ||
2158 | break; | ||
2159 | case IEEE80211_STYPE_DISASSOC: | ||
2160 | ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, | ||
2161 | skb->len); | ||
2162 | break; | ||
2163 | } | ||
1930 | } | 2164 | } |
1931 | 2165 | ||
1932 | kfree_skb(skb); | 2166 | kfree_skb(skb); |
@@ -1965,9 +2199,21 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, | |||
1965 | if (ieee80211_sta_active_ibss(sdata)) | 2199 | if (ieee80211_sta_active_ibss(sdata)) |
1966 | return; | 2200 | return; |
1967 | 2201 | ||
2202 | if ((sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) && | ||
2203 | (!(sdata->u.sta.flags & IEEE80211_STA_AUTO_CHANNEL_SEL))) | ||
2204 | return; | ||
2205 | |||
1968 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 2206 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " |
1969 | "IBSS networks with same SSID (merge)\n", sdata->dev->name); | 2207 | "IBSS networks with same SSID (merge)\n", sdata->dev->name); |
1970 | ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len); | 2208 | |
2209 | /* XXX maybe racy? */ | ||
2210 | if (sdata->local->scan_req) | ||
2211 | return; | ||
2212 | |||
2213 | memcpy(sdata->local->int_scan_req.ssids[0].ssid, | ||
2214 | ifsta->ssid, IEEE80211_MAX_SSID_LEN); | ||
2215 | sdata->local->int_scan_req.ssids[0].ssid_len = ifsta->ssid_len; | ||
2216 | ieee80211_request_scan(sdata, &sdata->local->int_scan_req); | ||
1971 | } | 2217 | } |
1972 | 2218 | ||
1973 | 2219 | ||
@@ -2013,94 +2259,56 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, | |||
2013 | netif_carrier_off(sdata->dev); | 2259 | netif_carrier_off(sdata->dev); |
2014 | } | 2260 | } |
2015 | 2261 | ||
2016 | |||
2017 | static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, | ||
2018 | const char *ssid, int ssid_len) | ||
2019 | { | ||
2020 | int tmp, hidden_ssid; | ||
2021 | |||
2022 | if (ssid_len == ifsta->ssid_len && | ||
2023 | !memcmp(ifsta->ssid, ssid, ssid_len)) | ||
2024 | return 1; | ||
2025 | |||
2026 | if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) | ||
2027 | return 0; | ||
2028 | |||
2029 | hidden_ssid = 1; | ||
2030 | tmp = ssid_len; | ||
2031 | while (tmp--) { | ||
2032 | if (ssid[tmp] != '\0') { | ||
2033 | hidden_ssid = 0; | ||
2034 | break; | ||
2035 | } | ||
2036 | } | ||
2037 | |||
2038 | if (hidden_ssid && (ifsta->ssid_len == ssid_len || ssid_len == 0)) | ||
2039 | return 1; | ||
2040 | |||
2041 | if (ssid_len == 1 && ssid[0] == ' ') | ||
2042 | return 1; | ||
2043 | |||
2044 | return 0; | ||
2045 | } | ||
2046 | |||
2047 | static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, | 2262 | static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, |
2048 | struct ieee80211_if_sta *ifsta) | 2263 | struct ieee80211_if_sta *ifsta) |
2049 | { | 2264 | { |
2050 | struct ieee80211_local *local = sdata->local; | 2265 | struct ieee80211_local *local = sdata->local; |
2051 | struct ieee80211_bss *bss; | ||
2052 | struct ieee80211_supported_band *sband; | 2266 | struct ieee80211_supported_band *sband; |
2053 | u8 bssid[ETH_ALEN], *pos; | 2267 | u8 *pos; |
2268 | u8 bssid[ETH_ALEN]; | ||
2269 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | ||
2270 | u16 capability; | ||
2054 | int i; | 2271 | int i; |
2055 | int ret; | 2272 | |
2056 | 2273 | if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) { | |
2057 | #if 0 | 2274 | memcpy(bssid, ifsta->bssid, ETH_ALEN); |
2058 | /* Easier testing, use fixed BSSID. */ | 2275 | } else { |
2059 | memset(bssid, 0xfe, ETH_ALEN); | 2276 | /* Generate random, not broadcast, locally administered BSSID. Mix in |
2060 | #else | 2277 | * own MAC address to make sure that devices that do not have proper |
2061 | /* Generate random, not broadcast, locally administered BSSID. Mix in | 2278 | * random number generator get different BSSID. */ |
2062 | * own MAC address to make sure that devices that do not have proper | 2279 | get_random_bytes(bssid, ETH_ALEN); |
2063 | * random number generator get different BSSID. */ | 2280 | for (i = 0; i < ETH_ALEN; i++) |
2064 | get_random_bytes(bssid, ETH_ALEN); | 2281 | bssid[i] ^= sdata->dev->dev_addr[i]; |
2065 | for (i = 0; i < ETH_ALEN; i++) | 2282 | bssid[0] &= ~0x01; |
2066 | bssid[i] ^= sdata->dev->dev_addr[i]; | 2283 | bssid[0] |= 0x02; |
2067 | bssid[0] &= ~0x01; | 2284 | } |
2068 | bssid[0] |= 0x02; | ||
2069 | #endif | ||
2070 | 2285 | ||
2071 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", | 2286 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", |
2072 | sdata->dev->name, bssid); | 2287 | sdata->dev->name, bssid); |
2073 | 2288 | ||
2074 | bss = ieee80211_rx_bss_add(local, bssid, | 2289 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
2075 | local->hw.conf.channel->center_freq, | ||
2076 | sdata->u.sta.ssid, sdata->u.sta.ssid_len); | ||
2077 | if (!bss) | ||
2078 | return -ENOMEM; | ||
2079 | |||
2080 | bss->band = local->hw.conf.channel->band; | ||
2081 | sband = local->hw.wiphy->bands[bss->band]; | ||
2082 | 2290 | ||
2083 | if (local->hw.conf.beacon_int == 0) | 2291 | if (local->hw.conf.beacon_int == 0) |
2084 | local->hw.conf.beacon_int = 100; | 2292 | local->hw.conf.beacon_int = 100; |
2085 | bss->beacon_int = local->hw.conf.beacon_int; | 2293 | |
2086 | bss->last_update = jiffies; | 2294 | capability = WLAN_CAPABILITY_IBSS; |
2087 | bss->capability = WLAN_CAPABILITY_IBSS; | ||
2088 | 2295 | ||
2089 | if (sdata->default_key) | 2296 | if (sdata->default_key) |
2090 | bss->capability |= WLAN_CAPABILITY_PRIVACY; | 2297 | capability |= WLAN_CAPABILITY_PRIVACY; |
2091 | else | 2298 | else |
2092 | sdata->drop_unencrypted = 0; | 2299 | sdata->drop_unencrypted = 0; |
2093 | 2300 | ||
2094 | bss->supp_rates_len = sband->n_bitrates; | 2301 | pos = supp_rates; |
2095 | pos = bss->supp_rates; | ||
2096 | for (i = 0; i < sband->n_bitrates; i++) { | 2302 | for (i = 0; i < sband->n_bitrates; i++) { |
2097 | int rate = sband->bitrates[i].bitrate; | 2303 | int rate = sband->bitrates[i].bitrate; |
2098 | *pos++ = (u8) (rate / 5); | 2304 | *pos++ = (u8) (rate / 5); |
2099 | } | 2305 | } |
2100 | 2306 | ||
2101 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); | 2307 | return __ieee80211_sta_join_ibss(sdata, ifsta, |
2102 | ieee80211_rx_bss_put(local, bss); | 2308 | bssid, local->hw.conf.beacon_int, |
2103 | return ret; | 2309 | local->hw.conf.channel->center_freq, |
2310 | sband->n_bitrates, supp_rates, | ||
2311 | capability); | ||
2104 | } | 2312 | } |
2105 | 2313 | ||
2106 | 2314 | ||
@@ -2109,8 +2317,6 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, | |||
2109 | { | 2317 | { |
2110 | struct ieee80211_local *local = sdata->local; | 2318 | struct ieee80211_local *local = sdata->local; |
2111 | struct ieee80211_bss *bss; | 2319 | struct ieee80211_bss *bss; |
2112 | int found = 0; | ||
2113 | u8 bssid[ETH_ALEN]; | ||
2114 | int active_ibss; | 2320 | int active_ibss; |
2115 | 2321 | ||
2116 | if (ifsta->ssid_len == 0) | 2322 | if (ifsta->ssid_len == 0) |
@@ -2121,51 +2327,39 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, | |||
2121 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", | 2327 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", |
2122 | sdata->dev->name, active_ibss); | 2328 | sdata->dev->name, active_ibss); |
2123 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2329 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
2124 | spin_lock_bh(&local->bss_lock); | 2330 | |
2125 | list_for_each_entry(bss, &local->bss_list, list) { | 2331 | if (active_ibss) |
2126 | if (ifsta->ssid_len != bss->ssid_len || | 2332 | return 0; |
2127 | memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 | 2333 | |
2128 | || !(bss->capability & WLAN_CAPABILITY_IBSS)) | 2334 | if (ifsta->flags & IEEE80211_STA_BSSID_SET) |
2129 | continue; | 2335 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, 0, |
2130 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2336 | ifsta->ssid, ifsta->ssid_len); |
2131 | printk(KERN_DEBUG " bssid=%pM found\n", bss->bssid); | 2337 | else |
2132 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2338 | bss = (void *)cfg80211_get_ibss(local->hw.wiphy, |
2133 | memcpy(bssid, bss->bssid, ETH_ALEN); | 2339 | NULL, |
2134 | found = 1; | 2340 | ifsta->ssid, ifsta->ssid_len); |
2135 | if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0) | ||
2136 | break; | ||
2137 | } | ||
2138 | spin_unlock_bh(&local->bss_lock); | ||
2139 | 2341 | ||
2140 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2342 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2141 | if (found) | 2343 | if (bss) |
2142 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " | 2344 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " |
2143 | "%pM\n", bssid, ifsta->bssid); | 2345 | "%pM\n", bss->cbss.bssid, ifsta->bssid); |
2144 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2346 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
2145 | 2347 | ||
2146 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { | 2348 | if (bss && |
2349 | (!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) || | ||
2350 | memcmp(ifsta->bssid, bss->cbss.bssid, ETH_ALEN))) { | ||
2147 | int ret; | 2351 | int ret; |
2148 | int search_freq; | ||
2149 | |||
2150 | if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) | ||
2151 | search_freq = bss->freq; | ||
2152 | else | ||
2153 | search_freq = local->hw.conf.channel->center_freq; | ||
2154 | |||
2155 | bss = ieee80211_rx_bss_get(local, bssid, search_freq, | ||
2156 | ifsta->ssid, ifsta->ssid_len); | ||
2157 | if (!bss) | ||
2158 | goto dont_join; | ||
2159 | 2352 | ||
2160 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" | 2353 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" |
2161 | " based on configured SSID\n", | 2354 | " based on configured SSID\n", |
2162 | sdata->dev->name, bssid); | 2355 | sdata->dev->name, bss->cbss.bssid); |
2356 | |||
2163 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); | 2357 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); |
2164 | ieee80211_rx_bss_put(local, bss); | 2358 | ieee80211_rx_bss_put(local, bss); |
2165 | return ret; | 2359 | return ret; |
2166 | } | 2360 | } else if (bss) |
2361 | ieee80211_rx_bss_put(local, bss); | ||
2167 | 2362 | ||
2168 | dont_join: | ||
2169 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2363 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2170 | printk(KERN_DEBUG " did not try to join ibss\n"); | 2364 | printk(KERN_DEBUG " did not try to join ibss\n"); |
2171 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2365 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
@@ -2179,8 +2373,15 @@ dont_join: | |||
2179 | IEEE80211_SCAN_INTERVAL)) { | 2373 | IEEE80211_SCAN_INTERVAL)) { |
2180 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 2374 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " |
2181 | "join\n", sdata->dev->name); | 2375 | "join\n", sdata->dev->name); |
2182 | return ieee80211_request_scan(sdata, ifsta->ssid, | 2376 | |
2183 | ifsta->ssid_len); | 2377 | /* XXX maybe racy? */ |
2378 | if (local->scan_req) | ||
2379 | return -EBUSY; | ||
2380 | |||
2381 | memcpy(local->int_scan_req.ssids[0].ssid, | ||
2382 | ifsta->ssid, IEEE80211_MAX_SSID_LEN); | ||
2383 | local->int_scan_req.ssids[0].ssid_len = ifsta->ssid_len; | ||
2384 | return ieee80211_request_scan(sdata, &local->int_scan_req); | ||
2184 | } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { | 2385 | } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { |
2185 | int interval = IEEE80211_SCAN_INTERVAL; | 2386 | int interval = IEEE80211_SCAN_INTERVAL; |
2186 | 2387 | ||
@@ -2214,76 +2415,81 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, | |||
2214 | struct ieee80211_if_sta *ifsta) | 2415 | struct ieee80211_if_sta *ifsta) |
2215 | { | 2416 | { |
2216 | struct ieee80211_local *local = sdata->local; | 2417 | struct ieee80211_local *local = sdata->local; |
2217 | struct ieee80211_bss *bss, *selected = NULL; | 2418 | struct ieee80211_bss *bss; |
2218 | int top_rssi = 0, freq; | 2419 | u8 *bssid = ifsta->bssid, *ssid = ifsta->ssid; |
2219 | 2420 | u8 ssid_len = ifsta->ssid_len; | |
2220 | spin_lock_bh(&local->bss_lock); | 2421 | u16 capa_mask = WLAN_CAPABILITY_ESS; |
2221 | freq = local->oper_channel->center_freq; | 2422 | u16 capa_val = WLAN_CAPABILITY_ESS; |
2222 | list_for_each_entry(bss, &local->bss_list, list) { | 2423 | struct ieee80211_channel *chan = local->oper_channel; |
2223 | if (!(bss->capability & WLAN_CAPABILITY_ESS)) | 2424 | |
2224 | continue; | 2425 | if (ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | |
2225 | 2426 | IEEE80211_STA_AUTO_BSSID_SEL | | |
2226 | if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | | 2427 | IEEE80211_STA_AUTO_CHANNEL_SEL)) { |
2227 | IEEE80211_STA_AUTO_BSSID_SEL | | 2428 | capa_mask |= WLAN_CAPABILITY_PRIVACY; |
2228 | IEEE80211_STA_AUTO_CHANNEL_SEL)) && | 2429 | if (sdata->default_key) |
2229 | (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ | 2430 | capa_val |= WLAN_CAPABILITY_PRIVACY; |
2230 | !!sdata->default_key)) | ||
2231 | continue; | ||
2232 | |||
2233 | if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && | ||
2234 | bss->freq != freq) | ||
2235 | continue; | ||
2236 | |||
2237 | if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && | ||
2238 | memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) | ||
2239 | continue; | ||
2240 | |||
2241 | if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && | ||
2242 | !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) | ||
2243 | continue; | ||
2244 | |||
2245 | if (!selected || top_rssi < bss->signal) { | ||
2246 | selected = bss; | ||
2247 | top_rssi = bss->signal; | ||
2248 | } | ||
2249 | } | 2431 | } |
2250 | if (selected) | ||
2251 | atomic_inc(&selected->users); | ||
2252 | spin_unlock_bh(&local->bss_lock); | ||
2253 | 2432 | ||
2254 | if (selected) { | 2433 | if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) |
2255 | ieee80211_set_freq(sdata, selected->freq); | 2434 | chan = NULL; |
2435 | |||
2436 | if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) | ||
2437 | bssid = NULL; | ||
2438 | |||
2439 | if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) { | ||
2440 | ssid = NULL; | ||
2441 | ssid_len = 0; | ||
2442 | } | ||
2443 | |||
2444 | bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, | ||
2445 | bssid, ssid, ssid_len, | ||
2446 | capa_mask, capa_val); | ||
2447 | |||
2448 | if (bss) { | ||
2449 | ieee80211_set_freq(sdata, bss->cbss.channel->center_freq); | ||
2256 | if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) | 2450 | if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) |
2257 | ieee80211_sta_set_ssid(sdata, selected->ssid, | 2451 | ieee80211_sta_set_ssid(sdata, bss->ssid, |
2258 | selected->ssid_len); | 2452 | bss->ssid_len); |
2259 | ieee80211_sta_set_bssid(sdata, selected->bssid); | 2453 | ieee80211_sta_set_bssid(sdata, bss->cbss.bssid); |
2260 | ieee80211_sta_def_wmm_params(sdata, selected); | 2454 | ieee80211_sta_def_wmm_params(sdata, bss->supp_rates_len, |
2455 | bss->supp_rates); | ||
2456 | if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED) | ||
2457 | sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED; | ||
2458 | else | ||
2459 | sdata->u.sta.flags &= ~IEEE80211_STA_MFP_ENABLED; | ||
2261 | 2460 | ||
2262 | /* Send out direct probe if no probe resp was received or | 2461 | /* Send out direct probe if no probe resp was received or |
2263 | * the one we have is outdated | 2462 | * the one we have is outdated |
2264 | */ | 2463 | */ |
2265 | if (!selected->last_probe_resp || | 2464 | if (!bss->last_probe_resp || |
2266 | time_after(jiffies, selected->last_probe_resp | 2465 | time_after(jiffies, bss->last_probe_resp |
2267 | + IEEE80211_SCAN_RESULT_EXPIRE)) | 2466 | + IEEE80211_SCAN_RESULT_EXPIRE)) |
2268 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; | 2467 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
2269 | else | 2468 | else |
2270 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | 2469 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; |
2271 | 2470 | ||
2272 | ieee80211_rx_bss_put(local, selected); | 2471 | ieee80211_rx_bss_put(local, bss); |
2273 | ieee80211_sta_reset_auth(sdata, ifsta); | 2472 | ieee80211_sta_reset_auth(sdata, ifsta); |
2274 | return 0; | 2473 | return 0; |
2275 | } else { | 2474 | } else { |
2276 | if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { | 2475 | if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { |
2277 | ifsta->assoc_scan_tries++; | 2476 | ifsta->assoc_scan_tries++; |
2477 | /* XXX maybe racy? */ | ||
2478 | if (local->scan_req) | ||
2479 | return -1; | ||
2480 | memcpy(local->int_scan_req.ssids[0].ssid, | ||
2481 | ifsta->ssid, IEEE80211_MAX_SSID_LEN); | ||
2278 | if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) | 2482 | if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) |
2279 | ieee80211_start_scan(sdata, NULL, 0); | 2483 | local->int_scan_req.ssids[0].ssid_len = 0; |
2280 | else | 2484 | else |
2281 | ieee80211_start_scan(sdata, ifsta->ssid, | 2485 | local->int_scan_req.ssids[0].ssid_len = ifsta->ssid_len; |
2282 | ifsta->ssid_len); | 2486 | ieee80211_start_scan(sdata, &local->int_scan_req); |
2283 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | 2487 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; |
2284 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | 2488 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); |
2285 | } else | 2489 | } else { |
2490 | ifsta->assoc_scan_tries = 0; | ||
2286 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 2491 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
2492 | } | ||
2287 | } | 2493 | } |
2288 | return -1; | 2494 | return -1; |
2289 | } | 2495 | } |
@@ -2315,8 +2521,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2315 | ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && | 2521 | ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && |
2316 | ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && | 2522 | ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && |
2317 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { | 2523 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { |
2318 | ieee80211_start_scan(sdata, ifsta->scan_ssid, | 2524 | ieee80211_start_scan(sdata, local->scan_req); |
2319 | ifsta->scan_ssid_len); | ||
2320 | return; | 2525 | return; |
2321 | } | 2526 | } |
2322 | 2527 | ||
@@ -2376,8 +2581,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2376 | 2581 | ||
2377 | ifsta = &sdata->u.sta; | 2582 | ifsta = &sdata->u.sta; |
2378 | INIT_WORK(&ifsta->work, ieee80211_sta_work); | 2583 | INIT_WORK(&ifsta->work, ieee80211_sta_work); |
2584 | INIT_WORK(&ifsta->chswitch_work, ieee80211_chswitch_work); | ||
2379 | setup_timer(&ifsta->timer, ieee80211_sta_timer, | 2585 | setup_timer(&ifsta->timer, ieee80211_sta_timer, |
2380 | (unsigned long) sdata); | 2586 | (unsigned long) sdata); |
2587 | setup_timer(&ifsta->chswitch_timer, ieee80211_chswitch_timer, | ||
2588 | (unsigned long) sdata); | ||
2381 | skb_queue_head_init(&ifsta->skb_queue); | 2589 | skb_queue_head_init(&ifsta->skb_queue); |
2382 | 2590 | ||
2383 | ifsta->capab = WLAN_CAPABILITY_ESS; | 2591 | ifsta->capab = WLAN_CAPABILITY_ESS; |
@@ -2396,7 +2604,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2396 | * must be callable in atomic context. | 2604 | * must be callable in atomic context. |
2397 | */ | 2605 | */ |
2398 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 2606 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
2399 | u8 *bssid,u8 *addr, u64 supp_rates) | 2607 | u8 *bssid,u8 *addr, u32 supp_rates) |
2400 | { | 2608 | { |
2401 | struct ieee80211_local *local = sdata->local; | 2609 | struct ieee80211_local *local = sdata->local; |
2402 | struct sta_info *sta; | 2610 | struct sta_info *sta; |
@@ -2474,16 +2682,16 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size | |||
2474 | memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); | 2682 | memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); |
2475 | memcpy(ifsta->ssid, ssid, len); | 2683 | memcpy(ifsta->ssid, ssid, len); |
2476 | ifsta->ssid_len = len; | 2684 | ifsta->ssid_len = len; |
2477 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
2478 | } | 2685 | } |
2479 | 2686 | ||
2687 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
2688 | |||
2480 | if (len) | 2689 | if (len) |
2481 | ifsta->flags |= IEEE80211_STA_SSID_SET; | 2690 | ifsta->flags |= IEEE80211_STA_SSID_SET; |
2482 | else | 2691 | else |
2483 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; | 2692 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; |
2484 | 2693 | ||
2485 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 2694 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
2486 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { | ||
2487 | ifsta->ibss_join_req = jiffies; | 2695 | ifsta->ibss_join_req = jiffies; |
2488 | ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; | 2696 | ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; |
2489 | return ieee80211_sta_find_ibss(sdata, ifsta); | 2697 | return ieee80211_sta_find_ibss(sdata, ifsta); |
@@ -2503,31 +2711,25 @@ int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size | |||
2503 | int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) | 2711 | int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) |
2504 | { | 2712 | { |
2505 | struct ieee80211_if_sta *ifsta; | 2713 | struct ieee80211_if_sta *ifsta; |
2506 | int res; | ||
2507 | 2714 | ||
2508 | ifsta = &sdata->u.sta; | 2715 | ifsta = &sdata->u.sta; |
2509 | 2716 | ||
2510 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { | 2717 | if (is_valid_ether_addr(bssid)) { |
2511 | memcpy(ifsta->bssid, bssid, ETH_ALEN); | 2718 | memcpy(ifsta->bssid, bssid, ETH_ALEN); |
2512 | res = 0; | 2719 | ifsta->flags |= IEEE80211_STA_BSSID_SET; |
2513 | /* | 2720 | } else { |
2514 | * Hack! See also ieee80211_sta_set_ssid. | 2721 | memset(ifsta->bssid, 0, ETH_ALEN); |
2515 | */ | 2722 | ifsta->flags &= ~IEEE80211_STA_BSSID_SET; |
2516 | if (netif_running(sdata->dev)) | 2723 | } |
2517 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | 2724 | |
2518 | if (res) { | 2725 | if (netif_running(sdata->dev)) { |
2726 | if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) { | ||
2519 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " | 2727 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " |
2520 | "the low-level driver\n", sdata->dev->name); | 2728 | "the low-level driver\n", sdata->dev->name); |
2521 | return res; | ||
2522 | } | 2729 | } |
2523 | } | 2730 | } |
2524 | 2731 | ||
2525 | if (is_valid_ether_addr(bssid)) | 2732 | return ieee80211_sta_set_ssid(sdata, ifsta->ssid, ifsta->ssid_len); |
2526 | ifsta->flags |= IEEE80211_STA_BSSID_SET; | ||
2527 | else | ||
2528 | ifsta->flags &= ~IEEE80211_STA_BSSID_SET; | ||
2529 | |||
2530 | return 0; | ||
2531 | } | 2733 | } |
2532 | 2734 | ||
2533 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) | 2735 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) |
@@ -2590,9 +2792,8 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | |||
2590 | 2792 | ||
2591 | if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 2793 | if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
2592 | ifsta = &sdata->u.sta; | 2794 | ifsta = &sdata->u.sta; |
2593 | if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || | 2795 | if ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) || |
2594 | (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && | 2796 | !ieee80211_sta_active_ibss(sdata)) |
2595 | !ieee80211_sta_active_ibss(sdata))) | ||
2596 | ieee80211_sta_find_ibss(sdata, ifsta); | 2797 | ieee80211_sta_find_ibss(sdata, ifsta); |
2597 | } | 2798 | } |
2598 | 2799 | ||
@@ -2623,12 +2824,15 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
2623 | struct ieee80211_local *local = | 2824 | struct ieee80211_local *local = |
2624 | container_of(work, struct ieee80211_local, | 2825 | container_of(work, struct ieee80211_local, |
2625 | dynamic_ps_enable_work); | 2826 | dynamic_ps_enable_work); |
2827 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
2626 | 2828 | ||
2627 | if (local->hw.conf.flags & IEEE80211_CONF_PS) | 2829 | if (local->hw.conf.flags & IEEE80211_CONF_PS) |
2628 | return; | 2830 | return; |
2629 | 2831 | ||
2630 | local->hw.conf.flags |= IEEE80211_CONF_PS; | 2832 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) |
2833 | ieee80211_send_nullfunc(local, sdata, 1); | ||
2631 | 2834 | ||
2835 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
2632 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 2836 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
2633 | } | 2837 | } |
2634 | 2838 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c new file mode 100644 index 000000000000..44525f517077 --- /dev/null +++ b/net/mac80211/pm.c | |||
@@ -0,0 +1,117 @@ | |||
1 | #include <net/mac80211.h> | ||
2 | #include <net/rtnetlink.h> | ||
3 | |||
4 | #include "ieee80211_i.h" | ||
5 | #include "led.h" | ||
6 | |||
7 | int __ieee80211_suspend(struct ieee80211_hw *hw) | ||
8 | { | ||
9 | struct ieee80211_local *local = hw_to_local(hw); | ||
10 | struct ieee80211_sub_if_data *sdata; | ||
11 | struct ieee80211_if_init_conf conf; | ||
12 | struct sta_info *sta; | ||
13 | |||
14 | flush_workqueue(local->hw.workqueue); | ||
15 | |||
16 | /* disable keys */ | ||
17 | list_for_each_entry(sdata, &local->interfaces, list) | ||
18 | ieee80211_disable_keys(sdata); | ||
19 | |||
20 | /* remove STAs */ | ||
21 | list_for_each_entry(sta, &local->sta_list, list) { | ||
22 | |||
23 | if (local->ops->sta_notify) { | ||
24 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
25 | sdata = container_of(sdata->bss, | ||
26 | struct ieee80211_sub_if_data, | ||
27 | u.ap); | ||
28 | |||
29 | local->ops->sta_notify(hw, &sdata->vif, | ||
30 | STA_NOTIFY_REMOVE, &sta->sta); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | /* remove all interfaces */ | ||
35 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
36 | |||
37 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
38 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
39 | netif_running(sdata->dev)) { | ||
40 | conf.vif = &sdata->vif; | ||
41 | conf.type = sdata->vif.type; | ||
42 | conf.mac_addr = sdata->dev->dev_addr; | ||
43 | local->ops->remove_interface(hw, &conf); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /* flush again, in case driver queued work */ | ||
48 | flush_workqueue(local->hw.workqueue); | ||
49 | |||
50 | /* stop hardware */ | ||
51 | if (local->open_count) { | ||
52 | ieee80211_led_radio(local, false); | ||
53 | local->ops->stop(hw); | ||
54 | } | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | int __ieee80211_resume(struct ieee80211_hw *hw) | ||
59 | { | ||
60 | struct ieee80211_local *local = hw_to_local(hw); | ||
61 | struct ieee80211_sub_if_data *sdata; | ||
62 | struct ieee80211_if_init_conf conf; | ||
63 | struct sta_info *sta; | ||
64 | int res; | ||
65 | |||
66 | /* restart hardware */ | ||
67 | if (local->open_count) { | ||
68 | res = local->ops->start(hw); | ||
69 | |||
70 | ieee80211_led_radio(local, hw->conf.radio_enabled); | ||
71 | } | ||
72 | |||
73 | /* add interfaces */ | ||
74 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
75 | |||
76 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
77 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
78 | netif_running(sdata->dev)) { | ||
79 | conf.vif = &sdata->vif; | ||
80 | conf.type = sdata->vif.type; | ||
81 | conf.mac_addr = sdata->dev->dev_addr; | ||
82 | res = local->ops->add_interface(hw, &conf); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | /* add STAs back */ | ||
87 | list_for_each_entry(sta, &local->sta_list, list) { | ||
88 | |||
89 | if (local->ops->sta_notify) { | ||
90 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
91 | sdata = container_of(sdata->bss, | ||
92 | struct ieee80211_sub_if_data, | ||
93 | u.ap); | ||
94 | |||
95 | local->ops->sta_notify(hw, &sdata->vif, | ||
96 | STA_NOTIFY_ADD, &sta->sta); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* add back keys */ | ||
101 | list_for_each_entry(sdata, &local->interfaces, list) | ||
102 | if (netif_running(sdata->dev)) | ||
103 | ieee80211_enable_keys(sdata); | ||
104 | |||
105 | /* setup RTS threshold */ | ||
106 | if (local->ops->set_rts_threshold) | ||
107 | local->ops->set_rts_threshold(hw, local->rts_threshold); | ||
108 | |||
109 | /* reconfigure hardware */ | ||
110 | ieee80211_hw_config(local, ~0); | ||
111 | |||
112 | netif_addr_lock_bh(local->mdev); | ||
113 | ieee80211_configure_filter(local); | ||
114 | netif_addr_unlock_bh(local->mdev); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7175ae80c36a..1327d424bf31 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -86,8 +86,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
86 | 86 | ||
87 | if (status->flag & RX_FLAG_TSFT) | 87 | if (status->flag & RX_FLAG_TSFT) |
88 | len += 8; | 88 | len += 8; |
89 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB || | 89 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
90 | local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
91 | len += 1; | 90 | len += 1; |
92 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | 91 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) |
93 | len += 1; | 92 | len += 1; |
@@ -102,7 +101,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
102 | return len; | 101 | return len; |
103 | } | 102 | } |
104 | 103 | ||
105 | /** | 104 | /* |
106 | * ieee80211_add_rx_radiotap_header - add radiotap header | 105 | * ieee80211_add_rx_radiotap_header - add radiotap header |
107 | * | 106 | * |
108 | * add a radiotap header containing all the fields which the hardware provided. | 107 | * add a radiotap header containing all the fields which the hardware provided. |
@@ -158,7 +157,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
158 | */ | 157 | */ |
159 | *pos = 0; | 158 | *pos = 0; |
160 | } else { | 159 | } else { |
161 | rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE); | 160 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); |
162 | *pos = rate->bitrate / 5; | 161 | *pos = rate->bitrate / 5; |
163 | } | 162 | } |
164 | pos++; | 163 | pos++; |
@@ -199,14 +198,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
199 | *pos = status->antenna; | 198 | *pos = status->antenna; |
200 | pos++; | 199 | pos++; |
201 | 200 | ||
202 | /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */ | ||
203 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) { | ||
204 | *pos = status->signal; | ||
205 | rthdr->it_present |= | ||
206 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL); | ||
207 | pos++; | ||
208 | } | ||
209 | |||
210 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ | 201 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ |
211 | 202 | ||
212 | /* IEEE80211_RADIOTAP_RX_FLAGS */ | 203 | /* IEEE80211_RADIOTAP_RX_FLAGS */ |
@@ -371,39 +362,50 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
371 | rx->skb->priority = (tid > 7) ? 0 : tid; | 362 | rx->skb->priority = (tid > 7) ? 0 : tid; |
372 | } | 363 | } |
373 | 364 | ||
374 | static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) | 365 | /** |
366 | * DOC: Packet alignment | ||
367 | * | ||
368 | * Drivers always need to pass packets that are aligned to two-byte boundaries | ||
369 | * to the stack. | ||
370 | * | ||
371 | * Additionally, should, if possible, align the payload data in a way that | ||
372 | * guarantees that the contained IP header is aligned to a four-byte | ||
373 | * boundary. In the case of regular frames, this simply means aligning the | ||
374 | * payload to a four-byte boundary (because either the IP header is directly | ||
375 | * contained, or IV/RFC1042 headers that have a length divisible by four are | ||
376 | * in front of it). | ||
377 | * | ||
378 | * With A-MSDU frames, however, the payload data address must yield two modulo | ||
379 | * four because there are 14-byte 802.3 headers within the A-MSDU frames that | ||
380 | * push the IP header further back to a multiple of four again. Thankfully, the | ||
381 | * specs were sane enough this time around to require padding each A-MSDU | ||
382 | * subframe to a length that is a multiple of four. | ||
383 | * | ||
384 | * Padding like Atheros hardware adds which is inbetween the 802.11 header and | ||
385 | * the payload is not supported, the driver is required to move the 802.11 | ||
386 | * header to be directly in front of the payload in that case. | ||
387 | */ | ||
388 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) | ||
375 | { | 389 | { |
376 | #ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT | ||
377 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 390 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
378 | int hdrlen; | 391 | int hdrlen; |
379 | 392 | ||
393 | #ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT | ||
394 | return; | ||
395 | #endif | ||
396 | |||
397 | if (WARN_ONCE((unsigned long)rx->skb->data & 1, | ||
398 | "unaligned packet at 0x%p\n", rx->skb->data)) | ||
399 | return; | ||
400 | |||
380 | if (!ieee80211_is_data_present(hdr->frame_control)) | 401 | if (!ieee80211_is_data_present(hdr->frame_control)) |
381 | return; | 402 | return; |
382 | 403 | ||
383 | /* | ||
384 | * Drivers are required to align the payload data in a way that | ||
385 | * guarantees that the contained IP header is aligned to a four- | ||
386 | * byte boundary. In the case of regular frames, this simply means | ||
387 | * aligning the payload to a four-byte boundary (because either | ||
388 | * the IP header is directly contained, or IV/RFC1042 headers that | ||
389 | * have a length divisible by four are in front of it. | ||
390 | * | ||
391 | * With A-MSDU frames, however, the payload data address must | ||
392 | * yield two modulo four because there are 14-byte 802.3 headers | ||
393 | * within the A-MSDU frames that push the IP header further back | ||
394 | * to a multiple of four again. Thankfully, the specs were sane | ||
395 | * enough this time around to require padding each A-MSDU subframe | ||
396 | * to a length that is a multiple of four. | ||
397 | * | ||
398 | * Padding like atheros hardware adds which is inbetween the 802.11 | ||
399 | * header and the payload is not supported, the driver is required | ||
400 | * to move the 802.11 header further back in that case. | ||
401 | */ | ||
402 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 404 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
403 | if (rx->flags & IEEE80211_RX_AMSDU) | 405 | if (rx->flags & IEEE80211_RX_AMSDU) |
404 | hdrlen += ETH_HLEN; | 406 | hdrlen += ETH_HLEN; |
405 | WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3); | 407 | WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3, |
406 | #endif | 408 | "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen); |
407 | } | 409 | } |
408 | 410 | ||
409 | 411 | ||
@@ -435,6 +437,52 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
435 | return RX_CONTINUE; | 437 | return RX_CONTINUE; |
436 | } | 438 | } |
437 | 439 | ||
440 | |||
441 | static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) | ||
442 | { | ||
443 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
444 | |||
445 | if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) | ||
446 | return 0; | ||
447 | |||
448 | return ieee80211_is_robust_mgmt_frame(hdr); | ||
449 | } | ||
450 | |||
451 | |||
452 | static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) | ||
453 | { | ||
454 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
455 | |||
456 | if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) | ||
457 | return 0; | ||
458 | |||
459 | return ieee80211_is_robust_mgmt_frame(hdr); | ||
460 | } | ||
461 | |||
462 | |||
463 | /* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */ | ||
464 | static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | ||
465 | { | ||
466 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; | ||
467 | struct ieee80211_mmie *mmie; | ||
468 | |||
469 | if (skb->len < 24 + sizeof(*mmie) || | ||
470 | !is_multicast_ether_addr(hdr->da)) | ||
471 | return -1; | ||
472 | |||
473 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) | ||
474 | return -1; /* not a robust management frame */ | ||
475 | |||
476 | mmie = (struct ieee80211_mmie *) | ||
477 | (skb->data + skb->len - sizeof(*mmie)); | ||
478 | if (mmie->element_id != WLAN_EID_MMIE || | ||
479 | mmie->length != sizeof(*mmie) - 2) | ||
480 | return -1; | ||
481 | |||
482 | return le16_to_cpu(mmie->key_id); | ||
483 | } | ||
484 | |||
485 | |||
438 | static ieee80211_rx_result | 486 | static ieee80211_rx_result |
439 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | 487 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) |
440 | { | 488 | { |
@@ -550,21 +598,23 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
550 | int hdrlen; | 598 | int hdrlen; |
551 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 599 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
552 | struct ieee80211_key *stakey = NULL; | 600 | struct ieee80211_key *stakey = NULL; |
601 | int mmie_keyidx = -1; | ||
553 | 602 | ||
554 | /* | 603 | /* |
555 | * Key selection 101 | 604 | * Key selection 101 |
556 | * | 605 | * |
557 | * There are three types of keys: | 606 | * There are four types of keys: |
558 | * - GTK (group keys) | 607 | * - GTK (group keys) |
608 | * - IGTK (group keys for management frames) | ||
559 | * - PTK (pairwise keys) | 609 | * - PTK (pairwise keys) |
560 | * - STK (station-to-station pairwise keys) | 610 | * - STK (station-to-station pairwise keys) |
561 | * | 611 | * |
562 | * When selecting a key, we have to distinguish between multicast | 612 | * When selecting a key, we have to distinguish between multicast |
563 | * (including broadcast) and unicast frames, the latter can only | 613 | * (including broadcast) and unicast frames, the latter can only |
564 | * use PTKs and STKs while the former always use GTKs. Unless, of | 614 | * use PTKs and STKs while the former always use GTKs and IGTKs. |
565 | * course, actual WEP keys ("pre-RSNA") are used, then unicast | 615 | * Unless, of course, actual WEP keys ("pre-RSNA") are used, then |
566 | * frames can also use key indizes like GTKs. Hence, if we don't | 616 | * unicast frames can also use key indices like GTKs. Hence, if we |
567 | * have a PTK/STK we check the key index for a WEP key. | 617 | * don't have a PTK/STK we check the key index for a WEP key. |
568 | * | 618 | * |
569 | * Note that in a regular BSS, multicast frames are sent by the | 619 | * Note that in a regular BSS, multicast frames are sent by the |
570 | * AP only, associated stations unicast the frame to the AP first | 620 | * AP only, associated stations unicast the frame to the AP first |
@@ -577,8 +627,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
577 | * possible. | 627 | * possible. |
578 | */ | 628 | */ |
579 | 629 | ||
580 | if (!ieee80211_has_protected(hdr->frame_control)) | 630 | if (!ieee80211_has_protected(hdr->frame_control)) { |
581 | return RX_CONTINUE; | 631 | if (!ieee80211_is_mgmt(hdr->frame_control) || |
632 | rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP)) | ||
633 | return RX_CONTINUE; | ||
634 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
635 | if (mmie_keyidx < 0) | ||
636 | return RX_CONTINUE; | ||
637 | } | ||
582 | 638 | ||
583 | /* | 639 | /* |
584 | * No point in finding a key and decrypting if the frame is neither | 640 | * No point in finding a key and decrypting if the frame is neither |
@@ -592,6 +648,16 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
592 | 648 | ||
593 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 649 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
594 | rx->key = stakey; | 650 | rx->key = stakey; |
651 | } else if (mmie_keyidx >= 0) { | ||
652 | /* Broadcast/multicast robust management frame / BIP */ | ||
653 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | ||
654 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | ||
655 | return RX_CONTINUE; | ||
656 | |||
657 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | ||
658 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
659 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | ||
660 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | ||
595 | } else { | 661 | } else { |
596 | /* | 662 | /* |
597 | * The device doesn't give us the IV so we won't be | 663 | * The device doesn't give us the IV so we won't be |
@@ -654,6 +720,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
654 | case ALG_CCMP: | 720 | case ALG_CCMP: |
655 | result = ieee80211_crypto_ccmp_decrypt(rx); | 721 | result = ieee80211_crypto_ccmp_decrypt(rx); |
656 | break; | 722 | break; |
723 | case ALG_AES_CMAC: | ||
724 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | ||
725 | break; | ||
657 | } | 726 | } |
658 | 727 | ||
659 | /* either the frame has been decrypted or will be dropped */ | 728 | /* either the frame has been decrypted or will be dropped */ |
@@ -662,6 +731,39 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
662 | return result; | 731 | return result; |
663 | } | 732 | } |
664 | 733 | ||
734 | static ieee80211_rx_result debug_noinline | ||
735 | ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx) | ||
736 | { | ||
737 | struct ieee80211_local *local; | ||
738 | struct ieee80211_hdr *hdr; | ||
739 | struct sk_buff *skb; | ||
740 | |||
741 | local = rx->local; | ||
742 | skb = rx->skb; | ||
743 | hdr = (struct ieee80211_hdr *) skb->data; | ||
744 | |||
745 | if (!local->pspolling) | ||
746 | return RX_CONTINUE; | ||
747 | |||
748 | if (!ieee80211_has_fromds(hdr->frame_control)) | ||
749 | /* this is not from AP */ | ||
750 | return RX_CONTINUE; | ||
751 | |||
752 | if (!ieee80211_is_data(hdr->frame_control)) | ||
753 | return RX_CONTINUE; | ||
754 | |||
755 | if (!ieee80211_has_moredata(hdr->frame_control)) { | ||
756 | /* AP has no more frames buffered for us */ | ||
757 | local->pspolling = false; | ||
758 | return RX_CONTINUE; | ||
759 | } | ||
760 | |||
761 | /* more data bit is set, let's request a new frame from the AP */ | ||
762 | ieee80211_send_pspoll(local, rx->sdata); | ||
763 | |||
764 | return RX_CONTINUE; | ||
765 | } | ||
766 | |||
665 | static void ap_sta_ps_start(struct sta_info *sta) | 767 | static void ap_sta_ps_start(struct sta_info *sta) |
666 | { | 768 | { |
667 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 769 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -1101,6 +1203,15 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1101 | /* Drop unencrypted frames if key is set. */ | 1203 | /* Drop unencrypted frames if key is set. */ |
1102 | if (unlikely(!ieee80211_has_protected(fc) && | 1204 | if (unlikely(!ieee80211_has_protected(fc) && |
1103 | !ieee80211_is_nullfunc(fc) && | 1205 | !ieee80211_is_nullfunc(fc) && |
1206 | (!ieee80211_is_mgmt(fc) || | ||
1207 | (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1208 | rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) && | ||
1209 | (rx->key || rx->sdata->drop_unencrypted))) | ||
1210 | return -EACCES; | ||
1211 | /* BIP does not use Protected field, so need to check MMIE */ | ||
1212 | if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) && | ||
1213 | ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | ||
1214 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | ||
1104 | (rx->key || rx->sdata->drop_unencrypted))) | 1215 | (rx->key || rx->sdata->drop_unencrypted))) |
1105 | return -EACCES; | 1216 | return -EACCES; |
1106 | 1217 | ||
@@ -1138,12 +1249,12 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1138 | 1249 | ||
1139 | switch (hdr->frame_control & | 1250 | switch (hdr->frame_control & |
1140 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { | 1251 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { |
1141 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): | 1252 | case cpu_to_le16(IEEE80211_FCTL_TODS): |
1142 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && | 1253 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && |
1143 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) | 1254 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) |
1144 | return -1; | 1255 | return -1; |
1145 | break; | 1256 | break; |
1146 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): | 1257 | case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): |
1147 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && | 1258 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1148 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) | 1259 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1149 | return -1; | 1260 | return -1; |
@@ -1157,13 +1268,13 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1157 | } | 1268 | } |
1158 | } | 1269 | } |
1159 | break; | 1270 | break; |
1160 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): | 1271 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1161 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | 1272 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
1162 | (is_multicast_ether_addr(dst) && | 1273 | (is_multicast_ether_addr(dst) && |
1163 | !compare_ether_addr(src, dev->dev_addr))) | 1274 | !compare_ether_addr(src, dev->dev_addr))) |
1164 | return -1; | 1275 | return -1; |
1165 | break; | 1276 | break; |
1166 | case __constant_cpu_to_le16(0): | 1277 | case cpu_to_le16(0): |
1167 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1278 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1168 | return -1; | 1279 | return -1; |
1169 | break; | 1280 | break; |
@@ -1267,10 +1378,37 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1267 | } | 1378 | } |
1268 | 1379 | ||
1269 | if (skb) { | 1380 | if (skb) { |
1270 | /* deliver to local stack */ | 1381 | int align __maybe_unused; |
1271 | skb->protocol = eth_type_trans(skb, dev); | 1382 | |
1272 | memset(skb->cb, 0, sizeof(skb->cb)); | 1383 | #if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
1273 | netif_rx(skb); | 1384 | /* |
1385 | * 'align' will only take the values 0 or 2 here | ||
1386 | * since all frames are required to be aligned | ||
1387 | * to 2-byte boundaries when being passed to | ||
1388 | * mac80211. That also explains the __skb_push() | ||
1389 | * below. | ||
1390 | */ | ||
1391 | align = (unsigned long)skb->data & 4; | ||
1392 | if (align) { | ||
1393 | if (WARN_ON(skb_headroom(skb) < 3)) { | ||
1394 | dev_kfree_skb(skb); | ||
1395 | skb = NULL; | ||
1396 | } else { | ||
1397 | u8 *data = skb->data; | ||
1398 | size_t len = skb->len; | ||
1399 | u8 *new = __skb_push(skb, align); | ||
1400 | memmove(new, data, len); | ||
1401 | __skb_trim(skb, len); | ||
1402 | } | ||
1403 | } | ||
1404 | #endif | ||
1405 | |||
1406 | if (skb) { | ||
1407 | /* deliver to local stack */ | ||
1408 | skb->protocol = eth_type_trans(skb, dev); | ||
1409 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
1410 | netif_rx(skb); | ||
1411 | } | ||
1274 | } | 1412 | } |
1275 | 1413 | ||
1276 | if (xmit_skb) { | 1414 | if (xmit_skb) { |
@@ -1339,14 +1477,20 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1339 | if (remaining <= subframe_len + padding) | 1477 | if (remaining <= subframe_len + padding) |
1340 | frame = skb; | 1478 | frame = skb; |
1341 | else { | 1479 | else { |
1342 | frame = dev_alloc_skb(local->hw.extra_tx_headroom + | 1480 | /* |
1343 | subframe_len); | 1481 | * Allocate and reserve two bytes more for payload |
1482 | * alignment since sizeof(struct ethhdr) is 14. | ||
1483 | */ | ||
1484 | frame = dev_alloc_skb( | ||
1485 | ALIGN(local->hw.extra_tx_headroom, 4) + | ||
1486 | subframe_len + 2); | ||
1344 | 1487 | ||
1345 | if (frame == NULL) | 1488 | if (frame == NULL) |
1346 | return RX_DROP_UNUSABLE; | 1489 | return RX_DROP_UNUSABLE; |
1347 | 1490 | ||
1348 | skb_reserve(frame, local->hw.extra_tx_headroom + | 1491 | skb_reserve(frame, |
1349 | sizeof(struct ethhdr)); | 1492 | ALIGN(local->hw.extra_tx_headroom, 4) + |
1493 | sizeof(struct ethhdr) + 2); | ||
1350 | memcpy(skb_put(frame, ntohs(len)), skb->data, | 1494 | memcpy(skb_put(frame, ntohs(len)), skb->data, |
1351 | ntohs(len)); | 1495 | ntohs(len)); |
1352 | 1496 | ||
@@ -1529,11 +1673,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1529 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; | 1673 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
1530 | 1674 | ||
1531 | /* reset session timer */ | 1675 | /* reset session timer */ |
1532 | if (tid_agg_rx->timeout) { | 1676 | if (tid_agg_rx->timeout) |
1533 | unsigned long expires = | 1677 | mod_timer(&tid_agg_rx->session_timer, |
1534 | jiffies + (tid_agg_rx->timeout / 1000) * HZ; | 1678 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); |
1535 | mod_timer(&tid_agg_rx->session_timer, expires); | ||
1536 | } | ||
1537 | 1679 | ||
1538 | /* manage reordering buffer according to requested */ | 1680 | /* manage reordering buffer according to requested */ |
1539 | /* sequence number */ | 1681 | /* sequence number */ |
@@ -1547,12 +1689,65 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1547 | return RX_CONTINUE; | 1689 | return RX_CONTINUE; |
1548 | } | 1690 | } |
1549 | 1691 | ||
1692 | static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | ||
1693 | struct ieee80211_mgmt *mgmt, | ||
1694 | size_t len) | ||
1695 | { | ||
1696 | struct ieee80211_local *local = sdata->local; | ||
1697 | struct sk_buff *skb; | ||
1698 | struct ieee80211_mgmt *resp; | ||
1699 | |||
1700 | if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) { | ||
1701 | /* Not to own unicast address */ | ||
1702 | return; | ||
1703 | } | ||
1704 | |||
1705 | if (compare_ether_addr(mgmt->sa, sdata->u.sta.bssid) != 0 || | ||
1706 | compare_ether_addr(mgmt->bssid, sdata->u.sta.bssid) != 0) { | ||
1707 | /* Not from the current AP. */ | ||
1708 | return; | ||
1709 | } | ||
1710 | |||
1711 | if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATE) { | ||
1712 | /* Association in progress; ignore SA Query */ | ||
1713 | return; | ||
1714 | } | ||
1715 | |||
1716 | if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) { | ||
1717 | /* Too short SA Query request frame */ | ||
1718 | return; | ||
1719 | } | ||
1720 | |||
1721 | skb = dev_alloc_skb(sizeof(*resp) + local->hw.extra_tx_headroom); | ||
1722 | if (skb == NULL) | ||
1723 | return; | ||
1724 | |||
1725 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1726 | resp = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
1727 | memset(resp, 0, 24); | ||
1728 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | ||
1729 | memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
1730 | memcpy(resp->bssid, sdata->u.sta.bssid, ETH_ALEN); | ||
1731 | resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
1732 | IEEE80211_STYPE_ACTION); | ||
1733 | skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query)); | ||
1734 | resp->u.action.category = WLAN_CATEGORY_SA_QUERY; | ||
1735 | resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE; | ||
1736 | memcpy(resp->u.action.u.sa_query.trans_id, | ||
1737 | mgmt->u.action.u.sa_query.trans_id, | ||
1738 | WLAN_SA_QUERY_TR_ID_LEN); | ||
1739 | |||
1740 | ieee80211_tx_skb(sdata, skb, 1); | ||
1741 | } | ||
1742 | |||
1550 | static ieee80211_rx_result debug_noinline | 1743 | static ieee80211_rx_result debug_noinline |
1551 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1744 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1552 | { | 1745 | { |
1553 | struct ieee80211_local *local = rx->local; | 1746 | struct ieee80211_local *local = rx->local; |
1554 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1747 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1748 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
1555 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1749 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1750 | struct ieee80211_bss *bss; | ||
1556 | int len = rx->skb->len; | 1751 | int len = rx->skb->len; |
1557 | 1752 | ||
1558 | if (!ieee80211_is_action(mgmt->frame_control)) | 1753 | if (!ieee80211_is_action(mgmt->frame_control)) |
@@ -1564,12 +1759,26 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1564 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1759 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1565 | return RX_DROP_MONITOR; | 1760 | return RX_DROP_MONITOR; |
1566 | 1761 | ||
1762 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | ||
1763 | return RX_DROP_MONITOR; | ||
1764 | |||
1567 | /* all categories we currently handle have action_code */ | 1765 | /* all categories we currently handle have action_code */ |
1568 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 1766 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) |
1569 | return RX_DROP_MONITOR; | 1767 | return RX_DROP_MONITOR; |
1570 | 1768 | ||
1571 | switch (mgmt->u.action.category) { | 1769 | switch (mgmt->u.action.category) { |
1572 | case WLAN_CATEGORY_BACK: | 1770 | case WLAN_CATEGORY_BACK: |
1771 | /* | ||
1772 | * The aggregation code is not prepared to handle | ||
1773 | * anything but STA/AP due to the BSSID handling; | ||
1774 | * IBSS could work in the code but isn't supported | ||
1775 | * by drivers or the standard. | ||
1776 | */ | ||
1777 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
1778 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
1779 | sdata->vif.type != NL80211_IFTYPE_AP) | ||
1780 | return RX_DROP_MONITOR; | ||
1781 | |||
1573 | switch (mgmt->u.action.u.addba_req.action_code) { | 1782 | switch (mgmt->u.action.u.addba_req.action_code) { |
1574 | case WLAN_ACTION_ADDBA_REQ: | 1783 | case WLAN_ACTION_ADDBA_REQ: |
1575 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1784 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
@@ -1601,6 +1810,42 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1601 | return RX_DROP_MONITOR; | 1810 | return RX_DROP_MONITOR; |
1602 | ieee80211_process_measurement_req(sdata, mgmt, len); | 1811 | ieee80211_process_measurement_req(sdata, mgmt, len); |
1603 | break; | 1812 | break; |
1813 | case WLAN_ACTION_SPCT_CHL_SWITCH: | ||
1814 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1815 | sizeof(mgmt->u.action.u.chan_switch))) | ||
1816 | return RX_DROP_MONITOR; | ||
1817 | |||
1818 | if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0) | ||
1819 | return RX_DROP_MONITOR; | ||
1820 | |||
1821 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, | ||
1822 | local->hw.conf.channel->center_freq, | ||
1823 | ifsta->ssid, ifsta->ssid_len); | ||
1824 | if (!bss) | ||
1825 | return RX_DROP_MONITOR; | ||
1826 | |||
1827 | ieee80211_process_chanswitch(sdata, | ||
1828 | &mgmt->u.action.u.chan_switch.sw_elem, bss); | ||
1829 | ieee80211_rx_bss_put(local, bss); | ||
1830 | break; | ||
1831 | } | ||
1832 | break; | ||
1833 | case WLAN_CATEGORY_SA_QUERY: | ||
1834 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1835 | sizeof(mgmt->u.action.u.sa_query))) | ||
1836 | return RX_DROP_MONITOR; | ||
1837 | switch (mgmt->u.action.u.sa_query.action) { | ||
1838 | case WLAN_ACTION_SA_QUERY_REQUEST: | ||
1839 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1840 | return RX_DROP_MONITOR; | ||
1841 | ieee80211_process_sa_query_req(sdata, mgmt, len); | ||
1842 | break; | ||
1843 | case WLAN_ACTION_SA_QUERY_RESPONSE: | ||
1844 | /* | ||
1845 | * SA Query response is currently only used in AP mode | ||
1846 | * and it is processed in user space. | ||
1847 | */ | ||
1848 | return RX_CONTINUE; | ||
1604 | } | 1849 | } |
1605 | break; | 1850 | break; |
1606 | default: | 1851 | default: |
@@ -1616,10 +1861,14 @@ static ieee80211_rx_result debug_noinline | |||
1616 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 1861 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1617 | { | 1862 | { |
1618 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1863 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1864 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1619 | 1865 | ||
1620 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1866 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1621 | return RX_DROP_MONITOR; | 1867 | return RX_DROP_MONITOR; |
1622 | 1868 | ||
1869 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | ||
1870 | return RX_DROP_MONITOR; | ||
1871 | |||
1623 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1872 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1624 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); | 1873 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); |
1625 | 1874 | ||
@@ -1780,6 +2029,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
1780 | CALL_RXH(ieee80211_rx_h_passive_scan) | 2029 | CALL_RXH(ieee80211_rx_h_passive_scan) |
1781 | CALL_RXH(ieee80211_rx_h_check) | 2030 | CALL_RXH(ieee80211_rx_h_check) |
1782 | CALL_RXH(ieee80211_rx_h_decrypt) | 2031 | CALL_RXH(ieee80211_rx_h_decrypt) |
2032 | CALL_RXH(ieee80211_rx_h_check_more_data) | ||
1783 | CALL_RXH(ieee80211_rx_h_sta_process) | 2033 | CALL_RXH(ieee80211_rx_h_sta_process) |
1784 | CALL_RXH(ieee80211_rx_h_defragment) | 2034 | CALL_RXH(ieee80211_rx_h_defragment) |
1785 | CALL_RXH(ieee80211_rx_h_ps_poll) | 2035 | CALL_RXH(ieee80211_rx_h_ps_poll) |
@@ -1823,9 +2073,10 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
1823 | /* main receive path */ | 2073 | /* main receive path */ |
1824 | 2074 | ||
1825 | static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | 2075 | static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, |
1826 | u8 *bssid, struct ieee80211_rx_data *rx, | 2076 | struct ieee80211_rx_data *rx, |
1827 | struct ieee80211_hdr *hdr) | 2077 | struct ieee80211_hdr *hdr) |
1828 | { | 2078 | { |
2079 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, sdata->vif.type); | ||
1829 | int multicast = is_multicast_ether_addr(hdr->addr1); | 2080 | int multicast = is_multicast_ether_addr(hdr->addr1); |
1830 | 2081 | ||
1831 | switch (sdata->vif.type) { | 2082 | switch (sdata->vif.type) { |
@@ -1928,7 +2179,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1928 | int prepares; | 2179 | int prepares; |
1929 | struct ieee80211_sub_if_data *prev = NULL; | 2180 | struct ieee80211_sub_if_data *prev = NULL; |
1930 | struct sk_buff *skb_new; | 2181 | struct sk_buff *skb_new; |
1931 | u8 *bssid; | ||
1932 | 2182 | ||
1933 | hdr = (struct ieee80211_hdr *)skb->data; | 2183 | hdr = (struct ieee80211_hdr *)skb->data; |
1934 | memset(&rx, 0, sizeof(rx)); | 2184 | memset(&rx, 0, sizeof(rx)); |
@@ -1956,7 +2206,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1956 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2206 | rx.flags |= IEEE80211_RX_IN_SCAN; |
1957 | 2207 | ||
1958 | ieee80211_parse_qos(&rx); | 2208 | ieee80211_parse_qos(&rx); |
1959 | ieee80211_verify_ip_alignment(&rx); | 2209 | ieee80211_verify_alignment(&rx); |
1960 | 2210 | ||
1961 | skb = rx.skb; | 2211 | skb = rx.skb; |
1962 | 2212 | ||
@@ -1967,9 +2217,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1967 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) | 2217 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) |
1968 | continue; | 2218 | continue; |
1969 | 2219 | ||
1970 | bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); | ||
1971 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2220 | rx.flags |= IEEE80211_RX_RA_MATCH; |
1972 | prepares = prepare_for_handlers(sdata, bssid, &rx, hdr); | 2221 | prepares = prepare_for_handlers(sdata, &rx, hdr); |
1973 | 2222 | ||
1974 | if (!prepares) | 2223 | if (!prepares) |
1975 | continue; | 2224 | continue; |
@@ -2174,11 +2423,9 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2174 | /* new un-ordered ampdu frame - process it */ | 2423 | /* new un-ordered ampdu frame - process it */ |
2175 | 2424 | ||
2176 | /* reset session timer */ | 2425 | /* reset session timer */ |
2177 | if (tid_agg_rx->timeout) { | 2426 | if (tid_agg_rx->timeout) |
2178 | unsigned long expires = | 2427 | mod_timer(&tid_agg_rx->session_timer, |
2179 | jiffies + (tid_agg_rx->timeout / 1000) * HZ; | 2428 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); |
2180 | mod_timer(&tid_agg_rx->session_timer, expires); | ||
2181 | } | ||
2182 | 2429 | ||
2183 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 2430 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
2184 | sc = le16_to_cpu(hdr->seq_ctrl); | 2431 | sc = le16_to_cpu(hdr->seq_ctrl); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f5c7c3371929..f883ab9f1e6e 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -12,14 +12,11 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | /* TODO: | 15 | /* TODO: figure out how to avoid that the "current BSS" expires */ |
16 | * order BSS list by RSSI(?) ("quality of AP") | ||
17 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, | ||
18 | * SSID) | ||
19 | */ | ||
20 | 16 | ||
21 | #include <linux/wireless.h> | 17 | #include <linux/wireless.h> |
22 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
19 | #include <linux/rtnetlink.h> | ||
23 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
24 | #include <net/iw_handler.h> | 21 | #include <net/iw_handler.h> |
25 | 22 | ||
@@ -30,192 +27,29 @@ | |||
30 | #define IEEE80211_CHANNEL_TIME (HZ / 33) | 27 | #define IEEE80211_CHANNEL_TIME (HZ / 33) |
31 | #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) | 28 | #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) |
32 | 29 | ||
33 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local) | ||
34 | { | ||
35 | spin_lock_init(&local->bss_lock); | ||
36 | INIT_LIST_HEAD(&local->bss_list); | ||
37 | } | ||
38 | |||
39 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) | ||
40 | { | ||
41 | struct ieee80211_bss *bss, *tmp; | ||
42 | |||
43 | list_for_each_entry_safe(bss, tmp, &local->bss_list, list) | ||
44 | ieee80211_rx_bss_put(local, bss); | ||
45 | } | ||
46 | |||
47 | struct ieee80211_bss * | 30 | struct ieee80211_bss * |
48 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | 31 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, |
49 | u8 *ssid, u8 ssid_len) | 32 | u8 *ssid, u8 ssid_len) |
50 | { | 33 | { |
51 | struct ieee80211_bss *bss; | 34 | return (void *)cfg80211_get_bss(local->hw.wiphy, |
52 | 35 | ieee80211_get_channel(local->hw.wiphy, | |
53 | spin_lock_bh(&local->bss_lock); | 36 | freq), |
54 | bss = local->bss_hash[STA_HASH(bssid)]; | 37 | bssid, ssid, ssid_len, |
55 | while (bss) { | 38 | 0, 0); |
56 | if (!bss_mesh_cfg(bss) && | ||
57 | !memcmp(bss->bssid, bssid, ETH_ALEN) && | ||
58 | bss->freq == freq && | ||
59 | bss->ssid_len == ssid_len && | ||
60 | (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { | ||
61 | atomic_inc(&bss->users); | ||
62 | break; | ||
63 | } | ||
64 | bss = bss->hnext; | ||
65 | } | ||
66 | spin_unlock_bh(&local->bss_lock); | ||
67 | return bss; | ||
68 | } | ||
69 | |||
70 | /* Caller must hold local->bss_lock */ | ||
71 | static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, | ||
72 | struct ieee80211_bss *bss) | ||
73 | { | ||
74 | u8 hash_idx; | ||
75 | |||
76 | if (bss_mesh_cfg(bss)) | ||
77 | hash_idx = mesh_id_hash(bss_mesh_id(bss), | ||
78 | bss_mesh_id_len(bss)); | ||
79 | else | ||
80 | hash_idx = STA_HASH(bss->bssid); | ||
81 | |||
82 | bss->hnext = local->bss_hash[hash_idx]; | ||
83 | local->bss_hash[hash_idx] = bss; | ||
84 | } | ||
85 | |||
86 | /* Caller must hold local->bss_lock */ | ||
87 | static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, | ||
88 | struct ieee80211_bss *bss) | ||
89 | { | ||
90 | struct ieee80211_bss *b, *prev = NULL; | ||
91 | b = local->bss_hash[STA_HASH(bss->bssid)]; | ||
92 | while (b) { | ||
93 | if (b == bss) { | ||
94 | if (!prev) | ||
95 | local->bss_hash[STA_HASH(bss->bssid)] = | ||
96 | bss->hnext; | ||
97 | else | ||
98 | prev->hnext = bss->hnext; | ||
99 | break; | ||
100 | } | ||
101 | prev = b; | ||
102 | b = b->hnext; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | struct ieee80211_bss * | ||
107 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | ||
108 | u8 *ssid, u8 ssid_len) | ||
109 | { | ||
110 | struct ieee80211_bss *bss; | ||
111 | |||
112 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
113 | if (!bss) | ||
114 | return NULL; | ||
115 | atomic_set(&bss->users, 2); | ||
116 | memcpy(bss->bssid, bssid, ETH_ALEN); | ||
117 | bss->freq = freq; | ||
118 | if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
119 | memcpy(bss->ssid, ssid, ssid_len); | ||
120 | bss->ssid_len = ssid_len; | ||
121 | } | ||
122 | |||
123 | spin_lock_bh(&local->bss_lock); | ||
124 | /* TODO: order by RSSI? */ | ||
125 | list_add_tail(&bss->list, &local->bss_list); | ||
126 | __ieee80211_rx_bss_hash_add(local, bss); | ||
127 | spin_unlock_bh(&local->bss_lock); | ||
128 | return bss; | ||
129 | } | ||
130 | |||
131 | #ifdef CONFIG_MAC80211_MESH | ||
132 | static struct ieee80211_bss * | ||
133 | ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, | ||
134 | u8 *mesh_cfg, int freq) | ||
135 | { | ||
136 | struct ieee80211_bss *bss; | ||
137 | |||
138 | spin_lock_bh(&local->bss_lock); | ||
139 | bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; | ||
140 | while (bss) { | ||
141 | if (bss_mesh_cfg(bss) && | ||
142 | !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && | ||
143 | bss->freq == freq && | ||
144 | mesh_id_len == bss->mesh_id_len && | ||
145 | (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, | ||
146 | mesh_id_len))) { | ||
147 | atomic_inc(&bss->users); | ||
148 | break; | ||
149 | } | ||
150 | bss = bss->hnext; | ||
151 | } | ||
152 | spin_unlock_bh(&local->bss_lock); | ||
153 | return bss; | ||
154 | } | 39 | } |
155 | 40 | ||
156 | static struct ieee80211_bss * | 41 | static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) |
157 | ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, | ||
158 | u8 *mesh_cfg, int mesh_config_len, int freq) | ||
159 | { | 42 | { |
160 | struct ieee80211_bss *bss; | 43 | struct ieee80211_bss *bss = (void *)cbss; |
161 | |||
162 | if (mesh_config_len != IEEE80211_MESH_CONFIG_LEN) | ||
163 | return NULL; | ||
164 | |||
165 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
166 | if (!bss) | ||
167 | return NULL; | ||
168 | |||
169 | bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); | ||
170 | if (!bss->mesh_cfg) { | ||
171 | kfree(bss); | ||
172 | return NULL; | ||
173 | } | ||
174 | |||
175 | if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { | ||
176 | bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); | ||
177 | if (!bss->mesh_id) { | ||
178 | kfree(bss->mesh_cfg); | ||
179 | kfree(bss); | ||
180 | return NULL; | ||
181 | } | ||
182 | memcpy(bss->mesh_id, mesh_id, mesh_id_len); | ||
183 | } | ||
184 | 44 | ||
185 | atomic_set(&bss->users, 2); | ||
186 | memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); | ||
187 | bss->mesh_id_len = mesh_id_len; | ||
188 | bss->freq = freq; | ||
189 | spin_lock_bh(&local->bss_lock); | ||
190 | /* TODO: order by RSSI? */ | ||
191 | list_add_tail(&bss->list, &local->bss_list); | ||
192 | __ieee80211_rx_bss_hash_add(local, bss); | ||
193 | spin_unlock_bh(&local->bss_lock); | ||
194 | return bss; | ||
195 | } | ||
196 | #endif | ||
197 | |||
198 | static void ieee80211_rx_bss_free(struct ieee80211_bss *bss) | ||
199 | { | ||
200 | kfree(bss->ies); | ||
201 | kfree(bss_mesh_id(bss)); | 45 | kfree(bss_mesh_id(bss)); |
202 | kfree(bss_mesh_cfg(bss)); | 46 | kfree(bss_mesh_cfg(bss)); |
203 | kfree(bss); | ||
204 | } | 47 | } |
205 | 48 | ||
206 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 49 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
207 | struct ieee80211_bss *bss) | 50 | struct ieee80211_bss *bss) |
208 | { | 51 | { |
209 | local_bh_disable(); | 52 | cfg80211_put_bss((struct cfg80211_bss *)bss); |
210 | if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) { | ||
211 | local_bh_enable(); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | __ieee80211_rx_bss_hash_del(local, bss); | ||
216 | list_del(&bss->list); | ||
217 | spin_unlock_bh(&local->bss_lock); | ||
218 | ieee80211_rx_bss_free(bss); | ||
219 | } | 53 | } |
220 | 54 | ||
221 | struct ieee80211_bss * | 55 | struct ieee80211_bss * |
@@ -224,49 +58,37 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
224 | struct ieee80211_mgmt *mgmt, | 58 | struct ieee80211_mgmt *mgmt, |
225 | size_t len, | 59 | size_t len, |
226 | struct ieee802_11_elems *elems, | 60 | struct ieee802_11_elems *elems, |
227 | int freq, bool beacon) | 61 | struct ieee80211_channel *channel, |
62 | bool beacon) | ||
228 | { | 63 | { |
229 | struct ieee80211_bss *bss; | 64 | struct ieee80211_bss *bss; |
230 | int clen; | 65 | int clen; |
231 | 66 | enum cfg80211_signal_type sigtype = CFG80211_SIGNAL_TYPE_NONE; | |
232 | #ifdef CONFIG_MAC80211_MESH | 67 | s32 signal = 0; |
233 | if (elems->mesh_config) | 68 | |
234 | bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, | 69 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { |
235 | elems->mesh_id_len, elems->mesh_config, freq); | 70 | sigtype = CFG80211_SIGNAL_TYPE_MBM; |
236 | else | 71 | signal = rx_status->signal * 100; |
237 | #endif | 72 | } else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) { |
238 | bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, | 73 | sigtype = CFG80211_SIGNAL_TYPE_UNSPEC; |
239 | elems->ssid, elems->ssid_len); | 74 | signal = (rx_status->signal * 100) / local->hw.max_signal; |
240 | if (!bss) { | ||
241 | #ifdef CONFIG_MAC80211_MESH | ||
242 | if (elems->mesh_config) | ||
243 | bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, | ||
244 | elems->mesh_id_len, elems->mesh_config, | ||
245 | elems->mesh_config_len, freq); | ||
246 | else | ||
247 | #endif | ||
248 | bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq, | ||
249 | elems->ssid, elems->ssid_len); | ||
250 | if (!bss) | ||
251 | return NULL; | ||
252 | } else { | ||
253 | #if 0 | ||
254 | /* TODO: order by RSSI? */ | ||
255 | spin_lock_bh(&local->bss_lock); | ||
256 | list_move_tail(&bss->list, &local->bss_list); | ||
257 | spin_unlock_bh(&local->bss_lock); | ||
258 | #endif | ||
259 | } | 75 | } |
260 | 76 | ||
77 | bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel, | ||
78 | mgmt, len, signal, sigtype, | ||
79 | GFP_ATOMIC); | ||
80 | |||
81 | if (!bss) | ||
82 | return NULL; | ||
83 | |||
84 | bss->cbss.free_priv = ieee80211_rx_bss_free; | ||
85 | |||
261 | /* save the ERP value so that it is available at association time */ | 86 | /* save the ERP value so that it is available at association time */ |
262 | if (elems->erp_info && elems->erp_info_len >= 1) { | 87 | if (elems->erp_info && elems->erp_info_len >= 1) { |
263 | bss->erp_value = elems->erp_info[0]; | 88 | bss->erp_value = elems->erp_info[0]; |
264 | bss->has_erp_value = 1; | 89 | bss->has_erp_value = 1; |
265 | } | 90 | } |
266 | 91 | ||
267 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | ||
268 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | ||
269 | |||
270 | if (elems->tim) { | 92 | if (elems->tim) { |
271 | struct ieee80211_tim_ie *tim_ie = | 93 | struct ieee80211_tim_ie *tim_ie = |
272 | (struct ieee80211_tim_ie *)elems->tim; | 94 | (struct ieee80211_tim_ie *)elems->tim; |
@@ -295,37 +117,27 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
295 | bss->supp_rates_len += clen; | 117 | bss->supp_rates_len += clen; |
296 | } | 118 | } |
297 | 119 | ||
298 | bss->band = rx_status->band; | ||
299 | |||
300 | bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); | ||
301 | bss->last_update = jiffies; | ||
302 | bss->signal = rx_status->signal; | ||
303 | bss->noise = rx_status->noise; | ||
304 | bss->qual = rx_status->qual; | ||
305 | bss->wmm_used = elems->wmm_param || elems->wmm_info; | 120 | bss->wmm_used = elems->wmm_param || elems->wmm_info; |
306 | 121 | ||
307 | if (!beacon) | 122 | if (!beacon) |
308 | bss->last_probe_resp = jiffies; | 123 | bss->last_probe_resp = jiffies; |
309 | 124 | ||
310 | /* | ||
311 | * For probe responses, or if we don't have any information yet, | ||
312 | * use the IEs from the beacon. | ||
313 | */ | ||
314 | if (!bss->ies || !beacon) { | ||
315 | if (bss->ies == NULL || bss->ies_len < elems->total_len) { | ||
316 | kfree(bss->ies); | ||
317 | bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); | ||
318 | } | ||
319 | if (bss->ies) { | ||
320 | memcpy(bss->ies, elems->ie_start, elems->total_len); | ||
321 | bss->ies_len = elems->total_len; | ||
322 | } else | ||
323 | bss->ies_len = 0; | ||
324 | } | ||
325 | |||
326 | return bss; | 125 | return bss; |
327 | } | 126 | } |
328 | 127 | ||
128 | void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid, | ||
129 | int freq, u8 *ssid, u8 ssid_len) | ||
130 | { | ||
131 | struct ieee80211_bss *bss; | ||
132 | struct ieee80211_local *local = sdata->local; | ||
133 | |||
134 | bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len); | ||
135 | if (bss) { | ||
136 | cfg80211_unlink_bss(local->hw.wiphy, (void *)bss); | ||
137 | ieee80211_rx_bss_put(local, bss); | ||
138 | } | ||
139 | } | ||
140 | |||
329 | ieee80211_rx_result | 141 | ieee80211_rx_result |
330 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 142 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
331 | struct ieee80211_rx_status *rx_status) | 143 | struct ieee80211_rx_status *rx_status) |
@@ -387,7 +199,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
387 | 199 | ||
388 | bss = ieee80211_bss_info_update(sdata->local, rx_status, | 200 | bss = ieee80211_bss_info_update(sdata->local, rx_status, |
389 | mgmt, skb->len, &elems, | 201 | mgmt, skb->len, &elems, |
390 | freq, beacon); | 202 | channel, beacon); |
391 | if (bss) | 203 | if (bss) |
392 | ieee80211_rx_bss_put(sdata->local, bss); | 204 | ieee80211_rx_bss_put(sdata->local, bss); |
393 | 205 | ||
@@ -395,7 +207,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
395 | return RX_QUEUED; | 207 | return RX_QUEUED; |
396 | } | 208 | } |
397 | 209 | ||
398 | static void ieee80211_send_nullfunc(struct ieee80211_local *local, | 210 | void ieee80211_send_nullfunc(struct ieee80211_local *local, |
399 | struct ieee80211_sub_if_data *sdata, | 211 | struct ieee80211_sub_if_data *sdata, |
400 | int powersave) | 212 | int powersave) |
401 | { | 213 | { |
@@ -425,26 +237,22 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
425 | ieee80211_tx_skb(sdata, skb, 0); | 237 | ieee80211_tx_skb(sdata, skb, 0); |
426 | } | 238 | } |
427 | 239 | ||
428 | void ieee80211_scan_completed(struct ieee80211_hw *hw) | 240 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
429 | { | 241 | { |
430 | struct ieee80211_local *local = hw_to_local(hw); | 242 | struct ieee80211_local *local = hw_to_local(hw); |
431 | struct ieee80211_sub_if_data *sdata; | 243 | struct ieee80211_sub_if_data *sdata; |
432 | union iwreq_data wrqu; | ||
433 | 244 | ||
434 | if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) | 245 | if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) |
435 | return; | 246 | return; |
436 | 247 | ||
437 | local->last_scan_completed = jiffies; | 248 | if (WARN_ON(!local->scan_req)) |
438 | memset(&wrqu, 0, sizeof(wrqu)); | 249 | return; |
439 | 250 | ||
440 | /* | 251 | if (local->scan_req != &local->int_scan_req) |
441 | * local->scan_sdata could have been NULLed by the interface | 252 | cfg80211_scan_done(local->scan_req, aborted); |
442 | * down code in case we were scanning on an interface that is | 253 | local->scan_req = NULL; |
443 | * being taken down. | 254 | |
444 | */ | 255 | local->last_scan_completed = jiffies; |
445 | sdata = local->scan_sdata; | ||
446 | if (sdata) | ||
447 | wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
448 | 256 | ||
449 | if (local->hw_scanning) { | 257 | if (local->hw_scanning) { |
450 | local->hw_scanning = false; | 258 | local->hw_scanning = false; |
@@ -472,8 +280,11 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
472 | netif_addr_unlock(local->mdev); | 280 | netif_addr_unlock(local->mdev); |
473 | netif_tx_unlock_bh(local->mdev); | 281 | netif_tx_unlock_bh(local->mdev); |
474 | 282 | ||
475 | rcu_read_lock(); | 283 | mutex_lock(&local->iflist_mtx); |
476 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 284 | list_for_each_entry(sdata, &local->interfaces, list) { |
285 | if (!netif_running(sdata->dev)) | ||
286 | continue; | ||
287 | |||
477 | /* Tell AP we're back */ | 288 | /* Tell AP we're back */ |
478 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 289 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
479 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | 290 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { |
@@ -482,8 +293,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
482 | } | 293 | } |
483 | } else | 294 | } else |
484 | netif_tx_wake_all_queues(sdata->dev); | 295 | netif_tx_wake_all_queues(sdata->dev); |
296 | |||
297 | /* re-enable beaconing */ | ||
298 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
299 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
300 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
301 | ieee80211_if_config(sdata, | ||
302 | IEEE80211_IFCC_BEACON_ENABLED); | ||
485 | } | 303 | } |
486 | rcu_read_unlock(); | 304 | mutex_unlock(&local->iflist_mtx); |
487 | 305 | ||
488 | done: | 306 | done: |
489 | ieee80211_mlme_notify_scan_completed(local); | 307 | ieee80211_mlme_notify_scan_completed(local); |
@@ -491,15 +309,13 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
491 | } | 309 | } |
492 | EXPORT_SYMBOL(ieee80211_scan_completed); | 310 | EXPORT_SYMBOL(ieee80211_scan_completed); |
493 | 311 | ||
494 | |||
495 | void ieee80211_scan_work(struct work_struct *work) | 312 | void ieee80211_scan_work(struct work_struct *work) |
496 | { | 313 | { |
497 | struct ieee80211_local *local = | 314 | struct ieee80211_local *local = |
498 | container_of(work, struct ieee80211_local, scan_work.work); | 315 | container_of(work, struct ieee80211_local, scan_work.work); |
499 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 316 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
500 | struct ieee80211_supported_band *sband; | ||
501 | struct ieee80211_channel *chan; | 317 | struct ieee80211_channel *chan; |
502 | int skip; | 318 | int skip, i; |
503 | unsigned long next_delay = 0; | 319 | unsigned long next_delay = 0; |
504 | 320 | ||
505 | /* | 321 | /* |
@@ -510,33 +326,13 @@ void ieee80211_scan_work(struct work_struct *work) | |||
510 | 326 | ||
511 | switch (local->scan_state) { | 327 | switch (local->scan_state) { |
512 | case SCAN_SET_CHANNEL: | 328 | case SCAN_SET_CHANNEL: |
513 | /* | ||
514 | * Get current scan band. scan_band may be IEEE80211_NUM_BANDS | ||
515 | * after we successfully scanned the last channel of the last | ||
516 | * band (and the last band is supported by the hw) | ||
517 | */ | ||
518 | if (local->scan_band < IEEE80211_NUM_BANDS) | ||
519 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
520 | else | ||
521 | sband = NULL; | ||
522 | |||
523 | /* | ||
524 | * If we are at an unsupported band and have more bands | ||
525 | * left to scan, advance to the next supported one. | ||
526 | */ | ||
527 | while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) { | ||
528 | local->scan_band++; | ||
529 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
530 | local->scan_channel_idx = 0; | ||
531 | } | ||
532 | |||
533 | /* if no more bands/channels left, complete scan */ | 329 | /* if no more bands/channels left, complete scan */ |
534 | if (!sband || local->scan_channel_idx >= sband->n_channels) { | 330 | if (local->scan_channel_idx >= local->scan_req->n_channels) { |
535 | ieee80211_scan_completed(local_to_hw(local)); | 331 | ieee80211_scan_completed(local_to_hw(local), false); |
536 | return; | 332 | return; |
537 | } | 333 | } |
538 | skip = 0; | 334 | skip = 0; |
539 | chan = &sband->channels[local->scan_channel_idx]; | 335 | chan = local->scan_req->channels[local->scan_channel_idx]; |
540 | 336 | ||
541 | if (chan->flags & IEEE80211_CHAN_DISABLED || | 337 | if (chan->flags & IEEE80211_CHAN_DISABLED || |
542 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 338 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
@@ -552,15 +348,6 @@ void ieee80211_scan_work(struct work_struct *work) | |||
552 | 348 | ||
553 | /* advance state machine to next channel/band */ | 349 | /* advance state machine to next channel/band */ |
554 | local->scan_channel_idx++; | 350 | local->scan_channel_idx++; |
555 | if (local->scan_channel_idx >= sband->n_channels) { | ||
556 | /* | ||
557 | * scan_band may end up == IEEE80211_NUM_BANDS, but | ||
558 | * we'll catch that case above and complete the scan | ||
559 | * if that is the case. | ||
560 | */ | ||
561 | local->scan_band++; | ||
562 | local->scan_channel_idx = 0; | ||
563 | } | ||
564 | 351 | ||
565 | if (skip) | 352 | if (skip) |
566 | break; | 353 | break; |
@@ -573,10 +360,14 @@ void ieee80211_scan_work(struct work_struct *work) | |||
573 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 360 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
574 | local->scan_state = SCAN_SET_CHANNEL; | 361 | local->scan_state = SCAN_SET_CHANNEL; |
575 | 362 | ||
576 | if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 363 | if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN || |
364 | !local->scan_req->n_ssids) | ||
577 | break; | 365 | break; |
578 | ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, | 366 | for (i = 0; i < local->scan_req->n_ssids; i++) |
579 | local->scan_ssid_len); | 367 | ieee80211_send_probe_req( |
368 | sdata, NULL, | ||
369 | local->scan_req->ssids[i].ssid, | ||
370 | local->scan_req->ssids[i].ssid_len); | ||
580 | next_delay = IEEE80211_CHANNEL_TIME; | 371 | next_delay = IEEE80211_CHANNEL_TIME; |
581 | break; | 372 | break; |
582 | } | 373 | } |
@@ -587,14 +378,19 @@ void ieee80211_scan_work(struct work_struct *work) | |||
587 | 378 | ||
588 | 379 | ||
589 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | 380 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, |
590 | u8 *ssid, size_t ssid_len) | 381 | struct cfg80211_scan_request *req) |
591 | { | 382 | { |
592 | struct ieee80211_local *local = scan_sdata->local; | 383 | struct ieee80211_local *local = scan_sdata->local; |
593 | struct ieee80211_sub_if_data *sdata; | 384 | struct ieee80211_sub_if_data *sdata; |
594 | 385 | ||
595 | if (ssid_len > IEEE80211_MAX_SSID_LEN) | 386 | if (!req) |
596 | return -EINVAL; | 387 | return -EINVAL; |
597 | 388 | ||
389 | if (local->scan_req && local->scan_req != req) | ||
390 | return -EBUSY; | ||
391 | |||
392 | local->scan_req = req; | ||
393 | |||
598 | /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) | 394 | /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) |
599 | * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS | 395 | * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS |
600 | * BSSID: MACAddress | 396 | * BSSID: MACAddress |
@@ -622,7 +418,7 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | |||
622 | int rc; | 418 | int rc; |
623 | 419 | ||
624 | local->hw_scanning = true; | 420 | local->hw_scanning = true; |
625 | rc = local->ops->hw_scan(local_to_hw(local), ssid, ssid_len); | 421 | rc = local->ops->hw_scan(local_to_hw(local), req); |
626 | if (rc) { | 422 | if (rc) { |
627 | local->hw_scanning = false; | 423 | local->hw_scanning = false; |
628 | return rc; | 424 | return rc; |
@@ -633,8 +429,18 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | |||
633 | 429 | ||
634 | local->sw_scanning = true; | 430 | local->sw_scanning = true; |
635 | 431 | ||
636 | rcu_read_lock(); | 432 | mutex_lock(&local->iflist_mtx); |
637 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 433 | list_for_each_entry(sdata, &local->interfaces, list) { |
434 | if (!netif_running(sdata->dev)) | ||
435 | continue; | ||
436 | |||
437 | /* disable beaconing */ | ||
438 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
439 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
440 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
441 | ieee80211_if_config(sdata, | ||
442 | IEEE80211_IFCC_BEACON_ENABLED); | ||
443 | |||
638 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 444 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
639 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | 445 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { |
640 | netif_tx_stop_all_queues(sdata->dev); | 446 | netif_tx_stop_all_queues(sdata->dev); |
@@ -643,17 +449,12 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | |||
643 | } else | 449 | } else |
644 | netif_tx_stop_all_queues(sdata->dev); | 450 | netif_tx_stop_all_queues(sdata->dev); |
645 | } | 451 | } |
646 | rcu_read_unlock(); | 452 | mutex_unlock(&local->iflist_mtx); |
647 | 453 | ||
648 | if (ssid) { | ||
649 | local->scan_ssid_len = ssid_len; | ||
650 | memcpy(local->scan_ssid, ssid, ssid_len); | ||
651 | } else | ||
652 | local->scan_ssid_len = 0; | ||
653 | local->scan_state = SCAN_SET_CHANNEL; | 454 | local->scan_state = SCAN_SET_CHANNEL; |
654 | local->scan_channel_idx = 0; | 455 | local->scan_channel_idx = 0; |
655 | local->scan_band = IEEE80211_BAND_2GHZ; | ||
656 | local->scan_sdata = scan_sdata; | 456 | local->scan_sdata = scan_sdata; |
457 | local->scan_req = req; | ||
657 | 458 | ||
658 | netif_addr_lock_bh(local->mdev); | 459 | netif_addr_lock_bh(local->mdev); |
659 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | 460 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; |
@@ -673,13 +474,21 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | |||
673 | 474 | ||
674 | 475 | ||
675 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 476 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
676 | u8 *ssid, size_t ssid_len) | 477 | struct cfg80211_scan_request *req) |
677 | { | 478 | { |
678 | struct ieee80211_local *local = sdata->local; | 479 | struct ieee80211_local *local = sdata->local; |
679 | struct ieee80211_if_sta *ifsta; | 480 | struct ieee80211_if_sta *ifsta; |
680 | 481 | ||
482 | if (!req) | ||
483 | return -EINVAL; | ||
484 | |||
485 | if (local->scan_req && local->scan_req != req) | ||
486 | return -EBUSY; | ||
487 | |||
488 | local->scan_req = req; | ||
489 | |||
681 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 490 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
682 | return ieee80211_start_scan(sdata, ssid, ssid_len); | 491 | return ieee80211_start_scan(sdata, req); |
683 | 492 | ||
684 | /* | 493 | /* |
685 | * STA has a state machine that might need to defer scanning | 494 | * STA has a state machine that might need to defer scanning |
@@ -694,241 +503,8 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
694 | } | 503 | } |
695 | 504 | ||
696 | ifsta = &sdata->u.sta; | 505 | ifsta = &sdata->u.sta; |
697 | |||
698 | ifsta->scan_ssid_len = ssid_len; | ||
699 | if (ssid_len) | ||
700 | memcpy(ifsta->scan_ssid, ssid, ssid_len); | ||
701 | set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); | 506 | set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); |
702 | queue_work(local->hw.workqueue, &ifsta->work); | 507 | queue_work(local->hw.workqueue, &ifsta->work); |
703 | 508 | ||
704 | return 0; | 509 | return 0; |
705 | } | 510 | } |
706 | |||
707 | |||
708 | static void ieee80211_scan_add_ies(struct iw_request_info *info, | ||
709 | struct ieee80211_bss *bss, | ||
710 | char **current_ev, char *end_buf) | ||
711 | { | ||
712 | u8 *pos, *end, *next; | ||
713 | struct iw_event iwe; | ||
714 | |||
715 | if (bss == NULL || bss->ies == NULL) | ||
716 | return; | ||
717 | |||
718 | /* | ||
719 | * If needed, fragment the IEs buffer (at IE boundaries) into short | ||
720 | * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. | ||
721 | */ | ||
722 | pos = bss->ies; | ||
723 | end = pos + bss->ies_len; | ||
724 | |||
725 | while (end - pos > IW_GENERIC_IE_MAX) { | ||
726 | next = pos + 2 + pos[1]; | ||
727 | while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) | ||
728 | next = next + 2 + next[1]; | ||
729 | |||
730 | memset(&iwe, 0, sizeof(iwe)); | ||
731 | iwe.cmd = IWEVGENIE; | ||
732 | iwe.u.data.length = next - pos; | ||
733 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
734 | end_buf, &iwe, pos); | ||
735 | |||
736 | pos = next; | ||
737 | } | ||
738 | |||
739 | if (end > pos) { | ||
740 | memset(&iwe, 0, sizeof(iwe)); | ||
741 | iwe.cmd = IWEVGENIE; | ||
742 | iwe.u.data.length = end - pos; | ||
743 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
744 | end_buf, &iwe, pos); | ||
745 | } | ||
746 | } | ||
747 | |||
748 | |||
749 | static char * | ||
750 | ieee80211_scan_result(struct ieee80211_local *local, | ||
751 | struct iw_request_info *info, | ||
752 | struct ieee80211_bss *bss, | ||
753 | char *current_ev, char *end_buf) | ||
754 | { | ||
755 | struct iw_event iwe; | ||
756 | char *buf; | ||
757 | |||
758 | if (time_after(jiffies, | ||
759 | bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
760 | return current_ev; | ||
761 | |||
762 | memset(&iwe, 0, sizeof(iwe)); | ||
763 | iwe.cmd = SIOCGIWAP; | ||
764 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
765 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); | ||
766 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
767 | IW_EV_ADDR_LEN); | ||
768 | |||
769 | memset(&iwe, 0, sizeof(iwe)); | ||
770 | iwe.cmd = SIOCGIWESSID; | ||
771 | if (bss_mesh_cfg(bss)) { | ||
772 | iwe.u.data.length = bss_mesh_id_len(bss); | ||
773 | iwe.u.data.flags = 1; | ||
774 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
775 | &iwe, bss_mesh_id(bss)); | ||
776 | } else { | ||
777 | iwe.u.data.length = bss->ssid_len; | ||
778 | iwe.u.data.flags = 1; | ||
779 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
780 | &iwe, bss->ssid); | ||
781 | } | ||
782 | |||
783 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | ||
784 | || bss_mesh_cfg(bss)) { | ||
785 | memset(&iwe, 0, sizeof(iwe)); | ||
786 | iwe.cmd = SIOCGIWMODE; | ||
787 | if (bss_mesh_cfg(bss)) | ||
788 | iwe.u.mode = IW_MODE_MESH; | ||
789 | else if (bss->capability & WLAN_CAPABILITY_ESS) | ||
790 | iwe.u.mode = IW_MODE_MASTER; | ||
791 | else | ||
792 | iwe.u.mode = IW_MODE_ADHOC; | ||
793 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | ||
794 | &iwe, IW_EV_UINT_LEN); | ||
795 | } | ||
796 | |||
797 | memset(&iwe, 0, sizeof(iwe)); | ||
798 | iwe.cmd = SIOCGIWFREQ; | ||
799 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); | ||
800 | iwe.u.freq.e = 0; | ||
801 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
802 | IW_EV_FREQ_LEN); | ||
803 | |||
804 | memset(&iwe, 0, sizeof(iwe)); | ||
805 | iwe.cmd = SIOCGIWFREQ; | ||
806 | iwe.u.freq.m = bss->freq; | ||
807 | iwe.u.freq.e = 6; | ||
808 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
809 | IW_EV_FREQ_LEN); | ||
810 | memset(&iwe, 0, sizeof(iwe)); | ||
811 | iwe.cmd = IWEVQUAL; | ||
812 | iwe.u.qual.qual = bss->qual; | ||
813 | iwe.u.qual.level = bss->signal; | ||
814 | iwe.u.qual.noise = bss->noise; | ||
815 | iwe.u.qual.updated = local->wstats_flags; | ||
816 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
817 | IW_EV_QUAL_LEN); | ||
818 | |||
819 | memset(&iwe, 0, sizeof(iwe)); | ||
820 | iwe.cmd = SIOCGIWENCODE; | ||
821 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | ||
822 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | ||
823 | else | ||
824 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
825 | iwe.u.data.length = 0; | ||
826 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
827 | &iwe, ""); | ||
828 | |||
829 | ieee80211_scan_add_ies(info, bss, ¤t_ev, end_buf); | ||
830 | |||
831 | if (bss->supp_rates_len > 0) { | ||
832 | /* display all supported rates in readable format */ | ||
833 | char *p = current_ev + iwe_stream_lcp_len(info); | ||
834 | int i; | ||
835 | |||
836 | memset(&iwe, 0, sizeof(iwe)); | ||
837 | iwe.cmd = SIOCGIWRATE; | ||
838 | /* Those two flags are ignored... */ | ||
839 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
840 | |||
841 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
842 | iwe.u.bitrate.value = ((bss->supp_rates[i] & | ||
843 | 0x7f) * 500000); | ||
844 | p = iwe_stream_add_value(info, current_ev, p, | ||
845 | end_buf, &iwe, IW_EV_PARAM_LEN); | ||
846 | } | ||
847 | current_ev = p; | ||
848 | } | ||
849 | |||
850 | buf = kmalloc(30, GFP_ATOMIC); | ||
851 | if (buf) { | ||
852 | memset(&iwe, 0, sizeof(iwe)); | ||
853 | iwe.cmd = IWEVCUSTOM; | ||
854 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); | ||
855 | iwe.u.data.length = strlen(buf); | ||
856 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
857 | &iwe, buf); | ||
858 | memset(&iwe, 0, sizeof(iwe)); | ||
859 | iwe.cmd = IWEVCUSTOM; | ||
860 | sprintf(buf, " Last beacon: %dms ago", | ||
861 | jiffies_to_msecs(jiffies - bss->last_update)); | ||
862 | iwe.u.data.length = strlen(buf); | ||
863 | current_ev = iwe_stream_add_point(info, current_ev, | ||
864 | end_buf, &iwe, buf); | ||
865 | kfree(buf); | ||
866 | } | ||
867 | |||
868 | if (bss_mesh_cfg(bss)) { | ||
869 | u8 *cfg = bss_mesh_cfg(bss); | ||
870 | buf = kmalloc(50, GFP_ATOMIC); | ||
871 | if (buf) { | ||
872 | memset(&iwe, 0, sizeof(iwe)); | ||
873 | iwe.cmd = IWEVCUSTOM; | ||
874 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | ||
875 | iwe.u.data.length = strlen(buf); | ||
876 | current_ev = iwe_stream_add_point(info, current_ev, | ||
877 | end_buf, | ||
878 | &iwe, buf); | ||
879 | sprintf(buf, "Path Selection Protocol ID: " | ||
880 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | ||
881 | cfg[4]); | ||
882 | iwe.u.data.length = strlen(buf); | ||
883 | current_ev = iwe_stream_add_point(info, current_ev, | ||
884 | end_buf, | ||
885 | &iwe, buf); | ||
886 | sprintf(buf, "Path Selection Metric ID: " | ||
887 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | ||
888 | cfg[8]); | ||
889 | iwe.u.data.length = strlen(buf); | ||
890 | current_ev = iwe_stream_add_point(info, current_ev, | ||
891 | end_buf, | ||
892 | &iwe, buf); | ||
893 | sprintf(buf, "Congestion Control Mode ID: " | ||
894 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | ||
895 | cfg[11], cfg[12]); | ||
896 | iwe.u.data.length = strlen(buf); | ||
897 | current_ev = iwe_stream_add_point(info, current_ev, | ||
898 | end_buf, | ||
899 | &iwe, buf); | ||
900 | sprintf(buf, "Channel Precedence: " | ||
901 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | ||
902 | cfg[15], cfg[16]); | ||
903 | iwe.u.data.length = strlen(buf); | ||
904 | current_ev = iwe_stream_add_point(info, current_ev, | ||
905 | end_buf, | ||
906 | &iwe, buf); | ||
907 | kfree(buf); | ||
908 | } | ||
909 | } | ||
910 | |||
911 | return current_ev; | ||
912 | } | ||
913 | |||
914 | |||
915 | int ieee80211_scan_results(struct ieee80211_local *local, | ||
916 | struct iw_request_info *info, | ||
917 | char *buf, size_t len) | ||
918 | { | ||
919 | char *current_ev = buf; | ||
920 | char *end_buf = buf + len; | ||
921 | struct ieee80211_bss *bss; | ||
922 | |||
923 | spin_lock_bh(&local->bss_lock); | ||
924 | list_for_each_entry(bss, &local->bss_list, list) { | ||
925 | if (buf + len - current_ev <= IW_EV_ADDR_LEN) { | ||
926 | spin_unlock_bh(&local->bss_lock); | ||
927 | return -E2BIG; | ||
928 | } | ||
929 | current_ev = ieee80211_scan_result(local, info, bss, | ||
930 | current_ev, end_buf); | ||
931 | } | ||
932 | spin_unlock_bh(&local->bss_lock); | ||
933 | return current_ev - buf; | ||
934 | } | ||
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index f72bad636d8e..47bb2aed2813 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -65,7 +65,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da | |||
65 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; | 65 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; |
66 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; | 66 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; |
67 | 67 | ||
68 | ieee80211_tx_skb(sdata, skb, 0); | 68 | ieee80211_tx_skb(sdata, skb, 1); |
69 | } | 69 | } |
70 | 70 | ||
71 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 71 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
@@ -84,3 +84,104 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | |||
84 | mgmt->sa, mgmt->bssid, | 84 | mgmt->sa, mgmt->bssid, |
85 | mgmt->u.action.u.measurement.dialog_token); | 85 | mgmt->u.action.u.measurement.dialog_token); |
86 | } | 86 | } |
87 | |||
88 | void ieee80211_chswitch_work(struct work_struct *work) | ||
89 | { | ||
90 | struct ieee80211_sub_if_data *sdata = | ||
91 | container_of(work, struct ieee80211_sub_if_data, u.sta.chswitch_work); | ||
92 | struct ieee80211_bss *bss; | ||
93 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
94 | |||
95 | if (!netif_running(sdata->dev)) | ||
96 | return; | ||
97 | |||
98 | bss = ieee80211_rx_bss_get(sdata->local, ifsta->bssid, | ||
99 | sdata->local->hw.conf.channel->center_freq, | ||
100 | ifsta->ssid, ifsta->ssid_len); | ||
101 | if (!bss) | ||
102 | goto exit; | ||
103 | |||
104 | sdata->local->oper_channel = sdata->local->csa_channel; | ||
105 | /* XXX: shouldn't really modify cfg80211-owned data! */ | ||
106 | if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL)) | ||
107 | bss->cbss.channel = sdata->local->oper_channel; | ||
108 | |||
109 | ieee80211_rx_bss_put(sdata->local, bss); | ||
110 | exit: | ||
111 | ifsta->flags &= ~IEEE80211_STA_CSA_RECEIVED; | ||
112 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | ||
113 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
114 | } | ||
115 | |||
116 | void ieee80211_chswitch_timer(unsigned long data) | ||
117 | { | ||
118 | struct ieee80211_sub_if_data *sdata = | ||
119 | (struct ieee80211_sub_if_data *) data; | ||
120 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
121 | |||
122 | queue_work(sdata->local->hw.workqueue, &ifsta->chswitch_work); | ||
123 | } | ||
124 | |||
125 | void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, | ||
126 | struct ieee80211_channel_sw_ie *sw_elem, | ||
127 | struct ieee80211_bss *bss) | ||
128 | { | ||
129 | struct ieee80211_channel *new_ch; | ||
130 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
131 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); | ||
132 | |||
133 | /* FIXME: Handle ADHOC later */ | ||
134 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
135 | return; | ||
136 | |||
137 | if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATED) | ||
138 | return; | ||
139 | |||
140 | if (sdata->local->sw_scanning || sdata->local->hw_scanning) | ||
141 | return; | ||
142 | |||
143 | /* Disregard subsequent beacons if we are already running a timer | ||
144 | processing a CSA */ | ||
145 | |||
146 | if (ifsta->flags & IEEE80211_STA_CSA_RECEIVED) | ||
147 | return; | ||
148 | |||
149 | new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); | ||
150 | if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) | ||
151 | return; | ||
152 | |||
153 | sdata->local->csa_channel = new_ch; | ||
154 | |||
155 | if (sw_elem->count <= 1) { | ||
156 | queue_work(sdata->local->hw.workqueue, &ifsta->chswitch_work); | ||
157 | } else { | ||
158 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
159 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
160 | ifsta->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
161 | mod_timer(&ifsta->chswitch_timer, | ||
162 | jiffies + | ||
163 | msecs_to_jiffies(sw_elem->count * | ||
164 | bss->cbss.beacon_interval)); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | ||
169 | u16 capab_info, u8 *pwr_constr_elem, | ||
170 | u8 pwr_constr_elem_len) | ||
171 | { | ||
172 | struct ieee80211_conf *conf = &sdata->local->hw.conf; | ||
173 | |||
174 | if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT)) | ||
175 | return; | ||
176 | |||
177 | /* Power constraint IE length should be 1 octet */ | ||
178 | if (pwr_constr_elem_len != 1) | ||
179 | return; | ||
180 | |||
181 | if ((*pwr_constr_elem <= conf->channel->max_power) && | ||
182 | (*pwr_constr_elem != sdata->local->power_constr_level)) { | ||
183 | sdata->local->power_constr_level = *pwr_constr_elem; | ||
184 | ieee80211_hw_config(sdata->local, 0); | ||
185 | } | ||
186 | } | ||
187 | |||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 10c5539c20ab..634f65c0130e 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -194,12 +194,41 @@ void sta_info_destroy(struct sta_info *sta) | |||
194 | dev_kfree_skb_any(skb); | 194 | dev_kfree_skb_any(skb); |
195 | 195 | ||
196 | for (i = 0; i < STA_TID_NUM; i++) { | 196 | for (i = 0; i < STA_TID_NUM; i++) { |
197 | struct tid_ampdu_rx *tid_rx; | ||
198 | struct tid_ampdu_tx *tid_tx; | ||
199 | |||
197 | spin_lock_bh(&sta->lock); | 200 | spin_lock_bh(&sta->lock); |
198 | if (sta->ampdu_mlme.tid_rx[i]) | 201 | tid_rx = sta->ampdu_mlme.tid_rx[i]; |
199 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer); | 202 | /* Make sure timer won't free the tid_rx struct, see below */ |
200 | if (sta->ampdu_mlme.tid_tx[i]) | 203 | if (tid_rx) |
201 | del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer); | 204 | tid_rx->shutdown = true; |
202 | spin_unlock_bh(&sta->lock); | 205 | spin_unlock_bh(&sta->lock); |
206 | |||
207 | /* | ||
208 | * Outside spinlock - shutdown is true now so that the timer | ||
209 | * won't free tid_rx, we have to do that now. Can't let the | ||
210 | * timer do it because we have to sync the timer outside the | ||
211 | * lock that it takes itself. | ||
212 | */ | ||
213 | if (tid_rx) { | ||
214 | del_timer_sync(&tid_rx->session_timer); | ||
215 | kfree(tid_rx); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * No need to do such complications for TX agg sessions, the | ||
220 | * path leading to freeing the tid_tx struct goes via a call | ||
221 | * from the driver, and thus needs to look up the sta struct | ||
222 | * again, which cannot be found when we get here. Hence, we | ||
223 | * just need to delete the timer and free the aggregation | ||
224 | * info; we won't be telling the peer about it then but that | ||
225 | * doesn't matter if we're not talking to it again anyway. | ||
226 | */ | ||
227 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
228 | if (tid_tx) { | ||
229 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
230 | kfree(tid_tx); | ||
231 | } | ||
203 | } | 232 | } |
204 | 233 | ||
205 | __sta_info_free(local, sta); | 234 | __sta_info_free(local, sta); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index e49a5b99cf10..d9653231992f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -34,6 +34,7 @@ | |||
34 | * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the | 34 | * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the |
35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next | 35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next |
36 | * frame to this station is transmitted. | 36 | * frame to this station is transmitted. |
37 | * @WLAN_STA_MFP: Management frame protection is used with this STA. | ||
37 | */ | 38 | */ |
38 | enum ieee80211_sta_info_flags { | 39 | enum ieee80211_sta_info_flags { |
39 | WLAN_STA_AUTH = 1<<0, | 40 | WLAN_STA_AUTH = 1<<0, |
@@ -46,6 +47,7 @@ enum ieee80211_sta_info_flags { | |||
46 | WLAN_STA_WDS = 1<<7, | 47 | WLAN_STA_WDS = 1<<7, |
47 | WLAN_STA_PSPOLL = 1<<8, | 48 | WLAN_STA_PSPOLL = 1<<8, |
48 | WLAN_STA_CLEAR_PS_FILT = 1<<9, | 49 | WLAN_STA_CLEAR_PS_FILT = 1<<9, |
50 | WLAN_STA_MFP = 1<<10, | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | #define STA_TID_NUM 16 | 53 | #define STA_TID_NUM 16 |
@@ -63,7 +65,6 @@ enum ieee80211_sta_info_flags { | |||
63 | #define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \ | 65 | #define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \ |
64 | HT_ADDBA_DRV_READY_MSK | \ | 66 | HT_ADDBA_DRV_READY_MSK | \ |
65 | HT_ADDBA_RECEIVED_MSK) | 67 | HT_ADDBA_RECEIVED_MSK) |
66 | #define HT_AGG_STATE_DEBUGFS_CTL BIT(7) | ||
67 | 68 | ||
68 | /** | 69 | /** |
69 | * struct tid_ampdu_tx - TID aggregation information (Tx). | 70 | * struct tid_ampdu_tx - TID aggregation information (Tx). |
@@ -87,7 +88,7 @@ struct tid_ampdu_tx { | |||
87 | * @stored_mpdu_num: number of MPDUs in reordering buffer | 88 | * @stored_mpdu_num: number of MPDUs in reordering buffer |
88 | * @ssn: Starting Sequence Number expected to be aggregated. | 89 | * @ssn: Starting Sequence Number expected to be aggregated. |
89 | * @buf_size: buffer size for incoming A-MPDUs | 90 | * @buf_size: buffer size for incoming A-MPDUs |
90 | * @timeout: reset timer value. | 91 | * @timeout: reset timer value (in TUs). |
91 | * @dialog_token: dialog token for aggregation session | 92 | * @dialog_token: dialog token for aggregation session |
92 | */ | 93 | */ |
93 | struct tid_ampdu_rx { | 94 | struct tid_ampdu_rx { |
@@ -99,6 +100,7 @@ struct tid_ampdu_rx { | |||
99 | u16 buf_size; | 100 | u16 buf_size; |
100 | u16 timeout; | 101 | u16 timeout; |
101 | u8 dialog_token; | 102 | u8 dialog_token; |
103 | bool shutdown; | ||
102 | }; | 104 | }; |
103 | 105 | ||
104 | /** | 106 | /** |
@@ -382,8 +384,6 @@ static inline u32 get_sta_flags(struct sta_info *sta) | |||
382 | } | 384 | } |
383 | 385 | ||
384 | 386 | ||
385 | /* Maximum number of concurrently registered stations */ | ||
386 | #define MAX_STA_COUNT 2007 | ||
387 | 387 | ||
388 | #define STA_HASH_SIZE 256 | 388 | #define STA_HASH_SIZE 256 |
389 | #define STA_HASH(sta) (sta[5]) | 389 | #define STA_HASH(sta) (sta[5]) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 94de5033f0b6..33926831c648 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #define IEEE80211_TX_OK 0 | 35 | #define IEEE80211_TX_OK 0 |
36 | #define IEEE80211_TX_AGAIN 1 | 36 | #define IEEE80211_TX_AGAIN 1 |
37 | #define IEEE80211_TX_FRAG_AGAIN 2 | 37 | #define IEEE80211_TX_FRAG_AGAIN 2 |
38 | #define IEEE80211_TX_PENDING 3 | ||
38 | 39 | ||
39 | /* misc utils */ | 40 | /* misc utils */ |
40 | 41 | ||
@@ -330,6 +331,22 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
330 | return TX_CONTINUE; | 331 | return TX_CONTINUE; |
331 | } | 332 | } |
332 | 333 | ||
334 | static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, | ||
335 | struct sk_buff *skb) | ||
336 | { | ||
337 | if (!ieee80211_is_mgmt(fc)) | ||
338 | return 0; | ||
339 | |||
340 | if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP)) | ||
341 | return 0; | ||
342 | |||
343 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) | ||
344 | skb->data)) | ||
345 | return 0; | ||
346 | |||
347 | return 1; | ||
348 | } | ||
349 | |||
333 | static ieee80211_tx_result | 350 | static ieee80211_tx_result |
334 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | 351 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) |
335 | { | 352 | { |
@@ -409,11 +426,17 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
409 | tx->key = NULL; | 426 | tx->key = NULL; |
410 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 427 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
411 | tx->key = key; | 428 | tx->key = key; |
429 | else if (ieee80211_is_mgmt(hdr->frame_control) && | ||
430 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | ||
431 | tx->key = key; | ||
412 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 432 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
413 | tx->key = key; | 433 | tx->key = key; |
414 | else if (tx->sdata->drop_unencrypted && | 434 | else if (tx->sdata->drop_unencrypted && |
415 | (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) && | 435 | (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) && |
416 | !(info->flags & IEEE80211_TX_CTL_INJECTED)) { | 436 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && |
437 | (!ieee80211_is_robust_mgmt_frame(hdr) || | ||
438 | (ieee80211_is_action(hdr->frame_control) && | ||
439 | tx->sta && test_sta_flags(tx->sta, WLAN_STA_MFP)))) { | ||
417 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 440 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
418 | return TX_DROP; | 441 | return TX_DROP; |
419 | } else | 442 | } else |
@@ -428,10 +451,19 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
428 | if (ieee80211_is_auth(hdr->frame_control)) | 451 | if (ieee80211_is_auth(hdr->frame_control)) |
429 | break; | 452 | break; |
430 | case ALG_TKIP: | 453 | case ALG_TKIP: |
431 | case ALG_CCMP: | ||
432 | if (!ieee80211_is_data_present(hdr->frame_control)) | 454 | if (!ieee80211_is_data_present(hdr->frame_control)) |
433 | tx->key = NULL; | 455 | tx->key = NULL; |
434 | break; | 456 | break; |
457 | case ALG_CCMP: | ||
458 | if (!ieee80211_is_data_present(hdr->frame_control) && | ||
459 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, | ||
460 | tx->skb)) | ||
461 | tx->key = NULL; | ||
462 | break; | ||
463 | case ALG_AES_CMAC: | ||
464 | if (!ieee80211_is_mgmt(hdr->frame_control)) | ||
465 | tx->key = NULL; | ||
466 | break; | ||
435 | } | 467 | } |
436 | } | 468 | } |
437 | 469 | ||
@@ -787,6 +819,8 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | |||
787 | return ieee80211_crypto_tkip_encrypt(tx); | 819 | return ieee80211_crypto_tkip_encrypt(tx); |
788 | case ALG_CCMP: | 820 | case ALG_CCMP: |
789 | return ieee80211_crypto_ccmp_encrypt(tx); | 821 | return ieee80211_crypto_ccmp_encrypt(tx); |
822 | case ALG_AES_CMAC: | ||
823 | return ieee80211_crypto_aes_cmac_encrypt(tx); | ||
790 | } | 824 | } |
791 | 825 | ||
792 | /* not reached */ | 826 | /* not reached */ |
@@ -1052,8 +1086,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1052 | 1086 | ||
1053 | if (skb) { | 1087 | if (skb) { |
1054 | if (netif_subqueue_stopped(local->mdev, skb)) | 1088 | if (netif_subqueue_stopped(local->mdev, skb)) |
1055 | return IEEE80211_TX_AGAIN; | 1089 | return IEEE80211_TX_PENDING; |
1056 | info = IEEE80211_SKB_CB(skb); | ||
1057 | 1090 | ||
1058 | ret = local->ops->tx(local_to_hw(local), skb); | 1091 | ret = local->ops->tx(local_to_hw(local), skb); |
1059 | if (ret) | 1092 | if (ret) |
@@ -1179,8 +1212,9 @@ retry: | |||
1179 | * queues, there's no reason for a driver to reject | 1212 | * queues, there's no reason for a driver to reject |
1180 | * a frame there, warn and drop it. | 1213 | * a frame there, warn and drop it. |
1181 | */ | 1214 | */ |
1182 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) | 1215 | if (ret != IEEE80211_TX_PENDING) |
1183 | goto drop; | 1216 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
1217 | goto drop; | ||
1184 | 1218 | ||
1185 | store = &local->pending_packet[queue]; | 1219 | store = &local->pending_packet[queue]; |
1186 | 1220 | ||
@@ -1296,6 +1330,19 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1296 | return 0; | 1330 | return 0; |
1297 | } | 1331 | } |
1298 | 1332 | ||
1333 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | ||
1334 | local->hw.conf.dynamic_ps_timeout > 0) { | ||
1335 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1336 | ieee80211_stop_queues_by_reason(&local->hw, | ||
1337 | IEEE80211_QUEUE_STOP_REASON_PS); | ||
1338 | queue_work(local->hw.workqueue, | ||
1339 | &local->dynamic_ps_disable_work); | ||
1340 | } | ||
1341 | |||
1342 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
1343 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
1344 | } | ||
1345 | |||
1299 | memset(info, 0, sizeof(*info)); | 1346 | memset(info, 0, sizeof(*info)); |
1300 | 1347 | ||
1301 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1348 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
@@ -1390,10 +1437,31 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1390 | struct net_device *dev) | 1437 | struct net_device *dev) |
1391 | { | 1438 | { |
1392 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1439 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1440 | struct ieee80211_channel *chan = local->hw.conf.channel; | ||
1393 | struct ieee80211_radiotap_header *prthdr = | 1441 | struct ieee80211_radiotap_header *prthdr = |
1394 | (struct ieee80211_radiotap_header *)skb->data; | 1442 | (struct ieee80211_radiotap_header *)skb->data; |
1395 | u16 len_rthdr; | 1443 | u16 len_rthdr; |
1396 | 1444 | ||
1445 | /* | ||
1446 | * Frame injection is not allowed if beaconing is not allowed | ||
1447 | * or if we need radar detection. Beaconing is usually not allowed when | ||
1448 | * the mode or operation (Adhoc, AP, Mesh) does not support DFS. | ||
1449 | * Passive scan is also used in world regulatory domains where | ||
1450 | * your country is not known and as such it should be treated as | ||
1451 | * NO TX unless the channel is explicitly allowed in which case | ||
1452 | * your current regulatory domain would not have the passive scan | ||
1453 | * flag. | ||
1454 | * | ||
1455 | * Since AP mode uses monitor interfaces to inject/TX management | ||
1456 | * frames we can make AP mode the exception to this rule once it | ||
1457 | * supports radar detection as its implementation can deal with | ||
1458 | * radar detection by itself. We can do that later by adding a | ||
1459 | * monitor flag interfaces used for AP support. | ||
1460 | */ | ||
1461 | if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR | | ||
1462 | IEEE80211_CHAN_PASSIVE_SCAN))) | ||
1463 | goto fail; | ||
1464 | |||
1397 | /* check for not even having the fixed radiotap header part */ | 1465 | /* check for not even having the fixed radiotap header part */ |
1398 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) | 1466 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) |
1399 | goto fail; /* too short to be possibly valid */ | 1467 | goto fail; /* too short to be possibly valid */ |
@@ -1477,19 +1545,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1477 | goto fail; | 1545 | goto fail; |
1478 | } | 1546 | } |
1479 | 1547 | ||
1480 | if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && | ||
1481 | local->dynamic_ps_timeout > 0) { | ||
1482 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1483 | ieee80211_stop_queues_by_reason(&local->hw, | ||
1484 | IEEE80211_QUEUE_STOP_REASON_PS); | ||
1485 | queue_work(local->hw.workqueue, | ||
1486 | &local->dynamic_ps_disable_work); | ||
1487 | } | ||
1488 | |||
1489 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
1490 | msecs_to_jiffies(local->dynamic_ps_timeout)); | ||
1491 | } | ||
1492 | |||
1493 | nh_pos = skb_network_header(skb) - skb->data; | 1548 | nh_pos = skb_network_header(skb) - skb->data; |
1494 | h_pos = skb_transport_header(skb) - skb->data; | 1549 | h_pos = skb_transport_header(skb) - skb->data; |
1495 | 1550 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index fb89e1d0aa03..73c7d7345abd 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -41,6 +41,15 @@ const unsigned char rfc1042_header[] __aligned(2) = | |||
41 | const unsigned char bridge_tunnel_header[] __aligned(2) = | 41 | const unsigned char bridge_tunnel_header[] __aligned(2) = |
42 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | 42 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; |
43 | 43 | ||
44 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) | ||
45 | { | ||
46 | struct ieee80211_local *local; | ||
47 | BUG_ON(!wiphy); | ||
48 | |||
49 | local = wiphy_priv(wiphy); | ||
50 | return &local->hw; | ||
51 | } | ||
52 | EXPORT_SYMBOL(wiphy_to_ieee80211_hw); | ||
44 | 53 | ||
45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 54 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
46 | enum nl80211_iftype type) | 55 | enum nl80211_iftype type) |
@@ -352,8 +361,8 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
352 | } | 361 | } |
353 | } | 362 | } |
354 | 363 | ||
355 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 364 | static void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
356 | enum queue_stop_reason reason) | 365 | enum queue_stop_reason reason) |
357 | { | 366 | { |
358 | struct ieee80211_local *local = hw_to_local(hw); | 367 | struct ieee80211_local *local = hw_to_local(hw); |
359 | unsigned long flags; | 368 | unsigned long flags; |
@@ -382,8 +391,8 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
382 | netif_stop_subqueue(local->mdev, queue); | 391 | netif_stop_subqueue(local->mdev, queue); |
383 | } | 392 | } |
384 | 393 | ||
385 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 394 | static void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, |
386 | enum queue_stop_reason reason) | 395 | enum queue_stop_reason reason) |
387 | { | 396 | { |
388 | struct ieee80211_local *local = hw_to_local(hw); | 397 | struct ieee80211_local *local = hw_to_local(hw); |
389 | unsigned long flags; | 398 | unsigned long flags; |
@@ -459,7 +468,7 @@ void ieee80211_iterate_active_interfaces( | |||
459 | struct ieee80211_local *local = hw_to_local(hw); | 468 | struct ieee80211_local *local = hw_to_local(hw); |
460 | struct ieee80211_sub_if_data *sdata; | 469 | struct ieee80211_sub_if_data *sdata; |
461 | 470 | ||
462 | rtnl_lock(); | 471 | mutex_lock(&local->iflist_mtx); |
463 | 472 | ||
464 | list_for_each_entry(sdata, &local->interfaces, list) { | 473 | list_for_each_entry(sdata, &local->interfaces, list) { |
465 | switch (sdata->vif.type) { | 474 | switch (sdata->vif.type) { |
@@ -480,7 +489,7 @@ void ieee80211_iterate_active_interfaces( | |||
480 | &sdata->vif); | 489 | &sdata->vif); |
481 | } | 490 | } |
482 | 491 | ||
483 | rtnl_unlock(); | 492 | mutex_unlock(&local->iflist_mtx); |
484 | } | 493 | } |
485 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); | 494 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); |
486 | 495 | ||
@@ -653,6 +662,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
653 | elems->pwr_constr_elem = pos; | 662 | elems->pwr_constr_elem = pos; |
654 | elems->pwr_constr_elem_len = elen; | 663 | elems->pwr_constr_elem_len = elen; |
655 | break; | 664 | break; |
665 | case WLAN_EID_TIMEOUT_INTERVAL: | ||
666 | elems->timeout_int = pos; | ||
667 | elems->timeout_int_len = elen; | ||
668 | break; | ||
656 | default: | 669 | default: |
657 | break; | 670 | break; |
658 | } | 671 | } |
@@ -727,12 +740,12 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | |||
727 | return ret; | 740 | return ret; |
728 | } | 741 | } |
729 | 742 | ||
730 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | 743 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
731 | enum ieee80211_band band) | 744 | enum ieee80211_band band) |
732 | { | 745 | { |
733 | struct ieee80211_supported_band *sband; | 746 | struct ieee80211_supported_band *sband; |
734 | struct ieee80211_rate *bitrates; | 747 | struct ieee80211_rate *bitrates; |
735 | u64 mandatory_rates; | 748 | u32 mandatory_rates; |
736 | enum ieee80211_rate_flags mandatory_flag; | 749 | enum ieee80211_rate_flags mandatory_flag; |
737 | int i; | 750 | int i; |
738 | 751 | ||
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 7162d5816f39..2b023dce8b24 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -37,7 +37,14 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta | |||
37 | struct ieee80211_key *key; | 37 | struct ieee80211_key *key; |
38 | int err; | 38 | int err; |
39 | 39 | ||
40 | if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { | 40 | if (alg == ALG_AES_CMAC) { |
41 | if (idx < NUM_DEFAULT_KEYS || | ||
42 | idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { | ||
43 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d " | ||
44 | "(BIP)\n", sdata->dev->name, idx); | ||
45 | return -EINVAL; | ||
46 | } | ||
47 | } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { | ||
41 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", | 48 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", |
42 | sdata->dev->name, idx); | 49 | sdata->dev->name, idx); |
43 | return -EINVAL; | 50 | return -EINVAL; |
@@ -103,6 +110,9 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta | |||
103 | 110 | ||
104 | if (set_tx_key || (!sta && !sdata->default_key && key)) | 111 | if (set_tx_key || (!sta && !sdata->default_key && key)) |
105 | ieee80211_set_default_key(sdata, idx); | 112 | ieee80211_set_default_key(sdata, idx); |
113 | if (alg == ALG_AES_CMAC && | ||
114 | (set_tx_key || (!sta && !sdata->default_mgmt_key && key))) | ||
115 | ieee80211_set_default_mgmt_key(sdata, idx); | ||
106 | } | 116 | } |
107 | 117 | ||
108 | out_unlock: | 118 | out_unlock: |
@@ -135,6 +145,21 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, | |||
135 | return -EOPNOTSUPP; | 145 | return -EOPNOTSUPP; |
136 | } | 146 | } |
137 | 147 | ||
148 | static u8 ieee80211_get_wstats_flags(struct ieee80211_local *local) | ||
149 | { | ||
150 | u8 wstats_flags = 0; | ||
151 | |||
152 | wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | | ||
153 | IEEE80211_HW_SIGNAL_DBM) ? | ||
154 | IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; | ||
155 | wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ? | ||
156 | IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID; | ||
157 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
158 | wstats_flags |= IW_QUAL_DBM; | ||
159 | |||
160 | return wstats_flags; | ||
161 | } | ||
162 | |||
138 | static int ieee80211_ioctl_giwrange(struct net_device *dev, | 163 | static int ieee80211_ioctl_giwrange(struct net_device *dev, |
139 | struct iw_request_info *info, | 164 | struct iw_request_info *info, |
140 | struct iw_point *data, char *extra) | 165 | struct iw_point *data, char *extra) |
@@ -163,9 +188,9 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
163 | range->num_encoding_sizes = 2; | 188 | range->num_encoding_sizes = 2; |
164 | range->max_encoding_tokens = NUM_DEFAULT_KEYS; | 189 | range->max_encoding_tokens = NUM_DEFAULT_KEYS; |
165 | 190 | ||
166 | if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC || | 191 | /* cfg80211 requires this, and enforces 0..100 */ |
167 | local->hw.flags & IEEE80211_HW_SIGNAL_DB) | 192 | if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
168 | range->max_qual.level = local->hw.max_signal; | 193 | range->max_qual.level = 100; |
169 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 194 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
170 | range->max_qual.level = -110; | 195 | range->max_qual.level = -110; |
171 | else | 196 | else |
@@ -177,13 +202,13 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
177 | range->max_qual.noise = 0; | 202 | range->max_qual.noise = 0; |
178 | 203 | ||
179 | range->max_qual.qual = 100; | 204 | range->max_qual.qual = 100; |
180 | range->max_qual.updated = local->wstats_flags; | 205 | range->max_qual.updated = ieee80211_get_wstats_flags(local); |
181 | 206 | ||
182 | range->avg_qual.qual = 50; | 207 | range->avg_qual.qual = 50; |
183 | /* not always true but better than nothing */ | 208 | /* not always true but better than nothing */ |
184 | range->avg_qual.level = range->max_qual.level / 2; | 209 | range->avg_qual.level = range->max_qual.level / 2; |
185 | range->avg_qual.noise = range->max_qual.noise / 2; | 210 | range->avg_qual.noise = range->max_qual.noise / 2; |
186 | range->avg_qual.updated = local->wstats_flags; | 211 | range->avg_qual.updated = ieee80211_get_wstats_flags(local); |
187 | 212 | ||
188 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | 213 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | |
189 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; | 214 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; |
@@ -230,13 +255,15 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
230 | { | 255 | { |
231 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 256 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
232 | 257 | ||
233 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 258 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC || |
259 | sdata->vif.type == NL80211_IFTYPE_STATION) | ||
234 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; | 260 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; |
235 | 261 | ||
236 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ | 262 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ |
237 | if (freq->e == 0) { | 263 | if (freq->e == 0) { |
238 | if (freq->m < 0) { | 264 | if (freq->m < 0) { |
239 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 265 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC || |
266 | sdata->vif.type == NL80211_IFTYPE_STATION) | ||
240 | sdata->u.sta.flags |= | 267 | sdata->u.sta.flags |= |
241 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 268 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
242 | return 0; | 269 | return 0; |
@@ -404,58 +431,6 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
404 | } | 431 | } |
405 | 432 | ||
406 | 433 | ||
407 | static int ieee80211_ioctl_siwscan(struct net_device *dev, | ||
408 | struct iw_request_info *info, | ||
409 | union iwreq_data *wrqu, char *extra) | ||
410 | { | ||
411 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
412 | struct iw_scan_req *req = NULL; | ||
413 | u8 *ssid = NULL; | ||
414 | size_t ssid_len = 0; | ||
415 | |||
416 | if (!netif_running(dev)) | ||
417 | return -ENETDOWN; | ||
418 | |||
419 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
420 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
421 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
422 | return -EOPNOTSUPP; | ||
423 | |||
424 | /* if SSID was specified explicitly then use that */ | ||
425 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | ||
426 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | ||
427 | req = (struct iw_scan_req *)extra; | ||
428 | ssid = req->essid; | ||
429 | ssid_len = req->essid_len; | ||
430 | } | ||
431 | |||
432 | return ieee80211_request_scan(sdata, ssid, ssid_len); | ||
433 | } | ||
434 | |||
435 | |||
436 | static int ieee80211_ioctl_giwscan(struct net_device *dev, | ||
437 | struct iw_request_info *info, | ||
438 | struct iw_point *data, char *extra) | ||
439 | { | ||
440 | int res; | ||
441 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
442 | struct ieee80211_sub_if_data *sdata; | ||
443 | |||
444 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
445 | |||
446 | if (local->sw_scanning || local->hw_scanning) | ||
447 | return -EAGAIN; | ||
448 | |||
449 | res = ieee80211_scan_results(local, info, extra, data->length); | ||
450 | if (res >= 0) { | ||
451 | data->length = res; | ||
452 | return 0; | ||
453 | } | ||
454 | data->length = 0; | ||
455 | return res; | ||
456 | } | ||
457 | |||
458 | |||
459 | static int ieee80211_ioctl_siwrate(struct net_device *dev, | 434 | static int ieee80211_ioctl_siwrate(struct net_device *dev, |
460 | struct iw_request_info *info, | 435 | struct iw_request_info *info, |
461 | struct iw_param *rate, char *extra) | 436 | struct iw_param *rate, char *extra) |
@@ -549,10 +524,9 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, | |||
549 | else /* Automatic power level setting */ | 524 | else /* Automatic power level setting */ |
550 | new_power_level = chan->max_power; | 525 | new_power_level = chan->max_power; |
551 | 526 | ||
552 | if (local->hw.conf.power_level != new_power_level) { | 527 | local->user_power_level = new_power_level; |
553 | local->hw.conf.power_level = new_power_level; | 528 | if (local->hw.conf.power_level != new_power_level) |
554 | reconf_flags |= IEEE80211_CONF_CHANGE_POWER; | 529 | reconf_flags |= IEEE80211_CONF_CHANGE_POWER; |
555 | } | ||
556 | 530 | ||
557 | if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { | 531 | if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { |
558 | local->hw.conf.radio_enabled = !(data->txpower.disabled); | 532 | local->hw.conf.radio_enabled = !(data->txpower.disabled); |
@@ -836,6 +810,9 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, | |||
836 | int ret = 0, timeout = 0; | 810 | int ret = 0, timeout = 0; |
837 | bool ps; | 811 | bool ps; |
838 | 812 | ||
813 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) | ||
814 | return -EOPNOTSUPP; | ||
815 | |||
839 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 816 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
840 | return -EINVAL; | 817 | return -EINVAL; |
841 | 818 | ||
@@ -852,31 +829,49 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, | |||
852 | ps = true; | 829 | ps = true; |
853 | break; | 830 | break; |
854 | default: /* Otherwise we ignore */ | 831 | default: /* Otherwise we ignore */ |
855 | break; | 832 | return -EINVAL; |
856 | } | 833 | } |
857 | 834 | ||
835 | if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT)) | ||
836 | return -EINVAL; | ||
837 | |||
858 | if (wrq->flags & IW_POWER_TIMEOUT) | 838 | if (wrq->flags & IW_POWER_TIMEOUT) |
859 | timeout = wrq->value / 1000; | 839 | timeout = wrq->value / 1000; |
860 | 840 | ||
861 | set: | 841 | set: |
862 | if (ps == local->powersave && timeout == local->dynamic_ps_timeout) | 842 | if (ps == local->powersave && timeout == conf->dynamic_ps_timeout) |
863 | return ret; | 843 | return ret; |
864 | 844 | ||
865 | local->powersave = ps; | 845 | local->powersave = ps; |
866 | local->dynamic_ps_timeout = timeout; | 846 | conf->dynamic_ps_timeout = timeout; |
867 | 847 | ||
868 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | 848 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) |
869 | if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && | 849 | ret = ieee80211_hw_config(local, |
870 | local->dynamic_ps_timeout > 0) | 850 | IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); |
871 | mod_timer(&local->dynamic_ps_timer, jiffies + | 851 | |
872 | msecs_to_jiffies(local->dynamic_ps_timeout)); | 852 | if (!(sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) |
873 | else { | 853 | return ret; |
874 | if (local->powersave) | 854 | |
875 | conf->flags |= IEEE80211_CONF_PS; | 855 | if (conf->dynamic_ps_timeout > 0 && |
876 | else | 856 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { |
877 | conf->flags &= ~IEEE80211_CONF_PS; | 857 | mod_timer(&local->dynamic_ps_timer, jiffies + |
858 | msecs_to_jiffies(conf->dynamic_ps_timeout)); | ||
859 | } else { | ||
860 | if (local->powersave) { | ||
861 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | ||
862 | ieee80211_send_nullfunc(local, sdata, 1); | ||
863 | conf->flags |= IEEE80211_CONF_PS; | ||
864 | ret = ieee80211_hw_config(local, | ||
865 | IEEE80211_CONF_CHANGE_PS); | ||
866 | } else { | ||
867 | conf->flags &= ~IEEE80211_CONF_PS; | ||
868 | ret = ieee80211_hw_config(local, | ||
869 | IEEE80211_CONF_CHANGE_PS); | ||
870 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | ||
871 | ieee80211_send_nullfunc(local, sdata, 0); | ||
872 | del_timer_sync(&local->dynamic_ps_timer); | ||
873 | cancel_work_sync(&local->dynamic_ps_enable_work); | ||
878 | } | 874 | } |
879 | ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
880 | } | 875 | } |
881 | 876 | ||
882 | return ret; | 877 | return ret; |
@@ -903,11 +898,22 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, | |||
903 | 898 | ||
904 | switch (data->flags & IW_AUTH_INDEX) { | 899 | switch (data->flags & IW_AUTH_INDEX) { |
905 | case IW_AUTH_WPA_VERSION: | 900 | case IW_AUTH_WPA_VERSION: |
906 | case IW_AUTH_CIPHER_PAIRWISE: | ||
907 | case IW_AUTH_CIPHER_GROUP: | 901 | case IW_AUTH_CIPHER_GROUP: |
908 | case IW_AUTH_WPA_ENABLED: | 902 | case IW_AUTH_WPA_ENABLED: |
909 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | 903 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: |
910 | case IW_AUTH_KEY_MGMT: | 904 | case IW_AUTH_KEY_MGMT: |
905 | case IW_AUTH_CIPHER_GROUP_MGMT: | ||
906 | break; | ||
907 | case IW_AUTH_CIPHER_PAIRWISE: | ||
908 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
909 | if (data->value & (IW_AUTH_CIPHER_WEP40 | | ||
910 | IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP)) | ||
911 | sdata->u.sta.flags |= | ||
912 | IEEE80211_STA_TKIP_WEP_USED; | ||
913 | else | ||
914 | sdata->u.sta.flags &= | ||
915 | ~IEEE80211_STA_TKIP_WEP_USED; | ||
916 | } | ||
911 | break; | 917 | break; |
912 | case IW_AUTH_DROP_UNENCRYPTED: | 918 | case IW_AUTH_DROP_UNENCRYPTED: |
913 | sdata->drop_unencrypted = !!data->value; | 919 | sdata->drop_unencrypted = !!data->value; |
@@ -934,6 +940,29 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, | |||
934 | else | 940 | else |
935 | ret = -EOPNOTSUPP; | 941 | ret = -EOPNOTSUPP; |
936 | break; | 942 | break; |
943 | case IW_AUTH_MFP: | ||
944 | if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) { | ||
945 | ret = -EOPNOTSUPP; | ||
946 | break; | ||
947 | } | ||
948 | if (sdata->vif.type == NL80211_IFTYPE_STATION || | ||
949 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
950 | switch (data->value) { | ||
951 | case IW_AUTH_MFP_DISABLED: | ||
952 | sdata->u.sta.mfp = IEEE80211_MFP_DISABLED; | ||
953 | break; | ||
954 | case IW_AUTH_MFP_OPTIONAL: | ||
955 | sdata->u.sta.mfp = IEEE80211_MFP_OPTIONAL; | ||
956 | break; | ||
957 | case IW_AUTH_MFP_REQUIRED: | ||
958 | sdata->u.sta.mfp = IEEE80211_MFP_REQUIRED; | ||
959 | break; | ||
960 | default: | ||
961 | ret = -EINVAL; | ||
962 | } | ||
963 | } else | ||
964 | ret = -EOPNOTSUPP; | ||
965 | break; | ||
937 | default: | 966 | default: |
938 | ret = -EOPNOTSUPP; | 967 | ret = -EOPNOTSUPP; |
939 | break; | 968 | break; |
@@ -965,7 +994,7 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev | |||
965 | wstats->qual.level = sta->last_signal; | 994 | wstats->qual.level = sta->last_signal; |
966 | wstats->qual.qual = sta->last_qual; | 995 | wstats->qual.qual = sta->last_qual; |
967 | wstats->qual.noise = sta->last_noise; | 996 | wstats->qual.noise = sta->last_noise; |
968 | wstats->qual.updated = local->wstats_flags; | 997 | wstats->qual.updated = ieee80211_get_wstats_flags(local); |
969 | } | 998 | } |
970 | 999 | ||
971 | rcu_read_unlock(); | 1000 | rcu_read_unlock(); |
@@ -1017,6 +1046,9 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev, | |||
1017 | case IW_ENCODE_ALG_CCMP: | 1046 | case IW_ENCODE_ALG_CCMP: |
1018 | alg = ALG_CCMP; | 1047 | alg = ALG_CCMP; |
1019 | break; | 1048 | break; |
1049 | case IW_ENCODE_ALG_AES_CMAC: | ||
1050 | alg = ALG_AES_CMAC; | ||
1051 | break; | ||
1020 | default: | 1052 | default: |
1021 | return -EOPNOTSUPP; | 1053 | return -EOPNOTSUPP; |
1022 | } | 1054 | } |
@@ -1025,20 +1057,41 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev, | |||
1025 | remove = 1; | 1057 | remove = 1; |
1026 | 1058 | ||
1027 | idx = erq->flags & IW_ENCODE_INDEX; | 1059 | idx = erq->flags & IW_ENCODE_INDEX; |
1028 | if (idx < 1 || idx > 4) { | 1060 | if (alg == ALG_AES_CMAC) { |
1029 | idx = -1; | 1061 | if (idx < NUM_DEFAULT_KEYS + 1 || |
1030 | if (!sdata->default_key) | 1062 | idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { |
1031 | idx = 0; | 1063 | idx = -1; |
1032 | else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | 1064 | if (!sdata->default_mgmt_key) |
1033 | if (sdata->default_key == sdata->keys[i]) { | 1065 | idx = 0; |
1034 | idx = i; | 1066 | else for (i = NUM_DEFAULT_KEYS; |
1035 | break; | 1067 | i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS; |
1068 | i++) { | ||
1069 | if (sdata->default_mgmt_key == sdata->keys[i]) | ||
1070 | { | ||
1071 | idx = i; | ||
1072 | break; | ||
1073 | } | ||
1036 | } | 1074 | } |
1037 | } | 1075 | if (idx < 0) |
1038 | if (idx < 0) | 1076 | return -EINVAL; |
1039 | return -EINVAL; | 1077 | } else |
1040 | } else | 1078 | idx--; |
1041 | idx--; | 1079 | } else { |
1080 | if (idx < 1 || idx > 4) { | ||
1081 | idx = -1; | ||
1082 | if (!sdata->default_key) | ||
1083 | idx = 0; | ||
1084 | else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
1085 | if (sdata->default_key == sdata->keys[i]) { | ||
1086 | idx = i; | ||
1087 | break; | ||
1088 | } | ||
1089 | } | ||
1090 | if (idx < 0) | ||
1091 | return -EINVAL; | ||
1092 | } else | ||
1093 | idx--; | ||
1094 | } | ||
1042 | 1095 | ||
1043 | return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, | 1096 | return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, |
1044 | remove, | 1097 | remove, |
@@ -1076,8 +1129,8 @@ static const iw_handler ieee80211_handler[] = | |||
1076 | (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ | 1129 | (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ |
1077 | (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */ | 1130 | (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */ |
1078 | (iw_handler) NULL, /* SIOCGIWAPLIST */ | 1131 | (iw_handler) NULL, /* SIOCGIWAPLIST */ |
1079 | (iw_handler) ieee80211_ioctl_siwscan, /* SIOCSIWSCAN */ | 1132 | (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ |
1080 | (iw_handler) ieee80211_ioctl_giwscan, /* SIOCGIWSCAN */ | 1133 | (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ |
1081 | (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */ | 1134 | (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */ |
1082 | (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */ | 1135 | (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */ |
1083 | (iw_handler) NULL, /* SIOCSIWNICKN */ | 1136 | (iw_handler) NULL, /* SIOCSIWNICKN */ |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 7aa63caf8d50..9101b48ec2ae 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2002-2004, Instant802 Networks, Inc. | 2 | * Copyright 2002-2004, Instant802 Networks, Inc. |
3 | * Copyright 2008, Jouni Malinen <j@w1.fi> | ||
3 | * | 4 | * |
4 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
@@ -19,6 +20,7 @@ | |||
19 | #include "michael.h" | 20 | #include "michael.h" |
20 | #include "tkip.h" | 21 | #include "tkip.h" |
21 | #include "aes_ccm.h" | 22 | #include "aes_ccm.h" |
23 | #include "aes_cmac.h" | ||
22 | #include "wpa.h" | 24 | #include "wpa.h" |
23 | 25 | ||
24 | ieee80211_tx_result | 26 | ieee80211_tx_result |
@@ -266,7 +268,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
266 | int encrypted) | 268 | int encrypted) |
267 | { | 269 | { |
268 | __le16 mask_fc; | 270 | __le16 mask_fc; |
269 | int a4_included; | 271 | int a4_included, mgmt; |
270 | u8 qos_tid; | 272 | u8 qos_tid; |
271 | u8 *b_0, *aad; | 273 | u8 *b_0, *aad; |
272 | u16 data_len, len_a; | 274 | u16 data_len, len_a; |
@@ -277,12 +279,15 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
277 | aad = scratch + 4 * AES_BLOCK_LEN; | 279 | aad = scratch + 4 * AES_BLOCK_LEN; |
278 | 280 | ||
279 | /* | 281 | /* |
280 | * Mask FC: zero subtype b4 b5 b6 | 282 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) |
281 | * Retry, PwrMgt, MoreData; set Protected | 283 | * Retry, PwrMgt, MoreData; set Protected |
282 | */ | 284 | */ |
285 | mgmt = ieee80211_is_mgmt(hdr->frame_control); | ||
283 | mask_fc = hdr->frame_control; | 286 | mask_fc = hdr->frame_control; |
284 | mask_fc &= ~cpu_to_le16(0x0070 | IEEE80211_FCTL_RETRY | | 287 | mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | |
285 | IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); | 288 | IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); |
289 | if (!mgmt) | ||
290 | mask_fc &= ~cpu_to_le16(0x0070); | ||
286 | mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 291 | mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
287 | 292 | ||
288 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 293 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -300,8 +305,10 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
300 | 305 | ||
301 | /* First block, b_0 */ | 306 | /* First block, b_0 */ |
302 | b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ | 307 | b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ |
303 | /* Nonce: QoS Priority | A2 | PN */ | 308 | /* Nonce: Nonce Flags | A2 | PN |
304 | b_0[1] = qos_tid; | 309 | * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) |
310 | */ | ||
311 | b_0[1] = qos_tid | (mgmt << 4); | ||
305 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); | 312 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); |
306 | memcpy(&b_0[8], pn, CCMP_PN_LEN); | 313 | memcpy(&b_0[8], pn, CCMP_PN_LEN); |
307 | /* l(m) */ | 314 | /* l(m) */ |
@@ -360,9 +367,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
360 | int hdrlen, len, tail; | 367 | int hdrlen, len, tail; |
361 | u8 *pos, *pn; | 368 | u8 *pos, *pn; |
362 | int i; | 369 | int i; |
370 | bool skip_hw; | ||
371 | |||
372 | skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) && | ||
373 | ieee80211_is_mgmt(hdr->frame_control); | ||
363 | 374 | ||
364 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 375 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
365 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 376 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && |
377 | !skip_hw) { | ||
366 | /* hwaccel - with no need for preallocated room for CCMP | 378 | /* hwaccel - with no need for preallocated room for CCMP |
367 | * header or MIC fields */ | 379 | * header or MIC fields */ |
368 | info->control.hw_key = &tx->key->conf; | 380 | info->control.hw_key = &tx->key->conf; |
@@ -397,7 +409,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
397 | 409 | ||
398 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); | 410 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
399 | 411 | ||
400 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 412 | if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) { |
401 | /* hwaccel - with preallocated room for CCMP header */ | 413 | /* hwaccel - with preallocated room for CCMP header */ |
402 | info->control.hw_key = &tx->key->conf; | 414 | info->control.hw_key = &tx->key->conf; |
403 | return 0; | 415 | return 0; |
@@ -446,7 +458,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
446 | 458 | ||
447 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 459 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
448 | 460 | ||
449 | if (!ieee80211_is_data(hdr->frame_control)) | 461 | if (!ieee80211_is_data(hdr->frame_control) && |
462 | !ieee80211_is_robust_mgmt_frame(hdr)) | ||
450 | return RX_CONTINUE; | 463 | return RX_CONTINUE; |
451 | 464 | ||
452 | data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; | 465 | data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; |
@@ -485,3 +498,126 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
485 | 498 | ||
486 | return RX_CONTINUE; | 499 | return RX_CONTINUE; |
487 | } | 500 | } |
501 | |||
502 | |||
503 | static void bip_aad(struct sk_buff *skb, u8 *aad) | ||
504 | { | ||
505 | /* BIP AAD: FC(masked) || A1 || A2 || A3 */ | ||
506 | |||
507 | /* FC type/subtype */ | ||
508 | aad[0] = skb->data[0]; | ||
509 | /* Mask FC Retry, PwrMgt, MoreData flags to zero */ | ||
510 | aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); | ||
511 | /* A1 || A2 || A3 */ | ||
512 | memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); | ||
513 | } | ||
514 | |||
515 | |||
516 | static inline void bip_ipn_swap(u8 *d, const u8 *s) | ||
517 | { | ||
518 | *d++ = s[5]; | ||
519 | *d++ = s[4]; | ||
520 | *d++ = s[3]; | ||
521 | *d++ = s[2]; | ||
522 | *d++ = s[1]; | ||
523 | *d = s[0]; | ||
524 | } | ||
525 | |||
526 | |||
527 | ieee80211_tx_result | ||
528 | ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | ||
529 | { | ||
530 | struct sk_buff *skb = tx->skb; | ||
531 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
532 | struct ieee80211_key *key = tx->key; | ||
533 | struct ieee80211_mmie *mmie; | ||
534 | u8 *pn, aad[20]; | ||
535 | int i; | ||
536 | |||
537 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | ||
538 | /* hwaccel */ | ||
539 | info->control.hw_key = &tx->key->conf; | ||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) | ||
544 | return TX_DROP; | ||
545 | |||
546 | mmie = (struct ieee80211_mmie *) skb_put(skb, sizeof(*mmie)); | ||
547 | mmie->element_id = WLAN_EID_MMIE; | ||
548 | mmie->length = sizeof(*mmie) - 2; | ||
549 | mmie->key_id = cpu_to_le16(key->conf.keyidx); | ||
550 | |||
551 | /* PN = PN + 1 */ | ||
552 | pn = key->u.aes_cmac.tx_pn; | ||
553 | |||
554 | for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) { | ||
555 | pn[i]++; | ||
556 | if (pn[i]) | ||
557 | break; | ||
558 | } | ||
559 | bip_ipn_swap(mmie->sequence_number, pn); | ||
560 | |||
561 | bip_aad(skb, aad); | ||
562 | |||
563 | /* | ||
564 | * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) | ||
565 | */ | ||
566 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf, | ||
567 | aad, skb->data + 24, skb->len - 24, mmie->mic); | ||
568 | |||
569 | return TX_CONTINUE; | ||
570 | } | ||
571 | |||
572 | |||
573 | ieee80211_rx_result | ||
574 | ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | ||
575 | { | ||
576 | struct sk_buff *skb = rx->skb; | ||
577 | struct ieee80211_key *key = rx->key; | ||
578 | struct ieee80211_mmie *mmie; | ||
579 | u8 aad[20], mic[8], ipn[6]; | ||
580 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
581 | |||
582 | if (!ieee80211_is_mgmt(hdr->frame_control)) | ||
583 | return RX_CONTINUE; | ||
584 | |||
585 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | ||
586 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | ||
587 | return RX_CONTINUE; | ||
588 | |||
589 | if (skb->len < 24 + sizeof(*mmie)) | ||
590 | return RX_DROP_UNUSABLE; | ||
591 | |||
592 | mmie = (struct ieee80211_mmie *) | ||
593 | (skb->data + skb->len - sizeof(*mmie)); | ||
594 | if (mmie->element_id != WLAN_EID_MMIE || | ||
595 | mmie->length != sizeof(*mmie) - 2) | ||
596 | return RX_DROP_UNUSABLE; /* Invalid MMIE */ | ||
597 | |||
598 | bip_ipn_swap(ipn, mmie->sequence_number); | ||
599 | |||
600 | if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) { | ||
601 | key->u.aes_cmac.replays++; | ||
602 | return RX_DROP_UNUSABLE; | ||
603 | } | ||
604 | |||
605 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { | ||
606 | /* hardware didn't decrypt/verify MIC */ | ||
607 | bip_aad(skb, aad); | ||
608 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, | ||
609 | key->u.aes_cmac.rx_crypto_buf, aad, | ||
610 | skb->data + 24, skb->len - 24, mic); | ||
611 | if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { | ||
612 | key->u.aes_cmac.icverrors++; | ||
613 | return RX_DROP_UNUSABLE; | ||
614 | } | ||
615 | } | ||
616 | |||
617 | memcpy(key->u.aes_cmac.rx_pn, ipn, 6); | ||
618 | |||
619 | /* Remove MMIE */ | ||
620 | skb_trim(skb, skb->len - sizeof(*mmie)); | ||
621 | |||
622 | return RX_CONTINUE; | ||
623 | } | ||
diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h index d42d221d8a1d..baba0608313e 100644 --- a/net/mac80211/wpa.h +++ b/net/mac80211/wpa.h | |||
@@ -28,4 +28,9 @@ ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx); | |||
28 | ieee80211_rx_result | 28 | ieee80211_rx_result |
29 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx); | 29 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx); |
30 | 30 | ||
31 | ieee80211_tx_result | ||
32 | ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx); | ||
33 | ieee80211_rx_result | ||
34 | ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx); | ||
35 | |||
31 | #endif /* WPA_H */ | 36 | #endif /* WPA_H */ |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 6be5d4efa51b..5c48378a852f 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -149,8 +149,8 @@ static struct task_struct *sync_backup_thread; | |||
149 | /* multicast addr */ | 149 | /* multicast addr */ |
150 | static struct sockaddr_in mcast_addr = { | 150 | static struct sockaddr_in mcast_addr = { |
151 | .sin_family = AF_INET, | 151 | .sin_family = AF_INET, |
152 | .sin_port = __constant_htons(IP_VS_SYNC_PORT), | 152 | .sin_port = cpu_to_be16(IP_VS_SYNC_PORT), |
153 | .sin_addr.s_addr = __constant_htonl(IP_VS_SYNC_GROUP), | 153 | .sin_addr.s_addr = cpu_to_be32(IP_VS_SYNC_GROUP), |
154 | }; | 154 | }; |
155 | 155 | ||
156 | 156 | ||
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 4f8fcf498545..07d9d8857e5d 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c | |||
@@ -177,7 +177,7 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { | |||
177 | .me = THIS_MODULE, | 177 | .me = THIS_MODULE, |
178 | .help = amanda_help, | 178 | .help = amanda_help, |
179 | .tuple.src.l3num = AF_INET, | 179 | .tuple.src.l3num = AF_INET, |
180 | .tuple.src.u.udp.port = __constant_htons(10080), | 180 | .tuple.src.u.udp.port = cpu_to_be16(10080), |
181 | .tuple.dst.protonum = IPPROTO_UDP, | 181 | .tuple.dst.protonum = IPPROTO_UDP, |
182 | .expect_policy = &amanda_exp_policy, | 182 | .expect_policy = &amanda_exp_policy, |
183 | }, | 183 | }, |
@@ -186,7 +186,7 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { | |||
186 | .me = THIS_MODULE, | 186 | .me = THIS_MODULE, |
187 | .help = amanda_help, | 187 | .help = amanda_help, |
188 | .tuple.src.l3num = AF_INET6, | 188 | .tuple.src.l3num = AF_INET6, |
189 | .tuple.src.u.udp.port = __constant_htons(10080), | 189 | .tuple.src.u.udp.port = cpu_to_be16(10080), |
190 | .tuple.dst.protonum = IPPROTO_UDP, | 190 | .tuple.dst.protonum = IPPROTO_UDP, |
191 | .expect_policy = &amanda_exp_policy, | 191 | .expect_policy = &amanda_exp_policy, |
192 | }, | 192 | }, |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 687bd633c3d7..66369490230e 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -1167,7 +1167,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { | |||
1167 | .name = "Q.931", | 1167 | .name = "Q.931", |
1168 | .me = THIS_MODULE, | 1168 | .me = THIS_MODULE, |
1169 | .tuple.src.l3num = AF_INET, | 1169 | .tuple.src.l3num = AF_INET, |
1170 | .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), | 1170 | .tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT), |
1171 | .tuple.dst.protonum = IPPROTO_TCP, | 1171 | .tuple.dst.protonum = IPPROTO_TCP, |
1172 | .help = q931_help, | 1172 | .help = q931_help, |
1173 | .expect_policy = &q931_exp_policy, | 1173 | .expect_policy = &q931_exp_policy, |
@@ -1176,7 +1176,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { | |||
1176 | .name = "Q.931", | 1176 | .name = "Q.931", |
1177 | .me = THIS_MODULE, | 1177 | .me = THIS_MODULE, |
1178 | .tuple.src.l3num = AF_INET6, | 1178 | .tuple.src.l3num = AF_INET6, |
1179 | .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), | 1179 | .tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT), |
1180 | .tuple.dst.protonum = IPPROTO_TCP, | 1180 | .tuple.dst.protonum = IPPROTO_TCP, |
1181 | .help = q931_help, | 1181 | .help = q931_help, |
1182 | .expect_policy = &q931_exp_policy, | 1182 | .expect_policy = &q931_exp_policy, |
@@ -1741,7 +1741,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { | |||
1741 | .name = "RAS", | 1741 | .name = "RAS", |
1742 | .me = THIS_MODULE, | 1742 | .me = THIS_MODULE, |
1743 | .tuple.src.l3num = AF_INET, | 1743 | .tuple.src.l3num = AF_INET, |
1744 | .tuple.src.u.udp.port = __constant_htons(RAS_PORT), | 1744 | .tuple.src.u.udp.port = cpu_to_be16(RAS_PORT), |
1745 | .tuple.dst.protonum = IPPROTO_UDP, | 1745 | .tuple.dst.protonum = IPPROTO_UDP, |
1746 | .help = ras_help, | 1746 | .help = ras_help, |
1747 | .expect_policy = &ras_exp_policy, | 1747 | .expect_policy = &ras_exp_policy, |
@@ -1750,7 +1750,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { | |||
1750 | .name = "RAS", | 1750 | .name = "RAS", |
1751 | .me = THIS_MODULE, | 1751 | .me = THIS_MODULE, |
1752 | .tuple.src.l3num = AF_INET6, | 1752 | .tuple.src.l3num = AF_INET6, |
1753 | .tuple.src.u.udp.port = __constant_htons(RAS_PORT), | 1753 | .tuple.src.u.udp.port = cpu_to_be16(RAS_PORT), |
1754 | .tuple.dst.protonum = IPPROTO_UDP, | 1754 | .tuple.dst.protonum = IPPROTO_UDP, |
1755 | .help = ras_help, | 1755 | .help = ras_help, |
1756 | .expect_policy = &ras_exp_policy, | 1756 | .expect_policy = &ras_exp_policy, |
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 5af4273b4668..8a3875e36ec2 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c | |||
@@ -105,7 +105,7 @@ static struct nf_conntrack_expect_policy exp_policy = { | |||
105 | static struct nf_conntrack_helper helper __read_mostly = { | 105 | static struct nf_conntrack_helper helper __read_mostly = { |
106 | .name = "netbios-ns", | 106 | .name = "netbios-ns", |
107 | .tuple.src.l3num = AF_INET, | 107 | .tuple.src.l3num = AF_INET, |
108 | .tuple.src.u.udp.port = __constant_htons(NMBD_PORT), | 108 | .tuple.src.u.udp.port = cpu_to_be16(NMBD_PORT), |
109 | .tuple.dst.protonum = IPPROTO_UDP, | 109 | .tuple.dst.protonum = IPPROTO_UDP, |
110 | .me = THIS_MODULE, | 110 | .me = THIS_MODULE, |
111 | .help = help, | 111 | .help = help, |
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 9e169ef2e854..72cca638a82d 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
@@ -591,7 +591,7 @@ static struct nf_conntrack_helper pptp __read_mostly = { | |||
591 | .name = "pptp", | 591 | .name = "pptp", |
592 | .me = THIS_MODULE, | 592 | .me = THIS_MODULE, |
593 | .tuple.src.l3num = AF_INET, | 593 | .tuple.src.l3num = AF_INET, |
594 | .tuple.src.u.tcp.port = __constant_htons(PPTP_CONTROL_PORT), | 594 | .tuple.src.u.tcp.port = cpu_to_be16(PPTP_CONTROL_PORT), |
595 | .tuple.dst.protonum = IPPROTO_TCP, | 595 | .tuple.dst.protonum = IPPROTO_TCP, |
596 | .help = conntrack_pptp_help, | 596 | .help = conntrack_pptp_help, |
597 | .destroy = pptp_destroy_siblings, | 597 | .destroy = pptp_destroy_siblings, |
diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c index cdc97f3105a3..5490fc37c92d 100644 --- a/net/netfilter/nf_tproxy_core.c +++ b/net/netfilter/nf_tproxy_core.c | |||
@@ -71,6 +71,7 @@ int | |||
71 | nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk) | 71 | nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk) |
72 | { | 72 | { |
73 | if (inet_sk(sk)->transparent) { | 73 | if (inet_sk(sk)->transparent) { |
74 | skb_orphan(skb); | ||
74 | skb->sk = sk; | 75 | skb->sk = sk; |
75 | skb->destructor = nf_tproxy_destructor; | 76 | skb->destructor = nf_tproxy_destructor; |
76 | return 1; | 77 | return 1; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9eb895c7a2a9..2760b62dc2c1 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -85,6 +85,7 @@ struct netlink_sock { | |||
85 | 85 | ||
86 | #define NETLINK_KERNEL_SOCKET 0x1 | 86 | #define NETLINK_KERNEL_SOCKET 0x1 |
87 | #define NETLINK_RECV_PKTINFO 0x2 | 87 | #define NETLINK_RECV_PKTINFO 0x2 |
88 | #define NETLINK_BROADCAST_SEND_ERROR 0x4 | ||
88 | 89 | ||
89 | static inline struct netlink_sock *nlk_sk(struct sock *sk) | 90 | static inline struct netlink_sock *nlk_sk(struct sock *sk) |
90 | { | 91 | { |
@@ -950,6 +951,7 @@ struct netlink_broadcast_data { | |||
950 | u32 pid; | 951 | u32 pid; |
951 | u32 group; | 952 | u32 group; |
952 | int failure; | 953 | int failure; |
954 | int delivery_failure; | ||
953 | int congested; | 955 | int congested; |
954 | int delivered; | 956 | int delivered; |
955 | gfp_t allocation; | 957 | gfp_t allocation; |
@@ -994,11 +996,15 @@ static inline int do_one_broadcast(struct sock *sk, | |||
994 | netlink_overrun(sk); | 996 | netlink_overrun(sk); |
995 | /* Clone failed. Notify ALL listeners. */ | 997 | /* Clone failed. Notify ALL listeners. */ |
996 | p->failure = 1; | 998 | p->failure = 1; |
999 | if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR) | ||
1000 | p->delivery_failure = 1; | ||
997 | } else if (sk_filter(sk, p->skb2)) { | 1001 | } else if (sk_filter(sk, p->skb2)) { |
998 | kfree_skb(p->skb2); | 1002 | kfree_skb(p->skb2); |
999 | p->skb2 = NULL; | 1003 | p->skb2 = NULL; |
1000 | } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) { | 1004 | } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) { |
1001 | netlink_overrun(sk); | 1005 | netlink_overrun(sk); |
1006 | if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR) | ||
1007 | p->delivery_failure = 1; | ||
1002 | } else { | 1008 | } else { |
1003 | p->congested |= val; | 1009 | p->congested |= val; |
1004 | p->delivered = 1; | 1010 | p->delivered = 1; |
@@ -1025,6 +1031,7 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
1025 | info.pid = pid; | 1031 | info.pid = pid; |
1026 | info.group = group; | 1032 | info.group = group; |
1027 | info.failure = 0; | 1033 | info.failure = 0; |
1034 | info.delivery_failure = 0; | ||
1028 | info.congested = 0; | 1035 | info.congested = 0; |
1029 | info.delivered = 0; | 1036 | info.delivered = 0; |
1030 | info.allocation = allocation; | 1037 | info.allocation = allocation; |
@@ -1045,13 +1052,14 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
1045 | if (info.skb2) | 1052 | if (info.skb2) |
1046 | kfree_skb(info.skb2); | 1053 | kfree_skb(info.skb2); |
1047 | 1054 | ||
1055 | if (info.delivery_failure) | ||
1056 | return -ENOBUFS; | ||
1057 | |||
1048 | if (info.delivered) { | 1058 | if (info.delivered) { |
1049 | if (info.congested && (allocation & __GFP_WAIT)) | 1059 | if (info.congested && (allocation & __GFP_WAIT)) |
1050 | yield(); | 1060 | yield(); |
1051 | return 0; | 1061 | return 0; |
1052 | } | 1062 | } |
1053 | if (info.failure) | ||
1054 | return -ENOBUFS; | ||
1055 | return -ESRCH; | 1063 | return -ESRCH; |
1056 | } | 1064 | } |
1057 | EXPORT_SYMBOL(netlink_broadcast); | 1065 | EXPORT_SYMBOL(netlink_broadcast); |
@@ -1159,6 +1167,13 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||
1159 | err = 0; | 1167 | err = 0; |
1160 | break; | 1168 | break; |
1161 | } | 1169 | } |
1170 | case NETLINK_BROADCAST_ERROR: | ||
1171 | if (val) | ||
1172 | nlk->flags |= NETLINK_BROADCAST_SEND_ERROR; | ||
1173 | else | ||
1174 | nlk->flags &= ~NETLINK_BROADCAST_SEND_ERROR; | ||
1175 | err = 0; | ||
1176 | break; | ||
1162 | default: | 1177 | default: |
1163 | err = -ENOPROTOOPT; | 1178 | err = -ENOPROTOOPT; |
1164 | } | 1179 | } |
@@ -1191,6 +1206,16 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, | |||
1191 | return -EFAULT; | 1206 | return -EFAULT; |
1192 | err = 0; | 1207 | err = 0; |
1193 | break; | 1208 | break; |
1209 | case NETLINK_BROADCAST_ERROR: | ||
1210 | if (len < sizeof(int)) | ||
1211 | return -EINVAL; | ||
1212 | len = sizeof(int); | ||
1213 | val = nlk->flags & NETLINK_BROADCAST_SEND_ERROR ? 1 : 0; | ||
1214 | if (put_user(len, optlen) || | ||
1215 | put_user(val, optval)) | ||
1216 | return -EFAULT; | ||
1217 | err = 0; | ||
1218 | break; | ||
1194 | default: | 1219 | default: |
1195 | err = -ENOPROTOOPT; | 1220 | err = -ENOPROTOOPT; |
1196 | } | 1221 | } |
@@ -1735,12 +1760,18 @@ int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid, | |||
1735 | exclude_pid = pid; | 1760 | exclude_pid = pid; |
1736 | } | 1761 | } |
1737 | 1762 | ||
1738 | /* errors reported via destination sk->sk_err */ | 1763 | /* errors reported via destination sk->sk_err, but propagate |
1739 | nlmsg_multicast(sk, skb, exclude_pid, group, flags); | 1764 | * delivery errors if NETLINK_BROADCAST_ERROR flag is set */ |
1765 | err = nlmsg_multicast(sk, skb, exclude_pid, group, flags); | ||
1740 | } | 1766 | } |
1741 | 1767 | ||
1742 | if (report) | 1768 | if (report) { |
1743 | err = nlmsg_unicast(sk, skb, pid); | 1769 | int err2; |
1770 | |||
1771 | err2 = nlmsg_unicast(sk, skb, pid); | ||
1772 | if (!err || err == -ESRCH) | ||
1773 | err = err2; | ||
1774 | } | ||
1744 | 1775 | ||
1745 | return err; | 1776 | return err; |
1746 | } | 1777 | } |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index e9c05b8f4f45..cba7849de98e 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -1432,7 +1432,7 @@ static int __init nr_proto_init(void) | |||
1432 | struct net_device *dev; | 1432 | struct net_device *dev; |
1433 | 1433 | ||
1434 | sprintf(name, "nr%d", i); | 1434 | sprintf(name, "nr%d", i); |
1435 | dev = alloc_netdev(sizeof(struct nr_private), name, nr_setup); | 1435 | dev = alloc_netdev(0, name, nr_setup); |
1436 | if (!dev) { | 1436 | if (!dev) { |
1437 | printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n"); | 1437 | printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n"); |
1438 | goto fail; | 1438 | goto fail; |
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 6caf459665f2..351372463fed 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c | |||
@@ -42,7 +42,7 @@ | |||
42 | 42 | ||
43 | int nr_rx_ip(struct sk_buff *skb, struct net_device *dev) | 43 | int nr_rx_ip(struct sk_buff *skb, struct net_device *dev) |
44 | { | 44 | { |
45 | struct net_device_stats *stats = netdev_priv(dev); | 45 | struct net_device_stats *stats = &dev->stats; |
46 | 46 | ||
47 | if (!netif_running(dev)) { | 47 | if (!netif_running(dev)) { |
48 | stats->rx_dropped++; | 48 | stats->rx_dropped++; |
@@ -171,8 +171,7 @@ static int nr_close(struct net_device *dev) | |||
171 | 171 | ||
172 | static int nr_xmit(struct sk_buff *skb, struct net_device *dev) | 172 | static int nr_xmit(struct sk_buff *skb, struct net_device *dev) |
173 | { | 173 | { |
174 | struct nr_private *nr = netdev_priv(dev); | 174 | struct net_device_stats *stats = &dev->stats; |
175 | struct net_device_stats *stats = &nr->stats; | ||
176 | unsigned int len = skb->len; | 175 | unsigned int len = skb->len; |
177 | 176 | ||
178 | if (!nr_route_frame(skb, NULL)) { | 177 | if (!nr_route_frame(skb, NULL)) { |
@@ -187,34 +186,27 @@ static int nr_xmit(struct sk_buff *skb, struct net_device *dev) | |||
187 | return 0; | 186 | return 0; |
188 | } | 187 | } |
189 | 188 | ||
190 | static struct net_device_stats *nr_get_stats(struct net_device *dev) | ||
191 | { | ||
192 | struct nr_private *nr = netdev_priv(dev); | ||
193 | |||
194 | return &nr->stats; | ||
195 | } | ||
196 | |||
197 | static const struct header_ops nr_header_ops = { | 189 | static const struct header_ops nr_header_ops = { |
198 | .create = nr_header, | 190 | .create = nr_header, |
199 | .rebuild= nr_rebuild_header, | 191 | .rebuild= nr_rebuild_header, |
200 | }; | 192 | }; |
201 | 193 | ||
194 | static const struct net_device_ops nr_netdev_ops = { | ||
195 | .ndo_open = nr_open, | ||
196 | .ndo_stop = nr_close, | ||
197 | .ndo_start_xmit = nr_xmit, | ||
198 | .ndo_set_mac_address = nr_set_mac_address, | ||
199 | }; | ||
202 | 200 | ||
203 | void nr_setup(struct net_device *dev) | 201 | void nr_setup(struct net_device *dev) |
204 | { | 202 | { |
205 | dev->mtu = NR_MAX_PACKET_SIZE; | 203 | dev->mtu = NR_MAX_PACKET_SIZE; |
206 | dev->hard_start_xmit = nr_xmit; | 204 | dev->netdev_ops = &nr_netdev_ops; |
207 | dev->open = nr_open; | ||
208 | dev->stop = nr_close; | ||
209 | |||
210 | dev->header_ops = &nr_header_ops; | 205 | dev->header_ops = &nr_header_ops; |
211 | dev->hard_header_len = NR_NETWORK_LEN + NR_TRANSPORT_LEN; | 206 | dev->hard_header_len = NR_NETWORK_LEN + NR_TRANSPORT_LEN; |
212 | dev->addr_len = AX25_ADDR_LEN; | 207 | dev->addr_len = AX25_ADDR_LEN; |
213 | dev->type = ARPHRD_NETROM; | 208 | dev->type = ARPHRD_NETROM; |
214 | dev->set_mac_address = nr_set_mac_address; | ||
215 | 209 | ||
216 | /* New-style flags. */ | 210 | /* New-style flags. */ |
217 | dev->flags = IFF_NOARP; | 211 | dev->flags = IFF_NOARP; |
218 | |||
219 | dev->get_stats = nr_get_stats; | ||
220 | } | 212 | } |
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 13cb323f8c38..81795ea87794 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c | |||
@@ -275,8 +275,6 @@ static inline int can_respond(struct sk_buff *skb) | |||
275 | return 0; | 275 | return 0; |
276 | 276 | ||
277 | ph = pn_hdr(skb); | 277 | ph = pn_hdr(skb); |
278 | if (phonet_address_get(skb->dev, ph->pn_rdev) != ph->pn_rdev) | ||
279 | return 0; /* we are not the destination */ | ||
280 | if (ph->pn_res == PN_PREFIX && !pskb_may_pull(skb, 5)) | 278 | if (ph->pn_res == PN_PREFIX && !pskb_may_pull(skb, 5)) |
281 | return 0; | 279 | return 0; |
282 | if (ph->pn_res == PN_COMMGR) /* indications */ | 280 | if (ph->pn_res == PN_COMMGR) /* indications */ |
@@ -344,8 +342,8 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, | |||
344 | struct packet_type *pkttype, | 342 | struct packet_type *pkttype, |
345 | struct net_device *orig_dev) | 343 | struct net_device *orig_dev) |
346 | { | 344 | { |
345 | struct net *net = dev_net(dev); | ||
347 | struct phonethdr *ph; | 346 | struct phonethdr *ph; |
348 | struct sock *sk; | ||
349 | struct sockaddr_pn sa; | 347 | struct sockaddr_pn sa; |
350 | u16 len; | 348 | u16 len; |
351 | 349 | ||
@@ -364,28 +362,28 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, | |||
364 | skb_reset_transport_header(skb); | 362 | skb_reset_transport_header(skb); |
365 | 363 | ||
366 | pn_skb_get_dst_sockaddr(skb, &sa); | 364 | pn_skb_get_dst_sockaddr(skb, &sa); |
367 | if (pn_sockaddr_get_addr(&sa) == 0) | ||
368 | goto out; /* currently, we cannot be device 0 */ | ||
369 | 365 | ||
370 | sk = pn_find_sock_by_sa(dev_net(dev), &sa); | 366 | /* check if we are the destination */ |
371 | if (sk == NULL) { | 367 | if (phonet_address_lookup(net, pn_sockaddr_get_addr(&sa)) == 0) { |
368 | /* Phonet packet input */ | ||
369 | struct sock *sk = pn_find_sock_by_sa(net, &sa); | ||
370 | |||
371 | if (sk) | ||
372 | return sk_receive_skb(sk, skb, 0); | ||
373 | |||
372 | if (can_respond(skb)) { | 374 | if (can_respond(skb)) { |
373 | send_obj_unreachable(skb); | 375 | send_obj_unreachable(skb); |
374 | send_reset_indications(skb); | 376 | send_reset_indications(skb); |
375 | } | 377 | } |
376 | goto out; | ||
377 | } | 378 | } |
378 | 379 | ||
379 | /* Push data to the socket (or other sockets connected to it). */ | ||
380 | return sk_receive_skb(sk, skb, 0); | ||
381 | |||
382 | out: | 380 | out: |
383 | kfree_skb(skb); | 381 | kfree_skb(skb); |
384 | return NET_RX_DROP; | 382 | return NET_RX_DROP; |
385 | } | 383 | } |
386 | 384 | ||
387 | static struct packet_type phonet_packet_type = { | 385 | static struct packet_type phonet_packet_type = { |
388 | .type = __constant_htons(ETH_P_PHONET), | 386 | .type = cpu_to_be16(ETH_P_PHONET), |
389 | .dev = NULL, | 387 | .dev = NULL, |
390 | .func = phonet_rcv, | 388 | .func = phonet_rcv, |
391 | }; | 389 | }; |
@@ -428,16 +426,18 @@ static int __init phonet_init(void) | |||
428 | { | 426 | { |
429 | int err; | 427 | int err; |
430 | 428 | ||
429 | err = phonet_device_init(); | ||
430 | if (err) | ||
431 | return err; | ||
432 | |||
431 | err = sock_register(&phonet_proto_family); | 433 | err = sock_register(&phonet_proto_family); |
432 | if (err) { | 434 | if (err) { |
433 | printk(KERN_ALERT | 435 | printk(KERN_ALERT |
434 | "phonet protocol family initialization failed\n"); | 436 | "phonet protocol family initialization failed\n"); |
435 | return err; | 437 | goto err_sock; |
436 | } | 438 | } |
437 | 439 | ||
438 | phonet_device_init(); | ||
439 | dev_add_pack(&phonet_packet_type); | 440 | dev_add_pack(&phonet_packet_type); |
440 | phonet_netlink_register(); | ||
441 | phonet_sysctl_init(); | 441 | phonet_sysctl_init(); |
442 | 442 | ||
443 | err = isi_register(); | 443 | err = isi_register(); |
@@ -449,6 +449,7 @@ err: | |||
449 | phonet_sysctl_exit(); | 449 | phonet_sysctl_exit(); |
450 | sock_unregister(PF_PHONET); | 450 | sock_unregister(PF_PHONET); |
451 | dev_remove_pack(&phonet_packet_type); | 451 | dev_remove_pack(&phonet_packet_type); |
452 | err_sock: | ||
452 | phonet_device_exit(); | 453 | phonet_device_exit(); |
453 | return err; | 454 | return err; |
454 | } | 455 | } |
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 5491bf5e354b..80a322d77909 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c | |||
@@ -28,32 +28,41 @@ | |||
28 | #include <linux/netdevice.h> | 28 | #include <linux/netdevice.h> |
29 | #include <linux/phonet.h> | 29 | #include <linux/phonet.h> |
30 | #include <net/sock.h> | 30 | #include <net/sock.h> |
31 | #include <net/netns/generic.h> | ||
31 | #include <net/phonet/pn_dev.h> | 32 | #include <net/phonet/pn_dev.h> |
32 | 33 | ||
33 | /* when accessing, remember to lock with spin_lock(&pndevs.lock); */ | 34 | struct phonet_net { |
34 | struct phonet_device_list pndevs = { | 35 | struct phonet_device_list pndevs; |
35 | .list = LIST_HEAD_INIT(pndevs.list), | ||
36 | .lock = __SPIN_LOCK_UNLOCKED(pndevs.lock), | ||
37 | }; | 36 | }; |
38 | 37 | ||
38 | int phonet_net_id; | ||
39 | |||
40 | struct phonet_device_list *phonet_device_list(struct net *net) | ||
41 | { | ||
42 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | ||
43 | return &pnn->pndevs; | ||
44 | } | ||
45 | |||
39 | /* Allocate new Phonet device. */ | 46 | /* Allocate new Phonet device. */ |
40 | static struct phonet_device *__phonet_device_alloc(struct net_device *dev) | 47 | static struct phonet_device *__phonet_device_alloc(struct net_device *dev) |
41 | { | 48 | { |
49 | struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); | ||
42 | struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC); | 50 | struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC); |
43 | if (pnd == NULL) | 51 | if (pnd == NULL) |
44 | return NULL; | 52 | return NULL; |
45 | pnd->netdev = dev; | 53 | pnd->netdev = dev; |
46 | bitmap_zero(pnd->addrs, 64); | 54 | bitmap_zero(pnd->addrs, 64); |
47 | 55 | ||
48 | list_add(&pnd->list, &pndevs.list); | 56 | list_add(&pnd->list, &pndevs->list); |
49 | return pnd; | 57 | return pnd; |
50 | } | 58 | } |
51 | 59 | ||
52 | static struct phonet_device *__phonet_get(struct net_device *dev) | 60 | static struct phonet_device *__phonet_get(struct net_device *dev) |
53 | { | 61 | { |
62 | struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); | ||
54 | struct phonet_device *pnd; | 63 | struct phonet_device *pnd; |
55 | 64 | ||
56 | list_for_each_entry(pnd, &pndevs.list, list) { | 65 | list_for_each_entry(pnd, &pndevs->list, list) { |
57 | if (pnd->netdev == dev) | 66 | if (pnd->netdev == dev) |
58 | return pnd; | 67 | return pnd; |
59 | } | 68 | } |
@@ -68,32 +77,33 @@ static void __phonet_device_free(struct phonet_device *pnd) | |||
68 | 77 | ||
69 | struct net_device *phonet_device_get(struct net *net) | 78 | struct net_device *phonet_device_get(struct net *net) |
70 | { | 79 | { |
80 | struct phonet_device_list *pndevs = phonet_device_list(net); | ||
71 | struct phonet_device *pnd; | 81 | struct phonet_device *pnd; |
72 | struct net_device *dev; | 82 | struct net_device *dev; |
73 | 83 | ||
74 | spin_lock_bh(&pndevs.lock); | 84 | spin_lock_bh(&pndevs->lock); |
75 | list_for_each_entry(pnd, &pndevs.list, list) { | 85 | list_for_each_entry(pnd, &pndevs->list, list) { |
76 | dev = pnd->netdev; | 86 | dev = pnd->netdev; |
77 | BUG_ON(!dev); | 87 | BUG_ON(!dev); |
78 | 88 | ||
79 | if (net_eq(dev_net(dev), net) && | 89 | if ((dev->reg_state == NETREG_REGISTERED) && |
80 | (dev->reg_state == NETREG_REGISTERED) && | ||
81 | ((pnd->netdev->flags & IFF_UP)) == IFF_UP) | 90 | ((pnd->netdev->flags & IFF_UP)) == IFF_UP) |
82 | break; | 91 | break; |
83 | dev = NULL; | 92 | dev = NULL; |
84 | } | 93 | } |
85 | if (dev) | 94 | if (dev) |
86 | dev_hold(dev); | 95 | dev_hold(dev); |
87 | spin_unlock_bh(&pndevs.lock); | 96 | spin_unlock_bh(&pndevs->lock); |
88 | return dev; | 97 | return dev; |
89 | } | 98 | } |
90 | 99 | ||
91 | int phonet_address_add(struct net_device *dev, u8 addr) | 100 | int phonet_address_add(struct net_device *dev, u8 addr) |
92 | { | 101 | { |
102 | struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); | ||
93 | struct phonet_device *pnd; | 103 | struct phonet_device *pnd; |
94 | int err = 0; | 104 | int err = 0; |
95 | 105 | ||
96 | spin_lock_bh(&pndevs.lock); | 106 | spin_lock_bh(&pndevs->lock); |
97 | /* Find or create Phonet-specific device data */ | 107 | /* Find or create Phonet-specific device data */ |
98 | pnd = __phonet_get(dev); | 108 | pnd = __phonet_get(dev); |
99 | if (pnd == NULL) | 109 | if (pnd == NULL) |
@@ -102,31 +112,33 @@ int phonet_address_add(struct net_device *dev, u8 addr) | |||
102 | err = -ENOMEM; | 112 | err = -ENOMEM; |
103 | else if (test_and_set_bit(addr >> 2, pnd->addrs)) | 113 | else if (test_and_set_bit(addr >> 2, pnd->addrs)) |
104 | err = -EEXIST; | 114 | err = -EEXIST; |
105 | spin_unlock_bh(&pndevs.lock); | 115 | spin_unlock_bh(&pndevs->lock); |
106 | return err; | 116 | return err; |
107 | } | 117 | } |
108 | 118 | ||
109 | int phonet_address_del(struct net_device *dev, u8 addr) | 119 | int phonet_address_del(struct net_device *dev, u8 addr) |
110 | { | 120 | { |
121 | struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); | ||
111 | struct phonet_device *pnd; | 122 | struct phonet_device *pnd; |
112 | int err = 0; | 123 | int err = 0; |
113 | 124 | ||
114 | spin_lock_bh(&pndevs.lock); | 125 | spin_lock_bh(&pndevs->lock); |
115 | pnd = __phonet_get(dev); | 126 | pnd = __phonet_get(dev); |
116 | if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) | 127 | if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) |
117 | err = -EADDRNOTAVAIL; | 128 | err = -EADDRNOTAVAIL; |
118 | else if (bitmap_empty(pnd->addrs, 64)) | 129 | else if (bitmap_empty(pnd->addrs, 64)) |
119 | __phonet_device_free(pnd); | 130 | __phonet_device_free(pnd); |
120 | spin_unlock_bh(&pndevs.lock); | 131 | spin_unlock_bh(&pndevs->lock); |
121 | return err; | 132 | return err; |
122 | } | 133 | } |
123 | 134 | ||
124 | /* Gets a source address toward a destination, through a interface. */ | 135 | /* Gets a source address toward a destination, through a interface. */ |
125 | u8 phonet_address_get(struct net_device *dev, u8 addr) | 136 | u8 phonet_address_get(struct net_device *dev, u8 addr) |
126 | { | 137 | { |
138 | struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); | ||
127 | struct phonet_device *pnd; | 139 | struct phonet_device *pnd; |
128 | 140 | ||
129 | spin_lock_bh(&pndevs.lock); | 141 | spin_lock_bh(&pndevs->lock); |
130 | pnd = __phonet_get(dev); | 142 | pnd = __phonet_get(dev); |
131 | if (pnd) { | 143 | if (pnd) { |
132 | BUG_ON(bitmap_empty(pnd->addrs, 64)); | 144 | BUG_ON(bitmap_empty(pnd->addrs, 64)); |
@@ -136,30 +148,31 @@ u8 phonet_address_get(struct net_device *dev, u8 addr) | |||
136 | addr = find_first_bit(pnd->addrs, 64) << 2; | 148 | addr = find_first_bit(pnd->addrs, 64) << 2; |
137 | } else | 149 | } else |
138 | addr = PN_NO_ADDR; | 150 | addr = PN_NO_ADDR; |
139 | spin_unlock_bh(&pndevs.lock); | 151 | spin_unlock_bh(&pndevs->lock); |
140 | return addr; | 152 | return addr; |
141 | } | 153 | } |
142 | 154 | ||
143 | int phonet_address_lookup(struct net *net, u8 addr) | 155 | int phonet_address_lookup(struct net *net, u8 addr) |
144 | { | 156 | { |
157 | struct phonet_device_list *pndevs = phonet_device_list(net); | ||
145 | struct phonet_device *pnd; | 158 | struct phonet_device *pnd; |
159 | int err = -EADDRNOTAVAIL; | ||
146 | 160 | ||
147 | spin_lock_bh(&pndevs.lock); | 161 | spin_lock_bh(&pndevs->lock); |
148 | list_for_each_entry(pnd, &pndevs.list, list) { | 162 | list_for_each_entry(pnd, &pndevs->list, list) { |
149 | if (!net_eq(dev_net(pnd->netdev), net)) | ||
150 | continue; | ||
151 | /* Don't allow unregistering devices! */ | 163 | /* Don't allow unregistering devices! */ |
152 | if ((pnd->netdev->reg_state != NETREG_REGISTERED) || | 164 | if ((pnd->netdev->reg_state != NETREG_REGISTERED) || |
153 | ((pnd->netdev->flags & IFF_UP)) != IFF_UP) | 165 | ((pnd->netdev->flags & IFF_UP)) != IFF_UP) |
154 | continue; | 166 | continue; |
155 | 167 | ||
156 | if (test_bit(addr >> 2, pnd->addrs)) { | 168 | if (test_bit(addr >> 2, pnd->addrs)) { |
157 | spin_unlock_bh(&pndevs.lock); | 169 | err = 0; |
158 | return 0; | 170 | goto found; |
159 | } | 171 | } |
160 | } | 172 | } |
161 | spin_unlock_bh(&pndevs.lock); | 173 | found: |
162 | return -EADDRNOTAVAIL; | 174 | spin_unlock_bh(&pndevs->lock); |
175 | return err; | ||
163 | } | 176 | } |
164 | 177 | ||
165 | /* notify Phonet of device events */ | 178 | /* notify Phonet of device events */ |
@@ -169,14 +182,16 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what, | |||
169 | struct net_device *dev = arg; | 182 | struct net_device *dev = arg; |
170 | 183 | ||
171 | if (what == NETDEV_UNREGISTER) { | 184 | if (what == NETDEV_UNREGISTER) { |
185 | struct phonet_device_list *pndevs; | ||
172 | struct phonet_device *pnd; | 186 | struct phonet_device *pnd; |
173 | 187 | ||
174 | /* Destroy phonet-specific device data */ | 188 | /* Destroy phonet-specific device data */ |
175 | spin_lock_bh(&pndevs.lock); | 189 | pndevs = phonet_device_list(dev_net(dev)); |
190 | spin_lock_bh(&pndevs->lock); | ||
176 | pnd = __phonet_get(dev); | 191 | pnd = __phonet_get(dev); |
177 | if (pnd) | 192 | if (pnd) |
178 | __phonet_device_free(pnd); | 193 | __phonet_device_free(pnd); |
179 | spin_unlock_bh(&pndevs.lock); | 194 | spin_unlock_bh(&pndevs->lock); |
180 | } | 195 | } |
181 | return 0; | 196 | return 0; |
182 | 197 | ||
@@ -187,24 +202,52 @@ static struct notifier_block phonet_device_notifier = { | |||
187 | .priority = 0, | 202 | .priority = 0, |
188 | }; | 203 | }; |
189 | 204 | ||
190 | /* Initialize Phonet devices list */ | 205 | /* Per-namespace Phonet devices handling */ |
191 | void phonet_device_init(void) | 206 | static int phonet_init_net(struct net *net) |
192 | { | 207 | { |
193 | register_netdevice_notifier(&phonet_device_notifier); | 208 | struct phonet_net *pnn = kmalloc(sizeof(*pnn), GFP_KERNEL); |
209 | if (!pnn) | ||
210 | return -ENOMEM; | ||
211 | |||
212 | INIT_LIST_HEAD(&pnn->pndevs.list); | ||
213 | spin_lock_init(&pnn->pndevs.lock); | ||
214 | net_assign_generic(net, phonet_net_id, pnn); | ||
215 | return 0; | ||
194 | } | 216 | } |
195 | 217 | ||
196 | void phonet_device_exit(void) | 218 | static void phonet_exit_net(struct net *net) |
197 | { | 219 | { |
220 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | ||
198 | struct phonet_device *pnd, *n; | 221 | struct phonet_device *pnd, *n; |
199 | 222 | ||
200 | rtnl_unregister_all(PF_PHONET); | 223 | list_for_each_entry_safe(pnd, n, &pnn->pndevs.list, list) |
201 | rtnl_lock(); | ||
202 | spin_lock_bh(&pndevs.lock); | ||
203 | |||
204 | list_for_each_entry_safe(pnd, n, &pndevs.list, list) | ||
205 | __phonet_device_free(pnd); | 224 | __phonet_device_free(pnd); |
206 | 225 | ||
207 | spin_unlock_bh(&pndevs.lock); | 226 | kfree(pnn); |
208 | rtnl_unlock(); | 227 | } |
228 | |||
229 | static struct pernet_operations phonet_net_ops = { | ||
230 | .init = phonet_init_net, | ||
231 | .exit = phonet_exit_net, | ||
232 | }; | ||
233 | |||
234 | /* Initialize Phonet devices list */ | ||
235 | int __init phonet_device_init(void) | ||
236 | { | ||
237 | int err = register_pernet_gen_device(&phonet_net_id, &phonet_net_ops); | ||
238 | if (err) | ||
239 | return err; | ||
240 | |||
241 | register_netdevice_notifier(&phonet_device_notifier); | ||
242 | err = phonet_netlink_register(); | ||
243 | if (err) | ||
244 | phonet_device_exit(); | ||
245 | return err; | ||
246 | } | ||
247 | |||
248 | void phonet_device_exit(void) | ||
249 | { | ||
250 | rtnl_unregister_all(PF_PHONET); | ||
209 | unregister_netdevice_notifier(&phonet_device_notifier); | 251 | unregister_netdevice_notifier(&phonet_device_notifier); |
252 | unregister_pernet_gen_device(phonet_net_id, &phonet_net_ops); | ||
210 | } | 253 | } |
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index 242fe8f8c322..cec4e5951681 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c | |||
@@ -47,8 +47,9 @@ static void rtmsg_notify(int event, struct net_device *dev, u8 addr) | |||
47 | kfree_skb(skb); | 47 | kfree_skb(skb); |
48 | goto errout; | 48 | goto errout; |
49 | } | 49 | } |
50 | err = rtnl_notify(skb, dev_net(dev), 0, | 50 | rtnl_notify(skb, dev_net(dev), 0, |
51 | RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL); | 51 | RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL); |
52 | return; | ||
52 | errout: | 53 | errout: |
53 | if (err < 0) | 54 | if (err < 0) |
54 | rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err); | 55 | rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err); |
@@ -123,17 +124,16 @@ nla_put_failure: | |||
123 | 124 | ||
124 | static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | 125 | static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) |
125 | { | 126 | { |
126 | struct net *net = sock_net(skb->sk); | 127 | struct phonet_device_list *pndevs; |
127 | struct phonet_device *pnd; | 128 | struct phonet_device *pnd; |
128 | int dev_idx = 0, dev_start_idx = cb->args[0]; | 129 | int dev_idx = 0, dev_start_idx = cb->args[0]; |
129 | int addr_idx = 0, addr_start_idx = cb->args[1]; | 130 | int addr_idx = 0, addr_start_idx = cb->args[1]; |
130 | 131 | ||
131 | spin_lock_bh(&pndevs.lock); | 132 | pndevs = phonet_device_list(sock_net(skb->sk)); |
132 | list_for_each_entry(pnd, &pndevs.list, list) { | 133 | spin_lock_bh(&pndevs->lock); |
134 | list_for_each_entry(pnd, &pndevs->list, list) { | ||
133 | u8 addr; | 135 | u8 addr; |
134 | 136 | ||
135 | if (!net_eq(dev_net(pnd->netdev), net)) | ||
136 | continue; | ||
137 | if (dev_idx > dev_start_idx) | 137 | if (dev_idx > dev_start_idx) |
138 | addr_start_idx = 0; | 138 | addr_start_idx = 0; |
139 | if (dev_idx++ < dev_start_idx) | 139 | if (dev_idx++ < dev_start_idx) |
@@ -153,16 +153,21 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | |||
153 | } | 153 | } |
154 | 154 | ||
155 | out: | 155 | out: |
156 | spin_unlock_bh(&pndevs.lock); | 156 | spin_unlock_bh(&pndevs->lock); |
157 | cb->args[0] = dev_idx; | 157 | cb->args[0] = dev_idx; |
158 | cb->args[1] = addr_idx; | 158 | cb->args[1] = addr_idx; |
159 | 159 | ||
160 | return skb->len; | 160 | return skb->len; |
161 | } | 161 | } |
162 | 162 | ||
163 | void __init phonet_netlink_register(void) | 163 | int __init phonet_netlink_register(void) |
164 | { | 164 | { |
165 | rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL); | 165 | int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL); |
166 | rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL); | 166 | if (err) |
167 | rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); | 167 | return err; |
168 | |||
169 | /* Further __rtnl_register() cannot fail */ | ||
170 | __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL); | ||
171 | __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); | ||
172 | return 0; | ||
168 | } | 173 | } |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 01392649b462..650139626581 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -1587,8 +1587,7 @@ static int __init rose_proto_init(void) | |||
1587 | char name[IFNAMSIZ]; | 1587 | char name[IFNAMSIZ]; |
1588 | 1588 | ||
1589 | sprintf(name, "rose%d", i); | 1589 | sprintf(name, "rose%d", i); |
1590 | dev = alloc_netdev(sizeof(struct net_device_stats), | 1590 | dev = alloc_netdev(0, name, rose_setup); |
1591 | name, rose_setup); | ||
1592 | if (!dev) { | 1591 | if (!dev) { |
1593 | printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n"); | 1592 | printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n"); |
1594 | rc = -ENOMEM; | 1593 | rc = -ENOMEM; |
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 12cfcf09556b..7dcf2569613b 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c | |||
@@ -57,7 +57,7 @@ static int rose_rebuild_header(struct sk_buff *skb) | |||
57 | { | 57 | { |
58 | #ifdef CONFIG_INET | 58 | #ifdef CONFIG_INET |
59 | struct net_device *dev = skb->dev; | 59 | struct net_device *dev = skb->dev; |
60 | struct net_device_stats *stats = netdev_priv(dev); | 60 | struct net_device_stats *stats = &dev->stats; |
61 | unsigned char *bp = (unsigned char *)skb->data; | 61 | unsigned char *bp = (unsigned char *)skb->data; |
62 | struct sk_buff *skbn; | 62 | struct sk_buff *skbn; |
63 | unsigned int len; | 63 | unsigned int len; |
@@ -133,7 +133,7 @@ static int rose_close(struct net_device *dev) | |||
133 | 133 | ||
134 | static int rose_xmit(struct sk_buff *skb, struct net_device *dev) | 134 | static int rose_xmit(struct sk_buff *skb, struct net_device *dev) |
135 | { | 135 | { |
136 | struct net_device_stats *stats = netdev_priv(dev); | 136 | struct net_device_stats *stats = &dev->stats; |
137 | 137 | ||
138 | if (!netif_running(dev)) { | 138 | if (!netif_running(dev)) { |
139 | printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n"); | 139 | printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n"); |
@@ -144,30 +144,28 @@ static int rose_xmit(struct sk_buff *skb, struct net_device *dev) | |||
144 | return 0; | 144 | return 0; |
145 | } | 145 | } |
146 | 146 | ||
147 | static struct net_device_stats *rose_get_stats(struct net_device *dev) | ||
148 | { | ||
149 | return netdev_priv(dev); | ||
150 | } | ||
151 | |||
152 | static const struct header_ops rose_header_ops = { | 147 | static const struct header_ops rose_header_ops = { |
153 | .create = rose_header, | 148 | .create = rose_header, |
154 | .rebuild= rose_rebuild_header, | 149 | .rebuild= rose_rebuild_header, |
155 | }; | 150 | }; |
156 | 151 | ||
152 | static const struct net_device_ops rose_netdev_ops = { | ||
153 | .ndo_open = rose_open, | ||
154 | .ndo_stop = rose_close, | ||
155 | .ndo_start_xmit = rose_xmit, | ||
156 | .ndo_set_mac_address = rose_set_mac_address, | ||
157 | }; | ||
158 | |||
157 | void rose_setup(struct net_device *dev) | 159 | void rose_setup(struct net_device *dev) |
158 | { | 160 | { |
159 | dev->mtu = ROSE_MAX_PACKET_SIZE - 2; | 161 | dev->mtu = ROSE_MAX_PACKET_SIZE - 2; |
160 | dev->hard_start_xmit = rose_xmit; | 162 | dev->netdev_ops = &rose_netdev_ops; |
161 | dev->open = rose_open; | ||
162 | dev->stop = rose_close; | ||
163 | 163 | ||
164 | dev->header_ops = &rose_header_ops; | 164 | dev->header_ops = &rose_header_ops; |
165 | dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN; | 165 | dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN; |
166 | dev->addr_len = ROSE_ADDR_LEN; | 166 | dev->addr_len = ROSE_ADDR_LEN; |
167 | dev->type = ARPHRD_ROSE; | 167 | dev->type = ARPHRD_ROSE; |
168 | dev->set_mac_address = rose_set_mac_address; | ||
169 | 168 | ||
170 | /* New-style flags. */ | 169 | /* New-style flags. */ |
171 | dev->flags = IFF_NOARP; | 170 | dev->flags = IFF_NOARP; |
172 | dev->get_stats = rose_get_stats; | ||
173 | } | 171 | } |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 0fc4a18fd96f..32009793307b 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -444,6 +444,17 @@ out: | |||
444 | } | 444 | } |
445 | EXPORT_SYMBOL(qdisc_calculate_pkt_len); | 445 | EXPORT_SYMBOL(qdisc_calculate_pkt_len); |
446 | 446 | ||
447 | void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc) | ||
448 | { | ||
449 | if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { | ||
450 | printk(KERN_WARNING | ||
451 | "%s: %s qdisc %X: is non-work-conserving?\n", | ||
452 | txt, qdisc->ops->id, qdisc->handle >> 16); | ||
453 | qdisc->flags |= TCQ_F_WARN_NONWC; | ||
454 | } | ||
455 | } | ||
456 | EXPORT_SYMBOL(qdisc_warn_nonwc); | ||
457 | |||
447 | static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | 458 | static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) |
448 | { | 459 | { |
449 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, | 460 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 45c31b1a4e1d..74226b265528 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -887,8 +887,7 @@ qdisc_peek_len(struct Qdisc *sch) | |||
887 | 887 | ||
888 | skb = sch->ops->peek(sch); | 888 | skb = sch->ops->peek(sch); |
889 | if (skb == NULL) { | 889 | if (skb == NULL) { |
890 | if (net_ratelimit()) | 890 | qdisc_warn_nonwc("qdisc_peek_len", sch); |
891 | printk("qdisc_peek_len: non work-conserving qdisc ?\n"); | ||
892 | return 0; | 891 | return 0; |
893 | } | 892 | } |
894 | len = qdisc_pkt_len(skb); | 893 | len = qdisc_pkt_len(skb); |
@@ -1642,8 +1641,7 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1642 | 1641 | ||
1643 | skb = qdisc_dequeue_peeked(cl->qdisc); | 1642 | skb = qdisc_dequeue_peeked(cl->qdisc); |
1644 | if (skb == NULL) { | 1643 | if (skb == NULL) { |
1645 | if (net_ratelimit()) | 1644 | qdisc_warn_nonwc("HFSC", cl->qdisc); |
1646 | printk("HFSC: Non-work-conserving qdisc ?\n"); | ||
1647 | return NULL; | 1645 | return NULL; |
1648 | } | 1646 | } |
1649 | 1647 | ||
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 2f0f0b04d3fb..355974f610c5 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/list.h> | 35 | #include <linux/list.h> |
36 | #include <linux/compiler.h> | 36 | #include <linux/compiler.h> |
37 | #include <linux/rbtree.h> | 37 | #include <linux/rbtree.h> |
38 | #include <linux/workqueue.h> | ||
38 | #include <net/netlink.h> | 39 | #include <net/netlink.h> |
39 | #include <net/pkt_sched.h> | 40 | #include <net/pkt_sched.h> |
40 | 41 | ||
@@ -114,8 +115,6 @@ struct htb_class { | |||
114 | struct tcf_proto *filter_list; | 115 | struct tcf_proto *filter_list; |
115 | int filter_cnt; | 116 | int filter_cnt; |
116 | 117 | ||
117 | int warned; /* only one warning about non work conserving .. */ | ||
118 | |||
119 | /* token bucket parameters */ | 118 | /* token bucket parameters */ |
120 | struct qdisc_rate_table *rate; /* rate table of the class itself */ | 119 | struct qdisc_rate_table *rate; /* rate table of the class itself */ |
121 | struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */ | 120 | struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */ |
@@ -155,6 +154,10 @@ struct htb_sched { | |||
155 | int direct_qlen; /* max qlen of above */ | 154 | int direct_qlen; /* max qlen of above */ |
156 | 155 | ||
157 | long direct_pkts; | 156 | long direct_pkts; |
157 | |||
158 | #define HTB_WARN_TOOMANYEVENTS 0x1 | ||
159 | unsigned int warned; /* only one warning */ | ||
160 | struct work_struct work; | ||
158 | }; | 161 | }; |
159 | 162 | ||
160 | /* find class in global hash table using given handle */ | 163 | /* find class in global hash table using given handle */ |
@@ -658,7 +661,7 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, | |||
658 | * htb_do_events - make mode changes to classes at the level | 661 | * htb_do_events - make mode changes to classes at the level |
659 | * | 662 | * |
660 | * Scans event queue for pending events and applies them. Returns time of | 663 | * Scans event queue for pending events and applies them. Returns time of |
661 | * next pending event (0 for no event in pq). | 664 | * next pending event (0 for no event in pq, q->now for too many events). |
662 | * Note: Applied are events whose have cl->pq_key <= q->now. | 665 | * Note: Applied are events whose have cl->pq_key <= q->now. |
663 | */ | 666 | */ |
664 | static psched_time_t htb_do_events(struct htb_sched *q, int level, | 667 | static psched_time_t htb_do_events(struct htb_sched *q, int level, |
@@ -686,8 +689,14 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level, | |||
686 | if (cl->cmode != HTB_CAN_SEND) | 689 | if (cl->cmode != HTB_CAN_SEND) |
687 | htb_add_to_wait_tree(q, cl, diff); | 690 | htb_add_to_wait_tree(q, cl, diff); |
688 | } | 691 | } |
689 | /* too much load - let's continue on next jiffie (including above) */ | 692 | |
690 | return q->now + 2 * PSCHED_TICKS_PER_SEC / HZ; | 693 | /* too much load - let's continue after a break for scheduling */ |
694 | if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) { | ||
695 | printk(KERN_WARNING "htb: too many events!\n"); | ||
696 | q->warned |= HTB_WARN_TOOMANYEVENTS; | ||
697 | } | ||
698 | |||
699 | return q->now; | ||
691 | } | 700 | } |
692 | 701 | ||
693 | /* Returns class->node+prio from id-tree where classe's id is >= id. NULL | 702 | /* Returns class->node+prio from id-tree where classe's id is >= id. NULL |
@@ -809,13 +818,8 @@ next: | |||
809 | skb = cl->un.leaf.q->dequeue(cl->un.leaf.q); | 818 | skb = cl->un.leaf.q->dequeue(cl->un.leaf.q); |
810 | if (likely(skb != NULL)) | 819 | if (likely(skb != NULL)) |
811 | break; | 820 | break; |
812 | if (!cl->warned) { | ||
813 | printk(KERN_WARNING | ||
814 | "htb: class %X isn't work conserving ?!\n", | ||
815 | cl->common.classid); | ||
816 | cl->warned = 1; | ||
817 | } | ||
818 | 821 | ||
822 | qdisc_warn_nonwc("htb", cl->un.leaf.q); | ||
819 | htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> | 823 | htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> |
820 | ptr[0]) + prio); | 824 | ptr[0]) + prio); |
821 | cl = htb_lookup_leaf(q->row[level] + prio, prio, | 825 | cl = htb_lookup_leaf(q->row[level] + prio, prio, |
@@ -892,7 +896,10 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) | |||
892 | } | 896 | } |
893 | } | 897 | } |
894 | sch->qstats.overlimits++; | 898 | sch->qstats.overlimits++; |
895 | qdisc_watchdog_schedule(&q->watchdog, next_event); | 899 | if (likely(next_event > q->now)) |
900 | qdisc_watchdog_schedule(&q->watchdog, next_event); | ||
901 | else | ||
902 | schedule_work(&q->work); | ||
896 | fin: | 903 | fin: |
897 | return skb; | 904 | return skb; |
898 | } | 905 | } |
@@ -962,6 +969,14 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = { | |||
962 | [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, | 969 | [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, |
963 | }; | 970 | }; |
964 | 971 | ||
972 | static void htb_work_func(struct work_struct *work) | ||
973 | { | ||
974 | struct htb_sched *q = container_of(work, struct htb_sched, work); | ||
975 | struct Qdisc *sch = q->watchdog.qdisc; | ||
976 | |||
977 | __netif_schedule(qdisc_root(sch)); | ||
978 | } | ||
979 | |||
965 | static int htb_init(struct Qdisc *sch, struct nlattr *opt) | 980 | static int htb_init(struct Qdisc *sch, struct nlattr *opt) |
966 | { | 981 | { |
967 | struct htb_sched *q = qdisc_priv(sch); | 982 | struct htb_sched *q = qdisc_priv(sch); |
@@ -996,6 +1011,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt) | |||
996 | INIT_LIST_HEAD(q->drops + i); | 1011 | INIT_LIST_HEAD(q->drops + i); |
997 | 1012 | ||
998 | qdisc_watchdog_init(&q->watchdog, sch); | 1013 | qdisc_watchdog_init(&q->watchdog, sch); |
1014 | INIT_WORK(&q->work, htb_work_func); | ||
999 | skb_queue_head_init(&q->direct_queue); | 1015 | skb_queue_head_init(&q->direct_queue); |
1000 | 1016 | ||
1001 | q->direct_qlen = qdisc_dev(sch)->tx_queue_len; | 1017 | q->direct_qlen = qdisc_dev(sch)->tx_queue_len; |
@@ -1188,7 +1204,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) | |||
1188 | kfree(cl); | 1204 | kfree(cl); |
1189 | } | 1205 | } |
1190 | 1206 | ||
1191 | /* always caled under BH & queue lock */ | ||
1192 | static void htb_destroy(struct Qdisc *sch) | 1207 | static void htb_destroy(struct Qdisc *sch) |
1193 | { | 1208 | { |
1194 | struct htb_sched *q = qdisc_priv(sch); | 1209 | struct htb_sched *q = qdisc_priv(sch); |
@@ -1196,6 +1211,7 @@ static void htb_destroy(struct Qdisc *sch) | |||
1196 | struct htb_class *cl; | 1211 | struct htb_class *cl; |
1197 | unsigned int i; | 1212 | unsigned int i; |
1198 | 1213 | ||
1214 | cancel_work_sync(&q->work); | ||
1199 | qdisc_watchdog_cancel(&q->watchdog); | 1215 | qdisc_watchdog_cancel(&q->watchdog); |
1200 | /* This line used to be after htb_destroy_class call below | 1216 | /* This line used to be after htb_destroy_class call below |
1201 | and surprisingly it worked in 2.4. But it must precede it | 1217 | and surprisingly it worked in 2.4. But it must precede it |
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 7e151861794b..912731203047 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c | |||
@@ -202,7 +202,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt) | |||
202 | int i; | 202 | int i; |
203 | 203 | ||
204 | if (!netif_is_multiqueue(qdisc_dev(sch))) | 204 | if (!netif_is_multiqueue(qdisc_dev(sch))) |
205 | return -EINVAL; | 205 | return -EOPNOTSUPP; |
206 | if (nla_len(opt) < sizeof(*qopt)) | 206 | if (nla_len(opt) < sizeof(*qopt)) |
207 | return -EINVAL; | 207 | return -EINVAL; |
208 | 208 | ||
diff --git a/net/sctp/input.c b/net/sctp/input.c index 2e4a8646dbc3..d2e98803ffe3 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -83,14 +83,15 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb) | |||
83 | { | 83 | { |
84 | struct sk_buff *list = skb_shinfo(skb)->frag_list; | 84 | struct sk_buff *list = skb_shinfo(skb)->frag_list; |
85 | struct sctphdr *sh = sctp_hdr(skb); | 85 | struct sctphdr *sh = sctp_hdr(skb); |
86 | __be32 cmp = sh->checksum; | 86 | __le32 cmp = sh->checksum; |
87 | __be32 val = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); | 87 | __le32 val; |
88 | __u32 tmp = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); | ||
88 | 89 | ||
89 | for (; list; list = list->next) | 90 | for (; list; list = list->next) |
90 | val = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), | 91 | tmp = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), |
91 | val); | 92 | tmp); |
92 | 93 | ||
93 | val = sctp_end_cksum(val); | 94 | val = sctp_end_cksum(tmp); |
94 | 95 | ||
95 | if (val != cmp) { | 96 | if (val != cmp) { |
96 | /* CRC failure, dump it. */ | 97 | /* CRC failure, dump it. */ |
@@ -142,7 +143,8 @@ int sctp_rcv(struct sk_buff *skb) | |||
142 | __skb_pull(skb, skb_transport_offset(skb)); | 143 | __skb_pull(skb, skb_transport_offset(skb)); |
143 | if (skb->len < sizeof(struct sctphdr)) | 144 | if (skb->len < sizeof(struct sctphdr)) |
144 | goto discard_it; | 145 | goto discard_it; |
145 | if (!skb_csum_unnecessary(skb) && sctp_rcv_checksum(skb) < 0) | 146 | if (!sctp_checksum_disable && !skb_csum_unnecessary(skb) && |
147 | sctp_rcv_checksum(skb) < 0) | ||
146 | goto discard_it; | 148 | goto discard_it; |
147 | 149 | ||
148 | skb_pull(skb, sizeof(struct sctphdr)); | 150 | skb_pull(skb, sizeof(struct sctphdr)); |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index ceaa4aa066ea..a63de3f7f185 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -97,8 +97,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, | |||
97 | if (addr) { | 97 | if (addr) { |
98 | addr->a.v6.sin6_family = AF_INET6; | 98 | addr->a.v6.sin6_family = AF_INET6; |
99 | addr->a.v6.sin6_port = 0; | 99 | addr->a.v6.sin6_port = 0; |
100 | memcpy(&addr->a.v6.sin6_addr, &ifa->addr, | 100 | ipv6_addr_copy(&addr->a.v6.sin6_addr, &ifa->addr); |
101 | sizeof(struct in6_addr)); | ||
102 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; | 101 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; |
103 | addr->valid = 1; | 102 | addr->valid = 1; |
104 | spin_lock_bh(&sctp_local_addr_lock); | 103 | spin_lock_bh(&sctp_local_addr_lock); |
@@ -628,9 +627,7 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr) | |||
628 | static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | 627 | static struct sock *sctp_v6_create_accept_sk(struct sock *sk, |
629 | struct sctp_association *asoc) | 628 | struct sctp_association *asoc) |
630 | { | 629 | { |
631 | struct inet_sock *inet = inet_sk(sk); | ||
632 | struct sock *newsk; | 630 | struct sock *newsk; |
633 | struct inet_sock *newinet; | ||
634 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); | 631 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); |
635 | struct sctp6_sock *newsctp6sk; | 632 | struct sctp6_sock *newsctp6sk; |
636 | 633 | ||
@@ -640,17 +637,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
640 | 637 | ||
641 | sock_init_data(NULL, newsk); | 638 | sock_init_data(NULL, newsk); |
642 | 639 | ||
643 | newsk->sk_type = SOCK_STREAM; | 640 | sctp_copy_sock(newsk, sk, asoc); |
644 | |||
645 | newsk->sk_prot = sk->sk_prot; | ||
646 | newsk->sk_no_check = sk->sk_no_check; | ||
647 | newsk->sk_reuse = sk->sk_reuse; | ||
648 | |||
649 | newsk->sk_destruct = inet_sock_destruct; | ||
650 | newsk->sk_family = PF_INET6; | ||
651 | newsk->sk_protocol = IPPROTO_SCTP; | ||
652 | newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | ||
653 | newsk->sk_shutdown = sk->sk_shutdown; | ||
654 | sock_reset_flag(sk, SOCK_ZAPPED); | 641 | sock_reset_flag(sk, SOCK_ZAPPED); |
655 | 642 | ||
656 | newsctp6sk = (struct sctp6_sock *)newsk; | 643 | newsctp6sk = (struct sctp6_sock *)newsk; |
@@ -658,7 +645,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
658 | 645 | ||
659 | sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped; | 646 | sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped; |
660 | 647 | ||
661 | newinet = inet_sk(newsk); | ||
662 | newnp = inet6_sk(newsk); | 648 | newnp = inet6_sk(newsk); |
663 | 649 | ||
664 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); | 650 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); |
@@ -666,26 +652,8 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
666 | /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() | 652 | /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() |
667 | * and getpeername(). | 653 | * and getpeername(). |
668 | */ | 654 | */ |
669 | newinet->sport = inet->sport; | ||
670 | newnp->saddr = np->saddr; | ||
671 | newnp->rcv_saddr = np->rcv_saddr; | ||
672 | newinet->dport = htons(asoc->peer.port); | ||
673 | sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); | 655 | sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); |
674 | 656 | ||
675 | /* Init the ipv4 part of the socket since we can have sockets | ||
676 | * using v6 API for ipv4. | ||
677 | */ | ||
678 | newinet->uc_ttl = -1; | ||
679 | newinet->mc_loop = 1; | ||
680 | newinet->mc_ttl = 1; | ||
681 | newinet->mc_index = 0; | ||
682 | newinet->mc_list = NULL; | ||
683 | |||
684 | if (ipv4_config.no_pmtu_disc) | ||
685 | newinet->pmtudisc = IP_PMTUDISC_DONT; | ||
686 | else | ||
687 | newinet->pmtudisc = IP_PMTUDISC_WANT; | ||
688 | |||
689 | sk_refcnt_debug_inc(newsk); | 657 | sk_refcnt_debug_inc(newsk); |
690 | 658 | ||
691 | if (newsk->sk_prot->init(newsk)) { | 659 | if (newsk->sk_prot->init(newsk)) { |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 73639355157e..07d58903a746 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -367,7 +367,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
367 | struct sctp_transport *tp = packet->transport; | 367 | struct sctp_transport *tp = packet->transport; |
368 | struct sctp_association *asoc = tp->asoc; | 368 | struct sctp_association *asoc = tp->asoc; |
369 | struct sctphdr *sh; | 369 | struct sctphdr *sh; |
370 | __be32 crc32 = __constant_cpu_to_be32(0); | ||
371 | struct sk_buff *nskb; | 370 | struct sk_buff *nskb; |
372 | struct sctp_chunk *chunk, *tmp; | 371 | struct sctp_chunk *chunk, *tmp; |
373 | struct sock *sk; | 372 | struct sock *sk; |
@@ -531,17 +530,16 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
531 | * Note: Adler-32 is no longer applicable, as has been replaced | 530 | * Note: Adler-32 is no longer applicable, as has been replaced |
532 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. | 531 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. |
533 | */ | 532 | */ |
534 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) { | 533 | if (!sctp_checksum_disable && !(dst->dev->features & NETIF_F_NO_CSUM)) { |
535 | crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); | 534 | __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); |
536 | crc32 = sctp_end_cksum(crc32); | 535 | |
536 | /* 3) Put the resultant value into the checksum field in the | ||
537 | * common header, and leave the rest of the bits unchanged. | ||
538 | */ | ||
539 | sh->checksum = sctp_end_cksum(crc32); | ||
537 | } else | 540 | } else |
538 | nskb->ip_summed = CHECKSUM_UNNECESSARY; | 541 | nskb->ip_summed = CHECKSUM_UNNECESSARY; |
539 | 542 | ||
540 | /* 3) Put the resultant value into the checksum field in the | ||
541 | * common header, and leave the rest of the bits unchanged. | ||
542 | */ | ||
543 | sh->checksum = crc32; | ||
544 | |||
545 | /* IP layer ECN support | 543 | /* IP layer ECN support |
546 | * From RFC 2481 | 544 | * From RFC 2481 |
547 | * "The ECN-Capable Transport (ECT) bit would be set by the | 545 | * "The ECN-Capable Transport (ECT) bit would be set by the |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index b78e3be69013..c1e316ee7155 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -589,46 +589,21 @@ static int sctp_v4_is_ce(const struct sk_buff *skb) | |||
589 | static struct sock *sctp_v4_create_accept_sk(struct sock *sk, | 589 | static struct sock *sctp_v4_create_accept_sk(struct sock *sk, |
590 | struct sctp_association *asoc) | 590 | struct sctp_association *asoc) |
591 | { | 591 | { |
592 | struct inet_sock *inet = inet_sk(sk); | ||
593 | struct inet_sock *newinet; | ||
594 | struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL, | 592 | struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL, |
595 | sk->sk_prot); | 593 | sk->sk_prot); |
594 | struct inet_sock *newinet; | ||
596 | 595 | ||
597 | if (!newsk) | 596 | if (!newsk) |
598 | goto out; | 597 | goto out; |
599 | 598 | ||
600 | sock_init_data(NULL, newsk); | 599 | sock_init_data(NULL, newsk); |
601 | 600 | ||
602 | newsk->sk_type = SOCK_STREAM; | 601 | sctp_copy_sock(newsk, sk, asoc); |
603 | |||
604 | newsk->sk_no_check = sk->sk_no_check; | ||
605 | newsk->sk_reuse = sk->sk_reuse; | ||
606 | newsk->sk_shutdown = sk->sk_shutdown; | ||
607 | |||
608 | newsk->sk_destruct = inet_sock_destruct; | ||
609 | newsk->sk_family = PF_INET; | ||
610 | newsk->sk_protocol = IPPROTO_SCTP; | ||
611 | newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | ||
612 | sock_reset_flag(newsk, SOCK_ZAPPED); | 602 | sock_reset_flag(newsk, SOCK_ZAPPED); |
613 | 603 | ||
614 | newinet = inet_sk(newsk); | 604 | newinet = inet_sk(newsk); |
615 | 605 | ||
616 | /* Initialize sk's sport, dport, rcv_saddr and daddr for | ||
617 | * getsockname() and getpeername() | ||
618 | */ | ||
619 | newinet->sport = inet->sport; | ||
620 | newinet->saddr = inet->saddr; | ||
621 | newinet->rcv_saddr = inet->rcv_saddr; | ||
622 | newinet->dport = htons(asoc->peer.port); | ||
623 | newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; | 606 | newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; |
624 | newinet->pmtudisc = inet->pmtudisc; | ||
625 | newinet->id = asoc->next_tsn ^ jiffies; | ||
626 | |||
627 | newinet->uc_ttl = -1; | ||
628 | newinet->mc_loop = 1; | ||
629 | newinet->mc_ttl = 1; | ||
630 | newinet->mc_index = 0; | ||
631 | newinet->mc_list = NULL; | ||
632 | 607 | ||
633 | sk_refcnt_debug_inc(newsk); | 608 | sk_refcnt_debug_inc(newsk); |
634 | 609 | ||
@@ -1411,4 +1386,6 @@ MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132"); | |||
1411 | MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132"); | 1386 | MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132"); |
1412 | MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>"); | 1387 | MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>"); |
1413 | MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)"); | 1388 | MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)"); |
1389 | module_param_named(no_checksums, sctp_checksum_disable, bool, 0644); | ||
1390 | MODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification"); | ||
1414 | MODULE_LICENSE("GPL"); | 1391 | MODULE_LICENSE("GPL"); |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index fd8acb48c3f2..b40e95f9851b 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -100,11 +100,11 @@ int sctp_chunk_iif(const struct sctp_chunk *chunk) | |||
100 | */ | 100 | */ |
101 | static const struct sctp_paramhdr ecap_param = { | 101 | static const struct sctp_paramhdr ecap_param = { |
102 | SCTP_PARAM_ECN_CAPABLE, | 102 | SCTP_PARAM_ECN_CAPABLE, |
103 | __constant_htons(sizeof(struct sctp_paramhdr)), | 103 | cpu_to_be16(sizeof(struct sctp_paramhdr)), |
104 | }; | 104 | }; |
105 | static const struct sctp_paramhdr prsctp_param = { | 105 | static const struct sctp_paramhdr prsctp_param = { |
106 | SCTP_PARAM_FWD_TSN_SUPPORT, | 106 | SCTP_PARAM_FWD_TSN_SUPPORT, |
107 | __constant_htons(sizeof(struct sctp_paramhdr)), | 107 | cpu_to_be16(sizeof(struct sctp_paramhdr)), |
108 | }; | 108 | }; |
109 | 109 | ||
110 | /* A helper to initialize to initialize an op error inside a | 110 | /* A helper to initialize to initialize an op error inside a |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index e1d6076b4f59..0146cfb1f182 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -461,9 +461,15 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
461 | * expires, set RTO <- RTO * 2 ("back off the timer"). The | 461 | * expires, set RTO <- RTO * 2 ("back off the timer"). The |
462 | * maximum value discussed in rule C7 above (RTO.max) may be | 462 | * maximum value discussed in rule C7 above (RTO.max) may be |
463 | * used to provide an upper bound to this doubling operation. | 463 | * used to provide an upper bound to this doubling operation. |
464 | * | ||
465 | * Special Case: the first HB doesn't trigger exponential backoff. | ||
466 | * The first unacknowleged HB triggers it. We do this with a flag | ||
467 | * that indicates that we have an outstanding HB. | ||
464 | */ | 468 | */ |
465 | transport->last_rto = transport->rto; | 469 | if (transport->hb_sent) { |
466 | transport->rto = min((transport->rto * 2), transport->asoc->rto_max); | 470 | transport->last_rto = transport->rto; |
471 | transport->rto = min((transport->rto * 2), transport->asoc->rto_max); | ||
472 | } | ||
467 | } | 473 | } |
468 | 474 | ||
469 | /* Worker routine to handle INIT command failure. */ | 475 | /* Worker routine to handle INIT command failure. */ |
@@ -621,6 +627,11 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
621 | t->error_count = 0; | 627 | t->error_count = 0; |
622 | t->asoc->overall_error_count = 0; | 628 | t->asoc->overall_error_count = 0; |
623 | 629 | ||
630 | /* Clear the hb_sent flag to signal that we had a good | ||
631 | * acknowledgement. | ||
632 | */ | ||
633 | t->hb_sent = 0; | ||
634 | |||
624 | /* Mark the destination transport address as active if it is not so | 635 | /* Mark the destination transport address as active if it is not so |
625 | * marked. | 636 | * marked. |
626 | */ | 637 | */ |
@@ -657,6 +668,8 @@ static void sctp_cmd_transport_reset(sctp_cmd_seq_t *cmds, | |||
657 | 668 | ||
658 | /* Mark one strike against a transport. */ | 669 | /* Mark one strike against a transport. */ |
659 | sctp_do_8_2_transport_strike(asoc, t); | 670 | sctp_do_8_2_transport_strike(asoc, t); |
671 | |||
672 | t->hb_sent = 1; | ||
660 | } | 673 | } |
661 | 674 | ||
662 | /* Helper function to process the process SACK command. */ | 675 | /* Helper function to process the process SACK command. */ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ff0a8f88de04..dea864f5de54 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -3939,7 +3939,6 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, | |||
3939 | { | 3939 | { |
3940 | struct sock *sk = asoc->base.sk; | 3940 | struct sock *sk = asoc->base.sk; |
3941 | struct socket *sock; | 3941 | struct socket *sock; |
3942 | struct inet_sock *inetsk; | ||
3943 | struct sctp_af *af; | 3942 | struct sctp_af *af; |
3944 | int err = 0; | 3943 | int err = 0; |
3945 | 3944 | ||
@@ -3954,18 +3953,18 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, | |||
3954 | if (err < 0) | 3953 | if (err < 0) |
3955 | return err; | 3954 | return err; |
3956 | 3955 | ||
3957 | /* Populate the fields of the newsk from the oldsk and migrate the | 3956 | sctp_copy_sock(sock->sk, sk, asoc); |
3958 | * asoc to the newsk. | ||
3959 | */ | ||
3960 | sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); | ||
3961 | 3957 | ||
3962 | /* Make peeled-off sockets more like 1-1 accepted sockets. | 3958 | /* Make peeled-off sockets more like 1-1 accepted sockets. |
3963 | * Set the daddr and initialize id to something more random | 3959 | * Set the daddr and initialize id to something more random |
3964 | */ | 3960 | */ |
3965 | af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); | 3961 | af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); |
3966 | af->to_sk_daddr(&asoc->peer.primary_addr, sk); | 3962 | af->to_sk_daddr(&asoc->peer.primary_addr, sk); |
3967 | inetsk = inet_sk(sock->sk); | 3963 | |
3968 | inetsk->id = asoc->next_tsn ^ jiffies; | 3964 | /* Populate the fields of the newsk from the oldsk and migrate the |
3965 | * asoc to the newsk. | ||
3966 | */ | ||
3967 | sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); | ||
3969 | 3968 | ||
3970 | *sockp = sock; | 3969 | *sockp = sock; |
3971 | 3970 | ||
@@ -6700,6 +6699,48 @@ done: | |||
6700 | sctp_skb_set_owner_r(skb, sk); | 6699 | sctp_skb_set_owner_r(skb, sk); |
6701 | } | 6700 | } |
6702 | 6701 | ||
6702 | void sctp_copy_sock(struct sock *newsk, struct sock *sk, | ||
6703 | struct sctp_association *asoc) | ||
6704 | { | ||
6705 | struct inet_sock *inet = inet_sk(sk); | ||
6706 | struct inet_sock *newinet = inet_sk(newsk); | ||
6707 | |||
6708 | newsk->sk_type = sk->sk_type; | ||
6709 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; | ||
6710 | newsk->sk_flags = sk->sk_flags; | ||
6711 | newsk->sk_no_check = sk->sk_no_check; | ||
6712 | newsk->sk_reuse = sk->sk_reuse; | ||
6713 | |||
6714 | newsk->sk_shutdown = sk->sk_shutdown; | ||
6715 | newsk->sk_destruct = inet_sock_destruct; | ||
6716 | newsk->sk_family = sk->sk_family; | ||
6717 | newsk->sk_protocol = IPPROTO_SCTP; | ||
6718 | newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | ||
6719 | newsk->sk_sndbuf = sk->sk_sndbuf; | ||
6720 | newsk->sk_rcvbuf = sk->sk_rcvbuf; | ||
6721 | newsk->sk_lingertime = sk->sk_lingertime; | ||
6722 | newsk->sk_rcvtimeo = sk->sk_rcvtimeo; | ||
6723 | newsk->sk_sndtimeo = sk->sk_sndtimeo; | ||
6724 | |||
6725 | newinet = inet_sk(newsk); | ||
6726 | |||
6727 | /* Initialize sk's sport, dport, rcv_saddr and daddr for | ||
6728 | * getsockname() and getpeername() | ||
6729 | */ | ||
6730 | newinet->sport = inet->sport; | ||
6731 | newinet->saddr = inet->saddr; | ||
6732 | newinet->rcv_saddr = inet->rcv_saddr; | ||
6733 | newinet->dport = htons(asoc->peer.port); | ||
6734 | newinet->pmtudisc = inet->pmtudisc; | ||
6735 | newinet->id = asoc->next_tsn ^ jiffies; | ||
6736 | |||
6737 | newinet->uc_ttl = inet->uc_ttl; | ||
6738 | newinet->mc_loop = 1; | ||
6739 | newinet->mc_ttl = 1; | ||
6740 | newinet->mc_index = 0; | ||
6741 | newinet->mc_list = NULL; | ||
6742 | } | ||
6743 | |||
6703 | /* Populate the fields of the newsk from the oldsk and migrate the assoc | 6744 | /* Populate the fields of the newsk from the oldsk and migrate the assoc |
6704 | * and its messages to the newsk. | 6745 | * and its messages to the newsk. |
6705 | */ | 6746 | */ |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index e745c118f239..5c29b14ee9af 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -79,6 +79,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
79 | peer->rttvar = 0; | 79 | peer->rttvar = 0; |
80 | peer->srtt = 0; | 80 | peer->srtt = 0; |
81 | peer->rto_pending = 0; | 81 | peer->rto_pending = 0; |
82 | peer->hb_sent = 0; | ||
82 | peer->fast_recovery = 0; | 83 | peer->fast_recovery = 0; |
83 | 84 | ||
84 | peer->last_time_heard = jiffies; | 85 | peer->last_time_heard = jiffies; |
@@ -608,6 +609,7 @@ void sctp_transport_reset(struct sctp_transport *t) | |||
608 | t->flight_size = 0; | 609 | t->flight_size = 0; |
609 | t->error_count = 0; | 610 | t->error_count = 0; |
610 | t->rto_pending = 0; | 611 | t->rto_pending = 0; |
612 | t->hb_sent = 0; | ||
611 | t->fast_recovery = 0; | 613 | t->fast_recovery = 0; |
612 | 614 | ||
613 | /* Initialize the state information for SFR-CACC */ | 615 | /* Initialize the state information for SFR-CACC */ |
diff --git a/net/socket.c b/net/socket.c index 35dd7371752a..47a3dc074eb0 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -545,6 +545,18 @@ void sock_release(struct socket *sock) | |||
545 | sock->file = NULL; | 545 | sock->file = NULL; |
546 | } | 546 | } |
547 | 547 | ||
548 | int sock_tx_timestamp(struct msghdr *msg, struct sock *sk, | ||
549 | union skb_shared_tx *shtx) | ||
550 | { | ||
551 | shtx->flags = 0; | ||
552 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) | ||
553 | shtx->hardware = 1; | ||
554 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) | ||
555 | shtx->software = 1; | ||
556 | return 0; | ||
557 | } | ||
558 | EXPORT_SYMBOL(sock_tx_timestamp); | ||
559 | |||
548 | static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, | 560 | static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, |
549 | struct msghdr *msg, size_t size) | 561 | struct msghdr *msg, size_t size) |
550 | { | 562 | { |
@@ -595,33 +607,65 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | |||
595 | return result; | 607 | return result; |
596 | } | 608 | } |
597 | 609 | ||
610 | static int ktime2ts(ktime_t kt, struct timespec *ts) | ||
611 | { | ||
612 | if (kt.tv64) { | ||
613 | *ts = ktime_to_timespec(kt); | ||
614 | return 1; | ||
615 | } else { | ||
616 | return 0; | ||
617 | } | ||
618 | } | ||
619 | |||
598 | /* | 620 | /* |
599 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) | 621 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) |
600 | */ | 622 | */ |
601 | void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | 623 | void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, |
602 | struct sk_buff *skb) | 624 | struct sk_buff *skb) |
603 | { | 625 | { |
604 | ktime_t kt = skb->tstamp; | 626 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); |
605 | 627 | struct timespec ts[3]; | |
606 | if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { | 628 | int empty = 1; |
607 | struct timeval tv; | 629 | struct skb_shared_hwtstamps *shhwtstamps = |
608 | /* Race occurred between timestamp enabling and packet | 630 | skb_hwtstamps(skb); |
609 | receiving. Fill in the current time for now. */ | 631 | |
610 | if (kt.tv64 == 0) | 632 | /* Race occurred between timestamp enabling and packet |
611 | kt = ktime_get_real(); | 633 | receiving. Fill in the current time for now. */ |
612 | skb->tstamp = kt; | 634 | if (need_software_tstamp && skb->tstamp.tv64 == 0) |
613 | tv = ktime_to_timeval(kt); | 635 | __net_timestamp(skb); |
614 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv); | 636 | |
615 | } else { | 637 | if (need_software_tstamp) { |
616 | struct timespec ts; | 638 | if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { |
617 | /* Race occurred between timestamp enabling and packet | 639 | struct timeval tv; |
618 | receiving. Fill in the current time for now. */ | 640 | skb_get_timestamp(skb, &tv); |
619 | if (kt.tv64 == 0) | 641 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, |
620 | kt = ktime_get_real(); | 642 | sizeof(tv), &tv); |
621 | skb->tstamp = kt; | 643 | } else { |
622 | ts = ktime_to_timespec(kt); | 644 | struct timespec ts; |
623 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts); | 645 | skb_get_timestampns(skb, &ts); |
646 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, | ||
647 | sizeof(ts), &ts); | ||
648 | } | ||
649 | } | ||
650 | |||
651 | |||
652 | memset(ts, 0, sizeof(ts)); | ||
653 | if (skb->tstamp.tv64 && | ||
654 | sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) { | ||
655 | skb_get_timestampns(skb, ts + 0); | ||
656 | empty = 0; | ||
657 | } | ||
658 | if (shhwtstamps) { | ||
659 | if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) && | ||
660 | ktime2ts(shhwtstamps->syststamp, ts + 1)) | ||
661 | empty = 0; | ||
662 | if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && | ||
663 | ktime2ts(shhwtstamps->hwtstamp, ts + 2)) | ||
664 | empty = 0; | ||
624 | } | 665 | } |
666 | if (!empty) | ||
667 | put_cmsg(msg, SOL_SOCKET, | ||
668 | SCM_TIMESTAMPING, sizeof(ts), &ts); | ||
625 | } | 669 | } |
626 | 670 | ||
627 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); | 671 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 5cbb404c4cdf..b49e434c094f 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1215,6 +1215,23 @@ out: | |||
1215 | read_unlock(&sk->sk_callback_lock); | 1215 | read_unlock(&sk->sk_callback_lock); |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | static void xs_write_space(struct sock *sk) | ||
1219 | { | ||
1220 | struct socket *sock; | ||
1221 | struct rpc_xprt *xprt; | ||
1222 | |||
1223 | if (unlikely(!(sock = sk->sk_socket))) | ||
1224 | return; | ||
1225 | clear_bit(SOCK_NOSPACE, &sock->flags); | ||
1226 | |||
1227 | if (unlikely(!(xprt = xprt_from_sock(sk)))) | ||
1228 | return; | ||
1229 | if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0) | ||
1230 | return; | ||
1231 | |||
1232 | xprt_write_space(xprt); | ||
1233 | } | ||
1234 | |||
1218 | /** | 1235 | /** |
1219 | * xs_udp_write_space - callback invoked when socket buffer space | 1236 | * xs_udp_write_space - callback invoked when socket buffer space |
1220 | * becomes available | 1237 | * becomes available |
@@ -1230,23 +1247,9 @@ static void xs_udp_write_space(struct sock *sk) | |||
1230 | read_lock(&sk->sk_callback_lock); | 1247 | read_lock(&sk->sk_callback_lock); |
1231 | 1248 | ||
1232 | /* from net/core/sock.c:sock_def_write_space */ | 1249 | /* from net/core/sock.c:sock_def_write_space */ |
1233 | if (sock_writeable(sk)) { | 1250 | if (sock_writeable(sk)) |
1234 | struct socket *sock; | 1251 | xs_write_space(sk); |
1235 | struct rpc_xprt *xprt; | ||
1236 | |||
1237 | if (unlikely(!(sock = sk->sk_socket))) | ||
1238 | goto out; | ||
1239 | clear_bit(SOCK_NOSPACE, &sock->flags); | ||
1240 | |||
1241 | if (unlikely(!(xprt = xprt_from_sock(sk)))) | ||
1242 | goto out; | ||
1243 | if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0) | ||
1244 | goto out; | ||
1245 | |||
1246 | xprt_write_space(xprt); | ||
1247 | } | ||
1248 | 1252 | ||
1249 | out: | ||
1250 | read_unlock(&sk->sk_callback_lock); | 1253 | read_unlock(&sk->sk_callback_lock); |
1251 | } | 1254 | } |
1252 | 1255 | ||
@@ -1265,23 +1268,9 @@ static void xs_tcp_write_space(struct sock *sk) | |||
1265 | read_lock(&sk->sk_callback_lock); | 1268 | read_lock(&sk->sk_callback_lock); |
1266 | 1269 | ||
1267 | /* from net/core/stream.c:sk_stream_write_space */ | 1270 | /* from net/core/stream.c:sk_stream_write_space */ |
1268 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { | 1271 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) |
1269 | struct socket *sock; | 1272 | xs_write_space(sk); |
1270 | struct rpc_xprt *xprt; | ||
1271 | |||
1272 | if (unlikely(!(sock = sk->sk_socket))) | ||
1273 | goto out; | ||
1274 | clear_bit(SOCK_NOSPACE, &sock->flags); | ||
1275 | 1273 | ||
1276 | if (unlikely(!(xprt = xprt_from_sock(sk)))) | ||
1277 | goto out; | ||
1278 | if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0) | ||
1279 | goto out; | ||
1280 | |||
1281 | xprt_write_space(xprt); | ||
1282 | } | ||
1283 | |||
1284 | out: | ||
1285 | read_unlock(&sk->sk_callback_lock); | 1274 | read_unlock(&sk->sk_callback_lock); |
1286 | } | 1275 | } |
1287 | 1276 | ||
diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c index cb3b4ad53683..5d149c1b5f0d 100644 --- a/net/wimax/op-msg.c +++ b/net/wimax/op-msg.c | |||
@@ -258,7 +258,6 @@ EXPORT_SYMBOL_GPL(wimax_msg_len); | |||
258 | */ | 258 | */ |
259 | int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) | 259 | int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) |
260 | { | 260 | { |
261 | int result; | ||
262 | struct device *dev = wimax_dev->net_dev->dev.parent; | 261 | struct device *dev = wimax_dev->net_dev->dev.parent; |
263 | void *msg = skb->data; | 262 | void *msg = skb->data; |
264 | size_t size = skb->len; | 263 | size_t size = skb->len; |
@@ -266,11 +265,9 @@ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) | |||
266 | 265 | ||
267 | d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size); | 266 | d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size); |
268 | d_dump(2, dev, msg, size); | 267 | d_dump(2, dev, msg, size); |
269 | result = genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); | 268 | genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); |
270 | d_printf(1, dev, "CTX: genl multicast result %d\n", result); | 269 | d_printf(1, dev, "CTX: genl multicast done\n"); |
271 | if (result == -ESRCH) /* Nobody connected, ignore it */ | 270 | return 0; |
272 | result = 0; /* btw, the skb is freed already */ | ||
273 | return result; | ||
274 | } | 271 | } |
275 | EXPORT_SYMBOL_GPL(wimax_msg_send); | 272 | EXPORT_SYMBOL_GPL(wimax_msg_send); |
276 | 273 | ||
diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 3869c0327882..a0ee76b52510 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c | |||
@@ -163,16 +163,12 @@ int wimax_gnl_re_state_change_send( | |||
163 | struct device *dev = wimax_dev_to_dev(wimax_dev); | 163 | struct device *dev = wimax_dev_to_dev(wimax_dev); |
164 | d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n", | 164 | d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n", |
165 | wimax_dev, report_skb); | 165 | wimax_dev, report_skb); |
166 | if (report_skb == NULL) | 166 | if (report_skb == NULL) { |
167 | result = -ENOMEM; | ||
167 | goto out; | 168 | goto out; |
168 | genlmsg_end(report_skb, header); | ||
169 | result = genlmsg_multicast(report_skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); | ||
170 | if (result == -ESRCH) /* Nobody connected, ignore it */ | ||
171 | result = 0; /* btw, the skb is freed already */ | ||
172 | if (result < 0) { | ||
173 | dev_err(dev, "RE_STCH: Error sending: %d\n", result); | ||
174 | nlmsg_free(report_skb); | ||
175 | } | 169 | } |
170 | genlmsg_end(report_skb, header); | ||
171 | genlmsg_multicast(report_skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); | ||
176 | out: | 172 | out: |
177 | d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n", | 173 | d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n", |
178 | wimax_dev, report_skb, result); | 174 | wimax_dev, report_skb, result); |
diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 938a334c8dbc..dad43c24f695 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile | |||
@@ -5,7 +5,7 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o | |||
5 | obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o | 5 | obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o |
6 | obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o | 6 | obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o |
7 | 7 | ||
8 | cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o | 8 | cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o |
9 | cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o | 9 | cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o |
10 | cfg80211-$(CONFIG_NL80211) += nl80211.o | 10 | cfg80211-$(CONFIG_NL80211) += nl80211.o |
11 | 11 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index b96fc0c3f1c4..0668b2bfc1da 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -240,6 +240,8 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | |||
240 | mutex_init(&drv->mtx); | 240 | mutex_init(&drv->mtx); |
241 | mutex_init(&drv->devlist_mtx); | 241 | mutex_init(&drv->devlist_mtx); |
242 | INIT_LIST_HEAD(&drv->netdev_list); | 242 | INIT_LIST_HEAD(&drv->netdev_list); |
243 | spin_lock_init(&drv->bss_lock); | ||
244 | INIT_LIST_HEAD(&drv->bss_list); | ||
243 | 245 | ||
244 | device_initialize(&drv->wiphy.dev); | 246 | device_initialize(&drv->wiphy.dev); |
245 | drv->wiphy.dev.class = &ieee80211_class; | 247 | drv->wiphy.dev.class = &ieee80211_class; |
@@ -259,6 +261,9 @@ int wiphy_register(struct wiphy *wiphy) | |||
259 | int i; | 261 | int i; |
260 | u16 ifmodes = wiphy->interface_modes; | 262 | u16 ifmodes = wiphy->interface_modes; |
261 | 263 | ||
264 | if (WARN_ON(wiphy->max_scan_ssids < 1)) | ||
265 | return -EINVAL; | ||
266 | |||
262 | /* sanity check ifmodes */ | 267 | /* sanity check ifmodes */ |
263 | WARN_ON(!ifmodes); | 268 | WARN_ON(!ifmodes); |
264 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; | 269 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; |
@@ -273,10 +278,16 @@ int wiphy_register(struct wiphy *wiphy) | |||
273 | 278 | ||
274 | sband->band = band; | 279 | sband->band = band; |
275 | 280 | ||
276 | if (!sband->n_channels || !sband->n_bitrates) { | 281 | if (WARN_ON(!sband->n_channels || !sband->n_bitrates)) |
277 | WARN_ON(1); | 282 | return -EINVAL; |
283 | |||
284 | /* | ||
285 | * Since we use a u32 for rate bitmaps in | ||
286 | * ieee80211_get_response_rate, we cannot | ||
287 | * have more than 32 legacy rates. | ||
288 | */ | ||
289 | if (WARN_ON(sband->n_bitrates > 32)) | ||
278 | return -EINVAL; | 290 | return -EINVAL; |
279 | } | ||
280 | 291 | ||
281 | for (i = 0; i < sband->n_channels; i++) { | 292 | for (i = 0; i < sband->n_channels; i++) { |
282 | sband->channels[i].orig_flags = | 293 | sband->channels[i].orig_flags = |
@@ -361,8 +372,11 @@ EXPORT_SYMBOL(wiphy_unregister); | |||
361 | 372 | ||
362 | void cfg80211_dev_free(struct cfg80211_registered_device *drv) | 373 | void cfg80211_dev_free(struct cfg80211_registered_device *drv) |
363 | { | 374 | { |
375 | struct cfg80211_internal_bss *scan, *tmp; | ||
364 | mutex_destroy(&drv->mtx); | 376 | mutex_destroy(&drv->mtx); |
365 | mutex_destroy(&drv->devlist_mtx); | 377 | mutex_destroy(&drv->devlist_mtx); |
378 | list_for_each_entry_safe(scan, tmp, &drv->bss_list, list) | ||
379 | cfg80211_put_bss(&scan->pub); | ||
366 | kfree(drv); | 380 | kfree(drv); |
367 | } | 381 | } |
368 | 382 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index f7fb9f413028..e29ad4cd464f 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -8,6 +8,8 @@ | |||
8 | #include <linux/mutex.h> | 8 | #include <linux/mutex.h> |
9 | #include <linux/list.h> | 9 | #include <linux/list.h> |
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/kref.h> | ||
12 | #include <linux/rbtree.h> | ||
11 | #include <net/genetlink.h> | 13 | #include <net/genetlink.h> |
12 | #include <net/wireless.h> | 14 | #include <net/wireless.h> |
13 | #include <net/cfg80211.h> | 15 | #include <net/cfg80211.h> |
@@ -41,6 +43,13 @@ struct cfg80211_registered_device { | |||
41 | struct mutex devlist_mtx; | 43 | struct mutex devlist_mtx; |
42 | struct list_head netdev_list; | 44 | struct list_head netdev_list; |
43 | 45 | ||
46 | /* BSSes/scanning */ | ||
47 | spinlock_t bss_lock; | ||
48 | struct list_head bss_list; | ||
49 | struct rb_root bss_tree; | ||
50 | u32 bss_generation; | ||
51 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ | ||
52 | |||
44 | /* must be last because of the way we do wiphy_priv(), | 53 | /* must be last because of the way we do wiphy_priv(), |
45 | * and it should at least be aligned to NETDEV_ALIGN */ | 54 | * and it should at least be aligned to NETDEV_ALIGN */ |
46 | struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); | 55 | struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); |
@@ -56,6 +65,15 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy) | |||
56 | extern struct mutex cfg80211_drv_mutex; | 65 | extern struct mutex cfg80211_drv_mutex; |
57 | extern struct list_head cfg80211_drv_list; | 66 | extern struct list_head cfg80211_drv_list; |
58 | 67 | ||
68 | struct cfg80211_internal_bss { | ||
69 | struct list_head list; | ||
70 | struct rb_node rbn; | ||
71 | unsigned long ts; | ||
72 | struct kref ref; | ||
73 | /* must be last because of priv member */ | ||
74 | struct cfg80211_bss pub; | ||
75 | }; | ||
76 | |||
59 | /* | 77 | /* |
60 | * This function returns a pointer to the driver | 78 | * This function returns a pointer to the driver |
61 | * that the genl_info item that is passed refers to. | 79 | * that the genl_info item that is passed refers to. |
@@ -94,4 +112,6 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv, | |||
94 | void ieee80211_set_bitrate_flags(struct wiphy *wiphy); | 112 | void ieee80211_set_bitrate_flags(struct wiphy *wiphy); |
95 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby); | 113 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby); |
96 | 114 | ||
115 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev); | ||
116 | |||
97 | #endif /* __NET_WIRELESS_CORE_H */ | 117 | #endif /* __NET_WIRELESS_CORE_H */ |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1e728fff474e..298a4de59948 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/nl80211.h> | 14 | #include <linux/nl80211.h> |
15 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
16 | #include <linux/netlink.h> | 16 | #include <linux/netlink.h> |
17 | #include <linux/etherdevice.h> | ||
17 | #include <net/genetlink.h> | 18 | #include <net/genetlink.h> |
18 | #include <net/cfg80211.h> | 19 | #include <net/cfg80211.h> |
19 | #include "core.h" | 20 | #include "core.h" |
@@ -105,6 +106,12 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
105 | 106 | ||
106 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, | 107 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, |
107 | .len = NL80211_HT_CAPABILITY_LEN }, | 108 | .len = NL80211_HT_CAPABILITY_LEN }, |
109 | |||
110 | [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 }, | ||
111 | [NL80211_ATTR_IE] = { .type = NLA_BINARY, | ||
112 | .len = IEEE80211_MAX_DATA_LEN }, | ||
113 | [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED }, | ||
114 | [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED }, | ||
108 | }; | 115 | }; |
109 | 116 | ||
110 | /* message building helper */ | 117 | /* message building helper */ |
@@ -137,6 +144,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
137 | 144 | ||
138 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); | 145 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); |
139 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); | 146 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); |
147 | NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, | ||
148 | dev->wiphy.max_scan_ssids); | ||
140 | 149 | ||
141 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); | 150 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); |
142 | if (!nl_modes) | 151 | if (!nl_modes) |
@@ -738,7 +747,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
738 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | 747 | if (info->attrs[NL80211_ATTR_KEY_IDX]) |
739 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 748 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
740 | 749 | ||
741 | if (key_idx > 3) | 750 | if (key_idx > 5) |
742 | return -EINVAL; | 751 | return -EINVAL; |
743 | 752 | ||
744 | if (info->attrs[NL80211_ATTR_MAC]) | 753 | if (info->attrs[NL80211_ATTR_MAC]) |
@@ -804,30 +813,41 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
804 | int err; | 813 | int err; |
805 | struct net_device *dev; | 814 | struct net_device *dev; |
806 | u8 key_idx; | 815 | u8 key_idx; |
816 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, | ||
817 | u8 key_index); | ||
807 | 818 | ||
808 | if (!info->attrs[NL80211_ATTR_KEY_IDX]) | 819 | if (!info->attrs[NL80211_ATTR_KEY_IDX]) |
809 | return -EINVAL; | 820 | return -EINVAL; |
810 | 821 | ||
811 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 822 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
812 | 823 | ||
813 | if (key_idx > 3) | 824 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) { |
825 | if (key_idx < 4 || key_idx > 5) | ||
826 | return -EINVAL; | ||
827 | } else if (key_idx > 3) | ||
814 | return -EINVAL; | 828 | return -EINVAL; |
815 | 829 | ||
816 | /* currently only support setting default key */ | 830 | /* currently only support setting default key */ |
817 | if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) | 831 | if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] && |
832 | !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) | ||
818 | return -EINVAL; | 833 | return -EINVAL; |
819 | 834 | ||
820 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 835 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
821 | if (err) | 836 | if (err) |
822 | return err; | 837 | return err; |
823 | 838 | ||
824 | if (!drv->ops->set_default_key) { | 839 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) |
840 | func = drv->ops->set_default_key; | ||
841 | else | ||
842 | func = drv->ops->set_default_mgmt_key; | ||
843 | |||
844 | if (!func) { | ||
825 | err = -EOPNOTSUPP; | 845 | err = -EOPNOTSUPP; |
826 | goto out; | 846 | goto out; |
827 | } | 847 | } |
828 | 848 | ||
829 | rtnl_lock(); | 849 | rtnl_lock(); |
830 | err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx); | 850 | err = func(&drv->wiphy, dev, key_idx); |
831 | rtnl_unlock(); | 851 | rtnl_unlock(); |
832 | 852 | ||
833 | out: | 853 | out: |
@@ -863,7 +883,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
863 | if (info->attrs[NL80211_ATTR_MAC]) | 883 | if (info->attrs[NL80211_ATTR_MAC]) |
864 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 884 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
865 | 885 | ||
866 | if (key_idx > 3) | 886 | if (key_idx > 5) |
867 | return -EINVAL; | 887 | return -EINVAL; |
868 | 888 | ||
869 | /* | 889 | /* |
@@ -894,6 +914,10 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
894 | if (params.key_len != 13) | 914 | if (params.key_len != 13) |
895 | return -EINVAL; | 915 | return -EINVAL; |
896 | break; | 916 | break; |
917 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
918 | if (params.key_len != 16) | ||
919 | return -EINVAL; | ||
920 | break; | ||
897 | default: | 921 | default: |
898 | return -EINVAL; | 922 | return -EINVAL; |
899 | } | 923 | } |
@@ -928,7 +952,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
928 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | 952 | if (info->attrs[NL80211_ATTR_KEY_IDX]) |
929 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 953 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
930 | 954 | ||
931 | if (key_idx > 3) | 955 | if (key_idx > 5) |
932 | return -EINVAL; | 956 | return -EINVAL; |
933 | 957 | ||
934 | if (info->attrs[NL80211_ATTR_MAC]) | 958 | if (info->attrs[NL80211_ATTR_MAC]) |
@@ -1889,6 +1913,11 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
1889 | mutex_lock(&cfg80211_drv_mutex); | 1913 | mutex_lock(&cfg80211_drv_mutex); |
1890 | r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY); | 1914 | r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY); |
1891 | mutex_unlock(&cfg80211_drv_mutex); | 1915 | mutex_unlock(&cfg80211_drv_mutex); |
1916 | /* This means the regulatory domain was already set, however | ||
1917 | * we don't want to confuse userspace with a "successful error" | ||
1918 | * message so lets just treat it as a success */ | ||
1919 | if (r == -EALREADY) | ||
1920 | r = 0; | ||
1892 | return r; | 1921 | return r; |
1893 | } | 1922 | } |
1894 | 1923 | ||
@@ -2069,6 +2098,81 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | |||
2069 | 2098 | ||
2070 | #undef FILL_IN_MESH_PARAM_IF_SET | 2099 | #undef FILL_IN_MESH_PARAM_IF_SET |
2071 | 2100 | ||
2101 | static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | ||
2102 | { | ||
2103 | struct sk_buff *msg; | ||
2104 | void *hdr = NULL; | ||
2105 | struct nlattr *nl_reg_rules; | ||
2106 | unsigned int i; | ||
2107 | int err = -EINVAL; | ||
2108 | |||
2109 | mutex_lock(&cfg80211_drv_mutex); | ||
2110 | |||
2111 | if (!cfg80211_regdomain) | ||
2112 | goto out; | ||
2113 | |||
2114 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
2115 | if (!msg) { | ||
2116 | err = -ENOBUFS; | ||
2117 | goto out; | ||
2118 | } | ||
2119 | |||
2120 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | ||
2121 | NL80211_CMD_GET_REG); | ||
2122 | if (!hdr) | ||
2123 | goto nla_put_failure; | ||
2124 | |||
2125 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, | ||
2126 | cfg80211_regdomain->alpha2); | ||
2127 | |||
2128 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); | ||
2129 | if (!nl_reg_rules) | ||
2130 | goto nla_put_failure; | ||
2131 | |||
2132 | for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { | ||
2133 | struct nlattr *nl_reg_rule; | ||
2134 | const struct ieee80211_reg_rule *reg_rule; | ||
2135 | const struct ieee80211_freq_range *freq_range; | ||
2136 | const struct ieee80211_power_rule *power_rule; | ||
2137 | |||
2138 | reg_rule = &cfg80211_regdomain->reg_rules[i]; | ||
2139 | freq_range = ®_rule->freq_range; | ||
2140 | power_rule = ®_rule->power_rule; | ||
2141 | |||
2142 | nl_reg_rule = nla_nest_start(msg, i); | ||
2143 | if (!nl_reg_rule) | ||
2144 | goto nla_put_failure; | ||
2145 | |||
2146 | NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS, | ||
2147 | reg_rule->flags); | ||
2148 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START, | ||
2149 | freq_range->start_freq_khz); | ||
2150 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END, | ||
2151 | freq_range->end_freq_khz); | ||
2152 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, | ||
2153 | freq_range->max_bandwidth_khz); | ||
2154 | NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | ||
2155 | power_rule->max_antenna_gain); | ||
2156 | NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, | ||
2157 | power_rule->max_eirp); | ||
2158 | |||
2159 | nla_nest_end(msg, nl_reg_rule); | ||
2160 | } | ||
2161 | |||
2162 | nla_nest_end(msg, nl_reg_rules); | ||
2163 | |||
2164 | genlmsg_end(msg, hdr); | ||
2165 | err = genlmsg_unicast(msg, info->snd_pid); | ||
2166 | goto out; | ||
2167 | |||
2168 | nla_put_failure: | ||
2169 | genlmsg_cancel(msg, hdr); | ||
2170 | err = -EMSGSIZE; | ||
2171 | out: | ||
2172 | mutex_unlock(&cfg80211_drv_mutex); | ||
2173 | return err; | ||
2174 | } | ||
2175 | |||
2072 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 2176 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
2073 | { | 2177 | { |
2074 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; | 2178 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; |
@@ -2134,6 +2238,283 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
2134 | return -EINVAL; | 2238 | return -EINVAL; |
2135 | } | 2239 | } |
2136 | 2240 | ||
2241 | static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb, | ||
2242 | struct genl_info *info) | ||
2243 | { | ||
2244 | struct cfg80211_registered_device *drv; | ||
2245 | int err; | ||
2246 | struct net_device *dev; | ||
2247 | struct mgmt_extra_ie_params params; | ||
2248 | |||
2249 | memset(¶ms, 0, sizeof(params)); | ||
2250 | |||
2251 | if (!info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) | ||
2252 | return -EINVAL; | ||
2253 | params.subtype = nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]); | ||
2254 | if (params.subtype > 15) | ||
2255 | return -EINVAL; /* FC Subtype field is 4 bits (0..15) */ | ||
2256 | |||
2257 | if (info->attrs[NL80211_ATTR_IE]) { | ||
2258 | params.ies = nla_data(info->attrs[NL80211_ATTR_IE]); | ||
2259 | params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); | ||
2260 | } | ||
2261 | |||
2262 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | ||
2263 | if (err) | ||
2264 | return err; | ||
2265 | |||
2266 | if (drv->ops->set_mgmt_extra_ie) { | ||
2267 | rtnl_lock(); | ||
2268 | err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, ¶ms); | ||
2269 | rtnl_unlock(); | ||
2270 | } else | ||
2271 | err = -EOPNOTSUPP; | ||
2272 | |||
2273 | cfg80211_put_dev(drv); | ||
2274 | dev_put(dev); | ||
2275 | return err; | ||
2276 | } | ||
2277 | |||
2278 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | ||
2279 | { | ||
2280 | struct cfg80211_registered_device *drv; | ||
2281 | struct net_device *dev; | ||
2282 | struct cfg80211_scan_request *request; | ||
2283 | struct cfg80211_ssid *ssid; | ||
2284 | struct ieee80211_channel *channel; | ||
2285 | struct nlattr *attr; | ||
2286 | struct wiphy *wiphy; | ||
2287 | int err, tmp, n_ssids = 0, n_channels = 0, i; | ||
2288 | enum ieee80211_band band; | ||
2289 | |||
2290 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | ||
2291 | if (err) | ||
2292 | return err; | ||
2293 | |||
2294 | wiphy = &drv->wiphy; | ||
2295 | |||
2296 | if (!drv->ops->scan) { | ||
2297 | err = -EOPNOTSUPP; | ||
2298 | goto out; | ||
2299 | } | ||
2300 | |||
2301 | rtnl_lock(); | ||
2302 | |||
2303 | if (drv->scan_req) { | ||
2304 | err = -EBUSY; | ||
2305 | goto out_unlock; | ||
2306 | } | ||
2307 | |||
2308 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | ||
2309 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) | ||
2310 | n_channels++; | ||
2311 | if (!n_channels) { | ||
2312 | err = -EINVAL; | ||
2313 | goto out_unlock; | ||
2314 | } | ||
2315 | } else { | ||
2316 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) | ||
2317 | if (wiphy->bands[band]) | ||
2318 | n_channels += wiphy->bands[band]->n_channels; | ||
2319 | } | ||
2320 | |||
2321 | if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) | ||
2322 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) | ||
2323 | n_ssids++; | ||
2324 | |||
2325 | if (n_ssids > wiphy->max_scan_ssids) { | ||
2326 | err = -EINVAL; | ||
2327 | goto out_unlock; | ||
2328 | } | ||
2329 | |||
2330 | request = kzalloc(sizeof(*request) | ||
2331 | + sizeof(*ssid) * n_ssids | ||
2332 | + sizeof(channel) * n_channels, GFP_KERNEL); | ||
2333 | if (!request) { | ||
2334 | err = -ENOMEM; | ||
2335 | goto out_unlock; | ||
2336 | } | ||
2337 | |||
2338 | request->channels = (void *)((char *)request + sizeof(*request)); | ||
2339 | request->n_channels = n_channels; | ||
2340 | if (n_ssids) | ||
2341 | request->ssids = (void *)(request->channels + n_channels); | ||
2342 | request->n_ssids = n_ssids; | ||
2343 | |||
2344 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | ||
2345 | /* user specified, bail out if channel not found */ | ||
2346 | request->n_channels = n_channels; | ||
2347 | i = 0; | ||
2348 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) { | ||
2349 | request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr)); | ||
2350 | if (!request->channels[i]) { | ||
2351 | err = -EINVAL; | ||
2352 | goto out_free; | ||
2353 | } | ||
2354 | i++; | ||
2355 | } | ||
2356 | } else { | ||
2357 | /* all channels */ | ||
2358 | i = 0; | ||
2359 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
2360 | int j; | ||
2361 | if (!wiphy->bands[band]) | ||
2362 | continue; | ||
2363 | for (j = 0; j < wiphy->bands[band]->n_channels; j++) { | ||
2364 | request->channels[i] = &wiphy->bands[band]->channels[j]; | ||
2365 | i++; | ||
2366 | } | ||
2367 | } | ||
2368 | } | ||
2369 | |||
2370 | i = 0; | ||
2371 | if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { | ||
2372 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { | ||
2373 | if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) { | ||
2374 | err = -EINVAL; | ||
2375 | goto out_free; | ||
2376 | } | ||
2377 | memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); | ||
2378 | request->ssids[i].ssid_len = nla_len(attr); | ||
2379 | i++; | ||
2380 | } | ||
2381 | } | ||
2382 | |||
2383 | request->ifidx = dev->ifindex; | ||
2384 | request->wiphy = &drv->wiphy; | ||
2385 | |||
2386 | drv->scan_req = request; | ||
2387 | err = drv->ops->scan(&drv->wiphy, dev, request); | ||
2388 | |||
2389 | out_free: | ||
2390 | if (err) { | ||
2391 | drv->scan_req = NULL; | ||
2392 | kfree(request); | ||
2393 | } | ||
2394 | out_unlock: | ||
2395 | rtnl_unlock(); | ||
2396 | out: | ||
2397 | cfg80211_put_dev(drv); | ||
2398 | dev_put(dev); | ||
2399 | return err; | ||
2400 | } | ||
2401 | |||
2402 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | ||
2403 | struct cfg80211_registered_device *rdev, | ||
2404 | struct net_device *dev, | ||
2405 | struct cfg80211_bss *res) | ||
2406 | { | ||
2407 | void *hdr; | ||
2408 | struct nlattr *bss; | ||
2409 | |||
2410 | hdr = nl80211hdr_put(msg, pid, seq, flags, | ||
2411 | NL80211_CMD_NEW_SCAN_RESULTS); | ||
2412 | if (!hdr) | ||
2413 | return -1; | ||
2414 | |||
2415 | NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION, | ||
2416 | rdev->bss_generation); | ||
2417 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | ||
2418 | |||
2419 | bss = nla_nest_start(msg, NL80211_ATTR_BSS); | ||
2420 | if (!bss) | ||
2421 | goto nla_put_failure; | ||
2422 | if (!is_zero_ether_addr(res->bssid)) | ||
2423 | NLA_PUT(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid); | ||
2424 | if (res->information_elements && res->len_information_elements) | ||
2425 | NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS, | ||
2426 | res->len_information_elements, | ||
2427 | res->information_elements); | ||
2428 | if (res->tsf) | ||
2429 | NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf); | ||
2430 | if (res->beacon_interval) | ||
2431 | NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval); | ||
2432 | NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability); | ||
2433 | NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq); | ||
2434 | |||
2435 | switch (res->signal_type) { | ||
2436 | case CFG80211_SIGNAL_TYPE_MBM: | ||
2437 | NLA_PUT_U32(msg, NL80211_BSS_SIGNAL_MBM, res->signal); | ||
2438 | break; | ||
2439 | case CFG80211_SIGNAL_TYPE_UNSPEC: | ||
2440 | NLA_PUT_U8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal); | ||
2441 | break; | ||
2442 | default: | ||
2443 | break; | ||
2444 | } | ||
2445 | |||
2446 | nla_nest_end(msg, bss); | ||
2447 | |||
2448 | return genlmsg_end(msg, hdr); | ||
2449 | |||
2450 | nla_put_failure: | ||
2451 | genlmsg_cancel(msg, hdr); | ||
2452 | return -EMSGSIZE; | ||
2453 | } | ||
2454 | |||
2455 | static int nl80211_dump_scan(struct sk_buff *skb, | ||
2456 | struct netlink_callback *cb) | ||
2457 | { | ||
2458 | struct cfg80211_registered_device *dev; | ||
2459 | struct net_device *netdev; | ||
2460 | struct cfg80211_internal_bss *scan; | ||
2461 | int ifidx = cb->args[0]; | ||
2462 | int start = cb->args[1], idx = 0; | ||
2463 | int err; | ||
2464 | |||
2465 | if (!ifidx) { | ||
2466 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | ||
2467 | nl80211_fam.attrbuf, nl80211_fam.maxattr, | ||
2468 | nl80211_policy); | ||
2469 | if (err) | ||
2470 | return err; | ||
2471 | |||
2472 | if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]) | ||
2473 | return -EINVAL; | ||
2474 | |||
2475 | ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); | ||
2476 | if (!ifidx) | ||
2477 | return -EINVAL; | ||
2478 | cb->args[0] = ifidx; | ||
2479 | } | ||
2480 | |||
2481 | netdev = dev_get_by_index(&init_net, ifidx); | ||
2482 | if (!netdev) | ||
2483 | return -ENODEV; | ||
2484 | |||
2485 | dev = cfg80211_get_dev_from_ifindex(ifidx); | ||
2486 | if (IS_ERR(dev)) { | ||
2487 | err = PTR_ERR(dev); | ||
2488 | goto out_put_netdev; | ||
2489 | } | ||
2490 | |||
2491 | spin_lock_bh(&dev->bss_lock); | ||
2492 | cfg80211_bss_expire(dev); | ||
2493 | |||
2494 | list_for_each_entry(scan, &dev->bss_list, list) { | ||
2495 | if (++idx <= start) | ||
2496 | continue; | ||
2497 | if (nl80211_send_bss(skb, | ||
2498 | NETLINK_CB(cb->skb).pid, | ||
2499 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
2500 | dev, netdev, &scan->pub) < 0) { | ||
2501 | idx--; | ||
2502 | goto out; | ||
2503 | } | ||
2504 | } | ||
2505 | |||
2506 | out: | ||
2507 | spin_unlock_bh(&dev->bss_lock); | ||
2508 | |||
2509 | cb->args[1] = idx; | ||
2510 | err = skb->len; | ||
2511 | cfg80211_put_dev(dev); | ||
2512 | out_put_netdev: | ||
2513 | dev_put(netdev); | ||
2514 | |||
2515 | return err; | ||
2516 | } | ||
2517 | |||
2137 | static struct genl_ops nl80211_ops[] = { | 2518 | static struct genl_ops nl80211_ops[] = { |
2138 | { | 2519 | { |
2139 | .cmd = NL80211_CMD_GET_WIPHY, | 2520 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -2272,6 +2653,12 @@ static struct genl_ops nl80211_ops[] = { | |||
2272 | .flags = GENL_ADMIN_PERM, | 2653 | .flags = GENL_ADMIN_PERM, |
2273 | }, | 2654 | }, |
2274 | { | 2655 | { |
2656 | .cmd = NL80211_CMD_GET_REG, | ||
2657 | .doit = nl80211_get_reg, | ||
2658 | .policy = nl80211_policy, | ||
2659 | /* can be retrieved by unprivileged users */ | ||
2660 | }, | ||
2661 | { | ||
2275 | .cmd = NL80211_CMD_SET_REG, | 2662 | .cmd = NL80211_CMD_SET_REG, |
2276 | .doit = nl80211_set_reg, | 2663 | .doit = nl80211_set_reg, |
2277 | .policy = nl80211_policy, | 2664 | .policy = nl80211_policy, |
@@ -2295,12 +2682,32 @@ static struct genl_ops nl80211_ops[] = { | |||
2295 | .policy = nl80211_policy, | 2682 | .policy = nl80211_policy, |
2296 | .flags = GENL_ADMIN_PERM, | 2683 | .flags = GENL_ADMIN_PERM, |
2297 | }, | 2684 | }, |
2685 | { | ||
2686 | .cmd = NL80211_CMD_SET_MGMT_EXTRA_IE, | ||
2687 | .doit = nl80211_set_mgmt_extra_ie, | ||
2688 | .policy = nl80211_policy, | ||
2689 | .flags = GENL_ADMIN_PERM, | ||
2690 | }, | ||
2691 | { | ||
2692 | .cmd = NL80211_CMD_TRIGGER_SCAN, | ||
2693 | .doit = nl80211_trigger_scan, | ||
2694 | .policy = nl80211_policy, | ||
2695 | .flags = GENL_ADMIN_PERM, | ||
2696 | }, | ||
2697 | { | ||
2698 | .cmd = NL80211_CMD_GET_SCAN, | ||
2699 | .policy = nl80211_policy, | ||
2700 | .dumpit = nl80211_dump_scan, | ||
2701 | }, | ||
2298 | }; | 2702 | }; |
2299 | 2703 | ||
2300 | /* multicast groups */ | 2704 | /* multicast groups */ |
2301 | static struct genl_multicast_group nl80211_config_mcgrp = { | 2705 | static struct genl_multicast_group nl80211_config_mcgrp = { |
2302 | .name = "config", | 2706 | .name = "config", |
2303 | }; | 2707 | }; |
2708 | static struct genl_multicast_group nl80211_scan_mcgrp = { | ||
2709 | .name = "scan", | ||
2710 | }; | ||
2304 | 2711 | ||
2305 | /* notification functions */ | 2712 | /* notification functions */ |
2306 | 2713 | ||
@@ -2320,6 +2727,66 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) | |||
2320 | genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); | 2727 | genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); |
2321 | } | 2728 | } |
2322 | 2729 | ||
2730 | static int nl80211_send_scan_donemsg(struct sk_buff *msg, | ||
2731 | struct cfg80211_registered_device *rdev, | ||
2732 | struct net_device *netdev, | ||
2733 | u32 pid, u32 seq, int flags, | ||
2734 | u32 cmd) | ||
2735 | { | ||
2736 | void *hdr; | ||
2737 | |||
2738 | hdr = nl80211hdr_put(msg, pid, seq, flags, cmd); | ||
2739 | if (!hdr) | ||
2740 | return -1; | ||
2741 | |||
2742 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->idx); | ||
2743 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
2744 | |||
2745 | /* XXX: we should probably bounce back the request? */ | ||
2746 | |||
2747 | return genlmsg_end(msg, hdr); | ||
2748 | |||
2749 | nla_put_failure: | ||
2750 | genlmsg_cancel(msg, hdr); | ||
2751 | return -EMSGSIZE; | ||
2752 | } | ||
2753 | |||
2754 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | ||
2755 | struct net_device *netdev) | ||
2756 | { | ||
2757 | struct sk_buff *msg; | ||
2758 | |||
2759 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
2760 | if (!msg) | ||
2761 | return; | ||
2762 | |||
2763 | if (nl80211_send_scan_donemsg(msg, rdev, netdev, 0, 0, 0, | ||
2764 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { | ||
2765 | nlmsg_free(msg); | ||
2766 | return; | ||
2767 | } | ||
2768 | |||
2769 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); | ||
2770 | } | ||
2771 | |||
2772 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | ||
2773 | struct net_device *netdev) | ||
2774 | { | ||
2775 | struct sk_buff *msg; | ||
2776 | |||
2777 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
2778 | if (!msg) | ||
2779 | return; | ||
2780 | |||
2781 | if (nl80211_send_scan_donemsg(msg, rdev, netdev, 0, 0, 0, | ||
2782 | NL80211_CMD_SCAN_ABORTED) < 0) { | ||
2783 | nlmsg_free(msg); | ||
2784 | return; | ||
2785 | } | ||
2786 | |||
2787 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); | ||
2788 | } | ||
2789 | |||
2323 | /* initialisation/exit functions */ | 2790 | /* initialisation/exit functions */ |
2324 | 2791 | ||
2325 | int nl80211_init(void) | 2792 | int nl80211_init(void) |
@@ -2340,6 +2807,10 @@ int nl80211_init(void) | |||
2340 | if (err) | 2807 | if (err) |
2341 | goto err_out; | 2808 | goto err_out; |
2342 | 2809 | ||
2810 | err = genl_register_mc_group(&nl80211_fam, &nl80211_scan_mcgrp); | ||
2811 | if (err) | ||
2812 | goto err_out; | ||
2813 | |||
2343 | return 0; | 2814 | return 0; |
2344 | err_out: | 2815 | err_out: |
2345 | genl_unregister_family(&nl80211_fam); | 2816 | genl_unregister_family(&nl80211_fam); |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index f3ea5c029aee..b565a5f84e97 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -7,6 +7,10 @@ | |||
7 | extern int nl80211_init(void); | 7 | extern int nl80211_init(void); |
8 | extern void nl80211_exit(void); | 8 | extern void nl80211_exit(void); |
9 | extern void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); | 9 | extern void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); |
10 | extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | ||
11 | struct net_device *netdev); | ||
12 | extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | ||
13 | struct net_device *netdev); | ||
10 | #else | 14 | #else |
11 | static inline int nl80211_init(void) | 15 | static inline int nl80211_init(void) |
12 | { | 16 | { |
@@ -19,6 +23,10 @@ static inline void nl80211_notify_dev_rename( | |||
19 | struct cfg80211_registered_device *rdev) | 23 | struct cfg80211_registered_device *rdev) |
20 | { | 24 | { |
21 | } | 25 | } |
26 | static inline void | ||
27 | nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | ||
28 | struct net_device *netdev) | ||
29 | {} | ||
22 | #endif /* CONFIG_NL80211 */ | 30 | #endif /* CONFIG_NL80211 */ |
23 | 31 | ||
24 | #endif /* __NET_WIRELESS_NL80211_H */ | 32 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 85c9034c59b2..2323644330cd 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -42,38 +42,6 @@ | |||
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "reg.h" | 43 | #include "reg.h" |
44 | 44 | ||
45 | /** | ||
46 | * struct regulatory_request - receipt of last regulatory request | ||
47 | * | ||
48 | * @wiphy: this is set if this request's initiator is | ||
49 | * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This | ||
50 | * can be used by the wireless core to deal with conflicts | ||
51 | * and potentially inform users of which devices specifically | ||
52 | * cased the conflicts. | ||
53 | * @initiator: indicates who sent this request, could be any of | ||
54 | * of those set in reg_set_by, %REGDOM_SET_BY_* | ||
55 | * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested | ||
56 | * regulatory domain. We have a few special codes: | ||
57 | * 00 - World regulatory domain | ||
58 | * 99 - built by driver but a specific alpha2 cannot be determined | ||
59 | * 98 - result of an intersection between two regulatory domains | ||
60 | * @intersect: indicates whether the wireless core should intersect | ||
61 | * the requested regulatory domain with the presently set regulatory | ||
62 | * domain. | ||
63 | * @country_ie_checksum: checksum of the last processed and accepted | ||
64 | * country IE | ||
65 | * @country_ie_env: lets us know if the AP is telling us we are outdoor, | ||
66 | * indoor, or if it doesn't matter | ||
67 | */ | ||
68 | struct regulatory_request { | ||
69 | struct wiphy *wiphy; | ||
70 | enum reg_set_by initiator; | ||
71 | char alpha2[2]; | ||
72 | bool intersect; | ||
73 | u32 country_ie_checksum; | ||
74 | enum environment_cap country_ie_env; | ||
75 | }; | ||
76 | |||
77 | /* Receipt of information from last regulatory request */ | 45 | /* Receipt of information from last regulatory request */ |
78 | static struct regulatory_request *last_request; | 46 | static struct regulatory_request *last_request; |
79 | 47 | ||
@@ -89,7 +57,7 @@ static u32 supported_bandwidths[] = { | |||
89 | /* Central wireless core regulatory domains, we only need two, | 57 | /* Central wireless core regulatory domains, we only need two, |
90 | * the current one and a world regulatory domain in case we have no | 58 | * the current one and a world regulatory domain in case we have no |
91 | * information to give us an alpha2 */ | 59 | * information to give us an alpha2 */ |
92 | static const struct ieee80211_regdomain *cfg80211_regdomain; | 60 | const struct ieee80211_regdomain *cfg80211_regdomain; |
93 | 61 | ||
94 | /* We use this as a place for the rd structure built from the | 62 | /* We use this as a place for the rd structure built from the |
95 | * last parsed country IE to rest until CRDA gets back to us with | 63 | * last parsed country IE to rest until CRDA gets back to us with |
@@ -790,42 +758,35 @@ static u32 map_regdom_flags(u32 rd_flags) | |||
790 | return channel_flags; | 758 | return channel_flags; |
791 | } | 759 | } |
792 | 760 | ||
793 | /** | 761 | static int freq_reg_info_regd(struct wiphy *wiphy, |
794 | * freq_reg_info - get regulatory information for the given frequency | 762 | u32 center_freq, |
795 | * @center_freq: Frequency in KHz for which we want regulatory information for | 763 | u32 *bandwidth, |
796 | * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one | 764 | const struct ieee80211_reg_rule **reg_rule, |
797 | * you can set this to 0. If this frequency is allowed we then set | 765 | const struct ieee80211_regdomain *custom_regd) |
798 | * this value to the maximum allowed bandwidth. | ||
799 | * @reg_rule: the regulatory rule which we have for this frequency | ||
800 | * | ||
801 | * Use this function to get the regulatory rule for a specific frequency on | ||
802 | * a given wireless device. If the device has a specific regulatory domain | ||
803 | * it wants to follow we respect that unless a country IE has been received | ||
804 | * and processed already. | ||
805 | * | ||
806 | * Returns 0 if it was able to find a valid regulatory rule which does | ||
807 | * apply to the given center_freq otherwise it returns non-zero. It will | ||
808 | * also return -ERANGE if we determine the given center_freq does not even have | ||
809 | * a regulatory rule for a frequency range in the center_freq's band. See | ||
810 | * freq_in_rule_band() for our current definition of a band -- this is purely | ||
811 | * subjective and right now its 802.11 specific. | ||
812 | */ | ||
813 | static int freq_reg_info(u32 center_freq, u32 *bandwidth, | ||
814 | const struct ieee80211_reg_rule **reg_rule) | ||
815 | { | 766 | { |
816 | int i; | 767 | int i; |
817 | bool band_rule_found = false; | 768 | bool band_rule_found = false; |
769 | const struct ieee80211_regdomain *regd; | ||
818 | u32 max_bandwidth = 0; | 770 | u32 max_bandwidth = 0; |
819 | 771 | ||
820 | if (!cfg80211_regdomain) | 772 | regd = custom_regd ? custom_regd : cfg80211_regdomain; |
773 | |||
774 | /* Follow the driver's regulatory domain, if present, unless a country | ||
775 | * IE has been processed or a user wants to help complaince further */ | ||
776 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && | ||
777 | last_request->initiator != REGDOM_SET_BY_USER && | ||
778 | wiphy->regd) | ||
779 | regd = wiphy->regd; | ||
780 | |||
781 | if (!regd) | ||
821 | return -EINVAL; | 782 | return -EINVAL; |
822 | 783 | ||
823 | for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { | 784 | for (i = 0; i < regd->n_reg_rules; i++) { |
824 | const struct ieee80211_reg_rule *rr; | 785 | const struct ieee80211_reg_rule *rr; |
825 | const struct ieee80211_freq_range *fr = NULL; | 786 | const struct ieee80211_freq_range *fr = NULL; |
826 | const struct ieee80211_power_rule *pr = NULL; | 787 | const struct ieee80211_power_rule *pr = NULL; |
827 | 788 | ||
828 | rr = &cfg80211_regdomain->reg_rules[i]; | 789 | rr = ®d->reg_rules[i]; |
829 | fr = &rr->freq_range; | 790 | fr = &rr->freq_range; |
830 | pr = &rr->power_rule; | 791 | pr = &rr->power_rule; |
831 | 792 | ||
@@ -849,6 +810,14 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth, | |||
849 | 810 | ||
850 | return !max_bandwidth; | 811 | return !max_bandwidth; |
851 | } | 812 | } |
813 | EXPORT_SYMBOL(freq_reg_info); | ||
814 | |||
815 | int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, | ||
816 | const struct ieee80211_reg_rule **reg_rule) | ||
817 | { | ||
818 | return freq_reg_info_regd(wiphy, center_freq, | ||
819 | bandwidth, reg_rule, NULL); | ||
820 | } | ||
852 | 821 | ||
853 | static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | 822 | static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, |
854 | unsigned int chan_idx) | 823 | unsigned int chan_idx) |
@@ -867,7 +836,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
867 | 836 | ||
868 | flags = chan->orig_flags; | 837 | flags = chan->orig_flags; |
869 | 838 | ||
870 | r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq), | 839 | r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq), |
871 | &max_bandwidth, ®_rule); | 840 | &max_bandwidth, ®_rule); |
872 | 841 | ||
873 | if (r) { | 842 | if (r) { |
@@ -907,6 +876,22 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
907 | 876 | ||
908 | power_rule = ®_rule->power_rule; | 877 | power_rule = ®_rule->power_rule; |
909 | 878 | ||
879 | if (last_request->initiator == REGDOM_SET_BY_DRIVER && | ||
880 | last_request->wiphy && last_request->wiphy == wiphy && | ||
881 | last_request->wiphy->strict_regulatory) { | ||
882 | /* This gaurantees the driver's requested regulatory domain | ||
883 | * will always be used as a base for further regulatory | ||
884 | * settings */ | ||
885 | chan->flags = chan->orig_flags = | ||
886 | map_regdom_flags(reg_rule->flags); | ||
887 | chan->max_antenna_gain = chan->orig_mag = | ||
888 | (int) MBI_TO_DBI(power_rule->max_antenna_gain); | ||
889 | chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); | ||
890 | chan->max_power = chan->orig_mpwr = | ||
891 | (int) MBM_TO_DBM(power_rule->max_eirp); | ||
892 | return; | ||
893 | } | ||
894 | |||
910 | chan->flags = flags | map_regdom_flags(reg_rule->flags); | 895 | chan->flags = flags | map_regdom_flags(reg_rule->flags); |
911 | chan->max_antenna_gain = min(chan->orig_mag, | 896 | chan->max_antenna_gain = min(chan->orig_mag, |
912 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); | 897 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); |
@@ -935,7 +920,12 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) | |||
935 | if (!last_request) | 920 | if (!last_request) |
936 | return true; | 921 | return true; |
937 | if (setby == REGDOM_SET_BY_CORE && | 922 | if (setby == REGDOM_SET_BY_CORE && |
938 | wiphy->fw_handles_regulatory) | 923 | wiphy->custom_regulatory) |
924 | return true; | ||
925 | /* wiphy->regd will be set once the device has its own | ||
926 | * desired regulatory domain set */ | ||
927 | if (wiphy->strict_regulatory && !wiphy->regd && | ||
928 | !is_world_regdom(last_request->alpha2)) | ||
939 | return true; | 929 | return true; |
940 | return false; | 930 | return false; |
941 | } | 931 | } |
@@ -945,20 +935,103 @@ static void update_all_wiphy_regulatory(enum reg_set_by setby) | |||
945 | struct cfg80211_registered_device *drv; | 935 | struct cfg80211_registered_device *drv; |
946 | 936 | ||
947 | list_for_each_entry(drv, &cfg80211_drv_list, list) | 937 | list_for_each_entry(drv, &cfg80211_drv_list, list) |
948 | if (!ignore_reg_update(&drv->wiphy, setby)) | 938 | wiphy_update_regulatory(&drv->wiphy, setby); |
949 | wiphy_update_regulatory(&drv->wiphy, setby); | ||
950 | } | 939 | } |
951 | 940 | ||
952 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) | 941 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) |
953 | { | 942 | { |
954 | enum ieee80211_band band; | 943 | enum ieee80211_band band; |
944 | |||
945 | if (ignore_reg_update(wiphy, setby)) | ||
946 | return; | ||
955 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 947 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
956 | if (wiphy->bands[band]) | 948 | if (wiphy->bands[band]) |
957 | handle_band(wiphy, band); | 949 | handle_band(wiphy, band); |
958 | if (wiphy->reg_notifier) | 950 | } |
959 | wiphy->reg_notifier(wiphy, setby); | 951 | if (wiphy->reg_notifier) |
952 | wiphy->reg_notifier(wiphy, last_request); | ||
953 | } | ||
954 | |||
955 | static void handle_channel_custom(struct wiphy *wiphy, | ||
956 | enum ieee80211_band band, | ||
957 | unsigned int chan_idx, | ||
958 | const struct ieee80211_regdomain *regd) | ||
959 | { | ||
960 | int r; | ||
961 | u32 max_bandwidth = 0; | ||
962 | const struct ieee80211_reg_rule *reg_rule = NULL; | ||
963 | const struct ieee80211_power_rule *power_rule = NULL; | ||
964 | struct ieee80211_supported_band *sband; | ||
965 | struct ieee80211_channel *chan; | ||
966 | |||
967 | sband = wiphy->bands[band]; | ||
968 | BUG_ON(chan_idx >= sband->n_channels); | ||
969 | chan = &sband->channels[chan_idx]; | ||
970 | |||
971 | r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), | ||
972 | &max_bandwidth, ®_rule, regd); | ||
973 | |||
974 | if (r) { | ||
975 | chan->flags = IEEE80211_CHAN_DISABLED; | ||
976 | return; | ||
977 | } | ||
978 | |||
979 | power_rule = ®_rule->power_rule; | ||
980 | |||
981 | chan->flags |= map_regdom_flags(reg_rule->flags); | ||
982 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); | ||
983 | chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); | ||
984 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | ||
985 | } | ||
986 | |||
987 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, | ||
988 | const struct ieee80211_regdomain *regd) | ||
989 | { | ||
990 | unsigned int i; | ||
991 | struct ieee80211_supported_band *sband; | ||
992 | |||
993 | BUG_ON(!wiphy->bands[band]); | ||
994 | sband = wiphy->bands[band]; | ||
995 | |||
996 | for (i = 0; i < sband->n_channels; i++) | ||
997 | handle_channel_custom(wiphy, band, i, regd); | ||
998 | } | ||
999 | |||
1000 | /* Used by drivers prior to wiphy registration */ | ||
1001 | void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | ||
1002 | const struct ieee80211_regdomain *regd) | ||
1003 | { | ||
1004 | enum ieee80211_band band; | ||
1005 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1006 | if (wiphy->bands[band]) | ||
1007 | handle_band_custom(wiphy, band, regd); | ||
960 | } | 1008 | } |
961 | } | 1009 | } |
1010 | EXPORT_SYMBOL(wiphy_apply_custom_regulatory); | ||
1011 | |||
1012 | static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, | ||
1013 | const struct ieee80211_regdomain *src_regd) | ||
1014 | { | ||
1015 | struct ieee80211_regdomain *regd; | ||
1016 | int size_of_regd = 0; | ||
1017 | unsigned int i; | ||
1018 | |||
1019 | size_of_regd = sizeof(struct ieee80211_regdomain) + | ||
1020 | ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule)); | ||
1021 | |||
1022 | regd = kzalloc(size_of_regd, GFP_KERNEL); | ||
1023 | if (!regd) | ||
1024 | return -ENOMEM; | ||
1025 | |||
1026 | memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); | ||
1027 | |||
1028 | for (i = 0; i < src_regd->n_reg_rules; i++) | ||
1029 | memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], | ||
1030 | sizeof(struct ieee80211_reg_rule)); | ||
1031 | |||
1032 | *dst_regd = regd; | ||
1033 | return 0; | ||
1034 | } | ||
962 | 1035 | ||
963 | /* Return value which can be used by ignore_request() to indicate | 1036 | /* Return value which can be used by ignore_request() to indicate |
964 | * it has been determined we should intersect two regulatory domains */ | 1037 | * it has been determined we should intersect two regulatory domains */ |
@@ -1007,9 +1080,14 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
1007 | } | 1080 | } |
1008 | return REG_INTERSECT; | 1081 | return REG_INTERSECT; |
1009 | case REGDOM_SET_BY_DRIVER: | 1082 | case REGDOM_SET_BY_DRIVER: |
1010 | if (last_request->initiator == REGDOM_SET_BY_DRIVER) | 1083 | if (last_request->initiator == REGDOM_SET_BY_CORE) { |
1084 | if (is_old_static_regdom(cfg80211_regdomain)) | ||
1085 | return 0; | ||
1086 | if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) | ||
1087 | return 0; | ||
1011 | return -EALREADY; | 1088 | return -EALREADY; |
1012 | return 0; | 1089 | } |
1090 | return REG_INTERSECT; | ||
1013 | case REGDOM_SET_BY_USER: | 1091 | case REGDOM_SET_BY_USER: |
1014 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) | 1092 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) |
1015 | return REG_INTERSECT; | 1093 | return REG_INTERSECT; |
@@ -1018,6 +1096,20 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
1018 | if (last_request->initiator == REGDOM_SET_BY_USER && | 1096 | if (last_request->initiator == REGDOM_SET_BY_USER && |
1019 | last_request->intersect) | 1097 | last_request->intersect) |
1020 | return -EOPNOTSUPP; | 1098 | return -EOPNOTSUPP; |
1099 | /* Process user requests only after previous user/driver/core | ||
1100 | * requests have been processed */ | ||
1101 | if (last_request->initiator == REGDOM_SET_BY_CORE || | ||
1102 | last_request->initiator == REGDOM_SET_BY_DRIVER || | ||
1103 | last_request->initiator == REGDOM_SET_BY_USER) { | ||
1104 | if (!alpha2_equal(last_request->alpha2, | ||
1105 | cfg80211_regdomain->alpha2)) | ||
1106 | return -EAGAIN; | ||
1107 | } | ||
1108 | |||
1109 | if (!is_old_static_regdom(cfg80211_regdomain) && | ||
1110 | alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) | ||
1111 | return -EALREADY; | ||
1112 | |||
1021 | return 0; | 1113 | return 0; |
1022 | } | 1114 | } |
1023 | 1115 | ||
@@ -1036,11 +1128,28 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | |||
1036 | 1128 | ||
1037 | r = ignore_request(wiphy, set_by, alpha2); | 1129 | r = ignore_request(wiphy, set_by, alpha2); |
1038 | 1130 | ||
1039 | if (r == REG_INTERSECT) | 1131 | if (r == REG_INTERSECT) { |
1132 | if (set_by == REGDOM_SET_BY_DRIVER) { | ||
1133 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); | ||
1134 | if (r) | ||
1135 | return r; | ||
1136 | } | ||
1040 | intersect = true; | 1137 | intersect = true; |
1041 | else if (r) | 1138 | } else if (r) { |
1139 | /* If the regulatory domain being requested by the | ||
1140 | * driver has already been set just copy it to the | ||
1141 | * wiphy */ | ||
1142 | if (r == -EALREADY && set_by == REGDOM_SET_BY_DRIVER) { | ||
1143 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); | ||
1144 | if (r) | ||
1145 | return r; | ||
1146 | r = -EALREADY; | ||
1147 | goto new_request; | ||
1148 | } | ||
1042 | return r; | 1149 | return r; |
1150 | } | ||
1043 | 1151 | ||
1152 | new_request: | ||
1044 | request = kzalloc(sizeof(struct regulatory_request), | 1153 | request = kzalloc(sizeof(struct regulatory_request), |
1045 | GFP_KERNEL); | 1154 | GFP_KERNEL); |
1046 | if (!request) | 1155 | if (!request) |
@@ -1056,6 +1165,11 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | |||
1056 | 1165 | ||
1057 | kfree(last_request); | 1166 | kfree(last_request); |
1058 | last_request = request; | 1167 | last_request = request; |
1168 | |||
1169 | /* When r == REG_INTERSECT we do need to call CRDA */ | ||
1170 | if (r < 0) | ||
1171 | return r; | ||
1172 | |||
1059 | /* | 1173 | /* |
1060 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled | 1174 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled |
1061 | * AND if CRDA is NOT present nothing will happen, if someone | 1175 | * AND if CRDA is NOT present nothing will happen, if someone |
@@ -1071,10 +1185,15 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | |||
1071 | 1185 | ||
1072 | void regulatory_hint(struct wiphy *wiphy, const char *alpha2) | 1186 | void regulatory_hint(struct wiphy *wiphy, const char *alpha2) |
1073 | { | 1187 | { |
1188 | int r; | ||
1074 | BUG_ON(!alpha2); | 1189 | BUG_ON(!alpha2); |
1075 | 1190 | ||
1076 | mutex_lock(&cfg80211_drv_mutex); | 1191 | mutex_lock(&cfg80211_drv_mutex); |
1077 | __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, 0, ENVIRON_ANY); | 1192 | r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, |
1193 | alpha2, 0, ENVIRON_ANY); | ||
1194 | /* This is required so that the orig_* parameters are saved */ | ||
1195 | if (r == -EALREADY && wiphy->strict_regulatory) | ||
1196 | wiphy_update_regulatory(wiphy, REGDOM_SET_BY_DRIVER); | ||
1078 | mutex_unlock(&cfg80211_drv_mutex); | 1197 | mutex_unlock(&cfg80211_drv_mutex); |
1079 | } | 1198 | } |
1080 | EXPORT_SYMBOL(regulatory_hint); | 1199 | EXPORT_SYMBOL(regulatory_hint); |
@@ -1247,7 +1366,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
1247 | "domain intersected: \n"); | 1366 | "domain intersected: \n"); |
1248 | } else | 1367 | } else |
1249 | printk(KERN_INFO "cfg80211: Current regulatory " | 1368 | printk(KERN_INFO "cfg80211: Current regulatory " |
1250 | "intersected: \n"); | 1369 | "domain intersected: \n"); |
1251 | } else if (is_world_regdom(rd->alpha2)) | 1370 | } else if (is_world_regdom(rd->alpha2)) |
1252 | printk(KERN_INFO "cfg80211: World regulatory " | 1371 | printk(KERN_INFO "cfg80211: World regulatory " |
1253 | "domain updated:\n"); | 1372 | "domain updated:\n"); |
@@ -1349,6 +1468,23 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1349 | } | 1468 | } |
1350 | 1469 | ||
1351 | if (!last_request->intersect) { | 1470 | if (!last_request->intersect) { |
1471 | int r; | ||
1472 | |||
1473 | if (last_request->initiator != REGDOM_SET_BY_DRIVER) { | ||
1474 | reset_regdomains(); | ||
1475 | cfg80211_regdomain = rd; | ||
1476 | return 0; | ||
1477 | } | ||
1478 | |||
1479 | /* For a driver hint, lets copy the regulatory domain the | ||
1480 | * driver wanted to the wiphy to deal with conflicts */ | ||
1481 | |||
1482 | BUG_ON(last_request->wiphy->regd); | ||
1483 | |||
1484 | r = reg_copy_regd(&last_request->wiphy->regd, rd); | ||
1485 | if (r) | ||
1486 | return r; | ||
1487 | |||
1352 | reset_regdomains(); | 1488 | reset_regdomains(); |
1353 | cfg80211_regdomain = rd; | 1489 | cfg80211_regdomain = rd; |
1354 | return 0; | 1490 | return 0; |
@@ -1362,8 +1498,14 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1362 | if (!intersected_rd) | 1498 | if (!intersected_rd) |
1363 | return -EINVAL; | 1499 | return -EINVAL; |
1364 | 1500 | ||
1365 | /* We can trash what CRDA provided now */ | 1501 | /* We can trash what CRDA provided now. |
1366 | kfree(rd); | 1502 | * However if a driver requested this specific regulatory |
1503 | * domain we keep it for its private use */ | ||
1504 | if (last_request->initiator == REGDOM_SET_BY_DRIVER) | ||
1505 | last_request->wiphy->regd = rd; | ||
1506 | else | ||
1507 | kfree(rd); | ||
1508 | |||
1367 | rd = NULL; | 1509 | rd = NULL; |
1368 | 1510 | ||
1369 | reset_regdomains(); | 1511 | reset_regdomains(); |
@@ -1447,6 +1589,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
1447 | /* Caller must hold cfg80211_drv_mutex */ | 1589 | /* Caller must hold cfg80211_drv_mutex */ |
1448 | void reg_device_remove(struct wiphy *wiphy) | 1590 | void reg_device_remove(struct wiphy *wiphy) |
1449 | { | 1591 | { |
1592 | kfree(wiphy->regd); | ||
1450 | if (!last_request || !last_request->wiphy) | 1593 | if (!last_request || !last_request->wiphy) |
1451 | return; | 1594 | return; |
1452 | if (last_request->wiphy != wiphy) | 1595 | if (last_request->wiphy != wiphy) |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index a76ea3ff7cd6..fe8c83f34fb7 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef __NET_WIRELESS_REG_H | 1 | #ifndef __NET_WIRELESS_REG_H |
2 | #define __NET_WIRELESS_REG_H | 2 | #define __NET_WIRELESS_REG_H |
3 | 3 | ||
4 | extern const struct ieee80211_regdomain *cfg80211_regdomain; | ||
5 | |||
4 | bool is_world_regdom(const char *alpha2); | 6 | bool is_world_regdom(const char *alpha2); |
5 | bool reg_is_valid_request(const char *alpha2); | 7 | bool reg_is_valid_request(const char *alpha2); |
6 | 8 | ||
@@ -11,13 +13,6 @@ void regulatory_exit(void); | |||
11 | 13 | ||
12 | int set_regdom(const struct ieee80211_regdomain *rd); | 14 | int set_regdom(const struct ieee80211_regdomain *rd); |
13 | 15 | ||
14 | enum environment_cap { | ||
15 | ENVIRON_ANY, | ||
16 | ENVIRON_INDOOR, | ||
17 | ENVIRON_OUTDOOR, | ||
18 | }; | ||
19 | |||
20 | |||
21 | /** | 16 | /** |
22 | * __regulatory_hint - hint to the wireless core a regulatory domain | 17 | * __regulatory_hint - hint to the wireless core a regulatory domain |
23 | * @wiphy: if the hint comes from country information from an AP, this | 18 | * @wiphy: if the hint comes from country information from an AP, this |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c new file mode 100644 index 000000000000..b1893c863b97 --- /dev/null +++ b/net/wireless/scan.c | |||
@@ -0,0 +1,836 @@ | |||
1 | /* | ||
2 | * cfg80211 scan result handling | ||
3 | * | ||
4 | * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> | ||
5 | */ | ||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/netdevice.h> | ||
9 | #include <linux/wireless.h> | ||
10 | #include <linux/nl80211.h> | ||
11 | #include <linux/etherdevice.h> | ||
12 | #include <net/arp.h> | ||
13 | #include <net/cfg80211.h> | ||
14 | #include <net/iw_handler.h> | ||
15 | #include "core.h" | ||
16 | #include "nl80211.h" | ||
17 | |||
18 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | ||
19 | |||
20 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | ||
21 | { | ||
22 | struct net_device *dev; | ||
23 | #ifdef CONFIG_WIRELESS_EXT | ||
24 | union iwreq_data wrqu; | ||
25 | #endif | ||
26 | |||
27 | dev = dev_get_by_index(&init_net, request->ifidx); | ||
28 | if (!dev) | ||
29 | goto out; | ||
30 | |||
31 | WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); | ||
32 | wiphy_to_dev(request->wiphy)->scan_req = NULL; | ||
33 | |||
34 | if (aborted) | ||
35 | nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev); | ||
36 | else | ||
37 | nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); | ||
38 | |||
39 | #ifdef CONFIG_WIRELESS_EXT | ||
40 | if (!aborted) { | ||
41 | memset(&wrqu, 0, sizeof(wrqu)); | ||
42 | |||
43 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | dev_put(dev); | ||
48 | |||
49 | out: | ||
50 | kfree(request); | ||
51 | } | ||
52 | EXPORT_SYMBOL(cfg80211_scan_done); | ||
53 | |||
54 | static void bss_release(struct kref *ref) | ||
55 | { | ||
56 | struct cfg80211_internal_bss *bss; | ||
57 | |||
58 | bss = container_of(ref, struct cfg80211_internal_bss, ref); | ||
59 | if (bss->pub.free_priv) | ||
60 | bss->pub.free_priv(&bss->pub); | ||
61 | kfree(bss); | ||
62 | } | ||
63 | |||
64 | /* must hold dev->bss_lock! */ | ||
65 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev) | ||
66 | { | ||
67 | struct cfg80211_internal_bss *bss, *tmp; | ||
68 | bool expired = false; | ||
69 | |||
70 | list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) { | ||
71 | if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
72 | continue; | ||
73 | list_del(&bss->list); | ||
74 | rb_erase(&bss->rbn, &dev->bss_tree); | ||
75 | kref_put(&bss->ref, bss_release); | ||
76 | expired = true; | ||
77 | } | ||
78 | |||
79 | if (expired) | ||
80 | dev->bss_generation++; | ||
81 | } | ||
82 | |||
83 | static u8 *find_ie(u8 num, u8 *ies, size_t len) | ||
84 | { | ||
85 | while (len > 2 && ies[0] != num) { | ||
86 | len -= ies[1] + 2; | ||
87 | ies += ies[1] + 2; | ||
88 | } | ||
89 | if (len < 2) | ||
90 | return NULL; | ||
91 | if (len < 2 + ies[1]) | ||
92 | return NULL; | ||
93 | return ies; | ||
94 | } | ||
95 | |||
96 | static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) | ||
97 | { | ||
98 | const u8 *ie1 = find_ie(num, ies1, len1); | ||
99 | const u8 *ie2 = find_ie(num, ies2, len2); | ||
100 | int r; | ||
101 | |||
102 | if (!ie1 && !ie2) | ||
103 | return 0; | ||
104 | if (!ie1) | ||
105 | return -1; | ||
106 | |||
107 | r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1])); | ||
108 | if (r == 0 && ie1[1] != ie2[1]) | ||
109 | return ie2[1] - ie1[1]; | ||
110 | return r; | ||
111 | } | ||
112 | |||
113 | static bool is_bss(struct cfg80211_bss *a, | ||
114 | const u8 *bssid, | ||
115 | const u8 *ssid, size_t ssid_len) | ||
116 | { | ||
117 | const u8 *ssidie; | ||
118 | |||
119 | if (bssid && compare_ether_addr(a->bssid, bssid)) | ||
120 | return false; | ||
121 | |||
122 | if (!ssid) | ||
123 | return true; | ||
124 | |||
125 | ssidie = find_ie(WLAN_EID_SSID, | ||
126 | a->information_elements, | ||
127 | a->len_information_elements); | ||
128 | if (!ssidie) | ||
129 | return false; | ||
130 | if (ssidie[1] != ssid_len) | ||
131 | return false; | ||
132 | return memcmp(ssidie + 2, ssid, ssid_len) == 0; | ||
133 | } | ||
134 | |||
135 | static bool is_mesh(struct cfg80211_bss *a, | ||
136 | const u8 *meshid, size_t meshidlen, | ||
137 | const u8 *meshcfg) | ||
138 | { | ||
139 | const u8 *ie; | ||
140 | |||
141 | if (!is_zero_ether_addr(a->bssid)) | ||
142 | return false; | ||
143 | |||
144 | ie = find_ie(WLAN_EID_MESH_ID, | ||
145 | a->information_elements, | ||
146 | a->len_information_elements); | ||
147 | if (!ie) | ||
148 | return false; | ||
149 | if (ie[1] != meshidlen) | ||
150 | return false; | ||
151 | if (memcmp(ie + 2, meshid, meshidlen)) | ||
152 | return false; | ||
153 | |||
154 | ie = find_ie(WLAN_EID_MESH_CONFIG, | ||
155 | a->information_elements, | ||
156 | a->len_information_elements); | ||
157 | if (ie[1] != IEEE80211_MESH_CONFIG_LEN) | ||
158 | return false; | ||
159 | |||
160 | /* | ||
161 | * Ignore mesh capability (last two bytes of the IE) when | ||
162 | * comparing since that may differ between stations taking | ||
163 | * part in the same mesh. | ||
164 | */ | ||
165 | return memcmp(ie + 2, meshcfg, IEEE80211_MESH_CONFIG_LEN - 2) == 0; | ||
166 | } | ||
167 | |||
168 | static int cmp_bss(struct cfg80211_bss *a, | ||
169 | struct cfg80211_bss *b) | ||
170 | { | ||
171 | int r; | ||
172 | |||
173 | if (a->channel != b->channel) | ||
174 | return b->channel->center_freq - a->channel->center_freq; | ||
175 | |||
176 | r = memcmp(a->bssid, b->bssid, ETH_ALEN); | ||
177 | if (r) | ||
178 | return r; | ||
179 | |||
180 | if (is_zero_ether_addr(a->bssid)) { | ||
181 | r = cmp_ies(WLAN_EID_MESH_ID, | ||
182 | a->information_elements, | ||
183 | a->len_information_elements, | ||
184 | b->information_elements, | ||
185 | b->len_information_elements); | ||
186 | if (r) | ||
187 | return r; | ||
188 | return cmp_ies(WLAN_EID_MESH_CONFIG, | ||
189 | a->information_elements, | ||
190 | a->len_information_elements, | ||
191 | b->information_elements, | ||
192 | b->len_information_elements); | ||
193 | } | ||
194 | |||
195 | return cmp_ies(WLAN_EID_SSID, | ||
196 | a->information_elements, | ||
197 | a->len_information_elements, | ||
198 | b->information_elements, | ||
199 | b->len_information_elements); | ||
200 | } | ||
201 | |||
202 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | ||
203 | struct ieee80211_channel *channel, | ||
204 | const u8 *bssid, | ||
205 | const u8 *ssid, size_t ssid_len, | ||
206 | u16 capa_mask, u16 capa_val) | ||
207 | { | ||
208 | struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); | ||
209 | struct cfg80211_internal_bss *bss, *res = NULL; | ||
210 | |||
211 | spin_lock_bh(&dev->bss_lock); | ||
212 | |||
213 | list_for_each_entry(bss, &dev->bss_list, list) { | ||
214 | if ((bss->pub.capability & capa_mask) != capa_val) | ||
215 | continue; | ||
216 | if (channel && bss->pub.channel != channel) | ||
217 | continue; | ||
218 | if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { | ||
219 | res = bss; | ||
220 | kref_get(&res->ref); | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | spin_unlock_bh(&dev->bss_lock); | ||
226 | if (!res) | ||
227 | return NULL; | ||
228 | return &res->pub; | ||
229 | } | ||
230 | EXPORT_SYMBOL(cfg80211_get_bss); | ||
231 | |||
232 | struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, | ||
233 | struct ieee80211_channel *channel, | ||
234 | const u8 *meshid, size_t meshidlen, | ||
235 | const u8 *meshcfg) | ||
236 | { | ||
237 | struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); | ||
238 | struct cfg80211_internal_bss *bss, *res = NULL; | ||
239 | |||
240 | spin_lock_bh(&dev->bss_lock); | ||
241 | |||
242 | list_for_each_entry(bss, &dev->bss_list, list) { | ||
243 | if (channel && bss->pub.channel != channel) | ||
244 | continue; | ||
245 | if (is_mesh(&bss->pub, meshid, meshidlen, meshcfg)) { | ||
246 | res = bss; | ||
247 | kref_get(&res->ref); | ||
248 | break; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | spin_unlock_bh(&dev->bss_lock); | ||
253 | if (!res) | ||
254 | return NULL; | ||
255 | return &res->pub; | ||
256 | } | ||
257 | EXPORT_SYMBOL(cfg80211_get_mesh); | ||
258 | |||
259 | |||
260 | static void rb_insert_bss(struct cfg80211_registered_device *dev, | ||
261 | struct cfg80211_internal_bss *bss) | ||
262 | { | ||
263 | struct rb_node **p = &dev->bss_tree.rb_node; | ||
264 | struct rb_node *parent = NULL; | ||
265 | struct cfg80211_internal_bss *tbss; | ||
266 | int cmp; | ||
267 | |||
268 | while (*p) { | ||
269 | parent = *p; | ||
270 | tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn); | ||
271 | |||
272 | cmp = cmp_bss(&bss->pub, &tbss->pub); | ||
273 | |||
274 | if (WARN_ON(!cmp)) { | ||
275 | /* will sort of leak this BSS */ | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | if (cmp < 0) | ||
280 | p = &(*p)->rb_left; | ||
281 | else | ||
282 | p = &(*p)->rb_right; | ||
283 | } | ||
284 | |||
285 | rb_link_node(&bss->rbn, parent, p); | ||
286 | rb_insert_color(&bss->rbn, &dev->bss_tree); | ||
287 | } | ||
288 | |||
289 | static struct cfg80211_internal_bss * | ||
290 | rb_find_bss(struct cfg80211_registered_device *dev, | ||
291 | struct cfg80211_internal_bss *res) | ||
292 | { | ||
293 | struct rb_node *n = dev->bss_tree.rb_node; | ||
294 | struct cfg80211_internal_bss *bss; | ||
295 | int r; | ||
296 | |||
297 | while (n) { | ||
298 | bss = rb_entry(n, struct cfg80211_internal_bss, rbn); | ||
299 | r = cmp_bss(&res->pub, &bss->pub); | ||
300 | |||
301 | if (r == 0) | ||
302 | return bss; | ||
303 | else if (r < 0) | ||
304 | n = n->rb_left; | ||
305 | else | ||
306 | n = n->rb_right; | ||
307 | } | ||
308 | |||
309 | return NULL; | ||
310 | } | ||
311 | |||
312 | static struct cfg80211_internal_bss * | ||
313 | cfg80211_bss_update(struct cfg80211_registered_device *dev, | ||
314 | struct cfg80211_internal_bss *res, | ||
315 | bool overwrite) | ||
316 | { | ||
317 | struct cfg80211_internal_bss *found = NULL; | ||
318 | const u8 *meshid, *meshcfg; | ||
319 | |||
320 | /* | ||
321 | * The reference to "res" is donated to this function. | ||
322 | */ | ||
323 | |||
324 | if (WARN_ON(!res->pub.channel)) { | ||
325 | kref_put(&res->ref, bss_release); | ||
326 | return NULL; | ||
327 | } | ||
328 | |||
329 | res->ts = jiffies; | ||
330 | |||
331 | if (is_zero_ether_addr(res->pub.bssid)) { | ||
332 | /* must be mesh, verify */ | ||
333 | meshid = find_ie(WLAN_EID_MESH_ID, res->pub.information_elements, | ||
334 | res->pub.len_information_elements); | ||
335 | meshcfg = find_ie(WLAN_EID_MESH_CONFIG, | ||
336 | res->pub.information_elements, | ||
337 | res->pub.len_information_elements); | ||
338 | if (!meshid || !meshcfg || | ||
339 | meshcfg[1] != IEEE80211_MESH_CONFIG_LEN) { | ||
340 | /* bogus mesh */ | ||
341 | kref_put(&res->ref, bss_release); | ||
342 | return NULL; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | spin_lock_bh(&dev->bss_lock); | ||
347 | |||
348 | found = rb_find_bss(dev, res); | ||
349 | |||
350 | if (found && overwrite) { | ||
351 | list_replace(&found->list, &res->list); | ||
352 | rb_replace_node(&found->rbn, &res->rbn, | ||
353 | &dev->bss_tree); | ||
354 | kref_put(&found->ref, bss_release); | ||
355 | found = res; | ||
356 | } else if (found) { | ||
357 | kref_get(&found->ref); | ||
358 | found->pub.beacon_interval = res->pub.beacon_interval; | ||
359 | found->pub.tsf = res->pub.tsf; | ||
360 | found->pub.signal = res->pub.signal; | ||
361 | found->pub.signal_type = res->pub.signal_type; | ||
362 | found->pub.capability = res->pub.capability; | ||
363 | found->ts = res->ts; | ||
364 | kref_put(&res->ref, bss_release); | ||
365 | } else { | ||
366 | /* this "consumes" the reference */ | ||
367 | list_add_tail(&res->list, &dev->bss_list); | ||
368 | rb_insert_bss(dev, res); | ||
369 | found = res; | ||
370 | } | ||
371 | |||
372 | dev->bss_generation++; | ||
373 | spin_unlock_bh(&dev->bss_lock); | ||
374 | |||
375 | kref_get(&found->ref); | ||
376 | return found; | ||
377 | } | ||
378 | |||
379 | struct cfg80211_bss * | ||
380 | cfg80211_inform_bss_frame(struct wiphy *wiphy, | ||
381 | struct ieee80211_channel *channel, | ||
382 | struct ieee80211_mgmt *mgmt, size_t len, | ||
383 | s32 signal, enum cfg80211_signal_type sigtype, | ||
384 | gfp_t gfp) | ||
385 | { | ||
386 | struct cfg80211_internal_bss *res; | ||
387 | size_t ielen = len - offsetof(struct ieee80211_mgmt, | ||
388 | u.probe_resp.variable); | ||
389 | bool overwrite; | ||
390 | size_t privsz = wiphy->bss_priv_size; | ||
391 | |||
392 | if (WARN_ON(sigtype == NL80211_BSS_SIGNAL_UNSPEC && | ||
393 | (signal < 0 || signal > 100))) | ||
394 | return NULL; | ||
395 | |||
396 | if (WARN_ON(!mgmt || !wiphy || | ||
397 | len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) | ||
398 | return NULL; | ||
399 | |||
400 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); | ||
401 | if (!res) | ||
402 | return NULL; | ||
403 | |||
404 | memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN); | ||
405 | res->pub.channel = channel; | ||
406 | res->pub.signal_type = sigtype; | ||
407 | res->pub.signal = signal; | ||
408 | res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); | ||
409 | res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); | ||
410 | res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); | ||
411 | /* point to after the private area */ | ||
412 | res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; | ||
413 | memcpy(res->pub.information_elements, mgmt->u.probe_resp.variable, ielen); | ||
414 | res->pub.len_information_elements = ielen; | ||
415 | |||
416 | kref_init(&res->ref); | ||
417 | |||
418 | overwrite = ieee80211_is_probe_resp(mgmt->frame_control); | ||
419 | |||
420 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, overwrite); | ||
421 | if (!res) | ||
422 | return NULL; | ||
423 | |||
424 | /* cfg80211_bss_update gives us a referenced result */ | ||
425 | return &res->pub; | ||
426 | } | ||
427 | EXPORT_SYMBOL(cfg80211_inform_bss_frame); | ||
428 | |||
429 | void cfg80211_put_bss(struct cfg80211_bss *pub) | ||
430 | { | ||
431 | struct cfg80211_internal_bss *bss; | ||
432 | |||
433 | if (!pub) | ||
434 | return; | ||
435 | |||
436 | bss = container_of(pub, struct cfg80211_internal_bss, pub); | ||
437 | kref_put(&bss->ref, bss_release); | ||
438 | } | ||
439 | EXPORT_SYMBOL(cfg80211_put_bss); | ||
440 | |||
441 | void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | ||
442 | { | ||
443 | struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); | ||
444 | struct cfg80211_internal_bss *bss; | ||
445 | |||
446 | if (WARN_ON(!pub)) | ||
447 | return; | ||
448 | |||
449 | bss = container_of(pub, struct cfg80211_internal_bss, pub); | ||
450 | |||
451 | spin_lock_bh(&dev->bss_lock); | ||
452 | |||
453 | list_del(&bss->list); | ||
454 | rb_erase(&bss->rbn, &dev->bss_tree); | ||
455 | |||
456 | spin_unlock_bh(&dev->bss_lock); | ||
457 | |||
458 | kref_put(&bss->ref, bss_release); | ||
459 | } | ||
460 | EXPORT_SYMBOL(cfg80211_unlink_bss); | ||
461 | |||
462 | #ifdef CONFIG_WIRELESS_EXT | ||
463 | int cfg80211_wext_siwscan(struct net_device *dev, | ||
464 | struct iw_request_info *info, | ||
465 | union iwreq_data *wrqu, char *extra) | ||
466 | { | ||
467 | struct cfg80211_registered_device *rdev; | ||
468 | struct wiphy *wiphy; | ||
469 | struct iw_scan_req *wreq = NULL; | ||
470 | struct cfg80211_scan_request *creq; | ||
471 | int i, err, n_channels = 0; | ||
472 | enum ieee80211_band band; | ||
473 | |||
474 | if (!netif_running(dev)) | ||
475 | return -ENETDOWN; | ||
476 | |||
477 | rdev = cfg80211_get_dev_from_ifindex(dev->ifindex); | ||
478 | |||
479 | if (IS_ERR(rdev)) | ||
480 | return PTR_ERR(rdev); | ||
481 | |||
482 | if (rdev->scan_req) { | ||
483 | err = -EBUSY; | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | wiphy = &rdev->wiphy; | ||
488 | |||
489 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) | ||
490 | if (wiphy->bands[band]) | ||
491 | n_channels += wiphy->bands[band]->n_channels; | ||
492 | |||
493 | creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + | ||
494 | n_channels * sizeof(void *), | ||
495 | GFP_ATOMIC); | ||
496 | if (!creq) { | ||
497 | err = -ENOMEM; | ||
498 | goto out; | ||
499 | } | ||
500 | |||
501 | creq->wiphy = wiphy; | ||
502 | creq->ifidx = dev->ifindex; | ||
503 | creq->ssids = (void *)(creq + 1); | ||
504 | creq->channels = (void *)(creq->ssids + 1); | ||
505 | creq->n_channels = n_channels; | ||
506 | creq->n_ssids = 1; | ||
507 | |||
508 | /* all channels */ | ||
509 | i = 0; | ||
510 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
511 | int j; | ||
512 | if (!wiphy->bands[band]) | ||
513 | continue; | ||
514 | for (j = 0; j < wiphy->bands[band]->n_channels; j++) { | ||
515 | creq->channels[i] = &wiphy->bands[band]->channels[j]; | ||
516 | i++; | ||
517 | } | ||
518 | } | ||
519 | |||
520 | /* translate scan request */ | ||
521 | if (wrqu->data.length == sizeof(struct iw_scan_req)) { | ||
522 | wreq = (struct iw_scan_req *)extra; | ||
523 | |||
524 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { | ||
525 | if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) | ||
526 | return -EINVAL; | ||
527 | memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); | ||
528 | creq->ssids[0].ssid_len = wreq->essid_len; | ||
529 | } | ||
530 | if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE) | ||
531 | creq->n_ssids = 0; | ||
532 | } | ||
533 | |||
534 | rdev->scan_req = creq; | ||
535 | err = rdev->ops->scan(wiphy, dev, creq); | ||
536 | if (err) { | ||
537 | rdev->scan_req = NULL; | ||
538 | kfree(creq); | ||
539 | } | ||
540 | out: | ||
541 | cfg80211_put_dev(rdev); | ||
542 | return err; | ||
543 | } | ||
544 | EXPORT_SYMBOL(cfg80211_wext_siwscan); | ||
545 | |||
546 | static void ieee80211_scan_add_ies(struct iw_request_info *info, | ||
547 | struct cfg80211_bss *bss, | ||
548 | char **current_ev, char *end_buf) | ||
549 | { | ||
550 | u8 *pos, *end, *next; | ||
551 | struct iw_event iwe; | ||
552 | |||
553 | if (!bss->information_elements || | ||
554 | !bss->len_information_elements) | ||
555 | return; | ||
556 | |||
557 | /* | ||
558 | * If needed, fragment the IEs buffer (at IE boundaries) into short | ||
559 | * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. | ||
560 | */ | ||
561 | pos = bss->information_elements; | ||
562 | end = pos + bss->len_information_elements; | ||
563 | |||
564 | while (end - pos > IW_GENERIC_IE_MAX) { | ||
565 | next = pos + 2 + pos[1]; | ||
566 | while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) | ||
567 | next = next + 2 + next[1]; | ||
568 | |||
569 | memset(&iwe, 0, sizeof(iwe)); | ||
570 | iwe.cmd = IWEVGENIE; | ||
571 | iwe.u.data.length = next - pos; | ||
572 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
573 | end_buf, &iwe, pos); | ||
574 | |||
575 | pos = next; | ||
576 | } | ||
577 | |||
578 | if (end > pos) { | ||
579 | memset(&iwe, 0, sizeof(iwe)); | ||
580 | iwe.cmd = IWEVGENIE; | ||
581 | iwe.u.data.length = end - pos; | ||
582 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
583 | end_buf, &iwe, pos); | ||
584 | } | ||
585 | } | ||
586 | |||
587 | |||
588 | static char * | ||
589 | ieee80211_bss(struct iw_request_info *info, | ||
590 | struct cfg80211_internal_bss *bss, | ||
591 | char *current_ev, char *end_buf) | ||
592 | { | ||
593 | struct iw_event iwe; | ||
594 | u8 *buf, *cfg, *p; | ||
595 | u8 *ie = bss->pub.information_elements; | ||
596 | int rem = bss->pub.len_information_elements, i; | ||
597 | bool ismesh = false; | ||
598 | |||
599 | memset(&iwe, 0, sizeof(iwe)); | ||
600 | iwe.cmd = SIOCGIWAP; | ||
601 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
602 | memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN); | ||
603 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
604 | IW_EV_ADDR_LEN); | ||
605 | |||
606 | memset(&iwe, 0, sizeof(iwe)); | ||
607 | iwe.cmd = SIOCGIWFREQ; | ||
608 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq); | ||
609 | iwe.u.freq.e = 0; | ||
610 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
611 | IW_EV_FREQ_LEN); | ||
612 | |||
613 | memset(&iwe, 0, sizeof(iwe)); | ||
614 | iwe.cmd = SIOCGIWFREQ; | ||
615 | iwe.u.freq.m = bss->pub.channel->center_freq; | ||
616 | iwe.u.freq.e = 6; | ||
617 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
618 | IW_EV_FREQ_LEN); | ||
619 | |||
620 | if (bss->pub.signal_type != CFG80211_SIGNAL_TYPE_NONE) { | ||
621 | memset(&iwe, 0, sizeof(iwe)); | ||
622 | iwe.cmd = IWEVQUAL; | ||
623 | iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED | | ||
624 | IW_QUAL_NOISE_INVALID | | ||
625 | IW_QUAL_QUAL_INVALID; | ||
626 | switch (bss->pub.signal_type) { | ||
627 | case CFG80211_SIGNAL_TYPE_MBM: | ||
628 | iwe.u.qual.level = bss->pub.signal / 100; | ||
629 | iwe.u.qual.updated |= IW_QUAL_DBM; | ||
630 | break; | ||
631 | case CFG80211_SIGNAL_TYPE_UNSPEC: | ||
632 | iwe.u.qual.level = bss->pub.signal; | ||
633 | break; | ||
634 | default: | ||
635 | /* not reached */ | ||
636 | break; | ||
637 | } | ||
638 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | ||
639 | &iwe, IW_EV_QUAL_LEN); | ||
640 | } | ||
641 | |||
642 | memset(&iwe, 0, sizeof(iwe)); | ||
643 | iwe.cmd = SIOCGIWENCODE; | ||
644 | if (bss->pub.capability & WLAN_CAPABILITY_PRIVACY) | ||
645 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | ||
646 | else | ||
647 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
648 | iwe.u.data.length = 0; | ||
649 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
650 | &iwe, ""); | ||
651 | |||
652 | while (rem >= 2) { | ||
653 | /* invalid data */ | ||
654 | if (ie[1] > rem - 2) | ||
655 | break; | ||
656 | |||
657 | switch (ie[0]) { | ||
658 | case WLAN_EID_SSID: | ||
659 | memset(&iwe, 0, sizeof(iwe)); | ||
660 | iwe.cmd = SIOCGIWESSID; | ||
661 | iwe.u.data.length = ie[1]; | ||
662 | iwe.u.data.flags = 1; | ||
663 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
664 | &iwe, ie + 2); | ||
665 | break; | ||
666 | case WLAN_EID_MESH_ID: | ||
667 | memset(&iwe, 0, sizeof(iwe)); | ||
668 | iwe.cmd = SIOCGIWESSID; | ||
669 | iwe.u.data.length = ie[1]; | ||
670 | iwe.u.data.flags = 1; | ||
671 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
672 | &iwe, ie + 2); | ||
673 | break; | ||
674 | case WLAN_EID_MESH_CONFIG: | ||
675 | ismesh = true; | ||
676 | if (ie[1] != IEEE80211_MESH_CONFIG_LEN) | ||
677 | break; | ||
678 | buf = kmalloc(50, GFP_ATOMIC); | ||
679 | if (!buf) | ||
680 | break; | ||
681 | cfg = ie + 2; | ||
682 | memset(&iwe, 0, sizeof(iwe)); | ||
683 | iwe.cmd = IWEVCUSTOM; | ||
684 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | ||
685 | iwe.u.data.length = strlen(buf); | ||
686 | current_ev = iwe_stream_add_point(info, current_ev, | ||
687 | end_buf, | ||
688 | &iwe, buf); | ||
689 | sprintf(buf, "Path Selection Protocol ID: " | ||
690 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | ||
691 | cfg[4]); | ||
692 | iwe.u.data.length = strlen(buf); | ||
693 | current_ev = iwe_stream_add_point(info, current_ev, | ||
694 | end_buf, | ||
695 | &iwe, buf); | ||
696 | sprintf(buf, "Path Selection Metric ID: " | ||
697 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | ||
698 | cfg[8]); | ||
699 | iwe.u.data.length = strlen(buf); | ||
700 | current_ev = iwe_stream_add_point(info, current_ev, | ||
701 | end_buf, | ||
702 | &iwe, buf); | ||
703 | sprintf(buf, "Congestion Control Mode ID: " | ||
704 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | ||
705 | cfg[11], cfg[12]); | ||
706 | iwe.u.data.length = strlen(buf); | ||
707 | current_ev = iwe_stream_add_point(info, current_ev, | ||
708 | end_buf, | ||
709 | &iwe, buf); | ||
710 | sprintf(buf, "Channel Precedence: " | ||
711 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | ||
712 | cfg[15], cfg[16]); | ||
713 | iwe.u.data.length = strlen(buf); | ||
714 | current_ev = iwe_stream_add_point(info, current_ev, | ||
715 | end_buf, | ||
716 | &iwe, buf); | ||
717 | kfree(buf); | ||
718 | break; | ||
719 | case WLAN_EID_SUPP_RATES: | ||
720 | case WLAN_EID_EXT_SUPP_RATES: | ||
721 | /* display all supported rates in readable format */ | ||
722 | p = current_ev + iwe_stream_lcp_len(info); | ||
723 | |||
724 | memset(&iwe, 0, sizeof(iwe)); | ||
725 | iwe.cmd = SIOCGIWRATE; | ||
726 | /* Those two flags are ignored... */ | ||
727 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
728 | |||
729 | for (i = 0; i < ie[1]; i++) { | ||
730 | iwe.u.bitrate.value = | ||
731 | ((ie[i + 2] & 0x7f) * 500000); | ||
732 | p = iwe_stream_add_value(info, current_ev, p, | ||
733 | end_buf, &iwe, IW_EV_PARAM_LEN); | ||
734 | } | ||
735 | current_ev = p; | ||
736 | break; | ||
737 | } | ||
738 | rem -= ie[1] + 2; | ||
739 | ie += ie[1] + 2; | ||
740 | } | ||
741 | |||
742 | if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | ||
743 | || ismesh) { | ||
744 | memset(&iwe, 0, sizeof(iwe)); | ||
745 | iwe.cmd = SIOCGIWMODE; | ||
746 | if (ismesh) | ||
747 | iwe.u.mode = IW_MODE_MESH; | ||
748 | else if (bss->pub.capability & WLAN_CAPABILITY_ESS) | ||
749 | iwe.u.mode = IW_MODE_MASTER; | ||
750 | else | ||
751 | iwe.u.mode = IW_MODE_ADHOC; | ||
752 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | ||
753 | &iwe, IW_EV_UINT_LEN); | ||
754 | } | ||
755 | |||
756 | buf = kmalloc(30, GFP_ATOMIC); | ||
757 | if (buf) { | ||
758 | memset(&iwe, 0, sizeof(iwe)); | ||
759 | iwe.cmd = IWEVCUSTOM; | ||
760 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf)); | ||
761 | iwe.u.data.length = strlen(buf); | ||
762 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
763 | &iwe, buf); | ||
764 | memset(&iwe, 0, sizeof(iwe)); | ||
765 | iwe.cmd = IWEVCUSTOM; | ||
766 | sprintf(buf, " Last beacon: %dms ago", | ||
767 | jiffies_to_msecs(jiffies - bss->ts)); | ||
768 | iwe.u.data.length = strlen(buf); | ||
769 | current_ev = iwe_stream_add_point(info, current_ev, | ||
770 | end_buf, &iwe, buf); | ||
771 | kfree(buf); | ||
772 | } | ||
773 | |||
774 | ieee80211_scan_add_ies(info, &bss->pub, ¤t_ev, end_buf); | ||
775 | |||
776 | return current_ev; | ||
777 | } | ||
778 | |||
779 | |||
780 | static int ieee80211_scan_results(struct cfg80211_registered_device *dev, | ||
781 | struct iw_request_info *info, | ||
782 | char *buf, size_t len) | ||
783 | { | ||
784 | char *current_ev = buf; | ||
785 | char *end_buf = buf + len; | ||
786 | struct cfg80211_internal_bss *bss; | ||
787 | |||
788 | spin_lock_bh(&dev->bss_lock); | ||
789 | cfg80211_bss_expire(dev); | ||
790 | |||
791 | list_for_each_entry(bss, &dev->bss_list, list) { | ||
792 | if (buf + len - current_ev <= IW_EV_ADDR_LEN) { | ||
793 | spin_unlock_bh(&dev->bss_lock); | ||
794 | return -E2BIG; | ||
795 | } | ||
796 | current_ev = ieee80211_bss(info, bss, | ||
797 | current_ev, end_buf); | ||
798 | } | ||
799 | spin_unlock_bh(&dev->bss_lock); | ||
800 | return current_ev - buf; | ||
801 | } | ||
802 | |||
803 | |||
804 | int cfg80211_wext_giwscan(struct net_device *dev, | ||
805 | struct iw_request_info *info, | ||
806 | struct iw_point *data, char *extra) | ||
807 | { | ||
808 | struct cfg80211_registered_device *rdev; | ||
809 | int res; | ||
810 | |||
811 | if (!netif_running(dev)) | ||
812 | return -ENETDOWN; | ||
813 | |||
814 | rdev = cfg80211_get_dev_from_ifindex(dev->ifindex); | ||
815 | |||
816 | if (IS_ERR(rdev)) | ||
817 | return PTR_ERR(rdev); | ||
818 | |||
819 | if (rdev->scan_req) { | ||
820 | res = -EAGAIN; | ||
821 | goto out; | ||
822 | } | ||
823 | |||
824 | res = ieee80211_scan_results(rdev, info, extra, data->length); | ||
825 | data->length = 0; | ||
826 | if (res >= 0) { | ||
827 | data->length = res; | ||
828 | res = 0; | ||
829 | } | ||
830 | |||
831 | out: | ||
832 | cfg80211_put_dev(rdev); | ||
833 | return res; | ||
834 | } | ||
835 | EXPORT_SYMBOL(cfg80211_wext_giwscan); | ||
836 | #endif | ||
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 79a382877641..26a72b0797a0 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -55,6 +55,34 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
55 | } | 55 | } |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | static int wiphy_suspend(struct device *dev, pm_message_t state) | ||
59 | { | ||
60 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); | ||
61 | int ret = 0; | ||
62 | |||
63 | if (rdev->ops->suspend) { | ||
64 | rtnl_lock(); | ||
65 | ret = rdev->ops->suspend(&rdev->wiphy); | ||
66 | rtnl_unlock(); | ||
67 | } | ||
68 | |||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | static int wiphy_resume(struct device *dev) | ||
73 | { | ||
74 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); | ||
75 | int ret = 0; | ||
76 | |||
77 | if (rdev->ops->resume) { | ||
78 | rtnl_lock(); | ||
79 | ret = rdev->ops->resume(&rdev->wiphy); | ||
80 | rtnl_unlock(); | ||
81 | } | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
58 | struct class ieee80211_class = { | 86 | struct class ieee80211_class = { |
59 | .name = "ieee80211", | 87 | .name = "ieee80211", |
60 | .owner = THIS_MODULE, | 88 | .owner = THIS_MODULE, |
@@ -63,6 +91,8 @@ struct class ieee80211_class = { | |||
63 | #ifdef CONFIG_HOTPLUG | 91 | #ifdef CONFIG_HOTPLUG |
64 | .dev_uevent = wiphy_uevent, | 92 | .dev_uevent = wiphy_uevent, |
65 | #endif | 93 | #endif |
94 | .suspend = wiphy_suspend, | ||
95 | .resume = wiphy_resume, | ||
66 | }; | 96 | }; |
67 | 97 | ||
68 | int wiphy_sysfs_init(void) | 98 | int wiphy_sysfs_init(void) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index e76cc28b0345..487cdd9bcffc 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | struct ieee80211_rate * | 10 | struct ieee80211_rate * |
11 | ieee80211_get_response_rate(struct ieee80211_supported_band *sband, | 11 | ieee80211_get_response_rate(struct ieee80211_supported_band *sband, |
12 | u64 basic_rates, int bitrate) | 12 | u32 basic_rates, int bitrate) |
13 | { | 13 | { |
14 | struct ieee80211_rate *result = &sband->bitrates[0]; | 14 | struct ieee80211_rate *result = &sband->bitrates[0]; |
15 | int i; | 15 | int i; |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 9fc5b023d111..8f76f4009c24 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -1609,7 +1609,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
1609 | SOCKOPS_WRAP(x25_proto, AF_X25); | 1609 | SOCKOPS_WRAP(x25_proto, AF_X25); |
1610 | 1610 | ||
1611 | static struct packet_type x25_packet_type = { | 1611 | static struct packet_type x25_packet_type = { |
1612 | .type = __constant_htons(ETH_P_X25), | 1612 | .type = cpu_to_be16(ETH_P_X25), |
1613 | .func = x25_lapb_receive_frame, | 1613 | .func = x25_lapb_receive_frame, |
1614 | }; | 1614 | }; |
1615 | 1615 | ||