diff options
Diffstat (limited to 'net')
218 files changed, 3854 insertions, 3593 deletions
diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index e69244dd8de8..b69bf4e7c48b 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h | |||
@@ -16,10 +16,6 @@ | |||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | /* | ||
20 | * $Id: bnep.h,v 1.5 2002/08/04 21:23:58 maxk Exp $ | ||
21 | */ | ||
22 | |||
23 | #ifndef _BNEP_H | 19 | #ifndef _BNEP_H |
24 | #define _BNEP_H | 20 | #define _BNEP_H |
25 | 21 | ||
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index f85d94643aaf..1d98a1b80da7 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -25,10 +25,6 @@ | |||
25 | SOFTWARE IS DISCLAIMED. | 25 | SOFTWARE IS DISCLAIMED. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* | ||
29 | * $Id: core.c,v 1.20 2002/08/04 21:23:58 maxk Exp $ | ||
30 | */ | ||
31 | |||
32 | #include <linux/module.h> | 28 | #include <linux/module.h> |
33 | 29 | ||
34 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 95e3837e4312..d9fa0ab2c87f 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
@@ -25,10 +25,6 @@ | |||
25 | SOFTWARE IS DISCLAIMED. | 25 | SOFTWARE IS DISCLAIMED. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* | ||
29 | * $Id: netdev.c,v 1.8 2002/08/04 21:23:58 maxk Exp $ | ||
30 | */ | ||
31 | |||
32 | #include <linux/module.h> | 28 | #include <linux/module.h> |
33 | 29 | ||
34 | #include <linux/socket.h> | 30 | #include <linux/socket.h> |
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 201e5b1ce473..8ffb57f2303a 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -24,10 +24,6 @@ | |||
24 | SOFTWARE IS DISCLAIMED. | 24 | SOFTWARE IS DISCLAIMED. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | /* | ||
28 | * $Id: sock.c,v 1.4 2002/08/04 21:23:58 maxk Exp $ | ||
29 | */ | ||
30 | |||
31 | #include <linux/module.h> | 27 | #include <linux/module.h> |
32 | 28 | ||
33 | #include <linux/types.h> | 29 | #include <linux/types.h> |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 0c2c93735e93..b4fb84e398e5 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -23,8 +23,6 @@ | |||
23 | 23 | ||
24 | /* | 24 | /* |
25 | * Bluetooth RFCOMM core. | 25 | * Bluetooth RFCOMM core. |
26 | * | ||
27 | * $Id: core.c,v 1.42 2002/10/01 23:26:25 maxk Exp $ | ||
28 | */ | 26 | */ |
29 | 27 | ||
30 | #include <linux/module.h> | 28 | #include <linux/module.h> |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 5083adcbfae5..c9054487670a 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -23,8 +23,6 @@ | |||
23 | 23 | ||
24 | /* | 24 | /* |
25 | * RFCOMM sockets. | 25 | * RFCOMM sockets. |
26 | * | ||
27 | * $Id: sock.c,v 1.24 2002/10/03 01:00:34 maxk Exp $ | ||
28 | */ | 26 | */ |
29 | 27 | ||
30 | #include <linux/module.h> | 28 | #include <linux/module.h> |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index c9191871c1e0..be84f4fc1477 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -23,8 +23,6 @@ | |||
23 | 23 | ||
24 | /* | 24 | /* |
25 | * RFCOMM TTY. | 25 | * RFCOMM TTY. |
26 | * | ||
27 | * $Id: tty.c,v 1.24 2002/10/03 01:54:38 holtmann Exp $ | ||
28 | */ | 26 | */ |
29 | 27 | ||
30 | #include <linux/module.h> | 28 | #include <linux/module.h> |
diff --git a/net/bridge/br.c b/net/bridge/br.c index 8f3c58e5f7a5..cede010f4ddd 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br.c,v 1.47 2001/12/24 00:56:41 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index bf7787395fe0..a6ffc6c2a69f 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_device.c,v 1.6 2001/12/24 00:59:55 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
@@ -21,12 +19,6 @@ | |||
21 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
22 | #include "br_private.h" | 20 | #include "br_private.h" |
23 | 21 | ||
24 | static struct net_device_stats *br_dev_get_stats(struct net_device *dev) | ||
25 | { | ||
26 | struct net_bridge *br = netdev_priv(dev); | ||
27 | return &br->statistics; | ||
28 | } | ||
29 | |||
30 | /* net device transmit always called with no BH (preempt_disabled) */ | 22 | /* net device transmit always called with no BH (preempt_disabled) */ |
31 | int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | 23 | int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) |
32 | { | 24 | { |
@@ -34,8 +26,8 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
34 | const unsigned char *dest = skb->data; | 26 | const unsigned char *dest = skb->data; |
35 | struct net_bridge_fdb_entry *dst; | 27 | struct net_bridge_fdb_entry *dst; |
36 | 28 | ||
37 | br->statistics.tx_packets++; | 29 | dev->stats.tx_packets++; |
38 | br->statistics.tx_bytes += skb->len; | 30 | dev->stats.tx_bytes += skb->len; |
39 | 31 | ||
40 | skb_reset_mac_header(skb); | 32 | skb_reset_mac_header(skb); |
41 | skb_pull(skb, ETH_HLEN); | 33 | skb_pull(skb, ETH_HLEN); |
@@ -161,7 +153,6 @@ void br_dev_setup(struct net_device *dev) | |||
161 | ether_setup(dev); | 153 | ether_setup(dev); |
162 | 154 | ||
163 | dev->do_ioctl = br_dev_ioctl; | 155 | dev->do_ioctl = br_dev_ioctl; |
164 | dev->get_stats = br_dev_get_stats; | ||
165 | dev->hard_start_xmit = br_dev_xmit; | 156 | dev->hard_start_xmit = br_dev_xmit; |
166 | dev->open = br_dev_open; | 157 | dev->open = br_dev_open; |
167 | dev->set_multicast_list = br_dev_set_multicast_list; | 158 | dev->set_multicast_list = br_dev_set_multicast_list; |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 72c5976a5ce3..4de74cdd091d 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_fdb.c,v 1.6 2002/01/17 00:57:07 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index bdd7c35c3c7b..512645727f51 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_forward.c,v 1.4 2001/08/14 22:05:57 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
@@ -115,7 +113,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, | |||
115 | struct sk_buff *skb2; | 113 | struct sk_buff *skb2; |
116 | 114 | ||
117 | if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { | 115 | if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { |
118 | br->statistics.tx_dropped++; | 116 | br->dev->stats.tx_dropped++; |
119 | kfree_skb(skb); | 117 | kfree_skb(skb); |
120 | return; | 118 | return; |
121 | } | 119 | } |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index c2397f503b0f..143c954681b8 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_if.c,v 1.7 2001/12/24 00:59:55 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 255c00f60ce7..0145e9416714 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_input.c,v 1.10 2001/12/24 04:50:20 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
@@ -24,13 +22,13 @@ const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | |||
24 | 22 | ||
25 | static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) | 23 | static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) |
26 | { | 24 | { |
27 | struct net_device *indev; | 25 | struct net_device *indev, *brdev = br->dev; |
28 | 26 | ||
29 | br->statistics.rx_packets++; | 27 | brdev->stats.rx_packets++; |
30 | br->statistics.rx_bytes += skb->len; | 28 | brdev->stats.rx_bytes += skb->len; |
31 | 29 | ||
32 | indev = skb->dev; | 30 | indev = skb->dev; |
33 | skb->dev = br->dev; | 31 | skb->dev = brdev; |
34 | 32 | ||
35 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, | 33 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, |
36 | netif_receive_skb); | 34 | netif_receive_skb); |
@@ -64,7 +62,7 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
64 | dst = NULL; | 62 | dst = NULL; |
65 | 63 | ||
66 | if (is_multicast_ether_addr(dest)) { | 64 | if (is_multicast_ether_addr(dest)) { |
67 | br->statistics.multicast++; | 65 | br->dev->stats.multicast++; |
68 | skb2 = skb; | 66 | skb2 = skb; |
69 | } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) { | 67 | } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) { |
70 | skb2 = skb; | 68 | skb2 = skb; |
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 0655a5f07f58..eeee218eed80 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_ioctl.c,v 1.4 2000/11/08 05:16:40 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 00644a544e3c..88d8ec7b3142 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_notify.c,v 1.2 2000/02/21 15:51:34 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c11b554fd109..83ff5861c2d2 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -4,8 +4,6 @@ | |||
4 | * Authors: | 4 | * Authors: |
5 | * Lennert Buytenhek <buytenh@gnu.org> | 5 | * Lennert Buytenhek <buytenh@gnu.org> |
6 | * | 6 | * |
7 | * $Id: br_private.h,v 1.7 2001/12/24 00:59:55 davem Exp $ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
11 | * as published by the Free Software Foundation; either version | 9 | * as published by the Free Software Foundation; either version |
@@ -90,7 +88,6 @@ struct net_bridge | |||
90 | spinlock_t lock; | 88 | spinlock_t lock; |
91 | struct list_head port_list; | 89 | struct list_head port_list; |
92 | struct net_device *dev; | 90 | struct net_device *dev; |
93 | struct net_device_stats statistics; | ||
94 | spinlock_t hash_lock; | 91 | spinlock_t hash_lock; |
95 | struct hlist_head hash[BR_HASH_SIZE]; | 92 | struct hlist_head hash[BR_HASH_SIZE]; |
96 | struct list_head age_list; | 93 | struct list_head age_list; |
diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h index e29f01ac1adf..8b650f7fbfa0 100644 --- a/net/bridge/br_private_stp.h +++ b/net/bridge/br_private_stp.h | |||
@@ -4,8 +4,6 @@ | |||
4 | * Authors: | 4 | * Authors: |
5 | * Lennert Buytenhek <buytenh@gnu.org> | 5 | * Lennert Buytenhek <buytenh@gnu.org> |
6 | * | 6 | * |
7 | * $Id: br_private_stp.h,v 1.3 2001/02/05 06:03:47 davem Exp $ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
11 | * as published by the Free Software Foundation; either version | 9 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index e38034aa56f5..284d1b2fa1ff 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_stp.c,v 1.4 2000/06/19 10:13:35 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index ddeb6e5d45d6..9dc2de656965 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_stp_bpdu.c,v 1.3 2001/11/10 02:35:25 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 1a430eccec9b..1a4e5c37a0cf 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_stp_if.c,v 1.4 2001/04/14 21:14:39 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 77f5255e6915..772a140bfdf0 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * | 7 | * |
8 | * $Id: br_stp_timer.c,v 1.3 2000/05/05 02:17:17 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig index 7beeefa0f9c0..fb684c2ff8b6 100644 --- a/net/bridge/netfilter/Kconfig +++ b/net/bridge/netfilter/Kconfig | |||
@@ -83,6 +83,15 @@ config BRIDGE_EBT_IP | |||
83 | 83 | ||
84 | To compile it as a module, choose M here. If unsure, say N. | 84 | To compile it as a module, choose M here. If unsure, say N. |
85 | 85 | ||
86 | config BRIDGE_EBT_IP6 | ||
87 | tristate "ebt: IP6 filter support" | ||
88 | depends on BRIDGE_NF_EBTABLES | ||
89 | help | ||
90 | This option adds the IP6 match, which allows basic IPV6 header field | ||
91 | filtering. | ||
92 | |||
93 | To compile it as a module, choose M here. If unsure, say N. | ||
94 | |||
86 | config BRIDGE_EBT_LIMIT | 95 | config BRIDGE_EBT_LIMIT |
87 | tristate "ebt: limit match support" | 96 | tristate "ebt: limit match support" |
88 | depends on BRIDGE_NF_EBTABLES | 97 | depends on BRIDGE_NF_EBTABLES |
diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile index 83715d73a503..dd960645b413 100644 --- a/net/bridge/netfilter/Makefile +++ b/net/bridge/netfilter/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_BRIDGE_EBT_802_3) += ebt_802_3.o | |||
14 | obj-$(CONFIG_BRIDGE_EBT_AMONG) += ebt_among.o | 14 | obj-$(CONFIG_BRIDGE_EBT_AMONG) += ebt_among.o |
15 | obj-$(CONFIG_BRIDGE_EBT_ARP) += ebt_arp.o | 15 | obj-$(CONFIG_BRIDGE_EBT_ARP) += ebt_arp.o |
16 | obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip.o | 16 | obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip.o |
17 | obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip6.o | ||
17 | obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o | 18 | obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o |
18 | obj-$(CONFIG_BRIDGE_EBT_MARK) += ebt_mark_m.o | 19 | obj-$(CONFIG_BRIDGE_EBT_MARK) += ebt_mark_m.o |
19 | obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o | 20 | obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o |
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c new file mode 100644 index 000000000000..36efb3a75249 --- /dev/null +++ b/net/bridge/netfilter/ebt_ip6.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * ebt_ip6 | ||
3 | * | ||
4 | * Authors: | ||
5 | * Manohar Castelino <manohar.r.castelino@intel.com> | ||
6 | * Kuo-Lang Tseng <kuo-lang.tseng@intel.com> | ||
7 | * Jan Engelhardt <jengelh@computergmbh.de> | ||
8 | * | ||
9 | * Summary: | ||
10 | * This is just a modification of the IPv4 code written by | ||
11 | * Bart De Schuymer <bdschuym@pandora.be> | ||
12 | * with the changes required to support IPv6 | ||
13 | * | ||
14 | * Jan, 2008 | ||
15 | */ | ||
16 | |||
17 | #include <linux/netfilter_bridge/ebtables.h> | ||
18 | #include <linux/netfilter_bridge/ebt_ip6.h> | ||
19 | #include <linux/ipv6.h> | ||
20 | #include <net/ipv6.h> | ||
21 | #include <linux/in.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <net/dsfield.h> | ||
24 | |||
25 | struct tcpudphdr { | ||
26 | __be16 src; | ||
27 | __be16 dst; | ||
28 | }; | ||
29 | |||
30 | static int ebt_filter_ip6(const struct sk_buff *skb, | ||
31 | const struct net_device *in, | ||
32 | const struct net_device *out, const void *data, | ||
33 | unsigned int datalen) | ||
34 | { | ||
35 | const struct ebt_ip6_info *info = (struct ebt_ip6_info *)data; | ||
36 | const struct ipv6hdr *ih6; | ||
37 | struct ipv6hdr _ip6h; | ||
38 | const struct tcpudphdr *pptr; | ||
39 | struct tcpudphdr _ports; | ||
40 | struct in6_addr tmp_addr; | ||
41 | int i; | ||
42 | |||
43 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); | ||
44 | if (ih6 == NULL) | ||
45 | return EBT_NOMATCH; | ||
46 | if (info->bitmask & EBT_IP6_TCLASS && | ||
47 | FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS)) | ||
48 | return EBT_NOMATCH; | ||
49 | for (i = 0; i < 4; i++) | ||
50 | tmp_addr.in6_u.u6_addr32[i] = ih6->saddr.in6_u.u6_addr32[i] & | ||
51 | info->smsk.in6_u.u6_addr32[i]; | ||
52 | if (info->bitmask & EBT_IP6_SOURCE && | ||
53 | FWINV((ipv6_addr_cmp(&tmp_addr, &info->saddr) != 0), | ||
54 | EBT_IP6_SOURCE)) | ||
55 | return EBT_NOMATCH; | ||
56 | for (i = 0; i < 4; i++) | ||
57 | tmp_addr.in6_u.u6_addr32[i] = ih6->daddr.in6_u.u6_addr32[i] & | ||
58 | info->dmsk.in6_u.u6_addr32[i]; | ||
59 | if (info->bitmask & EBT_IP6_DEST && | ||
60 | FWINV((ipv6_addr_cmp(&tmp_addr, &info->daddr) != 0), EBT_IP6_DEST)) | ||
61 | return EBT_NOMATCH; | ||
62 | if (info->bitmask & EBT_IP6_PROTO) { | ||
63 | uint8_t nexthdr = ih6->nexthdr; | ||
64 | int offset_ph; | ||
65 | |||
66 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr); | ||
67 | if (offset_ph == -1) | ||
68 | return EBT_NOMATCH; | ||
69 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) | ||
70 | return EBT_NOMATCH; | ||
71 | if (!(info->bitmask & EBT_IP6_DPORT) && | ||
72 | !(info->bitmask & EBT_IP6_SPORT)) | ||
73 | return EBT_MATCH; | ||
74 | pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports), | ||
75 | &_ports); | ||
76 | if (pptr == NULL) | ||
77 | return EBT_NOMATCH; | ||
78 | if (info->bitmask & EBT_IP6_DPORT) { | ||
79 | u32 dst = ntohs(pptr->dst); | ||
80 | if (FWINV(dst < info->dport[0] || | ||
81 | dst > info->dport[1], EBT_IP6_DPORT)) | ||
82 | return EBT_NOMATCH; | ||
83 | } | ||
84 | if (info->bitmask & EBT_IP6_SPORT) { | ||
85 | u32 src = ntohs(pptr->src); | ||
86 | if (FWINV(src < info->sport[0] || | ||
87 | src > info->sport[1], EBT_IP6_SPORT)) | ||
88 | return EBT_NOMATCH; | ||
89 | } | ||
90 | return EBT_MATCH; | ||
91 | } | ||
92 | return EBT_MATCH; | ||
93 | } | ||
94 | |||
95 | static int ebt_ip6_check(const char *tablename, unsigned int hookmask, | ||
96 | const struct ebt_entry *e, void *data, unsigned int datalen) | ||
97 | { | ||
98 | struct ebt_ip6_info *info = (struct ebt_ip6_info *)data; | ||
99 | |||
100 | if (datalen != EBT_ALIGN(sizeof(struct ebt_ip6_info))) | ||
101 | return -EINVAL; | ||
102 | if (e->ethproto != htons(ETH_P_IPV6) || e->invflags & EBT_IPROTO) | ||
103 | return -EINVAL; | ||
104 | if (info->bitmask & ~EBT_IP6_MASK || info->invflags & ~EBT_IP6_MASK) | ||
105 | return -EINVAL; | ||
106 | if (info->bitmask & (EBT_IP6_DPORT | EBT_IP6_SPORT)) { | ||
107 | if (info->invflags & EBT_IP6_PROTO) | ||
108 | return -EINVAL; | ||
109 | if (info->protocol != IPPROTO_TCP && | ||
110 | info->protocol != IPPROTO_UDP && | ||
111 | info->protocol != IPPROTO_UDPLITE && | ||
112 | info->protocol != IPPROTO_SCTP && | ||
113 | info->protocol != IPPROTO_DCCP) | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | if (info->bitmask & EBT_IP6_DPORT && info->dport[0] > info->dport[1]) | ||
117 | return -EINVAL; | ||
118 | if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1]) | ||
119 | return -EINVAL; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static struct ebt_match filter_ip6 = | ||
124 | { | ||
125 | .name = EBT_IP6_MATCH, | ||
126 | .match = ebt_filter_ip6, | ||
127 | .check = ebt_ip6_check, | ||
128 | .me = THIS_MODULE, | ||
129 | }; | ||
130 | |||
131 | static int __init ebt_ip6_init(void) | ||
132 | { | ||
133 | return ebt_register_match(&filter_ip6); | ||
134 | } | ||
135 | |||
136 | static void __exit ebt_ip6_fini(void) | ||
137 | { | ||
138 | ebt_unregister_match(&filter_ip6); | ||
139 | } | ||
140 | |||
141 | module_init(ebt_ip6_init); | ||
142 | module_exit(ebt_ip6_fini); | ||
143 | MODULE_DESCRIPTION("Ebtables: IPv6 protocol packet match"); | ||
144 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 0b209e4aad0a..c883ec8a28b4 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
@@ -18,6 +18,9 @@ | |||
18 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <net/netfilter/nf_log.h> | 20 | #include <net/netfilter/nf_log.h> |
21 | #include <linux/ipv6.h> | ||
22 | #include <net/ipv6.h> | ||
23 | #include <linux/in6.h> | ||
21 | 24 | ||
22 | static DEFINE_SPINLOCK(ebt_log_lock); | 25 | static DEFINE_SPINLOCK(ebt_log_lock); |
23 | 26 | ||
@@ -58,6 +61,27 @@ static void print_MAC(const unsigned char *p) | |||
58 | printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':'); | 61 | printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':'); |
59 | } | 62 | } |
60 | 63 | ||
64 | static void | ||
65 | print_ports(const struct sk_buff *skb, uint8_t protocol, int offset) | ||
66 | { | ||
67 | if (protocol == IPPROTO_TCP || | ||
68 | protocol == IPPROTO_UDP || | ||
69 | protocol == IPPROTO_UDPLITE || | ||
70 | protocol == IPPROTO_SCTP || | ||
71 | protocol == IPPROTO_DCCP) { | ||
72 | const struct tcpudphdr *pptr; | ||
73 | struct tcpudphdr _ports; | ||
74 | |||
75 | pptr = skb_header_pointer(skb, offset, | ||
76 | sizeof(_ports), &_ports); | ||
77 | if (pptr == NULL) { | ||
78 | printk(" INCOMPLETE TCP/UDP header"); | ||
79 | return; | ||
80 | } | ||
81 | printk(" SPT=%u DPT=%u", ntohs(pptr->src), ntohs(pptr->dst)); | ||
82 | } | ||
83 | } | ||
84 | |||
61 | #define myNIPQUAD(a) a[0], a[1], a[2], a[3] | 85 | #define myNIPQUAD(a) a[0], a[1], a[2], a[3] |
62 | static void | 86 | static void |
63 | ebt_log_packet(unsigned int pf, unsigned int hooknum, | 87 | ebt_log_packet(unsigned int pf, unsigned int hooknum, |
@@ -95,23 +119,31 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum, | |||
95 | printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP " | 119 | printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP " |
96 | "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr), | 120 | "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr), |
97 | NIPQUAD(ih->daddr), ih->tos, ih->protocol); | 121 | NIPQUAD(ih->daddr), ih->tos, ih->protocol); |
98 | if (ih->protocol == IPPROTO_TCP || | 122 | print_ports(skb, ih->protocol, ih->ihl*4); |
99 | ih->protocol == IPPROTO_UDP || | 123 | goto out; |
100 | ih->protocol == IPPROTO_UDPLITE || | 124 | } |
101 | ih->protocol == IPPROTO_SCTP || | 125 | |
102 | ih->protocol == IPPROTO_DCCP) { | 126 | if ((bitmask & EBT_LOG_IP6) && eth_hdr(skb)->h_proto == |
103 | const struct tcpudphdr *pptr; | 127 | htons(ETH_P_IPV6)) { |
104 | struct tcpudphdr _ports; | 128 | const struct ipv6hdr *ih; |
105 | 129 | struct ipv6hdr _iph; | |
106 | pptr = skb_header_pointer(skb, ih->ihl*4, | 130 | uint8_t nexthdr; |
107 | sizeof(_ports), &_ports); | 131 | int offset_ph; |
108 | if (pptr == NULL) { | 132 | |
109 | printk(" INCOMPLETE TCP/UDP header"); | 133 | ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); |
110 | goto out; | 134 | if (ih == NULL) { |
111 | } | 135 | printk(" INCOMPLETE IPv6 header"); |
112 | printk(" SPT=%u DPT=%u", ntohs(pptr->src), | 136 | goto out; |
113 | ntohs(pptr->dst)); | ||
114 | } | 137 | } |
138 | printk(" IPv6 SRC=%x:%x:%x:%x:%x:%x:%x:%x " | ||
139 | "IPv6 DST=%x:%x:%x:%x:%x:%x:%x:%x, IPv6 " | ||
140 | "priority=0x%01X, Next Header=%d", NIP6(ih->saddr), | ||
141 | NIP6(ih->daddr), ih->priority, ih->nexthdr); | ||
142 | nexthdr = ih->nexthdr; | ||
143 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr); | ||
144 | if (offset_ph == -1) | ||
145 | goto out; | ||
146 | print_ports(skb, nexthdr, offset_ph); | ||
115 | goto out; | 147 | goto out; |
116 | } | 148 | } |
117 | 149 | ||
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 90e2177af081..dccd737ea2e3 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -242,11 +242,11 @@ static ssize_t netstat_show(const struct device *d, | |||
242 | offset % sizeof(unsigned long) != 0); | 242 | offset % sizeof(unsigned long) != 0); |
243 | 243 | ||
244 | read_lock(&dev_base_lock); | 244 | read_lock(&dev_base_lock); |
245 | if (dev_isalive(dev) && dev->get_stats && | 245 | if (dev_isalive(dev)) { |
246 | (stats = (*dev->get_stats)(dev))) | 246 | stats = dev->get_stats(dev); |
247 | ret = sprintf(buf, fmt_ulong, | 247 | ret = sprintf(buf, fmt_ulong, |
248 | *(unsigned long *)(((u8 *) stats) + offset)); | 248 | *(unsigned long *)(((u8 *) stats) + offset)); |
249 | 249 | } | |
250 | read_unlock(&dev_base_lock); | 250 | read_unlock(&dev_base_lock); |
251 | return ret; | 251 | return ret; |
252 | } | 252 | } |
@@ -457,8 +457,7 @@ int netdev_register_kobject(struct net_device *net) | |||
457 | strlcpy(dev->bus_id, net->name, BUS_ID_SIZE); | 457 | strlcpy(dev->bus_id, net->name, BUS_ID_SIZE); |
458 | 458 | ||
459 | #ifdef CONFIG_SYSFS | 459 | #ifdef CONFIG_SYSFS |
460 | if (net->get_stats) | 460 | *groups++ = &netstat_group; |
461 | *groups++ = &netstat_group; | ||
462 | 461 | ||
463 | #ifdef CONFIG_WIRELESS_EXT | 462 | #ifdef CONFIG_WIRELESS_EXT |
464 | if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats) | 463 | if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats) |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a9a77216310e..6c8d7f0ea01a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -607,6 +607,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
607 | { | 607 | { |
608 | struct ifinfomsg *ifm; | 608 | struct ifinfomsg *ifm; |
609 | struct nlmsghdr *nlh; | 609 | struct nlmsghdr *nlh; |
610 | struct net_device_stats *stats; | ||
611 | struct nlattr *attr; | ||
610 | 612 | ||
611 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); | 613 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); |
612 | if (nlh == NULL) | 614 | if (nlh == NULL) |
@@ -653,19 +655,13 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
653 | NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); | 655 | NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); |
654 | } | 656 | } |
655 | 657 | ||
656 | if (dev->get_stats) { | 658 | attr = nla_reserve(skb, IFLA_STATS, |
657 | struct net_device_stats *stats = dev->get_stats(dev); | 659 | sizeof(struct rtnl_link_stats)); |
658 | if (stats) { | 660 | if (attr == NULL) |
659 | struct nlattr *attr; | 661 | goto nla_put_failure; |
660 | 662 | ||
661 | attr = nla_reserve(skb, IFLA_STATS, | 663 | stats = dev->get_stats(dev); |
662 | sizeof(struct rtnl_link_stats)); | 664 | copy_rtnl_link_stats(nla_data(attr), stats); |
663 | if (attr == NULL) | ||
664 | goto nla_put_failure; | ||
665 | |||
666 | copy_rtnl_link_stats(nla_data(attr), stats); | ||
667 | } | ||
668 | } | ||
669 | 665 | ||
670 | if (dev->rtnl_link_ops) { | 666 | if (dev->rtnl_link_ops) { |
671 | if (rtnl_link_fill(skb, dev) < 0) | 667 | if (rtnl_link_fill(skb, dev) < 0) |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1e556d312117..3e18f8525e82 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -4,8 +4,6 @@ | |||
4 | * Authors: Alan Cox <iiitac@pyr.swan.ac.uk> | 4 | * Authors: Alan Cox <iiitac@pyr.swan.ac.uk> |
5 | * Florian La Roche <rzsfl@rz.uni-sb.de> | 5 | * Florian La Roche <rzsfl@rz.uni-sb.de> |
6 | * | 6 | * |
7 | * Version: $Id: skbuff.c,v 1.90 2001/11/07 05:56:19 davem Exp $ | ||
8 | * | ||
9 | * Fixes: | 7 | * Fixes: |
10 | * Alan Cox : Fixed the worst of the load | 8 | * Alan Cox : Fixed the worst of the load |
11 | * balancer bugs. | 9 | * balancer bugs. |
diff --git a/net/core/sock.c b/net/core/sock.c index 88094cb09c06..3879bf65897e 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * handler for protocols to use and generic option handler. | 7 | * handler for protocols to use and generic option handler. |
8 | * | 8 | * |
9 | * | 9 | * |
10 | * Version: $Id: sock.c,v 1.117 2002/02/01 22:01:03 davem Exp $ | ||
11 | * | ||
12 | * Authors: Ross Biro | 10 | * Authors: Ross Biro |
13 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
14 | * Florian La Roche, <flla@stud.uni-sb.de> | 12 | * Florian La Roche, <flla@stud.uni-sb.de> |
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 5fc801057244..a570e2af22cb 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -125,14 +125,6 @@ static struct ctl_table net_core_table[] = { | |||
125 | #endif /* CONFIG_XFRM */ | 125 | #endif /* CONFIG_XFRM */ |
126 | #endif /* CONFIG_NET */ | 126 | #endif /* CONFIG_NET */ |
127 | { | 127 | { |
128 | .ctl_name = NET_CORE_SOMAXCONN, | ||
129 | .procname = "somaxconn", | ||
130 | .data = &init_net.core.sysctl_somaxconn, | ||
131 | .maxlen = sizeof(int), | ||
132 | .mode = 0644, | ||
133 | .proc_handler = &proc_dointvec | ||
134 | }, | ||
135 | { | ||
136 | .ctl_name = NET_CORE_BUDGET, | 128 | .ctl_name = NET_CORE_BUDGET, |
137 | .procname = "netdev_budget", | 129 | .procname = "netdev_budget", |
138 | .data = &netdev_budget, | 130 | .data = &netdev_budget, |
@@ -151,6 +143,18 @@ static struct ctl_table net_core_table[] = { | |||
151 | { .ctl_name = 0 } | 143 | { .ctl_name = 0 } |
152 | }; | 144 | }; |
153 | 145 | ||
146 | static struct ctl_table netns_core_table[] = { | ||
147 | { | ||
148 | .ctl_name = NET_CORE_SOMAXCONN, | ||
149 | .procname = "somaxconn", | ||
150 | .data = &init_net.core.sysctl_somaxconn, | ||
151 | .maxlen = sizeof(int), | ||
152 | .mode = 0644, | ||
153 | .proc_handler = &proc_dointvec | ||
154 | }, | ||
155 | { .ctl_name = 0 } | ||
156 | }; | ||
157 | |||
154 | static __net_initdata struct ctl_path net_core_path[] = { | 158 | static __net_initdata struct ctl_path net_core_path[] = { |
155 | { .procname = "net", .ctl_name = CTL_NET, }, | 159 | { .procname = "net", .ctl_name = CTL_NET, }, |
156 | { .procname = "core", .ctl_name = NET_CORE, }, | 160 | { .procname = "core", .ctl_name = NET_CORE, }, |
@@ -159,23 +163,17 @@ static __net_initdata struct ctl_path net_core_path[] = { | |||
159 | 163 | ||
160 | static __net_init int sysctl_core_net_init(struct net *net) | 164 | static __net_init int sysctl_core_net_init(struct net *net) |
161 | { | 165 | { |
162 | struct ctl_table *tbl, *tmp; | 166 | struct ctl_table *tbl; |
163 | 167 | ||
164 | net->core.sysctl_somaxconn = SOMAXCONN; | 168 | net->core.sysctl_somaxconn = SOMAXCONN; |
165 | 169 | ||
166 | tbl = net_core_table; | 170 | tbl = netns_core_table; |
167 | if (net != &init_net) { | 171 | if (net != &init_net) { |
168 | tbl = kmemdup(tbl, sizeof(net_core_table), GFP_KERNEL); | 172 | tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL); |
169 | if (tbl == NULL) | 173 | if (tbl == NULL) |
170 | goto err_dup; | 174 | goto err_dup; |
171 | 175 | ||
172 | for (tmp = tbl; tmp->procname; tmp++) { | 176 | tbl[0].data = &net->core.sysctl_somaxconn; |
173 | if (tmp->data >= (void *)&init_net && | ||
174 | tmp->data < (void *)(&init_net + 1)) | ||
175 | tmp->data += (char *)net - (char *)&init_net; | ||
176 | else | ||
177 | tmp->mode &= ~0222; | ||
178 | } | ||
179 | } | 177 | } |
180 | 178 | ||
181 | net->core.sysctl_hdr = register_net_sysctl_table(net, | 179 | net->core.sysctl_hdr = register_net_sysctl_table(net, |
@@ -186,7 +184,7 @@ static __net_init int sysctl_core_net_init(struct net *net) | |||
186 | return 0; | 184 | return 0; |
187 | 185 | ||
188 | err_reg: | 186 | err_reg: |
189 | if (tbl != net_core_table) | 187 | if (tbl != netns_core_table) |
190 | kfree(tbl); | 188 | kfree(tbl); |
191 | err_dup: | 189 | err_dup: |
192 | return -ENOMEM; | 190 | return -ENOMEM; |
@@ -198,7 +196,7 @@ static __net_exit void sysctl_core_net_exit(struct net *net) | |||
198 | 196 | ||
199 | tbl = net->core.sysctl_hdr->ctl_table_arg; | 197 | tbl = net->core.sysctl_hdr->ctl_table_arg; |
200 | unregister_net_sysctl_table(net->core.sysctl_hdr); | 198 | unregister_net_sysctl_table(net->core.sysctl_hdr); |
201 | BUG_ON(tbl == net_core_table); | 199 | BUG_ON(tbl == netns_core_table); |
202 | kfree(tbl); | 200 | kfree(tbl); |
203 | } | 201 | } |
204 | 202 | ||
@@ -209,6 +207,7 @@ static __net_initdata struct pernet_operations sysctl_core_ops = { | |||
209 | 207 | ||
210 | static __init int sysctl_core_init(void) | 208 | static __init int sysctl_core_init(void) |
211 | { | 209 | { |
210 | register_net_sysctl_rotable(net_core_path, net_core_table); | ||
212 | return register_pernet_subsys(&sysctl_core_ops); | 211 | return register_pernet_subsys(&sysctl_core_ops); |
213 | } | 212 | } |
214 | 213 | ||
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 200ee1e63728..69dbc342a464 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c | |||
@@ -391,7 +391,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
391 | 391 | ||
392 | wstats.updated = 0; | 392 | wstats.updated = 0; |
393 | if (rx_stats->mask & IEEE80211_STATMASK_RSSI) { | 393 | if (rx_stats->mask & IEEE80211_STATMASK_RSSI) { |
394 | wstats.level = rx_stats->rssi; | 394 | wstats.level = rx_stats->signal; |
395 | wstats.updated |= IW_QUAL_LEVEL_UPDATED; | 395 | wstats.updated |= IW_QUAL_LEVEL_UPDATED; |
396 | } else | 396 | } else |
397 | wstats.updated |= IW_QUAL_LEVEL_INVALID; | 397 | wstats.updated |= IW_QUAL_LEVEL_INVALID; |
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index d8b02603cbe5..d996547f7a62 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c | |||
@@ -542,90 +542,4 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
542 | return 1; | 542 | return 1; |
543 | } | 543 | } |
544 | 544 | ||
545 | /* Incoming 802.11 strucure is converted to a TXB | ||
546 | * a block of 802.11 fragment packets (stored as skbs) */ | ||
547 | int ieee80211_tx_frame(struct ieee80211_device *ieee, | ||
548 | struct ieee80211_hdr *frame, int hdr_len, int total_len, | ||
549 | int encrypt_mpdu) | ||
550 | { | ||
551 | struct ieee80211_txb *txb = NULL; | ||
552 | unsigned long flags; | ||
553 | struct net_device_stats *stats = &ieee->stats; | ||
554 | struct sk_buff *skb_frag; | ||
555 | int priority = -1; | ||
556 | int fraglen = total_len; | ||
557 | int headroom = ieee->tx_headroom; | ||
558 | struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; | ||
559 | |||
560 | spin_lock_irqsave(&ieee->lock, flags); | ||
561 | |||
562 | if (encrypt_mpdu && (!ieee->sec.encrypt || !crypt)) | ||
563 | encrypt_mpdu = 0; | ||
564 | |||
565 | /* If there is no driver handler to take the TXB, dont' bother | ||
566 | * creating it... */ | ||
567 | if (!ieee->hard_start_xmit) { | ||
568 | printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); | ||
569 | goto success; | ||
570 | } | ||
571 | |||
572 | if (unlikely(total_len < 24)) { | ||
573 | printk(KERN_WARNING "%s: skb too small (%d).\n", | ||
574 | ieee->dev->name, total_len); | ||
575 | goto success; | ||
576 | } | ||
577 | |||
578 | if (encrypt_mpdu) { | ||
579 | frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
580 | fraglen += crypt->ops->extra_mpdu_prefix_len + | ||
581 | crypt->ops->extra_mpdu_postfix_len; | ||
582 | headroom += crypt->ops->extra_mpdu_prefix_len; | ||
583 | } | ||
584 | |||
585 | /* When we allocate the TXB we allocate enough space for the reserve | ||
586 | * and full fragment bytes (bytes_per_frag doesn't include prefix, | ||
587 | * postfix, header, FCS, etc.) */ | ||
588 | txb = ieee80211_alloc_txb(1, fraglen, headroom, GFP_ATOMIC); | ||
589 | if (unlikely(!txb)) { | ||
590 | printk(KERN_WARNING "%s: Could not allocate TXB\n", | ||
591 | ieee->dev->name); | ||
592 | goto failed; | ||
593 | } | ||
594 | txb->encrypted = 0; | ||
595 | txb->payload_size = fraglen; | ||
596 | |||
597 | skb_frag = txb->fragments[0]; | ||
598 | |||
599 | memcpy(skb_put(skb_frag, total_len), frame, total_len); | ||
600 | |||
601 | if (ieee->config & | ||
602 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||
603 | skb_put(skb_frag, 4); | ||
604 | |||
605 | /* To avoid overcomplicating things, we do the corner-case frame | ||
606 | * encryption in software. The only real situation where encryption is | ||
607 | * needed here is during software-based shared key authentication. */ | ||
608 | if (encrypt_mpdu) | ||
609 | ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); | ||
610 | |||
611 | success: | ||
612 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
613 | |||
614 | if (txb) { | ||
615 | if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) { | ||
616 | stats->tx_packets++; | ||
617 | stats->tx_bytes += txb->payload_size; | ||
618 | return 0; | ||
619 | } | ||
620 | ieee80211_txb_free(txb); | ||
621 | } | ||
622 | return 0; | ||
623 | |||
624 | failed: | ||
625 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
626 | stats->tx_errors++; | ||
627 | return 1; | ||
628 | } | ||
629 | |||
630 | EXPORT_SYMBOL(ieee80211_tx_frame); | ||
631 | EXPORT_SYMBOL(ieee80211_txb_free); | 545 | EXPORT_SYMBOL(ieee80211_txb_free); |
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 623489afa62c..822606b615ca 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c | |||
@@ -744,98 +744,9 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee, | |||
744 | return 0; | 744 | return 0; |
745 | } | 745 | } |
746 | 746 | ||
747 | int ieee80211_wx_set_auth(struct net_device *dev, | ||
748 | struct iw_request_info *info, | ||
749 | union iwreq_data *wrqu, | ||
750 | char *extra) | ||
751 | { | ||
752 | struct ieee80211_device *ieee = netdev_priv(dev); | ||
753 | unsigned long flags; | ||
754 | int err = 0; | ||
755 | |||
756 | spin_lock_irqsave(&ieee->lock, flags); | ||
757 | |||
758 | switch (wrqu->param.flags & IW_AUTH_INDEX) { | ||
759 | case IW_AUTH_WPA_VERSION: | ||
760 | case IW_AUTH_CIPHER_PAIRWISE: | ||
761 | case IW_AUTH_CIPHER_GROUP: | ||
762 | case IW_AUTH_KEY_MGMT: | ||
763 | /* | ||
764 | * Host AP driver does not use these parameters and allows | ||
765 | * wpa_supplicant to control them internally. | ||
766 | */ | ||
767 | break; | ||
768 | case IW_AUTH_TKIP_COUNTERMEASURES: | ||
769 | break; /* FIXME */ | ||
770 | case IW_AUTH_DROP_UNENCRYPTED: | ||
771 | ieee->drop_unencrypted = !!wrqu->param.value; | ||
772 | break; | ||
773 | case IW_AUTH_80211_AUTH_ALG: | ||
774 | break; /* FIXME */ | ||
775 | case IW_AUTH_WPA_ENABLED: | ||
776 | ieee->privacy_invoked = ieee->wpa_enabled = !!wrqu->param.value; | ||
777 | break; | ||
778 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
779 | ieee->ieee802_1x = !!wrqu->param.value; | ||
780 | break; | ||
781 | case IW_AUTH_PRIVACY_INVOKED: | ||
782 | ieee->privacy_invoked = !!wrqu->param.value; | ||
783 | break; | ||
784 | default: | ||
785 | err = -EOPNOTSUPP; | ||
786 | break; | ||
787 | } | ||
788 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
789 | return err; | ||
790 | } | ||
791 | |||
792 | int ieee80211_wx_get_auth(struct net_device *dev, | ||
793 | struct iw_request_info *info, | ||
794 | union iwreq_data *wrqu, | ||
795 | char *extra) | ||
796 | { | ||
797 | struct ieee80211_device *ieee = netdev_priv(dev); | ||
798 | unsigned long flags; | ||
799 | int err = 0; | ||
800 | |||
801 | spin_lock_irqsave(&ieee->lock, flags); | ||
802 | |||
803 | switch (wrqu->param.flags & IW_AUTH_INDEX) { | ||
804 | case IW_AUTH_WPA_VERSION: | ||
805 | case IW_AUTH_CIPHER_PAIRWISE: | ||
806 | case IW_AUTH_CIPHER_GROUP: | ||
807 | case IW_AUTH_KEY_MGMT: | ||
808 | case IW_AUTH_TKIP_COUNTERMEASURES: /* FIXME */ | ||
809 | case IW_AUTH_80211_AUTH_ALG: /* FIXME */ | ||
810 | /* | ||
811 | * Host AP driver does not use these parameters and allows | ||
812 | * wpa_supplicant to control them internally. | ||
813 | */ | ||
814 | err = -EOPNOTSUPP; | ||
815 | break; | ||
816 | case IW_AUTH_DROP_UNENCRYPTED: | ||
817 | wrqu->param.value = ieee->drop_unencrypted; | ||
818 | break; | ||
819 | case IW_AUTH_WPA_ENABLED: | ||
820 | wrqu->param.value = ieee->wpa_enabled; | ||
821 | break; | ||
822 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
823 | wrqu->param.value = ieee->ieee802_1x; | ||
824 | break; | ||
825 | default: | ||
826 | err = -EOPNOTSUPP; | ||
827 | break; | ||
828 | } | ||
829 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
830 | return err; | ||
831 | } | ||
832 | |||
833 | EXPORT_SYMBOL(ieee80211_wx_set_encodeext); | 747 | EXPORT_SYMBOL(ieee80211_wx_set_encodeext); |
834 | EXPORT_SYMBOL(ieee80211_wx_get_encodeext); | 748 | EXPORT_SYMBOL(ieee80211_wx_get_encodeext); |
835 | 749 | ||
836 | EXPORT_SYMBOL(ieee80211_wx_get_scan); | 750 | EXPORT_SYMBOL(ieee80211_wx_get_scan); |
837 | EXPORT_SYMBOL(ieee80211_wx_set_encode); | 751 | EXPORT_SYMBOL(ieee80211_wx_set_encode); |
838 | EXPORT_SYMBOL(ieee80211_wx_get_encode); | 752 | EXPORT_SYMBOL(ieee80211_wx_get_encode); |
839 | |||
840 | EXPORT_SYMBOL_GPL(ieee80211_wx_set_auth); | ||
841 | EXPORT_SYMBOL_GPL(ieee80211_wx_get_auth); | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 24eca23c2db3..42bd24b64b57 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * PF_INET protocol family socket handler. | 6 | * PF_INET protocol family socket handler. |
7 | * | 7 | * |
8 | * Version: $Id: af_inet.c,v 1.137 2002/02/01 22:01:03 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Florian La Roche, <flla@stud.uni-sb.de> | 10 | * Florian La Roche, <flla@stud.uni-sb.de> |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 9b539fa9fe18..20c515a1be28 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -1,7 +1,5 @@ | |||
1 | /* linux/net/ipv4/arp.c | 1 | /* linux/net/ipv4/arp.c |
2 | * | 2 | * |
3 | * Version: $Id: arp.c,v 1.99 2001/08/30 22:55:42 davem Exp $ | ||
4 | * | ||
5 | * Copyright (C) 1994 by Florian La Roche | 3 | * Copyright (C) 1994 by Florian La Roche |
6 | * | 4 | * |
7 | * This module implements the Address Resolution Protocol ARP (RFC 826), | 5 | * This module implements the Address Resolution Protocol ARP (RFC 826), |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 79a7ef6209ff..f8c0b0aea93a 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * NET3 IP device support routines. | 2 | * NET3 IP device support routines. |
3 | * | 3 | * |
4 | * Version: $Id: devinet.c,v 1.44 2001/10/31 21:55:54 davem Exp $ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
8 | * as published by the Free Software Foundation; either version | 6 | * as published by the Free Software Foundation; either version |
@@ -1013,7 +1011,7 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) | |||
1013 | memcpy(old, ifa->ifa_label, IFNAMSIZ); | 1011 | memcpy(old, ifa->ifa_label, IFNAMSIZ); |
1014 | memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); | 1012 | memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); |
1015 | if (named++ == 0) | 1013 | if (named++ == 0) |
1016 | continue; | 1014 | goto skip; |
1017 | dot = strchr(old, ':'); | 1015 | dot = strchr(old, ':'); |
1018 | if (dot == NULL) { | 1016 | if (dot == NULL) { |
1019 | sprintf(old, ":%d", named); | 1017 | sprintf(old, ":%d", named); |
@@ -1024,6 +1022,8 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) | |||
1024 | } else { | 1022 | } else { |
1025 | strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); | 1023 | strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); |
1026 | } | 1024 | } |
1025 | skip: | ||
1026 | rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); | ||
1027 | } | 1027 | } |
1028 | } | 1028 | } |
1029 | 1029 | ||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 0b2ac6a3d903..5ad01d63f83b 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * IPv4 Forwarding Information Base: FIB frontend. | 6 | * IPv4 Forwarding Information Base: FIB frontend. |
7 | * | 7 | * |
8 | * Version: $Id: fib_frontend.c,v 1.26 2001/10/31 21:55:54 davem Exp $ | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
11 | * | 9 | * |
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index 2e2fc3376ac9..eeec4bf982b8 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * IPv4 FIB: lookup engine and maintenance routines. | 6 | * IPv4 FIB: lookup engine and maintenance routines. |
7 | * | 7 | * |
8 | * Version: $Id: fib_hash.c,v 1.13 2001/10/31 21:55:54 davem Exp $ | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
11 | * | 9 | * |
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 0d4d72827e4b..ded2ae34eab1 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * IPv4 Forwarding Information Base: semantics. | 6 | * IPv4 Forwarding Information Base: semantics. |
7 | * | 7 | * |
8 | * Version: $Id: fib_semantics.c,v 1.19 2002/01/12 07:54:56 davem Exp $ | ||
9 | * | ||
10 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 8 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
11 | * | 9 | * |
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 4b02d14e7ab9..394db9c941a1 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -22,8 +22,6 @@ | |||
22 | * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson | 22 | * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson |
23 | * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999 | 23 | * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999 |
24 | * | 24 | * |
25 | * Version: $Id: fib_trie.c,v 1.3 2005/06/08 14:20:01 robert Exp $ | ||
26 | * | ||
27 | * | 25 | * |
28 | * Code from fib_hash has been reused which includes the following header: | 26 | * Code from fib_hash has been reused which includes the following header: |
29 | * | 27 | * |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 87397351ddac..aa7cf46853b7 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -3,8 +3,6 @@ | |||
3 | * | 3 | * |
4 | * Alan Cox, <alan@redhat.com> | 4 | * Alan Cox, <alan@redhat.com> |
5 | * | 5 | * |
6 | * Version: $Id: icmp.c,v 1.85 2002/02/01 22:01:03 davem Exp $ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
10 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 2769dc4a4c84..68e84a933e90 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -8,8 +8,6 @@ | |||
8 | * the older version didn't come out right using gcc 2.5.8, the newer one | 8 | * the older version didn't come out right using gcc 2.5.8, the newer one |
9 | * seems to fall out with gcc 2.6.2. | 9 | * seems to fall out with gcc 2.6.2. |
10 | * | 10 | * |
11 | * Version: $Id: igmp.c,v 1.47 2002/02/01 22:01:03 davem Exp $ | ||
12 | * | ||
13 | * Authors: | 11 | * Authors: |
14 | * Alan Cox <Alan.Cox@linux.org> | 12 | * Alan Cox <Alan.Cox@linux.org> |
15 | * | 13 | * |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index da97695e7096..c10036e7a463 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * inet_diag.c Module for monitoring INET transport protocols sockets. | 2 | * inet_diag.c Module for monitoring INET transport protocols sockets. |
3 | * | 3 | * |
4 | * Version: $Id: inet_diag.c,v 1.3 2002/02/01 22:01:04 davem Exp $ | ||
5 | * | ||
6 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 4 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index af995198f643..a456ceeac3f2 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c | |||
@@ -3,8 +3,6 @@ | |||
3 | * | 3 | * |
4 | * This source is covered by the GNU GPL, the same as all kernel sources. | 4 | * This source is covered by the GNU GPL, the same as all kernel sources. |
5 | * | 5 | * |
6 | * Version: $Id: inetpeer.c,v 1.7 2001/09/20 21:22:50 davem Exp $ | ||
7 | * | ||
8 | * Authors: Andrey V. Savochkin <saw@msu.ru> | 6 | * Authors: Andrey V. Savochkin <saw@msu.ru> |
9 | */ | 7 | */ |
10 | 8 | ||
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 4813c39b438b..37d36a3f33cd 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * The IP forwarding functionality. | 6 | * The IP forwarding functionality. |
7 | * | 7 | * |
8 | * Version: $Id: ip_forward.c,v 1.48 2000/12/13 18:31:48 davem Exp $ | ||
9 | * | ||
10 | * Authors: see ip.c | 8 | * Authors: see ip.c |
11 | * | 9 | * |
12 | * Fixes: | 10 | * Fixes: |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index cd6ce6ac6358..91e321407313 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * The IP fragmentation functionality. | 6 | * The IP fragmentation functionality. |
7 | * | 7 | * |
8 | * Version: $Id: ip_fragment.c,v 1.59 2002/01/12 07:54:56 davem Exp $ | ||
9 | * | ||
10 | * Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG> | 8 | * Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG> |
11 | * Alan Cox <Alan.Cox@linux.org> | 9 | * Alan Cox <Alan.Cox@linux.org> |
12 | * | 10 | * |
@@ -598,7 +596,7 @@ int ip_defrag(struct sk_buff *skb, u32 user) | |||
598 | #ifdef CONFIG_SYSCTL | 596 | #ifdef CONFIG_SYSCTL |
599 | static int zero; | 597 | static int zero; |
600 | 598 | ||
601 | static struct ctl_table ip4_frags_ctl_table[] = { | 599 | static struct ctl_table ip4_frags_ns_ctl_table[] = { |
602 | { | 600 | { |
603 | .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH, | 601 | .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH, |
604 | .procname = "ipfrag_high_thresh", | 602 | .procname = "ipfrag_high_thresh", |
@@ -624,6 +622,10 @@ static struct ctl_table ip4_frags_ctl_table[] = { | |||
624 | .proc_handler = &proc_dointvec_jiffies, | 622 | .proc_handler = &proc_dointvec_jiffies, |
625 | .strategy = &sysctl_jiffies | 623 | .strategy = &sysctl_jiffies |
626 | }, | 624 | }, |
625 | { } | ||
626 | }; | ||
627 | |||
628 | static struct ctl_table ip4_frags_ctl_table[] = { | ||
627 | { | 629 | { |
628 | .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL, | 630 | .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL, |
629 | .procname = "ipfrag_secret_interval", | 631 | .procname = "ipfrag_secret_interval", |
@@ -644,22 +646,20 @@ static struct ctl_table ip4_frags_ctl_table[] = { | |||
644 | { } | 646 | { } |
645 | }; | 647 | }; |
646 | 648 | ||
647 | static int ip4_frags_ctl_register(struct net *net) | 649 | static int ip4_frags_ns_ctl_register(struct net *net) |
648 | { | 650 | { |
649 | struct ctl_table *table; | 651 | struct ctl_table *table; |
650 | struct ctl_table_header *hdr; | 652 | struct ctl_table_header *hdr; |
651 | 653 | ||
652 | table = ip4_frags_ctl_table; | 654 | table = ip4_frags_ns_ctl_table; |
653 | if (net != &init_net) { | 655 | if (net != &init_net) { |
654 | table = kmemdup(table, sizeof(ip4_frags_ctl_table), GFP_KERNEL); | 656 | table = kmemdup(table, sizeof(ip4_frags_ns_ctl_table), GFP_KERNEL); |
655 | if (table == NULL) | 657 | if (table == NULL) |
656 | goto err_alloc; | 658 | goto err_alloc; |
657 | 659 | ||
658 | table[0].data = &net->ipv4.frags.high_thresh; | 660 | table[0].data = &net->ipv4.frags.high_thresh; |
659 | table[1].data = &net->ipv4.frags.low_thresh; | 661 | table[1].data = &net->ipv4.frags.low_thresh; |
660 | table[2].data = &net->ipv4.frags.timeout; | 662 | table[2].data = &net->ipv4.frags.timeout; |
661 | table[3].mode &= ~0222; | ||
662 | table[4].mode &= ~0222; | ||
663 | } | 663 | } |
664 | 664 | ||
665 | hdr = register_net_sysctl_table(net, net_ipv4_ctl_path, table); | 665 | hdr = register_net_sysctl_table(net, net_ipv4_ctl_path, table); |
@@ -676,7 +676,7 @@ err_alloc: | |||
676 | return -ENOMEM; | 676 | return -ENOMEM; |
677 | } | 677 | } |
678 | 678 | ||
679 | static void ip4_frags_ctl_unregister(struct net *net) | 679 | static void ip4_frags_ns_ctl_unregister(struct net *net) |
680 | { | 680 | { |
681 | struct ctl_table *table; | 681 | struct ctl_table *table; |
682 | 682 | ||
@@ -684,13 +684,22 @@ static void ip4_frags_ctl_unregister(struct net *net) | |||
684 | unregister_net_sysctl_table(net->ipv4.frags_hdr); | 684 | unregister_net_sysctl_table(net->ipv4.frags_hdr); |
685 | kfree(table); | 685 | kfree(table); |
686 | } | 686 | } |
687 | |||
688 | static void ip4_frags_ctl_register(void) | ||
689 | { | ||
690 | register_net_sysctl_rotable(net_ipv4_ctl_path, ip4_frags_ctl_table); | ||
691 | } | ||
687 | #else | 692 | #else |
688 | static inline int ip4_frags_ctl_register(struct net *net) | 693 | static inline int ip4_frags_ns_ctl_register(struct net *net) |
689 | { | 694 | { |
690 | return 0; | 695 | return 0; |
691 | } | 696 | } |
692 | 697 | ||
693 | static inline void ip4_frags_ctl_unregister(struct net *net) | 698 | static inline void ip4_frags_ns_ctl_unregister(struct net *net) |
699 | { | ||
700 | } | ||
701 | |||
702 | static inline void ip4_frags_ctl_register(void) | ||
694 | { | 703 | { |
695 | } | 704 | } |
696 | #endif | 705 | #endif |
@@ -714,12 +723,12 @@ static int ipv4_frags_init_net(struct net *net) | |||
714 | 723 | ||
715 | inet_frags_init_net(&net->ipv4.frags); | 724 | inet_frags_init_net(&net->ipv4.frags); |
716 | 725 | ||
717 | return ip4_frags_ctl_register(net); | 726 | return ip4_frags_ns_ctl_register(net); |
718 | } | 727 | } |
719 | 728 | ||
720 | static void ipv4_frags_exit_net(struct net *net) | 729 | static void ipv4_frags_exit_net(struct net *net) |
721 | { | 730 | { |
722 | ip4_frags_ctl_unregister(net); | 731 | ip4_frags_ns_ctl_unregister(net); |
723 | inet_frags_exit_net(&net->ipv4.frags, &ip4_frags); | 732 | inet_frags_exit_net(&net->ipv4.frags, &ip4_frags); |
724 | } | 733 | } |
725 | 734 | ||
@@ -730,6 +739,7 @@ static struct pernet_operations ip4_frags_ops = { | |||
730 | 739 | ||
731 | void __init ipfrag_init(void) | 740 | void __init ipfrag_init(void) |
732 | { | 741 | { |
742 | ip4_frags_ctl_register(); | ||
733 | register_pernet_subsys(&ip4_frags_ops); | 743 | register_pernet_subsys(&ip4_frags_ops); |
734 | ip4_frags.hashfn = ip4_hashfn; | 744 | ip4_frags.hashfn = ip4_hashfn; |
735 | ip4_frags.constructor = ip4_frag_init; | 745 | ip4_frags.constructor = ip4_frag_init; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 4342cba4ff82..2a61158ea722 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -473,6 +473,8 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
473 | read_lock(&ipgre_lock); | 473 | read_lock(&ipgre_lock); |
474 | if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev), | 474 | if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev), |
475 | iph->saddr, iph->daddr, key)) != NULL) { | 475 | iph->saddr, iph->daddr, key)) != NULL) { |
476 | struct net_device_stats *stats = &tunnel->dev->stats; | ||
477 | |||
476 | secpath_reset(skb); | 478 | secpath_reset(skb); |
477 | 479 | ||
478 | skb->protocol = *(__be16*)(h + 2); | 480 | skb->protocol = *(__be16*)(h + 2); |
@@ -497,28 +499,28 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
497 | /* Looped back packet, drop it! */ | 499 | /* Looped back packet, drop it! */ |
498 | if (skb->rtable->fl.iif == 0) | 500 | if (skb->rtable->fl.iif == 0) |
499 | goto drop; | 501 | goto drop; |
500 | tunnel->stat.multicast++; | 502 | stats->multicast++; |
501 | skb->pkt_type = PACKET_BROADCAST; | 503 | skb->pkt_type = PACKET_BROADCAST; |
502 | } | 504 | } |
503 | #endif | 505 | #endif |
504 | 506 | ||
505 | if (((flags&GRE_CSUM) && csum) || | 507 | if (((flags&GRE_CSUM) && csum) || |
506 | (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) { | 508 | (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) { |
507 | tunnel->stat.rx_crc_errors++; | 509 | stats->rx_crc_errors++; |
508 | tunnel->stat.rx_errors++; | 510 | stats->rx_errors++; |
509 | goto drop; | 511 | goto drop; |
510 | } | 512 | } |
511 | if (tunnel->parms.i_flags&GRE_SEQ) { | 513 | if (tunnel->parms.i_flags&GRE_SEQ) { |
512 | if (!(flags&GRE_SEQ) || | 514 | if (!(flags&GRE_SEQ) || |
513 | (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) { | 515 | (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) { |
514 | tunnel->stat.rx_fifo_errors++; | 516 | stats->rx_fifo_errors++; |
515 | tunnel->stat.rx_errors++; | 517 | stats->rx_errors++; |
516 | goto drop; | 518 | goto drop; |
517 | } | 519 | } |
518 | tunnel->i_seqno = seqno + 1; | 520 | tunnel->i_seqno = seqno + 1; |
519 | } | 521 | } |
520 | tunnel->stat.rx_packets++; | 522 | stats->rx_packets++; |
521 | tunnel->stat.rx_bytes += skb->len; | 523 | stats->rx_bytes += skb->len; |
522 | skb->dev = tunnel->dev; | 524 | skb->dev = tunnel->dev; |
523 | dst_release(skb->dst); | 525 | dst_release(skb->dst); |
524 | skb->dst = NULL; | 526 | skb->dst = NULL; |
@@ -540,7 +542,7 @@ drop_nolock: | |||
540 | static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 542 | static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
541 | { | 543 | { |
542 | struct ip_tunnel *tunnel = netdev_priv(dev); | 544 | struct ip_tunnel *tunnel = netdev_priv(dev); |
543 | struct net_device_stats *stats = &tunnel->stat; | 545 | struct net_device_stats *stats = &tunnel->dev->stats; |
544 | struct iphdr *old_iph = ip_hdr(skb); | 546 | struct iphdr *old_iph = ip_hdr(skb); |
545 | struct iphdr *tiph; | 547 | struct iphdr *tiph; |
546 | u8 tos; | 548 | u8 tos; |
@@ -554,7 +556,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
554 | int mtu; | 556 | int mtu; |
555 | 557 | ||
556 | if (tunnel->recursion++) { | 558 | if (tunnel->recursion++) { |
557 | tunnel->stat.collisions++; | 559 | stats->collisions++; |
558 | goto tx_error; | 560 | goto tx_error; |
559 | } | 561 | } |
560 | 562 | ||
@@ -570,7 +572,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
570 | /* NBMA tunnel */ | 572 | /* NBMA tunnel */ |
571 | 573 | ||
572 | if (skb->dst == NULL) { | 574 | if (skb->dst == NULL) { |
573 | tunnel->stat.tx_fifo_errors++; | 575 | stats->tx_fifo_errors++; |
574 | goto tx_error; | 576 | goto tx_error; |
575 | } | 577 | } |
576 | 578 | ||
@@ -621,7 +623,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
621 | .tos = RT_TOS(tos) } }, | 623 | .tos = RT_TOS(tos) } }, |
622 | .proto = IPPROTO_GRE }; | 624 | .proto = IPPROTO_GRE }; |
623 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 625 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { |
624 | tunnel->stat.tx_carrier_errors++; | 626 | stats->tx_carrier_errors++; |
625 | goto tx_error; | 627 | goto tx_error; |
626 | } | 628 | } |
627 | } | 629 | } |
@@ -629,7 +631,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
629 | 631 | ||
630 | if (tdev == dev) { | 632 | if (tdev == dev) { |
631 | ip_rt_put(rt); | 633 | ip_rt_put(rt); |
632 | tunnel->stat.collisions++; | 634 | stats->collisions++; |
633 | goto tx_error; | 635 | goto tx_error; |
634 | } | 636 | } |
635 | 637 | ||
@@ -954,11 +956,6 @@ done: | |||
954 | return err; | 956 | return err; |
955 | } | 957 | } |
956 | 958 | ||
957 | static struct net_device_stats *ipgre_tunnel_get_stats(struct net_device *dev) | ||
958 | { | ||
959 | return &(((struct ip_tunnel*)netdev_priv(dev))->stat); | ||
960 | } | ||
961 | |||
962 | static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 959 | static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) |
963 | { | 960 | { |
964 | struct ip_tunnel *tunnel = netdev_priv(dev); | 961 | struct ip_tunnel *tunnel = netdev_priv(dev); |
@@ -1084,7 +1081,6 @@ static void ipgre_tunnel_setup(struct net_device *dev) | |||
1084 | dev->uninit = ipgre_tunnel_uninit; | 1081 | dev->uninit = ipgre_tunnel_uninit; |
1085 | dev->destructor = free_netdev; | 1082 | dev->destructor = free_netdev; |
1086 | dev->hard_start_xmit = ipgre_tunnel_xmit; | 1083 | dev->hard_start_xmit = ipgre_tunnel_xmit; |
1087 | dev->get_stats = ipgre_tunnel_get_stats; | ||
1088 | dev->do_ioctl = ipgre_tunnel_ioctl; | 1084 | dev->do_ioctl = ipgre_tunnel_ioctl; |
1089 | dev->change_mtu = ipgre_tunnel_change_mtu; | 1085 | dev->change_mtu = ipgre_tunnel_change_mtu; |
1090 | 1086 | ||
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index ff77a4a7f9ec..7c26428ea67b 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * The Internet Protocol (IP) module. | 6 | * The Internet Protocol (IP) module. |
7 | * | 7 | * |
8 | * Version: $Id: ip_input.c,v 1.55 2002/01/12 07:39:45 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Donald Becker, <becker@super.org> | 10 | * Donald Becker, <becker@super.org> |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 33126ad2cfdc..be3f18a7a40e 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * The options processing module for ip.c | 6 | * The options processing module for ip.c |
7 | * | 7 | * |
8 | * Version: $Id: ip_options.c,v 1.21 2001/09/01 00:31:50 davem Exp $ | ||
9 | * | ||
10 | * Authors: A.N.Kuznetsov | 8 | * Authors: A.N.Kuznetsov |
11 | * | 9 | * |
12 | */ | 10 | */ |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index e527628f56cf..f1278eecf56d 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * The Internet Protocol (IP) output module. | 6 | * The Internet Protocol (IP) output module. |
7 | * | 7 | * |
8 | * Version: $Id: ip_output.c,v 1.100 2002/02/01 22:01:03 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Donald Becker, <becker@super.org> | 10 | * Donald Becker, <becker@super.org> |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index e0514e82308e..105d92a039b9 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * The IP to API glue. | 6 | * The IP to API glue. |
7 | * | 7 | * |
8 | * Version: $Id: ip_sockglue.c,v 1.62 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Authors: see ip.c | 8 | * Authors: see ip.c |
11 | * | 9 | * |
12 | * Fixes: | 10 | * Fixes: |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index ed45037ce9be..b88aa9afa42e 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: ipconfig.c,v 1.46 2002/02/01 22:01:04 davem Exp $ | ||
3 | * | ||
4 | * Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or | 2 | * Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or |
5 | * user-supplied information to configure own IP address and routes. | 3 | * user-supplied information to configure own IP address and routes. |
6 | * | 4 | * |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index af5cb53da5cc..4c6d2caf9203 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Linux NET3: IP/IP protocol decoder. | 2 | * Linux NET3: IP/IP protocol decoder. |
3 | * | 3 | * |
4 | * Version: $Id: ipip.c,v 1.50 2001/10/02 02:22:36 davem Exp $ | ||
5 | * | ||
6 | * Authors: | 4 | * Authors: |
7 | * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 | 5 | * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 |
8 | * | 6 | * |
@@ -368,8 +366,8 @@ static int ipip_rcv(struct sk_buff *skb) | |||
368 | skb->protocol = htons(ETH_P_IP); | 366 | skb->protocol = htons(ETH_P_IP); |
369 | skb->pkt_type = PACKET_HOST; | 367 | skb->pkt_type = PACKET_HOST; |
370 | 368 | ||
371 | tunnel->stat.rx_packets++; | 369 | tunnel->dev->stats.rx_packets++; |
372 | tunnel->stat.rx_bytes += skb->len; | 370 | tunnel->dev->stats.rx_bytes += skb->len; |
373 | skb->dev = tunnel->dev; | 371 | skb->dev = tunnel->dev; |
374 | dst_release(skb->dst); | 372 | dst_release(skb->dst); |
375 | skb->dst = NULL; | 373 | skb->dst = NULL; |
@@ -392,7 +390,7 @@ static int ipip_rcv(struct sk_buff *skb) | |||
392 | static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 390 | static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
393 | { | 391 | { |
394 | struct ip_tunnel *tunnel = netdev_priv(dev); | 392 | struct ip_tunnel *tunnel = netdev_priv(dev); |
395 | struct net_device_stats *stats = &tunnel->stat; | 393 | struct net_device_stats *stats = &tunnel->dev->stats; |
396 | struct iphdr *tiph = &tunnel->parms.iph; | 394 | struct iphdr *tiph = &tunnel->parms.iph; |
397 | u8 tos = tunnel->parms.iph.tos; | 395 | u8 tos = tunnel->parms.iph.tos; |
398 | __be16 df = tiph->frag_off; | 396 | __be16 df = tiph->frag_off; |
@@ -405,7 +403,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
405 | int mtu; | 403 | int mtu; |
406 | 404 | ||
407 | if (tunnel->recursion++) { | 405 | if (tunnel->recursion++) { |
408 | tunnel->stat.collisions++; | 406 | stats->collisions++; |
409 | goto tx_error; | 407 | goto tx_error; |
410 | } | 408 | } |
411 | 409 | ||
@@ -418,7 +416,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
418 | if (!dst) { | 416 | if (!dst) { |
419 | /* NBMA tunnel */ | 417 | /* NBMA tunnel */ |
420 | if ((rt = skb->rtable) == NULL) { | 418 | if ((rt = skb->rtable) == NULL) { |
421 | tunnel->stat.tx_fifo_errors++; | 419 | stats->tx_fifo_errors++; |
422 | goto tx_error; | 420 | goto tx_error; |
423 | } | 421 | } |
424 | if ((dst = rt->rt_gateway) == 0) | 422 | if ((dst = rt->rt_gateway) == 0) |
@@ -433,7 +431,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
433 | .tos = RT_TOS(tos) } }, | 431 | .tos = RT_TOS(tos) } }, |
434 | .proto = IPPROTO_IPIP }; | 432 | .proto = IPPROTO_IPIP }; |
435 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 433 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { |
436 | tunnel->stat.tx_carrier_errors++; | 434 | stats->tx_carrier_errors++; |
437 | goto tx_error_icmp; | 435 | goto tx_error_icmp; |
438 | } | 436 | } |
439 | } | 437 | } |
@@ -441,7 +439,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
441 | 439 | ||
442 | if (tdev == dev) { | 440 | if (tdev == dev) { |
443 | ip_rt_put(rt); | 441 | ip_rt_put(rt); |
444 | tunnel->stat.collisions++; | 442 | stats->collisions++; |
445 | goto tx_error; | 443 | goto tx_error; |
446 | } | 444 | } |
447 | 445 | ||
@@ -451,7 +449,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
451 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; | 449 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; |
452 | 450 | ||
453 | if (mtu < 68) { | 451 | if (mtu < 68) { |
454 | tunnel->stat.collisions++; | 452 | stats->collisions++; |
455 | ip_rt_put(rt); | 453 | ip_rt_put(rt); |
456 | goto tx_error; | 454 | goto tx_error; |
457 | } | 455 | } |
@@ -685,11 +683,6 @@ done: | |||
685 | return err; | 683 | return err; |
686 | } | 684 | } |
687 | 685 | ||
688 | static struct net_device_stats *ipip_tunnel_get_stats(struct net_device *dev) | ||
689 | { | ||
690 | return &(((struct ip_tunnel*)netdev_priv(dev))->stat); | ||
691 | } | ||
692 | |||
693 | static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 686 | static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu) |
694 | { | 687 | { |
695 | if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr)) | 688 | if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr)) |
@@ -702,7 +695,6 @@ static void ipip_tunnel_setup(struct net_device *dev) | |||
702 | { | 695 | { |
703 | dev->uninit = ipip_tunnel_uninit; | 696 | dev->uninit = ipip_tunnel_uninit; |
704 | dev->hard_start_xmit = ipip_tunnel_xmit; | 697 | dev->hard_start_xmit = ipip_tunnel_xmit; |
705 | dev->get_stats = ipip_tunnel_get_stats; | ||
706 | dev->do_ioctl = ipip_tunnel_ioctl; | 698 | dev->do_ioctl = ipip_tunnel_ioctl; |
707 | dev->change_mtu = ipip_tunnel_change_mtu; | 699 | dev->change_mtu = ipip_tunnel_change_mtu; |
708 | dev->destructor = free_netdev; | 700 | dev->destructor = free_netdev; |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 11700a4dcd95..300ab0c2919e 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -9,8 +9,6 @@ | |||
9 | * as published by the Free Software Foundation; either version | 9 | * as published by the Free Software Foundation; either version |
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * Version: $Id: ipmr.c,v 1.65 2001/10/31 21:55:54 davem Exp $ | ||
13 | * | ||
14 | * Fixes: | 12 | * Fixes: |
15 | * Michael Chastain : Incorrect size of copying. | 13 | * Michael Chastain : Incorrect size of copying. |
16 | * Alan Cox : Added the cache manager code | 14 | * Alan Cox : Added the cache manager code |
@@ -181,26 +179,20 @@ static int reg_vif_num = -1; | |||
181 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | 179 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) |
182 | { | 180 | { |
183 | read_lock(&mrt_lock); | 181 | read_lock(&mrt_lock); |
184 | ((struct net_device_stats*)netdev_priv(dev))->tx_bytes += skb->len; | 182 | dev->stats.tx_bytes += skb->len; |
185 | ((struct net_device_stats*)netdev_priv(dev))->tx_packets++; | 183 | dev->stats.tx_packets++; |
186 | ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT); | 184 | ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT); |
187 | read_unlock(&mrt_lock); | 185 | read_unlock(&mrt_lock); |
188 | kfree_skb(skb); | 186 | kfree_skb(skb); |
189 | return 0; | 187 | return 0; |
190 | } | 188 | } |
191 | 189 | ||
192 | static struct net_device_stats *reg_vif_get_stats(struct net_device *dev) | ||
193 | { | ||
194 | return (struct net_device_stats*)netdev_priv(dev); | ||
195 | } | ||
196 | |||
197 | static void reg_vif_setup(struct net_device *dev) | 190 | static void reg_vif_setup(struct net_device *dev) |
198 | { | 191 | { |
199 | dev->type = ARPHRD_PIMREG; | 192 | dev->type = ARPHRD_PIMREG; |
200 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8; | 193 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8; |
201 | dev->flags = IFF_NOARP; | 194 | dev->flags = IFF_NOARP; |
202 | dev->hard_start_xmit = reg_vif_xmit; | 195 | dev->hard_start_xmit = reg_vif_xmit; |
203 | dev->get_stats = reg_vif_get_stats; | ||
204 | dev->destructor = free_netdev; | 196 | dev->destructor = free_netdev; |
205 | } | 197 | } |
206 | 198 | ||
@@ -209,8 +201,7 @@ static struct net_device *ipmr_reg_vif(void) | |||
209 | struct net_device *dev; | 201 | struct net_device *dev; |
210 | struct in_device *in_dev; | 202 | struct in_device *in_dev; |
211 | 203 | ||
212 | dev = alloc_netdev(sizeof(struct net_device_stats), "pimreg", | 204 | dev = alloc_netdev(0, "pimreg", reg_vif_setup); |
213 | reg_vif_setup); | ||
214 | 205 | ||
215 | if (dev == NULL) | 206 | if (dev == NULL) |
216 | return NULL; | 207 | return NULL; |
@@ -1170,8 +1161,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1170 | if (vif->flags & VIFF_REGISTER) { | 1161 | if (vif->flags & VIFF_REGISTER) { |
1171 | vif->pkt_out++; | 1162 | vif->pkt_out++; |
1172 | vif->bytes_out+=skb->len; | 1163 | vif->bytes_out+=skb->len; |
1173 | ((struct net_device_stats*)netdev_priv(vif->dev))->tx_bytes += skb->len; | 1164 | vif->dev->stats.tx_bytes += skb->len; |
1174 | ((struct net_device_stats*)netdev_priv(vif->dev))->tx_packets++; | 1165 | vif->dev->stats.tx_packets++; |
1175 | ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT); | 1166 | ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT); |
1176 | kfree_skb(skb); | 1167 | kfree_skb(skb); |
1177 | return; | 1168 | return; |
@@ -1230,8 +1221,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1230 | if (vif->flags & VIFF_TUNNEL) { | 1221 | if (vif->flags & VIFF_TUNNEL) { |
1231 | ip_encap(skb, vif->local, vif->remote); | 1222 | ip_encap(skb, vif->local, vif->remote); |
1232 | /* FIXME: extra output firewall step used to be here. --RR */ | 1223 | /* FIXME: extra output firewall step used to be here. --RR */ |
1233 | ((struct ip_tunnel *)netdev_priv(vif->dev))->stat.tx_packets++; | 1224 | vif->dev->stats.tx_packets++; |
1234 | ((struct ip_tunnel *)netdev_priv(vif->dev))->stat.tx_bytes+=skb->len; | 1225 | vif->dev->stats.tx_bytes += skb->len; |
1235 | } | 1226 | } |
1236 | 1227 | ||
1237 | IPCB(skb)->flags |= IPSKB_FORWARDED; | 1228 | IPCB(skb)->flags |= IPSKB_FORWARDED; |
@@ -1487,8 +1478,8 @@ int pim_rcv_v1(struct sk_buff * skb) | |||
1487 | skb->pkt_type = PACKET_HOST; | 1478 | skb->pkt_type = PACKET_HOST; |
1488 | dst_release(skb->dst); | 1479 | dst_release(skb->dst); |
1489 | skb->dst = NULL; | 1480 | skb->dst = NULL; |
1490 | ((struct net_device_stats*)netdev_priv(reg_dev))->rx_bytes += skb->len; | 1481 | reg_dev->stats.rx_bytes += skb->len; |
1491 | ((struct net_device_stats*)netdev_priv(reg_dev))->rx_packets++; | 1482 | reg_dev->stats.rx_packets++; |
1492 | nf_reset(skb); | 1483 | nf_reset(skb); |
1493 | netif_rx(skb); | 1484 | netif_rx(skb); |
1494 | dev_put(reg_dev); | 1485 | dev_put(reg_dev); |
@@ -1542,8 +1533,8 @@ static int pim_rcv(struct sk_buff * skb) | |||
1542 | skb->ip_summed = 0; | 1533 | skb->ip_summed = 0; |
1543 | skb->pkt_type = PACKET_HOST; | 1534 | skb->pkt_type = PACKET_HOST; |
1544 | dst_release(skb->dst); | 1535 | dst_release(skb->dst); |
1545 | ((struct net_device_stats*)netdev_priv(reg_dev))->rx_bytes += skb->len; | 1536 | reg_dev->stats.rx_bytes += skb->len; |
1546 | ((struct net_device_stats*)netdev_priv(reg_dev))->rx_packets++; | 1537 | reg_dev->stats.rx_packets++; |
1547 | skb->dst = NULL; | 1538 | skb->dst = NULL; |
1548 | nf_reset(skb); | 1539 | nf_reset(skb); |
1549 | netif_rx(skb); | 1540 | netif_rx(skb); |
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index 535abe0c45e7..1f1897a1a702 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_app.c: Application module support for IPVS | 2 | * ip_vs_app.c: Application module support for IPVS |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_app.c,v 1.17 2003/03/22 06:31:21 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index 65f1ba112752..f8bdae47a77f 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * high-performance and highly available server based on a | 5 | * high-performance and highly available server based on a |
6 | * cluster of servers. | 6 | * cluster of servers. |
7 | * | 7 | * |
8 | * Version: $Id: ip_vs_conn.c,v 1.31 2003/04/18 09:03:16 wensong Exp $ | ||
9 | * | ||
10 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 8 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
11 | * Peter Kese <peter.kese@ijs.si> | 9 | * Peter Kese <peter.kese@ijs.si> |
12 | * Julian Anastasov <ja@ssi.bg> | 10 | * Julian Anastasov <ja@ssi.bg> |
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 963981a9d501..bcf6276ba4b2 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * high-performance and highly available server based on a | 5 | * high-performance and highly available server based on a |
6 | * cluster of servers. | 6 | * cluster of servers. |
7 | * | 7 | * |
8 | * Version: $Id: ip_vs_core.c,v 1.34 2003/05/10 03:05:23 wensong Exp $ | ||
9 | * | ||
10 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 8 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
11 | * Peter Kese <peter.kese@ijs.si> | 9 | * Peter Kese <peter.kese@ijs.si> |
12 | * Julian Anastasov <ja@ssi.bg> | 10 | * Julian Anastasov <ja@ssi.bg> |
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 94c5767c8e01..9a5ace0b4dd6 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * high-performance and highly available server based on a | 5 | * high-performance and highly available server based on a |
6 | * cluster of servers. | 6 | * cluster of servers. |
7 | * | 7 | * |
8 | * Version: $Id: ip_vs_ctl.c,v 1.36 2003/06/08 09:31:19 wensong Exp $ | ||
9 | * | ||
10 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 8 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
11 | * Peter Kese <peter.kese@ijs.si> | 9 | * Peter Kese <peter.kese@ijs.si> |
12 | * Julian Anastasov <ja@ssi.bg> | 10 | * Julian Anastasov <ja@ssi.bg> |
diff --git a/net/ipv4/ipvs/ip_vs_dh.c b/net/ipv4/ipvs/ip_vs_dh.c index dcf5d46aaa5e..8afc1503ed20 100644 --- a/net/ipv4/ipvs/ip_vs_dh.c +++ b/net/ipv4/ipvs/ip_vs_dh.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Destination Hashing scheduling module | 2 | * IPVS: Destination Hashing scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_dh.c,v 1.5 2002/09/15 08:14:08 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@gnuchina.org> | 4 | * Authors: Wensong Zhang <wensong@gnuchina.org> |
7 | * | 5 | * |
8 | * Inspired by the consistent hashing scheduler patch from | 6 | * Inspired by the consistent hashing scheduler patch from |
diff --git a/net/ipv4/ipvs/ip_vs_est.c b/net/ipv4/ipvs/ip_vs_est.c index dfa0d713c801..bc04eedd6dbb 100644 --- a/net/ipv4/ipvs/ip_vs_est.c +++ b/net/ipv4/ipvs/ip_vs_est.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_est.c: simple rate estimator for IPVS | 2 | * ip_vs_est.c: simple rate estimator for IPVS |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_est.c,v 1.4 2002/11/30 01:50:35 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c index 59aa166b7678..c1c758e4f733 100644 --- a/net/ipv4/ipvs/ip_vs_ftp.c +++ b/net/ipv4/ipvs/ip_vs_ftp.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_ftp.c: IPVS ftp application module | 2 | * ip_vs_ftp.c: IPVS ftp application module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_ftp.c,v 1.13 2002/09/15 08:14:08 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * | 5 | * |
8 | * Changes: | 6 | * Changes: |
diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c index 3888642706ad..0efa3db4b180 100644 --- a/net/ipv4/ipvs/ip_vs_lblc.c +++ b/net/ipv4/ipvs/ip_vs_lblc.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Locality-Based Least-Connection scheduling module | 2 | * IPVS: Locality-Based Least-Connection scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_lblc.c,v 1.10 2002/09/15 08:14:08 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@gnuchina.org> | 4 | * Authors: Wensong Zhang <wensong@gnuchina.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c index daa260eb21cf..8e3bbeb45138 100644 --- a/net/ipv4/ipvs/ip_vs_lblcr.c +++ b/net/ipv4/ipvs/ip_vs_lblcr.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Locality-Based Least-Connection with Replication scheduler | 2 | * IPVS: Locality-Based Least-Connection with Replication scheduler |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_lblcr.c,v 1.11 2002/09/15 08:14:08 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@gnuchina.org> | 4 | * Authors: Wensong Zhang <wensong@gnuchina.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_lc.c b/net/ipv4/ipvs/ip_vs_lc.c index d88fef90a641..ac9f08e065d5 100644 --- a/net/ipv4/ipvs/ip_vs_lc.c +++ b/net/ipv4/ipvs/ip_vs_lc.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Least-Connection Scheduling module | 2 | * IPVS: Least-Connection Scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_lc.c,v 1.10 2003/04/18 09:03:16 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_nq.c b/net/ipv4/ipvs/ip_vs_nq.c index bc2a9e5f2a7b..a46bf258d420 100644 --- a/net/ipv4/ipvs/ip_vs_nq.c +++ b/net/ipv4/ipvs/ip_vs_nq.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Never Queue scheduling module | 2 | * IPVS: Never Queue scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_nq.c,v 1.2 2003/06/08 09:31:19 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c index 4b1c16cbb16b..876714f23d65 100644 --- a/net/ipv4/ipvs/ip_vs_proto.c +++ b/net/ipv4/ipvs/ip_vs_proto.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_proto.c: transport protocol load balancing support for IPVS | 2 | * ip_vs_proto.c: transport protocol load balancing support for IPVS |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_proto.c,v 1.2 2003/04/18 09:03:16 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * Julian Anastasov <ja@ssi.bg> | 5 | * Julian Anastasov <ja@ssi.bg> |
8 | * | 6 | * |
diff --git a/net/ipv4/ipvs/ip_vs_proto_ah.c b/net/ipv4/ipvs/ip_vs_proto_ah.c index 4bf835e1d86d..73e0ea87c1f5 100644 --- a/net/ipv4/ipvs/ip_vs_proto_ah.c +++ b/net/ipv4/ipvs/ip_vs_proto_ah.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_proto_ah.c: AH IPSec load balancing support for IPVS | 2 | * ip_vs_proto_ah.c: AH IPSec load balancing support for IPVS |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_proto_ah.c,v 1.1 2003/07/04 15:04:37 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Julian Anastasov <ja@ssi.bg>, February 2002 | 4 | * Authors: Julian Anastasov <ja@ssi.bg>, February 2002 |
7 | * Wensong Zhang <wensong@linuxvirtualserver.org> | 5 | * Wensong Zhang <wensong@linuxvirtualserver.org> |
8 | * | 6 | * |
diff --git a/net/ipv4/ipvs/ip_vs_proto_esp.c b/net/ipv4/ipvs/ip_vs_proto_esp.c index db6a6b7b1a0b..21d70c8ffa54 100644 --- a/net/ipv4/ipvs/ip_vs_proto_esp.c +++ b/net/ipv4/ipvs/ip_vs_proto_esp.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_proto_esp.c: ESP IPSec load balancing support for IPVS | 2 | * ip_vs_proto_esp.c: ESP IPSec load balancing support for IPVS |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_proto_esp.c,v 1.1 2003/07/04 15:04:37 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Julian Anastasov <ja@ssi.bg>, February 2002 | 4 | * Authors: Julian Anastasov <ja@ssi.bg>, February 2002 |
7 | * Wensong Zhang <wensong@linuxvirtualserver.org> | 5 | * Wensong Zhang <wensong@linuxvirtualserver.org> |
8 | * | 6 | * |
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index b83dc14b0a4d..d0ea467986a0 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_proto_tcp.c: TCP load balancing support for IPVS | 2 | * ip_vs_proto_tcp.c: TCP load balancing support for IPVS |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_proto_tcp.c,v 1.3 2002/11/30 01:50:35 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * Julian Anastasov <ja@ssi.bg> | 5 | * Julian Anastasov <ja@ssi.bg> |
8 | * | 6 | * |
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 75771cb3cd6f..c6be5d56823f 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_proto_udp.c: UDP load balancing support for IPVS | 2 | * ip_vs_proto_udp.c: UDP load balancing support for IPVS |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_proto_udp.c,v 1.3 2002/11/30 01:50:35 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * Julian Anastasov <ja@ssi.bg> | 5 | * Julian Anastasov <ja@ssi.bg> |
8 | * | 6 | * |
diff --git a/net/ipv4/ipvs/ip_vs_rr.c b/net/ipv4/ipvs/ip_vs_rr.c index 433f8a947924..c8db12d39e61 100644 --- a/net/ipv4/ipvs/ip_vs_rr.c +++ b/net/ipv4/ipvs/ip_vs_rr.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Round-Robin Scheduling module | 2 | * IPVS: Round-Robin Scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_rr.c,v 1.9 2002/09/15 08:14:08 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * Peter Kese <peter.kese@ijs.si> | 5 | * Peter Kese <peter.kese@ijs.si> |
8 | * | 6 | * |
diff --git a/net/ipv4/ipvs/ip_vs_sched.c b/net/ipv4/ipvs/ip_vs_sched.c index 121a32b1b756..b64767309855 100644 --- a/net/ipv4/ipvs/ip_vs_sched.c +++ b/net/ipv4/ipvs/ip_vs_sched.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * high-performance and highly available server based on a | 5 | * high-performance and highly available server based on a |
6 | * cluster of servers. | 6 | * cluster of servers. |
7 | * | 7 | * |
8 | * Version: $Id: ip_vs_sched.c,v 1.13 2003/05/10 03:05:23 wensong Exp $ | ||
9 | * | ||
10 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 8 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
11 | * Peter Kese <peter.kese@ijs.si> | 9 | * Peter Kese <peter.kese@ijs.si> |
12 | * | 10 | * |
diff --git a/net/ipv4/ipvs/ip_vs_sed.c b/net/ipv4/ipvs/ip_vs_sed.c index dd7c128f9db3..2a7d31358181 100644 --- a/net/ipv4/ipvs/ip_vs_sed.c +++ b/net/ipv4/ipvs/ip_vs_sed.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Shortest Expected Delay scheduling module | 2 | * IPVS: Shortest Expected Delay scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_sed.c,v 1.1 2003/05/10 03:06:08 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_sh.c b/net/ipv4/ipvs/ip_vs_sh.c index 1b25b00ef1e1..b8fdfac65001 100644 --- a/net/ipv4/ipvs/ip_vs_sh.c +++ b/net/ipv4/ipvs/ip_vs_sh.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Source Hashing scheduling module | 2 | * IPVS: Source Hashing scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_sh.c,v 1.5 2002/09/15 08:14:08 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@gnuchina.org> | 4 | * Authors: Wensong Zhang <wensong@gnuchina.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index eff54efe0351..2d4a86f73325 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * high-performance and highly available server based on a | 5 | * high-performance and highly available server based on a |
6 | * cluster of servers. | 6 | * cluster of servers. |
7 | * | 7 | * |
8 | * Version: $Id: ip_vs_sync.c,v 1.13 2003/06/08 09:31:19 wensong Exp $ | ||
9 | * | ||
10 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 8 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
11 | * | 9 | * |
12 | * ip_vs_sync: sync connection info from master load balancer to backups | 10 | * ip_vs_sync: sync connection info from master load balancer to backups |
diff --git a/net/ipv4/ipvs/ip_vs_wlc.c b/net/ipv4/ipvs/ip_vs_wlc.c index 8a9d913261d8..772c3cb4eca1 100644 --- a/net/ipv4/ipvs/ip_vs_wlc.c +++ b/net/ipv4/ipvs/ip_vs_wlc.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Weighted Least-Connection Scheduling module | 2 | * IPVS: Weighted Least-Connection Scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_wlc.c,v 1.13 2003/04/18 09:03:16 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * Peter Kese <peter.kese@ijs.si> | 5 | * Peter Kese <peter.kese@ijs.si> |
8 | * | 6 | * |
diff --git a/net/ipv4/ipvs/ip_vs_wrr.c b/net/ipv4/ipvs/ip_vs_wrr.c index 85c680add6df..1d6932d7dc97 100644 --- a/net/ipv4/ipvs/ip_vs_wrr.c +++ b/net/ipv4/ipvs/ip_vs_wrr.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * IPVS: Weighted Round-Robin Scheduling module | 2 | * IPVS: Weighted Round-Robin Scheduling module |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_wrr.c,v 1.12 2002/09/15 08:14:08 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index f63006caea03..9892d4aca42e 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ip_vs_xmit.c: various packet transmitters for IPVS | 2 | * ip_vs_xmit.c: various packet transmitters for IPVS |
3 | * | 3 | * |
4 | * Version: $Id: ip_vs_xmit.c,v 1.2 2002/11/30 01:50:35 wensong Exp $ | ||
5 | * | ||
6 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> | 4 | * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> |
7 | * Julian Anastasov <ja@ssi.bg> | 5 | * Julian Anastasov <ja@ssi.bg> |
8 | * | 6 | * |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 2767841a8cef..6e251402506e 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -365,6 +365,18 @@ config IP_NF_RAW | |||
365 | If you want to compile it as a module, say M here and read | 365 | If you want to compile it as a module, say M here and read |
366 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 366 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
367 | 367 | ||
368 | # security table for MAC policy | ||
369 | config IP_NF_SECURITY | ||
370 | tristate "Security table" | ||
371 | depends on IP_NF_IPTABLES | ||
372 | depends on SECURITY | ||
373 | default m if NETFILTER_ADVANCED=n | ||
374 | help | ||
375 | This option adds a `security' table to iptables, for use | ||
376 | with Mandatory Access Control (MAC) policy. | ||
377 | |||
378 | If unsure, say N. | ||
379 | |||
368 | # ARP tables | 380 | # ARP tables |
369 | config IP_NF_ARPTABLES | 381 | config IP_NF_ARPTABLES |
370 | tristate "ARP tables support" | 382 | tristate "ARP tables support" |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index d9b92fbf5579..3f31291f37ce 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -42,6 +42,7 @@ obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o | |||
42 | obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o | 42 | obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o |
43 | obj-$(CONFIG_NF_NAT) += iptable_nat.o | 43 | obj-$(CONFIG_NF_NAT) += iptable_nat.o |
44 | obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o | 44 | obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o |
45 | obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o | ||
45 | 46 | ||
46 | # matches | 47 | # matches |
47 | obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o | 48 | obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 26a37cedcf2e..aa33a4a7a715 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -156,7 +156,6 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
156 | case IPQ_COPY_META: | 156 | case IPQ_COPY_META: |
157 | case IPQ_COPY_NONE: | 157 | case IPQ_COPY_NONE: |
158 | size = NLMSG_SPACE(sizeof(*pmsg)); | 158 | size = NLMSG_SPACE(sizeof(*pmsg)); |
159 | data_len = 0; | ||
160 | break; | 159 | break; |
161 | 160 | ||
162 | case IPQ_COPY_PACKET: | 161 | case IPQ_COPY_PACKET: |
@@ -224,8 +223,6 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
224 | return skb; | 223 | return skb; |
225 | 224 | ||
226 | nlmsg_failure: | 225 | nlmsg_failure: |
227 | if (skb) | ||
228 | kfree_skb(skb); | ||
229 | *errp = -EINVAL; | 226 | *errp = -EINVAL; |
230 | printk(KERN_ERR "ip_queue: error creating packet message\n"); | 227 | printk(KERN_ERR "ip_queue: error creating packet message\n"); |
231 | return NULL; | 228 | return NULL; |
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c new file mode 100644 index 000000000000..2b472ac2263a --- /dev/null +++ b/net/ipv4/netfilter/iptable_security.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * "security" table | ||
3 | * | ||
4 | * This is for use by Mandatory Access Control (MAC) security models, | ||
5 | * which need to be able to manage security policy in separate context | ||
6 | * to DAC. | ||
7 | * | ||
8 | * Based on iptable_mangle.c | ||
9 | * | ||
10 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | ||
11 | * Copyright (C) 2000-2004 Netfilter Core Team <coreteam <at> netfilter.org> | ||
12 | * Copyright (C) 2008 Red Hat, Inc., James Morris <jmorris <at> redhat.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
20 | #include <net/ip.h> | ||
21 | |||
22 | MODULE_LICENSE("GPL"); | ||
23 | MODULE_AUTHOR("James Morris <jmorris <at> redhat.com>"); | ||
24 | MODULE_DESCRIPTION("iptables security table, for MAC rules"); | ||
25 | |||
26 | #define SECURITY_VALID_HOOKS (1 << NF_INET_LOCAL_IN) | \ | ||
27 | (1 << NF_INET_FORWARD) | \ | ||
28 | (1 << NF_INET_LOCAL_OUT) | ||
29 | |||
30 | static struct | ||
31 | { | ||
32 | struct ipt_replace repl; | ||
33 | struct ipt_standard entries[3]; | ||
34 | struct ipt_error term; | ||
35 | } initial_table __initdata = { | ||
36 | .repl = { | ||
37 | .name = "security", | ||
38 | .valid_hooks = SECURITY_VALID_HOOKS, | ||
39 | .num_entries = 4, | ||
40 | .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), | ||
41 | .hook_entry = { | ||
42 | [NF_INET_LOCAL_IN] = 0, | ||
43 | [NF_INET_FORWARD] = sizeof(struct ipt_standard), | ||
44 | [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, | ||
45 | }, | ||
46 | .underflow = { | ||
47 | [NF_INET_LOCAL_IN] = 0, | ||
48 | [NF_INET_FORWARD] = sizeof(struct ipt_standard), | ||
49 | [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, | ||
50 | }, | ||
51 | }, | ||
52 | .entries = { | ||
53 | IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ | ||
54 | IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ | ||
55 | IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ | ||
56 | }, | ||
57 | .term = IPT_ERROR_INIT, /* ERROR */ | ||
58 | }; | ||
59 | |||
60 | static struct xt_table security_table = { | ||
61 | .name = "security", | ||
62 | .valid_hooks = SECURITY_VALID_HOOKS, | ||
63 | .lock = __RW_LOCK_UNLOCKED(security_table.lock), | ||
64 | .me = THIS_MODULE, | ||
65 | .af = AF_INET, | ||
66 | }; | ||
67 | |||
68 | static unsigned int | ||
69 | ipt_local_in_hook(unsigned int hook, | ||
70 | struct sk_buff *skb, | ||
71 | const struct net_device *in, | ||
72 | const struct net_device *out, | ||
73 | int (*okfn)(struct sk_buff *)) | ||
74 | { | ||
75 | return ipt_do_table(skb, hook, in, out, | ||
76 | nf_local_in_net(in, out)->ipv4.iptable_security); | ||
77 | } | ||
78 | |||
79 | static unsigned int | ||
80 | ipt_forward_hook(unsigned int hook, | ||
81 | struct sk_buff *skb, | ||
82 | const struct net_device *in, | ||
83 | const struct net_device *out, | ||
84 | int (*okfn)(struct sk_buff *)) | ||
85 | { | ||
86 | return ipt_do_table(skb, hook, in, out, | ||
87 | nf_forward_net(in, out)->ipv4.iptable_security); | ||
88 | } | ||
89 | |||
90 | static unsigned int | ||
91 | ipt_local_out_hook(unsigned int hook, | ||
92 | struct sk_buff *skb, | ||
93 | const struct net_device *in, | ||
94 | const struct net_device *out, | ||
95 | int (*okfn)(struct sk_buff *)) | ||
96 | { | ||
97 | /* Somebody is playing with raw sockets. */ | ||
98 | if (skb->len < sizeof(struct iphdr) | ||
99 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { | ||
100 | if (net_ratelimit()) | ||
101 | printk(KERN_INFO "iptable_security: ignoring short " | ||
102 | "SOCK_RAW packet.\n"); | ||
103 | return NF_ACCEPT; | ||
104 | } | ||
105 | return ipt_do_table(skb, hook, in, out, | ||
106 | nf_local_out_net(in, out)->ipv4.iptable_security); | ||
107 | } | ||
108 | |||
109 | static struct nf_hook_ops ipt_ops[] __read_mostly = { | ||
110 | { | ||
111 | .hook = ipt_local_in_hook, | ||
112 | .owner = THIS_MODULE, | ||
113 | .pf = PF_INET, | ||
114 | .hooknum = NF_INET_LOCAL_IN, | ||
115 | .priority = NF_IP_PRI_SECURITY, | ||
116 | }, | ||
117 | { | ||
118 | .hook = ipt_forward_hook, | ||
119 | .owner = THIS_MODULE, | ||
120 | .pf = PF_INET, | ||
121 | .hooknum = NF_INET_FORWARD, | ||
122 | .priority = NF_IP_PRI_SECURITY, | ||
123 | }, | ||
124 | { | ||
125 | .hook = ipt_local_out_hook, | ||
126 | .owner = THIS_MODULE, | ||
127 | .pf = PF_INET, | ||
128 | .hooknum = NF_INET_LOCAL_OUT, | ||
129 | .priority = NF_IP_PRI_SECURITY, | ||
130 | }, | ||
131 | }; | ||
132 | |||
133 | static int __net_init iptable_security_net_init(struct net *net) | ||
134 | { | ||
135 | net->ipv4.iptable_security = | ||
136 | ipt_register_table(net, &security_table, &initial_table.repl); | ||
137 | |||
138 | if (IS_ERR(net->ipv4.iptable_security)) | ||
139 | return PTR_ERR(net->ipv4.iptable_security); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static void __net_exit iptable_security_net_exit(struct net *net) | ||
145 | { | ||
146 | ipt_unregister_table(net->ipv4.iptable_security); | ||
147 | } | ||
148 | |||
149 | static struct pernet_operations iptable_security_net_ops = { | ||
150 | .init = iptable_security_net_init, | ||
151 | .exit = iptable_security_net_exit, | ||
152 | }; | ||
153 | |||
154 | static int __init iptable_security_init(void) | ||
155 | { | ||
156 | int ret; | ||
157 | |||
158 | ret = register_pernet_subsys(&iptable_security_net_ops); | ||
159 | if (ret < 0) | ||
160 | return ret; | ||
161 | |||
162 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | ||
163 | if (ret < 0) | ||
164 | goto cleanup_table; | ||
165 | |||
166 | return ret; | ||
167 | |||
168 | cleanup_table: | ||
169 | unregister_pernet_subsys(&iptable_security_net_ops); | ||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static void __exit iptable_security_fini(void) | ||
174 | { | ||
175 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | ||
176 | unregister_pernet_subsys(&iptable_security_net_ops); | ||
177 | } | ||
178 | |||
179 | module_init(iptable_security_init); | ||
180 | module_exit(iptable_security_fini); | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 78ab19accace..97791048fa9b 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -87,9 +87,8 @@ static int icmp_packet(struct nf_conn *ct, | |||
87 | means this will only run once even if count hits zero twice | 87 | means this will only run once even if count hits zero twice |
88 | (theoretically possible with SMP) */ | 88 | (theoretically possible with SMP) */ |
89 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { | 89 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { |
90 | if (atomic_dec_and_test(&ct->proto.icmp.count) | 90 | if (atomic_dec_and_test(&ct->proto.icmp.count)) |
91 | && del_timer(&ct->timeout)) | 91 | nf_ct_kill_acct(ct, ctinfo, skb); |
92 | ct->timeout.function((unsigned long)ct); | ||
93 | } else { | 92 | } else { |
94 | atomic_inc(&ct->proto.icmp.count); | 93 | atomic_inc(&ct->proto.icmp.count); |
95 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); | 94 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 552169b41b16..eb5cee279c5f 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * PROC file system. It is mainly used for debugging and | 7 | * PROC file system. It is mainly used for debugging and |
8 | * statistics. | 8 | * statistics. |
9 | * | 9 | * |
10 | * Version: $Id: proc.c,v 1.45 2001/05/16 16:45:35 davem Exp $ | ||
11 | * | ||
12 | * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 10 | * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
13 | * Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de> | 11 | * Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de> |
14 | * Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de> | 12 | * Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de> |
diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c index 971ab9356e51..ea50da0649fd 100644 --- a/net/ipv4/protocol.c +++ b/net/ipv4/protocol.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * INET protocol dispatch tables. | 6 | * INET protocol dispatch tables. |
7 | * | 7 | * |
8 | * Version: $Id: protocol.c,v 1.14 2001/05/18 02:25:49 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * | 10 | * |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e7e091d365ff..1d0c97c8712d 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * RAW - implementation of IP "raw" sockets. | 6 | * RAW - implementation of IP "raw" sockets. |
7 | * | 7 | * |
8 | * Version: $Id: raw.c,v 1.64 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * | 10 | * |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 96be336064fb..fe3a02237286 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * ROUTE - implementation of the IP router. | 6 | * ROUTE - implementation of the IP router. |
7 | * | 7 | * |
8 | * Version: $Id: route.c,v 1.103 2002/01/12 07:44:09 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Alan Cox, <gw4pts@gw4pts.ampr.org> | 10 | * Alan Cox, <gw4pts@gw4pts.ampr.org> |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index d182a2a26291..fdde2ae07e24 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -8,8 +8,6 @@ | |||
8 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
9 | * as published by the Free Software Foundation; either version | 9 | * as published by the Free Software Foundation; either version |
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | ||
12 | * $Id: syncookies.c,v 1.18 2002/02/01 22:01:04 davem Exp $ | ||
13 | */ | 11 | */ |
14 | 12 | ||
15 | #include <linux/tcp.h> | 13 | #include <linux/tcp.h> |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index c437f804ee38..901607003205 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem. | 2 | * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem. |
3 | * | 3 | * |
4 | * $Id: sysctl_net_ipv4.c,v 1.50 2001/10/20 00:00:11 davem Exp $ | ||
5 | * | ||
6 | * Begun April 1, 1996, Mike Shaver. | 4 | * Begun April 1, 1996, Mike Shaver. |
7 | * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS] | 5 | * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS] |
8 | */ | 6 | */ |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fc54a48fde1e..cf0850c068f5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Implementation of the Transmission Control Protocol(TCP). | 6 | * Implementation of the Transmission Control Protocol(TCP). |
7 | * | 7 | * |
8 | * Version: $Id: tcp.c,v 1.216 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Mark Evans, <evansmp@uhura.aston.ac.uk> | 10 | * Mark Evans, <evansmp@uhura.aston.ac.uk> |
@@ -2463,6 +2461,76 @@ static unsigned long tcp_md5sig_users; | |||
2463 | static struct tcp_md5sig_pool **tcp_md5sig_pool; | 2461 | static struct tcp_md5sig_pool **tcp_md5sig_pool; |
2464 | static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); | 2462 | static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); |
2465 | 2463 | ||
2464 | int tcp_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | ||
2465 | int bplen, | ||
2466 | struct tcphdr *th, unsigned int tcplen, | ||
2467 | struct tcp_md5sig_pool *hp) | ||
2468 | { | ||
2469 | struct scatterlist sg[4]; | ||
2470 | __u16 data_len; | ||
2471 | int block = 0; | ||
2472 | __sum16 cksum; | ||
2473 | struct hash_desc *desc = &hp->md5_desc; | ||
2474 | int err; | ||
2475 | unsigned int nbytes = 0; | ||
2476 | |||
2477 | sg_init_table(sg, 4); | ||
2478 | |||
2479 | /* 1. The TCP pseudo-header */ | ||
2480 | sg_set_buf(&sg[block++], &hp->md5_blk, bplen); | ||
2481 | nbytes += bplen; | ||
2482 | |||
2483 | /* 2. The TCP header, excluding options, and assuming a | ||
2484 | * checksum of zero | ||
2485 | */ | ||
2486 | cksum = th->check; | ||
2487 | th->check = 0; | ||
2488 | sg_set_buf(&sg[block++], th, sizeof(*th)); | ||
2489 | nbytes += sizeof(*th); | ||
2490 | |||
2491 | /* 3. The TCP segment data (if any) */ | ||
2492 | data_len = tcplen - (th->doff << 2); | ||
2493 | if (data_len > 0) { | ||
2494 | u8 *data = (u8 *)th + (th->doff << 2); | ||
2495 | sg_set_buf(&sg[block++], data, data_len); | ||
2496 | nbytes += data_len; | ||
2497 | } | ||
2498 | |||
2499 | /* 4. an independently-specified key or password, known to both | ||
2500 | * TCPs and presumably connection-specific | ||
2501 | */ | ||
2502 | sg_set_buf(&sg[block++], key->key, key->keylen); | ||
2503 | nbytes += key->keylen; | ||
2504 | |||
2505 | sg_mark_end(&sg[block - 1]); | ||
2506 | |||
2507 | /* Now store the hash into the packet */ | ||
2508 | err = crypto_hash_init(desc); | ||
2509 | if (err) { | ||
2510 | if (net_ratelimit()) | ||
2511 | printk(KERN_WARNING "%s(): hash_init failed\n", __func__); | ||
2512 | return -1; | ||
2513 | } | ||
2514 | err = crypto_hash_update(desc, sg, nbytes); | ||
2515 | if (err) { | ||
2516 | if (net_ratelimit()) | ||
2517 | printk(KERN_WARNING "%s(): hash_update failed\n", __func__); | ||
2518 | return -1; | ||
2519 | } | ||
2520 | err = crypto_hash_final(desc, md5_hash); | ||
2521 | if (err) { | ||
2522 | if (net_ratelimit()) | ||
2523 | printk(KERN_WARNING "%s(): hash_final failed\n", __func__); | ||
2524 | return -1; | ||
2525 | } | ||
2526 | |||
2527 | /* Reset header */ | ||
2528 | th->check = cksum; | ||
2529 | |||
2530 | return 0; | ||
2531 | } | ||
2532 | EXPORT_SYMBOL(tcp_calc_md5_hash); | ||
2533 | |||
2466 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) | 2534 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) |
2467 | { | 2535 | { |
2468 | int cpu; | 2536 | int cpu; |
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index 2fbcc7d1b1a0..838d491dfda7 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * tcp_diag.c Module for monitoring TCP transport protocols sockets. | 2 | * tcp_diag.c Module for monitoring TCP transport protocols sockets. |
3 | * | 3 | * |
4 | * Version: $Id: tcp_diag.c,v 1.3 2002/02/01 22:01:04 davem Exp $ | ||
5 | * | ||
6 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 4 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index cad73b7dfef0..de30e70ff256 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Implementation of the Transmission Control Protocol(TCP). | 6 | * Implementation of the Transmission Control Protocol(TCP). |
7 | * | 7 | * |
8 | * Version: $Id: tcp_input.c,v 1.243 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Mark Evans, <evansmp@uhura.aston.ac.uk> | 10 | * Mark Evans, <evansmp@uhura.aston.ac.uk> |
@@ -3450,6 +3448,43 @@ static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, | |||
3450 | return 1; | 3448 | return 1; |
3451 | } | 3449 | } |
3452 | 3450 | ||
3451 | #ifdef CONFIG_TCP_MD5SIG | ||
3452 | /* | ||
3453 | * Parse MD5 Signature option | ||
3454 | */ | ||
3455 | u8 *tcp_parse_md5sig_option(struct tcphdr *th) | ||
3456 | { | ||
3457 | int length = (th->doff << 2) - sizeof (*th); | ||
3458 | u8 *ptr = (u8*)(th + 1); | ||
3459 | |||
3460 | /* If the TCP option is too short, we can short cut */ | ||
3461 | if (length < TCPOLEN_MD5SIG) | ||
3462 | return NULL; | ||
3463 | |||
3464 | while (length > 0) { | ||
3465 | int opcode = *ptr++; | ||
3466 | int opsize; | ||
3467 | |||
3468 | switch(opcode) { | ||
3469 | case TCPOPT_EOL: | ||
3470 | return NULL; | ||
3471 | case TCPOPT_NOP: | ||
3472 | length--; | ||
3473 | continue; | ||
3474 | default: | ||
3475 | opsize = *ptr++; | ||
3476 | if (opsize < 2 || opsize > length) | ||
3477 | return NULL; | ||
3478 | if (opcode == TCPOPT_MD5SIG) | ||
3479 | return ptr; | ||
3480 | } | ||
3481 | ptr += opsize - 2; | ||
3482 | length -= opsize; | ||
3483 | } | ||
3484 | return NULL; | ||
3485 | } | ||
3486 | #endif | ||
3487 | |||
3453 | static inline void tcp_store_ts_recent(struct tcp_sock *tp) | 3488 | static inline void tcp_store_ts_recent(struct tcp_sock *tp) |
3454 | { | 3489 | { |
3455 | tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; | 3490 | tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; |
@@ -5422,6 +5457,9 @@ EXPORT_SYMBOL(sysctl_tcp_ecn); | |||
5422 | EXPORT_SYMBOL(sysctl_tcp_reordering); | 5457 | EXPORT_SYMBOL(sysctl_tcp_reordering); |
5423 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); | 5458 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); |
5424 | EXPORT_SYMBOL(tcp_parse_options); | 5459 | EXPORT_SYMBOL(tcp_parse_options); |
5460 | #ifdef CONFIG_TCP_MD5SIG | ||
5461 | EXPORT_SYMBOL(tcp_parse_md5sig_option); | ||
5462 | #endif | ||
5425 | EXPORT_SYMBOL(tcp_rcv_established); | 5463 | EXPORT_SYMBOL(tcp_rcv_established); |
5426 | EXPORT_SYMBOL(tcp_rcv_state_process); | 5464 | EXPORT_SYMBOL(tcp_rcv_state_process); |
5427 | EXPORT_SYMBOL(tcp_initialize_rcv_mss); | 5465 | EXPORT_SYMBOL(tcp_initialize_rcv_mss); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 97a230026e13..b219a7a7cd08 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Implementation of the Transmission Control Protocol(TCP). | 6 | * Implementation of the Transmission Control Protocol(TCP). |
7 | * | 7 | * |
8 | * Version: $Id: tcp_ipv4.c,v 1.240 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * IPv4 specific functions | 8 | * IPv4 specific functions |
11 | * | 9 | * |
12 | * | 10 | * |
@@ -95,8 +93,13 @@ static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, | |||
95 | __be32 addr); | 93 | __be32 addr); |
96 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 94 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, |
97 | __be32 saddr, __be32 daddr, | 95 | __be32 saddr, __be32 daddr, |
98 | struct tcphdr *th, int protocol, | 96 | struct tcphdr *th, unsigned int tcplen); |
99 | unsigned int tcplen); | 97 | #else |
98 | static inline | ||
99 | struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) | ||
100 | { | ||
101 | return NULL; | ||
102 | } | ||
100 | #endif | 103 | #endif |
101 | 104 | ||
102 | struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { | 105 | struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { |
@@ -586,8 +589,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
586 | key, | 589 | key, |
587 | ip_hdr(skb)->daddr, | 590 | ip_hdr(skb)->daddr, |
588 | ip_hdr(skb)->saddr, | 591 | ip_hdr(skb)->saddr, |
589 | &rep.th, IPPROTO_TCP, | 592 | &rep.th, arg.iov[0].iov_len); |
590 | arg.iov[0].iov_len); | ||
591 | } | 593 | } |
592 | #endif | 594 | #endif |
593 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, | 595 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, |
@@ -606,9 +608,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
606 | outside socket context is ugly, certainly. What can I do? | 608 | outside socket context is ugly, certainly. What can I do? |
607 | */ | 609 | */ |
608 | 610 | ||
609 | static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | 611 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
610 | struct sk_buff *skb, u32 seq, u32 ack, | 612 | u32 win, u32 ts, int oif, |
611 | u32 win, u32 ts) | 613 | struct tcp_md5sig_key *key) |
612 | { | 614 | { |
613 | struct tcphdr *th = tcp_hdr(skb); | 615 | struct tcphdr *th = tcp_hdr(skb); |
614 | struct { | 616 | struct { |
@@ -620,10 +622,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
620 | ]; | 622 | ]; |
621 | } rep; | 623 | } rep; |
622 | struct ip_reply_arg arg; | 624 | struct ip_reply_arg arg; |
623 | #ifdef CONFIG_TCP_MD5SIG | ||
624 | struct tcp_md5sig_key *key; | ||
625 | struct tcp_md5sig_key tw_key; | ||
626 | #endif | ||
627 | 625 | ||
628 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 626 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
629 | memset(&arg, 0, sizeof(arg)); | 627 | memset(&arg, 0, sizeof(arg)); |
@@ -649,23 +647,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
649 | rep.th.window = htons(win); | 647 | rep.th.window = htons(win); |
650 | 648 | ||
651 | #ifdef CONFIG_TCP_MD5SIG | 649 | #ifdef CONFIG_TCP_MD5SIG |
652 | /* | ||
653 | * The SKB holds an imcoming packet, but may not have a valid ->sk | ||
654 | * pointer. This is especially the case when we're dealing with a | ||
655 | * TIME_WAIT ack, because the sk structure is long gone, and only | ||
656 | * the tcp_timewait_sock remains. So the md5 key is stashed in that | ||
657 | * structure, and we use it in preference. I believe that (twsk || | ||
658 | * skb->sk) holds true, but we program defensively. | ||
659 | */ | ||
660 | if (!twsk && skb->sk) { | ||
661 | key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr); | ||
662 | } else if (twsk && twsk->tw_md5_keylen) { | ||
663 | tw_key.key = twsk->tw_md5_key; | ||
664 | tw_key.keylen = twsk->tw_md5_keylen; | ||
665 | key = &tw_key; | ||
666 | } else | ||
667 | key = NULL; | ||
668 | |||
669 | if (key) { | 650 | if (key) { |
670 | int offset = (ts) ? 3 : 0; | 651 | int offset = (ts) ? 3 : 0; |
671 | 652 | ||
@@ -680,16 +661,15 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
680 | key, | 661 | key, |
681 | ip_hdr(skb)->daddr, | 662 | ip_hdr(skb)->daddr, |
682 | ip_hdr(skb)->saddr, | 663 | ip_hdr(skb)->saddr, |
683 | &rep.th, IPPROTO_TCP, | 664 | &rep.th, arg.iov[0].iov_len); |
684 | arg.iov[0].iov_len); | ||
685 | } | 665 | } |
686 | #endif | 666 | #endif |
687 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, | 667 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, |
688 | ip_hdr(skb)->saddr, /* XXX */ | 668 | ip_hdr(skb)->saddr, /* XXX */ |
689 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 669 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
690 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 670 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
691 | if (twsk) | 671 | if (oif) |
692 | arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if; | 672 | arg.bound_dev_if = oif; |
693 | 673 | ||
694 | ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb, | 674 | ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb, |
695 | &arg, arg.iov[0].iov_len); | 675 | &arg, arg.iov[0].iov_len); |
@@ -702,9 +682,12 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
702 | struct inet_timewait_sock *tw = inet_twsk(sk); | 682 | struct inet_timewait_sock *tw = inet_twsk(sk); |
703 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 683 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
704 | 684 | ||
705 | tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 685 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
706 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 686 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
707 | tcptw->tw_ts_recent); | 687 | tcptw->tw_ts_recent, |
688 | tw->tw_bound_dev_if, | ||
689 | tcp_twsk_md5_key(tcptw) | ||
690 | ); | ||
708 | 691 | ||
709 | inet_twsk_put(tw); | 692 | inet_twsk_put(tw); |
710 | } | 693 | } |
@@ -712,9 +695,11 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
712 | static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, | 695 | static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, |
713 | struct request_sock *req) | 696 | struct request_sock *req) |
714 | { | 697 | { |
715 | tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, | 698 | tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, |
716 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 699 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
717 | req->ts_recent); | 700 | req->ts_recent, |
701 | 0, | ||
702 | tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr)); | ||
718 | } | 703 | } |
719 | 704 | ||
720 | /* | 705 | /* |
@@ -1006,18 +991,12 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1006 | 991 | ||
1007 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 992 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, |
1008 | __be32 saddr, __be32 daddr, | 993 | __be32 saddr, __be32 daddr, |
1009 | struct tcphdr *th, int protocol, | 994 | struct tcphdr *th, |
1010 | unsigned int tcplen) | 995 | unsigned int tcplen) |
1011 | { | 996 | { |
1012 | struct scatterlist sg[4]; | ||
1013 | __u16 data_len; | ||
1014 | int block = 0; | ||
1015 | __sum16 old_checksum; | ||
1016 | struct tcp_md5sig_pool *hp; | 997 | struct tcp_md5sig_pool *hp; |
1017 | struct tcp4_pseudohdr *bp; | 998 | struct tcp4_pseudohdr *bp; |
1018 | struct hash_desc *desc; | ||
1019 | int err; | 999 | int err; |
1020 | unsigned int nbytes = 0; | ||
1021 | 1000 | ||
1022 | /* | 1001 | /* |
1023 | * Okay, so RFC2385 is turned on for this connection, | 1002 | * Okay, so RFC2385 is turned on for this connection, |
@@ -1029,63 +1008,25 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
1029 | goto clear_hash_noput; | 1008 | goto clear_hash_noput; |
1030 | 1009 | ||
1031 | bp = &hp->md5_blk.ip4; | 1010 | bp = &hp->md5_blk.ip4; |
1032 | desc = &hp->md5_desc; | ||
1033 | 1011 | ||
1034 | /* | 1012 | /* |
1035 | * 1. the TCP pseudo-header (in the order: source IP address, | 1013 | * The TCP pseudo-header (in the order: source IP address, |
1036 | * destination IP address, zero-padded protocol number, and | 1014 | * destination IP address, zero-padded protocol number, and |
1037 | * segment length) | 1015 | * segment length) |
1038 | */ | 1016 | */ |
1039 | bp->saddr = saddr; | 1017 | bp->saddr = saddr; |
1040 | bp->daddr = daddr; | 1018 | bp->daddr = daddr; |
1041 | bp->pad = 0; | 1019 | bp->pad = 0; |
1042 | bp->protocol = protocol; | 1020 | bp->protocol = IPPROTO_TCP; |
1043 | bp->len = htons(tcplen); | 1021 | bp->len = htons(tcplen); |
1044 | 1022 | ||
1045 | sg_init_table(sg, 4); | 1023 | err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp), |
1046 | 1024 | th, tcplen, hp); | |
1047 | sg_set_buf(&sg[block++], bp, sizeof(*bp)); | ||
1048 | nbytes += sizeof(*bp); | ||
1049 | |||
1050 | /* 2. the TCP header, excluding options, and assuming a | ||
1051 | * checksum of zero/ | ||
1052 | */ | ||
1053 | old_checksum = th->check; | ||
1054 | th->check = 0; | ||
1055 | sg_set_buf(&sg[block++], th, sizeof(struct tcphdr)); | ||
1056 | nbytes += sizeof(struct tcphdr); | ||
1057 | |||
1058 | /* 3. the TCP segment data (if any) */ | ||
1059 | data_len = tcplen - (th->doff << 2); | ||
1060 | if (data_len > 0) { | ||
1061 | unsigned char *data = (unsigned char *)th + (th->doff << 2); | ||
1062 | sg_set_buf(&sg[block++], data, data_len); | ||
1063 | nbytes += data_len; | ||
1064 | } | ||
1065 | |||
1066 | /* 4. an independently-specified key or password, known to both | ||
1067 | * TCPs and presumably connection-specific | ||
1068 | */ | ||
1069 | sg_set_buf(&sg[block++], key->key, key->keylen); | ||
1070 | nbytes += key->keylen; | ||
1071 | |||
1072 | sg_mark_end(&sg[block - 1]); | ||
1073 | |||
1074 | /* Now store the Hash into the packet */ | ||
1075 | err = crypto_hash_init(desc); | ||
1076 | if (err) | ||
1077 | goto clear_hash; | ||
1078 | err = crypto_hash_update(desc, sg, nbytes); | ||
1079 | if (err) | ||
1080 | goto clear_hash; | ||
1081 | err = crypto_hash_final(desc, md5_hash); | ||
1082 | if (err) | 1025 | if (err) |
1083 | goto clear_hash; | 1026 | goto clear_hash; |
1084 | 1027 | ||
1085 | /* Reset header, and free up the crypto */ | 1028 | /* Free up the crypto pool */ |
1086 | tcp_put_md5sig_pool(); | 1029 | tcp_put_md5sig_pool(); |
1087 | th->check = old_checksum; | ||
1088 | |||
1089 | out: | 1030 | out: |
1090 | return 0; | 1031 | return 0; |
1091 | clear_hash: | 1032 | clear_hash: |
@@ -1099,7 +1040,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
1099 | struct sock *sk, | 1040 | struct sock *sk, |
1100 | struct dst_entry *dst, | 1041 | struct dst_entry *dst, |
1101 | struct request_sock *req, | 1042 | struct request_sock *req, |
1102 | struct tcphdr *th, int protocol, | 1043 | struct tcphdr *th, |
1103 | unsigned int tcplen) | 1044 | unsigned int tcplen) |
1104 | { | 1045 | { |
1105 | __be32 saddr, daddr; | 1046 | __be32 saddr, daddr; |
@@ -1115,7 +1056,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
1115 | } | 1056 | } |
1116 | return tcp_v4_do_calc_md5_hash(md5_hash, key, | 1057 | return tcp_v4_do_calc_md5_hash(md5_hash, key, |
1117 | saddr, daddr, | 1058 | saddr, daddr, |
1118 | th, protocol, tcplen); | 1059 | th, tcplen); |
1119 | } | 1060 | } |
1120 | 1061 | ||
1121 | EXPORT_SYMBOL(tcp_v4_calc_md5_hash); | 1062 | EXPORT_SYMBOL(tcp_v4_calc_md5_hash); |
@@ -1134,52 +1075,12 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) | |||
1134 | struct tcp_md5sig_key *hash_expected; | 1075 | struct tcp_md5sig_key *hash_expected; |
1135 | const struct iphdr *iph = ip_hdr(skb); | 1076 | const struct iphdr *iph = ip_hdr(skb); |
1136 | struct tcphdr *th = tcp_hdr(skb); | 1077 | struct tcphdr *th = tcp_hdr(skb); |
1137 | int length = (th->doff << 2) - sizeof(struct tcphdr); | ||
1138 | int genhash; | 1078 | int genhash; |
1139 | unsigned char *ptr; | ||
1140 | unsigned char newhash[16]; | 1079 | unsigned char newhash[16]; |
1141 | 1080 | ||
1142 | hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); | 1081 | hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); |
1082 | hash_location = tcp_parse_md5sig_option(th); | ||
1143 | 1083 | ||
1144 | /* | ||
1145 | * If the TCP option length is less than the TCP_MD5SIG | ||
1146 | * option length, then we can shortcut | ||
1147 | */ | ||
1148 | if (length < TCPOLEN_MD5SIG) { | ||
1149 | if (hash_expected) | ||
1150 | return 1; | ||
1151 | else | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | /* Okay, we can't shortcut - we have to grub through the options */ | ||
1156 | ptr = (unsigned char *)(th + 1); | ||
1157 | while (length > 0) { | ||
1158 | int opcode = *ptr++; | ||
1159 | int opsize; | ||
1160 | |||
1161 | switch (opcode) { | ||
1162 | case TCPOPT_EOL: | ||
1163 | goto done_opts; | ||
1164 | case TCPOPT_NOP: | ||
1165 | length--; | ||
1166 | continue; | ||
1167 | default: | ||
1168 | opsize = *ptr++; | ||
1169 | if (opsize < 2) | ||
1170 | goto done_opts; | ||
1171 | if (opsize > length) | ||
1172 | goto done_opts; | ||
1173 | |||
1174 | if (opcode == TCPOPT_MD5SIG) { | ||
1175 | hash_location = ptr; | ||
1176 | goto done_opts; | ||
1177 | } | ||
1178 | } | ||
1179 | ptr += opsize-2; | ||
1180 | length -= opsize; | ||
1181 | } | ||
1182 | done_opts: | ||
1183 | /* We've parsed the options - do we have a hash? */ | 1084 | /* We've parsed the options - do we have a hash? */ |
1184 | if (!hash_expected && !hash_location) | 1085 | if (!hash_expected && !hash_location) |
1185 | return 0; | 1086 | return 0; |
@@ -1206,8 +1107,7 @@ done_opts: | |||
1206 | genhash = tcp_v4_do_calc_md5_hash(newhash, | 1107 | genhash = tcp_v4_do_calc_md5_hash(newhash, |
1207 | hash_expected, | 1108 | hash_expected, |
1208 | iph->saddr, iph->daddr, | 1109 | iph->saddr, iph->daddr, |
1209 | th, sk->sk_protocol, | 1110 | th, skb->len); |
1210 | skb->len); | ||
1211 | 1111 | ||
1212 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | 1112 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { |
1213 | if (net_ratelimit()) { | 1113 | if (net_ratelimit()) { |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 8245247a6ceb..ea68a478fad6 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Implementation of the Transmission Control Protocol(TCP). | 6 | * Implementation of the Transmission Control Protocol(TCP). |
7 | * | 7 | * |
8 | * Version: $Id: tcp_minisocks.c,v 1.15 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Mark Evans, <evansmp@uhura.aston.ac.uk> | 10 | * Mark Evans, <evansmp@uhura.aston.ac.uk> |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index ad993ecb4810..8f83ab432705 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Implementation of the Transmission Control Protocol(TCP). | 6 | * Implementation of the Transmission Control Protocol(TCP). |
7 | * | 7 | * |
8 | * Version: $Id: tcp_output.c,v 1.146 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Mark Evans, <evansmp@uhura.aston.ac.uk> | 10 | * Mark Evans, <evansmp@uhura.aston.ac.uk> |
@@ -607,7 +605,6 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
607 | md5, | 605 | md5, |
608 | sk, NULL, NULL, | 606 | sk, NULL, NULL, |
609 | tcp_hdr(skb), | 607 | tcp_hdr(skb), |
610 | sk->sk_protocol, | ||
611 | skb->len); | 608 | skb->len); |
612 | } | 609 | } |
613 | #endif | 610 | #endif |
@@ -2266,7 +2263,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2266 | tp->af_specific->calc_md5_hash(md5_hash_location, | 2263 | tp->af_specific->calc_md5_hash(md5_hash_location, |
2267 | md5, | 2264 | md5, |
2268 | NULL, dst, req, | 2265 | NULL, dst, req, |
2269 | tcp_hdr(skb), sk->sk_protocol, | 2266 | tcp_hdr(skb), |
2270 | skb->len); | 2267 | skb->len); |
2271 | } | 2268 | } |
2272 | #endif | 2269 | #endif |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 63ed9d6830e7..3e358cbb1247 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Implementation of the Transmission Control Protocol(TCP). | 6 | * Implementation of the Transmission Control Protocol(TCP). |
7 | * | 7 | * |
8 | * Version: $Id: tcp_timer.c,v 1.88 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Mark Evans, <evansmp@uhura.aston.ac.uk> | 10 | * Mark Evans, <evansmp@uhura.aston.ac.uk> |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 56fcda3694ba..355e6d62d483 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * The User Datagram Protocol (UDP). | 6 | * The User Datagram Protocol (UDP). |
7 | * | 7 | * |
8 | * Version: $Id: udp.c,v 1.102 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Arnt Gulbrandsen, <agulbra@nvg.unit.no> | 10 | * Arnt Gulbrandsen, <agulbra@nvg.unit.no> |
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 72ce26b6c4d3..4ad16b6d5138 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * UDPLITE An implementation of the UDP-Lite protocol (RFC 3828). | 2 | * UDPLITE An implementation of the UDP-Lite protocol (RFC 3828). |
3 | * | 3 | * |
4 | * Version: $Id: udplite.c,v 1.25 2006/10/19 07:22:36 gerrit Exp $ | ||
5 | * | ||
6 | * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk> | 4 | * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk> |
7 | * | 5 | * |
8 | * Changes: | 6 | * Changes: |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 147588f4c7c0..9be6be3a7ff3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -6,8 +6,6 @@ | |||
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
8 | * | 8 | * |
9 | * $Id: addrconf.c,v 1.69 2001/10/31 21:55:54 davem Exp $ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
13 | * as published by the Free Software Foundation; either version | 11 | * as published by the Free Software Foundation; either version |
@@ -231,6 +229,12 @@ static inline int addrconf_qdisc_ok(struct net_device *dev) | |||
231 | return (dev->qdisc != &noop_qdisc); | 229 | return (dev->qdisc != &noop_qdisc); |
232 | } | 230 | } |
233 | 231 | ||
232 | /* Check if a route is valid prefix route */ | ||
233 | static inline int addrconf_is_prefix_route(const struct rt6_info *rt) | ||
234 | { | ||
235 | return ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0); | ||
236 | } | ||
237 | |||
234 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | 238 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) |
235 | { | 239 | { |
236 | if (del_timer(&ifp->timer)) | 240 | if (del_timer(&ifp->timer)) |
@@ -777,7 +781,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
777 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); | 781 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); |
778 | rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); | 782 | rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); |
779 | 783 | ||
780 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 784 | if (rt && addrconf_is_prefix_route(rt)) { |
781 | if (onlink == 0) { | 785 | if (onlink == 0) { |
782 | ip6_del_rt(rt); | 786 | ip6_del_rt(rt); |
783 | rt = NULL; | 787 | rt = NULL; |
@@ -958,7 +962,8 @@ static inline int ipv6_saddr_preferred(int type) | |||
958 | return 0; | 962 | return 0; |
959 | } | 963 | } |
960 | 964 | ||
961 | static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, | 965 | static int ipv6_get_saddr_eval(struct net *net, |
966 | struct ipv6_saddr_score *score, | ||
962 | struct ipv6_saddr_dst *dst, | 967 | struct ipv6_saddr_dst *dst, |
963 | int i) | 968 | int i) |
964 | { | 969 | { |
@@ -1037,7 +1042,8 @@ static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, | |||
1037 | break; | 1042 | break; |
1038 | case IPV6_SADDR_RULE_LABEL: | 1043 | case IPV6_SADDR_RULE_LABEL: |
1039 | /* Rule 6: Prefer matching label */ | 1044 | /* Rule 6: Prefer matching label */ |
1040 | ret = ipv6_addr_label(&score->ifa->addr, score->addr_type, | 1045 | ret = ipv6_addr_label(net, |
1046 | &score->ifa->addr, score->addr_type, | ||
1041 | score->ifa->idev->dev->ifindex) == dst->label; | 1047 | score->ifa->idev->dev->ifindex) == dst->label; |
1042 | break; | 1048 | break; |
1043 | #ifdef CONFIG_IPV6_PRIVACY | 1049 | #ifdef CONFIG_IPV6_PRIVACY |
@@ -1091,7 +1097,7 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, | |||
1091 | dst.addr = daddr; | 1097 | dst.addr = daddr; |
1092 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; | 1098 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; |
1093 | dst.scope = __ipv6_addr_src_scope(dst_type); | 1099 | dst.scope = __ipv6_addr_src_scope(dst_type); |
1094 | dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); | 1100 | dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex); |
1095 | dst.prefs = prefs; | 1101 | dst.prefs = prefs; |
1096 | 1102 | ||
1097 | hiscore->rule = -1; | 1103 | hiscore->rule = -1; |
@@ -1159,8 +1165,8 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, | |||
1159 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { | 1165 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { |
1160 | int minihiscore, miniscore; | 1166 | int minihiscore, miniscore; |
1161 | 1167 | ||
1162 | minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i); | 1168 | minihiscore = ipv6_get_saddr_eval(net, hiscore, &dst, i); |
1163 | miniscore = ipv6_get_saddr_eval(score, &dst, i); | 1169 | miniscore = ipv6_get_saddr_eval(net, score, &dst, i); |
1164 | 1170 | ||
1165 | if (minihiscore > miniscore) { | 1171 | if (minihiscore > miniscore) { |
1166 | if (i == IPV6_SADDR_RULE_SCOPE && | 1172 | if (i == IPV6_SADDR_RULE_SCOPE && |
@@ -1788,7 +1794,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1788 | rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, | 1794 | rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, |
1789 | dev->ifindex, 1); | 1795 | dev->ifindex, 1); |
1790 | 1796 | ||
1791 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 1797 | if (rt && addrconf_is_prefix_route(rt)) { |
1792 | /* Autoconf prefix route */ | 1798 | /* Autoconf prefix route */ |
1793 | if (valid_lft == 0) { | 1799 | if (valid_lft == 0) { |
1794 | ip6_del_rt(rt); | 1800 | ip6_del_rt(rt); |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 9bfa8846f262..08909039d87b 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -29,6 +29,9 @@ | |||
29 | */ | 29 | */ |
30 | struct ip6addrlbl_entry | 30 | struct ip6addrlbl_entry |
31 | { | 31 | { |
32 | #ifdef CONFIG_NET_NS | ||
33 | struct net *lbl_net; | ||
34 | #endif | ||
32 | struct in6_addr prefix; | 35 | struct in6_addr prefix; |
33 | int prefixlen; | 36 | int prefixlen; |
34 | int ifindex; | 37 | int ifindex; |
@@ -46,6 +49,16 @@ static struct ip6addrlbl_table | |||
46 | u32 seq; | 49 | u32 seq; |
47 | } ip6addrlbl_table; | 50 | } ip6addrlbl_table; |
48 | 51 | ||
52 | static inline | ||
53 | struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl) | ||
54 | { | ||
55 | #ifdef CONFIG_NET_NS | ||
56 | return lbl->lbl_net; | ||
57 | #else | ||
58 | return &init_net; | ||
59 | #endif | ||
60 | } | ||
61 | |||
49 | /* | 62 | /* |
50 | * Default policy table (RFC3484 + extensions) | 63 | * Default policy table (RFC3484 + extensions) |
51 | * | 64 | * |
@@ -65,7 +78,7 @@ static struct ip6addrlbl_table | |||
65 | 78 | ||
66 | #define IPV6_ADDR_LABEL_DEFAULT 0xffffffffUL | 79 | #define IPV6_ADDR_LABEL_DEFAULT 0xffffffffUL |
67 | 80 | ||
68 | static const __initdata struct ip6addrlbl_init_table | 81 | static const __net_initdata struct ip6addrlbl_init_table |
69 | { | 82 | { |
70 | const struct in6_addr *prefix; | 83 | const struct in6_addr *prefix; |
71 | int prefixlen; | 84 | int prefixlen; |
@@ -108,6 +121,9 @@ static const __initdata struct ip6addrlbl_init_table | |||
108 | /* Object management */ | 121 | /* Object management */ |
109 | static inline void ip6addrlbl_free(struct ip6addrlbl_entry *p) | 122 | static inline void ip6addrlbl_free(struct ip6addrlbl_entry *p) |
110 | { | 123 | { |
124 | #ifdef CONFIG_NET_NS | ||
125 | release_net(p->lbl_net); | ||
126 | #endif | ||
111 | kfree(p); | 127 | kfree(p); |
112 | } | 128 | } |
113 | 129 | ||
@@ -128,10 +144,13 @@ static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p) | |||
128 | } | 144 | } |
129 | 145 | ||
130 | /* Find label */ | 146 | /* Find label */ |
131 | static int __ip6addrlbl_match(struct ip6addrlbl_entry *p, | 147 | static int __ip6addrlbl_match(struct net *net, |
148 | struct ip6addrlbl_entry *p, | ||
132 | const struct in6_addr *addr, | 149 | const struct in6_addr *addr, |
133 | int addrtype, int ifindex) | 150 | int addrtype, int ifindex) |
134 | { | 151 | { |
152 | if (!net_eq(ip6addrlbl_net(p), net)) | ||
153 | return 0; | ||
135 | if (p->ifindex && p->ifindex != ifindex) | 154 | if (p->ifindex && p->ifindex != ifindex) |
136 | return 0; | 155 | return 0; |
137 | if (p->addrtype && p->addrtype != addrtype) | 156 | if (p->addrtype && p->addrtype != addrtype) |
@@ -141,19 +160,21 @@ static int __ip6addrlbl_match(struct ip6addrlbl_entry *p, | |||
141 | return 1; | 160 | return 1; |
142 | } | 161 | } |
143 | 162 | ||
144 | static struct ip6addrlbl_entry *__ipv6_addr_label(const struct in6_addr *addr, | 163 | static struct ip6addrlbl_entry *__ipv6_addr_label(struct net *net, |
164 | const struct in6_addr *addr, | ||
145 | int type, int ifindex) | 165 | int type, int ifindex) |
146 | { | 166 | { |
147 | struct hlist_node *pos; | 167 | struct hlist_node *pos; |
148 | struct ip6addrlbl_entry *p; | 168 | struct ip6addrlbl_entry *p; |
149 | hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) { | 169 | hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) { |
150 | if (__ip6addrlbl_match(p, addr, type, ifindex)) | 170 | if (__ip6addrlbl_match(net, p, addr, type, ifindex)) |
151 | return p; | 171 | return p; |
152 | } | 172 | } |
153 | return NULL; | 173 | return NULL; |
154 | } | 174 | } |
155 | 175 | ||
156 | u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex) | 176 | u32 ipv6_addr_label(struct net *net, |
177 | const struct in6_addr *addr, int type, int ifindex) | ||
157 | { | 178 | { |
158 | u32 label; | 179 | u32 label; |
159 | struct ip6addrlbl_entry *p; | 180 | struct ip6addrlbl_entry *p; |
@@ -161,7 +182,7 @@ u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex) | |||
161 | type &= IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK; | 182 | type &= IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK; |
162 | 183 | ||
163 | rcu_read_lock(); | 184 | rcu_read_lock(); |
164 | p = __ipv6_addr_label(addr, type, ifindex); | 185 | p = __ipv6_addr_label(net, addr, type, ifindex); |
165 | label = p ? p->label : IPV6_ADDR_LABEL_DEFAULT; | 186 | label = p ? p->label : IPV6_ADDR_LABEL_DEFAULT; |
166 | rcu_read_unlock(); | 187 | rcu_read_unlock(); |
167 | 188 | ||
@@ -174,7 +195,8 @@ u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex) | |||
174 | } | 195 | } |
175 | 196 | ||
176 | /* allocate one entry */ | 197 | /* allocate one entry */ |
177 | static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix, | 198 | static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net, |
199 | const struct in6_addr *prefix, | ||
178 | int prefixlen, int ifindex, | 200 | int prefixlen, int ifindex, |
179 | u32 label) | 201 | u32 label) |
180 | { | 202 | { |
@@ -216,6 +238,9 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix, | |||
216 | newp->addrtype = addrtype; | 238 | newp->addrtype = addrtype; |
217 | newp->label = label; | 239 | newp->label = label; |
218 | INIT_HLIST_NODE(&newp->list); | 240 | INIT_HLIST_NODE(&newp->list); |
241 | #ifdef CONFIG_NET_NS | ||
242 | newp->lbl_net = hold_net(net); | ||
243 | #endif | ||
219 | atomic_set(&newp->refcnt, 1); | 244 | atomic_set(&newp->refcnt, 1); |
220 | return newp; | 245 | return newp; |
221 | } | 246 | } |
@@ -237,6 +262,7 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) | |||
237 | hlist_for_each_entry_safe(p, pos, n, | 262 | hlist_for_each_entry_safe(p, pos, n, |
238 | &ip6addrlbl_table.head, list) { | 263 | &ip6addrlbl_table.head, list) { |
239 | if (p->prefixlen == newp->prefixlen && | 264 | if (p->prefixlen == newp->prefixlen && |
265 | net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) && | ||
240 | p->ifindex == newp->ifindex && | 266 | p->ifindex == newp->ifindex && |
241 | ipv6_addr_equal(&p->prefix, &newp->prefix)) { | 267 | ipv6_addr_equal(&p->prefix, &newp->prefix)) { |
242 | if (!replace) { | 268 | if (!replace) { |
@@ -261,7 +287,8 @@ out: | |||
261 | } | 287 | } |
262 | 288 | ||
263 | /* add a label */ | 289 | /* add a label */ |
264 | static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen, | 290 | static int ip6addrlbl_add(struct net *net, |
291 | const struct in6_addr *prefix, int prefixlen, | ||
265 | int ifindex, u32 label, int replace) | 292 | int ifindex, u32 label, int replace) |
266 | { | 293 | { |
267 | struct ip6addrlbl_entry *newp; | 294 | struct ip6addrlbl_entry *newp; |
@@ -274,7 +301,7 @@ static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen, | |||
274 | (unsigned int)label, | 301 | (unsigned int)label, |
275 | replace); | 302 | replace); |
276 | 303 | ||
277 | newp = ip6addrlbl_alloc(prefix, prefixlen, ifindex, label); | 304 | newp = ip6addrlbl_alloc(net, prefix, prefixlen, ifindex, label); |
278 | if (IS_ERR(newp)) | 305 | if (IS_ERR(newp)) |
279 | return PTR_ERR(newp); | 306 | return PTR_ERR(newp); |
280 | spin_lock(&ip6addrlbl_table.lock); | 307 | spin_lock(&ip6addrlbl_table.lock); |
@@ -286,7 +313,8 @@ static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen, | |||
286 | } | 313 | } |
287 | 314 | ||
288 | /* remove a label */ | 315 | /* remove a label */ |
289 | static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | 316 | static int __ip6addrlbl_del(struct net *net, |
317 | const struct in6_addr *prefix, int prefixlen, | ||
290 | int ifindex) | 318 | int ifindex) |
291 | { | 319 | { |
292 | struct ip6addrlbl_entry *p = NULL; | 320 | struct ip6addrlbl_entry *p = NULL; |
@@ -300,6 +328,7 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
300 | 328 | ||
301 | hlist_for_each_entry_safe(p, pos, n, &ip6addrlbl_table.head, list) { | 329 | hlist_for_each_entry_safe(p, pos, n, &ip6addrlbl_table.head, list) { |
302 | if (p->prefixlen == prefixlen && | 330 | if (p->prefixlen == prefixlen && |
331 | net_eq(ip6addrlbl_net(p), net) && | ||
303 | p->ifindex == ifindex && | 332 | p->ifindex == ifindex && |
304 | ipv6_addr_equal(&p->prefix, prefix)) { | 333 | ipv6_addr_equal(&p->prefix, prefix)) { |
305 | hlist_del_rcu(&p->list); | 334 | hlist_del_rcu(&p->list); |
@@ -311,7 +340,8 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
311 | return ret; | 340 | return ret; |
312 | } | 341 | } |
313 | 342 | ||
314 | static int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | 343 | static int ip6addrlbl_del(struct net *net, |
344 | const struct in6_addr *prefix, int prefixlen, | ||
315 | int ifindex) | 345 | int ifindex) |
316 | { | 346 | { |
317 | struct in6_addr prefix_buf; | 347 | struct in6_addr prefix_buf; |
@@ -324,13 +354,13 @@ static int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
324 | 354 | ||
325 | ipv6_addr_prefix(&prefix_buf, prefix, prefixlen); | 355 | ipv6_addr_prefix(&prefix_buf, prefix, prefixlen); |
326 | spin_lock(&ip6addrlbl_table.lock); | 356 | spin_lock(&ip6addrlbl_table.lock); |
327 | ret = __ip6addrlbl_del(&prefix_buf, prefixlen, ifindex); | 357 | ret = __ip6addrlbl_del(net, &prefix_buf, prefixlen, ifindex); |
328 | spin_unlock(&ip6addrlbl_table.lock); | 358 | spin_unlock(&ip6addrlbl_table.lock); |
329 | return ret; | 359 | return ret; |
330 | } | 360 | } |
331 | 361 | ||
332 | /* add default label */ | 362 | /* add default label */ |
333 | static __init int ip6addrlbl_init(void) | 363 | static int __net_init ip6addrlbl_net_init(struct net *net) |
334 | { | 364 | { |
335 | int err = 0; | 365 | int err = 0; |
336 | int i; | 366 | int i; |
@@ -338,7 +368,8 @@ static __init int ip6addrlbl_init(void) | |||
338 | ADDRLABEL(KERN_DEBUG "%s()\n", __func__); | 368 | ADDRLABEL(KERN_DEBUG "%s()\n", __func__); |
339 | 369 | ||
340 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { | 370 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { |
341 | int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix, | 371 | int ret = ip6addrlbl_add(net, |
372 | ip6addrlbl_init_table[i].prefix, | ||
342 | ip6addrlbl_init_table[i].prefixlen, | 373 | ip6addrlbl_init_table[i].prefixlen, |
343 | 0, | 374 | 0, |
344 | ip6addrlbl_init_table[i].label, 0); | 375 | ip6addrlbl_init_table[i].label, 0); |
@@ -349,11 +380,32 @@ static __init int ip6addrlbl_init(void) | |||
349 | return err; | 380 | return err; |
350 | } | 381 | } |
351 | 382 | ||
383 | static void __net_exit ip6addrlbl_net_exit(struct net *net) | ||
384 | { | ||
385 | struct ip6addrlbl_entry *p = NULL; | ||
386 | struct hlist_node *pos, *n; | ||
387 | |||
388 | /* Remove all labels belonging to the exiting net */ | ||
389 | spin_lock(&ip6addrlbl_table.lock); | ||
390 | hlist_for_each_entry_safe(p, pos, n, &ip6addrlbl_table.head, list) { | ||
391 | if (net_eq(ip6addrlbl_net(p), net)) { | ||
392 | hlist_del_rcu(&p->list); | ||
393 | ip6addrlbl_put(p); | ||
394 | } | ||
395 | } | ||
396 | spin_unlock(&ip6addrlbl_table.lock); | ||
397 | } | ||
398 | |||
399 | static struct pernet_operations ipv6_addr_label_ops = { | ||
400 | .init = ip6addrlbl_net_init, | ||
401 | .exit = ip6addrlbl_net_exit, | ||
402 | }; | ||
403 | |||
352 | int __init ipv6_addr_label_init(void) | 404 | int __init ipv6_addr_label_init(void) |
353 | { | 405 | { |
354 | spin_lock_init(&ip6addrlbl_table.lock); | 406 | spin_lock_init(&ip6addrlbl_table.lock); |
355 | 407 | ||
356 | return ip6addrlbl_init(); | 408 | return register_pernet_subsys(&ipv6_addr_label_ops); |
357 | } | 409 | } |
358 | 410 | ||
359 | static const struct nla_policy ifal_policy[IFAL_MAX+1] = { | 411 | static const struct nla_policy ifal_policy[IFAL_MAX+1] = { |
@@ -371,9 +423,6 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
371 | u32 label; | 423 | u32 label; |
372 | int err = 0; | 424 | int err = 0; |
373 | 425 | ||
374 | if (net != &init_net) | ||
375 | return 0; | ||
376 | |||
377 | err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy); | 426 | err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy); |
378 | if (err < 0) | 427 | if (err < 0) |
379 | return err; | 428 | return err; |
@@ -385,7 +434,7 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
385 | return -EINVAL; | 434 | return -EINVAL; |
386 | 435 | ||
387 | if (ifal->ifal_index && | 436 | if (ifal->ifal_index && |
388 | !__dev_get_by_index(&init_net, ifal->ifal_index)) | 437 | !__dev_get_by_index(net, ifal->ifal_index)) |
389 | return -EINVAL; | 438 | return -EINVAL; |
390 | 439 | ||
391 | if (!tb[IFAL_ADDRESS]) | 440 | if (!tb[IFAL_ADDRESS]) |
@@ -403,12 +452,12 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
403 | 452 | ||
404 | switch(nlh->nlmsg_type) { | 453 | switch(nlh->nlmsg_type) { |
405 | case RTM_NEWADDRLABEL: | 454 | case RTM_NEWADDRLABEL: |
406 | err = ip6addrlbl_add(pfx, ifal->ifal_prefixlen, | 455 | err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen, |
407 | ifal->ifal_index, label, | 456 | ifal->ifal_index, label, |
408 | nlh->nlmsg_flags & NLM_F_REPLACE); | 457 | nlh->nlmsg_flags & NLM_F_REPLACE); |
409 | break; | 458 | break; |
410 | case RTM_DELADDRLABEL: | 459 | case RTM_DELADDRLABEL: |
411 | err = ip6addrlbl_del(pfx, ifal->ifal_prefixlen, | 460 | err = ip6addrlbl_del(net, pfx, ifal->ifal_prefixlen, |
412 | ifal->ifal_index); | 461 | ifal->ifal_index); |
413 | break; | 462 | break; |
414 | default: | 463 | default: |
@@ -458,12 +507,10 @@ static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
458 | int idx = 0, s_idx = cb->args[0]; | 507 | int idx = 0, s_idx = cb->args[0]; |
459 | int err; | 508 | int err; |
460 | 509 | ||
461 | if (net != &init_net) | ||
462 | return 0; | ||
463 | |||
464 | rcu_read_lock(); | 510 | rcu_read_lock(); |
465 | hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) { | 511 | hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) { |
466 | if (idx >= s_idx) { | 512 | if (idx >= s_idx && |
513 | net_eq(ip6addrlbl_net(p), net)) { | ||
467 | if ((err = ip6addrlbl_fill(skb, p, | 514 | if ((err = ip6addrlbl_fill(skb, p, |
468 | ip6addrlbl_table.seq, | 515 | ip6addrlbl_table.seq, |
469 | NETLINK_CB(cb->skb).pid, | 516 | NETLINK_CB(cb->skb).pid, |
@@ -499,9 +546,6 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
499 | struct ip6addrlbl_entry *p; | 546 | struct ip6addrlbl_entry *p; |
500 | struct sk_buff *skb; | 547 | struct sk_buff *skb; |
501 | 548 | ||
502 | if (net != &init_net) | ||
503 | return 0; | ||
504 | |||
505 | err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy); | 549 | err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy); |
506 | if (err < 0) | 550 | if (err < 0) |
507 | return err; | 551 | return err; |
@@ -513,7 +557,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
513 | return -EINVAL; | 557 | return -EINVAL; |
514 | 558 | ||
515 | if (ifal->ifal_index && | 559 | if (ifal->ifal_index && |
516 | !__dev_get_by_index(&init_net, ifal->ifal_index)) | 560 | !__dev_get_by_index(net, ifal->ifal_index)) |
517 | return -EINVAL; | 561 | return -EINVAL; |
518 | 562 | ||
519 | if (!tb[IFAL_ADDRESS]) | 563 | if (!tb[IFAL_ADDRESS]) |
@@ -524,7 +568,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
524 | return -EINVAL; | 568 | return -EINVAL; |
525 | 569 | ||
526 | rcu_read_lock(); | 570 | rcu_read_lock(); |
527 | p = __ipv6_addr_label(addr, ipv6_addr_type(addr), ifal->ifal_index); | 571 | p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index); |
528 | if (p && ip6addrlbl_hold(p)) | 572 | if (p && ip6addrlbl_hold(p)) |
529 | p = NULL; | 573 | p = NULL; |
530 | lseq = ip6addrlbl_table.seq; | 574 | lseq = ip6addrlbl_table.seq; |
@@ -552,7 +596,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
552 | goto out; | 596 | goto out; |
553 | } | 597 | } |
554 | 598 | ||
555 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); | 599 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); |
556 | out: | 600 | out: |
557 | return err; | 601 | return err; |
558 | } | 602 | } |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e84b3fd17fb4..350457c761e6 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * | 7 | * |
8 | * Adapted from linux/net/ipv4/af_inet.c | 8 | * Adapted from linux/net/ipv4/af_inet.c |
9 | * | 9 | * |
10 | * $Id: af_inet6.c,v 1.66 2002/02/01 22:01:04 davem Exp $ | ||
11 | * | ||
12 | * Fixes: | 10 | * Fixes: |
13 | * piggy, Karl Knutson : Socket protocol table | 11 | * piggy, Karl Knutson : Socket protocol table |
14 | * Hideaki YOSHIFUJI : sin6_scope_id support | 12 | * Hideaki YOSHIFUJI : sin6_scope_id support |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 0f0f94a40335..f7b535dec860 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: datagram.c,v 1.24 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 3cd1c993d52b..602ea826f0a5 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * Andi Kleen <ak@muc.de> | 7 | * Andi Kleen <ak@muc.de> |
8 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 8 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
9 | * | 9 | * |
10 | * $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 11 | * modify it under the terms of the GNU General Public License |
14 | * as published by the Free Software Foundation; either version | 12 | * as published by the Free Software Foundation; either version |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index d42dd16d3487..399d41f65437 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: icmp.c,v 1.38 2002/02/08 03:57:19 davem Exp $ | ||
9 | * | ||
10 | * Based on net/ipv4/icmp.c | 8 | * Based on net/ipv4/icmp.c |
11 | * | 9 | * |
12 | * RFC 1885 | 10 | * RFC 1885 |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 1ee4fa17c129..4de2b9efcacb 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: ip6_fib.c,v 1.25 2001/10/31 21:55:55 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 4e5c8615832c..f77a6011c302 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -6,8 +6,6 @@ | |||
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * Ian P. Morris <I.P.Morris@soton.ac.uk> | 7 | * Ian P. Morris <I.P.Morris@soton.ac.uk> |
8 | * | 8 | * |
9 | * $Id: ip6_input.c,v 1.19 2000/12/13 18:31:50 davem Exp $ | ||
10 | * | ||
11 | * Based in linux/net/ipv4/ip_input.c | 9 | * Based in linux/net/ipv4/ip_input.c |
12 | * | 10 | * |
13 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 48cdce9c696c..40a2813a63d1 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: ip6_output.c,v 1.34 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Based on linux/net/ipv4/ip_output.c | 8 | * Based on linux/net/ipv4/ip_output.c |
11 | * | 9 | * |
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 2bda3ba100b1..17c7b098cdb0 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -6,8 +6,6 @@ | |||
6 | * Ville Nuorvala <vnuorval@tcs.hut.fi> | 6 | * Ville Nuorvala <vnuorval@tcs.hut.fi> |
7 | * Yasuyuki Kozakai <kozakai@linux-ipv6.org> | 7 | * Yasuyuki Kozakai <kozakai@linux-ipv6.org> |
8 | * | 8 | * |
9 | * $Id$ | ||
10 | * | ||
11 | * Based on: | 9 | * Based on: |
12 | * linux/net/ipv6/sit.c and linux/net/ipv4/ipip.c | 10 | * linux/net/ipv6/sit.c and linux/net/ipv4/ipip.c |
13 | * | 11 | * |
@@ -711,7 +709,7 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
711 | } | 709 | } |
712 | 710 | ||
713 | if (!ip6_tnl_rcv_ctl(t)) { | 711 | if (!ip6_tnl_rcv_ctl(t)) { |
714 | t->stat.rx_dropped++; | 712 | t->dev->stats.rx_dropped++; |
715 | read_unlock(&ip6_tnl_lock); | 713 | read_unlock(&ip6_tnl_lock); |
716 | goto discard; | 714 | goto discard; |
717 | } | 715 | } |
@@ -728,8 +726,8 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
728 | 726 | ||
729 | dscp_ecn_decapsulate(t, ipv6h, skb); | 727 | dscp_ecn_decapsulate(t, ipv6h, skb); |
730 | 728 | ||
731 | t->stat.rx_packets++; | 729 | t->dev->stats.rx_packets++; |
732 | t->stat.rx_bytes += skb->len; | 730 | t->dev->stats.rx_bytes += skb->len; |
733 | netif_rx(skb); | 731 | netif_rx(skb); |
734 | read_unlock(&ip6_tnl_lock); | 732 | read_unlock(&ip6_tnl_lock); |
735 | return 0; | 733 | return 0; |
@@ -849,7 +847,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
849 | __u32 *pmtu) | 847 | __u32 *pmtu) |
850 | { | 848 | { |
851 | struct ip6_tnl *t = netdev_priv(dev); | 849 | struct ip6_tnl *t = netdev_priv(dev); |
852 | struct net_device_stats *stats = &t->stat; | 850 | struct net_device_stats *stats = &t->dev->stats; |
853 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 851 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
854 | struct ipv6_tel_txoption opt; | 852 | struct ipv6_tel_txoption opt; |
855 | struct dst_entry *dst; | 853 | struct dst_entry *dst; |
@@ -1043,11 +1041,11 @@ static int | |||
1043 | ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | 1041 | ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) |
1044 | { | 1042 | { |
1045 | struct ip6_tnl *t = netdev_priv(dev); | 1043 | struct ip6_tnl *t = netdev_priv(dev); |
1046 | struct net_device_stats *stats = &t->stat; | 1044 | struct net_device_stats *stats = &t->dev->stats; |
1047 | int ret; | 1045 | int ret; |
1048 | 1046 | ||
1049 | if (t->recursion++) { | 1047 | if (t->recursion++) { |
1050 | t->stat.collisions++; | 1048 | stats->collisions++; |
1051 | goto tx_err; | 1049 | goto tx_err; |
1052 | } | 1050 | } |
1053 | 1051 | ||
@@ -1289,19 +1287,6 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1289 | } | 1287 | } |
1290 | 1288 | ||
1291 | /** | 1289 | /** |
1292 | * ip6_tnl_get_stats - return the stats for tunnel device | ||
1293 | * @dev: virtual device associated with tunnel | ||
1294 | * | ||
1295 | * Return: stats for device | ||
1296 | **/ | ||
1297 | |||
1298 | static struct net_device_stats * | ||
1299 | ip6_tnl_get_stats(struct net_device *dev) | ||
1300 | { | ||
1301 | return &(((struct ip6_tnl *)netdev_priv(dev))->stat); | ||
1302 | } | ||
1303 | |||
1304 | /** | ||
1305 | * ip6_tnl_change_mtu - change mtu manually for tunnel device | 1290 | * ip6_tnl_change_mtu - change mtu manually for tunnel device |
1306 | * @dev: virtual device associated with tunnel | 1291 | * @dev: virtual device associated with tunnel |
1307 | * @new_mtu: the new mtu | 1292 | * @new_mtu: the new mtu |
@@ -1334,7 +1319,6 @@ static void ip6_tnl_dev_setup(struct net_device *dev) | |||
1334 | dev->uninit = ip6_tnl_dev_uninit; | 1319 | dev->uninit = ip6_tnl_dev_uninit; |
1335 | dev->destructor = free_netdev; | 1320 | dev->destructor = free_netdev; |
1336 | dev->hard_start_xmit = ip6_tnl_xmit; | 1321 | dev->hard_start_xmit = ip6_tnl_xmit; |
1337 | dev->get_stats = ip6_tnl_get_stats; | ||
1338 | dev->do_ioctl = ip6_tnl_ioctl; | 1322 | dev->do_ioctl = ip6_tnl_ioctl; |
1339 | dev->change_mtu = ip6_tnl_change_mtu; | 1323 | dev->change_mtu = ip6_tnl_change_mtu; |
1340 | 1324 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 14796181e8b5..90e763073dc5 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -388,8 +388,8 @@ static int pim6_rcv(struct sk_buff *skb) | |||
388 | skb->ip_summed = 0; | 388 | skb->ip_summed = 0; |
389 | skb->pkt_type = PACKET_HOST; | 389 | skb->pkt_type = PACKET_HOST; |
390 | dst_release(skb->dst); | 390 | dst_release(skb->dst); |
391 | ((struct net_device_stats *)netdev_priv(reg_dev))->rx_bytes += skb->len; | 391 | reg_dev->stats.rx_bytes += skb->len; |
392 | ((struct net_device_stats *)netdev_priv(reg_dev))->rx_packets++; | 392 | reg_dev->stats.rx_packets++; |
393 | skb->dst = NULL; | 393 | skb->dst = NULL; |
394 | nf_reset(skb); | 394 | nf_reset(skb); |
395 | netif_rx(skb); | 395 | netif_rx(skb); |
@@ -409,26 +409,20 @@ static struct inet6_protocol pim6_protocol = { | |||
409 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | 409 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) |
410 | { | 410 | { |
411 | read_lock(&mrt_lock); | 411 | read_lock(&mrt_lock); |
412 | ((struct net_device_stats *)netdev_priv(dev))->tx_bytes += skb->len; | 412 | dev->stats.tx_bytes += skb->len; |
413 | ((struct net_device_stats *)netdev_priv(dev))->tx_packets++; | 413 | dev->stats.tx_packets++; |
414 | ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT); | 414 | ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT); |
415 | read_unlock(&mrt_lock); | 415 | read_unlock(&mrt_lock); |
416 | kfree_skb(skb); | 416 | kfree_skb(skb); |
417 | return 0; | 417 | return 0; |
418 | } | 418 | } |
419 | 419 | ||
420 | static struct net_device_stats *reg_vif_get_stats(struct net_device *dev) | ||
421 | { | ||
422 | return (struct net_device_stats *)netdev_priv(dev); | ||
423 | } | ||
424 | |||
425 | static void reg_vif_setup(struct net_device *dev) | 420 | static void reg_vif_setup(struct net_device *dev) |
426 | { | 421 | { |
427 | dev->type = ARPHRD_PIMREG; | 422 | dev->type = ARPHRD_PIMREG; |
428 | dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8; | 423 | dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8; |
429 | dev->flags = IFF_NOARP; | 424 | dev->flags = IFF_NOARP; |
430 | dev->hard_start_xmit = reg_vif_xmit; | 425 | dev->hard_start_xmit = reg_vif_xmit; |
431 | dev->get_stats = reg_vif_get_stats; | ||
432 | dev->destructor = free_netdev; | 426 | dev->destructor = free_netdev; |
433 | } | 427 | } |
434 | 428 | ||
@@ -436,9 +430,7 @@ static struct net_device *ip6mr_reg_vif(void) | |||
436 | { | 430 | { |
437 | struct net_device *dev; | 431 | struct net_device *dev; |
438 | 432 | ||
439 | dev = alloc_netdev(sizeof(struct net_device_stats), "pim6reg", | 433 | dev = alloc_netdev(0, "pim6reg", reg_vif_setup); |
440 | reg_vif_setup); | ||
441 | |||
442 | if (dev == NULL) | 434 | if (dev == NULL) |
443 | return NULL; | 435 | return NULL; |
444 | 436 | ||
@@ -1248,7 +1240,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
1248 | 1240 | ||
1249 | #endif | 1241 | #endif |
1250 | /* | 1242 | /* |
1251 | * Spurious command, or MRT_VERSION which you cannot | 1243 | * Spurious command, or MRT6_VERSION which you cannot |
1252 | * set. | 1244 | * set. |
1253 | */ | 1245 | */ |
1254 | default: | 1246 | default: |
@@ -1377,8 +1369,8 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | |||
1377 | if (vif->flags & MIFF_REGISTER) { | 1369 | if (vif->flags & MIFF_REGISTER) { |
1378 | vif->pkt_out++; | 1370 | vif->pkt_out++; |
1379 | vif->bytes_out += skb->len; | 1371 | vif->bytes_out += skb->len; |
1380 | ((struct net_device_stats *)netdev_priv(vif->dev))->tx_bytes += skb->len; | 1372 | vif->dev->stats.tx_bytes += skb->len; |
1381 | ((struct net_device_stats *)netdev_priv(vif->dev))->tx_packets++; | 1373 | vif->dev->stats.tx_packets++; |
1382 | ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT); | 1374 | ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT); |
1383 | kfree_skb(skb); | 1375 | kfree_skb(skb); |
1384 | return 0; | 1376 | return 0; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index c042ce19bd14..a9988841172a 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * | 7 | * |
8 | * Based on linux/net/ipv4/ip_sockglue.c | 8 | * Based on linux/net/ipv4/ip_sockglue.c |
9 | * | 9 | * |
10 | * $Id: ipv6_sockglue.c,v 1.41 2002/02/01 22:01:04 davem Exp $ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 11 | * modify it under the terms of the GNU General Public License |
14 | * as published by the Free Software Foundation; either version | 12 | * as published by the Free Software Foundation; either version |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index fd632dd7f98d..bd2fe4cfafa7 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: mcast.c,v 1.40 2002/02/08 03:57:19 davem Exp $ | ||
9 | * | ||
10 | * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c | 8 | * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c |
11 | * | 9 | * |
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
@@ -164,7 +162,6 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
164 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ | 162 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ |
165 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) | 163 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) |
166 | 164 | ||
167 | #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) | ||
168 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) | 165 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) |
169 | 166 | ||
170 | #define IPV6_MLD_MAX_MSF 64 | 167 | #define IPV6_MLD_MAX_MSF 64 |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 6cae5475737e..689dec899c57 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -208,5 +208,17 @@ config IP6_NF_RAW | |||
208 | If you want to compile it as a module, say M here and read | 208 | If you want to compile it as a module, say M here and read |
209 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 209 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
210 | 210 | ||
211 | # security table for MAC policy | ||
212 | config IP6_NF_SECURITY | ||
213 | tristate "Security table" | ||
214 | depends on IP6_NF_IPTABLES | ||
215 | depends on SECURITY | ||
216 | default m if NETFILTER_ADVANCED=n | ||
217 | help | ||
218 | This option adds a `security' table to iptables, for use | ||
219 | with Mandatory Access Control (MAC) policy. | ||
220 | |||
221 | If unsure, say N. | ||
222 | |||
211 | endmenu | 223 | endmenu |
212 | 224 | ||
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index fbf2c14ed887..3f17c948eefb 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o | |||
8 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o | 8 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o |
9 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o | 9 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o |
10 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 10 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
11 | obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o | ||
11 | 12 | ||
12 | # objects for l3 independent conntrack | 13 | # objects for l3 independent conntrack |
13 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o | 14 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 2eff3ae8977d..1b8815f6153d 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -159,7 +159,6 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
159 | case IPQ_COPY_META: | 159 | case IPQ_COPY_META: |
160 | case IPQ_COPY_NONE: | 160 | case IPQ_COPY_NONE: |
161 | size = NLMSG_SPACE(sizeof(*pmsg)); | 161 | size = NLMSG_SPACE(sizeof(*pmsg)); |
162 | data_len = 0; | ||
163 | break; | 162 | break; |
164 | 163 | ||
165 | case IPQ_COPY_PACKET: | 164 | case IPQ_COPY_PACKET: |
@@ -226,8 +225,6 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
226 | return skb; | 225 | return skb; |
227 | 226 | ||
228 | nlmsg_failure: | 227 | nlmsg_failure: |
229 | if (skb) | ||
230 | kfree_skb(skb); | ||
231 | *errp = -EINVAL; | 228 | *errp = -EINVAL; |
232 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); | 229 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); |
233 | return NULL; | 230 | return NULL; |
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c new file mode 100644 index 000000000000..063a3d9c3c67 --- /dev/null +++ b/net/ipv6/netfilter/ip6table_security.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * "security" table for IPv6 | ||
3 | * | ||
4 | * This is for use by Mandatory Access Control (MAC) security models, | ||
5 | * which need to be able to manage security policy in separate context | ||
6 | * to DAC. | ||
7 | * | ||
8 | * Based on iptable_mangle.c | ||
9 | * | ||
10 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | ||
11 | * Copyright (C) 2000-2004 Netfilter Core Team <coreteam <at> netfilter.org> | ||
12 | * Copyright (C) 2008 Red Hat, Inc., James Morris <jmorris <at> redhat.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
20 | |||
21 | MODULE_LICENSE("GPL"); | ||
22 | MODULE_AUTHOR("James Morris <jmorris <at> redhat.com>"); | ||
23 | MODULE_DESCRIPTION("ip6tables security table, for MAC rules"); | ||
24 | |||
25 | #define SECURITY_VALID_HOOKS (1 << NF_INET_LOCAL_IN) | \ | ||
26 | (1 << NF_INET_FORWARD) | \ | ||
27 | (1 << NF_INET_LOCAL_OUT) | ||
28 | |||
29 | static struct | ||
30 | { | ||
31 | struct ip6t_replace repl; | ||
32 | struct ip6t_standard entries[3]; | ||
33 | struct ip6t_error term; | ||
34 | } initial_table __initdata = { | ||
35 | .repl = { | ||
36 | .name = "security", | ||
37 | .valid_hooks = SECURITY_VALID_HOOKS, | ||
38 | .num_entries = 4, | ||
39 | .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), | ||
40 | .hook_entry = { | ||
41 | [NF_INET_LOCAL_IN] = 0, | ||
42 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard), | ||
43 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2, | ||
44 | }, | ||
45 | .underflow = { | ||
46 | [NF_INET_LOCAL_IN] = 0, | ||
47 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard), | ||
48 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2, | ||
49 | }, | ||
50 | }, | ||
51 | .entries = { | ||
52 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ | ||
53 | IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ | ||
54 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ | ||
55 | }, | ||
56 | .term = IP6T_ERROR_INIT, /* ERROR */ | ||
57 | }; | ||
58 | |||
59 | static struct xt_table security_table = { | ||
60 | .name = "security", | ||
61 | .valid_hooks = SECURITY_VALID_HOOKS, | ||
62 | .lock = __RW_LOCK_UNLOCKED(security_table.lock), | ||
63 | .me = THIS_MODULE, | ||
64 | .af = AF_INET6, | ||
65 | }; | ||
66 | |||
67 | static unsigned int | ||
68 | ip6t_local_in_hook(unsigned int hook, | ||
69 | struct sk_buff *skb, | ||
70 | const struct net_device *in, | ||
71 | const struct net_device *out, | ||
72 | int (*okfn)(struct sk_buff *)) | ||
73 | { | ||
74 | return ip6t_do_table(skb, hook, in, out, | ||
75 | init_net.ipv6.ip6table_security); | ||
76 | } | ||
77 | |||
78 | static unsigned int | ||
79 | ip6t_forward_hook(unsigned int hook, | ||
80 | struct sk_buff *skb, | ||
81 | const struct net_device *in, | ||
82 | const struct net_device *out, | ||
83 | int (*okfn)(struct sk_buff *)) | ||
84 | { | ||
85 | return ip6t_do_table(skb, hook, in, out, | ||
86 | init_net.ipv6.ip6table_security); | ||
87 | } | ||
88 | |||
89 | static unsigned int | ||
90 | ip6t_local_out_hook(unsigned int hook, | ||
91 | struct sk_buff *skb, | ||
92 | const struct net_device *in, | ||
93 | const struct net_device *out, | ||
94 | int (*okfn)(struct sk_buff *)) | ||
95 | { | ||
96 | /* TBD: handle short packets via raw socket */ | ||
97 | return ip6t_do_table(skb, hook, in, out, | ||
98 | init_net.ipv6.ip6table_security); | ||
99 | } | ||
100 | |||
101 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | ||
102 | { | ||
103 | .hook = ip6t_local_in_hook, | ||
104 | .owner = THIS_MODULE, | ||
105 | .pf = PF_INET6, | ||
106 | .hooknum = NF_INET_LOCAL_IN, | ||
107 | .priority = NF_IP6_PRI_SECURITY, | ||
108 | }, | ||
109 | { | ||
110 | .hook = ip6t_forward_hook, | ||
111 | .owner = THIS_MODULE, | ||
112 | .pf = PF_INET6, | ||
113 | .hooknum = NF_INET_FORWARD, | ||
114 | .priority = NF_IP6_PRI_SECURITY, | ||
115 | }, | ||
116 | { | ||
117 | .hook = ip6t_local_out_hook, | ||
118 | .owner = THIS_MODULE, | ||
119 | .pf = PF_INET6, | ||
120 | .hooknum = NF_INET_LOCAL_OUT, | ||
121 | .priority = NF_IP6_PRI_SECURITY, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static int __net_init ip6table_security_net_init(struct net *net) | ||
126 | { | ||
127 | net->ipv6.ip6table_security = | ||
128 | ip6t_register_table(net, &security_table, &initial_table.repl); | ||
129 | |||
130 | if (IS_ERR(net->ipv6.ip6table_security)) | ||
131 | return PTR_ERR(net->ipv6.ip6table_security); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void __net_exit ip6table_security_net_exit(struct net *net) | ||
137 | { | ||
138 | ip6t_unregister_table(net->ipv6.ip6table_security); | ||
139 | } | ||
140 | |||
141 | static struct pernet_operations ip6table_security_net_ops = { | ||
142 | .init = ip6table_security_net_init, | ||
143 | .exit = ip6table_security_net_exit, | ||
144 | }; | ||
145 | |||
146 | static int __init ip6table_security_init(void) | ||
147 | { | ||
148 | int ret; | ||
149 | |||
150 | ret = register_pernet_subsys(&ip6table_security_net_ops); | ||
151 | if (ret < 0) | ||
152 | return ret; | ||
153 | |||
154 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | ||
155 | if (ret < 0) | ||
156 | goto cleanup_table; | ||
157 | |||
158 | return ret; | ||
159 | |||
160 | cleanup_table: | ||
161 | unregister_pernet_subsys(&ip6table_security_net_ops); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static void __exit ip6table_security_fini(void) | ||
166 | { | ||
167 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | ||
168 | unregister_pernet_subsys(&ip6table_security_net_ops); | ||
169 | } | ||
170 | |||
171 | module_init(ip6table_security_init); | ||
172 | module_exit(ip6table_security_fini); | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index ee713b03e9ec..14d47d833545 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -89,9 +89,8 @@ static int icmpv6_packet(struct nf_conn *ct, | |||
89 | means this will only run once even if count hits zero twice | 89 | means this will only run once even if count hits zero twice |
90 | (theoretically possible with SMP) */ | 90 | (theoretically possible with SMP) */ |
91 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { | 91 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { |
92 | if (atomic_dec_and_test(&ct->proto.icmp.count) | 92 | if (atomic_dec_and_test(&ct->proto.icmp.count)) |
93 | && del_timer(&ct->timeout)) | 93 | nf_ct_kill_acct(ct, ctinfo, skb); |
94 | ct->timeout.function((unsigned long)ct); | ||
95 | } else { | 94 | } else { |
96 | atomic_inc(&ct->proto.icmp.count); | 95 | atomic_inc(&ct->proto.icmp.count); |
97 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); | 96 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index df0736a4cafa..cbc7e514d3ec 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * PROC file system. This is very similar to the IPv4 version, | 7 | * PROC file system. This is very similar to the IPv4 version, |
8 | * except it reports the sockets in the INET6 address family. | 8 | * except it reports the sockets in the INET6 address family. |
9 | * | 9 | * |
10 | * Version: $Id: proc.c,v 1.17 2002/02/01 22:01:04 davem Exp $ | ||
11 | * | ||
12 | * Authors: David S. Miller (davem@caip.rutgers.edu) | 10 | * Authors: David S. Miller (davem@caip.rutgers.edu) |
13 | * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 11 | * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> |
14 | * | 12 | * |
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index f929f47b925e..9ab789159913 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * PF_INET6 protocol dispatch tables. | 6 | * PF_INET6 protocol dispatch tables. |
7 | * | 7 | * |
8 | * Version: $Id: protocol.c,v 1.10 2001/05/18 02:25:49 davem Exp $ | ||
9 | * | ||
10 | * Authors: Pedro Roque <roque@di.fc.ul.pt> | 8 | * Authors: Pedro Roque <roque@di.fc.ul.pt> |
11 | * | 9 | * |
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 3aee12310d94..70a57e45bf0e 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * | 7 | * |
8 | * Adapted from linux/net/ipv4/raw.c | 8 | * Adapted from linux/net/ipv4/raw.c |
9 | * | 9 | * |
10 | * $Id: raw.c,v 1.51 2002/02/01 22:01:04 davem Exp $ | ||
11 | * | ||
12 | * Fixes: | 10 | * Fixes: |
13 | * Hideaki YOSHIFUJI : sin6_scope_id support | 11 | * Hideaki YOSHIFUJI : sin6_scope_id support |
14 | * YOSHIFUJI,H.@USAGI : raw checksum (RFC2292(bis) compliance) | 12 | * YOSHIFUJI,H.@USAGI : raw checksum (RFC2292(bis) compliance) |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 798cabc7535b..13509f906d89 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: reassembly.c,v 1.26 2001/03/07 22:00:57 davem Exp $ | ||
9 | * | ||
10 | * Based on: net/ipv4/ip_fragment.c | 8 | * Based on: net/ipv4/ip_fragment.c |
11 | * | 9 | * |
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
@@ -632,7 +630,7 @@ static struct inet6_protocol frag_protocol = | |||
632 | }; | 630 | }; |
633 | 631 | ||
634 | #ifdef CONFIG_SYSCTL | 632 | #ifdef CONFIG_SYSCTL |
635 | static struct ctl_table ip6_frags_ctl_table[] = { | 633 | static struct ctl_table ip6_frags_ns_ctl_table[] = { |
636 | { | 634 | { |
637 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, | 635 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, |
638 | .procname = "ip6frag_high_thresh", | 636 | .procname = "ip6frag_high_thresh", |
@@ -658,6 +656,10 @@ static struct ctl_table ip6_frags_ctl_table[] = { | |||
658 | .proc_handler = &proc_dointvec_jiffies, | 656 | .proc_handler = &proc_dointvec_jiffies, |
659 | .strategy = &sysctl_jiffies, | 657 | .strategy = &sysctl_jiffies, |
660 | }, | 658 | }, |
659 | { } | ||
660 | }; | ||
661 | |||
662 | static struct ctl_table ip6_frags_ctl_table[] = { | ||
661 | { | 663 | { |
662 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, | 664 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, |
663 | .procname = "ip6frag_secret_interval", | 665 | .procname = "ip6frag_secret_interval", |
@@ -670,21 +672,20 @@ static struct ctl_table ip6_frags_ctl_table[] = { | |||
670 | { } | 672 | { } |
671 | }; | 673 | }; |
672 | 674 | ||
673 | static int ip6_frags_sysctl_register(struct net *net) | 675 | static int ip6_frags_ns_sysctl_register(struct net *net) |
674 | { | 676 | { |
675 | struct ctl_table *table; | 677 | struct ctl_table *table; |
676 | struct ctl_table_header *hdr; | 678 | struct ctl_table_header *hdr; |
677 | 679 | ||
678 | table = ip6_frags_ctl_table; | 680 | table = ip6_frags_ns_ctl_table; |
679 | if (net != &init_net) { | 681 | if (net != &init_net) { |
680 | table = kmemdup(table, sizeof(ip6_frags_ctl_table), GFP_KERNEL); | 682 | table = kmemdup(table, sizeof(ip6_frags_ns_ctl_table), GFP_KERNEL); |
681 | if (table == NULL) | 683 | if (table == NULL) |
682 | goto err_alloc; | 684 | goto err_alloc; |
683 | 685 | ||
684 | table[0].data = &net->ipv6.frags.high_thresh; | 686 | table[0].data = &net->ipv6.frags.high_thresh; |
685 | table[1].data = &net->ipv6.frags.low_thresh; | 687 | table[1].data = &net->ipv6.frags.low_thresh; |
686 | table[2].data = &net->ipv6.frags.timeout; | 688 | table[2].data = &net->ipv6.frags.timeout; |
687 | table[3].mode &= ~0222; | ||
688 | } | 689 | } |
689 | 690 | ||
690 | hdr = register_net_sysctl_table(net, net_ipv6_ctl_path, table); | 691 | hdr = register_net_sysctl_table(net, net_ipv6_ctl_path, table); |
@@ -701,7 +702,7 @@ err_alloc: | |||
701 | return -ENOMEM; | 702 | return -ENOMEM; |
702 | } | 703 | } |
703 | 704 | ||
704 | static void ip6_frags_sysctl_unregister(struct net *net) | 705 | static void ip6_frags_ns_sysctl_unregister(struct net *net) |
705 | { | 706 | { |
706 | struct ctl_table *table; | 707 | struct ctl_table *table; |
707 | 708 | ||
@@ -709,13 +710,36 @@ static void ip6_frags_sysctl_unregister(struct net *net) | |||
709 | unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr); | 710 | unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr); |
710 | kfree(table); | 711 | kfree(table); |
711 | } | 712 | } |
713 | |||
714 | static struct ctl_table_header *ip6_ctl_header; | ||
715 | |||
716 | static int ip6_frags_sysctl_register(void) | ||
717 | { | ||
718 | ip6_ctl_header = register_net_sysctl_rotable(net_ipv6_ctl_path, | ||
719 | ip6_frags_ctl_table); | ||
720 | return ip6_ctl_header == NULL ? -ENOMEM : 0; | ||
721 | } | ||
722 | |||
723 | static void ip6_frags_sysctl_unregister(void) | ||
724 | { | ||
725 | unregister_net_sysctl_table(ip6_ctl_header); | ||
726 | } | ||
712 | #else | 727 | #else |
713 | static inline int ip6_frags_sysctl_register(struct net *net) | 728 | static inline int ip6_frags_ns_sysctl_register(struct net *net) |
714 | { | 729 | { |
715 | return 0; | 730 | return 0; |
716 | } | 731 | } |
717 | 732 | ||
718 | static inline void ip6_frags_sysctl_unregister(struct net *net) | 733 | static inline void ip6_frags_ns_sysctl_unregister(struct net *net) |
734 | { | ||
735 | } | ||
736 | |||
737 | static inline int ip6_frags_sysctl_register(void) | ||
738 | { | ||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | static inline void ip6_frags_sysctl_unregister(void) | ||
719 | { | 743 | { |
720 | } | 744 | } |
721 | #endif | 745 | #endif |
@@ -728,12 +752,12 @@ static int ipv6_frags_init_net(struct net *net) | |||
728 | 752 | ||
729 | inet_frags_init_net(&net->ipv6.frags); | 753 | inet_frags_init_net(&net->ipv6.frags); |
730 | 754 | ||
731 | return ip6_frags_sysctl_register(net); | 755 | return ip6_frags_ns_sysctl_register(net); |
732 | } | 756 | } |
733 | 757 | ||
734 | static void ipv6_frags_exit_net(struct net *net) | 758 | static void ipv6_frags_exit_net(struct net *net) |
735 | { | 759 | { |
736 | ip6_frags_sysctl_unregister(net); | 760 | ip6_frags_ns_sysctl_unregister(net); |
737 | inet_frags_exit_net(&net->ipv6.frags, &ip6_frags); | 761 | inet_frags_exit_net(&net->ipv6.frags, &ip6_frags); |
738 | } | 762 | } |
739 | 763 | ||
@@ -750,7 +774,13 @@ int __init ipv6_frag_init(void) | |||
750 | if (ret) | 774 | if (ret) |
751 | goto out; | 775 | goto out; |
752 | 776 | ||
753 | register_pernet_subsys(&ip6_frags_ops); | 777 | ret = ip6_frags_sysctl_register(); |
778 | if (ret) | ||
779 | goto err_sysctl; | ||
780 | |||
781 | ret = register_pernet_subsys(&ip6_frags_ops); | ||
782 | if (ret) | ||
783 | goto err_pernet; | ||
754 | 784 | ||
755 | ip6_frags.hashfn = ip6_hashfn; | 785 | ip6_frags.hashfn = ip6_hashfn; |
756 | ip6_frags.constructor = ip6_frag_init; | 786 | ip6_frags.constructor = ip6_frag_init; |
@@ -763,11 +793,18 @@ int __init ipv6_frag_init(void) | |||
763 | inet_frags_init(&ip6_frags); | 793 | inet_frags_init(&ip6_frags); |
764 | out: | 794 | out: |
765 | return ret; | 795 | return ret; |
796 | |||
797 | err_pernet: | ||
798 | ip6_frags_sysctl_unregister(); | ||
799 | err_sysctl: | ||
800 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); | ||
801 | goto out; | ||
766 | } | 802 | } |
767 | 803 | ||
768 | void ipv6_frag_exit(void) | 804 | void ipv6_frag_exit(void) |
769 | { | 805 | { |
770 | inet_frags_fini(&ip6_frags); | 806 | inet_frags_fini(&ip6_frags); |
807 | ip6_frags_sysctl_unregister(); | ||
771 | unregister_pernet_subsys(&ip6_frags_ops); | 808 | unregister_pernet_subsys(&ip6_frags_ops); |
772 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); | 809 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); |
773 | } | 810 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d1f3e19b06c7..efe036aa3dd1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3de6ffdaedf2..b0c5080420a8 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -6,8 +6,6 @@ | |||
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 7 | * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
8 | * | 8 | * |
9 | * $Id: sit.c,v 1.53 2001/09/25 05:09:53 davem Exp $ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
13 | * as published by the Free Software Foundation; either version | 11 | * as published by the Free Software Foundation; either version |
@@ -491,13 +489,13 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
491 | 489 | ||
492 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && | 490 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && |
493 | !isatap_chksrc(skb, iph, tunnel)) { | 491 | !isatap_chksrc(skb, iph, tunnel)) { |
494 | tunnel->stat.rx_errors++; | 492 | tunnel->dev->stats.rx_errors++; |
495 | read_unlock(&ipip6_lock); | 493 | read_unlock(&ipip6_lock); |
496 | kfree_skb(skb); | 494 | kfree_skb(skb); |
497 | return 0; | 495 | return 0; |
498 | } | 496 | } |
499 | tunnel->stat.rx_packets++; | 497 | tunnel->dev->stats.rx_packets++; |
500 | tunnel->stat.rx_bytes += skb->len; | 498 | tunnel->dev->stats.rx_bytes += skb->len; |
501 | skb->dev = tunnel->dev; | 499 | skb->dev = tunnel->dev; |
502 | dst_release(skb->dst); | 500 | dst_release(skb->dst); |
503 | skb->dst = NULL; | 501 | skb->dst = NULL; |
@@ -537,7 +535,7 @@ static inline __be32 try_6to4(struct in6_addr *v6dst) | |||
537 | static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 535 | static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
538 | { | 536 | { |
539 | struct ip_tunnel *tunnel = netdev_priv(dev); | 537 | struct ip_tunnel *tunnel = netdev_priv(dev); |
540 | struct net_device_stats *stats = &tunnel->stat; | 538 | struct net_device_stats *stats = &tunnel->dev->stats; |
541 | struct iphdr *tiph = &tunnel->parms.iph; | 539 | struct iphdr *tiph = &tunnel->parms.iph; |
542 | struct ipv6hdr *iph6 = ipv6_hdr(skb); | 540 | struct ipv6hdr *iph6 = ipv6_hdr(skb); |
543 | u8 tos = tunnel->parms.iph.tos; | 541 | u8 tos = tunnel->parms.iph.tos; |
@@ -551,7 +549,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
551 | int addr_type; | 549 | int addr_type; |
552 | 550 | ||
553 | if (tunnel->recursion++) { | 551 | if (tunnel->recursion++) { |
554 | tunnel->stat.collisions++; | 552 | stats->collisions++; |
555 | goto tx_error; | 553 | goto tx_error; |
556 | } | 554 | } |
557 | 555 | ||
@@ -618,20 +616,20 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
618 | .oif = tunnel->parms.link, | 616 | .oif = tunnel->parms.link, |
619 | .proto = IPPROTO_IPV6 }; | 617 | .proto = IPPROTO_IPV6 }; |
620 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 618 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { |
621 | tunnel->stat.tx_carrier_errors++; | 619 | stats->tx_carrier_errors++; |
622 | goto tx_error_icmp; | 620 | goto tx_error_icmp; |
623 | } | 621 | } |
624 | } | 622 | } |
625 | if (rt->rt_type != RTN_UNICAST) { | 623 | if (rt->rt_type != RTN_UNICAST) { |
626 | ip_rt_put(rt); | 624 | ip_rt_put(rt); |
627 | tunnel->stat.tx_carrier_errors++; | 625 | stats->tx_carrier_errors++; |
628 | goto tx_error_icmp; | 626 | goto tx_error_icmp; |
629 | } | 627 | } |
630 | tdev = rt->u.dst.dev; | 628 | tdev = rt->u.dst.dev; |
631 | 629 | ||
632 | if (tdev == dev) { | 630 | if (tdev == dev) { |
633 | ip_rt_put(rt); | 631 | ip_rt_put(rt); |
634 | tunnel->stat.collisions++; | 632 | stats->collisions++; |
635 | goto tx_error; | 633 | goto tx_error; |
636 | } | 634 | } |
637 | 635 | ||
@@ -641,7 +639,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
641 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; | 639 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; |
642 | 640 | ||
643 | if (mtu < 68) { | 641 | if (mtu < 68) { |
644 | tunnel->stat.collisions++; | 642 | stats->collisions++; |
645 | ip_rt_put(rt); | 643 | ip_rt_put(rt); |
646 | goto tx_error; | 644 | goto tx_error; |
647 | } | 645 | } |
@@ -916,11 +914,6 @@ done: | |||
916 | return err; | 914 | return err; |
917 | } | 915 | } |
918 | 916 | ||
919 | static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev) | ||
920 | { | ||
921 | return &(((struct ip_tunnel*)netdev_priv(dev))->stat); | ||
922 | } | ||
923 | |||
924 | static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 917 | static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) |
925 | { | 918 | { |
926 | if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr)) | 919 | if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr)) |
@@ -934,7 +927,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) | |||
934 | dev->uninit = ipip6_tunnel_uninit; | 927 | dev->uninit = ipip6_tunnel_uninit; |
935 | dev->destructor = free_netdev; | 928 | dev->destructor = free_netdev; |
936 | dev->hard_start_xmit = ipip6_tunnel_xmit; | 929 | dev->hard_start_xmit = ipip6_tunnel_xmit; |
937 | dev->get_stats = ipip6_tunnel_get_stats; | ||
938 | dev->do_ioctl = ipip6_tunnel_ioctl; | 930 | dev->do_ioctl = ipip6_tunnel_ioctl; |
939 | dev->change_mtu = ipip6_tunnel_change_mtu; | 931 | dev->change_mtu = ipip6_tunnel_change_mtu; |
940 | 932 | ||
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 3804dcbbfab0..5c99274558bf 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -37,6 +37,10 @@ static ctl_table ipv6_table_template[] = { | |||
37 | .mode = 0644, | 37 | .mode = 0644, |
38 | .proc_handler = &proc_dointvec | 38 | .proc_handler = &proc_dointvec |
39 | }, | 39 | }, |
40 | { .ctl_name = 0 } | ||
41 | }; | ||
42 | |||
43 | static ctl_table ipv6_table[] = { | ||
40 | { | 44 | { |
41 | .ctl_name = NET_IPV6_MLD_MAX_MSF, | 45 | .ctl_name = NET_IPV6_MLD_MAX_MSF, |
42 | .procname = "mld_max_msf", | 46 | .procname = "mld_max_msf", |
@@ -80,12 +84,6 @@ static int ipv6_sysctl_net_init(struct net *net) | |||
80 | 84 | ||
81 | ipv6_table[2].data = &net->ipv6.sysctl.bindv6only; | 85 | ipv6_table[2].data = &net->ipv6.sysctl.bindv6only; |
82 | 86 | ||
83 | /* We don't want this value to be per namespace, it should be global | ||
84 | to all namespaces, so make it read-only when we are not in the | ||
85 | init network namespace */ | ||
86 | if (net != &init_net) | ||
87 | ipv6_table[3].mode = 0444; | ||
88 | |||
89 | net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path, | 87 | net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path, |
90 | ipv6_table); | 88 | ipv6_table); |
91 | if (!net->ipv6.sysctl.table) | 89 | if (!net->ipv6.sysctl.table) |
@@ -126,12 +124,29 @@ static struct pernet_operations ipv6_sysctl_net_ops = { | |||
126 | .exit = ipv6_sysctl_net_exit, | 124 | .exit = ipv6_sysctl_net_exit, |
127 | }; | 125 | }; |
128 | 126 | ||
127 | static struct ctl_table_header *ip6_header; | ||
128 | |||
129 | int ipv6_sysctl_register(void) | 129 | int ipv6_sysctl_register(void) |
130 | { | 130 | { |
131 | return register_pernet_subsys(&ipv6_sysctl_net_ops); | 131 | int err = -ENOMEM;; |
132 | |||
133 | ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_table); | ||
134 | if (ip6_header == NULL) | ||
135 | goto out; | ||
136 | |||
137 | err = register_pernet_subsys(&ipv6_sysctl_net_ops); | ||
138 | if (err) | ||
139 | goto err_pernet; | ||
140 | out: | ||
141 | return err; | ||
142 | |||
143 | err_pernet: | ||
144 | unregister_net_sysctl_table(ip6_header); | ||
145 | goto out; | ||
132 | } | 146 | } |
133 | 147 | ||
134 | void ipv6_sysctl_unregister(void) | 148 | void ipv6_sysctl_unregister(void) |
135 | { | 149 | { |
150 | unregister_net_sysctl_table(ip6_header); | ||
136 | unregister_pernet_subsys(&ipv6_sysctl_net_ops); | 151 | unregister_pernet_subsys(&ipv6_sysctl_net_ops); |
137 | } | 152 | } |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index cb46749d4c32..ebed5d3adb82 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: tcp_ipv6.c,v 1.144 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Based on: | 8 | * Based on: |
11 | * linux/net/ipv4/tcp.c | 9 | * linux/net/ipv4/tcp.c |
12 | * linux/net/ipv4/tcp_input.c | 10 | * linux/net/ipv4/tcp_input.c |
@@ -82,6 +80,12 @@ static struct inet_connection_sock_af_ops ipv6_specific; | |||
82 | #ifdef CONFIG_TCP_MD5SIG | 80 | #ifdef CONFIG_TCP_MD5SIG |
83 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; | 81 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; |
84 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; | 82 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; |
83 | #else | ||
84 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | ||
85 | struct in6_addr *addr) | ||
86 | { | ||
87 | return NULL; | ||
88 | } | ||
85 | #endif | 89 | #endif |
86 | 90 | ||
87 | static void tcp_v6_hash(struct sock *sk) | 91 | static void tcp_v6_hash(struct sock *sk) |
@@ -736,78 +740,34 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | |||
736 | static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 740 | static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, |
737 | struct in6_addr *saddr, | 741 | struct in6_addr *saddr, |
738 | struct in6_addr *daddr, | 742 | struct in6_addr *daddr, |
739 | struct tcphdr *th, int protocol, | 743 | struct tcphdr *th, unsigned int tcplen) |
740 | unsigned int tcplen) | ||
741 | { | 744 | { |
742 | struct scatterlist sg[4]; | ||
743 | __u16 data_len; | ||
744 | int block = 0; | ||
745 | __sum16 cksum; | ||
746 | struct tcp_md5sig_pool *hp; | 745 | struct tcp_md5sig_pool *hp; |
747 | struct tcp6_pseudohdr *bp; | 746 | struct tcp6_pseudohdr *bp; |
748 | struct hash_desc *desc; | ||
749 | int err; | 747 | int err; |
750 | unsigned int nbytes = 0; | ||
751 | 748 | ||
752 | hp = tcp_get_md5sig_pool(); | 749 | hp = tcp_get_md5sig_pool(); |
753 | if (!hp) { | 750 | if (!hp) { |
754 | printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); | 751 | printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); |
755 | goto clear_hash_noput; | 752 | goto clear_hash_noput; |
756 | } | 753 | } |
754 | |||
757 | bp = &hp->md5_blk.ip6; | 755 | bp = &hp->md5_blk.ip6; |
758 | desc = &hp->md5_desc; | ||
759 | 756 | ||
760 | /* 1. TCP pseudo-header (RFC2460) */ | 757 | /* 1. TCP pseudo-header (RFC2460) */ |
761 | ipv6_addr_copy(&bp->saddr, saddr); | 758 | ipv6_addr_copy(&bp->saddr, saddr); |
762 | ipv6_addr_copy(&bp->daddr, daddr); | 759 | ipv6_addr_copy(&bp->daddr, daddr); |
763 | bp->len = htonl(tcplen); | 760 | bp->len = htonl(tcplen); |
764 | bp->protocol = htonl(protocol); | 761 | bp->protocol = htonl(IPPROTO_TCP); |
765 | |||
766 | sg_init_table(sg, 4); | ||
767 | 762 | ||
768 | sg_set_buf(&sg[block++], bp, sizeof(*bp)); | 763 | err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp), |
769 | nbytes += sizeof(*bp); | 764 | th, tcplen, hp); |
770 | 765 | ||
771 | /* 2. TCP header, excluding options */ | 766 | if (err) |
772 | cksum = th->check; | ||
773 | th->check = 0; | ||
774 | sg_set_buf(&sg[block++], th, sizeof(*th)); | ||
775 | nbytes += sizeof(*th); | ||
776 | |||
777 | /* 3. TCP segment data (if any) */ | ||
778 | data_len = tcplen - (th->doff << 2); | ||
779 | if (data_len > 0) { | ||
780 | u8 *data = (u8 *)th + (th->doff << 2); | ||
781 | sg_set_buf(&sg[block++], data, data_len); | ||
782 | nbytes += data_len; | ||
783 | } | ||
784 | |||
785 | /* 4. shared key */ | ||
786 | sg_set_buf(&sg[block++], key->key, key->keylen); | ||
787 | nbytes += key->keylen; | ||
788 | |||
789 | sg_mark_end(&sg[block - 1]); | ||
790 | |||
791 | /* Now store the hash into the packet */ | ||
792 | err = crypto_hash_init(desc); | ||
793 | if (err) { | ||
794 | printk(KERN_WARNING "%s(): hash_init failed\n", __func__); | ||
795 | goto clear_hash; | ||
796 | } | ||
797 | err = crypto_hash_update(desc, sg, nbytes); | ||
798 | if (err) { | ||
799 | printk(KERN_WARNING "%s(): hash_update failed\n", __func__); | ||
800 | goto clear_hash; | ||
801 | } | ||
802 | err = crypto_hash_final(desc, md5_hash); | ||
803 | if (err) { | ||
804 | printk(KERN_WARNING "%s(): hash_final failed\n", __func__); | ||
805 | goto clear_hash; | 767 | goto clear_hash; |
806 | } | ||
807 | 768 | ||
808 | /* Reset header, and free up the crypto */ | 769 | /* Free up the crypto pool */ |
809 | tcp_put_md5sig_pool(); | 770 | tcp_put_md5sig_pool(); |
810 | th->check = cksum; | ||
811 | out: | 771 | out: |
812 | return 0; | 772 | return 0; |
813 | clear_hash: | 773 | clear_hash: |
@@ -821,8 +781,7 @@ static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
821 | struct sock *sk, | 781 | struct sock *sk, |
822 | struct dst_entry *dst, | 782 | struct dst_entry *dst, |
823 | struct request_sock *req, | 783 | struct request_sock *req, |
824 | struct tcphdr *th, int protocol, | 784 | struct tcphdr *th, unsigned int tcplen) |
825 | unsigned int tcplen) | ||
826 | { | 785 | { |
827 | struct in6_addr *saddr, *daddr; | 786 | struct in6_addr *saddr, *daddr; |
828 | 787 | ||
@@ -835,7 +794,7 @@ static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
835 | } | 794 | } |
836 | return tcp_v6_do_calc_md5_hash(md5_hash, key, | 795 | return tcp_v6_do_calc_md5_hash(md5_hash, key, |
837 | saddr, daddr, | 796 | saddr, daddr, |
838 | th, protocol, tcplen); | 797 | th, tcplen); |
839 | } | 798 | } |
840 | 799 | ||
841 | static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | 800 | static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) |
@@ -844,43 +803,12 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
844 | struct tcp_md5sig_key *hash_expected; | 803 | struct tcp_md5sig_key *hash_expected; |
845 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 804 | struct ipv6hdr *ip6h = ipv6_hdr(skb); |
846 | struct tcphdr *th = tcp_hdr(skb); | 805 | struct tcphdr *th = tcp_hdr(skb); |
847 | int length = (th->doff << 2) - sizeof (*th); | ||
848 | int genhash; | 806 | int genhash; |
849 | u8 *ptr; | ||
850 | u8 newhash[16]; | 807 | u8 newhash[16]; |
851 | 808 | ||
852 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); | 809 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); |
810 | hash_location = tcp_parse_md5sig_option(th); | ||
853 | 811 | ||
854 | /* If the TCP option is too short, we can short cut */ | ||
855 | if (length < TCPOLEN_MD5SIG) | ||
856 | return hash_expected ? 1 : 0; | ||
857 | |||
858 | /* parse options */ | ||
859 | ptr = (u8*)(th + 1); | ||
860 | while (length > 0) { | ||
861 | int opcode = *ptr++; | ||
862 | int opsize; | ||
863 | |||
864 | switch(opcode) { | ||
865 | case TCPOPT_EOL: | ||
866 | goto done_opts; | ||
867 | case TCPOPT_NOP: | ||
868 | length--; | ||
869 | continue; | ||
870 | default: | ||
871 | opsize = *ptr++; | ||
872 | if (opsize < 2 || opsize > length) | ||
873 | goto done_opts; | ||
874 | if (opcode == TCPOPT_MD5SIG) { | ||
875 | hash_location = ptr; | ||
876 | goto done_opts; | ||
877 | } | ||
878 | } | ||
879 | ptr += opsize - 2; | ||
880 | length -= opsize; | ||
881 | } | ||
882 | |||
883 | done_opts: | ||
884 | /* do we have a hash as expected? */ | 812 | /* do we have a hash as expected? */ |
885 | if (!hash_expected) { | 813 | if (!hash_expected) { |
886 | if (!hash_location) | 814 | if (!hash_location) |
@@ -910,8 +838,7 @@ done_opts: | |||
910 | genhash = tcp_v6_do_calc_md5_hash(newhash, | 838 | genhash = tcp_v6_do_calc_md5_hash(newhash, |
911 | hash_expected, | 839 | hash_expected, |
912 | &ip6h->saddr, &ip6h->daddr, | 840 | &ip6h->saddr, &ip6h->daddr, |
913 | th, sk->sk_protocol, | 841 | th, skb->len); |
914 | skb->len); | ||
915 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | 842 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { |
916 | if (net_ratelimit()) { | 843 | if (net_ratelimit()) { |
917 | printk(KERN_INFO "MD5 Hash %s for " | 844 | printk(KERN_INFO "MD5 Hash %s for " |
@@ -1051,7 +978,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1051 | tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key, | 978 | tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key, |
1052 | &ipv6_hdr(skb)->daddr, | 979 | &ipv6_hdr(skb)->daddr, |
1053 | &ipv6_hdr(skb)->saddr, | 980 | &ipv6_hdr(skb)->saddr, |
1054 | t1, IPPROTO_TCP, tot_len); | 981 | t1, tot_len); |
1055 | } | 982 | } |
1056 | #endif | 983 | #endif |
1057 | 984 | ||
@@ -1088,8 +1015,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1088 | kfree_skb(buff); | 1015 | kfree_skb(buff); |
1089 | } | 1016 | } |
1090 | 1017 | ||
1091 | static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | 1018 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, |
1092 | struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) | 1019 | struct tcp_md5sig_key *key) |
1093 | { | 1020 | { |
1094 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1021 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1095 | struct sk_buff *buff; | 1022 | struct sk_buff *buff; |
@@ -1098,22 +1025,6 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1098 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 1025 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
1099 | unsigned int tot_len = sizeof(struct tcphdr); | 1026 | unsigned int tot_len = sizeof(struct tcphdr); |
1100 | __be32 *topt; | 1027 | __be32 *topt; |
1101 | #ifdef CONFIG_TCP_MD5SIG | ||
1102 | struct tcp_md5sig_key *key; | ||
1103 | struct tcp_md5sig_key tw_key; | ||
1104 | #endif | ||
1105 | |||
1106 | #ifdef CONFIG_TCP_MD5SIG | ||
1107 | if (!tw && skb->sk) { | ||
1108 | key = tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr); | ||
1109 | } else if (tw && tw->tw_md5_keylen) { | ||
1110 | tw_key.key = tw->tw_md5_key; | ||
1111 | tw_key.keylen = tw->tw_md5_keylen; | ||
1112 | key = &tw_key; | ||
1113 | } else { | ||
1114 | key = NULL; | ||
1115 | } | ||
1116 | #endif | ||
1117 | 1028 | ||
1118 | if (ts) | 1029 | if (ts) |
1119 | tot_len += TCPOLEN_TSTAMP_ALIGNED; | 1030 | tot_len += TCPOLEN_TSTAMP_ALIGNED; |
@@ -1157,7 +1068,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1157 | tcp_v6_do_calc_md5_hash((__u8 *)topt, key, | 1068 | tcp_v6_do_calc_md5_hash((__u8 *)topt, key, |
1158 | &ipv6_hdr(skb)->daddr, | 1069 | &ipv6_hdr(skb)->daddr, |
1159 | &ipv6_hdr(skb)->saddr, | 1070 | &ipv6_hdr(skb)->saddr, |
1160 | t1, IPPROTO_TCP, tot_len); | 1071 | t1, tot_len); |
1161 | } | 1072 | } |
1162 | #endif | 1073 | #endif |
1163 | 1074 | ||
@@ -1193,16 +1104,17 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
1193 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1104 | struct inet_timewait_sock *tw = inet_twsk(sk); |
1194 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 1105 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
1195 | 1106 | ||
1196 | tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 1107 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
1197 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 1108 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
1198 | tcptw->tw_ts_recent); | 1109 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw)); |
1199 | 1110 | ||
1200 | inet_twsk_put(tw); | 1111 | inet_twsk_put(tw); |
1201 | } | 1112 | } |
1202 | 1113 | ||
1203 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | 1114 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) |
1204 | { | 1115 | { |
1205 | tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); | 1116 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, |
1117 | tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr)); | ||
1206 | } | 1118 | } |
1207 | 1119 | ||
1208 | 1120 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index dd309626ae9a..e0693fffc9bd 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * | 7 | * |
8 | * Based on linux/ipv4/udp.c | 8 | * Based on linux/ipv4/udp.c |
9 | * | 9 | * |
10 | * $Id: udp.c,v 1.65 2002/02/01 22:01:04 davem Exp $ | ||
11 | * | ||
12 | * Fixes: | 10 | * Fixes: |
13 | * Hideaki YOSHIFUJI : sin6_scope_id support | 11 | * Hideaki YOSHIFUJI : sin6_scope_id support |
14 | * YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which | 12 | * YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which |
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 491efd00a866..f6cdcb348e05 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
@@ -2,8 +2,6 @@ | |||
2 | * UDPLITEv6 An implementation of the UDP-Lite protocol over IPv6. | 2 | * UDPLITEv6 An implementation of the UDP-Lite protocol over IPv6. |
3 | * See also net/ipv4/udplite.c | 3 | * See also net/ipv4/udplite.c |
4 | * | 4 | * |
5 | * Version: $Id: udplite.c,v 1.9 2006/10/19 08:28:10 gerrit Exp $ | ||
6 | * | ||
7 | * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk> | 5 | * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk> |
8 | * | 6 | * |
9 | * Changes: | 7 | * Changes: |
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index e0eab5927c4f..f6e54fa97f47 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c | |||
@@ -628,8 +628,8 @@ dev_irnet_poll(struct file * file, | |||
628 | * This is the way pppd configure us and control us while the PPP | 628 | * This is the way pppd configure us and control us while the PPP |
629 | * instance is active. | 629 | * instance is active. |
630 | */ | 630 | */ |
631 | static int | 631 | static long |
632 | dev_irnet_ioctl(struct inode * inode, | 632 | dev_irnet_ioctl( |
633 | struct file * file, | 633 | struct file * file, |
634 | unsigned int cmd, | 634 | unsigned int cmd, |
635 | unsigned long arg) | 635 | unsigned long arg) |
@@ -660,6 +660,7 @@ dev_irnet_ioctl(struct inode * inode, | |||
660 | { | 660 | { |
661 | DEBUG(FS_INFO, "Entering PPP discipline.\n"); | 661 | DEBUG(FS_INFO, "Entering PPP discipline.\n"); |
662 | /* PPP channel setup (ap->chan in configued in dev_irnet_open())*/ | 662 | /* PPP channel setup (ap->chan in configued in dev_irnet_open())*/ |
663 | lock_kernel(); | ||
663 | err = ppp_register_channel(&ap->chan); | 664 | err = ppp_register_channel(&ap->chan); |
664 | if(err == 0) | 665 | if(err == 0) |
665 | { | 666 | { |
@@ -672,12 +673,14 @@ dev_irnet_ioctl(struct inode * inode, | |||
672 | } | 673 | } |
673 | else | 674 | else |
674 | DERROR(FS_ERROR, "Can't setup PPP channel...\n"); | 675 | DERROR(FS_ERROR, "Can't setup PPP channel...\n"); |
676 | unlock_kernel(); | ||
675 | } | 677 | } |
676 | else | 678 | else |
677 | { | 679 | { |
678 | /* In theory, should be N_TTY */ | 680 | /* In theory, should be N_TTY */ |
679 | DEBUG(FS_INFO, "Exiting PPP discipline.\n"); | 681 | DEBUG(FS_INFO, "Exiting PPP discipline.\n"); |
680 | /* Disconnect from the generic PPP layer */ | 682 | /* Disconnect from the generic PPP layer */ |
683 | lock_kernel(); | ||
681 | if(ap->ppp_open) | 684 | if(ap->ppp_open) |
682 | { | 685 | { |
683 | ap->ppp_open = 0; | 686 | ap->ppp_open = 0; |
@@ -686,24 +689,20 @@ dev_irnet_ioctl(struct inode * inode, | |||
686 | else | 689 | else |
687 | DERROR(FS_ERROR, "Channel not registered !\n"); | 690 | DERROR(FS_ERROR, "Channel not registered !\n"); |
688 | err = 0; | 691 | err = 0; |
692 | unlock_kernel(); | ||
689 | } | 693 | } |
690 | break; | 694 | break; |
691 | 695 | ||
692 | /* Query PPP channel and unit number */ | 696 | /* Query PPP channel and unit number */ |
693 | case PPPIOCGCHAN: | 697 | case PPPIOCGCHAN: |
694 | if(!ap->ppp_open) | 698 | if(ap->ppp_open && !put_user(ppp_channel_index(&ap->chan), |
695 | break; | 699 | (int __user *)argp)) |
696 | if(put_user(ppp_channel_index(&ap->chan), (int __user *)argp)) | 700 | err = 0; |
697 | break; | ||
698 | DEBUG(FS_INFO, "Query channel.\n"); | ||
699 | err = 0; | ||
700 | break; | 701 | break; |
701 | case PPPIOCGUNIT: | 702 | case PPPIOCGUNIT: |
702 | if(!ap->ppp_open) | 703 | lock_kernel(); |
703 | break; | 704 | if(ap->ppp_open && !put_user(ppp_unit_number(&ap->chan), |
704 | if(put_user(ppp_unit_number(&ap->chan), (int __user *)argp)) | 705 | (int __user *)argp)) |
705 | break; | ||
706 | DEBUG(FS_INFO, "Query unit number.\n"); | ||
707 | err = 0; | 706 | err = 0; |
708 | break; | 707 | break; |
709 | 708 | ||
@@ -723,34 +722,39 @@ dev_irnet_ioctl(struct inode * inode, | |||
723 | DEBUG(FS_INFO, "Standard PPP ioctl.\n"); | 722 | DEBUG(FS_INFO, "Standard PPP ioctl.\n"); |
724 | if(!capable(CAP_NET_ADMIN)) | 723 | if(!capable(CAP_NET_ADMIN)) |
725 | err = -EPERM; | 724 | err = -EPERM; |
726 | else | 725 | else { |
726 | lock_kernel(); | ||
727 | err = ppp_irnet_ioctl(&ap->chan, cmd, arg); | 727 | err = ppp_irnet_ioctl(&ap->chan, cmd, arg); |
728 | unlock_kernel(); | ||
729 | } | ||
728 | break; | 730 | break; |
729 | 731 | ||
730 | /* TTY IOCTLs : Pretend that we are a tty, to keep pppd happy */ | 732 | /* TTY IOCTLs : Pretend that we are a tty, to keep pppd happy */ |
731 | /* Get termios */ | 733 | /* Get termios */ |
732 | case TCGETS: | 734 | case TCGETS: |
733 | DEBUG(FS_INFO, "Get termios.\n"); | 735 | DEBUG(FS_INFO, "Get termios.\n"); |
736 | lock_kernel(); | ||
734 | #ifndef TCGETS2 | 737 | #ifndef TCGETS2 |
735 | if(kernel_termios_to_user_termios((struct termios __user *)argp, &ap->termios)) | 738 | if(!kernel_termios_to_user_termios((struct termios __user *)argp, &ap->termios)) |
736 | break; | 739 | err = 0; |
737 | #else | 740 | #else |
738 | if(kernel_termios_to_user_termios_1((struct termios __user *)argp, &ap->termios)) | 741 | if(kernel_termios_to_user_termios_1((struct termios __user *)argp, &ap->termios)) |
739 | break; | 742 | err = 0; |
740 | #endif | 743 | #endif |
741 | err = 0; | 744 | unlock_kernel(); |
742 | break; | 745 | break; |
743 | /* Set termios */ | 746 | /* Set termios */ |
744 | case TCSETSF: | 747 | case TCSETSF: |
745 | DEBUG(FS_INFO, "Set termios.\n"); | 748 | DEBUG(FS_INFO, "Set termios.\n"); |
749 | lock_kernel(); | ||
746 | #ifndef TCGETS2 | 750 | #ifndef TCGETS2 |
747 | if(user_termios_to_kernel_termios(&ap->termios, (struct termios __user *)argp)) | 751 | if(!user_termios_to_kernel_termios(&ap->termios, (struct termios __user *)argp)) |
748 | break; | 752 | err = 0; |
749 | #else | 753 | #else |
750 | if(user_termios_to_kernel_termios_1(&ap->termios, (struct termios __user *)argp)) | 754 | if(!user_termios_to_kernel_termios_1(&ap->termios, (struct termios __user *)argp)) |
751 | break; | 755 | err = 0; |
752 | #endif | 756 | #endif |
753 | err = 0; | 757 | unlock_kernel(); |
754 | break; | 758 | break; |
755 | 759 | ||
756 | /* Set DTR/RTS */ | 760 | /* Set DTR/RTS */ |
@@ -773,7 +777,9 @@ dev_irnet_ioctl(struct inode * inode, | |||
773 | * We should also worry that we don't accept junk here and that | 777 | * We should also worry that we don't accept junk here and that |
774 | * we get rid of our own buffers */ | 778 | * we get rid of our own buffers */ |
775 | #ifdef FLUSH_TO_PPP | 779 | #ifdef FLUSH_TO_PPP |
780 | lock_kernel(); | ||
776 | ppp_output_wakeup(&ap->chan); | 781 | ppp_output_wakeup(&ap->chan); |
782 | unlock_kernel(); | ||
777 | #endif /* FLUSH_TO_PPP */ | 783 | #endif /* FLUSH_TO_PPP */ |
778 | err = 0; | 784 | err = 0; |
779 | break; | 785 | break; |
@@ -788,7 +794,7 @@ dev_irnet_ioctl(struct inode * inode, | |||
788 | 794 | ||
789 | default: | 795 | default: |
790 | DERROR(FS_ERROR, "Unsupported ioctl (0x%X)\n", cmd); | 796 | DERROR(FS_ERROR, "Unsupported ioctl (0x%X)\n", cmd); |
791 | err = -ENOIOCTLCMD; | 797 | err = -ENOTTY; |
792 | } | 798 | } |
793 | 799 | ||
794 | DEXIT(FS_TRACE, " - err = 0x%X\n", err); | 800 | DEXIT(FS_TRACE, " - err = 0x%X\n", err); |
diff --git a/net/irda/irnet/irnet_ppp.h b/net/irda/irnet/irnet_ppp.h index d2beb7df8f7f..d9f8bd4ebd05 100644 --- a/net/irda/irnet/irnet_ppp.h +++ b/net/irda/irnet/irnet_ppp.h | |||
@@ -76,9 +76,8 @@ static ssize_t | |||
76 | static unsigned int | 76 | static unsigned int |
77 | dev_irnet_poll(struct file *, | 77 | dev_irnet_poll(struct file *, |
78 | poll_table *); | 78 | poll_table *); |
79 | static int | 79 | static long |
80 | dev_irnet_ioctl(struct inode *, | 80 | dev_irnet_ioctl(struct file *, |
81 | struct file *, | ||
82 | unsigned int, | 81 | unsigned int, |
83 | unsigned long); | 82 | unsigned long); |
84 | /* ------------------------ PPP INTERFACE ------------------------ */ | 83 | /* ------------------------ PPP INTERFACE ------------------------ */ |
@@ -102,7 +101,7 @@ static struct file_operations irnet_device_fops = | |||
102 | .read = dev_irnet_read, | 101 | .read = dev_irnet_read, |
103 | .write = dev_irnet_write, | 102 | .write = dev_irnet_write, |
104 | .poll = dev_irnet_poll, | 103 | .poll = dev_irnet_poll, |
105 | .ioctl = dev_irnet_ioctl, | 104 | .unlocked_ioctl = dev_irnet_ioctl, |
106 | .open = dev_irnet_open, | 105 | .open = dev_irnet_open, |
107 | .release = dev_irnet_close | 106 | .release = dev_irnet_close |
108 | /* Also : llseek, readdir, mmap, flush, fsync, fasync, lock, readv, writev */ | 107 | /* Also : llseek, readdir, mmap, flush, fsync, fasync, lock, readv, writev */ |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 7b0038f45b16..58e4aee3e696 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -644,6 +644,7 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
644 | } | 644 | } |
645 | 645 | ||
646 | txmsg.class = 0; | 646 | txmsg.class = 0; |
647 | memcpy(&txmsg.class, skb->data, skb->len >= 4 ? 4 : skb->len); | ||
647 | txmsg.tag = iucv->send_tag++; | 648 | txmsg.tag = iucv->send_tag++; |
648 | memcpy(skb->cb, &txmsg.tag, 4); | 649 | memcpy(skb->cb, &txmsg.tag, 4); |
649 | skb_queue_tail(&iucv->send_skb_q, skb); | 650 | skb_queue_tail(&iucv->send_skb_q, skb); |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 918970762131..531a206ce7a6 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -474,14 +474,14 @@ static void iucv_setmask_mp(void) | |||
474 | { | 474 | { |
475 | int cpu; | 475 | int cpu; |
476 | 476 | ||
477 | preempt_disable(); | 477 | get_online_cpus(); |
478 | for_each_online_cpu(cpu) | 478 | for_each_online_cpu(cpu) |
479 | /* Enable all cpus with a declared buffer. */ | 479 | /* Enable all cpus with a declared buffer. */ |
480 | if (cpu_isset(cpu, iucv_buffer_cpumask) && | 480 | if (cpu_isset(cpu, iucv_buffer_cpumask) && |
481 | !cpu_isset(cpu, iucv_irq_cpumask)) | 481 | !cpu_isset(cpu, iucv_irq_cpumask)) |
482 | smp_call_function_single(cpu, iucv_allow_cpu, | 482 | smp_call_function_single(cpu, iucv_allow_cpu, |
483 | NULL, 0, 1); | 483 | NULL, 0, 1); |
484 | preempt_enable(); | 484 | put_online_cpus(); |
485 | } | 485 | } |
486 | 486 | ||
487 | /** | 487 | /** |
@@ -521,16 +521,17 @@ static int iucv_enable(void) | |||
521 | goto out; | 521 | goto out; |
522 | /* Declare per cpu buffers. */ | 522 | /* Declare per cpu buffers. */ |
523 | rc = -EIO; | 523 | rc = -EIO; |
524 | preempt_disable(); | 524 | get_online_cpus(); |
525 | for_each_online_cpu(cpu) | 525 | for_each_online_cpu(cpu) |
526 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 0, 1); | 526 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 0, 1); |
527 | preempt_enable(); | ||
528 | if (cpus_empty(iucv_buffer_cpumask)) | 527 | if (cpus_empty(iucv_buffer_cpumask)) |
529 | /* No cpu could declare an iucv buffer. */ | 528 | /* No cpu could declare an iucv buffer. */ |
530 | goto out_path; | 529 | goto out_path; |
530 | put_online_cpus(); | ||
531 | return 0; | 531 | return 0; |
532 | 532 | ||
533 | out_path: | 533 | out_path: |
534 | put_online_cpus(); | ||
534 | kfree(iucv_path_table); | 535 | kfree(iucv_path_table); |
535 | out: | 536 | out: |
536 | return rc; | 537 | return rc; |
@@ -545,7 +546,9 @@ out: | |||
545 | */ | 546 | */ |
546 | static void iucv_disable(void) | 547 | static void iucv_disable(void) |
547 | { | 548 | { |
549 | get_online_cpus(); | ||
548 | on_each_cpu(iucv_retrieve_cpu, NULL, 0, 1); | 550 | on_each_cpu(iucv_retrieve_cpu, NULL, 0, 1); |
551 | put_online_cpus(); | ||
549 | kfree(iucv_path_table); | 552 | kfree(iucv_path_table); |
550 | } | 553 | } |
551 | 554 | ||
@@ -598,7 +601,7 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, | |||
598 | return NOTIFY_OK; | 601 | return NOTIFY_OK; |
599 | } | 602 | } |
600 | 603 | ||
601 | static struct notifier_block __cpuinitdata iucv_cpu_notifier = { | 604 | static struct notifier_block __refdata iucv_cpu_notifier = { |
602 | .notifier_call = iucv_cpu_notify, | 605 | .notifier_call = iucv_cpu_notify, |
603 | }; | 606 | }; |
604 | 607 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index 7470e367272b..f0fc46c8038d 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -579,25 +579,43 @@ static uint8_t pfkey_proto_from_xfrm(uint8_t proto) | |||
579 | return (proto ? proto : IPSEC_PROTO_ANY); | 579 | return (proto ? proto : IPSEC_PROTO_ANY); |
580 | } | 580 | } |
581 | 581 | ||
582 | static int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, | 582 | static inline int pfkey_sockaddr_len(sa_family_t family) |
583 | xfrm_address_t *xaddr) | ||
584 | { | 583 | { |
585 | switch (((struct sockaddr*)(addr + 1))->sa_family) { | 584 | switch (family) { |
585 | case AF_INET: | ||
586 | return sizeof(struct sockaddr_in); | ||
587 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
588 | case AF_INET6: | ||
589 | return sizeof(struct sockaddr_in6); | ||
590 | #endif | ||
591 | } | ||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static | ||
596 | int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr) | ||
597 | { | ||
598 | switch (sa->sa_family) { | ||
586 | case AF_INET: | 599 | case AF_INET: |
587 | xaddr->a4 = | 600 | xaddr->a4 = |
588 | ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr; | 601 | ((struct sockaddr_in *)sa)->sin_addr.s_addr; |
589 | return AF_INET; | 602 | return AF_INET; |
590 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 603 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
591 | case AF_INET6: | 604 | case AF_INET6: |
592 | memcpy(xaddr->a6, | 605 | memcpy(xaddr->a6, |
593 | &((struct sockaddr_in6 *)(addr + 1))->sin6_addr, | 606 | &((struct sockaddr_in6 *)sa)->sin6_addr, |
594 | sizeof(struct in6_addr)); | 607 | sizeof(struct in6_addr)); |
595 | return AF_INET6; | 608 | return AF_INET6; |
596 | #endif | 609 | #endif |
597 | default: | ||
598 | return 0; | ||
599 | } | 610 | } |
600 | /* NOTREACHED */ | 611 | return 0; |
612 | } | ||
613 | |||
614 | static | ||
615 | int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, xfrm_address_t *xaddr) | ||
616 | { | ||
617 | return pfkey_sockaddr_extract((struct sockaddr *)(addr + 1), | ||
618 | xaddr); | ||
601 | } | 619 | } |
602 | 620 | ||
603 | static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs) | 621 | static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs) |
@@ -642,20 +660,11 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void ** | |||
642 | } | 660 | } |
643 | 661 | ||
644 | #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) | 662 | #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) |
663 | |||
645 | static int | 664 | static int |
646 | pfkey_sockaddr_size(sa_family_t family) | 665 | pfkey_sockaddr_size(sa_family_t family) |
647 | { | 666 | { |
648 | switch (family) { | 667 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family)); |
649 | case AF_INET: | ||
650 | return PFKEY_ALIGN8(sizeof(struct sockaddr_in)); | ||
651 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
652 | case AF_INET6: | ||
653 | return PFKEY_ALIGN8(sizeof(struct sockaddr_in6)); | ||
654 | #endif | ||
655 | default: | ||
656 | return 0; | ||
657 | } | ||
658 | /* NOTREACHED */ | ||
659 | } | 668 | } |
660 | 669 | ||
661 | static inline int pfkey_mode_from_xfrm(int mode) | 670 | static inline int pfkey_mode_from_xfrm(int mode) |
@@ -687,6 +696,36 @@ static inline int pfkey_mode_to_xfrm(int mode) | |||
687 | } | 696 | } |
688 | } | 697 | } |
689 | 698 | ||
699 | static unsigned int pfkey_sockaddr_fill(xfrm_address_t *xaddr, __be16 port, | ||
700 | struct sockaddr *sa, | ||
701 | unsigned short family) | ||
702 | { | ||
703 | switch (family) { | ||
704 | case AF_INET: | ||
705 | { | ||
706 | struct sockaddr_in *sin = (struct sockaddr_in *)sa; | ||
707 | sin->sin_family = AF_INET; | ||
708 | sin->sin_port = port; | ||
709 | sin->sin_addr.s_addr = xaddr->a4; | ||
710 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
711 | return 32; | ||
712 | } | ||
713 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
714 | case AF_INET6: | ||
715 | { | ||
716 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; | ||
717 | sin6->sin6_family = AF_INET6; | ||
718 | sin6->sin6_port = port; | ||
719 | sin6->sin6_flowinfo = 0; | ||
720 | ipv6_addr_copy(&sin6->sin6_addr, (struct in6_addr *)xaddr->a6); | ||
721 | sin6->sin6_scope_id = 0; | ||
722 | return 128; | ||
723 | } | ||
724 | #endif | ||
725 | } | ||
726 | return 0; | ||
727 | } | ||
728 | |||
690 | static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | 729 | static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, |
691 | int add_keys, int hsc) | 730 | int add_keys, int hsc) |
692 | { | 731 | { |
@@ -697,13 +736,9 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | |||
697 | struct sadb_address *addr; | 736 | struct sadb_address *addr; |
698 | struct sadb_key *key; | 737 | struct sadb_key *key; |
699 | struct sadb_x_sa2 *sa2; | 738 | struct sadb_x_sa2 *sa2; |
700 | struct sockaddr_in *sin; | ||
701 | struct sadb_x_sec_ctx *sec_ctx; | 739 | struct sadb_x_sec_ctx *sec_ctx; |
702 | struct xfrm_sec_ctx *xfrm_ctx; | 740 | struct xfrm_sec_ctx *xfrm_ctx; |
703 | int ctx_size = 0; | 741 | int ctx_size = 0; |
704 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
705 | struct sockaddr_in6 *sin6; | ||
706 | #endif | ||
707 | int size; | 742 | int size; |
708 | int auth_key_size = 0; | 743 | int auth_key_size = 0; |
709 | int encrypt_key_size = 0; | 744 | int encrypt_key_size = 0; |
@@ -732,14 +767,7 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | |||
732 | } | 767 | } |
733 | 768 | ||
734 | /* identity & sensitivity */ | 769 | /* identity & sensitivity */ |
735 | 770 | if (xfrm_addr_cmp(&x->sel.saddr, &x->props.saddr, x->props.family)) | |
736 | if ((x->props.family == AF_INET && | ||
737 | x->sel.saddr.a4 != x->props.saddr.a4) | ||
738 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
739 | || (x->props.family == AF_INET6 && | ||
740 | memcmp (x->sel.saddr.a6, x->props.saddr.a6, sizeof (struct in6_addr))) | ||
741 | #endif | ||
742 | ) | ||
743 | size += sizeof(struct sadb_address) + sockaddr_size; | 771 | size += sizeof(struct sadb_address) + sockaddr_size; |
744 | 772 | ||
745 | if (add_keys) { | 773 | if (add_keys) { |
@@ -861,29 +889,12 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | |||
861 | protocol's number." - RFC2367 */ | 889 | protocol's number." - RFC2367 */ |
862 | addr->sadb_address_proto = 0; | 890 | addr->sadb_address_proto = 0; |
863 | addr->sadb_address_reserved = 0; | 891 | addr->sadb_address_reserved = 0; |
864 | if (x->props.family == AF_INET) { | ||
865 | addr->sadb_address_prefixlen = 32; | ||
866 | 892 | ||
867 | sin = (struct sockaddr_in *) (addr + 1); | 893 | addr->sadb_address_prefixlen = |
868 | sin->sin_family = AF_INET; | 894 | pfkey_sockaddr_fill(&x->props.saddr, 0, |
869 | sin->sin_addr.s_addr = x->props.saddr.a4; | 895 | (struct sockaddr *) (addr + 1), |
870 | sin->sin_port = 0; | 896 | x->props.family); |
871 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | 897 | if (!addr->sadb_address_prefixlen) |
872 | } | ||
873 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
874 | else if (x->props.family == AF_INET6) { | ||
875 | addr->sadb_address_prefixlen = 128; | ||
876 | |||
877 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
878 | sin6->sin6_family = AF_INET6; | ||
879 | sin6->sin6_port = 0; | ||
880 | sin6->sin6_flowinfo = 0; | ||
881 | memcpy(&sin6->sin6_addr, x->props.saddr.a6, | ||
882 | sizeof(struct in6_addr)); | ||
883 | sin6->sin6_scope_id = 0; | ||
884 | } | ||
885 | #endif | ||
886 | else | ||
887 | BUG(); | 898 | BUG(); |
888 | 899 | ||
889 | /* dst address */ | 900 | /* dst address */ |
@@ -894,70 +905,32 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | |||
894 | sizeof(uint64_t); | 905 | sizeof(uint64_t); |
895 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 906 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; |
896 | addr->sadb_address_proto = 0; | 907 | addr->sadb_address_proto = 0; |
897 | addr->sadb_address_prefixlen = 32; /* XXX */ | ||
898 | addr->sadb_address_reserved = 0; | 908 | addr->sadb_address_reserved = 0; |
899 | if (x->props.family == AF_INET) { | ||
900 | sin = (struct sockaddr_in *) (addr + 1); | ||
901 | sin->sin_family = AF_INET; | ||
902 | sin->sin_addr.s_addr = x->id.daddr.a4; | ||
903 | sin->sin_port = 0; | ||
904 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
905 | 909 | ||
906 | if (x->sel.saddr.a4 != x->props.saddr.a4) { | 910 | addr->sadb_address_prefixlen = |
907 | addr = (struct sadb_address*) skb_put(skb, | 911 | pfkey_sockaddr_fill(&x->id.daddr, 0, |
908 | sizeof(struct sadb_address)+sockaddr_size); | 912 | (struct sockaddr *) (addr + 1), |
909 | addr->sadb_address_len = | 913 | x->props.family); |
910 | (sizeof(struct sadb_address)+sockaddr_size)/ | 914 | if (!addr->sadb_address_prefixlen) |
911 | sizeof(uint64_t); | 915 | BUG(); |
912 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; | ||
913 | addr->sadb_address_proto = | ||
914 | pfkey_proto_from_xfrm(x->sel.proto); | ||
915 | addr->sadb_address_prefixlen = x->sel.prefixlen_s; | ||
916 | addr->sadb_address_reserved = 0; | ||
917 | |||
918 | sin = (struct sockaddr_in *) (addr + 1); | ||
919 | sin->sin_family = AF_INET; | ||
920 | sin->sin_addr.s_addr = x->sel.saddr.a4; | ||
921 | sin->sin_port = x->sel.sport; | ||
922 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
923 | } | ||
924 | } | ||
925 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
926 | else if (x->props.family == AF_INET6) { | ||
927 | addr->sadb_address_prefixlen = 128; | ||
928 | 916 | ||
929 | sin6 = (struct sockaddr_in6 *) (addr + 1); | 917 | if (xfrm_addr_cmp(&x->sel.saddr, &x->props.saddr, |
930 | sin6->sin6_family = AF_INET6; | 918 | x->props.family)) { |
931 | sin6->sin6_port = 0; | 919 | addr = (struct sadb_address*) skb_put(skb, |
932 | sin6->sin6_flowinfo = 0; | 920 | sizeof(struct sadb_address)+sockaddr_size); |
933 | memcpy(&sin6->sin6_addr, x->id.daddr.a6, sizeof(struct in6_addr)); | 921 | addr->sadb_address_len = |
934 | sin6->sin6_scope_id = 0; | 922 | (sizeof(struct sadb_address)+sockaddr_size)/ |
923 | sizeof(uint64_t); | ||
924 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; | ||
925 | addr->sadb_address_proto = | ||
926 | pfkey_proto_from_xfrm(x->sel.proto); | ||
927 | addr->sadb_address_prefixlen = x->sel.prefixlen_s; | ||
928 | addr->sadb_address_reserved = 0; | ||
935 | 929 | ||
936 | if (memcmp (x->sel.saddr.a6, x->props.saddr.a6, | 930 | pfkey_sockaddr_fill(&x->sel.saddr, x->sel.sport, |
937 | sizeof(struct in6_addr))) { | 931 | (struct sockaddr *) (addr + 1), |
938 | addr = (struct sadb_address *) skb_put(skb, | 932 | x->props.family); |
939 | sizeof(struct sadb_address)+sockaddr_size); | ||
940 | addr->sadb_address_len = | ||
941 | (sizeof(struct sadb_address)+sockaddr_size)/ | ||
942 | sizeof(uint64_t); | ||
943 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; | ||
944 | addr->sadb_address_proto = | ||
945 | pfkey_proto_from_xfrm(x->sel.proto); | ||
946 | addr->sadb_address_prefixlen = x->sel.prefixlen_s; | ||
947 | addr->sadb_address_reserved = 0; | ||
948 | |||
949 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
950 | sin6->sin6_family = AF_INET6; | ||
951 | sin6->sin6_port = x->sel.sport; | ||
952 | sin6->sin6_flowinfo = 0; | ||
953 | memcpy(&sin6->sin6_addr, x->sel.saddr.a6, | ||
954 | sizeof(struct in6_addr)); | ||
955 | sin6->sin6_scope_id = 0; | ||
956 | } | ||
957 | } | 933 | } |
958 | #endif | ||
959 | else | ||
960 | BUG(); | ||
961 | 934 | ||
962 | /* auth key */ | 935 | /* auth key */ |
963 | if (add_keys && auth_key_size) { | 936 | if (add_keys && auth_key_size) { |
@@ -1853,10 +1826,6 @@ static int | |||
1853 | parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | 1826 | parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) |
1854 | { | 1827 | { |
1855 | struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr; | 1828 | struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr; |
1856 | struct sockaddr_in *sin; | ||
1857 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1858 | struct sockaddr_in6 *sin6; | ||
1859 | #endif | ||
1860 | int mode; | 1829 | int mode; |
1861 | 1830 | ||
1862 | if (xp->xfrm_nr >= XFRM_MAX_DEPTH) | 1831 | if (xp->xfrm_nr >= XFRM_MAX_DEPTH) |
@@ -1881,31 +1850,19 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | |||
1881 | 1850 | ||
1882 | /* addresses present only in tunnel mode */ | 1851 | /* addresses present only in tunnel mode */ |
1883 | if (t->mode == XFRM_MODE_TUNNEL) { | 1852 | if (t->mode == XFRM_MODE_TUNNEL) { |
1884 | struct sockaddr *sa; | 1853 | u8 *sa = (u8 *) (rq + 1); |
1885 | sa = (struct sockaddr *)(rq+1); | 1854 | int family, socklen; |
1886 | switch(sa->sa_family) { | 1855 | |
1887 | case AF_INET: | 1856 | family = pfkey_sockaddr_extract((struct sockaddr *)sa, |
1888 | sin = (struct sockaddr_in*)sa; | 1857 | &t->saddr); |
1889 | t->saddr.a4 = sin->sin_addr.s_addr; | 1858 | if (!family) |
1890 | sin++; | ||
1891 | if (sin->sin_family != AF_INET) | ||
1892 | return -EINVAL; | ||
1893 | t->id.daddr.a4 = sin->sin_addr.s_addr; | ||
1894 | break; | ||
1895 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1896 | case AF_INET6: | ||
1897 | sin6 = (struct sockaddr_in6*)sa; | ||
1898 | memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); | ||
1899 | sin6++; | ||
1900 | if (sin6->sin6_family != AF_INET6) | ||
1901 | return -EINVAL; | ||
1902 | memcpy(t->id.daddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); | ||
1903 | break; | ||
1904 | #endif | ||
1905 | default: | ||
1906 | return -EINVAL; | 1859 | return -EINVAL; |
1907 | } | 1860 | |
1908 | t->encap_family = sa->sa_family; | 1861 | socklen = pfkey_sockaddr_len(family); |
1862 | if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen), | ||
1863 | &t->id.daddr) != family) | ||
1864 | return -EINVAL; | ||
1865 | t->encap_family = family; | ||
1909 | } else | 1866 | } else |
1910 | t->encap_family = xp->family; | 1867 | t->encap_family = xp->family; |
1911 | 1868 | ||
@@ -1952,9 +1909,7 @@ static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) | |||
1952 | 1909 | ||
1953 | for (i=0; i<xp->xfrm_nr; i++) { | 1910 | for (i=0; i<xp->xfrm_nr; i++) { |
1954 | t = xp->xfrm_vec + i; | 1911 | t = xp->xfrm_vec + i; |
1955 | socklen += (t->encap_family == AF_INET ? | 1912 | socklen += pfkey_sockaddr_len(t->encap_family); |
1956 | sizeof(struct sockaddr_in) : | ||
1957 | sizeof(struct sockaddr_in6)); | ||
1958 | } | 1913 | } |
1959 | 1914 | ||
1960 | return sizeof(struct sadb_msg) + | 1915 | return sizeof(struct sadb_msg) + |
@@ -1987,18 +1942,12 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
1987 | struct sadb_address *addr; | 1942 | struct sadb_address *addr; |
1988 | struct sadb_lifetime *lifetime; | 1943 | struct sadb_lifetime *lifetime; |
1989 | struct sadb_x_policy *pol; | 1944 | struct sadb_x_policy *pol; |
1990 | struct sockaddr_in *sin; | ||
1991 | struct sadb_x_sec_ctx *sec_ctx; | 1945 | struct sadb_x_sec_ctx *sec_ctx; |
1992 | struct xfrm_sec_ctx *xfrm_ctx; | 1946 | struct xfrm_sec_ctx *xfrm_ctx; |
1993 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1994 | struct sockaddr_in6 *sin6; | ||
1995 | #endif | ||
1996 | int i; | 1947 | int i; |
1997 | int size; | 1948 | int size; |
1998 | int sockaddr_size = pfkey_sockaddr_size(xp->family); | 1949 | int sockaddr_size = pfkey_sockaddr_size(xp->family); |
1999 | int socklen = (xp->family == AF_INET ? | 1950 | int socklen = pfkey_sockaddr_len(xp->family); |
2000 | sizeof(struct sockaddr_in) : | ||
2001 | sizeof(struct sockaddr_in6)); | ||
2002 | 1951 | ||
2003 | size = pfkey_xfrm_policy2msg_size(xp); | 1952 | size = pfkey_xfrm_policy2msg_size(xp); |
2004 | 1953 | ||
@@ -2016,26 +1965,10 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
2016 | addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto); | 1965 | addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto); |
2017 | addr->sadb_address_prefixlen = xp->selector.prefixlen_s; | 1966 | addr->sadb_address_prefixlen = xp->selector.prefixlen_s; |
2018 | addr->sadb_address_reserved = 0; | 1967 | addr->sadb_address_reserved = 0; |
2019 | /* src address */ | 1968 | if (!pfkey_sockaddr_fill(&xp->selector.saddr, |
2020 | if (xp->family == AF_INET) { | 1969 | xp->selector.sport, |
2021 | sin = (struct sockaddr_in *) (addr + 1); | 1970 | (struct sockaddr *) (addr + 1), |
2022 | sin->sin_family = AF_INET; | 1971 | xp->family)) |
2023 | sin->sin_addr.s_addr = xp->selector.saddr.a4; | ||
2024 | sin->sin_port = xp->selector.sport; | ||
2025 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
2026 | } | ||
2027 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2028 | else if (xp->family == AF_INET6) { | ||
2029 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
2030 | sin6->sin6_family = AF_INET6; | ||
2031 | sin6->sin6_port = xp->selector.sport; | ||
2032 | sin6->sin6_flowinfo = 0; | ||
2033 | memcpy(&sin6->sin6_addr, xp->selector.saddr.a6, | ||
2034 | sizeof(struct in6_addr)); | ||
2035 | sin6->sin6_scope_id = 0; | ||
2036 | } | ||
2037 | #endif | ||
2038 | else | ||
2039 | BUG(); | 1972 | BUG(); |
2040 | 1973 | ||
2041 | /* dst address */ | 1974 | /* dst address */ |
@@ -2048,26 +1981,10 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
2048 | addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto); | 1981 | addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto); |
2049 | addr->sadb_address_prefixlen = xp->selector.prefixlen_d; | 1982 | addr->sadb_address_prefixlen = xp->selector.prefixlen_d; |
2050 | addr->sadb_address_reserved = 0; | 1983 | addr->sadb_address_reserved = 0; |
2051 | if (xp->family == AF_INET) { | 1984 | |
2052 | sin = (struct sockaddr_in *) (addr + 1); | 1985 | pfkey_sockaddr_fill(&xp->selector.daddr, xp->selector.dport, |
2053 | sin->sin_family = AF_INET; | 1986 | (struct sockaddr *) (addr + 1), |
2054 | sin->sin_addr.s_addr = xp->selector.daddr.a4; | 1987 | xp->family); |
2055 | sin->sin_port = xp->selector.dport; | ||
2056 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
2057 | } | ||
2058 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2059 | else if (xp->family == AF_INET6) { | ||
2060 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
2061 | sin6->sin6_family = AF_INET6; | ||
2062 | sin6->sin6_port = xp->selector.dport; | ||
2063 | sin6->sin6_flowinfo = 0; | ||
2064 | memcpy(&sin6->sin6_addr, xp->selector.daddr.a6, | ||
2065 | sizeof(struct in6_addr)); | ||
2066 | sin6->sin6_scope_id = 0; | ||
2067 | } | ||
2068 | #endif | ||
2069 | else | ||
2070 | BUG(); | ||
2071 | 1988 | ||
2072 | /* hard time */ | 1989 | /* hard time */ |
2073 | lifetime = (struct sadb_lifetime *) skb_put(skb, | 1990 | lifetime = (struct sadb_lifetime *) skb_put(skb, |
@@ -2121,12 +2038,13 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
2121 | int mode; | 2038 | int mode; |
2122 | 2039 | ||
2123 | req_size = sizeof(struct sadb_x_ipsecrequest); | 2040 | req_size = sizeof(struct sadb_x_ipsecrequest); |
2124 | if (t->mode == XFRM_MODE_TUNNEL) | 2041 | if (t->mode == XFRM_MODE_TUNNEL) { |
2125 | req_size += ((t->encap_family == AF_INET ? | 2042 | socklen = pfkey_sockaddr_len(t->encap_family); |
2126 | sizeof(struct sockaddr_in) : | 2043 | req_size += socklen * 2; |
2127 | sizeof(struct sockaddr_in6)) * 2); | 2044 | } else { |
2128 | else | ||
2129 | size -= 2*socklen; | 2045 | size -= 2*socklen; |
2046 | socklen = 0; | ||
2047 | } | ||
2130 | rq = (void*)skb_put(skb, req_size); | 2048 | rq = (void*)skb_put(skb, req_size); |
2131 | pol->sadb_x_policy_len += req_size/8; | 2049 | pol->sadb_x_policy_len += req_size/8; |
2132 | memset(rq, 0, sizeof(*rq)); | 2050 | memset(rq, 0, sizeof(*rq)); |
@@ -2141,42 +2059,15 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
2141 | if (t->optional) | 2059 | if (t->optional) |
2142 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE; | 2060 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE; |
2143 | rq->sadb_x_ipsecrequest_reqid = t->reqid; | 2061 | rq->sadb_x_ipsecrequest_reqid = t->reqid; |
2062 | |||
2144 | if (t->mode == XFRM_MODE_TUNNEL) { | 2063 | if (t->mode == XFRM_MODE_TUNNEL) { |
2145 | switch (t->encap_family) { | 2064 | u8 *sa = (void *)(rq + 1); |
2146 | case AF_INET: | 2065 | pfkey_sockaddr_fill(&t->saddr, 0, |
2147 | sin = (void*)(rq+1); | 2066 | (struct sockaddr *)sa, |
2148 | sin->sin_family = AF_INET; | 2067 | t->encap_family); |
2149 | sin->sin_addr.s_addr = t->saddr.a4; | 2068 | pfkey_sockaddr_fill(&t->id.daddr, 0, |
2150 | sin->sin_port = 0; | 2069 | (struct sockaddr *) (sa + socklen), |
2151 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | 2070 | t->encap_family); |
2152 | sin++; | ||
2153 | sin->sin_family = AF_INET; | ||
2154 | sin->sin_addr.s_addr = t->id.daddr.a4; | ||
2155 | sin->sin_port = 0; | ||
2156 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
2157 | break; | ||
2158 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2159 | case AF_INET6: | ||
2160 | sin6 = (void*)(rq+1); | ||
2161 | sin6->sin6_family = AF_INET6; | ||
2162 | sin6->sin6_port = 0; | ||
2163 | sin6->sin6_flowinfo = 0; | ||
2164 | memcpy(&sin6->sin6_addr, t->saddr.a6, | ||
2165 | sizeof(struct in6_addr)); | ||
2166 | sin6->sin6_scope_id = 0; | ||
2167 | |||
2168 | sin6++; | ||
2169 | sin6->sin6_family = AF_INET6; | ||
2170 | sin6->sin6_port = 0; | ||
2171 | sin6->sin6_flowinfo = 0; | ||
2172 | memcpy(&sin6->sin6_addr, t->id.daddr.a6, | ||
2173 | sizeof(struct in6_addr)); | ||
2174 | sin6->sin6_scope_id = 0; | ||
2175 | break; | ||
2176 | #endif | ||
2177 | default: | ||
2178 | break; | ||
2179 | } | ||
2180 | } | 2071 | } |
2181 | } | 2072 | } |
2182 | 2073 | ||
@@ -2459,61 +2350,31 @@ out: | |||
2459 | #ifdef CONFIG_NET_KEY_MIGRATE | 2350 | #ifdef CONFIG_NET_KEY_MIGRATE |
2460 | static int pfkey_sockaddr_pair_size(sa_family_t family) | 2351 | static int pfkey_sockaddr_pair_size(sa_family_t family) |
2461 | { | 2352 | { |
2462 | switch (family) { | 2353 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); |
2463 | case AF_INET: | ||
2464 | return PFKEY_ALIGN8(sizeof(struct sockaddr_in) * 2); | ||
2465 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2466 | case AF_INET6: | ||
2467 | return PFKEY_ALIGN8(sizeof(struct sockaddr_in6) * 2); | ||
2468 | #endif | ||
2469 | default: | ||
2470 | return 0; | ||
2471 | } | ||
2472 | /* NOTREACHED */ | ||
2473 | } | 2354 | } |
2474 | 2355 | ||
2475 | static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, | 2356 | static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, |
2476 | xfrm_address_t *saddr, xfrm_address_t *daddr, | 2357 | xfrm_address_t *saddr, xfrm_address_t *daddr, |
2477 | u16 *family) | 2358 | u16 *family) |
2478 | { | 2359 | { |
2479 | struct sockaddr *sa = (struct sockaddr *)(rq + 1); | 2360 | u8 *sa = (u8 *) (rq + 1); |
2361 | int af, socklen; | ||
2362 | |||
2480 | if (rq->sadb_x_ipsecrequest_len < | 2363 | if (rq->sadb_x_ipsecrequest_len < |
2481 | pfkey_sockaddr_pair_size(sa->sa_family)) | 2364 | pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family)) |
2482 | return -EINVAL; | 2365 | return -EINVAL; |
2483 | 2366 | ||
2484 | switch (sa->sa_family) { | 2367 | af = pfkey_sockaddr_extract((struct sockaddr *) sa, |
2485 | case AF_INET: | 2368 | saddr); |
2486 | { | 2369 | if (!af) |
2487 | struct sockaddr_in *sin; | ||
2488 | sin = (struct sockaddr_in *)sa; | ||
2489 | if ((sin+1)->sin_family != AF_INET) | ||
2490 | return -EINVAL; | ||
2491 | memcpy(&saddr->a4, &sin->sin_addr, sizeof(saddr->a4)); | ||
2492 | sin++; | ||
2493 | memcpy(&daddr->a4, &sin->sin_addr, sizeof(daddr->a4)); | ||
2494 | *family = AF_INET; | ||
2495 | break; | ||
2496 | } | ||
2497 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2498 | case AF_INET6: | ||
2499 | { | ||
2500 | struct sockaddr_in6 *sin6; | ||
2501 | sin6 = (struct sockaddr_in6 *)sa; | ||
2502 | if ((sin6+1)->sin6_family != AF_INET6) | ||
2503 | return -EINVAL; | ||
2504 | memcpy(&saddr->a6, &sin6->sin6_addr, | ||
2505 | sizeof(saddr->a6)); | ||
2506 | sin6++; | ||
2507 | memcpy(&daddr->a6, &sin6->sin6_addr, | ||
2508 | sizeof(daddr->a6)); | ||
2509 | *family = AF_INET6; | ||
2510 | break; | ||
2511 | } | ||
2512 | #endif | ||
2513 | default: | ||
2514 | return -EINVAL; | 2370 | return -EINVAL; |
2515 | } | ||
2516 | 2371 | ||
2372 | socklen = pfkey_sockaddr_len(af); | ||
2373 | if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen), | ||
2374 | daddr) != af) | ||
2375 | return -EINVAL; | ||
2376 | |||
2377 | *family = af; | ||
2517 | return 0; | 2378 | return 0; |
2518 | } | 2379 | } |
2519 | 2380 | ||
@@ -3094,10 +2955,6 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct | |||
3094 | struct sadb_msg *hdr; | 2955 | struct sadb_msg *hdr; |
3095 | struct sadb_address *addr; | 2956 | struct sadb_address *addr; |
3096 | struct sadb_x_policy *pol; | 2957 | struct sadb_x_policy *pol; |
3097 | struct sockaddr_in *sin; | ||
3098 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3099 | struct sockaddr_in6 *sin6; | ||
3100 | #endif | ||
3101 | int sockaddr_size; | 2958 | int sockaddr_size; |
3102 | int size; | 2959 | int size; |
3103 | struct sadb_x_sec_ctx *sec_ctx; | 2960 | struct sadb_x_sec_ctx *sec_ctx; |
@@ -3146,29 +3003,11 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct | |||
3146 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; | 3003 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; |
3147 | addr->sadb_address_proto = 0; | 3004 | addr->sadb_address_proto = 0; |
3148 | addr->sadb_address_reserved = 0; | 3005 | addr->sadb_address_reserved = 0; |
3149 | if (x->props.family == AF_INET) { | 3006 | addr->sadb_address_prefixlen = |
3150 | addr->sadb_address_prefixlen = 32; | 3007 | pfkey_sockaddr_fill(&x->props.saddr, 0, |
3151 | 3008 | (struct sockaddr *) (addr + 1), | |
3152 | sin = (struct sockaddr_in *) (addr + 1); | 3009 | x->props.family); |
3153 | sin->sin_family = AF_INET; | 3010 | if (!addr->sadb_address_prefixlen) |
3154 | sin->sin_addr.s_addr = x->props.saddr.a4; | ||
3155 | sin->sin_port = 0; | ||
3156 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3157 | } | ||
3158 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3159 | else if (x->props.family == AF_INET6) { | ||
3160 | addr->sadb_address_prefixlen = 128; | ||
3161 | |||
3162 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
3163 | sin6->sin6_family = AF_INET6; | ||
3164 | sin6->sin6_port = 0; | ||
3165 | sin6->sin6_flowinfo = 0; | ||
3166 | memcpy(&sin6->sin6_addr, | ||
3167 | x->props.saddr.a6, sizeof(struct in6_addr)); | ||
3168 | sin6->sin6_scope_id = 0; | ||
3169 | } | ||
3170 | #endif | ||
3171 | else | ||
3172 | BUG(); | 3011 | BUG(); |
3173 | 3012 | ||
3174 | /* dst address */ | 3013 | /* dst address */ |
@@ -3180,29 +3019,11 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct | |||
3180 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 3019 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; |
3181 | addr->sadb_address_proto = 0; | 3020 | addr->sadb_address_proto = 0; |
3182 | addr->sadb_address_reserved = 0; | 3021 | addr->sadb_address_reserved = 0; |
3183 | if (x->props.family == AF_INET) { | 3022 | addr->sadb_address_prefixlen = |
3184 | addr->sadb_address_prefixlen = 32; | 3023 | pfkey_sockaddr_fill(&x->id.daddr, 0, |
3185 | 3024 | (struct sockaddr *) (addr + 1), | |
3186 | sin = (struct sockaddr_in *) (addr + 1); | 3025 | x->props.family); |
3187 | sin->sin_family = AF_INET; | 3026 | if (!addr->sadb_address_prefixlen) |
3188 | sin->sin_addr.s_addr = x->id.daddr.a4; | ||
3189 | sin->sin_port = 0; | ||
3190 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3191 | } | ||
3192 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3193 | else if (x->props.family == AF_INET6) { | ||
3194 | addr->sadb_address_prefixlen = 128; | ||
3195 | |||
3196 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
3197 | sin6->sin6_family = AF_INET6; | ||
3198 | sin6->sin6_port = 0; | ||
3199 | sin6->sin6_flowinfo = 0; | ||
3200 | memcpy(&sin6->sin6_addr, | ||
3201 | x->id.daddr.a6, sizeof(struct in6_addr)); | ||
3202 | sin6->sin6_scope_id = 0; | ||
3203 | } | ||
3204 | #endif | ||
3205 | else | ||
3206 | BUG(); | 3027 | BUG(); |
3207 | 3028 | ||
3208 | pol = (struct sadb_x_policy *) skb_put(skb, sizeof(struct sadb_x_policy)); | 3029 | pol = (struct sadb_x_policy *) skb_put(skb, sizeof(struct sadb_x_policy)); |
@@ -3328,10 +3149,6 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | |||
3328 | struct sadb_sa *sa; | 3149 | struct sadb_sa *sa; |
3329 | struct sadb_address *addr; | 3150 | struct sadb_address *addr; |
3330 | struct sadb_x_nat_t_port *n_port; | 3151 | struct sadb_x_nat_t_port *n_port; |
3331 | struct sockaddr_in *sin; | ||
3332 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3333 | struct sockaddr_in6 *sin6; | ||
3334 | #endif | ||
3335 | int sockaddr_size; | 3152 | int sockaddr_size; |
3336 | int size; | 3153 | int size; |
3337 | __u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0); | 3154 | __u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0); |
@@ -3395,29 +3212,11 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | |||
3395 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; | 3212 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; |
3396 | addr->sadb_address_proto = 0; | 3213 | addr->sadb_address_proto = 0; |
3397 | addr->sadb_address_reserved = 0; | 3214 | addr->sadb_address_reserved = 0; |
3398 | if (x->props.family == AF_INET) { | 3215 | addr->sadb_address_prefixlen = |
3399 | addr->sadb_address_prefixlen = 32; | 3216 | pfkey_sockaddr_fill(&x->props.saddr, 0, |
3400 | 3217 | (struct sockaddr *) (addr + 1), | |
3401 | sin = (struct sockaddr_in *) (addr + 1); | 3218 | x->props.family); |
3402 | sin->sin_family = AF_INET; | 3219 | if (!addr->sadb_address_prefixlen) |
3403 | sin->sin_addr.s_addr = x->props.saddr.a4; | ||
3404 | sin->sin_port = 0; | ||
3405 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3406 | } | ||
3407 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3408 | else if (x->props.family == AF_INET6) { | ||
3409 | addr->sadb_address_prefixlen = 128; | ||
3410 | |||
3411 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
3412 | sin6->sin6_family = AF_INET6; | ||
3413 | sin6->sin6_port = 0; | ||
3414 | sin6->sin6_flowinfo = 0; | ||
3415 | memcpy(&sin6->sin6_addr, | ||
3416 | x->props.saddr.a6, sizeof(struct in6_addr)); | ||
3417 | sin6->sin6_scope_id = 0; | ||
3418 | } | ||
3419 | #endif | ||
3420 | else | ||
3421 | BUG(); | 3220 | BUG(); |
3422 | 3221 | ||
3423 | /* NAT_T_SPORT (old port) */ | 3222 | /* NAT_T_SPORT (old port) */ |
@@ -3436,28 +3235,11 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | |||
3436 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 3235 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; |
3437 | addr->sadb_address_proto = 0; | 3236 | addr->sadb_address_proto = 0; |
3438 | addr->sadb_address_reserved = 0; | 3237 | addr->sadb_address_reserved = 0; |
3439 | if (x->props.family == AF_INET) { | 3238 | addr->sadb_address_prefixlen = |
3440 | addr->sadb_address_prefixlen = 32; | 3239 | pfkey_sockaddr_fill(ipaddr, 0, |
3441 | 3240 | (struct sockaddr *) (addr + 1), | |
3442 | sin = (struct sockaddr_in *) (addr + 1); | 3241 | x->props.family); |
3443 | sin->sin_family = AF_INET; | 3242 | if (!addr->sadb_address_prefixlen) |
3444 | sin->sin_addr.s_addr = ipaddr->a4; | ||
3445 | sin->sin_port = 0; | ||
3446 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3447 | } | ||
3448 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3449 | else if (x->props.family == AF_INET6) { | ||
3450 | addr->sadb_address_prefixlen = 128; | ||
3451 | |||
3452 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
3453 | sin6->sin6_family = AF_INET6; | ||
3454 | sin6->sin6_port = 0; | ||
3455 | sin6->sin6_flowinfo = 0; | ||
3456 | memcpy(&sin6->sin6_addr, &ipaddr->a6, sizeof(struct in6_addr)); | ||
3457 | sin6->sin6_scope_id = 0; | ||
3458 | } | ||
3459 | #endif | ||
3460 | else | ||
3461 | BUG(); | 3243 | BUG(); |
3462 | 3244 | ||
3463 | /* NAT_T_DPORT (new port) */ | 3245 | /* NAT_T_DPORT (new port) */ |
@@ -3475,10 +3257,6 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type, | |||
3475 | struct xfrm_selector *sel) | 3257 | struct xfrm_selector *sel) |
3476 | { | 3258 | { |
3477 | struct sadb_address *addr; | 3259 | struct sadb_address *addr; |
3478 | struct sockaddr_in *sin; | ||
3479 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3480 | struct sockaddr_in6 *sin6; | ||
3481 | #endif | ||
3482 | addr = (struct sadb_address *)skb_put(skb, sizeof(struct sadb_address) + sasize); | 3260 | addr = (struct sadb_address *)skb_put(skb, sizeof(struct sadb_address) + sasize); |
3483 | addr->sadb_address_len = (sizeof(struct sadb_address) + sasize)/8; | 3261 | addr->sadb_address_len = (sizeof(struct sadb_address) + sasize)/8; |
3484 | addr->sadb_address_exttype = type; | 3262 | addr->sadb_address_exttype = type; |
@@ -3487,50 +3265,16 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type, | |||
3487 | 3265 | ||
3488 | switch (type) { | 3266 | switch (type) { |
3489 | case SADB_EXT_ADDRESS_SRC: | 3267 | case SADB_EXT_ADDRESS_SRC: |
3490 | if (sel->family == AF_INET) { | 3268 | addr->sadb_address_prefixlen = sel->prefixlen_s; |
3491 | addr->sadb_address_prefixlen = sel->prefixlen_s; | 3269 | pfkey_sockaddr_fill(&sel->saddr, 0, |
3492 | sin = (struct sockaddr_in *)(addr + 1); | 3270 | (struct sockaddr *)(addr + 1), |
3493 | sin->sin_family = AF_INET; | 3271 | sel->family); |
3494 | memcpy(&sin->sin_addr.s_addr, &sel->saddr, | ||
3495 | sizeof(sin->sin_addr.s_addr)); | ||
3496 | sin->sin_port = 0; | ||
3497 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3498 | } | ||
3499 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3500 | else if (sel->family == AF_INET6) { | ||
3501 | addr->sadb_address_prefixlen = sel->prefixlen_s; | ||
3502 | sin6 = (struct sockaddr_in6 *)(addr + 1); | ||
3503 | sin6->sin6_family = AF_INET6; | ||
3504 | sin6->sin6_port = 0; | ||
3505 | sin6->sin6_flowinfo = 0; | ||
3506 | sin6->sin6_scope_id = 0; | ||
3507 | memcpy(&sin6->sin6_addr.s6_addr, &sel->saddr, | ||
3508 | sizeof(sin6->sin6_addr.s6_addr)); | ||
3509 | } | ||
3510 | #endif | ||
3511 | break; | 3272 | break; |
3512 | case SADB_EXT_ADDRESS_DST: | 3273 | case SADB_EXT_ADDRESS_DST: |
3513 | if (sel->family == AF_INET) { | 3274 | addr->sadb_address_prefixlen = sel->prefixlen_d; |
3514 | addr->sadb_address_prefixlen = sel->prefixlen_d; | 3275 | pfkey_sockaddr_fill(&sel->daddr, 0, |
3515 | sin = (struct sockaddr_in *)(addr + 1); | 3276 | (struct sockaddr *)(addr + 1), |
3516 | sin->sin_family = AF_INET; | 3277 | sel->family); |
3517 | memcpy(&sin->sin_addr.s_addr, &sel->daddr, | ||
3518 | sizeof(sin->sin_addr.s_addr)); | ||
3519 | sin->sin_port = 0; | ||
3520 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3521 | } | ||
3522 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3523 | else if (sel->family == AF_INET6) { | ||
3524 | addr->sadb_address_prefixlen = sel->prefixlen_d; | ||
3525 | sin6 = (struct sockaddr_in6 *)(addr + 1); | ||
3526 | sin6->sin6_family = AF_INET6; | ||
3527 | sin6->sin6_port = 0; | ||
3528 | sin6->sin6_flowinfo = 0; | ||
3529 | sin6->sin6_scope_id = 0; | ||
3530 | memcpy(&sin6->sin6_addr.s6_addr, &sel->daddr, | ||
3531 | sizeof(sin6->sin6_addr.s6_addr)); | ||
3532 | } | ||
3533 | #endif | ||
3534 | break; | 3278 | break; |
3535 | default: | 3279 | default: |
3536 | return -EINVAL; | 3280 | return -EINVAL; |
@@ -3545,10 +3289,8 @@ static int set_ipsecrequest(struct sk_buff *skb, | |||
3545 | xfrm_address_t *src, xfrm_address_t *dst) | 3289 | xfrm_address_t *src, xfrm_address_t *dst) |
3546 | { | 3290 | { |
3547 | struct sadb_x_ipsecrequest *rq; | 3291 | struct sadb_x_ipsecrequest *rq; |
3548 | struct sockaddr_in *sin; | 3292 | u8 *sa; |
3549 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 3293 | int socklen = pfkey_sockaddr_len(family); |
3550 | struct sockaddr_in6 *sin6; | ||
3551 | #endif | ||
3552 | int size_req; | 3294 | int size_req; |
3553 | 3295 | ||
3554 | size_req = sizeof(struct sadb_x_ipsecrequest) + | 3296 | size_req = sizeof(struct sadb_x_ipsecrequest) + |
@@ -3562,38 +3304,10 @@ static int set_ipsecrequest(struct sk_buff *skb, | |||
3562 | rq->sadb_x_ipsecrequest_level = level; | 3304 | rq->sadb_x_ipsecrequest_level = level; |
3563 | rq->sadb_x_ipsecrequest_reqid = reqid; | 3305 | rq->sadb_x_ipsecrequest_reqid = reqid; |
3564 | 3306 | ||
3565 | switch (family) { | 3307 | sa = (u8 *) (rq + 1); |
3566 | case AF_INET: | 3308 | if (!pfkey_sockaddr_fill(src, 0, (struct sockaddr *)sa, family) || |
3567 | sin = (struct sockaddr_in *)(rq + 1); | 3309 | !pfkey_sockaddr_fill(dst, 0, (struct sockaddr *)(sa + socklen), family)) |
3568 | sin->sin_family = AF_INET; | ||
3569 | memcpy(&sin->sin_addr.s_addr, src, | ||
3570 | sizeof(sin->sin_addr.s_addr)); | ||
3571 | sin++; | ||
3572 | sin->sin_family = AF_INET; | ||
3573 | memcpy(&sin->sin_addr.s_addr, dst, | ||
3574 | sizeof(sin->sin_addr.s_addr)); | ||
3575 | break; | ||
3576 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3577 | case AF_INET6: | ||
3578 | sin6 = (struct sockaddr_in6 *)(rq + 1); | ||
3579 | sin6->sin6_family = AF_INET6; | ||
3580 | sin6->sin6_port = 0; | ||
3581 | sin6->sin6_flowinfo = 0; | ||
3582 | sin6->sin6_scope_id = 0; | ||
3583 | memcpy(&sin6->sin6_addr.s6_addr, src, | ||
3584 | sizeof(sin6->sin6_addr.s6_addr)); | ||
3585 | sin6++; | ||
3586 | sin6->sin6_family = AF_INET6; | ||
3587 | sin6->sin6_port = 0; | ||
3588 | sin6->sin6_flowinfo = 0; | ||
3589 | sin6->sin6_scope_id = 0; | ||
3590 | memcpy(&sin6->sin6_addr.s6_addr, dst, | ||
3591 | sizeof(sin6->sin6_addr.s6_addr)); | ||
3592 | break; | ||
3593 | #endif | ||
3594 | default: | ||
3595 | return -EINVAL; | 3310 | return -EINVAL; |
3596 | } | ||
3597 | 3311 | ||
3598 | return 0; | 3312 | return 0; |
3599 | } | 3313 | } |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a24b459dd45a..590e00b2766c 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -7,11 +7,23 @@ config MAC80211 | |||
7 | select CRC32 | 7 | select CRC32 |
8 | select WIRELESS_EXT | 8 | select WIRELESS_EXT |
9 | select CFG80211 | 9 | select CFG80211 |
10 | select NET_SCH_FIFO | ||
11 | ---help--- | 10 | ---help--- |
12 | This option enables the hardware independent IEEE 802.11 | 11 | This option enables the hardware independent IEEE 802.11 |
13 | networking stack. | 12 | networking stack. |
14 | 13 | ||
14 | config MAC80211_QOS | ||
15 | def_bool y | ||
16 | depends on MAC80211 | ||
17 | depends on NET_SCHED | ||
18 | depends on NETDEVICES_MULTIQUEUE | ||
19 | |||
20 | comment "QoS/HT support disabled" | ||
21 | depends on MAC80211 && !MAC80211_QOS | ||
22 | comment "QoS/HT support needs CONFIG_NET_SCHED" | ||
23 | depends on MAC80211 && !NET_SCHED | ||
24 | comment "QoS/HT support needs CONFIG_NETDEVICES_MULTIQUEUE" | ||
25 | depends on MAC80211 && !NETDEVICES_MULTIQUEUE | ||
26 | |||
15 | menu "Rate control algorithm selection" | 27 | menu "Rate control algorithm selection" |
16 | depends on MAC80211 != n | 28 | depends on MAC80211 != n |
17 | 29 | ||
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 4e5847fd316c..1d2a4e010e5c 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -29,7 +29,7 @@ mac80211-y := \ | |||
29 | event.o | 29 | event.o |
30 | 30 | ||
31 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o | 31 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o |
32 | mac80211-$(CONFIG_NET_SCHED) += wme.o | 32 | mac80211-$(CONFIG_MAC80211_QOS) += wme.o |
33 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ | 33 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ |
34 | debugfs.o \ | 34 | debugfs.o \ |
35 | debugfs_sta.o \ | 35 | debugfs_sta.o \ |
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index 59f1691f62c8..4d4c2dfcf9a0 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -134,7 +134,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
134 | } | 134 | } |
135 | 135 | ||
136 | 136 | ||
137 | struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[]) | 137 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) |
138 | { | 138 | { |
139 | struct crypto_cipher *tfm; | 139 | struct crypto_cipher *tfm; |
140 | 140 | ||
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h index 885f19030b29..8cd0f14aab4d 100644 --- a/net/mac80211/aes_ccm.h +++ b/net/mac80211/aes_ccm.h | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #define AES_BLOCK_LEN 16 | 15 | #define AES_BLOCK_LEN 16 |
16 | 16 | ||
17 | struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[]); | 17 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); |
18 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | 18 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, |
19 | u8 *b_0, u8 *aad, u8 *data, size_t data_len, | 19 | u8 *b_0, u8 *aad, u8 *data, size_t data_len, |
20 | u8 *cdata, u8 *mic); | 20 | u8 *cdata, u8 *mic); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a9fce4afdf21..81087281b031 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -256,8 +256,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
256 | case ALG_TKIP: | 256 | case ALG_TKIP: |
257 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | 257 | params.cipher = WLAN_CIPHER_SUITE_TKIP; |
258 | 258 | ||
259 | iv32 = key->u.tkip.iv32; | 259 | iv32 = key->u.tkip.tx.iv32; |
260 | iv16 = key->u.tkip.iv16; | 260 | iv16 = key->u.tkip.tx.iv16; |
261 | 261 | ||
262 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && | 262 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
263 | sdata->local->ops->get_tkip_seq) | 263 | sdata->local->ops->get_tkip_seq) |
@@ -602,6 +602,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
602 | */ | 602 | */ |
603 | 603 | ||
604 | if (params->station_flags & STATION_FLAG_CHANGED) { | 604 | if (params->station_flags & STATION_FLAG_CHANGED) { |
605 | spin_lock_bh(&sta->lock); | ||
605 | sta->flags &= ~WLAN_STA_AUTHORIZED; | 606 | sta->flags &= ~WLAN_STA_AUTHORIZED; |
606 | if (params->station_flags & STATION_FLAG_AUTHORIZED) | 607 | if (params->station_flags & STATION_FLAG_AUTHORIZED) |
607 | sta->flags |= WLAN_STA_AUTHORIZED; | 608 | sta->flags |= WLAN_STA_AUTHORIZED; |
@@ -613,6 +614,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
613 | sta->flags &= ~WLAN_STA_WME; | 614 | sta->flags &= ~WLAN_STA_WME; |
614 | if (params->station_flags & STATION_FLAG_WME) | 615 | if (params->station_flags & STATION_FLAG_WME) |
615 | sta->flags |= WLAN_STA_WME; | 616 | sta->flags |= WLAN_STA_WME; |
617 | spin_unlock_bh(&sta->lock); | ||
616 | } | 618 | } |
617 | 619 | ||
618 | /* | 620 | /* |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 1cccbfd781f6..d20d90eead1f 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -197,45 +197,6 @@ DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u", | |||
197 | DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u", | 197 | DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u", |
198 | local->tx_status_drop); | 198 | local->tx_status_drop); |
199 | 199 | ||
200 | static ssize_t stats_wme_rx_queue_read(struct file *file, | ||
201 | char __user *userbuf, | ||
202 | size_t count, loff_t *ppos) | ||
203 | { | ||
204 | struct ieee80211_local *local = file->private_data; | ||
205 | char buf[NUM_RX_DATA_QUEUES*15], *p = buf; | ||
206 | int i; | ||
207 | |||
208 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | ||
209 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
210 | "%u\n", local->wme_rx_queue[i]); | ||
211 | |||
212 | return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf); | ||
213 | } | ||
214 | |||
215 | static const struct file_operations stats_wme_rx_queue_ops = { | ||
216 | .read = stats_wme_rx_queue_read, | ||
217 | .open = mac80211_open_file_generic, | ||
218 | }; | ||
219 | |||
220 | static ssize_t stats_wme_tx_queue_read(struct file *file, | ||
221 | char __user *userbuf, | ||
222 | size_t count, loff_t *ppos) | ||
223 | { | ||
224 | struct ieee80211_local *local = file->private_data; | ||
225 | char buf[NUM_TX_DATA_QUEUES*15], *p = buf; | ||
226 | int i; | ||
227 | |||
228 | for (i = 0; i < NUM_TX_DATA_QUEUES; i++) | ||
229 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
230 | "%u\n", local->wme_tx_queue[i]); | ||
231 | |||
232 | return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf); | ||
233 | } | ||
234 | |||
235 | static const struct file_operations stats_wme_tx_queue_ops = { | ||
236 | .read = stats_wme_tx_queue_read, | ||
237 | .open = mac80211_open_file_generic, | ||
238 | }; | ||
239 | #endif | 200 | #endif |
240 | 201 | ||
241 | DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount); | 202 | DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount); |
@@ -303,8 +264,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
303 | DEBUGFS_STATS_ADD(rx_expand_skb_head2); | 264 | DEBUGFS_STATS_ADD(rx_expand_skb_head2); |
304 | DEBUGFS_STATS_ADD(rx_handlers_fragments); | 265 | DEBUGFS_STATS_ADD(rx_handlers_fragments); |
305 | DEBUGFS_STATS_ADD(tx_status_drop); | 266 | DEBUGFS_STATS_ADD(tx_status_drop); |
306 | DEBUGFS_STATS_ADD(wme_tx_queue); | ||
307 | DEBUGFS_STATS_ADD(wme_rx_queue); | ||
308 | #endif | 267 | #endif |
309 | DEBUGFS_STATS_ADD(dot11ACKFailureCount); | 268 | DEBUGFS_STATS_ADD(dot11ACKFailureCount); |
310 | DEBUGFS_STATS_ADD(dot11RTSFailureCount); | 269 | DEBUGFS_STATS_ADD(dot11RTSFailureCount); |
@@ -356,8 +315,6 @@ void debugfs_hw_del(struct ieee80211_local *local) | |||
356 | DEBUGFS_STATS_DEL(rx_expand_skb_head2); | 315 | DEBUGFS_STATS_DEL(rx_expand_skb_head2); |
357 | DEBUGFS_STATS_DEL(rx_handlers_fragments); | 316 | DEBUGFS_STATS_DEL(rx_handlers_fragments); |
358 | DEBUGFS_STATS_DEL(tx_status_drop); | 317 | DEBUGFS_STATS_DEL(tx_status_drop); |
359 | DEBUGFS_STATS_DEL(wme_tx_queue); | ||
360 | DEBUGFS_STATS_DEL(wme_rx_queue); | ||
361 | #endif | 318 | #endif |
362 | DEBUGFS_STATS_DEL(dot11ACKFailureCount); | 319 | DEBUGFS_STATS_DEL(dot11ACKFailureCount); |
363 | DEBUGFS_STATS_DEL(dot11RTSFailureCount); | 320 | DEBUGFS_STATS_DEL(dot11RTSFailureCount); |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 19efc3a6a932..7439b63df5d0 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -97,8 +97,8 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | |||
97 | break; | 97 | break; |
98 | case ALG_TKIP: | 98 | case ALG_TKIP: |
99 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", | 99 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", |
100 | key->u.tkip.iv32, | 100 | key->u.tkip.tx.iv32, |
101 | key->u.tkip.iv16); | 101 | key->u.tkip.tx.iv16); |
102 | break; | 102 | break; |
103 | case ALG_CCMP: | 103 | case ALG_CCMP: |
104 | tpn = key->u.ccmp.tx_pn; | 104 | tpn = key->u.ccmp.tx_pn; |
@@ -128,8 +128,8 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
128 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 128 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) |
129 | p += scnprintf(p, sizeof(buf)+buf-p, | 129 | p += scnprintf(p, sizeof(buf)+buf-p, |
130 | "%08x %04x\n", | 130 | "%08x %04x\n", |
131 | key->u.tkip.iv32_rx[i], | 131 | key->u.tkip.rx[i].iv32, |
132 | key->u.tkip.iv16_rx[i]); | 132 | key->u.tkip.rx[i].iv16); |
133 | len = p - buf; | 133 | len = p - buf; |
134 | break; | 134 | break; |
135 | case ALG_CCMP: | 135 | case ALG_CCMP: |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index e3326d046944..b2089b2da48a 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -155,7 +155,6 @@ static const struct file_operations name##_ops = { \ | |||
155 | __IEEE80211_IF_WFILE(name) | 155 | __IEEE80211_IF_WFILE(name) |
156 | 156 | ||
157 | /* common attributes */ | 157 | /* common attributes */ |
158 | IEEE80211_IF_FILE(channel_use, channel_use, DEC); | ||
159 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 158 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
160 | 159 | ||
161 | /* STA/IBSS attributes */ | 160 | /* STA/IBSS attributes */ |
@@ -248,7 +247,6 @@ IEEE80211_IF_WFILE(min_discovery_timeout, | |||
248 | 247 | ||
249 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 248 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
250 | { | 249 | { |
251 | DEBUGFS_ADD(channel_use, sta); | ||
252 | DEBUGFS_ADD(drop_unencrypted, sta); | 250 | DEBUGFS_ADD(drop_unencrypted, sta); |
253 | DEBUGFS_ADD(state, sta); | 251 | DEBUGFS_ADD(state, sta); |
254 | DEBUGFS_ADD(bssid, sta); | 252 | DEBUGFS_ADD(bssid, sta); |
@@ -269,7 +267,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
269 | 267 | ||
270 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 268 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
271 | { | 269 | { |
272 | DEBUGFS_ADD(channel_use, ap); | ||
273 | DEBUGFS_ADD(drop_unencrypted, ap); | 270 | DEBUGFS_ADD(drop_unencrypted, ap); |
274 | DEBUGFS_ADD(num_sta_ps, ap); | 271 | DEBUGFS_ADD(num_sta_ps, ap); |
275 | DEBUGFS_ADD(dtim_count, ap); | 272 | DEBUGFS_ADD(dtim_count, ap); |
@@ -281,14 +278,12 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
281 | 278 | ||
282 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 279 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
283 | { | 280 | { |
284 | DEBUGFS_ADD(channel_use, wds); | ||
285 | DEBUGFS_ADD(drop_unencrypted, wds); | 281 | DEBUGFS_ADD(drop_unencrypted, wds); |
286 | DEBUGFS_ADD(peer, wds); | 282 | DEBUGFS_ADD(peer, wds); |
287 | } | 283 | } |
288 | 284 | ||
289 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 285 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
290 | { | 286 | { |
291 | DEBUGFS_ADD(channel_use, vlan); | ||
292 | DEBUGFS_ADD(drop_unencrypted, vlan); | 287 | DEBUGFS_ADD(drop_unencrypted, vlan); |
293 | } | 288 | } |
294 | 289 | ||
@@ -376,7 +371,6 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
376 | 371 | ||
377 | static void del_sta_files(struct ieee80211_sub_if_data *sdata) | 372 | static void del_sta_files(struct ieee80211_sub_if_data *sdata) |
378 | { | 373 | { |
379 | DEBUGFS_DEL(channel_use, sta); | ||
380 | DEBUGFS_DEL(drop_unencrypted, sta); | 374 | DEBUGFS_DEL(drop_unencrypted, sta); |
381 | DEBUGFS_DEL(state, sta); | 375 | DEBUGFS_DEL(state, sta); |
382 | DEBUGFS_DEL(bssid, sta); | 376 | DEBUGFS_DEL(bssid, sta); |
@@ -397,7 +391,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata) | |||
397 | 391 | ||
398 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) | 392 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) |
399 | { | 393 | { |
400 | DEBUGFS_DEL(channel_use, ap); | ||
401 | DEBUGFS_DEL(drop_unencrypted, ap); | 394 | DEBUGFS_DEL(drop_unencrypted, ap); |
402 | DEBUGFS_DEL(num_sta_ps, ap); | 395 | DEBUGFS_DEL(num_sta_ps, ap); |
403 | DEBUGFS_DEL(dtim_count, ap); | 396 | DEBUGFS_DEL(dtim_count, ap); |
@@ -409,14 +402,12 @@ static void del_ap_files(struct ieee80211_sub_if_data *sdata) | |||
409 | 402 | ||
410 | static void del_wds_files(struct ieee80211_sub_if_data *sdata) | 403 | static void del_wds_files(struct ieee80211_sub_if_data *sdata) |
411 | { | 404 | { |
412 | DEBUGFS_DEL(channel_use, wds); | ||
413 | DEBUGFS_DEL(drop_unencrypted, wds); | 405 | DEBUGFS_DEL(drop_unencrypted, wds); |
414 | DEBUGFS_DEL(peer, wds); | 406 | DEBUGFS_DEL(peer, wds); |
415 | } | 407 | } |
416 | 408 | ||
417 | static void del_vlan_files(struct ieee80211_sub_if_data *sdata) | 409 | static void del_vlan_files(struct ieee80211_sub_if_data *sdata) |
418 | { | 410 | { |
419 | DEBUGFS_DEL(channel_use, vlan); | ||
420 | DEBUGFS_DEL(drop_unencrypted, vlan); | 411 | DEBUGFS_DEL(drop_unencrypted, vlan); |
421 | } | 412 | } |
422 | 413 | ||
@@ -528,7 +519,7 @@ void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata, | |||
528 | add_files(sdata); | 519 | add_files(sdata); |
529 | } | 520 | } |
530 | 521 | ||
531 | static int netdev_notify(struct notifier_block * nb, | 522 | static int netdev_notify(struct notifier_block *nb, |
532 | unsigned long state, | 523 | unsigned long state, |
533 | void *ndev) | 524 | void *ndev) |
534 | { | 525 | { |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 6d47a1d31b37..79a062782d52 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -63,10 +63,9 @@ STA_FILE(tx_fragments, tx_fragments, LU); | |||
63 | STA_FILE(tx_filtered, tx_filtered_count, LU); | 63 | STA_FILE(tx_filtered, tx_filtered_count, LU); |
64 | STA_FILE(tx_retry_failed, tx_retry_failed, LU); | 64 | STA_FILE(tx_retry_failed, tx_retry_failed, LU); |
65 | STA_FILE(tx_retry_count, tx_retry_count, LU); | 65 | STA_FILE(tx_retry_count, tx_retry_count, LU); |
66 | STA_FILE(last_rssi, last_rssi, D); | ||
67 | STA_FILE(last_signal, last_signal, D); | 66 | STA_FILE(last_signal, last_signal, D); |
67 | STA_FILE(last_qual, last_qual, D); | ||
68 | STA_FILE(last_noise, last_noise, D); | 68 | STA_FILE(last_noise, last_noise, D); |
69 | STA_FILE(channel_use, channel_use, D); | ||
70 | STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); | 69 | STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); |
71 | 70 | ||
72 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 71 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, |
@@ -74,14 +73,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
74 | { | 73 | { |
75 | char buf[100]; | 74 | char buf[100]; |
76 | struct sta_info *sta = file->private_data; | 75 | struct sta_info *sta = file->private_data; |
76 | u32 staflags = get_sta_flags(sta); | ||
77 | int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s", | 77 | int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s", |
78 | sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "", | 78 | staflags & WLAN_STA_AUTH ? "AUTH\n" : "", |
79 | sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "", | 79 | staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", |
80 | sta->flags & WLAN_STA_PS ? "PS\n" : "", | 80 | staflags & WLAN_STA_PS ? "PS\n" : "", |
81 | sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", | 81 | staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", |
82 | sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", | 82 | staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", |
83 | sta->flags & WLAN_STA_WME ? "WME\n" : "", | 83 | staflags & WLAN_STA_WME ? "WME\n" : "", |
84 | sta->flags & WLAN_STA_WDS ? "WDS\n" : ""); | 84 | staflags & WLAN_STA_WDS ? "WDS\n" : ""); |
85 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 85 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
86 | } | 86 | } |
87 | STA_OPS(flags); | 87 | STA_OPS(flags); |
@@ -123,36 +123,6 @@ static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, | |||
123 | } | 123 | } |
124 | STA_OPS(last_seq_ctrl); | 124 | STA_OPS(last_seq_ctrl); |
125 | 125 | ||
126 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
127 | static ssize_t sta_wme_rx_queue_read(struct file *file, char __user *userbuf, | ||
128 | size_t count, loff_t *ppos) | ||
129 | { | ||
130 | char buf[15*NUM_RX_DATA_QUEUES], *p = buf; | ||
131 | int i; | ||
132 | struct sta_info *sta = file->private_data; | ||
133 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | ||
134 | p += scnprintf(p, sizeof(buf)+buf-p, "%u ", | ||
135 | sta->wme_rx_queue[i]); | ||
136 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); | ||
137 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | ||
138 | } | ||
139 | STA_OPS(wme_rx_queue); | ||
140 | |||
141 | static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf, | ||
142 | size_t count, loff_t *ppos) | ||
143 | { | ||
144 | char buf[15*NUM_TX_DATA_QUEUES], *p = buf; | ||
145 | int i; | ||
146 | struct sta_info *sta = file->private_data; | ||
147 | for (i = 0; i < NUM_TX_DATA_QUEUES; i++) | ||
148 | p += scnprintf(p, sizeof(buf)+buf-p, "%u ", | ||
149 | sta->wme_tx_queue[i]); | ||
150 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); | ||
151 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | ||
152 | } | ||
153 | STA_OPS(wme_tx_queue); | ||
154 | #endif | ||
155 | |||
156 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | 126 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, |
157 | size_t count, loff_t *ppos) | 127 | size_t count, loff_t *ppos) |
158 | { | 128 | { |
@@ -293,10 +263,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
293 | DEBUGFS_ADD(num_ps_buf_frames); | 263 | DEBUGFS_ADD(num_ps_buf_frames); |
294 | DEBUGFS_ADD(inactive_ms); | 264 | DEBUGFS_ADD(inactive_ms); |
295 | DEBUGFS_ADD(last_seq_ctrl); | 265 | DEBUGFS_ADD(last_seq_ctrl); |
296 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
297 | DEBUGFS_ADD(wme_rx_queue); | ||
298 | DEBUGFS_ADD(wme_tx_queue); | ||
299 | #endif | ||
300 | DEBUGFS_ADD(agg_status); | 266 | DEBUGFS_ADD(agg_status); |
301 | } | 267 | } |
302 | 268 | ||
@@ -306,10 +272,6 @@ void ieee80211_sta_debugfs_remove(struct sta_info *sta) | |||
306 | DEBUGFS_DEL(num_ps_buf_frames); | 272 | DEBUGFS_DEL(num_ps_buf_frames); |
307 | DEBUGFS_DEL(inactive_ms); | 273 | DEBUGFS_DEL(inactive_ms); |
308 | DEBUGFS_DEL(last_seq_ctrl); | 274 | DEBUGFS_DEL(last_seq_ctrl); |
309 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
310 | DEBUGFS_DEL(wme_rx_queue); | ||
311 | DEBUGFS_DEL(wme_tx_queue); | ||
312 | #endif | ||
313 | DEBUGFS_DEL(agg_status); | 275 | DEBUGFS_DEL(agg_status); |
314 | 276 | ||
315 | debugfs_remove(sta->debugfs.dir); | 277 | debugfs_remove(sta->debugfs.dir); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 006486b26726..b19bd16703b2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -2,6 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -82,7 +83,7 @@ struct ieee80211_sta_bss { | |||
82 | u16 capability; /* host byte order */ | 83 | u16 capability; /* host byte order */ |
83 | enum ieee80211_band band; | 84 | enum ieee80211_band band; |
84 | int freq; | 85 | int freq; |
85 | int rssi, signal, noise; | 86 | int signal, noise, qual; |
86 | u8 *wpa_ie; | 87 | u8 *wpa_ie; |
87 | size_t wpa_ie_len; | 88 | size_t wpa_ie_len; |
88 | u8 *rsn_ie; | 89 | u8 *rsn_ie; |
@@ -91,6 +92,8 @@ struct ieee80211_sta_bss { | |||
91 | size_t wmm_ie_len; | 92 | size_t wmm_ie_len; |
92 | u8 *ht_ie; | 93 | u8 *ht_ie; |
93 | size_t ht_ie_len; | 94 | size_t ht_ie_len; |
95 | u8 *ht_add_ie; | ||
96 | size_t ht_add_ie_len; | ||
94 | #ifdef CONFIG_MAC80211_MESH | 97 | #ifdef CONFIG_MAC80211_MESH |
95 | u8 *mesh_id; | 98 | u8 *mesh_id; |
96 | size_t mesh_id_len; | 99 | size_t mesh_id_len; |
@@ -147,7 +150,6 @@ typedef unsigned __bitwise__ ieee80211_tx_result; | |||
147 | #define IEEE80211_TX_UNICAST BIT(1) | 150 | #define IEEE80211_TX_UNICAST BIT(1) |
148 | #define IEEE80211_TX_PS_BUFFERED BIT(2) | 151 | #define IEEE80211_TX_PS_BUFFERED BIT(2) |
149 | #define IEEE80211_TX_PROBE_LAST_FRAG BIT(3) | 152 | #define IEEE80211_TX_PROBE_LAST_FRAG BIT(3) |
150 | #define IEEE80211_TX_INJECTED BIT(4) | ||
151 | 153 | ||
152 | struct ieee80211_tx_data { | 154 | struct ieee80211_tx_data { |
153 | struct sk_buff *skb; | 155 | struct sk_buff *skb; |
@@ -157,13 +159,12 @@ struct ieee80211_tx_data { | |||
157 | struct sta_info *sta; | 159 | struct sta_info *sta; |
158 | struct ieee80211_key *key; | 160 | struct ieee80211_key *key; |
159 | 161 | ||
160 | struct ieee80211_tx_control *control; | ||
161 | struct ieee80211_channel *channel; | 162 | struct ieee80211_channel *channel; |
162 | struct ieee80211_rate *rate; | 163 | s8 rate_idx; |
163 | /* use this rate (if set) for last fragment; rate can | 164 | /* use this rate (if set) for last fragment; rate can |
164 | * be set to lower rate for the first fragments, e.g., | 165 | * be set to lower rate for the first fragments, e.g., |
165 | * when using CTS protection with IEEE 802.11g. */ | 166 | * when using CTS protection with IEEE 802.11g. */ |
166 | struct ieee80211_rate *last_frag_rate; | 167 | s8 last_frag_rate_idx; |
167 | 168 | ||
168 | /* Extra fragments (in addition to the first fragment | 169 | /* Extra fragments (in addition to the first fragment |
169 | * in skb) */ | 170 | * in skb) */ |
@@ -202,32 +203,16 @@ struct ieee80211_rx_data { | |||
202 | unsigned int flags; | 203 | unsigned int flags; |
203 | int sent_ps_buffered; | 204 | int sent_ps_buffered; |
204 | int queue; | 205 | int queue; |
205 | int load; | ||
206 | u32 tkip_iv32; | 206 | u32 tkip_iv32; |
207 | u16 tkip_iv16; | 207 | u16 tkip_iv16; |
208 | }; | 208 | }; |
209 | 209 | ||
210 | /* flags used in struct ieee80211_tx_packet_data.flags */ | ||
211 | #define IEEE80211_TXPD_REQ_TX_STATUS BIT(0) | ||
212 | #define IEEE80211_TXPD_DO_NOT_ENCRYPT BIT(1) | ||
213 | #define IEEE80211_TXPD_REQUEUE BIT(2) | ||
214 | #define IEEE80211_TXPD_EAPOL_FRAME BIT(3) | ||
215 | #define IEEE80211_TXPD_AMPDU BIT(4) | ||
216 | /* Stored in sk_buff->cb */ | ||
217 | struct ieee80211_tx_packet_data { | ||
218 | int ifindex; | ||
219 | unsigned long jiffies; | ||
220 | unsigned int flags; | ||
221 | u8 queue; | ||
222 | }; | ||
223 | |||
224 | struct ieee80211_tx_stored_packet { | 210 | struct ieee80211_tx_stored_packet { |
225 | struct ieee80211_tx_control control; | ||
226 | struct sk_buff *skb; | 211 | struct sk_buff *skb; |
227 | struct sk_buff **extra_frag; | 212 | struct sk_buff **extra_frag; |
228 | struct ieee80211_rate *last_frag_rate; | 213 | s8 last_frag_rate_idx; |
229 | int num_extra_frag; | 214 | int num_extra_frag; |
230 | unsigned int last_frag_rate_ctrl_probe; | 215 | bool last_frag_rate_ctrl_probe; |
231 | }; | 216 | }; |
232 | 217 | ||
233 | struct beacon_data { | 218 | struct beacon_data { |
@@ -464,14 +449,11 @@ struct ieee80211_sub_if_data { | |||
464 | struct ieee80211_if_sta sta; | 449 | struct ieee80211_if_sta sta; |
465 | u32 mntr_flags; | 450 | u32 mntr_flags; |
466 | } u; | 451 | } u; |
467 | int channel_use; | ||
468 | int channel_use_raw; | ||
469 | 452 | ||
470 | #ifdef CONFIG_MAC80211_DEBUGFS | 453 | #ifdef CONFIG_MAC80211_DEBUGFS |
471 | struct dentry *debugfsdir; | 454 | struct dentry *debugfsdir; |
472 | union { | 455 | union { |
473 | struct { | 456 | struct { |
474 | struct dentry *channel_use; | ||
475 | struct dentry *drop_unencrypted; | 457 | struct dentry *drop_unencrypted; |
476 | struct dentry *state; | 458 | struct dentry *state; |
477 | struct dentry *bssid; | 459 | struct dentry *bssid; |
@@ -490,7 +472,6 @@ struct ieee80211_sub_if_data { | |||
490 | struct dentry *num_beacons_sta; | 472 | struct dentry *num_beacons_sta; |
491 | } sta; | 473 | } sta; |
492 | struct { | 474 | struct { |
493 | struct dentry *channel_use; | ||
494 | struct dentry *drop_unencrypted; | 475 | struct dentry *drop_unencrypted; |
495 | struct dentry *num_sta_ps; | 476 | struct dentry *num_sta_ps; |
496 | struct dentry *dtim_count; | 477 | struct dentry *dtim_count; |
@@ -500,12 +481,10 @@ struct ieee80211_sub_if_data { | |||
500 | struct dentry *num_buffered_multicast; | 481 | struct dentry *num_buffered_multicast; |
501 | } ap; | 482 | } ap; |
502 | struct { | 483 | struct { |
503 | struct dentry *channel_use; | ||
504 | struct dentry *drop_unencrypted; | 484 | struct dentry *drop_unencrypted; |
505 | struct dentry *peer; | 485 | struct dentry *peer; |
506 | } wds; | 486 | } wds; |
507 | struct { | 487 | struct { |
508 | struct dentry *channel_use; | ||
509 | struct dentry *drop_unencrypted; | 488 | struct dentry *drop_unencrypted; |
510 | } vlan; | 489 | } vlan; |
511 | struct { | 490 | struct { |
@@ -610,8 +589,8 @@ struct ieee80211_local { | |||
610 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 589 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
611 | struct timer_list sta_cleanup; | 590 | struct timer_list sta_cleanup; |
612 | 591 | ||
613 | unsigned long state[NUM_TX_DATA_QUEUES_AMPDU]; | 592 | unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; |
614 | struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES_AMPDU]; | 593 | struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; |
615 | struct tasklet_struct tx_pending_tasklet; | 594 | struct tasklet_struct tx_pending_tasklet; |
616 | 595 | ||
617 | /* number of interfaces with corresponding IFF_ flags */ | 596 | /* number of interfaces with corresponding IFF_ flags */ |
@@ -677,9 +656,6 @@ struct ieee80211_local { | |||
677 | assoc_led_name[32], radio_led_name[32]; | 656 | assoc_led_name[32], radio_led_name[32]; |
678 | #endif | 657 | #endif |
679 | 658 | ||
680 | u32 channel_use; | ||
681 | u32 channel_use_raw; | ||
682 | |||
683 | #ifdef CONFIG_MAC80211_DEBUGFS | 659 | #ifdef CONFIG_MAC80211_DEBUGFS |
684 | struct work_struct sta_debugfs_add; | 660 | struct work_struct sta_debugfs_add; |
685 | #endif | 661 | #endif |
@@ -705,8 +681,6 @@ struct ieee80211_local { | |||
705 | unsigned int rx_expand_skb_head2; | 681 | unsigned int rx_expand_skb_head2; |
706 | unsigned int rx_handlers_fragments; | 682 | unsigned int rx_handlers_fragments; |
707 | unsigned int tx_status_drop; | 683 | unsigned int tx_status_drop; |
708 | unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; | ||
709 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; | ||
710 | #define I802_DEBUG_INC(c) (c)++ | 684 | #define I802_DEBUG_INC(c) (c)++ |
711 | #else /* CONFIG_MAC80211_DEBUG_COUNTERS */ | 685 | #else /* CONFIG_MAC80211_DEBUG_COUNTERS */ |
712 | #define I802_DEBUG_INC(c) do { } while (0) | 686 | #define I802_DEBUG_INC(c) do { } while (0) |
@@ -764,8 +738,6 @@ struct ieee80211_local { | |||
764 | struct dentry *rx_expand_skb_head2; | 738 | struct dentry *rx_expand_skb_head2; |
765 | struct dentry *rx_handlers_fragments; | 739 | struct dentry *rx_handlers_fragments; |
766 | struct dentry *tx_status_drop; | 740 | struct dentry *tx_status_drop; |
767 | struct dentry *wme_tx_queue; | ||
768 | struct dentry *wme_rx_queue; | ||
769 | #endif | 741 | #endif |
770 | struct dentry *dot11ACKFailureCount; | 742 | struct dentry *dot11ACKFailureCount; |
771 | struct dentry *dot11RTSFailureCount; | 743 | struct dentry *dot11RTSFailureCount; |
@@ -778,6 +750,15 @@ struct ieee80211_local { | |||
778 | #endif | 750 | #endif |
779 | }; | 751 | }; |
780 | 752 | ||
753 | static inline int ieee80211_is_multiqueue(struct ieee80211_local *local) | ||
754 | { | ||
755 | #ifdef CONFIG_MAC80211_QOS | ||
756 | return netif_is_multiqueue(local->mdev); | ||
757 | #else | ||
758 | return 0; | ||
759 | #endif | ||
760 | } | ||
761 | |||
781 | /* this struct represents 802.11n's RA/TID combination */ | 762 | /* this struct represents 802.11n's RA/TID combination */ |
782 | struct ieee80211_ra_tid { | 763 | struct ieee80211_ra_tid { |
783 | u8 ra[ETH_ALEN]; | 764 | u8 ra[ETH_ALEN]; |
@@ -847,11 +828,6 @@ static inline struct ieee80211_hw *local_to_hw( | |||
847 | return &local->hw; | 828 | return &local->hw; |
848 | } | 829 | } |
849 | 830 | ||
850 | enum ieee80211_link_state_t { | ||
851 | IEEE80211_LINK_STATE_XOFF = 0, | ||
852 | IEEE80211_LINK_STATE_PENDING, | ||
853 | }; | ||
854 | |||
855 | struct sta_attribute { | 831 | struct sta_attribute { |
856 | struct attribute attr; | 832 | struct attribute attr; |
857 | ssize_t (*show)(const struct sta_info *, char *buf); | 833 | ssize_t (*show)(const struct sta_info *, char *buf); |
@@ -877,29 +853,8 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | |||
877 | 853 | ||
878 | /* ieee80211_ioctl.c */ | 854 | /* ieee80211_ioctl.c */ |
879 | extern const struct iw_handler_def ieee80211_iw_handler_def; | 855 | extern const struct iw_handler_def ieee80211_iw_handler_def; |
880 | |||
881 | |||
882 | /* Least common multiple of the used rates (in 100 kbps). This is used to | ||
883 | * calculate rate_inv values for each rate so that only integers are needed. */ | ||
884 | #define CHAN_UTIL_RATE_LCM 95040 | ||
885 | /* 1 usec is 1/8 * (95040/10) = 1188 */ | ||
886 | #define CHAN_UTIL_PER_USEC 1188 | ||
887 | /* Amount of bits to shift the result right to scale the total utilization | ||
888 | * to values that will not wrap around 32-bit integers. */ | ||
889 | #define CHAN_UTIL_SHIFT 9 | ||
890 | /* Theoretical maximum of channel utilization counter in 10 ms (stat_time=1): | ||
891 | * (CHAN_UTIL_PER_USEC * 10000) >> CHAN_UTIL_SHIFT = 23203. So dividing the | ||
892 | * raw value with about 23 should give utilization in 10th of a percentage | ||
893 | * (1/1000). However, utilization is only estimated and not all intervals | ||
894 | * between frames etc. are calculated. 18 seems to give numbers that are closer | ||
895 | * to the real maximum. */ | ||
896 | #define CHAN_UTIL_PER_10MS 18 | ||
897 | #define CHAN_UTIL_HDR_LONG (202 * CHAN_UTIL_PER_USEC) | ||
898 | #define CHAN_UTIL_HDR_SHORT (40 * CHAN_UTIL_PER_USEC) | ||
899 | |||
900 | |||
901 | /* ieee80211_ioctl.c */ | ||
902 | int ieee80211_set_freq(struct net_device *dev, int freq); | 856 | int ieee80211_set_freq(struct net_device *dev, int freq); |
857 | |||
903 | /* ieee80211_sta.c */ | 858 | /* ieee80211_sta.c */ |
904 | void ieee80211_sta_timer(unsigned long data); | 859 | void ieee80211_sta_timer(unsigned long data); |
905 | void ieee80211_sta_work(struct work_struct *work); | 860 | void ieee80211_sta_work(struct work_struct *work); |
@@ -919,9 +874,9 @@ ieee80211_rx_result ieee80211_sta_rx_scan( | |||
919 | void ieee80211_rx_bss_list_init(struct net_device *dev); | 874 | void ieee80211_rx_bss_list_init(struct net_device *dev); |
920 | void ieee80211_rx_bss_list_deinit(struct net_device *dev); | 875 | void ieee80211_rx_bss_list_deinit(struct net_device *dev); |
921 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); | 876 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); |
922 | struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, | 877 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, |
923 | struct sk_buff *skb, u8 *bssid, | 878 | struct sk_buff *skb, u8 *bssid, |
924 | u8 *addr); | 879 | u8 *addr); |
925 | int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); | 880 | int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); |
926 | int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); | 881 | int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); |
927 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 882 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, |
@@ -940,7 +895,6 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | |||
940 | 895 | ||
941 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, | 896 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, |
942 | u16 tid, u16 initiator, u16 reason); | 897 | u16 tid, u16 initiator, u16 reason); |
943 | void sta_rx_agg_session_timer_expired(unsigned long data); | ||
944 | void sta_addba_resp_timer_expired(unsigned long data); | 898 | void sta_addba_resp_timer_expired(unsigned long data); |
945 | void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr); | 899 | void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr); |
946 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 900 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 06e88a5a036d..984472702381 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -33,9 +33,8 @@ static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) | |||
33 | { | 33 | { |
34 | int i; | 34 | int i; |
35 | 35 | ||
36 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { | 36 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
37 | __skb_queue_purge(&sdata->fragments[i].skb_list); | 37 | __skb_queue_purge(&sdata->fragments[i].skb_list); |
38 | } | ||
39 | } | 38 | } |
40 | 39 | ||
41 | /* Must be called with rtnl lock held. */ | 40 | /* Must be called with rtnl lock held. */ |
@@ -167,9 +166,10 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
167 | ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | | 166 | ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | |
168 | IEEE80211_AUTH_ALG_SHARED_KEY; | 167 | IEEE80211_AUTH_ALG_SHARED_KEY; |
169 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | | 168 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | |
170 | IEEE80211_STA_WMM_ENABLED | | ||
171 | IEEE80211_STA_AUTO_BSSID_SEL | | 169 | IEEE80211_STA_AUTO_BSSID_SEL | |
172 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 170 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
171 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | ||
172 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | ||
173 | 173 | ||
174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); | 174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); |
175 | sdata->bss = &msdata->u.ap; | 175 | sdata->bss = &msdata->u.ap; |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 150d66dbda9d..d4893bd17754 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -321,8 +321,15 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
321 | * some hardware cannot handle TKIP with QoS, so | 321 | * some hardware cannot handle TKIP with QoS, so |
322 | * we indicate whether QoS could be in use. | 322 | * we indicate whether QoS could be in use. |
323 | */ | 323 | */ |
324 | if (sta->flags & WLAN_STA_WME) | 324 | if (test_sta_flags(sta, WLAN_STA_WME)) |
325 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; | 325 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; |
326 | |||
327 | /* | ||
328 | * This key is for a specific sta interface, | ||
329 | * inform the driver that it should try to store | ||
330 | * this key as pairwise key. | ||
331 | */ | ||
332 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | ||
326 | } else { | 333 | } else { |
327 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 334 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { |
328 | struct sta_info *ap; | 335 | struct sta_info *ap; |
@@ -335,7 +342,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
335 | /* same here, the AP could be using QoS */ | 342 | /* same here, the AP could be using QoS */ |
336 | ap = sta_info_get(key->local, key->sdata->u.sta.bssid); | 343 | ap = sta_info_get(key->local, key->sdata->u.sta.bssid); |
337 | if (ap) { | 344 | if (ap) { |
338 | if (ap->flags & WLAN_STA_WME) | 345 | if (test_sta_flags(ap, WLAN_STA_WME)) |
339 | key->conf.flags |= | 346 | key->conf.flags |= |
340 | IEEE80211_KEY_FLAG_WMM_STA; | 347 | IEEE80211_KEY_FLAG_WMM_STA; |
341 | } | 348 | } |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index f52c3df1fe9a..a0f774aafa45 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -69,6 +69,13 @@ enum ieee80211_internal_key_flags { | |||
69 | KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), | 69 | KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), |
70 | }; | 70 | }; |
71 | 71 | ||
72 | struct tkip_ctx { | ||
73 | u32 iv32; | ||
74 | u16 iv16; | ||
75 | u16 p1k[5]; | ||
76 | int initialized; | ||
77 | }; | ||
78 | |||
72 | struct ieee80211_key { | 79 | struct ieee80211_key { |
73 | struct ieee80211_local *local; | 80 | struct ieee80211_local *local; |
74 | struct ieee80211_sub_if_data *sdata; | 81 | struct ieee80211_sub_if_data *sdata; |
@@ -85,16 +92,10 @@ struct ieee80211_key { | |||
85 | union { | 92 | union { |
86 | struct { | 93 | struct { |
87 | /* last used TSC */ | 94 | /* last used TSC */ |
88 | u32 iv32; | 95 | struct tkip_ctx tx; |
89 | u16 iv16; | ||
90 | u16 p1k[5]; | ||
91 | int tx_initialized; | ||
92 | 96 | ||
93 | /* last received RSC */ | 97 | /* last received RSC */ |
94 | u32 iv32_rx[NUM_RX_DATA_QUEUES]; | 98 | struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; |
95 | u16 iv16_rx[NUM_RX_DATA_QUEUES]; | ||
96 | u16 p1k_rx[NUM_RX_DATA_QUEUES][5]; | ||
97 | int rx_initialized[NUM_RX_DATA_QUEUES]; | ||
98 | } tkip; | 99 | } tkip; |
99 | struct { | 100 | struct { |
100 | u8 tx_pn[6]; | 101 | u8 tx_pn[6]; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 98c0b5e56ecc..b182f018a187 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -35,8 +35,6 @@ | |||
35 | #include "debugfs.h" | 35 | #include "debugfs.h" |
36 | #include "debugfs_netdev.h" | 36 | #include "debugfs_netdev.h" |
37 | 37 | ||
38 | #define SUPP_MCS_SET_LEN 16 | ||
39 | |||
40 | /* | 38 | /* |
41 | * For seeing transmitted packets on monitor interfaces | 39 | * For seeing transmitted packets on monitor interfaces |
42 | * we have a radiotap header too. | 40 | * we have a radiotap header too. |
@@ -112,7 +110,13 @@ static int ieee80211_master_open(struct net_device *dev) | |||
112 | break; | 110 | break; |
113 | } | 111 | } |
114 | } | 112 | } |
115 | return res; | 113 | |
114 | if (res) | ||
115 | return res; | ||
116 | |||
117 | netif_start_queue(local->mdev); | ||
118 | |||
119 | return 0; | ||
116 | } | 120 | } |
117 | 121 | ||
118 | static int ieee80211_master_stop(struct net_device *dev) | 122 | static int ieee80211_master_stop(struct net_device *dev) |
@@ -346,6 +350,7 @@ static int ieee80211_open(struct net_device *dev) | |||
346 | goto err_del_interface; | 350 | goto err_del_interface; |
347 | } | 351 | } |
348 | 352 | ||
353 | /* no locking required since STA is not live yet */ | ||
349 | sta->flags |= WLAN_STA_AUTHORIZED; | 354 | sta->flags |= WLAN_STA_AUTHORIZED; |
350 | 355 | ||
351 | res = sta_info_insert(sta); | 356 | res = sta_info_insert(sta); |
@@ -385,8 +390,8 @@ static int ieee80211_open(struct net_device *dev) | |||
385 | * yet be effective. Trigger execution of ieee80211_sta_work | 390 | * yet be effective. Trigger execution of ieee80211_sta_work |
386 | * to fix this. | 391 | * to fix this. |
387 | */ | 392 | */ |
388 | if(sdata->vif.type == IEEE80211_IF_TYPE_STA || | 393 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || |
389 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 394 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { |
390 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 395 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
391 | queue_work(local->hw.workqueue, &ifsta->work); | 396 | queue_work(local->hw.workqueue, &ifsta->work); |
392 | } | 397 | } |
@@ -585,16 +590,16 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
585 | sta = sta_info_get(local, ra); | 590 | sta = sta_info_get(local, ra); |
586 | if (!sta) { | 591 | if (!sta) { |
587 | printk(KERN_DEBUG "Could not find the station\n"); | 592 | printk(KERN_DEBUG "Could not find the station\n"); |
588 | rcu_read_unlock(); | 593 | ret = -ENOENT; |
589 | return -ENOENT; | 594 | goto exit; |
590 | } | 595 | } |
591 | 596 | ||
592 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 597 | spin_lock_bh(&sta->lock); |
593 | 598 | ||
594 | /* we have tried too many times, receiver does not want A-MPDU */ | 599 | /* we have tried too many times, receiver does not want A-MPDU */ |
595 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | 600 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { |
596 | ret = -EBUSY; | 601 | ret = -EBUSY; |
597 | goto start_ba_exit; | 602 | goto err_unlock_sta; |
598 | } | 603 | } |
599 | 604 | ||
600 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 605 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
@@ -605,7 +610,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
605 | "idle on tid %u\n", tid); | 610 | "idle on tid %u\n", tid); |
606 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 611 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
607 | ret = -EAGAIN; | 612 | ret = -EAGAIN; |
608 | goto start_ba_exit; | 613 | goto err_unlock_sta; |
609 | } | 614 | } |
610 | 615 | ||
611 | /* prepare A-MPDU MLME for Tx aggregation */ | 616 | /* prepare A-MPDU MLME for Tx aggregation */ |
@@ -616,7 +621,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
616 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | 621 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", |
617 | tid); | 622 | tid); |
618 | ret = -ENOMEM; | 623 | ret = -ENOMEM; |
619 | goto start_ba_exit; | 624 | goto err_unlock_sta; |
620 | } | 625 | } |
621 | /* Tx timer */ | 626 | /* Tx timer */ |
622 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | 627 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = |
@@ -639,7 +644,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
639 | printk(KERN_DEBUG "BA request denied - queue unavailable for" | 644 | printk(KERN_DEBUG "BA request denied - queue unavailable for" |
640 | " tid %d\n", tid); | 645 | " tid %d\n", tid); |
641 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 646 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
642 | goto start_ba_err; | 647 | goto err_unlock_queue; |
643 | } | 648 | } |
644 | sdata = sta->sdata; | 649 | sdata = sta->sdata; |
645 | 650 | ||
@@ -661,12 +666,13 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
661 | " tid %d\n", tid); | 666 | " tid %d\n", tid); |
662 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 667 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
663 | *state = HT_AGG_STATE_IDLE; | 668 | *state = HT_AGG_STATE_IDLE; |
664 | goto start_ba_err; | 669 | goto err_unlock_queue; |
665 | } | 670 | } |
666 | 671 | ||
667 | /* Will put all the packets in the new SW queue */ | 672 | /* Will put all the packets in the new SW queue */ |
668 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | 673 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); |
669 | spin_unlock_bh(&local->mdev->queue_lock); | 674 | spin_unlock_bh(&local->mdev->queue_lock); |
675 | spin_unlock_bh(&sta->lock); | ||
670 | 676 | ||
671 | /* send an addBA request */ | 677 | /* send an addBA request */ |
672 | sta->ampdu_mlme.dialog_token_allocator++; | 678 | sta->ampdu_mlme.dialog_token_allocator++; |
@@ -674,25 +680,26 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
674 | sta->ampdu_mlme.dialog_token_allocator; | 680 | sta->ampdu_mlme.dialog_token_allocator; |
675 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | 681 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; |
676 | 682 | ||
683 | |||
677 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, | 684 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, |
678 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | 685 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, |
679 | sta->ampdu_mlme.tid_tx[tid]->ssn, | 686 | sta->ampdu_mlme.tid_tx[tid]->ssn, |
680 | 0x40, 5000); | 687 | 0x40, 5000); |
681 | |||
682 | /* activate the timer for the recipient's addBA response */ | 688 | /* activate the timer for the recipient's addBA response */ |
683 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | 689 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = |
684 | jiffies + ADDBA_RESP_INTERVAL; | 690 | jiffies + ADDBA_RESP_INTERVAL; |
685 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 691 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
686 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | 692 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); |
687 | goto start_ba_exit; | 693 | goto exit; |
688 | 694 | ||
689 | start_ba_err: | 695 | err_unlock_queue: |
690 | kfree(sta->ampdu_mlme.tid_tx[tid]); | 696 | kfree(sta->ampdu_mlme.tid_tx[tid]); |
691 | sta->ampdu_mlme.tid_tx[tid] = NULL; | 697 | sta->ampdu_mlme.tid_tx[tid] = NULL; |
692 | spin_unlock_bh(&local->mdev->queue_lock); | 698 | spin_unlock_bh(&local->mdev->queue_lock); |
693 | ret = -EBUSY; | 699 | ret = -EBUSY; |
694 | start_ba_exit: | 700 | err_unlock_sta: |
695 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 701 | spin_unlock_bh(&sta->lock); |
702 | exit: | ||
696 | rcu_read_unlock(); | 703 | rcu_read_unlock(); |
697 | return ret; | 704 | return ret; |
698 | } | 705 | } |
@@ -720,7 +727,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
720 | 727 | ||
721 | /* check if the TID is in aggregation */ | 728 | /* check if the TID is in aggregation */ |
722 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 729 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
723 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 730 | spin_lock_bh(&sta->lock); |
724 | 731 | ||
725 | if (*state != HT_AGG_STATE_OPERATIONAL) { | 732 | if (*state != HT_AGG_STATE_OPERATIONAL) { |
726 | ret = -ENOENT; | 733 | ret = -ENOENT; |
@@ -750,7 +757,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
750 | } | 757 | } |
751 | 758 | ||
752 | stop_BA_exit: | 759 | stop_BA_exit: |
753 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 760 | spin_unlock_bh(&sta->lock); |
754 | rcu_read_unlock(); | 761 | rcu_read_unlock(); |
755 | return ret; | 762 | return ret; |
756 | } | 763 | } |
@@ -779,12 +786,12 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
779 | } | 786 | } |
780 | 787 | ||
781 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 788 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
782 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 789 | spin_lock_bh(&sta->lock); |
783 | 790 | ||
784 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 791 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
785 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | 792 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", |
786 | *state); | 793 | *state); |
787 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 794 | spin_unlock_bh(&sta->lock); |
788 | rcu_read_unlock(); | 795 | rcu_read_unlock(); |
789 | return; | 796 | return; |
790 | } | 797 | } |
@@ -797,7 +804,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
797 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | 804 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); |
798 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 805 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); |
799 | } | 806 | } |
800 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 807 | spin_unlock_bh(&sta->lock); |
801 | rcu_read_unlock(); | 808 | rcu_read_unlock(); |
802 | } | 809 | } |
803 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | 810 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); |
@@ -831,10 +838,11 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
831 | } | 838 | } |
832 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 839 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
833 | 840 | ||
834 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 841 | /* NOTE: no need to use sta->lock in this state check, as |
842 | * ieee80211_stop_tx_ba_session will let only | ||
843 | * one stop call to pass through per sta/tid */ | ||
835 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | 844 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { |
836 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | 845 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); |
837 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
838 | rcu_read_unlock(); | 846 | rcu_read_unlock(); |
839 | return; | 847 | return; |
840 | } | 848 | } |
@@ -857,11 +865,12 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
857 | * ieee80211_wake_queue is not used here as this queue is not | 865 | * ieee80211_wake_queue is not used here as this queue is not |
858 | * necessarily stopped */ | 866 | * necessarily stopped */ |
859 | netif_schedule(local->mdev); | 867 | netif_schedule(local->mdev); |
868 | spin_lock_bh(&sta->lock); | ||
860 | *state = HT_AGG_STATE_IDLE; | 869 | *state = HT_AGG_STATE_IDLE; |
861 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 870 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
862 | kfree(sta->ampdu_mlme.tid_tx[tid]); | 871 | kfree(sta->ampdu_mlme.tid_tx[tid]); |
863 | sta->ampdu_mlme.tid_tx[tid] = NULL; | 872 | sta->ampdu_mlme.tid_tx[tid] = NULL; |
864 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 873 | spin_unlock_bh(&sta->lock); |
865 | 874 | ||
866 | rcu_read_unlock(); | 875 | rcu_read_unlock(); |
867 | } | 876 | } |
@@ -967,8 +976,7 @@ void ieee80211_if_setup(struct net_device *dev) | |||
967 | /* everything else */ | 976 | /* everything else */ |
968 | 977 | ||
969 | static int __ieee80211_if_config(struct net_device *dev, | 978 | static int __ieee80211_if_config(struct net_device *dev, |
970 | struct sk_buff *beacon, | 979 | struct sk_buff *beacon) |
971 | struct ieee80211_tx_control *control) | ||
972 | { | 980 | { |
973 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 981 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
974 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 982 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
@@ -986,13 +994,11 @@ static int __ieee80211_if_config(struct net_device *dev, | |||
986 | conf.ssid_len = sdata->u.sta.ssid_len; | 994 | conf.ssid_len = sdata->u.sta.ssid_len; |
987 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 995 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
988 | conf.beacon = beacon; | 996 | conf.beacon = beacon; |
989 | conf.beacon_control = control; | ||
990 | ieee80211_start_mesh(dev); | 997 | ieee80211_start_mesh(dev); |
991 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 998 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { |
992 | conf.ssid = sdata->u.ap.ssid; | 999 | conf.ssid = sdata->u.ap.ssid; |
993 | conf.ssid_len = sdata->u.ap.ssid_len; | 1000 | conf.ssid_len = sdata->u.ap.ssid_len; |
994 | conf.beacon = beacon; | 1001 | conf.beacon = beacon; |
995 | conf.beacon_control = control; | ||
996 | } | 1002 | } |
997 | return local->ops->config_interface(local_to_hw(local), | 1003 | return local->ops->config_interface(local_to_hw(local), |
998 | &sdata->vif, &conf); | 1004 | &sdata->vif, &conf); |
@@ -1005,23 +1011,21 @@ int ieee80211_if_config(struct net_device *dev) | |||
1005 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && | 1011 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && |
1006 | (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | 1012 | (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) |
1007 | return ieee80211_if_config_beacon(dev); | 1013 | return ieee80211_if_config_beacon(dev); |
1008 | return __ieee80211_if_config(dev, NULL, NULL); | 1014 | return __ieee80211_if_config(dev, NULL); |
1009 | } | 1015 | } |
1010 | 1016 | ||
1011 | int ieee80211_if_config_beacon(struct net_device *dev) | 1017 | int ieee80211_if_config_beacon(struct net_device *dev) |
1012 | { | 1018 | { |
1013 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1019 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1014 | struct ieee80211_tx_control control; | ||
1015 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1020 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1016 | struct sk_buff *skb; | 1021 | struct sk_buff *skb; |
1017 | 1022 | ||
1018 | if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | 1023 | if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) |
1019 | return 0; | 1024 | return 0; |
1020 | skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif, | 1025 | skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif); |
1021 | &control); | ||
1022 | if (!skb) | 1026 | if (!skb) |
1023 | return -ENOMEM; | 1027 | return -ENOMEM; |
1024 | return __ieee80211_if_config(dev, skb, &control); | 1028 | return __ieee80211_if_config(dev, skb); |
1025 | } | 1029 | } |
1026 | 1030 | ||
1027 | int ieee80211_hw_config(struct ieee80211_local *local) | 1031 | int ieee80211_hw_config(struct ieee80211_local *local) |
@@ -1068,56 +1072,84 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | |||
1068 | struct ieee80211_supported_band *sband; | 1072 | struct ieee80211_supported_band *sband; |
1069 | struct ieee80211_ht_info ht_conf; | 1073 | struct ieee80211_ht_info ht_conf; |
1070 | struct ieee80211_ht_bss_info ht_bss_conf; | 1074 | struct ieee80211_ht_bss_info ht_bss_conf; |
1071 | int i; | ||
1072 | u32 changed = 0; | 1075 | u32 changed = 0; |
1076 | int i; | ||
1077 | u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS; | ||
1078 | u8 tx_mcs_set_cap; | ||
1073 | 1079 | ||
1074 | sband = local->hw.wiphy->bands[conf->channel->band]; | 1080 | sband = local->hw.wiphy->bands[conf->channel->band]; |
1075 | 1081 | ||
1082 | memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); | ||
1083 | memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); | ||
1084 | |||
1076 | /* HT is not supported */ | 1085 | /* HT is not supported */ |
1077 | if (!sband->ht_info.ht_supported) { | 1086 | if (!sband->ht_info.ht_supported) { |
1078 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | 1087 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; |
1079 | return 0; | 1088 | goto out; |
1080 | } | 1089 | } |
1081 | 1090 | ||
1082 | memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); | 1091 | /* disable HT */ |
1083 | memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); | 1092 | if (!enable_ht) { |
1084 | 1093 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) | |
1085 | if (enable_ht) { | ||
1086 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) | ||
1087 | changed |= BSS_CHANGED_HT; | 1094 | changed |= BSS_CHANGED_HT; |
1095 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | ||
1096 | conf->ht_conf.ht_supported = 0; | ||
1097 | goto out; | ||
1098 | } | ||
1088 | 1099 | ||
1089 | conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; | ||
1090 | ht_conf.ht_supported = 1; | ||
1091 | 1100 | ||
1092 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; | 1101 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) |
1093 | ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); | 1102 | changed |= BSS_CHANGED_HT; |
1094 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; | ||
1095 | 1103 | ||
1096 | for (i = 0; i < SUPP_MCS_SET_LEN; i++) | 1104 | conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; |
1097 | ht_conf.supp_mcs_set[i] = | 1105 | ht_conf.ht_supported = 1; |
1098 | sband->ht_info.supp_mcs_set[i] & | ||
1099 | req_ht_cap->supp_mcs_set[i]; | ||
1100 | 1106 | ||
1101 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | 1107 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; |
1102 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | 1108 | ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); |
1103 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | 1109 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; |
1110 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | ||
1111 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | ||
1112 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | ||
1104 | 1113 | ||
1105 | ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; | 1114 | ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; |
1106 | ht_conf.ampdu_density = req_ht_cap->ampdu_density; | 1115 | ht_conf.ampdu_density = req_ht_cap->ampdu_density; |
1107 | 1116 | ||
1108 | /* if bss configuration changed store the new one */ | 1117 | /* Bits 96-100 */ |
1109 | if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || | 1118 | tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12]; |
1110 | memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { | 1119 | |
1111 | changed |= BSS_CHANGED_HT; | 1120 | /* configure suppoerted Tx MCS according to requested MCS |
1112 | memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); | 1121 | * (based in most cases on Rx capabilities of peer) and self |
1113 | memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); | 1122 | * Tx MCS capabilities (as defined by low level driver HW |
1114 | } | 1123 | * Tx capabilities) */ |
1115 | } else { | 1124 | if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED)) |
1116 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) | 1125 | goto check_changed; |
1117 | changed |= BSS_CHANGED_HT; | ||
1118 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | ||
1119 | } | ||
1120 | 1126 | ||
1127 | /* Counting from 0 therfore + 1 */ | ||
1128 | if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF) | ||
1129 | max_tx_streams = ((tx_mcs_set_cap & | ||
1130 | IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1; | ||
1131 | |||
1132 | for (i = 0; i < max_tx_streams; i++) | ||
1133 | ht_conf.supp_mcs_set[i] = | ||
1134 | sband->ht_info.supp_mcs_set[i] & | ||
1135 | req_ht_cap->supp_mcs_set[i]; | ||
1136 | |||
1137 | if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM) | ||
1138 | for (i = IEEE80211_SUPP_MCS_SET_UEQM; | ||
1139 | i < IEEE80211_SUPP_MCS_SET_LEN; i++) | ||
1140 | ht_conf.supp_mcs_set[i] = | ||
1141 | sband->ht_info.supp_mcs_set[i] & | ||
1142 | req_ht_cap->supp_mcs_set[i]; | ||
1143 | |||
1144 | check_changed: | ||
1145 | /* if bss configuration changed store the new one */ | ||
1146 | if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || | ||
1147 | memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { | ||
1148 | changed |= BSS_CHANGED_HT; | ||
1149 | memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); | ||
1150 | memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); | ||
1151 | } | ||
1152 | out: | ||
1121 | return changed; | 1153 | return changed; |
1122 | } | 1154 | } |
1123 | 1155 | ||
@@ -1148,38 +1180,20 @@ void ieee80211_reset_erp_info(struct net_device *dev) | |||
1148 | } | 1180 | } |
1149 | 1181 | ||
1150 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 1182 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
1151 | struct sk_buff *skb, | 1183 | struct sk_buff *skb) |
1152 | struct ieee80211_tx_status *status) | ||
1153 | { | 1184 | { |
1154 | struct ieee80211_local *local = hw_to_local(hw); | 1185 | struct ieee80211_local *local = hw_to_local(hw); |
1155 | struct ieee80211_tx_status *saved; | 1186 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1156 | int tmp; | 1187 | int tmp; |
1157 | 1188 | ||
1158 | skb->dev = local->mdev; | 1189 | skb->dev = local->mdev; |
1159 | saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC); | ||
1160 | if (unlikely(!saved)) { | ||
1161 | if (net_ratelimit()) | ||
1162 | printk(KERN_WARNING "%s: Not enough memory, " | ||
1163 | "dropping tx status", skb->dev->name); | ||
1164 | /* should be dev_kfree_skb_irq, but due to this function being | ||
1165 | * named _irqsafe instead of just _irq we can't be sure that | ||
1166 | * people won't call it from non-irq contexts */ | ||
1167 | dev_kfree_skb_any(skb); | ||
1168 | return; | ||
1169 | } | ||
1170 | memcpy(saved, status, sizeof(struct ieee80211_tx_status)); | ||
1171 | /* copy pointer to saved status into skb->cb for use by tasklet */ | ||
1172 | memcpy(skb->cb, &saved, sizeof(saved)); | ||
1173 | |||
1174 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; | 1190 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; |
1175 | skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ? | 1191 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? |
1176 | &local->skb_queue : &local->skb_queue_unreliable, skb); | 1192 | &local->skb_queue : &local->skb_queue_unreliable, skb); |
1177 | tmp = skb_queue_len(&local->skb_queue) + | 1193 | tmp = skb_queue_len(&local->skb_queue) + |
1178 | skb_queue_len(&local->skb_queue_unreliable); | 1194 | skb_queue_len(&local->skb_queue_unreliable); |
1179 | while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && | 1195 | while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && |
1180 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { | 1196 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { |
1181 | memcpy(&saved, skb->cb, sizeof(saved)); | ||
1182 | kfree(saved); | ||
1183 | dev_kfree_skb_irq(skb); | 1197 | dev_kfree_skb_irq(skb); |
1184 | tmp--; | 1198 | tmp--; |
1185 | I802_DEBUG_INC(local->tx_status_drop); | 1199 | I802_DEBUG_INC(local->tx_status_drop); |
@@ -1193,7 +1207,6 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
1193 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 1207 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
1194 | struct sk_buff *skb; | 1208 | struct sk_buff *skb; |
1195 | struct ieee80211_rx_status rx_status; | 1209 | struct ieee80211_rx_status rx_status; |
1196 | struct ieee80211_tx_status *tx_status; | ||
1197 | struct ieee80211_ra_tid *ra_tid; | 1210 | struct ieee80211_ra_tid *ra_tid; |
1198 | 1211 | ||
1199 | while ((skb = skb_dequeue(&local->skb_queue)) || | 1212 | while ((skb = skb_dequeue(&local->skb_queue)) || |
@@ -1208,12 +1221,8 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
1208 | __ieee80211_rx(local_to_hw(local), skb, &rx_status); | 1221 | __ieee80211_rx(local_to_hw(local), skb, &rx_status); |
1209 | break; | 1222 | break; |
1210 | case IEEE80211_TX_STATUS_MSG: | 1223 | case IEEE80211_TX_STATUS_MSG: |
1211 | /* get pointer to saved status out of skb->cb */ | ||
1212 | memcpy(&tx_status, skb->cb, sizeof(tx_status)); | ||
1213 | skb->pkt_type = 0; | 1224 | skb->pkt_type = 0; |
1214 | ieee80211_tx_status(local_to_hw(local), | 1225 | ieee80211_tx_status(local_to_hw(local), skb); |
1215 | skb, tx_status); | ||
1216 | kfree(tx_status); | ||
1217 | break; | 1226 | break; |
1218 | case IEEE80211_DELBA_MSG: | 1227 | case IEEE80211_DELBA_MSG: |
1219 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 1228 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
@@ -1242,24 +1251,15 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
1242 | * Also, tx_packet_data in cb is restored from tx_control. */ | 1251 | * Also, tx_packet_data in cb is restored from tx_control. */ |
1243 | static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | 1252 | static void ieee80211_remove_tx_extra(struct ieee80211_local *local, |
1244 | struct ieee80211_key *key, | 1253 | struct ieee80211_key *key, |
1245 | struct sk_buff *skb, | 1254 | struct sk_buff *skb) |
1246 | struct ieee80211_tx_control *control) | ||
1247 | { | 1255 | { |
1248 | int hdrlen, iv_len, mic_len; | 1256 | int hdrlen, iv_len, mic_len; |
1249 | struct ieee80211_tx_packet_data *pkt_data; | 1257 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1250 | 1258 | ||
1251 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | 1259 | info->flags &= IEEE80211_TX_CTL_REQ_TX_STATUS | |
1252 | pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex; | 1260 | IEEE80211_TX_CTL_DO_NOT_ENCRYPT | |
1253 | pkt_data->flags = 0; | 1261 | IEEE80211_TX_CTL_REQUEUE | |
1254 | if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS) | 1262 | IEEE80211_TX_CTL_EAPOL_FRAME; |
1255 | pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS; | ||
1256 | if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT) | ||
1257 | pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT; | ||
1258 | if (control->flags & IEEE80211_TXCTL_REQUEUE) | ||
1259 | pkt_data->flags |= IEEE80211_TXPD_REQUEUE; | ||
1260 | if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME) | ||
1261 | pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME; | ||
1262 | pkt_data->queue = control->queue; | ||
1263 | 1263 | ||
1264 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1264 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1265 | 1265 | ||
@@ -1306,9 +1306,10 @@ no_key: | |||
1306 | 1306 | ||
1307 | static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | 1307 | static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, |
1308 | struct sta_info *sta, | 1308 | struct sta_info *sta, |
1309 | struct sk_buff *skb, | 1309 | struct sk_buff *skb) |
1310 | struct ieee80211_tx_status *status) | ||
1311 | { | 1310 | { |
1311 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1312 | |||
1312 | sta->tx_filtered_count++; | 1313 | sta->tx_filtered_count++; |
1313 | 1314 | ||
1314 | /* | 1315 | /* |
@@ -1316,7 +1317,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1316 | * packet. If the STA went to power save mode, this will happen | 1317 | * packet. If the STA went to power save mode, this will happen |
1317 | * when it wakes up for the next time. | 1318 | * when it wakes up for the next time. |
1318 | */ | 1319 | */ |
1319 | sta->flags |= WLAN_STA_CLEAR_PS_FILT; | 1320 | set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); |
1320 | 1321 | ||
1321 | /* | 1322 | /* |
1322 | * This code races in the following way: | 1323 | * This code races in the following way: |
@@ -1348,20 +1349,18 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1348 | * can be unknown, for example with different interrupt status | 1349 | * can be unknown, for example with different interrupt status |
1349 | * bits. | 1350 | * bits. |
1350 | */ | 1351 | */ |
1351 | if (sta->flags & WLAN_STA_PS && | 1352 | if (test_sta_flags(sta, WLAN_STA_PS) && |
1352 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | 1353 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { |
1353 | ieee80211_remove_tx_extra(local, sta->key, skb, | 1354 | ieee80211_remove_tx_extra(local, sta->key, skb); |
1354 | &status->control); | ||
1355 | skb_queue_tail(&sta->tx_filtered, skb); | 1355 | skb_queue_tail(&sta->tx_filtered, skb); |
1356 | return; | 1356 | return; |
1357 | } | 1357 | } |
1358 | 1358 | ||
1359 | if (!(sta->flags & WLAN_STA_PS) && | 1359 | if (!test_sta_flags(sta, WLAN_STA_PS) && |
1360 | !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) { | 1360 | !(info->flags & IEEE80211_TX_CTL_REQUEUE)) { |
1361 | /* Software retry the packet once */ | 1361 | /* Software retry the packet once */ |
1362 | status->control.flags |= IEEE80211_TXCTL_REQUEUE; | 1362 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
1363 | ieee80211_remove_tx_extra(local, sta->key, skb, | 1363 | ieee80211_remove_tx_extra(local, sta->key, skb); |
1364 | &status->control); | ||
1365 | dev_queue_xmit(skb); | 1364 | dev_queue_xmit(skb); |
1366 | return; | 1365 | return; |
1367 | } | 1366 | } |
@@ -1371,61 +1370,49 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1371 | "queue_len=%d PS=%d @%lu\n", | 1370 | "queue_len=%d PS=%d @%lu\n", |
1372 | wiphy_name(local->hw.wiphy), | 1371 | wiphy_name(local->hw.wiphy), |
1373 | skb_queue_len(&sta->tx_filtered), | 1372 | skb_queue_len(&sta->tx_filtered), |
1374 | !!(sta->flags & WLAN_STA_PS), jiffies); | 1373 | !!test_sta_flags(sta, WLAN_STA_PS), jiffies); |
1375 | dev_kfree_skb(skb); | 1374 | dev_kfree_skb(skb); |
1376 | } | 1375 | } |
1377 | 1376 | ||
1378 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | 1377 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |
1379 | struct ieee80211_tx_status *status) | ||
1380 | { | 1378 | { |
1381 | struct sk_buff *skb2; | 1379 | struct sk_buff *skb2; |
1382 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1380 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1383 | struct ieee80211_local *local = hw_to_local(hw); | 1381 | struct ieee80211_local *local = hw_to_local(hw); |
1382 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1384 | u16 frag, type; | 1383 | u16 frag, type; |
1385 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 1384 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
1386 | struct ieee80211_sub_if_data *sdata; | 1385 | struct ieee80211_sub_if_data *sdata; |
1387 | struct net_device *prev_dev = NULL; | 1386 | struct net_device *prev_dev = NULL; |
1388 | 1387 | ||
1389 | if (!status) { | ||
1390 | printk(KERN_ERR | ||
1391 | "%s: ieee80211_tx_status called with NULL status\n", | ||
1392 | wiphy_name(local->hw.wiphy)); | ||
1393 | dev_kfree_skb(skb); | ||
1394 | return; | ||
1395 | } | ||
1396 | |||
1397 | rcu_read_lock(); | 1388 | rcu_read_lock(); |
1398 | 1389 | ||
1399 | if (status->excessive_retries) { | 1390 | if (info->status.excessive_retries) { |
1400 | struct sta_info *sta; | 1391 | struct sta_info *sta; |
1401 | sta = sta_info_get(local, hdr->addr1); | 1392 | sta = sta_info_get(local, hdr->addr1); |
1402 | if (sta) { | 1393 | if (sta) { |
1403 | if (sta->flags & WLAN_STA_PS) { | 1394 | if (test_sta_flags(sta, WLAN_STA_PS)) { |
1404 | /* | 1395 | /* |
1405 | * The STA is in power save mode, so assume | 1396 | * The STA is in power save mode, so assume |
1406 | * that this TX packet failed because of that. | 1397 | * that this TX packet failed because of that. |
1407 | */ | 1398 | */ |
1408 | status->excessive_retries = 0; | 1399 | ieee80211_handle_filtered_frame(local, sta, skb); |
1409 | status->flags |= IEEE80211_TX_STATUS_TX_FILTERED; | ||
1410 | ieee80211_handle_filtered_frame(local, sta, | ||
1411 | skb, status); | ||
1412 | rcu_read_unlock(); | 1400 | rcu_read_unlock(); |
1413 | return; | 1401 | return; |
1414 | } | 1402 | } |
1415 | } | 1403 | } |
1416 | } | 1404 | } |
1417 | 1405 | ||
1418 | if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) { | 1406 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
1419 | struct sta_info *sta; | 1407 | struct sta_info *sta; |
1420 | sta = sta_info_get(local, hdr->addr1); | 1408 | sta = sta_info_get(local, hdr->addr1); |
1421 | if (sta) { | 1409 | if (sta) { |
1422 | ieee80211_handle_filtered_frame(local, sta, skb, | 1410 | ieee80211_handle_filtered_frame(local, sta, skb); |
1423 | status); | ||
1424 | rcu_read_unlock(); | 1411 | rcu_read_unlock(); |
1425 | return; | 1412 | return; |
1426 | } | 1413 | } |
1427 | } else | 1414 | } else |
1428 | rate_control_tx_status(local->mdev, skb, status); | 1415 | rate_control_tx_status(local->mdev, skb); |
1429 | 1416 | ||
1430 | rcu_read_unlock(); | 1417 | rcu_read_unlock(); |
1431 | 1418 | ||
@@ -1439,14 +1426,14 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1439 | frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; | 1426 | frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; |
1440 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; | 1427 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; |
1441 | 1428 | ||
1442 | if (status->flags & IEEE80211_TX_STATUS_ACK) { | 1429 | if (info->flags & IEEE80211_TX_STAT_ACK) { |
1443 | if (frag == 0) { | 1430 | if (frag == 0) { |
1444 | local->dot11TransmittedFrameCount++; | 1431 | local->dot11TransmittedFrameCount++; |
1445 | if (is_multicast_ether_addr(hdr->addr1)) | 1432 | if (is_multicast_ether_addr(hdr->addr1)) |
1446 | local->dot11MulticastTransmittedFrameCount++; | 1433 | local->dot11MulticastTransmittedFrameCount++; |
1447 | if (status->retry_count > 0) | 1434 | if (info->status.retry_count > 0) |
1448 | local->dot11RetryCount++; | 1435 | local->dot11RetryCount++; |
1449 | if (status->retry_count > 1) | 1436 | if (info->status.retry_count > 1) |
1450 | local->dot11MultipleRetryCount++; | 1437 | local->dot11MultipleRetryCount++; |
1451 | } | 1438 | } |
1452 | 1439 | ||
@@ -1483,7 +1470,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1483 | return; | 1470 | return; |
1484 | } | 1471 | } |
1485 | 1472 | ||
1486 | rthdr = (struct ieee80211_tx_status_rtap_hdr*) | 1473 | rthdr = (struct ieee80211_tx_status_rtap_hdr *) |
1487 | skb_push(skb, sizeof(*rthdr)); | 1474 | skb_push(skb, sizeof(*rthdr)); |
1488 | 1475 | ||
1489 | memset(rthdr, 0, sizeof(*rthdr)); | 1476 | memset(rthdr, 0, sizeof(*rthdr)); |
@@ -1492,17 +1479,17 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1492 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | 1479 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | |
1493 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); | 1480 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); |
1494 | 1481 | ||
1495 | if (!(status->flags & IEEE80211_TX_STATUS_ACK) && | 1482 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && |
1496 | !is_multicast_ether_addr(hdr->addr1)) | 1483 | !is_multicast_ether_addr(hdr->addr1)) |
1497 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | 1484 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); |
1498 | 1485 | ||
1499 | if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) && | 1486 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) && |
1500 | (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) | 1487 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) |
1501 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | 1488 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); |
1502 | else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) | 1489 | else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) |
1503 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | 1490 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); |
1504 | 1491 | ||
1505 | rthdr->data_retries = status->retry_count; | 1492 | rthdr->data_retries = info->status.retry_count; |
1506 | 1493 | ||
1507 | /* XXX: is this sufficient for BPF? */ | 1494 | /* XXX: is this sufficient for BPF? */ |
1508 | skb_set_mac_header(skb, 0); | 1495 | skb_set_mac_header(skb, 0); |
@@ -1652,12 +1639,32 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1652 | if (result < 0) | 1639 | if (result < 0) |
1653 | return result; | 1640 | return result; |
1654 | 1641 | ||
1642 | /* | ||
1643 | * We use the number of queues for feature tests (QoS, HT) internally | ||
1644 | * so restrict them appropriately. | ||
1645 | */ | ||
1646 | #ifdef CONFIG_MAC80211_QOS | ||
1647 | if (hw->queues > IEEE80211_MAX_QUEUES) | ||
1648 | hw->queues = IEEE80211_MAX_QUEUES; | ||
1649 | if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) | ||
1650 | hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; | ||
1651 | if (hw->queues < 4) | ||
1652 | hw->ampdu_queues = 0; | ||
1653 | #else | ||
1654 | hw->queues = 1; | ||
1655 | hw->ampdu_queues = 0; | ||
1656 | #endif | ||
1657 | |||
1655 | /* for now, mdev needs sub_if_data :/ */ | 1658 | /* for now, mdev needs sub_if_data :/ */ |
1656 | mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), | 1659 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data), |
1657 | "wmaster%d", ether_setup); | 1660 | "wmaster%d", ether_setup, |
1661 | ieee80211_num_queues(hw)); | ||
1658 | if (!mdev) | 1662 | if (!mdev) |
1659 | goto fail_mdev_alloc; | 1663 | goto fail_mdev_alloc; |
1660 | 1664 | ||
1665 | if (ieee80211_num_queues(hw) > 1) | ||
1666 | mdev->features |= NETIF_F_MULTI_QUEUE; | ||
1667 | |||
1661 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | 1668 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); |
1662 | mdev->ieee80211_ptr = &sdata->wdev; | 1669 | mdev->ieee80211_ptr = &sdata->wdev; |
1663 | sdata->wdev.wiphy = local->hw.wiphy; | 1670 | sdata->wdev.wiphy = local->hw.wiphy; |
@@ -1702,13 +1709,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1702 | 1709 | ||
1703 | local->hw.conf.beacon_int = 1000; | 1710 | local->hw.conf.beacon_int = 1000; |
1704 | 1711 | ||
1705 | local->wstats_flags |= local->hw.max_rssi ? | 1712 | local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | |
1706 | IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID; | 1713 | IEEE80211_HW_SIGNAL_DB | |
1707 | local->wstats_flags |= local->hw.max_signal ? | 1714 | IEEE80211_HW_SIGNAL_DBM) ? |
1708 | IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; | 1715 | IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; |
1709 | local->wstats_flags |= local->hw.max_noise ? | 1716 | local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ? |
1710 | IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID; | 1717 | IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID; |
1711 | if (local->hw.max_rssi < 0 || local->hw.max_noise < 0) | 1718 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
1712 | local->wstats_flags |= IW_QUAL_DBM; | 1719 | local->wstats_flags |= IW_QUAL_DBM; |
1713 | 1720 | ||
1714 | result = sta_info_start(local); | 1721 | result = sta_info_start(local); |
@@ -1858,7 +1865,9 @@ static int __init ieee80211_init(void) | |||
1858 | struct sk_buff *skb; | 1865 | struct sk_buff *skb; |
1859 | int ret; | 1866 | int ret; |
1860 | 1867 | ||
1861 | BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb)); | 1868 | BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb)); |
1869 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + | ||
1870 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); | ||
1862 | 1871 | ||
1863 | ret = rc80211_pid_init(); | 1872 | ret = rc80211_pid_init(); |
1864 | if (ret) | 1873 | if (ret) |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 697ef67f96b6..b5933b271491 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -315,6 +315,13 @@ struct mesh_table *mesh_table_alloc(int size_order) | |||
315 | return newtbl; | 315 | return newtbl; |
316 | } | 316 | } |
317 | 317 | ||
318 | static void __mesh_table_free(struct mesh_table *tbl) | ||
319 | { | ||
320 | kfree(tbl->hash_buckets); | ||
321 | kfree(tbl->hashwlock); | ||
322 | kfree(tbl); | ||
323 | } | ||
324 | |||
318 | void mesh_table_free(struct mesh_table *tbl, bool free_leafs) | 325 | void mesh_table_free(struct mesh_table *tbl, bool free_leafs) |
319 | { | 326 | { |
320 | struct hlist_head *mesh_hash; | 327 | struct hlist_head *mesh_hash; |
@@ -330,9 +337,7 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs) | |||
330 | } | 337 | } |
331 | spin_unlock(&tbl->hashwlock[i]); | 338 | spin_unlock(&tbl->hashwlock[i]); |
332 | } | 339 | } |
333 | kfree(tbl->hash_buckets); | 340 | __mesh_table_free(tbl); |
334 | kfree(tbl->hashwlock); | ||
335 | kfree(tbl); | ||
336 | } | 341 | } |
337 | 342 | ||
338 | static void ieee80211_mesh_path_timer(unsigned long data) | 343 | static void ieee80211_mesh_path_timer(unsigned long data) |
@@ -349,21 +354,16 @@ struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | |||
349 | { | 354 | { |
350 | struct mesh_table *newtbl; | 355 | struct mesh_table *newtbl; |
351 | struct hlist_head *oldhash; | 356 | struct hlist_head *oldhash; |
352 | struct hlist_node *p; | 357 | struct hlist_node *p, *q; |
353 | int err = 0; | ||
354 | int i; | 358 | int i; |
355 | 359 | ||
356 | if (atomic_read(&tbl->entries) | 360 | if (atomic_read(&tbl->entries) |
357 | < tbl->mean_chain_len * (tbl->hash_mask + 1)) { | 361 | < tbl->mean_chain_len * (tbl->hash_mask + 1)) |
358 | err = -EPERM; | ||
359 | goto endgrow; | 362 | goto endgrow; |
360 | } | ||
361 | 363 | ||
362 | newtbl = mesh_table_alloc(tbl->size_order + 1); | 364 | newtbl = mesh_table_alloc(tbl->size_order + 1); |
363 | if (!newtbl) { | 365 | if (!newtbl) |
364 | err = -ENOMEM; | ||
365 | goto endgrow; | 366 | goto endgrow; |
366 | } | ||
367 | 367 | ||
368 | newtbl->free_node = tbl->free_node; | 368 | newtbl->free_node = tbl->free_node; |
369 | newtbl->mean_chain_len = tbl->mean_chain_len; | 369 | newtbl->mean_chain_len = tbl->mean_chain_len; |
@@ -373,13 +373,19 @@ struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | |||
373 | oldhash = tbl->hash_buckets; | 373 | oldhash = tbl->hash_buckets; |
374 | for (i = 0; i <= tbl->hash_mask; i++) | 374 | for (i = 0; i <= tbl->hash_mask; i++) |
375 | hlist_for_each(p, &oldhash[i]) | 375 | hlist_for_each(p, &oldhash[i]) |
376 | tbl->copy_node(p, newtbl); | 376 | if (tbl->copy_node(p, newtbl) < 0) |
377 | goto errcopy; | ||
377 | 378 | ||
379 | return newtbl; | ||
380 | |||
381 | errcopy: | ||
382 | for (i = 0; i <= newtbl->hash_mask; i++) { | ||
383 | hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) | ||
384 | tbl->free_node(p, 0); | ||
385 | } | ||
386 | __mesh_table_free(tbl); | ||
378 | endgrow: | 387 | endgrow: |
379 | if (err) | 388 | return NULL; |
380 | return NULL; | ||
381 | else | ||
382 | return newtbl; | ||
383 | } | 389 | } |
384 | 390 | ||
385 | /** | 391 | /** |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 2e161f6d8288..669eafafe497 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -109,7 +109,7 @@ struct mesh_table { | |||
109 | __u32 hash_rnd; /* Used for hash generation */ | 109 | __u32 hash_rnd; /* Used for hash generation */ |
110 | atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ | 110 | atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ |
111 | void (*free_node) (struct hlist_node *p, bool free_leafs); | 111 | void (*free_node) (struct hlist_node *p, bool free_leafs); |
112 | void (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); | 112 | int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); |
113 | int size_order; | 113 | int size_order; |
114 | int mean_chain_len; | 114 | int mean_chain_len; |
115 | }; | 115 | }; |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index af0cd1e3e213..7fa149e230e6 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -26,7 +26,7 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae) | |||
26 | { | 26 | { |
27 | if (ae) | 27 | if (ae) |
28 | offset += 6; | 28 | offset += 6; |
29 | return le32_to_cpu(get_unaligned((__le32 *) (preq_elem + offset))); | 29 | return get_unaligned_le32(preq_elem + offset); |
30 | } | 30 | } |
31 | 31 | ||
32 | /* HWMP IE processing macros */ | 32 | /* HWMP IE processing macros */ |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 99c2d360888e..947b13b40726 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -158,19 +158,14 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
158 | if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) | 158 | if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) |
159 | return -ENOSPC; | 159 | return -ENOSPC; |
160 | 160 | ||
161 | err = -ENOMEM; | ||
161 | new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); | 162 | new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); |
162 | if (!new_mpath) { | 163 | if (!new_mpath) |
163 | atomic_dec(&sdata->u.sta.mpaths); | 164 | goto err_path_alloc; |
164 | err = -ENOMEM; | 165 | |
165 | goto endadd2; | ||
166 | } | ||
167 | new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); | 166 | new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); |
168 | if (!new_node) { | 167 | if (!new_node) |
169 | kfree(new_mpath); | 168 | goto err_node_alloc; |
170 | atomic_dec(&sdata->u.sta.mpaths); | ||
171 | err = -ENOMEM; | ||
172 | goto endadd2; | ||
173 | } | ||
174 | 169 | ||
175 | read_lock(&pathtbl_resize_lock); | 170 | read_lock(&pathtbl_resize_lock); |
176 | memcpy(new_mpath->dst, dst, ETH_ALEN); | 171 | memcpy(new_mpath->dst, dst, ETH_ALEN); |
@@ -189,16 +184,11 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
189 | 184 | ||
190 | spin_lock(&mesh_paths->hashwlock[hash_idx]); | 185 | spin_lock(&mesh_paths->hashwlock[hash_idx]); |
191 | 186 | ||
187 | err = -EEXIST; | ||
192 | hlist_for_each_entry(node, n, bucket, list) { | 188 | hlist_for_each_entry(node, n, bucket, list) { |
193 | mpath = node->mpath; | 189 | mpath = node->mpath; |
194 | if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN) | 190 | if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN) == 0) |
195 | == 0) { | 191 | goto err_exists; |
196 | err = -EEXIST; | ||
197 | atomic_dec(&sdata->u.sta.mpaths); | ||
198 | kfree(new_node); | ||
199 | kfree(new_mpath); | ||
200 | goto endadd; | ||
201 | } | ||
202 | } | 192 | } |
203 | 193 | ||
204 | hlist_add_head_rcu(&new_node->list, bucket); | 194 | hlist_add_head_rcu(&new_node->list, bucket); |
@@ -206,10 +196,9 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
206 | mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1)) | 196 | mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1)) |
207 | grow = 1; | 197 | grow = 1; |
208 | 198 | ||
209 | endadd: | ||
210 | spin_unlock(&mesh_paths->hashwlock[hash_idx]); | 199 | spin_unlock(&mesh_paths->hashwlock[hash_idx]); |
211 | read_unlock(&pathtbl_resize_lock); | 200 | read_unlock(&pathtbl_resize_lock); |
212 | if (!err && grow) { | 201 | if (grow) { |
213 | struct mesh_table *oldtbl, *newtbl; | 202 | struct mesh_table *oldtbl, *newtbl; |
214 | 203 | ||
215 | write_lock(&pathtbl_resize_lock); | 204 | write_lock(&pathtbl_resize_lock); |
@@ -217,7 +206,7 @@ endadd: | |||
217 | newtbl = mesh_table_grow(mesh_paths); | 206 | newtbl = mesh_table_grow(mesh_paths); |
218 | if (!newtbl) { | 207 | if (!newtbl) { |
219 | write_unlock(&pathtbl_resize_lock); | 208 | write_unlock(&pathtbl_resize_lock); |
220 | return -ENOMEM; | 209 | return 0; |
221 | } | 210 | } |
222 | rcu_assign_pointer(mesh_paths, newtbl); | 211 | rcu_assign_pointer(mesh_paths, newtbl); |
223 | write_unlock(&pathtbl_resize_lock); | 212 | write_unlock(&pathtbl_resize_lock); |
@@ -225,7 +214,16 @@ endadd: | |||
225 | synchronize_rcu(); | 214 | synchronize_rcu(); |
226 | mesh_table_free(oldtbl, false); | 215 | mesh_table_free(oldtbl, false); |
227 | } | 216 | } |
228 | endadd2: | 217 | return 0; |
218 | |||
219 | err_exists: | ||
220 | spin_unlock(&mesh_paths->hashwlock[hash_idx]); | ||
221 | read_unlock(&pathtbl_resize_lock); | ||
222 | kfree(new_node); | ||
223 | err_node_alloc: | ||
224 | kfree(new_mpath); | ||
225 | err_path_alloc: | ||
226 | atomic_dec(&sdata->u.sta.mpaths); | ||
229 | return err; | 227 | return err; |
230 | } | 228 | } |
231 | 229 | ||
@@ -460,25 +458,28 @@ static void mesh_path_node_free(struct hlist_node *p, bool free_leafs) | |||
460 | struct mpath_node *node = hlist_entry(p, struct mpath_node, list); | 458 | struct mpath_node *node = hlist_entry(p, struct mpath_node, list); |
461 | mpath = node->mpath; | 459 | mpath = node->mpath; |
462 | hlist_del_rcu(p); | 460 | hlist_del_rcu(p); |
463 | synchronize_rcu(); | ||
464 | if (free_leafs) | 461 | if (free_leafs) |
465 | kfree(mpath); | 462 | kfree(mpath); |
466 | kfree(node); | 463 | kfree(node); |
467 | } | 464 | } |
468 | 465 | ||
469 | static void mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | 466 | static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) |
470 | { | 467 | { |
471 | struct mesh_path *mpath; | 468 | struct mesh_path *mpath; |
472 | struct mpath_node *node, *new_node; | 469 | struct mpath_node *node, *new_node; |
473 | u32 hash_idx; | 470 | u32 hash_idx; |
474 | 471 | ||
472 | new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC); | ||
473 | if (new_node == NULL) | ||
474 | return -ENOMEM; | ||
475 | |||
475 | node = hlist_entry(p, struct mpath_node, list); | 476 | node = hlist_entry(p, struct mpath_node, list); |
476 | mpath = node->mpath; | 477 | mpath = node->mpath; |
477 | new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); | ||
478 | new_node->mpath = mpath; | 478 | new_node->mpath = mpath; |
479 | hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); | 479 | hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); |
480 | hlist_add_head(&new_node->list, | 480 | hlist_add_head(&new_node->list, |
481 | &newtbl->hash_buckets[hash_idx]); | 481 | &newtbl->hash_buckets[hash_idx]); |
482 | return 0; | ||
482 | } | 483 | } |
483 | 484 | ||
484 | int mesh_pathtbl_init(void) | 485 | int mesh_pathtbl_init(void) |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 37f0c2b94ae7..9efeb1f07025 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -79,7 +79,7 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | |||
79 | * | 79 | * |
80 | * @sta: mes peer link to restart | 80 | * @sta: mes peer link to restart |
81 | * | 81 | * |
82 | * Locking: this function must be called holding sta->plink_lock | 82 | * Locking: this function must be called holding sta->lock |
83 | */ | 83 | */ |
84 | static inline void mesh_plink_fsm_restart(struct sta_info *sta) | 84 | static inline void mesh_plink_fsm_restart(struct sta_info *sta) |
85 | { | 85 | { |
@@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
105 | if (!sta) | 105 | if (!sta) |
106 | return NULL; | 106 | return NULL; |
107 | 107 | ||
108 | sta->flags |= WLAN_STA_AUTHORIZED; | 108 | sta->flags = WLAN_STA_AUTHORIZED; |
109 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 109 | sta->supp_rates[local->hw.conf.channel->band] = rates; |
110 | 110 | ||
111 | return sta; | 111 | return sta; |
@@ -118,7 +118,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
118 | * | 118 | * |
119 | * All mesh paths with this peer as next hop will be flushed | 119 | * All mesh paths with this peer as next hop will be flushed |
120 | * | 120 | * |
121 | * Locking: the caller must hold sta->plink_lock | 121 | * Locking: the caller must hold sta->lock |
122 | */ | 122 | */ |
123 | static void __mesh_plink_deactivate(struct sta_info *sta) | 123 | static void __mesh_plink_deactivate(struct sta_info *sta) |
124 | { | 124 | { |
@@ -139,9 +139,9 @@ static void __mesh_plink_deactivate(struct sta_info *sta) | |||
139 | */ | 139 | */ |
140 | void mesh_plink_deactivate(struct sta_info *sta) | 140 | void mesh_plink_deactivate(struct sta_info *sta) |
141 | { | 141 | { |
142 | spin_lock_bh(&sta->plink_lock); | 142 | spin_lock_bh(&sta->lock); |
143 | __mesh_plink_deactivate(sta); | 143 | __mesh_plink_deactivate(sta); |
144 | spin_unlock_bh(&sta->plink_lock); | 144 | spin_unlock_bh(&sta->lock); |
145 | } | 145 | } |
146 | 146 | ||
147 | static int mesh_plink_frame_tx(struct net_device *dev, | 147 | static int mesh_plink_frame_tx(struct net_device *dev, |
@@ -270,10 +270,10 @@ static void mesh_plink_timer(unsigned long data) | |||
270 | */ | 270 | */ |
271 | sta = (struct sta_info *) data; | 271 | sta = (struct sta_info *) data; |
272 | 272 | ||
273 | spin_lock_bh(&sta->plink_lock); | 273 | spin_lock_bh(&sta->lock); |
274 | if (sta->ignore_plink_timer) { | 274 | if (sta->ignore_plink_timer) { |
275 | sta->ignore_plink_timer = false; | 275 | sta->ignore_plink_timer = false; |
276 | spin_unlock_bh(&sta->plink_lock); | 276 | spin_unlock_bh(&sta->lock); |
277 | return; | 277 | return; |
278 | } | 278 | } |
279 | mpl_dbg("Mesh plink timer for %s fired on state %d\n", | 279 | mpl_dbg("Mesh plink timer for %s fired on state %d\n", |
@@ -298,7 +298,7 @@ static void mesh_plink_timer(unsigned long data) | |||
298 | rand % sta->plink_timeout; | 298 | rand % sta->plink_timeout; |
299 | ++sta->plink_retries; | 299 | ++sta->plink_retries; |
300 | mod_plink_timer(sta, sta->plink_timeout); | 300 | mod_plink_timer(sta, sta->plink_timeout); |
301 | spin_unlock_bh(&sta->plink_lock); | 301 | spin_unlock_bh(&sta->lock); |
302 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 302 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, |
303 | 0, 0); | 303 | 0, 0); |
304 | break; | 304 | break; |
@@ -311,7 +311,7 @@ static void mesh_plink_timer(unsigned long data) | |||
311 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); | 311 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); |
312 | sta->plink_state = PLINK_HOLDING; | 312 | sta->plink_state = PLINK_HOLDING; |
313 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 313 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
314 | spin_unlock_bh(&sta->plink_lock); | 314 | spin_unlock_bh(&sta->lock); |
315 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, | 315 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, |
316 | reason); | 316 | reason); |
317 | break; | 317 | break; |
@@ -319,10 +319,10 @@ static void mesh_plink_timer(unsigned long data) | |||
319 | /* holding timer */ | 319 | /* holding timer */ |
320 | del_timer(&sta->plink_timer); | 320 | del_timer(&sta->plink_timer); |
321 | mesh_plink_fsm_restart(sta); | 321 | mesh_plink_fsm_restart(sta); |
322 | spin_unlock_bh(&sta->plink_lock); | 322 | spin_unlock_bh(&sta->lock); |
323 | break; | 323 | break; |
324 | default: | 324 | default: |
325 | spin_unlock_bh(&sta->plink_lock); | 325 | spin_unlock_bh(&sta->lock); |
326 | break; | 326 | break; |
327 | } | 327 | } |
328 | } | 328 | } |
@@ -344,16 +344,16 @@ int mesh_plink_open(struct sta_info *sta) | |||
344 | DECLARE_MAC_BUF(mac); | 344 | DECLARE_MAC_BUF(mac); |
345 | #endif | 345 | #endif |
346 | 346 | ||
347 | spin_lock_bh(&sta->plink_lock); | 347 | spin_lock_bh(&sta->lock); |
348 | get_random_bytes(&llid, 2); | 348 | get_random_bytes(&llid, 2); |
349 | sta->llid = llid; | 349 | sta->llid = llid; |
350 | if (sta->plink_state != PLINK_LISTEN) { | 350 | if (sta->plink_state != PLINK_LISTEN) { |
351 | spin_unlock_bh(&sta->plink_lock); | 351 | spin_unlock_bh(&sta->lock); |
352 | return -EBUSY; | 352 | return -EBUSY; |
353 | } | 353 | } |
354 | sta->plink_state = PLINK_OPN_SNT; | 354 | sta->plink_state = PLINK_OPN_SNT; |
355 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 355 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
356 | spin_unlock_bh(&sta->plink_lock); | 356 | spin_unlock_bh(&sta->lock); |
357 | mpl_dbg("Mesh plink: starting establishment with %s\n", | 357 | mpl_dbg("Mesh plink: starting establishment with %s\n", |
358 | print_mac(mac, sta->addr)); | 358 | print_mac(mac, sta->addr)); |
359 | 359 | ||
@@ -367,10 +367,10 @@ void mesh_plink_block(struct sta_info *sta) | |||
367 | DECLARE_MAC_BUF(mac); | 367 | DECLARE_MAC_BUF(mac); |
368 | #endif | 368 | #endif |
369 | 369 | ||
370 | spin_lock_bh(&sta->plink_lock); | 370 | spin_lock_bh(&sta->lock); |
371 | __mesh_plink_deactivate(sta); | 371 | __mesh_plink_deactivate(sta); |
372 | sta->plink_state = PLINK_BLOCKED; | 372 | sta->plink_state = PLINK_BLOCKED; |
373 | spin_unlock_bh(&sta->plink_lock); | 373 | spin_unlock_bh(&sta->lock); |
374 | } | 374 | } |
375 | 375 | ||
376 | int mesh_plink_close(struct sta_info *sta) | 376 | int mesh_plink_close(struct sta_info *sta) |
@@ -383,14 +383,14 @@ int mesh_plink_close(struct sta_info *sta) | |||
383 | 383 | ||
384 | mpl_dbg("Mesh plink: closing link with %s\n", | 384 | mpl_dbg("Mesh plink: closing link with %s\n", |
385 | print_mac(mac, sta->addr)); | 385 | print_mac(mac, sta->addr)); |
386 | spin_lock_bh(&sta->plink_lock); | 386 | spin_lock_bh(&sta->lock); |
387 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); | 387 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); |
388 | reason = sta->reason; | 388 | reason = sta->reason; |
389 | 389 | ||
390 | if (sta->plink_state == PLINK_LISTEN || | 390 | if (sta->plink_state == PLINK_LISTEN || |
391 | sta->plink_state == PLINK_BLOCKED) { | 391 | sta->plink_state == PLINK_BLOCKED) { |
392 | mesh_plink_fsm_restart(sta); | 392 | mesh_plink_fsm_restart(sta); |
393 | spin_unlock_bh(&sta->plink_lock); | 393 | spin_unlock_bh(&sta->lock); |
394 | return 0; | 394 | return 0; |
395 | } else if (sta->plink_state == PLINK_ESTAB) { | 395 | } else if (sta->plink_state == PLINK_ESTAB) { |
396 | __mesh_plink_deactivate(sta); | 396 | __mesh_plink_deactivate(sta); |
@@ -402,7 +402,7 @@ int mesh_plink_close(struct sta_info *sta) | |||
402 | sta->plink_state = PLINK_HOLDING; | 402 | sta->plink_state = PLINK_HOLDING; |
403 | llid = sta->llid; | 403 | llid = sta->llid; |
404 | plid = sta->plid; | 404 | plid = sta->plid; |
405 | spin_unlock_bh(&sta->plink_lock); | 405 | spin_unlock_bh(&sta->lock); |
406 | mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, | 406 | mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, |
407 | plid, reason); | 407 | plid, reason); |
408 | return 0; | 408 | return 0; |
@@ -490,7 +490,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
490 | /* avoid warning */ | 490 | /* avoid warning */ |
491 | break; | 491 | break; |
492 | } | 492 | } |
493 | spin_lock_bh(&sta->plink_lock); | 493 | spin_lock_bh(&sta->lock); |
494 | } else if (!sta) { | 494 | } else if (!sta) { |
495 | /* ftype == PLINK_OPEN */ | 495 | /* ftype == PLINK_OPEN */ |
496 | u64 rates; | 496 | u64 rates; |
@@ -512,9 +512,9 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
512 | return; | 512 | return; |
513 | } | 513 | } |
514 | event = OPN_ACPT; | 514 | event = OPN_ACPT; |
515 | spin_lock_bh(&sta->plink_lock); | 515 | spin_lock_bh(&sta->lock); |
516 | } else { | 516 | } else { |
517 | spin_lock_bh(&sta->plink_lock); | 517 | spin_lock_bh(&sta->lock); |
518 | switch (ftype) { | 518 | switch (ftype) { |
519 | case PLINK_OPEN: | 519 | case PLINK_OPEN: |
520 | if (!mesh_plink_free_count(sdata) || | 520 | if (!mesh_plink_free_count(sdata) || |
@@ -551,7 +551,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
551 | break; | 551 | break; |
552 | default: | 552 | default: |
553 | mpl_dbg("Mesh plink: unknown frame subtype\n"); | 553 | mpl_dbg("Mesh plink: unknown frame subtype\n"); |
554 | spin_unlock_bh(&sta->plink_lock); | 554 | spin_unlock_bh(&sta->lock); |
555 | rcu_read_unlock(); | 555 | rcu_read_unlock(); |
556 | return; | 556 | return; |
557 | } | 557 | } |
@@ -568,7 +568,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
568 | switch (event) { | 568 | switch (event) { |
569 | case CLS_ACPT: | 569 | case CLS_ACPT: |
570 | mesh_plink_fsm_restart(sta); | 570 | mesh_plink_fsm_restart(sta); |
571 | spin_unlock_bh(&sta->plink_lock); | 571 | spin_unlock_bh(&sta->lock); |
572 | break; | 572 | break; |
573 | case OPN_ACPT: | 573 | case OPN_ACPT: |
574 | sta->plink_state = PLINK_OPN_RCVD; | 574 | sta->plink_state = PLINK_OPN_RCVD; |
@@ -576,14 +576,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
576 | get_random_bytes(&llid, 2); | 576 | get_random_bytes(&llid, 2); |
577 | sta->llid = llid; | 577 | sta->llid = llid; |
578 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 578 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
579 | spin_unlock_bh(&sta->plink_lock); | 579 | spin_unlock_bh(&sta->lock); |
580 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 580 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, |
581 | 0, 0); | 581 | 0, 0); |
582 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, | 582 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, |
583 | llid, plid, 0); | 583 | llid, plid, 0); |
584 | break; | 584 | break; |
585 | default: | 585 | default: |
586 | spin_unlock_bh(&sta->plink_lock); | 586 | spin_unlock_bh(&sta->lock); |
587 | break; | 587 | break; |
588 | } | 588 | } |
589 | break; | 589 | break; |
@@ -603,7 +603,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
603 | sta->ignore_plink_timer = true; | 603 | sta->ignore_plink_timer = true; |
604 | 604 | ||
605 | llid = sta->llid; | 605 | llid = sta->llid; |
606 | spin_unlock_bh(&sta->plink_lock); | 606 | spin_unlock_bh(&sta->lock); |
607 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 607 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
608 | plid, reason); | 608 | plid, reason); |
609 | break; | 609 | break; |
@@ -612,7 +612,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
612 | sta->plink_state = PLINK_OPN_RCVD; | 612 | sta->plink_state = PLINK_OPN_RCVD; |
613 | sta->plid = plid; | 613 | sta->plid = plid; |
614 | llid = sta->llid; | 614 | llid = sta->llid; |
615 | spin_unlock_bh(&sta->plink_lock); | 615 | spin_unlock_bh(&sta->lock); |
616 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 616 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, |
617 | plid, 0); | 617 | plid, 0); |
618 | break; | 618 | break; |
@@ -622,10 +622,10 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
622 | dot11MeshConfirmTimeout(sdata))) | 622 | dot11MeshConfirmTimeout(sdata))) |
623 | sta->ignore_plink_timer = true; | 623 | sta->ignore_plink_timer = true; |
624 | 624 | ||
625 | spin_unlock_bh(&sta->plink_lock); | 625 | spin_unlock_bh(&sta->lock); |
626 | break; | 626 | break; |
627 | default: | 627 | default: |
628 | spin_unlock_bh(&sta->plink_lock); | 628 | spin_unlock_bh(&sta->lock); |
629 | break; | 629 | break; |
630 | } | 630 | } |
631 | break; | 631 | break; |
@@ -645,13 +645,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
645 | sta->ignore_plink_timer = true; | 645 | sta->ignore_plink_timer = true; |
646 | 646 | ||
647 | llid = sta->llid; | 647 | llid = sta->llid; |
648 | spin_unlock_bh(&sta->plink_lock); | 648 | spin_unlock_bh(&sta->lock); |
649 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 649 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
650 | plid, reason); | 650 | plid, reason); |
651 | break; | 651 | break; |
652 | case OPN_ACPT: | 652 | case OPN_ACPT: |
653 | llid = sta->llid; | 653 | llid = sta->llid; |
654 | spin_unlock_bh(&sta->plink_lock); | 654 | spin_unlock_bh(&sta->lock); |
655 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 655 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, |
656 | plid, 0); | 656 | plid, 0); |
657 | break; | 657 | break; |
@@ -659,12 +659,12 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
659 | del_timer(&sta->plink_timer); | 659 | del_timer(&sta->plink_timer); |
660 | sta->plink_state = PLINK_ESTAB; | 660 | sta->plink_state = PLINK_ESTAB; |
661 | mesh_plink_inc_estab_count(sdata); | 661 | mesh_plink_inc_estab_count(sdata); |
662 | spin_unlock_bh(&sta->plink_lock); | 662 | spin_unlock_bh(&sta->lock); |
663 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", | 663 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", |
664 | print_mac(mac, sta->addr)); | 664 | print_mac(mac, sta->addr)); |
665 | break; | 665 | break; |
666 | default: | 666 | default: |
667 | spin_unlock_bh(&sta->plink_lock); | 667 | spin_unlock_bh(&sta->lock); |
668 | break; | 668 | break; |
669 | } | 669 | } |
670 | break; | 670 | break; |
@@ -684,7 +684,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
684 | sta->ignore_plink_timer = true; | 684 | sta->ignore_plink_timer = true; |
685 | 685 | ||
686 | llid = sta->llid; | 686 | llid = sta->llid; |
687 | spin_unlock_bh(&sta->plink_lock); | 687 | spin_unlock_bh(&sta->lock); |
688 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 688 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
689 | plid, reason); | 689 | plid, reason); |
690 | break; | 690 | break; |
@@ -692,14 +692,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
692 | del_timer(&sta->plink_timer); | 692 | del_timer(&sta->plink_timer); |
693 | sta->plink_state = PLINK_ESTAB; | 693 | sta->plink_state = PLINK_ESTAB; |
694 | mesh_plink_inc_estab_count(sdata); | 694 | mesh_plink_inc_estab_count(sdata); |
695 | spin_unlock_bh(&sta->plink_lock); | 695 | spin_unlock_bh(&sta->lock); |
696 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", | 696 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", |
697 | print_mac(mac, sta->addr)); | 697 | print_mac(mac, sta->addr)); |
698 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 698 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, |
699 | plid, 0); | 699 | plid, 0); |
700 | break; | 700 | break; |
701 | default: | 701 | default: |
702 | spin_unlock_bh(&sta->plink_lock); | 702 | spin_unlock_bh(&sta->lock); |
703 | break; | 703 | break; |
704 | } | 704 | } |
705 | break; | 705 | break; |
@@ -713,18 +713,18 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
713 | sta->plink_state = PLINK_HOLDING; | 713 | sta->plink_state = PLINK_HOLDING; |
714 | llid = sta->llid; | 714 | llid = sta->llid; |
715 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 715 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
716 | spin_unlock_bh(&sta->plink_lock); | 716 | spin_unlock_bh(&sta->lock); |
717 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 717 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
718 | plid, reason); | 718 | plid, reason); |
719 | break; | 719 | break; |
720 | case OPN_ACPT: | 720 | case OPN_ACPT: |
721 | llid = sta->llid; | 721 | llid = sta->llid; |
722 | spin_unlock_bh(&sta->plink_lock); | 722 | spin_unlock_bh(&sta->lock); |
723 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 723 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, |
724 | plid, 0); | 724 | plid, 0); |
725 | break; | 725 | break; |
726 | default: | 726 | default: |
727 | spin_unlock_bh(&sta->plink_lock); | 727 | spin_unlock_bh(&sta->lock); |
728 | break; | 728 | break; |
729 | } | 729 | } |
730 | break; | 730 | break; |
@@ -734,7 +734,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
734 | if (del_timer(&sta->plink_timer)) | 734 | if (del_timer(&sta->plink_timer)) |
735 | sta->ignore_plink_timer = 1; | 735 | sta->ignore_plink_timer = 1; |
736 | mesh_plink_fsm_restart(sta); | 736 | mesh_plink_fsm_restart(sta); |
737 | spin_unlock_bh(&sta->plink_lock); | 737 | spin_unlock_bh(&sta->lock); |
738 | break; | 738 | break; |
739 | case OPN_ACPT: | 739 | case OPN_ACPT: |
740 | case CNF_ACPT: | 740 | case CNF_ACPT: |
@@ -742,19 +742,19 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
742 | case CNF_RJCT: | 742 | case CNF_RJCT: |
743 | llid = sta->llid; | 743 | llid = sta->llid; |
744 | reason = sta->reason; | 744 | reason = sta->reason; |
745 | spin_unlock_bh(&sta->plink_lock); | 745 | spin_unlock_bh(&sta->lock); |
746 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 746 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
747 | plid, reason); | 747 | plid, reason); |
748 | break; | 748 | break; |
749 | default: | 749 | default: |
750 | spin_unlock_bh(&sta->plink_lock); | 750 | spin_unlock_bh(&sta->lock); |
751 | } | 751 | } |
752 | break; | 752 | break; |
753 | default: | 753 | default: |
754 | /* should not get here, PLINK_BLOCKED is dealt with at the | 754 | /* should not get here, PLINK_BLOCKED is dealt with at the |
755 | * beggining of the function | 755 | * beggining of the function |
756 | */ | 756 | */ |
757 | spin_unlock_bh(&sta->plink_lock); | 757 | spin_unlock_bh(&sta->lock); |
758 | break; | 758 | break; |
759 | } | 759 | } |
760 | 760 | ||
diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c index 0f844f7895f1..1fcdf38cf60c 100644 --- a/net/mac80211/michael.c +++ b/net/mac80211/michael.c | |||
@@ -6,85 +6,58 @@ | |||
6 | * 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 |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | |||
10 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/bitops.h> | ||
11 | #include <asm/unaligned.h> | ||
11 | 12 | ||
12 | #include "michael.h" | 13 | #include "michael.h" |
13 | 14 | ||
14 | static inline u32 rotr(u32 val, int bits) | 15 | static void michael_block(struct michael_mic_ctx *mctx, u32 val) |
15 | { | ||
16 | return (val >> bits) | (val << (32 - bits)); | ||
17 | } | ||
18 | |||
19 | |||
20 | static inline u32 rotl(u32 val, int bits) | ||
21 | { | ||
22 | return (val << bits) | (val >> (32 - bits)); | ||
23 | } | ||
24 | |||
25 | |||
26 | static inline u32 xswap(u32 val) | ||
27 | { | ||
28 | return ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); | ||
29 | } | ||
30 | |||
31 | |||
32 | #define michael_block(l, r) \ | ||
33 | do { \ | ||
34 | r ^= rotl(l, 17); \ | ||
35 | l += r; \ | ||
36 | r ^= xswap(l); \ | ||
37 | l += r; \ | ||
38 | r ^= rotl(l, 3); \ | ||
39 | l += r; \ | ||
40 | r ^= rotr(l, 2); \ | ||
41 | l += r; \ | ||
42 | } while (0) | ||
43 | |||
44 | |||
45 | static inline u32 michael_get32(u8 *data) | ||
46 | { | 16 | { |
47 | return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); | 17 | mctx->l ^= val; |
18 | mctx->r ^= rol32(mctx->l, 17); | ||
19 | mctx->l += mctx->r; | ||
20 | mctx->r ^= ((mctx->l & 0xff00ff00) >> 8) | | ||
21 | ((mctx->l & 0x00ff00ff) << 8); | ||
22 | mctx->l += mctx->r; | ||
23 | mctx->r ^= rol32(mctx->l, 3); | ||
24 | mctx->l += mctx->r; | ||
25 | mctx->r ^= ror32(mctx->l, 2); | ||
26 | mctx->l += mctx->r; | ||
48 | } | 27 | } |
49 | 28 | ||
50 | 29 | static void michael_mic_hdr(struct michael_mic_ctx *mctx, | |
51 | static inline void michael_put32(u32 val, u8 *data) | 30 | const u8 *key, const u8 *da, const u8 *sa, u8 priority) |
52 | { | 31 | { |
53 | data[0] = val & 0xff; | 32 | mctx->l = get_unaligned_le32(key); |
54 | data[1] = (val >> 8) & 0xff; | 33 | mctx->r = get_unaligned_le32(key + 4); |
55 | data[2] = (val >> 16) & 0xff; | 34 | |
56 | data[3] = (val >> 24) & 0xff; | 35 | /* |
36 | * A pseudo header (DA, SA, Priority, 0, 0, 0) is used in Michael MIC | ||
37 | * calculation, but it is _not_ transmitted | ||
38 | */ | ||
39 | michael_block(mctx, get_unaligned_le32(da)); | ||
40 | michael_block(mctx, get_unaligned_le16(&da[4]) | | ||
41 | (get_unaligned_le16(sa) << 16)); | ||
42 | michael_block(mctx, get_unaligned_le32(&sa[2])); | ||
43 | michael_block(mctx, priority); | ||
57 | } | 44 | } |
58 | 45 | ||
59 | 46 | void michael_mic(const u8 *key, const u8 *da, const u8 *sa, u8 priority, | |
60 | void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority, | 47 | const u8 *data, size_t data_len, u8 *mic) |
61 | u8 *data, size_t data_len, u8 *mic) | ||
62 | { | 48 | { |
63 | u32 l, r, val; | 49 | u32 val; |
64 | size_t block, blocks, left; | 50 | size_t block, blocks, left; |
51 | struct michael_mic_ctx mctx; | ||
65 | 52 | ||
66 | l = michael_get32(key); | 53 | michael_mic_hdr(&mctx, key, da, sa, priority); |
67 | r = michael_get32(key + 4); | ||
68 | |||
69 | /* A pseudo header (DA, SA, Priority, 0, 0, 0) is used in Michael MIC | ||
70 | * calculation, but it is _not_ transmitted */ | ||
71 | l ^= michael_get32(da); | ||
72 | michael_block(l, r); | ||
73 | l ^= da[4] | (da[5] << 8) | (sa[0] << 16) | (sa[1] << 24); | ||
74 | michael_block(l, r); | ||
75 | l ^= michael_get32(&sa[2]); | ||
76 | michael_block(l, r); | ||
77 | l ^= priority; | ||
78 | michael_block(l, r); | ||
79 | 54 | ||
80 | /* Real data */ | 55 | /* Real data */ |
81 | blocks = data_len / 4; | 56 | blocks = data_len / 4; |
82 | left = data_len % 4; | 57 | left = data_len % 4; |
83 | 58 | ||
84 | for (block = 0; block < blocks; block++) { | 59 | for (block = 0; block < blocks; block++) |
85 | l ^= michael_get32(&data[block * 4]); | 60 | michael_block(&mctx, get_unaligned_le32(&data[block * 4])); |
86 | michael_block(l, r); | ||
87 | } | ||
88 | 61 | ||
89 | /* Partial block of 0..3 bytes and padding: 0x5a + 4..7 zeros to make | 62 | /* Partial block of 0..3 bytes and padding: 0x5a + 4..7 zeros to make |
90 | * total length a multiple of 4. */ | 63 | * total length a multiple of 4. */ |
@@ -94,11 +67,10 @@ void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority, | |||
94 | left--; | 67 | left--; |
95 | val |= data[blocks * 4 + left]; | 68 | val |= data[blocks * 4 + left]; |
96 | } | 69 | } |
97 | l ^= val; | ||
98 | michael_block(l, r); | ||
99 | /* last block is zero, so l ^ 0 = l */ | ||
100 | michael_block(l, r); | ||
101 | 70 | ||
102 | michael_put32(l, mic); | 71 | michael_block(&mctx, val); |
103 | michael_put32(r, mic + 4); | 72 | michael_block(&mctx, 0); |
73 | |||
74 | put_unaligned_le32(mctx.l, mic); | ||
75 | put_unaligned_le32(mctx.r, mic + 4); | ||
104 | } | 76 | } |
diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h index 2e6aebabeea1..69b4501f13ba 100644 --- a/net/mac80211/michael.h +++ b/net/mac80211/michael.h | |||
@@ -14,7 +14,11 @@ | |||
14 | 14 | ||
15 | #define MICHAEL_MIC_LEN 8 | 15 | #define MICHAEL_MIC_LEN 8 |
16 | 16 | ||
17 | void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority, | 17 | struct michael_mic_ctx { |
18 | u8 *data, size_t data_len, u8 *mic); | 18 | u32 l, r; |
19 | }; | ||
20 | |||
21 | void michael_mic(const u8 *key, const u8 *da, const u8 *sa, u8 priority, | ||
22 | const u8 *data, size_t data_len, u8 *mic); | ||
19 | 23 | ||
20 | #endif /* MICHAEL_H */ | 24 | #endif /* MICHAEL_H */ |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 4d2b582dd055..7f05820dc629 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -87,6 +87,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, | |||
87 | u8 *ssid, size_t ssid_len); | 87 | u8 *ssid, size_t ssid_len); |
88 | static int ieee80211_sta_config_auth(struct net_device *dev, | 88 | static int ieee80211_sta_config_auth(struct net_device *dev, |
89 | struct ieee80211_if_sta *ifsta); | 89 | struct ieee80211_if_sta *ifsta); |
90 | static void sta_rx_agg_session_timer_expired(unsigned long data); | ||
90 | 91 | ||
91 | 92 | ||
92 | void ieee802_11_parse_elems(u8 *start, size_t len, | 93 | void ieee802_11_parse_elems(u8 *start, size_t len, |
@@ -256,19 +257,8 @@ static void ieee80211_sta_def_wmm_params(struct net_device *dev, | |||
256 | qparam.cw_max = 1023; | 257 | qparam.cw_max = 1023; |
257 | qparam.txop = 0; | 258 | qparam.txop = 0; |
258 | 259 | ||
259 | for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++) | 260 | for (i = 0; i < local_to_hw(local)->queues; i++) |
260 | local->ops->conf_tx(local_to_hw(local), | 261 | local->ops->conf_tx(local_to_hw(local), i, &qparam); |
261 | i + IEEE80211_TX_QUEUE_DATA0, | ||
262 | &qparam); | ||
263 | |||
264 | if (ibss) { | ||
265 | /* IBSS uses different parameters for Beacon sending */ | ||
266 | qparam.cw_min++; | ||
267 | qparam.cw_min *= 2; | ||
268 | qparam.cw_min--; | ||
269 | local->ops->conf_tx(local_to_hw(local), | ||
270 | IEEE80211_TX_QUEUE_BEACON, &qparam); | ||
271 | } | ||
272 | } | 262 | } |
273 | } | 263 | } |
274 | 264 | ||
@@ -282,6 +272,12 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, | |||
282 | int count; | 272 | int count; |
283 | u8 *pos; | 273 | u8 *pos; |
284 | 274 | ||
275 | if (!(ifsta->flags & IEEE80211_STA_WMM_ENABLED)) | ||
276 | return; | ||
277 | |||
278 | if (!wmm_param) | ||
279 | return; | ||
280 | |||
285 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) | 281 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) |
286 | return; | 282 | return; |
287 | count = wmm_param[6] & 0x0f; | 283 | count = wmm_param[6] & 0x0f; |
@@ -305,29 +301,25 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, | |||
305 | 301 | ||
306 | switch (aci) { | 302 | switch (aci) { |
307 | case 1: | 303 | case 1: |
308 | queue = IEEE80211_TX_QUEUE_DATA3; | 304 | queue = 3; |
309 | if (acm) { | 305 | if (acm) |
310 | local->wmm_acm |= BIT(0) | BIT(3); | 306 | local->wmm_acm |= BIT(0) | BIT(3); |
311 | } | ||
312 | break; | 307 | break; |
313 | case 2: | 308 | case 2: |
314 | queue = IEEE80211_TX_QUEUE_DATA1; | 309 | queue = 1; |
315 | if (acm) { | 310 | if (acm) |
316 | local->wmm_acm |= BIT(4) | BIT(5); | 311 | local->wmm_acm |= BIT(4) | BIT(5); |
317 | } | ||
318 | break; | 312 | break; |
319 | case 3: | 313 | case 3: |
320 | queue = IEEE80211_TX_QUEUE_DATA0; | 314 | queue = 0; |
321 | if (acm) { | 315 | if (acm) |
322 | local->wmm_acm |= BIT(6) | BIT(7); | 316 | local->wmm_acm |= BIT(6) | BIT(7); |
323 | } | ||
324 | break; | 317 | break; |
325 | case 0: | 318 | case 0: |
326 | default: | 319 | default: |
327 | queue = IEEE80211_TX_QUEUE_DATA2; | 320 | queue = 2; |
328 | if (acm) { | 321 | if (acm) |
329 | local->wmm_acm |= BIT(1) | BIT(2); | 322 | local->wmm_acm |= BIT(1) | BIT(2); |
330 | } | ||
331 | break; | 323 | break; |
332 | } | 324 | } |
333 | 325 | ||
@@ -586,7 +578,7 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, | |||
586 | int encrypt) | 578 | int encrypt) |
587 | { | 579 | { |
588 | struct ieee80211_sub_if_data *sdata; | 580 | struct ieee80211_sub_if_data *sdata; |
589 | struct ieee80211_tx_packet_data *pkt_data; | 581 | struct ieee80211_tx_info *info; |
590 | 582 | ||
591 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 583 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
592 | skb->dev = sdata->local->mdev; | 584 | skb->dev = sdata->local->mdev; |
@@ -594,11 +586,11 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, | |||
594 | skb_set_network_header(skb, 0); | 586 | skb_set_network_header(skb, 0); |
595 | skb_set_transport_header(skb, 0); | 587 | skb_set_transport_header(skb, 0); |
596 | 588 | ||
597 | pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; | 589 | info = IEEE80211_SKB_CB(skb); |
598 | memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); | 590 | memset(info, 0, sizeof(struct ieee80211_tx_info)); |
599 | pkt_data->ifindex = sdata->dev->ifindex; | 591 | info->control.ifindex = sdata->dev->ifindex; |
600 | if (!encrypt) | 592 | if (!encrypt) |
601 | pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT; | 593 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; |
602 | 594 | ||
603 | dev_queue_xmit(skb); | 595 | dev_queue_xmit(skb); |
604 | } | 596 | } |
@@ -727,9 +719,8 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
727 | if (bss) { | 719 | if (bss) { |
728 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 720 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) |
729 | capab |= WLAN_CAPABILITY_PRIVACY; | 721 | capab |= WLAN_CAPABILITY_PRIVACY; |
730 | if (bss->wmm_ie) { | 722 | if (bss->wmm_ie) |
731 | wmm = 1; | 723 | wmm = 1; |
732 | } | ||
733 | 724 | ||
734 | /* get all rates supported by the device and the AP as | 725 | /* get all rates supported by the device and the AP as |
735 | * some APs don't like getting a superset of their rates | 726 | * some APs don't like getting a superset of their rates |
@@ -821,9 +812,32 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
821 | *pos++ = 1; /* WME ver */ | 812 | *pos++ = 1; /* WME ver */ |
822 | *pos++ = 0; | 813 | *pos++ = 0; |
823 | } | 814 | } |
815 | |||
824 | /* wmm support is a must to HT */ | 816 | /* wmm support is a must to HT */ |
825 | if (wmm && sband->ht_info.ht_supported) { | 817 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && |
826 | __le16 tmp = cpu_to_le16(sband->ht_info.cap); | 818 | sband->ht_info.ht_supported && bss->ht_add_ie) { |
819 | struct ieee80211_ht_addt_info *ht_add_info = | ||
820 | (struct ieee80211_ht_addt_info *)bss->ht_add_ie; | ||
821 | u16 cap = sband->ht_info.cap; | ||
822 | __le16 tmp; | ||
823 | u32 flags = local->hw.conf.channel->flags; | ||
824 | |||
825 | switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) { | ||
826 | case IEEE80211_HT_IE_CHA_SEC_ABOVE: | ||
827 | if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { | ||
828 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; | ||
829 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
830 | } | ||
831 | break; | ||
832 | case IEEE80211_HT_IE_CHA_SEC_BELOW: | ||
833 | if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { | ||
834 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; | ||
835 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
836 | } | ||
837 | break; | ||
838 | } | ||
839 | |||
840 | tmp = cpu_to_le16(cap); | ||
827 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); | 841 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); |
828 | *pos++ = WLAN_EID_HT_CAPABILITY; | 842 | *pos++ = WLAN_EID_HT_CAPABILITY; |
829 | *pos++ = sizeof(struct ieee80211_ht_cap); | 843 | *pos++ = sizeof(struct ieee80211_ht_cap); |
@@ -1141,8 +1155,8 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, | |||
1141 | struct ieee80211_mgmt *mgmt; | 1155 | struct ieee80211_mgmt *mgmt; |
1142 | u16 capab; | 1156 | u16 capab; |
1143 | 1157 | ||
1144 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 + | 1158 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); |
1145 | sizeof(mgmt->u.action.u.addba_resp)); | 1159 | |
1146 | if (!skb) { | 1160 | if (!skb) { |
1147 | printk(KERN_DEBUG "%s: failed to allocate buffer " | 1161 | printk(KERN_DEBUG "%s: failed to allocate buffer " |
1148 | "for addba resp frame\n", dev->name); | 1162 | "for addba resp frame\n", dev->name); |
@@ -1190,9 +1204,7 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, | |||
1190 | struct ieee80211_mgmt *mgmt; | 1204 | struct ieee80211_mgmt *mgmt; |
1191 | u16 capab; | 1205 | u16 capab; |
1192 | 1206 | ||
1193 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 + | 1207 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); |
1194 | sizeof(mgmt->u.action.u.addba_req)); | ||
1195 | |||
1196 | 1208 | ||
1197 | if (!skb) { | 1209 | if (!skb) { |
1198 | printk(KERN_ERR "%s: failed to allocate buffer " | 1210 | printk(KERN_ERR "%s: failed to allocate buffer " |
@@ -1293,7 +1305,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1293 | 1305 | ||
1294 | 1306 | ||
1295 | /* examine state machine */ | 1307 | /* examine state machine */ |
1296 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1308 | spin_lock_bh(&sta->lock); |
1297 | 1309 | ||
1298 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | 1310 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { |
1299 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1311 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -1360,7 +1372,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1360 | tid_agg_rx->stored_mpdu_num = 0; | 1372 | tid_agg_rx->stored_mpdu_num = 0; |
1361 | status = WLAN_STATUS_SUCCESS; | 1373 | status = WLAN_STATUS_SUCCESS; |
1362 | end: | 1374 | end: |
1363 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1375 | spin_unlock_bh(&sta->lock); |
1364 | 1376 | ||
1365 | end_no_lock: | 1377 | end_no_lock: |
1366 | ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, | 1378 | ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, |
@@ -1392,10 +1404,10 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1392 | 1404 | ||
1393 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 1405 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
1394 | 1406 | ||
1395 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1407 | spin_lock_bh(&sta->lock); |
1396 | 1408 | ||
1397 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 1409 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
1398 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1410 | spin_unlock_bh(&sta->lock); |
1399 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" | 1411 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" |
1400 | "%d\n", *state); | 1412 | "%d\n", *state); |
1401 | goto addba_resp_exit; | 1413 | goto addba_resp_exit; |
@@ -1403,7 +1415,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1403 | 1415 | ||
1404 | if (mgmt->u.action.u.addba_resp.dialog_token != | 1416 | if (mgmt->u.action.u.addba_resp.dialog_token != |
1405 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | 1417 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { |
1406 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1418 | spin_unlock_bh(&sta->lock); |
1407 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1419 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1408 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | 1420 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); |
1409 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1421 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
@@ -1427,7 +1439,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1427 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 1439 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); |
1428 | } | 1440 | } |
1429 | 1441 | ||
1430 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1442 | spin_unlock_bh(&sta->lock); |
1431 | printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid); | 1443 | printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid); |
1432 | } else { | 1444 | } else { |
1433 | printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); | 1445 | printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); |
@@ -1435,7 +1447,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1435 | sta->ampdu_mlme.addba_req_num[tid]++; | 1447 | sta->ampdu_mlme.addba_req_num[tid]++; |
1436 | /* this will allow the state check in stop_BA_session */ | 1448 | /* this will allow the state check in stop_BA_session */ |
1437 | *state = HT_AGG_STATE_OPERATIONAL; | 1449 | *state = HT_AGG_STATE_OPERATIONAL; |
1438 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1450 | spin_unlock_bh(&sta->lock); |
1439 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, | 1451 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, |
1440 | WLAN_BACK_INITIATOR); | 1452 | WLAN_BACK_INITIATOR); |
1441 | } | 1453 | } |
@@ -1454,8 +1466,7 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | |||
1454 | struct ieee80211_mgmt *mgmt; | 1466 | struct ieee80211_mgmt *mgmt; |
1455 | u16 params; | 1467 | u16 params; |
1456 | 1468 | ||
1457 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 + | 1469 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); |
1458 | sizeof(mgmt->u.action.u.delba)); | ||
1459 | 1470 | ||
1460 | if (!skb) { | 1471 | if (!skb) { |
1461 | printk(KERN_ERR "%s: failed to allocate buffer " | 1472 | printk(KERN_ERR "%s: failed to allocate buffer " |
@@ -1506,17 +1517,17 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | |||
1506 | } | 1517 | } |
1507 | 1518 | ||
1508 | /* check if TID is in operational state */ | 1519 | /* check if TID is in operational state */ |
1509 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1520 | spin_lock_bh(&sta->lock); |
1510 | if (sta->ampdu_mlme.tid_state_rx[tid] | 1521 | if (sta->ampdu_mlme.tid_state_rx[tid] |
1511 | != HT_AGG_STATE_OPERATIONAL) { | 1522 | != HT_AGG_STATE_OPERATIONAL) { |
1512 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1523 | spin_unlock_bh(&sta->lock); |
1513 | rcu_read_unlock(); | 1524 | rcu_read_unlock(); |
1514 | return; | 1525 | return; |
1515 | } | 1526 | } |
1516 | sta->ampdu_mlme.tid_state_rx[tid] = | 1527 | sta->ampdu_mlme.tid_state_rx[tid] = |
1517 | HT_AGG_STATE_REQ_STOP_BA_MSK | | 1528 | HT_AGG_STATE_REQ_STOP_BA_MSK | |
1518 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 1529 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
1519 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1530 | spin_unlock_bh(&sta->lock); |
1520 | 1531 | ||
1521 | /* stop HW Rx aggregation. ampdu_action existence | 1532 | /* stop HW Rx aggregation. ampdu_action existence |
1522 | * already verified in session init so we add the BUG_ON */ | 1533 | * already verified in session init so we add the BUG_ON */ |
@@ -1593,10 +1604,10 @@ static void ieee80211_sta_process_delba(struct net_device *dev, | |||
1593 | ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, | 1604 | ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, |
1594 | WLAN_BACK_INITIATOR, 0); | 1605 | WLAN_BACK_INITIATOR, 0); |
1595 | else { /* WLAN_BACK_RECIPIENT */ | 1606 | else { /* WLAN_BACK_RECIPIENT */ |
1596 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1607 | spin_lock_bh(&sta->lock); |
1597 | sta->ampdu_mlme.tid_state_tx[tid] = | 1608 | sta->ampdu_mlme.tid_state_tx[tid] = |
1598 | HT_AGG_STATE_OPERATIONAL; | 1609 | HT_AGG_STATE_OPERATIONAL; |
1599 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1610 | spin_unlock_bh(&sta->lock); |
1600 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, | 1611 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, |
1601 | WLAN_BACK_RECIPIENT); | 1612 | WLAN_BACK_RECIPIENT); |
1602 | } | 1613 | } |
@@ -1633,9 +1644,9 @@ void sta_addba_resp_timer_expired(unsigned long data) | |||
1633 | 1644 | ||
1634 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 1645 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
1635 | /* check if the TID waits for addBA response */ | 1646 | /* check if the TID waits for addBA response */ |
1636 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1647 | spin_lock_bh(&sta->lock); |
1637 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 1648 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
1638 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1649 | spin_unlock_bh(&sta->lock); |
1639 | *state = HT_AGG_STATE_IDLE; | 1650 | *state = HT_AGG_STATE_IDLE; |
1640 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | 1651 | printk(KERN_DEBUG "timer expired on tid %d but we are not " |
1641 | "expecting addBA response there", tid); | 1652 | "expecting addBA response there", tid); |
@@ -1646,7 +1657,7 @@ void sta_addba_resp_timer_expired(unsigned long data) | |||
1646 | 1657 | ||
1647 | /* go through the state check in stop_BA_session */ | 1658 | /* go through the state check in stop_BA_session */ |
1648 | *state = HT_AGG_STATE_OPERATIONAL; | 1659 | *state = HT_AGG_STATE_OPERATIONAL; |
1649 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1660 | spin_unlock_bh(&sta->lock); |
1650 | ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, | 1661 | ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, |
1651 | WLAN_BACK_INITIATOR); | 1662 | WLAN_BACK_INITIATOR); |
1652 | 1663 | ||
@@ -1659,7 +1670,7 @@ timer_expired_exit: | |||
1659 | * resetting it after each frame that arrives from the originator. | 1670 | * resetting it after each frame that arrives from the originator. |
1660 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | 1671 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. |
1661 | */ | 1672 | */ |
1662 | void sta_rx_agg_session_timer_expired(unsigned long data) | 1673 | static void sta_rx_agg_session_timer_expired(unsigned long data) |
1663 | { | 1674 | { |
1664 | /* not an elegant detour, but there is no choice as the timer passes | 1675 | /* not an elegant detour, but there is no choice as the timer passes |
1665 | * only one argument, and various sta_info are needed here, so init | 1676 | * only one argument, and various sta_info are needed here, so init |
@@ -1848,9 +1859,8 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev, | |||
1848 | " (reason=%d)\n", | 1859 | " (reason=%d)\n", |
1849 | dev->name, print_mac(mac, mgmt->sa), reason_code); | 1860 | dev->name, print_mac(mac, mgmt->sa), reason_code); |
1850 | 1861 | ||
1851 | if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) { | 1862 | if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) |
1852 | printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); | 1863 | printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); |
1853 | } | ||
1854 | 1864 | ||
1855 | if (ifsta->state == IEEE80211_AUTHENTICATE || | 1865 | if (ifsta->state == IEEE80211_AUTHENTICATE || |
1856 | ifsta->state == IEEE80211_ASSOCIATE || | 1866 | ifsta->state == IEEE80211_ASSOCIATE || |
@@ -2013,8 +2023,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2013 | local->hw.conf.channel->center_freq, | 2023 | local->hw.conf.channel->center_freq, |
2014 | ifsta->ssid, ifsta->ssid_len); | 2024 | ifsta->ssid, ifsta->ssid_len); |
2015 | if (bss) { | 2025 | if (bss) { |
2016 | sta->last_rssi = bss->rssi; | ||
2017 | sta->last_signal = bss->signal; | 2026 | sta->last_signal = bss->signal; |
2027 | sta->last_qual = bss->qual; | ||
2018 | sta->last_noise = bss->noise; | 2028 | sta->last_noise = bss->noise; |
2019 | ieee80211_rx_bss_put(dev, bss); | 2029 | ieee80211_rx_bss_put(dev, bss); |
2020 | } | 2030 | } |
@@ -2038,8 +2048,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2038 | * to between the sta_info_alloc() and sta_info_insert() above. | 2048 | * to between the sta_info_alloc() and sta_info_insert() above. |
2039 | */ | 2049 | */ |
2040 | 2050 | ||
2041 | sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | | 2051 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | |
2042 | WLAN_STA_AUTHORIZED; | 2052 | WLAN_STA_AUTHORIZED); |
2043 | 2053 | ||
2044 | rates = 0; | 2054 | rates = 0; |
2045 | basic_rates = 0; | 2055 | basic_rates = 0; |
@@ -2083,7 +2093,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2083 | else | 2093 | else |
2084 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 2094 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
2085 | 2095 | ||
2086 | if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) { | 2096 | if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && |
2097 | (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { | ||
2087 | struct ieee80211_ht_bss_info bss_info; | 2098 | struct ieee80211_ht_bss_info bss_info; |
2088 | ieee80211_ht_cap_ie_to_ht_info( | 2099 | ieee80211_ht_cap_ie_to_ht_info( |
2089 | (struct ieee80211_ht_cap *) | 2100 | (struct ieee80211_ht_cap *) |
@@ -2096,8 +2107,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2096 | 2107 | ||
2097 | rate_control_rate_init(sta, local); | 2108 | rate_control_rate_init(sta, local); |
2098 | 2109 | ||
2099 | if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { | 2110 | if (elems.wmm_param) { |
2100 | sta->flags |= WLAN_STA_WME; | 2111 | set_sta_flags(sta, WLAN_STA_WME); |
2101 | rcu_read_unlock(); | 2112 | rcu_read_unlock(); |
2102 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 2113 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, |
2103 | elems.wmm_param_len); | 2114 | elems.wmm_param_len); |
@@ -2281,6 +2292,7 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) | |||
2281 | kfree(bss->rsn_ie); | 2292 | kfree(bss->rsn_ie); |
2282 | kfree(bss->wmm_ie); | 2293 | kfree(bss->wmm_ie); |
2283 | kfree(bss->ht_ie); | 2294 | kfree(bss->ht_ie); |
2295 | kfree(bss->ht_add_ie); | ||
2284 | kfree(bss_mesh_id(bss)); | 2296 | kfree(bss_mesh_id(bss)); |
2285 | kfree(bss_mesh_cfg(bss)); | 2297 | kfree(bss_mesh_cfg(bss)); |
2286 | kfree(bss); | 2298 | kfree(bss); |
@@ -2331,7 +2343,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2331 | int res, rates, i, j; | 2343 | int res, rates, i, j; |
2332 | struct sk_buff *skb; | 2344 | struct sk_buff *skb; |
2333 | struct ieee80211_mgmt *mgmt; | 2345 | struct ieee80211_mgmt *mgmt; |
2334 | struct ieee80211_tx_control control; | 2346 | struct ieee80211_tx_info *control; |
2335 | struct rate_selection ratesel; | 2347 | struct rate_selection ratesel; |
2336 | u8 *pos; | 2348 | u8 *pos; |
2337 | struct ieee80211_sub_if_data *sdata; | 2349 | struct ieee80211_sub_if_data *sdata; |
@@ -2419,21 +2431,22 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2419 | memcpy(pos, &bss->supp_rates[8], rates); | 2431 | memcpy(pos, &bss->supp_rates[8], rates); |
2420 | } | 2432 | } |
2421 | 2433 | ||
2422 | memset(&control, 0, sizeof(control)); | 2434 | control = IEEE80211_SKB_CB(skb); |
2435 | |||
2423 | rate_control_get_rate(dev, sband, skb, &ratesel); | 2436 | rate_control_get_rate(dev, sband, skb, &ratesel); |
2424 | if (!ratesel.rate) { | 2437 | if (ratesel.rate_idx < 0) { |
2425 | printk(KERN_DEBUG "%s: Failed to determine TX rate " | 2438 | printk(KERN_DEBUG "%s: Failed to determine TX rate " |
2426 | "for IBSS beacon\n", dev->name); | 2439 | "for IBSS beacon\n", dev->name); |
2427 | break; | 2440 | break; |
2428 | } | 2441 | } |
2429 | control.vif = &sdata->vif; | 2442 | control->control.vif = &sdata->vif; |
2430 | control.tx_rate = ratesel.rate; | 2443 | control->tx_rate_idx = ratesel.rate_idx; |
2431 | if (sdata->bss_conf.use_short_preamble && | 2444 | if (sdata->bss_conf.use_short_preamble && |
2432 | ratesel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) | 2445 | sband->bitrates[ratesel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) |
2433 | control.flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; | 2446 | control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; |
2434 | control.antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 2447 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; |
2435 | control.flags |= IEEE80211_TXCTL_NO_ACK; | 2448 | control->flags |= IEEE80211_TX_CTL_NO_ACK; |
2436 | control.retry_limit = 1; | 2449 | control->control.retry_limit = 1; |
2437 | 2450 | ||
2438 | ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); | 2451 | ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); |
2439 | if (ifsta->probe_resp) { | 2452 | if (ifsta->probe_resp) { |
@@ -2448,8 +2461,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2448 | } | 2461 | } |
2449 | 2462 | ||
2450 | if (local->ops->beacon_update && | 2463 | if (local->ops->beacon_update && |
2451 | local->ops->beacon_update(local_to_hw(local), | 2464 | local->ops->beacon_update(local_to_hw(local), skb) == 0) { |
2452 | skb, &control) == 0) { | ||
2453 | printk(KERN_DEBUG "%s: Configured IBSS beacon " | 2465 | printk(KERN_DEBUG "%s: Configured IBSS beacon " |
2454 | "template\n", dev->name); | 2466 | "template\n", dev->name); |
2455 | skb = NULL; | 2467 | skb = NULL; |
@@ -2657,6 +2669,26 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2657 | bss->ht_ie_len = 0; | 2669 | bss->ht_ie_len = 0; |
2658 | } | 2670 | } |
2659 | 2671 | ||
2672 | if (elems.ht_info_elem && | ||
2673 | (!bss->ht_add_ie || | ||
2674 | bss->ht_add_ie_len != elems.ht_info_elem_len || | ||
2675 | memcmp(bss->ht_add_ie, elems.ht_info_elem, | ||
2676 | elems.ht_info_elem_len))) { | ||
2677 | kfree(bss->ht_add_ie); | ||
2678 | bss->ht_add_ie = | ||
2679 | kmalloc(elems.ht_info_elem_len + 2, GFP_ATOMIC); | ||
2680 | if (bss->ht_add_ie) { | ||
2681 | memcpy(bss->ht_add_ie, elems.ht_info_elem - 2, | ||
2682 | elems.ht_info_elem_len + 2); | ||
2683 | bss->ht_add_ie_len = elems.ht_info_elem_len + 2; | ||
2684 | } else | ||
2685 | bss->ht_add_ie_len = 0; | ||
2686 | } else if (!elems.ht_info_elem && bss->ht_add_ie) { | ||
2687 | kfree(bss->ht_add_ie); | ||
2688 | bss->ht_add_ie = NULL; | ||
2689 | bss->ht_add_ie_len = 0; | ||
2690 | } | ||
2691 | |||
2660 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 2692 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); |
2661 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 2693 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); |
2662 | 2694 | ||
@@ -2682,9 +2714,9 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2682 | 2714 | ||
2683 | bss->timestamp = beacon_timestamp; | 2715 | bss->timestamp = beacon_timestamp; |
2684 | bss->last_update = jiffies; | 2716 | bss->last_update = jiffies; |
2685 | bss->rssi = rx_status->ssi; | ||
2686 | bss->signal = rx_status->signal; | 2717 | bss->signal = rx_status->signal; |
2687 | bss->noise = rx_status->noise; | 2718 | bss->noise = rx_status->noise; |
2719 | bss->qual = rx_status->qual; | ||
2688 | if (!beacon && !bss->probe_resp) | 2720 | if (!beacon && !bss->probe_resp) |
2689 | bss->probe_resp = true; | 2721 | bss->probe_resp = true; |
2690 | 2722 | ||
@@ -2879,10 +2911,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2879 | 2911 | ||
2880 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); | 2912 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); |
2881 | 2913 | ||
2882 | if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { | 2914 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, |
2883 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 2915 | elems.wmm_param_len); |
2884 | elems.wmm_param_len); | ||
2885 | } | ||
2886 | 2916 | ||
2887 | /* Do not send changes to driver if we are scanning. This removes | 2917 | /* Do not send changes to driver if we are scanning. This removes |
2888 | * requirement that driver's bss_info_changed function needs to be | 2918 | * requirement that driver's bss_info_changed function needs to be |
@@ -3478,9 +3508,9 @@ static int ieee80211_sta_config_auth(struct net_device *dev, | |||
3478 | !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) | 3508 | !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) |
3479 | continue; | 3509 | continue; |
3480 | 3510 | ||
3481 | if (!selected || top_rssi < bss->rssi) { | 3511 | if (!selected || top_rssi < bss->signal) { |
3482 | selected = bss; | 3512 | selected = bss; |
3483 | top_rssi = bss->rssi; | 3513 | top_rssi = bss->signal; |
3484 | } | 3514 | } |
3485 | } | 3515 | } |
3486 | if (selected) | 3516 | if (selected) |
@@ -3557,10 +3587,12 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
3557 | bss->beacon_int = local->hw.conf.beacon_int; | 3587 | bss->beacon_int = local->hw.conf.beacon_int; |
3558 | bss->last_update = jiffies; | 3588 | bss->last_update = jiffies; |
3559 | bss->capability = WLAN_CAPABILITY_IBSS; | 3589 | bss->capability = WLAN_CAPABILITY_IBSS; |
3560 | if (sdata->default_key) { | 3590 | |
3591 | if (sdata->default_key) | ||
3561 | bss->capability |= WLAN_CAPABILITY_PRIVACY; | 3592 | bss->capability |= WLAN_CAPABILITY_PRIVACY; |
3562 | } else | 3593 | else |
3563 | sdata->drop_unencrypted = 0; | 3594 | sdata->drop_unencrypted = 0; |
3595 | |||
3564 | bss->supp_rates_len = sband->n_bitrates; | 3596 | bss->supp_rates_len = sband->n_bitrates; |
3565 | pos = bss->supp_rates; | 3597 | pos = bss->supp_rates; |
3566 | for (i = 0; i < sband->n_bitrates; i++) { | 3598 | for (i = 0; i < sband->n_bitrates; i++) { |
@@ -4114,8 +4146,8 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4114 | IW_EV_FREQ_LEN); | 4146 | IW_EV_FREQ_LEN); |
4115 | memset(&iwe, 0, sizeof(iwe)); | 4147 | memset(&iwe, 0, sizeof(iwe)); |
4116 | iwe.cmd = IWEVQUAL; | 4148 | iwe.cmd = IWEVQUAL; |
4117 | iwe.u.qual.qual = bss->signal; | 4149 | iwe.u.qual.qual = bss->qual; |
4118 | iwe.u.qual.level = bss->rssi; | 4150 | iwe.u.qual.level = bss->signal; |
4119 | iwe.u.qual.noise = bss->noise; | 4151 | iwe.u.qual.noise = bss->noise; |
4120 | iwe.u.qual.updated = local->wstats_flags; | 4152 | iwe.u.qual.updated = local->wstats_flags; |
4121 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4153 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, |
@@ -4146,6 +4178,14 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4146 | bss->rsn_ie); | 4178 | bss->rsn_ie); |
4147 | } | 4179 | } |
4148 | 4180 | ||
4181 | if (bss && bss->ht_ie) { | ||
4182 | memset(&iwe, 0, sizeof(iwe)); | ||
4183 | iwe.cmd = IWEVGENIE; | ||
4184 | iwe.u.data.length = bss->ht_ie_len; | ||
4185 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | ||
4186 | bss->ht_ie); | ||
4187 | } | ||
4188 | |||
4149 | if (bss && bss->supp_rates_len > 0) { | 4189 | if (bss && bss->supp_rates_len > 0) { |
4150 | /* display all supported rates in readable format */ | 4190 | /* display all supported rates in readable format */ |
4151 | char *p = current_ev + IW_EV_LCP_LEN; | 4191 | char *p = current_ev + IW_EV_LCP_LEN; |
@@ -4247,6 +4287,7 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) | |||
4247 | { | 4287 | { |
4248 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 4288 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
4249 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 4289 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4290 | |||
4250 | kfree(ifsta->extra_ie); | 4291 | kfree(ifsta->extra_ie); |
4251 | if (len == 0) { | 4292 | if (len == 0) { |
4252 | ifsta->extra_ie = NULL; | 4293 | ifsta->extra_ie = NULL; |
@@ -4264,9 +4305,9 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) | |||
4264 | } | 4305 | } |
4265 | 4306 | ||
4266 | 4307 | ||
4267 | struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, | 4308 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, |
4268 | struct sk_buff *skb, u8 *bssid, | 4309 | struct sk_buff *skb, u8 *bssid, |
4269 | u8 *addr) | 4310 | u8 *addr) |
4270 | { | 4311 | { |
4271 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 4312 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
4272 | struct sta_info *sta; | 4313 | struct sta_info *sta; |
@@ -4290,7 +4331,7 @@ struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, | |||
4290 | if (!sta) | 4331 | if (!sta) |
4291 | return NULL; | 4332 | return NULL; |
4292 | 4333 | ||
4293 | sta->flags |= WLAN_STA_AUTHORIZED; | 4334 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); |
4294 | 4335 | ||
4295 | sta->supp_rates[local->hw.conf.channel->band] = | 4336 | sta->supp_rates[local->hw.conf.channel->band] = |
4296 | sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band]; | 4337 | sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band]; |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 841df93807fc..0388c090dfe9 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -176,20 +176,24 @@ void rate_control_get_rate(struct net_device *dev, | |||
176 | rcu_read_lock(); | 176 | rcu_read_lock(); |
177 | sta = sta_info_get(local, hdr->addr1); | 177 | sta = sta_info_get(local, hdr->addr1); |
178 | 178 | ||
179 | memset(sel, 0, sizeof(struct rate_selection)); | 179 | sel->rate_idx = -1; |
180 | sel->nonerp_idx = -1; | ||
181 | sel->probe_idx = -1; | ||
180 | 182 | ||
181 | ref->ops->get_rate(ref->priv, dev, sband, skb, sel); | 183 | ref->ops->get_rate(ref->priv, dev, sband, skb, sel); |
182 | 184 | ||
185 | BUG_ON(sel->rate_idx < 0); | ||
186 | |||
183 | /* Select a non-ERP backup rate. */ | 187 | /* Select a non-ERP backup rate. */ |
184 | if (!sel->nonerp) { | 188 | if (sel->nonerp_idx < 0) { |
185 | for (i = 0; i < sband->n_bitrates; i++) { | 189 | for (i = 0; i < sband->n_bitrates; i++) { |
186 | struct ieee80211_rate *rate = &sband->bitrates[i]; | 190 | struct ieee80211_rate *rate = &sband->bitrates[i]; |
187 | if (sel->rate->bitrate < rate->bitrate) | 191 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) |
188 | break; | 192 | break; |
189 | 193 | ||
190 | if (rate_supported(sta, sband->band, i) && | 194 | if (rate_supported(sta, sband->band, i) && |
191 | !(rate->flags & IEEE80211_RATE_ERP_G)) | 195 | !(rate->flags & IEEE80211_RATE_ERP_G)) |
192 | sel->nonerp = rate; | 196 | sel->nonerp_idx = i; |
193 | } | 197 | } |
194 | } | 198 | } |
195 | 199 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5b45f33cb766..0ed9c8a2f56f 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -19,22 +19,22 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "sta_info.h" | 20 | #include "sta_info.h" |
21 | 21 | ||
22 | /* TODO: kdoc */ | 22 | /** |
23 | * struct rate_selection - rate selection for rate control algos | ||
24 | * @rate: selected transmission rate index | ||
25 | * @nonerp: Non-ERP rate to use instead if ERP cannot be used | ||
26 | * @probe: rate for probing (or -1) | ||
27 | * | ||
28 | */ | ||
23 | struct rate_selection { | 29 | struct rate_selection { |
24 | /* Selected transmission rate */ | 30 | s8 rate_idx, nonerp_idx, probe_idx; |
25 | struct ieee80211_rate *rate; | ||
26 | /* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */ | ||
27 | struct ieee80211_rate *nonerp; | ||
28 | /* probe with this rate, or NULL for no probing */ | ||
29 | struct ieee80211_rate *probe; | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | struct rate_control_ops { | 33 | struct rate_control_ops { |
33 | struct module *module; | 34 | struct module *module; |
34 | const char *name; | 35 | const char *name; |
35 | void (*tx_status)(void *priv, struct net_device *dev, | 36 | void (*tx_status)(void *priv, struct net_device *dev, |
36 | struct sk_buff *skb, | 37 | struct sk_buff *skb); |
37 | struct ieee80211_tx_status *status); | ||
38 | void (*get_rate)(void *priv, struct net_device *dev, | 38 | void (*get_rate)(void *priv, struct net_device *dev, |
39 | struct ieee80211_supported_band *band, | 39 | struct ieee80211_supported_band *band, |
40 | struct sk_buff *skb, | 40 | struct sk_buff *skb, |
@@ -76,13 +76,12 @@ struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); | |||
76 | void rate_control_put(struct rate_control_ref *ref); | 76 | void rate_control_put(struct rate_control_ref *ref); |
77 | 77 | ||
78 | static inline void rate_control_tx_status(struct net_device *dev, | 78 | static inline void rate_control_tx_status(struct net_device *dev, |
79 | struct sk_buff *skb, | 79 | struct sk_buff *skb) |
80 | struct ieee80211_tx_status *status) | ||
81 | { | 80 | { |
82 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 81 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
83 | struct rate_control_ref *ref = local->rate_ctrl; | 82 | struct rate_control_ref *ref = local->rate_ctrl; |
84 | 83 | ||
85 | ref->ops->tx_status(ref->priv, dev, skb, status); | 84 | ref->ops->tx_status(ref->priv, dev, skb); |
86 | } | 85 | } |
87 | 86 | ||
88 | 87 | ||
@@ -138,7 +137,7 @@ static inline int rate_supported(struct sta_info *sta, | |||
138 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); | 137 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); |
139 | } | 138 | } |
140 | 139 | ||
141 | static inline int | 140 | static inline s8 |
142 | rate_lowest_index(struct ieee80211_local *local, | 141 | rate_lowest_index(struct ieee80211_local *local, |
143 | struct ieee80211_supported_band *sband, | 142 | struct ieee80211_supported_band *sband, |
144 | struct sta_info *sta) | 143 | struct sta_info *sta) |
@@ -155,14 +154,6 @@ rate_lowest_index(struct ieee80211_local *local, | |||
155 | return 0; | 154 | return 0; |
156 | } | 155 | } |
157 | 156 | ||
158 | static inline struct ieee80211_rate * | ||
159 | rate_lowest(struct ieee80211_local *local, | ||
160 | struct ieee80211_supported_band *sband, | ||
161 | struct sta_info *sta) | ||
162 | { | ||
163 | return &sband->bitrates[rate_lowest_index(local, sband, sta)]; | ||
164 | } | ||
165 | |||
166 | 157 | ||
167 | /* functions for rate control related to a device */ | 158 | /* functions for rate control related to a device */ |
168 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 159 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index 04afc13ed825..2078803d3581 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h | |||
@@ -61,7 +61,7 @@ enum rc_pid_event_type { | |||
61 | union rc_pid_event_data { | 61 | union rc_pid_event_data { |
62 | /* RC_PID_EVENT_TX_STATUS */ | 62 | /* RC_PID_EVENT_TX_STATUS */ |
63 | struct { | 63 | struct { |
64 | struct ieee80211_tx_status tx_status; | 64 | struct ieee80211_tx_info tx_status; |
65 | }; | 65 | }; |
66 | /* RC_PID_EVENT_TYPE_RATE_CHANGE */ | 66 | /* RC_PID_EVENT_TYPE_RATE_CHANGE */ |
67 | /* RC_PID_EVENT_TYPE_TX_RATE */ | 67 | /* RC_PID_EVENT_TYPE_TX_RATE */ |
@@ -158,7 +158,7 @@ struct rc_pid_debugfs_entries { | |||
158 | }; | 158 | }; |
159 | 159 | ||
160 | void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, | 160 | void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, |
161 | struct ieee80211_tx_status *stat); | 161 | struct ieee80211_tx_info *stat); |
162 | 162 | ||
163 | void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf, | 163 | void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf, |
164 | int index, int rate); | 164 | int index, int rate); |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index a849b745bdb5..e8945413e4a2 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -237,8 +237,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
237 | } | 237 | } |
238 | 238 | ||
239 | static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | 239 | static void rate_control_pid_tx_status(void *priv, struct net_device *dev, |
240 | struct sk_buff *skb, | 240 | struct sk_buff *skb) |
241 | struct ieee80211_tx_status *status) | ||
242 | { | 241 | { |
243 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 242 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
244 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 243 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -248,6 +247,7 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
248 | struct rc_pid_sta_info *spinfo; | 247 | struct rc_pid_sta_info *spinfo; |
249 | unsigned long period; | 248 | unsigned long period; |
250 | struct ieee80211_supported_band *sband; | 249 | struct ieee80211_supported_band *sband; |
250 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
251 | 251 | ||
252 | rcu_read_lock(); | 252 | rcu_read_lock(); |
253 | 253 | ||
@@ -266,28 +266,28 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
266 | 266 | ||
267 | /* Ignore all frames that were sent with a different rate than the rate | 267 | /* Ignore all frames that were sent with a different rate than the rate |
268 | * we currently advise mac80211 to use. */ | 268 | * we currently advise mac80211 to use. */ |
269 | if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx]) | 269 | if (info->tx_rate_idx != sta->txrate_idx) |
270 | goto unlock; | 270 | goto unlock; |
271 | 271 | ||
272 | spinfo = sta->rate_ctrl_priv; | 272 | spinfo = sta->rate_ctrl_priv; |
273 | spinfo->tx_num_xmit++; | 273 | spinfo->tx_num_xmit++; |
274 | 274 | ||
275 | #ifdef CONFIG_MAC80211_DEBUGFS | 275 | #ifdef CONFIG_MAC80211_DEBUGFS |
276 | rate_control_pid_event_tx_status(&spinfo->events, status); | 276 | rate_control_pid_event_tx_status(&spinfo->events, info); |
277 | #endif | 277 | #endif |
278 | 278 | ||
279 | /* We count frames that totally failed to be transmitted as two bad | 279 | /* We count frames that totally failed to be transmitted as two bad |
280 | * frames, those that made it out but had some retries as one good and | 280 | * frames, those that made it out but had some retries as one good and |
281 | * one bad frame. */ | 281 | * one bad frame. */ |
282 | if (status->excessive_retries) { | 282 | if (info->status.excessive_retries) { |
283 | spinfo->tx_num_failed += 2; | 283 | spinfo->tx_num_failed += 2; |
284 | spinfo->tx_num_xmit++; | 284 | spinfo->tx_num_xmit++; |
285 | } else if (status->retry_count) { | 285 | } else if (info->status.retry_count) { |
286 | spinfo->tx_num_failed++; | 286 | spinfo->tx_num_failed++; |
287 | spinfo->tx_num_xmit++; | 287 | spinfo->tx_num_xmit++; |
288 | } | 288 | } |
289 | 289 | ||
290 | if (status->excessive_retries) { | 290 | if (info->status.excessive_retries) { |
291 | sta->tx_retry_failed++; | 291 | sta->tx_retry_failed++; |
292 | sta->tx_num_consecutive_failures++; | 292 | sta->tx_num_consecutive_failures++; |
293 | sta->tx_num_mpdu_fail++; | 293 | sta->tx_num_mpdu_fail++; |
@@ -295,8 +295,8 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
295 | sta->tx_num_consecutive_failures = 0; | 295 | sta->tx_num_consecutive_failures = 0; |
296 | sta->tx_num_mpdu_ok++; | 296 | sta->tx_num_mpdu_ok++; |
297 | } | 297 | } |
298 | sta->tx_retry_count += status->retry_count; | 298 | sta->tx_retry_count += info->status.retry_count; |
299 | sta->tx_num_mpdu_fail += status->retry_count; | 299 | sta->tx_num_mpdu_fail += info->status.retry_count; |
300 | 300 | ||
301 | /* Update PID controller state. */ | 301 | /* Update PID controller state. */ |
302 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 302 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
@@ -330,7 +330,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | |||
330 | fc = le16_to_cpu(hdr->frame_control); | 330 | fc = le16_to_cpu(hdr->frame_control); |
331 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 331 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
332 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 332 | is_multicast_ether_addr(hdr->addr1) || !sta) { |
333 | sel->rate = rate_lowest(local, sband, sta); | 333 | sel->rate_idx = rate_lowest_index(local, sband, sta); |
334 | rcu_read_unlock(); | 334 | rcu_read_unlock(); |
335 | return; | 335 | return; |
336 | } | 336 | } |
@@ -349,7 +349,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | |||
349 | 349 | ||
350 | rcu_read_unlock(); | 350 | rcu_read_unlock(); |
351 | 351 | ||
352 | sel->rate = &sband->bitrates[rateidx]; | 352 | sel->rate_idx = rateidx; |
353 | 353 | ||
354 | #ifdef CONFIG_MAC80211_DEBUGFS | 354 | #ifdef CONFIG_MAC80211_DEBUGFS |
355 | rate_control_pid_event_tx_rate( | 355 | rate_control_pid_event_tx_rate( |
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index ff5c380f3c13..8121d3bc6835 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c | |||
@@ -39,11 +39,11 @@ static void rate_control_pid_event(struct rc_pid_event_buffer *buf, | |||
39 | } | 39 | } |
40 | 40 | ||
41 | void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, | 41 | void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, |
42 | struct ieee80211_tx_status *stat) | 42 | struct ieee80211_tx_info *stat) |
43 | { | 43 | { |
44 | union rc_pid_event_data evd; | 44 | union rc_pid_event_data evd; |
45 | 45 | ||
46 | memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_status)); | 46 | memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_info)); |
47 | rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd); | 47 | rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd); |
48 | } | 48 | } |
49 | 49 | ||
@@ -167,8 +167,8 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, | |||
167 | switch (ev->type) { | 167 | switch (ev->type) { |
168 | case RC_PID_EVENT_TYPE_TX_STATUS: | 168 | case RC_PID_EVENT_TYPE_TX_STATUS: |
169 | p += snprintf(pb + p, length - p, "tx_status %u %u", | 169 | p += snprintf(pb + p, length - p, "tx_status %u %u", |
170 | ev->data.tx_status.excessive_retries, | 170 | ev->data.tx_status.status.excessive_retries, |
171 | ev->data.tx_status.retry_count); | 171 | ev->data.tx_status.status.retry_count); |
172 | break; | 172 | break; |
173 | case RC_PID_EVENT_TYPE_RATE_CHANGE: | 173 | case RC_PID_EVENT_TYPE_RATE_CHANGE: |
174 | p += snprintf(pb + p, length - p, "rate_change %d %d", | 174 | p += snprintf(pb + p, length - p, "rate_change %d %d", |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0941e5d6a522..a3643fd86af9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -77,6 +77,134 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status, | |||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | 79 | ||
80 | static int | ||
81 | ieee80211_rx_radiotap_len(struct ieee80211_local *local, | ||
82 | struct ieee80211_rx_status *status) | ||
83 | { | ||
84 | int len; | ||
85 | |||
86 | /* always present fields */ | ||
87 | len = sizeof(struct ieee80211_radiotap_header) + 9; | ||
88 | |||
89 | if (status->flag & RX_FLAG_TSFT) | ||
90 | len += 8; | ||
91 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB || | ||
92 | local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
93 | len += 1; | ||
94 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | ||
95 | len += 1; | ||
96 | |||
97 | if (len & 1) /* padding for RX_FLAGS if necessary */ | ||
98 | len++; | ||
99 | |||
100 | /* make sure radiotap starts at a naturally aligned address */ | ||
101 | if (len % 8) | ||
102 | len = roundup(len, 8); | ||
103 | |||
104 | return len; | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * ieee80211_add_rx_radiotap_header - add radiotap header | ||
109 | * | ||
110 | * add a radiotap header containing all the fields which the hardware provided. | ||
111 | */ | ||
112 | static void | ||
113 | ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | ||
114 | struct sk_buff *skb, | ||
115 | struct ieee80211_rx_status *status, | ||
116 | struct ieee80211_rate *rate, | ||
117 | int rtap_len) | ||
118 | { | ||
119 | struct ieee80211_radiotap_header *rthdr; | ||
120 | unsigned char *pos; | ||
121 | |||
122 | rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); | ||
123 | memset(rthdr, 0, rtap_len); | ||
124 | |||
125 | /* radiotap header, set always present flags */ | ||
126 | rthdr->it_present = | ||
127 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | ||
128 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
129 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
130 | (1 << IEEE80211_RADIOTAP_ANTENNA) | | ||
131 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); | ||
132 | rthdr->it_len = cpu_to_le16(rtap_len); | ||
133 | |||
134 | pos = (unsigned char *)(rthdr+1); | ||
135 | |||
136 | /* the order of the following fields is important */ | ||
137 | |||
138 | /* IEEE80211_RADIOTAP_TSFT */ | ||
139 | if (status->flag & RX_FLAG_TSFT) { | ||
140 | *(__le64 *)pos = cpu_to_le64(status->mactime); | ||
141 | rthdr->it_present |= | ||
142 | cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); | ||
143 | pos += 8; | ||
144 | } | ||
145 | |||
146 | /* IEEE80211_RADIOTAP_FLAGS */ | ||
147 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | ||
148 | *pos |= IEEE80211_RADIOTAP_F_FCS; | ||
149 | pos++; | ||
150 | |||
151 | /* IEEE80211_RADIOTAP_RATE */ | ||
152 | *pos = rate->bitrate / 5; | ||
153 | pos++; | ||
154 | |||
155 | /* IEEE80211_RADIOTAP_CHANNEL */ | ||
156 | *(__le16 *)pos = cpu_to_le16(status->freq); | ||
157 | pos += 2; | ||
158 | if (status->band == IEEE80211_BAND_5GHZ) | ||
159 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
160 | IEEE80211_CHAN_5GHZ); | ||
161 | else | ||
162 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_DYN | | ||
163 | IEEE80211_CHAN_2GHZ); | ||
164 | pos += 2; | ||
165 | |||
166 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ | ||
167 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { | ||
168 | *pos = status->signal; | ||
169 | rthdr->it_present |= | ||
170 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); | ||
171 | pos++; | ||
172 | } | ||
173 | |||
174 | /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ | ||
175 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) { | ||
176 | *pos = status->noise; | ||
177 | rthdr->it_present |= | ||
178 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE); | ||
179 | pos++; | ||
180 | } | ||
181 | |||
182 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ | ||
183 | |||
184 | /* IEEE80211_RADIOTAP_ANTENNA */ | ||
185 | *pos = status->antenna; | ||
186 | pos++; | ||
187 | |||
188 | /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */ | ||
189 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) { | ||
190 | *pos = status->signal; | ||
191 | rthdr->it_present |= | ||
192 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL); | ||
193 | pos++; | ||
194 | } | ||
195 | |||
196 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ | ||
197 | |||
198 | /* IEEE80211_RADIOTAP_RX_FLAGS */ | ||
199 | /* ensure 2 byte alignment for the 2 byte field as required */ | ||
200 | if ((pos - (unsigned char *)rthdr) & 1) | ||
201 | pos++; | ||
202 | /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ | ||
203 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | ||
204 | *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); | ||
205 | pos += 2; | ||
206 | } | ||
207 | |||
80 | /* | 208 | /* |
81 | * This function copies a received frame to all monitor interfaces and | 209 | * This function copies a received frame to all monitor interfaces and |
82 | * returns a cleaned-up SKB that no longer includes the FCS nor the | 210 | * returns a cleaned-up SKB that no longer includes the FCS nor the |
@@ -89,17 +217,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
89 | { | 217 | { |
90 | struct ieee80211_sub_if_data *sdata; | 218 | struct ieee80211_sub_if_data *sdata; |
91 | int needed_headroom = 0; | 219 | int needed_headroom = 0; |
92 | struct ieee80211_radiotap_header *rthdr; | ||
93 | __le64 *rttsft = NULL; | ||
94 | struct ieee80211_rtap_fixed_data { | ||
95 | u8 flags; | ||
96 | u8 rate; | ||
97 | __le16 chan_freq; | ||
98 | __le16 chan_flags; | ||
99 | u8 antsignal; | ||
100 | u8 padding_for_rxflags; | ||
101 | __le16 rx_flags; | ||
102 | } __attribute__ ((packed)) *rtfixed; | ||
103 | struct sk_buff *skb, *skb2; | 220 | struct sk_buff *skb, *skb2; |
104 | struct net_device *prev_dev = NULL; | 221 | struct net_device *prev_dev = NULL; |
105 | int present_fcs_len = 0; | 222 | int present_fcs_len = 0; |
@@ -116,8 +233,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
116 | if (status->flag & RX_FLAG_RADIOTAP) | 233 | if (status->flag & RX_FLAG_RADIOTAP) |
117 | rtap_len = ieee80211_get_radiotap_len(origskb->data); | 234 | rtap_len = ieee80211_get_radiotap_len(origskb->data); |
118 | else | 235 | else |
119 | /* room for radiotap header, always present fields and TSFT */ | 236 | /* room for the radiotap header based on driver features */ |
120 | needed_headroom = sizeof(*rthdr) + sizeof(*rtfixed) + 8; | 237 | needed_headroom = ieee80211_rx_radiotap_len(local, status); |
121 | 238 | ||
122 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 239 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
123 | present_fcs_len = FCS_LEN; | 240 | present_fcs_len = FCS_LEN; |
@@ -163,55 +280,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
163 | } | 280 | } |
164 | 281 | ||
165 | /* if necessary, prepend radiotap information */ | 282 | /* if necessary, prepend radiotap information */ |
166 | if (!(status->flag & RX_FLAG_RADIOTAP)) { | 283 | if (!(status->flag & RX_FLAG_RADIOTAP)) |
167 | rtfixed = (void *) skb_push(skb, sizeof(*rtfixed)); | 284 | ieee80211_add_rx_radiotap_header(local, skb, status, rate, |
168 | rtap_len = sizeof(*rthdr) + sizeof(*rtfixed); | 285 | needed_headroom); |
169 | if (status->flag & RX_FLAG_TSFT) { | ||
170 | rttsft = (void *) skb_push(skb, sizeof(*rttsft)); | ||
171 | rtap_len += 8; | ||
172 | } | ||
173 | rthdr = (void *) skb_push(skb, sizeof(*rthdr)); | ||
174 | memset(rthdr, 0, sizeof(*rthdr)); | ||
175 | memset(rtfixed, 0, sizeof(*rtfixed)); | ||
176 | rthdr->it_present = | ||
177 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | ||
178 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
179 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
180 | (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | | ||
181 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); | ||
182 | rtfixed->flags = 0; | ||
183 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | ||
184 | rtfixed->flags |= IEEE80211_RADIOTAP_F_FCS; | ||
185 | |||
186 | if (rttsft) { | ||
187 | *rttsft = cpu_to_le64(status->mactime); | ||
188 | rthdr->it_present |= | ||
189 | cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); | ||
190 | } | ||
191 | |||
192 | /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ | ||
193 | rtfixed->rx_flags = 0; | ||
194 | if (status->flag & | ||
195 | (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | ||
196 | rtfixed->rx_flags |= | ||
197 | cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); | ||
198 | |||
199 | rtfixed->rate = rate->bitrate / 5; | ||
200 | |||
201 | rtfixed->chan_freq = cpu_to_le16(status->freq); | ||
202 | |||
203 | if (status->band == IEEE80211_BAND_5GHZ) | ||
204 | rtfixed->chan_flags = | ||
205 | cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
206 | IEEE80211_CHAN_5GHZ); | ||
207 | else | ||
208 | rtfixed->chan_flags = | ||
209 | cpu_to_le16(IEEE80211_CHAN_DYN | | ||
210 | IEEE80211_CHAN_2GHZ); | ||
211 | |||
212 | rtfixed->antsignal = status->ssi; | ||
213 | rthdr->it_len = cpu_to_le16(rtap_len); | ||
214 | } | ||
215 | 286 | ||
216 | skb_reset_mac_header(skb); | 287 | skb_reset_mac_header(skb); |
217 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 288 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -275,11 +346,6 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
275 | } | 346 | } |
276 | } | 347 | } |
277 | 348 | ||
278 | I802_DEBUG_INC(rx->local->wme_rx_queue[tid]); | ||
279 | /* only a debug counter, sta might not be assigned properly yet */ | ||
280 | if (rx->sta) | ||
281 | I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]); | ||
282 | |||
283 | rx->queue = tid; | 349 | rx->queue = tid; |
284 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. | 350 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. |
285 | * For now, set skb->priority to 0 for other cases. */ | 351 | * For now, set skb->priority to 0 for other cases. */ |
@@ -321,51 +387,9 @@ static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) | |||
321 | } | 387 | } |
322 | 388 | ||
323 | 389 | ||
324 | static u32 ieee80211_rx_load_stats(struct ieee80211_local *local, | ||
325 | struct sk_buff *skb, | ||
326 | struct ieee80211_rx_status *status, | ||
327 | struct ieee80211_rate *rate) | ||
328 | { | ||
329 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
330 | u32 load = 0, hdrtime; | ||
331 | |||
332 | /* Estimate total channel use caused by this frame */ | ||
333 | |||
334 | /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values, | ||
335 | * 1 usec = 1/8 * (1080 / 10) = 13.5 */ | ||
336 | |||
337 | if (status->band == IEEE80211_BAND_5GHZ || | ||
338 | (status->band == IEEE80211_BAND_5GHZ && | ||
339 | rate->flags & IEEE80211_RATE_ERP_G)) | ||
340 | hdrtime = CHAN_UTIL_HDR_SHORT; | ||
341 | else | ||
342 | hdrtime = CHAN_UTIL_HDR_LONG; | ||
343 | |||
344 | load = hdrtime; | ||
345 | if (!is_multicast_ether_addr(hdr->addr1)) | ||
346 | load += hdrtime; | ||
347 | |||
348 | /* TODO: optimise again */ | ||
349 | load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate; | ||
350 | |||
351 | /* Divide channel_use by 8 to avoid wrapping around the counter */ | ||
352 | load >>= CHAN_UTIL_SHIFT; | ||
353 | |||
354 | return load; | ||
355 | } | ||
356 | |||
357 | /* rx handlers */ | 390 | /* rx handlers */ |
358 | 391 | ||
359 | static ieee80211_rx_result | 392 | static ieee80211_rx_result |
360 | ieee80211_rx_h_if_stats(struct ieee80211_rx_data *rx) | ||
361 | { | ||
362 | if (rx->sta) | ||
363 | rx->sta->channel_use_raw += rx->load; | ||
364 | rx->sdata->channel_use_raw += rx->load; | ||
365 | return RX_CONTINUE; | ||
366 | } | ||
367 | |||
368 | static ieee80211_rx_result | ||
369 | ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | 393 | ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) |
370 | { | 394 | { |
371 | struct ieee80211_local *local = rx->local; | 395 | struct ieee80211_local *local = rx->local; |
@@ -484,7 +508,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
484 | ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL && | 508 | ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL && |
485 | (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && | 509 | (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && |
486 | rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 510 | rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && |
487 | (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) { | 511 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { |
488 | if ((!(rx->fc & IEEE80211_FCTL_FROMDS) && | 512 | if ((!(rx->fc & IEEE80211_FCTL_FROMDS) && |
489 | !(rx->fc & IEEE80211_FCTL_TODS) && | 513 | !(rx->fc & IEEE80211_FCTL_TODS) && |
490 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) | 514 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) |
@@ -635,8 +659,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | |||
635 | 659 | ||
636 | if (sdata->bss) | 660 | if (sdata->bss) |
637 | atomic_inc(&sdata->bss->num_sta_ps); | 661 | atomic_inc(&sdata->bss->num_sta_ps); |
638 | sta->flags |= WLAN_STA_PS; | 662 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
639 | sta->flags &= ~WLAN_STA_PSPOLL; | ||
640 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 663 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
641 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 664 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
642 | dev->name, print_mac(mac, sta->addr), sta->aid); | 665 | dev->name, print_mac(mac, sta->addr), sta->aid); |
@@ -649,7 +672,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
649 | struct sk_buff *skb; | 672 | struct sk_buff *skb; |
650 | int sent = 0; | 673 | int sent = 0; |
651 | struct ieee80211_sub_if_data *sdata; | 674 | struct ieee80211_sub_if_data *sdata; |
652 | struct ieee80211_tx_packet_data *pkt_data; | 675 | struct ieee80211_tx_info *info; |
653 | DECLARE_MAC_BUF(mac); | 676 | DECLARE_MAC_BUF(mac); |
654 | 677 | ||
655 | sdata = sta->sdata; | 678 | sdata = sta->sdata; |
@@ -657,7 +680,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
657 | if (sdata->bss) | 680 | if (sdata->bss) |
658 | atomic_dec(&sdata->bss->num_sta_ps); | 681 | atomic_dec(&sdata->bss->num_sta_ps); |
659 | 682 | ||
660 | sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL); | 683 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
661 | 684 | ||
662 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 685 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
663 | sta_info_clear_tim_bit(sta); | 686 | sta_info_clear_tim_bit(sta); |
@@ -669,13 +692,13 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
669 | 692 | ||
670 | /* Send all buffered frames to the station */ | 693 | /* Send all buffered frames to the station */ |
671 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { | 694 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { |
672 | pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; | 695 | info = IEEE80211_SKB_CB(skb); |
673 | sent++; | 696 | sent++; |
674 | pkt_data->flags |= IEEE80211_TXPD_REQUEUE; | 697 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
675 | dev_queue_xmit(skb); | 698 | dev_queue_xmit(skb); |
676 | } | 699 | } |
677 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | 700 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { |
678 | pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; | 701 | info = IEEE80211_SKB_CB(skb); |
679 | local->total_ps_buffered--; | 702 | local->total_ps_buffered--; |
680 | sent++; | 703 | sent++; |
681 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 704 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
@@ -683,7 +706,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
683 | "since STA not sleeping anymore\n", dev->name, | 706 | "since STA not sleeping anymore\n", dev->name, |
684 | print_mac(mac, sta->addr), sta->aid); | 707 | print_mac(mac, sta->addr), sta->aid); |
685 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 708 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
686 | pkt_data->flags |= IEEE80211_TXPD_REQUEUE; | 709 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
687 | dev_queue_xmit(skb); | 710 | dev_queue_xmit(skb); |
688 | } | 711 | } |
689 | 712 | ||
@@ -725,16 +748,17 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
725 | 748 | ||
726 | sta->rx_fragments++; | 749 | sta->rx_fragments++; |
727 | sta->rx_bytes += rx->skb->len; | 750 | sta->rx_bytes += rx->skb->len; |
728 | sta->last_rssi = rx->status->ssi; | ||
729 | sta->last_signal = rx->status->signal; | 751 | sta->last_signal = rx->status->signal; |
752 | sta->last_qual = rx->status->qual; | ||
730 | sta->last_noise = rx->status->noise; | 753 | sta->last_noise = rx->status->noise; |
731 | 754 | ||
732 | if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) { | 755 | if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) { |
733 | /* Change STA power saving mode only in the end of a frame | 756 | /* Change STA power saving mode only in the end of a frame |
734 | * exchange sequence */ | 757 | * exchange sequence */ |
735 | if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM)) | 758 | if (test_sta_flags(sta, WLAN_STA_PS) && |
759 | !(rx->fc & IEEE80211_FCTL_PM)) | ||
736 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); | 760 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); |
737 | else if (!(sta->flags & WLAN_STA_PS) && | 761 | else if (!test_sta_flags(sta, WLAN_STA_PS) && |
738 | (rx->fc & IEEE80211_FCTL_PM)) | 762 | (rx->fc & IEEE80211_FCTL_PM)) |
739 | ap_sta_ps_start(dev, sta); | 763 | ap_sta_ps_start(dev, sta); |
740 | } | 764 | } |
@@ -988,7 +1012,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
988 | * Tell TX path to send one frame even though the STA may | 1012 | * Tell TX path to send one frame even though the STA may |
989 | * still remain is PS mode after this frame exchange. | 1013 | * still remain is PS mode after this frame exchange. |
990 | */ | 1014 | */ |
991 | rx->sta->flags |= WLAN_STA_PSPOLL; | 1015 | set_sta_flags(rx->sta, WLAN_STA_PSPOLL); |
992 | 1016 | ||
993 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1017 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
994 | printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", | 1018 | printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", |
@@ -1051,7 +1075,8 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | |||
1051 | static int | 1075 | static int |
1052 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | 1076 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) |
1053 | { | 1077 | { |
1054 | if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) { | 1078 | if (unlikely(!rx->sta || |
1079 | !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) { | ||
1055 | #ifdef CONFIG_MAC80211_DEBUG | 1080 | #ifdef CONFIG_MAC80211_DEBUG |
1056 | if (net_ratelimit()) | 1081 | if (net_ratelimit()) |
1057 | printk(KERN_DEBUG "%s: dropped frame " | 1082 | printk(KERN_DEBUG "%s: dropped frame " |
@@ -1713,7 +1738,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) | |||
1713 | typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *); | 1738 | typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *); |
1714 | static ieee80211_rx_handler ieee80211_rx_handlers[] = | 1739 | static ieee80211_rx_handler ieee80211_rx_handlers[] = |
1715 | { | 1740 | { |
1716 | ieee80211_rx_h_if_stats, | ||
1717 | ieee80211_rx_h_passive_scan, | 1741 | ieee80211_rx_h_passive_scan, |
1718 | ieee80211_rx_h_check, | 1742 | ieee80211_rx_h_check, |
1719 | ieee80211_rx_h_decrypt, | 1743 | ieee80211_rx_h_decrypt, |
@@ -1872,7 +1896,6 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1872 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | 1896 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
1873 | struct sk_buff *skb, | 1897 | struct sk_buff *skb, |
1874 | struct ieee80211_rx_status *status, | 1898 | struct ieee80211_rx_status *status, |
1875 | u32 load, | ||
1876 | struct ieee80211_rate *rate) | 1899 | struct ieee80211_rate *rate) |
1877 | { | 1900 | { |
1878 | struct ieee80211_local *local = hw_to_local(hw); | 1901 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -1891,7 +1914,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1891 | rx.local = local; | 1914 | rx.local = local; |
1892 | 1915 | ||
1893 | rx.status = status; | 1916 | rx.status = status; |
1894 | rx.load = load; | ||
1895 | rx.rate = rate; | 1917 | rx.rate = rate; |
1896 | rx.fc = le16_to_cpu(hdr->frame_control); | 1918 | rx.fc = le16_to_cpu(hdr->frame_control); |
1897 | type = rx.fc & IEEE80211_FCTL_FTYPE; | 1919 | type = rx.fc & IEEE80211_FCTL_FTYPE; |
@@ -2000,7 +2022,6 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2000 | struct ieee80211_rx_status status; | 2022 | struct ieee80211_rx_status status; |
2001 | u16 head_seq_num, buf_size; | 2023 | u16 head_seq_num, buf_size; |
2002 | int index; | 2024 | int index; |
2003 | u32 pkt_load; | ||
2004 | struct ieee80211_supported_band *sband; | 2025 | struct ieee80211_supported_band *sband; |
2005 | struct ieee80211_rate *rate; | 2026 | struct ieee80211_rate *rate; |
2006 | 2027 | ||
@@ -2035,12 +2056,9 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2035 | sizeof(status)); | 2056 | sizeof(status)); |
2036 | sband = local->hw.wiphy->bands[status.band]; | 2057 | sband = local->hw.wiphy->bands[status.band]; |
2037 | rate = &sband->bitrates[status.rate_idx]; | 2058 | rate = &sband->bitrates[status.rate_idx]; |
2038 | pkt_load = ieee80211_rx_load_stats(local, | ||
2039 | tid_agg_rx->reorder_buf[index], | ||
2040 | &status, rate); | ||
2041 | __ieee80211_rx_handle_packet(hw, | 2059 | __ieee80211_rx_handle_packet(hw, |
2042 | tid_agg_rx->reorder_buf[index], | 2060 | tid_agg_rx->reorder_buf[index], |
2043 | &status, pkt_load, rate); | 2061 | &status, rate); |
2044 | tid_agg_rx->stored_mpdu_num--; | 2062 | tid_agg_rx->stored_mpdu_num--; |
2045 | tid_agg_rx->reorder_buf[index] = NULL; | 2063 | tid_agg_rx->reorder_buf[index] = NULL; |
2046 | } | 2064 | } |
@@ -2082,11 +2100,8 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2082 | sizeof(status)); | 2100 | sizeof(status)); |
2083 | sband = local->hw.wiphy->bands[status.band]; | 2101 | sband = local->hw.wiphy->bands[status.band]; |
2084 | rate = &sband->bitrates[status.rate_idx]; | 2102 | rate = &sband->bitrates[status.rate_idx]; |
2085 | pkt_load = ieee80211_rx_load_stats(local, | ||
2086 | tid_agg_rx->reorder_buf[index], | ||
2087 | &status, rate); | ||
2088 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | 2103 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], |
2089 | &status, pkt_load, rate); | 2104 | &status, rate); |
2090 | tid_agg_rx->stored_mpdu_num--; | 2105 | tid_agg_rx->stored_mpdu_num--; |
2091 | tid_agg_rx->reorder_buf[index] = NULL; | 2106 | tid_agg_rx->reorder_buf[index] = NULL; |
2092 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 2107 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
@@ -2165,7 +2180,6 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2165 | struct ieee80211_rx_status *status) | 2180 | struct ieee80211_rx_status *status) |
2166 | { | 2181 | { |
2167 | struct ieee80211_local *local = hw_to_local(hw); | 2182 | struct ieee80211_local *local = hw_to_local(hw); |
2168 | u32 pkt_load; | ||
2169 | struct ieee80211_rate *rate = NULL; | 2183 | struct ieee80211_rate *rate = NULL; |
2170 | struct ieee80211_supported_band *sband; | 2184 | struct ieee80211_supported_band *sband; |
2171 | 2185 | ||
@@ -2205,11 +2219,8 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2205 | return; | 2219 | return; |
2206 | } | 2220 | } |
2207 | 2221 | ||
2208 | pkt_load = ieee80211_rx_load_stats(local, skb, status, rate); | ||
2209 | local->channel_use_raw += pkt_load; | ||
2210 | |||
2211 | if (!ieee80211_rx_reorder_ampdu(local, skb)) | 2222 | if (!ieee80211_rx_reorder_ampdu(local, skb)) |
2212 | __ieee80211_rx_handle_packet(hw, skb, status, pkt_load, rate); | 2223 | __ieee80211_rx_handle_packet(hw, skb, status, rate); |
2213 | 2224 | ||
2214 | rcu_read_unlock(); | 2225 | rcu_read_unlock(); |
2215 | } | 2226 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 7d4fe4a52929..c24770cb02c5 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -202,14 +202,12 @@ void sta_info_destroy(struct sta_info *sta) | |||
202 | dev_kfree_skb_any(skb); | 202 | dev_kfree_skb_any(skb); |
203 | 203 | ||
204 | for (i = 0; i < STA_TID_NUM; i++) { | 204 | for (i = 0; i < STA_TID_NUM; i++) { |
205 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 205 | spin_lock_bh(&sta->lock); |
206 | if (sta->ampdu_mlme.tid_rx[i]) | 206 | if (sta->ampdu_mlme.tid_rx[i]) |
207 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer); | 207 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer); |
208 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | ||
209 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
210 | if (sta->ampdu_mlme.tid_tx[i]) | 208 | if (sta->ampdu_mlme.tid_tx[i]) |
211 | del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer); | 209 | del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer); |
212 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 210 | spin_unlock_bh(&sta->lock); |
213 | } | 211 | } |
214 | 212 | ||
215 | __sta_info_free(local, sta); | 213 | __sta_info_free(local, sta); |
@@ -236,6 +234,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
236 | if (!sta) | 234 | if (!sta) |
237 | return NULL; | 235 | return NULL; |
238 | 236 | ||
237 | spin_lock_init(&sta->lock); | ||
238 | |||
239 | memcpy(sta->addr, addr, ETH_ALEN); | 239 | memcpy(sta->addr, addr, ETH_ALEN); |
240 | sta->local = local; | 240 | sta->local = local; |
241 | sta->sdata = sdata; | 241 | sta->sdata = sdata; |
@@ -249,15 +249,13 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
249 | return NULL; | 249 | return NULL; |
250 | } | 250 | } |
251 | 251 | ||
252 | spin_lock_init(&sta->ampdu_mlme.ampdu_rx); | ||
253 | spin_lock_init(&sta->ampdu_mlme.ampdu_tx); | ||
254 | for (i = 0; i < STA_TID_NUM; i++) { | 252 | for (i = 0; i < STA_TID_NUM; i++) { |
255 | /* timer_to_tid must be initialized with identity mapping to | 253 | /* timer_to_tid must be initialized with identity mapping to |
256 | * enable session_timer's data differentiation. refer to | 254 | * enable session_timer's data differentiation. refer to |
257 | * sta_rx_agg_session_timer_expired for useage */ | 255 | * sta_rx_agg_session_timer_expired for useage */ |
258 | sta->timer_to_tid[i] = i; | 256 | sta->timer_to_tid[i] = i; |
259 | /* tid to tx queue: initialize according to HW (0 is valid) */ | 257 | /* tid to tx queue: initialize according to HW (0 is valid) */ |
260 | sta->tid_to_tx_q[i] = local->hw.queues; | 258 | sta->tid_to_tx_q[i] = ieee80211_num_queues(&local->hw); |
261 | /* rx */ | 259 | /* rx */ |
262 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; | 260 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; |
263 | sta->ampdu_mlme.tid_rx[i] = NULL; | 261 | sta->ampdu_mlme.tid_rx[i] = NULL; |
@@ -276,7 +274,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
276 | 274 | ||
277 | #ifdef CONFIG_MAC80211_MESH | 275 | #ifdef CONFIG_MAC80211_MESH |
278 | sta->plink_state = PLINK_LISTEN; | 276 | sta->plink_state = PLINK_LISTEN; |
279 | spin_lock_init(&sta->plink_lock); | ||
280 | init_timer(&sta->plink_timer); | 277 | init_timer(&sta->plink_timer); |
281 | #endif | 278 | #endif |
282 | 279 | ||
@@ -437,8 +434,7 @@ void __sta_info_unlink(struct sta_info **sta) | |||
437 | 434 | ||
438 | list_del(&(*sta)->list); | 435 | list_del(&(*sta)->list); |
439 | 436 | ||
440 | if ((*sta)->flags & WLAN_STA_PS) { | 437 | if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { |
441 | (*sta)->flags &= ~WLAN_STA_PS; | ||
442 | if (sdata->bss) | 438 | if (sdata->bss) |
443 | atomic_dec(&sdata->bss->num_sta_ps); | 439 | atomic_dec(&sdata->bss->num_sta_ps); |
444 | __sta_info_clear_tim_bit(sdata->bss, *sta); | 440 | __sta_info_clear_tim_bit(sdata->bss, *sta); |
@@ -515,20 +511,20 @@ static inline int sta_info_buffer_expired(struct ieee80211_local *local, | |||
515 | struct sta_info *sta, | 511 | struct sta_info *sta, |
516 | struct sk_buff *skb) | 512 | struct sk_buff *skb) |
517 | { | 513 | { |
518 | struct ieee80211_tx_packet_data *pkt_data; | 514 | struct ieee80211_tx_info *info; |
519 | int timeout; | 515 | int timeout; |
520 | 516 | ||
521 | if (!skb) | 517 | if (!skb) |
522 | return 0; | 518 | return 0; |
523 | 519 | ||
524 | pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; | 520 | info = IEEE80211_SKB_CB(skb); |
525 | 521 | ||
526 | /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */ | 522 | /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */ |
527 | timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 / | 523 | timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 / |
528 | 15625) * HZ; | 524 | 15625) * HZ; |
529 | if (timeout < STA_TX_BUFFER_EXPIRE) | 525 | if (timeout < STA_TX_BUFFER_EXPIRE) |
530 | timeout = STA_TX_BUFFER_EXPIRE; | 526 | timeout = STA_TX_BUFFER_EXPIRE; |
531 | return time_after(jiffies, pkt_data->jiffies + timeout); | 527 | return time_after(jiffies, info->control.jiffies + timeout); |
532 | } | 528 | } |
533 | 529 | ||
534 | 530 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index f8c95bc9659c..95753f860acf 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -32,7 +32,7 @@ | |||
32 | * @WLAN_STA_WDS: Station is one of our WDS peers. | 32 | * @WLAN_STA_WDS: Station is one of our WDS peers. |
33 | * @WLAN_STA_PSPOLL: Station has just PS-polled us. | 33 | * @WLAN_STA_PSPOLL: Station has just PS-polled us. |
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_TXCTL_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 | */ | 37 | */ |
38 | enum ieee80211_sta_info_flags { | 38 | enum ieee80211_sta_info_flags { |
@@ -129,23 +129,19 @@ enum plink_state { | |||
129 | * | 129 | * |
130 | * @tid_state_rx: TID's state in Rx session state machine. | 130 | * @tid_state_rx: TID's state in Rx session state machine. |
131 | * @tid_rx: aggregation info for Rx per TID | 131 | * @tid_rx: aggregation info for Rx per TID |
132 | * @ampdu_rx: for locking sections in aggregation Rx flow | ||
133 | * @tid_state_tx: TID's state in Tx session state machine. | 132 | * @tid_state_tx: TID's state in Tx session state machine. |
134 | * @tid_tx: aggregation info for Tx per TID | 133 | * @tid_tx: aggregation info for Tx per TID |
135 | * @addba_req_num: number of times addBA request has been sent. | 134 | * @addba_req_num: number of times addBA request has been sent. |
136 | * @ampdu_tx: for locking sectionsi in aggregation Tx flow | ||
137 | * @dialog_token_allocator: dialog token enumerator for each new session; | 135 | * @dialog_token_allocator: dialog token enumerator for each new session; |
138 | */ | 136 | */ |
139 | struct sta_ampdu_mlme { | 137 | struct sta_ampdu_mlme { |
140 | /* rx */ | 138 | /* rx */ |
141 | u8 tid_state_rx[STA_TID_NUM]; | 139 | u8 tid_state_rx[STA_TID_NUM]; |
142 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; | 140 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; |
143 | spinlock_t ampdu_rx; | ||
144 | /* tx */ | 141 | /* tx */ |
145 | u8 tid_state_tx[STA_TID_NUM]; | 142 | u8 tid_state_tx[STA_TID_NUM]; |
146 | struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; | 143 | struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; |
147 | u8 addba_req_num[STA_TID_NUM]; | 144 | u8 addba_req_num[STA_TID_NUM]; |
148 | spinlock_t ampdu_tx; | ||
149 | u8 dialog_token_allocator; | 145 | u8 dialog_token_allocator; |
150 | }; | 146 | }; |
151 | 147 | ||
@@ -177,6 +173,8 @@ struct sta_ampdu_mlme { | |||
177 | * @rx_bytes: Number of bytes received from this STA | 173 | * @rx_bytes: Number of bytes received from this STA |
178 | * @supp_rates: Bitmap of supported rates (per band) | 174 | * @supp_rates: Bitmap of supported rates (per band) |
179 | * @ht_info: HT capabilities of this STA | 175 | * @ht_info: HT capabilities of this STA |
176 | * @lock: used for locking all fields that require locking, see comments | ||
177 | * in the header file. | ||
180 | */ | 178 | */ |
181 | struct sta_info { | 179 | struct sta_info { |
182 | /* General information, mostly static */ | 180 | /* General information, mostly static */ |
@@ -187,6 +185,7 @@ struct sta_info { | |||
187 | struct ieee80211_key *key; | 185 | struct ieee80211_key *key; |
188 | struct rate_control_ref *rate_ctrl; | 186 | struct rate_control_ref *rate_ctrl; |
189 | void *rate_ctrl_priv; | 187 | void *rate_ctrl_priv; |
188 | spinlock_t lock; | ||
190 | struct ieee80211_ht_info ht_info; | 189 | struct ieee80211_ht_info ht_info; |
191 | u64 supp_rates[IEEE80211_NUM_BANDS]; | 190 | u64 supp_rates[IEEE80211_NUM_BANDS]; |
192 | u8 addr[ETH_ALEN]; | 191 | u8 addr[ETH_ALEN]; |
@@ -199,7 +198,7 @@ struct sta_info { | |||
199 | */ | 198 | */ |
200 | u8 pin_status; | 199 | u8 pin_status; |
201 | 200 | ||
202 | /* frequently updated information, needs locking? */ | 201 | /* frequently updated information, locked with lock spinlock */ |
203 | u32 flags; | 202 | u32 flags; |
204 | 203 | ||
205 | /* | 204 | /* |
@@ -217,8 +216,8 @@ struct sta_info { | |||
217 | * from this STA */ | 216 | * from this STA */ |
218 | unsigned long rx_fragments; /* number of received MPDUs */ | 217 | unsigned long rx_fragments; /* number of received MPDUs */ |
219 | unsigned long rx_dropped; /* number of dropped MPDUs from this STA */ | 218 | unsigned long rx_dropped; /* number of dropped MPDUs from this STA */ |
220 | int last_rssi; /* RSSI of last received frame from this STA */ | ||
221 | int last_signal; /* signal of last received frame from this STA */ | 219 | int last_signal; /* signal of last received frame from this STA */ |
220 | int last_qual; /* qual of last received frame from this STA */ | ||
222 | int last_noise; /* noise of last received frame from this STA */ | 221 | int last_noise; /* noise of last received frame from this STA */ |
223 | /* last received seq/frag number from this STA (per RX queue) */ | 222 | /* last received seq/frag number from this STA (per RX queue) */ |
224 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 223 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; |
@@ -246,12 +245,8 @@ struct sta_info { | |||
246 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; | 245 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; |
247 | #endif | 246 | #endif |
248 | 247 | ||
249 | /* Debug counters, no locking doesn't matter */ | ||
250 | int channel_use; | ||
251 | int channel_use_raw; | ||
252 | |||
253 | /* | 248 | /* |
254 | * Aggregation information, comes with own locking. | 249 | * Aggregation information, locked with lock. |
255 | */ | 250 | */ |
256 | struct sta_ampdu_mlme ampdu_mlme; | 251 | struct sta_ampdu_mlme ampdu_mlme; |
257 | u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */ | 252 | u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */ |
@@ -270,9 +265,6 @@ struct sta_info { | |||
270 | enum plink_state plink_state; | 265 | enum plink_state plink_state; |
271 | u32 plink_timeout; | 266 | u32 plink_timeout; |
272 | struct timer_list plink_timer; | 267 | struct timer_list plink_timer; |
273 | spinlock_t plink_lock; /* For peer_state reads / updates and other | ||
274 | updates in the structure. Ensures robust | ||
275 | transitions for the peerlink FSM */ | ||
276 | #endif | 268 | #endif |
277 | 269 | ||
278 | #ifdef CONFIG_MAC80211_DEBUGFS | 270 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -299,6 +291,64 @@ static inline enum plink_state sta_plink_state(struct sta_info *sta) | |||
299 | return PLINK_LISTEN; | 291 | return PLINK_LISTEN; |
300 | } | 292 | } |
301 | 293 | ||
294 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) | ||
295 | { | ||
296 | spin_lock_bh(&sta->lock); | ||
297 | sta->flags |= flags; | ||
298 | spin_unlock_bh(&sta->lock); | ||
299 | } | ||
300 | |||
301 | static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) | ||
302 | { | ||
303 | spin_lock_bh(&sta->lock); | ||
304 | sta->flags &= ~flags; | ||
305 | spin_unlock_bh(&sta->lock); | ||
306 | } | ||
307 | |||
308 | static inline void set_and_clear_sta_flags(struct sta_info *sta, | ||
309 | const u32 set, const u32 clear) | ||
310 | { | ||
311 | spin_lock_bh(&sta->lock); | ||
312 | sta->flags |= set; | ||
313 | sta->flags &= ~clear; | ||
314 | spin_unlock_bh(&sta->lock); | ||
315 | } | ||
316 | |||
317 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) | ||
318 | { | ||
319 | u32 ret; | ||
320 | |||
321 | spin_lock_bh(&sta->lock); | ||
322 | ret = sta->flags & flags; | ||
323 | spin_unlock_bh(&sta->lock); | ||
324 | |||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | static inline u32 test_and_clear_sta_flags(struct sta_info *sta, | ||
329 | const u32 flags) | ||
330 | { | ||
331 | u32 ret; | ||
332 | |||
333 | spin_lock_bh(&sta->lock); | ||
334 | ret = sta->flags & flags; | ||
335 | sta->flags &= ~flags; | ||
336 | spin_unlock_bh(&sta->lock); | ||
337 | |||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static inline u32 get_sta_flags(struct sta_info *sta) | ||
342 | { | ||
343 | u32 ret; | ||
344 | |||
345 | spin_lock_bh(&sta->lock); | ||
346 | ret = sta->flags; | ||
347 | spin_unlock_bh(&sta->lock); | ||
348 | |||
349 | return ret; | ||
350 | } | ||
351 | |||
302 | 352 | ||
303 | /* Maximum number of concurrently registered stations */ | 353 | /* Maximum number of concurrently registered stations */ |
304 | #define MAX_STA_COUNT 2007 | 354 | #define MAX_STA_COUNT 2007 |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 09093da24af6..a00cf1ea7719 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -6,25 +6,23 @@ | |||
6 | * 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 |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | |||
10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/bitops.h> | ||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
13 | #include <asm/unaligned.h> | ||
13 | 14 | ||
14 | #include <net/mac80211.h> | 15 | #include <net/mac80211.h> |
15 | #include "key.h" | 16 | #include "key.h" |
16 | #include "tkip.h" | 17 | #include "tkip.h" |
17 | #include "wep.h" | 18 | #include "wep.h" |
18 | 19 | ||
19 | |||
20 | /* TKIP key mixing functions */ | ||
21 | |||
22 | |||
23 | #define PHASE1_LOOP_COUNT 8 | 20 | #define PHASE1_LOOP_COUNT 8 |
24 | 21 | ||
25 | 22 | /* | |
26 | /* 2-byte by 2-byte subset of the full AES S-box table; second part of this | 23 | * 2-byte by 2-byte subset of the full AES S-box table; second part of this |
27 | * table is identical to first part but byte-swapped */ | 24 | * table is identical to first part but byte-swapped |
25 | */ | ||
28 | static const u16 tkip_sbox[256] = | 26 | static const u16 tkip_sbox[256] = |
29 | { | 27 | { |
30 | 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, | 28 | 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, |
@@ -61,84 +59,48 @@ static const u16 tkip_sbox[256] = | |||
61 | 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, | 59 | 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, |
62 | }; | 60 | }; |
63 | 61 | ||
64 | 62 | static u16 tkipS(u16 val) | |
65 | static inline u16 Mk16(u8 x, u8 y) | ||
66 | { | ||
67 | return ((u16) x << 8) | (u16) y; | ||
68 | } | ||
69 | |||
70 | |||
71 | static inline u8 Hi8(u16 v) | ||
72 | { | ||
73 | return v >> 8; | ||
74 | } | ||
75 | |||
76 | |||
77 | static inline u8 Lo8(u16 v) | ||
78 | { | ||
79 | return v & 0xff; | ||
80 | } | ||
81 | |||
82 | |||
83 | static inline u16 Hi16(u32 v) | ||
84 | { | 63 | { |
85 | return v >> 16; | 64 | return tkip_sbox[val & 0xff] ^ swab16(tkip_sbox[val >> 8]); |
86 | } | 65 | } |
87 | 66 | ||
88 | 67 | /* | |
89 | static inline u16 Lo16(u32 v) | 68 | * P1K := Phase1(TA, TK, TSC) |
90 | { | ||
91 | return v & 0xffff; | ||
92 | } | ||
93 | |||
94 | |||
95 | static inline u16 RotR1(u16 v) | ||
96 | { | ||
97 | return (v >> 1) | ((v & 0x0001) << 15); | ||
98 | } | ||
99 | |||
100 | |||
101 | static inline u16 tkip_S(u16 val) | ||
102 | { | ||
103 | u16 a = tkip_sbox[Hi8(val)]; | ||
104 | |||
105 | return tkip_sbox[Lo8(val)] ^ Hi8(a) ^ (Lo8(a) << 8); | ||
106 | } | ||
107 | |||
108 | |||
109 | |||
110 | /* P1K := Phase1(TA, TK, TSC) | ||
111 | * TA = transmitter address (48 bits) | 69 | * TA = transmitter address (48 bits) |
112 | * TK = dot11DefaultKeyValue or dot11KeyMappingValue (128 bits) | 70 | * TK = dot11DefaultKeyValue or dot11KeyMappingValue (128 bits) |
113 | * TSC = TKIP sequence counter (48 bits, only 32 msb bits used) | 71 | * TSC = TKIP sequence counter (48 bits, only 32 msb bits used) |
114 | * P1K: 80 bits | 72 | * P1K: 80 bits |
115 | */ | 73 | */ |
116 | static void tkip_mixing_phase1(const u8 *ta, const u8 *tk, u32 tsc_IV32, | 74 | static void tkip_mixing_phase1(struct ieee80211_key *key, const u8 *ta, |
117 | u16 *p1k) | 75 | struct tkip_ctx *ctx, u32 tsc_IV32) |
118 | { | 76 | { |
119 | int i, j; | 77 | int i, j; |
78 | const u8 *tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; | ||
79 | u16 *p1k = ctx->p1k; | ||
120 | 80 | ||
121 | p1k[0] = Lo16(tsc_IV32); | 81 | p1k[0] = tsc_IV32 & 0xFFFF; |
122 | p1k[1] = Hi16(tsc_IV32); | 82 | p1k[1] = tsc_IV32 >> 16; |
123 | p1k[2] = Mk16(ta[1], ta[0]); | 83 | p1k[2] = get_unaligned_le16(ta + 0); |
124 | p1k[3] = Mk16(ta[3], ta[2]); | 84 | p1k[3] = get_unaligned_le16(ta + 2); |
125 | p1k[4] = Mk16(ta[5], ta[4]); | 85 | p1k[4] = get_unaligned_le16(ta + 4); |
126 | 86 | ||
127 | for (i = 0; i < PHASE1_LOOP_COUNT; i++) { | 87 | for (i = 0; i < PHASE1_LOOP_COUNT; i++) { |
128 | j = 2 * (i & 1); | 88 | j = 2 * (i & 1); |
129 | p1k[0] += tkip_S(p1k[4] ^ Mk16(tk[ 1 + j], tk[ 0 + j])); | 89 | p1k[0] += tkipS(p1k[4] ^ get_unaligned_le16(tk + 0 + j)); |
130 | p1k[1] += tkip_S(p1k[0] ^ Mk16(tk[ 5 + j], tk[ 4 + j])); | 90 | p1k[1] += tkipS(p1k[0] ^ get_unaligned_le16(tk + 4 + j)); |
131 | p1k[2] += tkip_S(p1k[1] ^ Mk16(tk[ 9 + j], tk[ 8 + j])); | 91 | p1k[2] += tkipS(p1k[1] ^ get_unaligned_le16(tk + 8 + j)); |
132 | p1k[3] += tkip_S(p1k[2] ^ Mk16(tk[13 + j], tk[12 + j])); | 92 | p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j)); |
133 | p1k[4] += tkip_S(p1k[3] ^ Mk16(tk[ 1 + j], tk[ 0 + j])) + i; | 93 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; |
134 | } | 94 | } |
95 | ctx->initialized = 1; | ||
135 | } | 96 | } |
136 | 97 | ||
137 | 98 | static void tkip_mixing_phase2(struct ieee80211_key *key, struct tkip_ctx *ctx, | |
138 | static void tkip_mixing_phase2(const u16 *p1k, const u8 *tk, u16 tsc_IV16, | 99 | u16 tsc_IV16, u8 *rc4key) |
139 | u8 *rc4key) | ||
140 | { | 100 | { |
141 | u16 ppk[6]; | 101 | u16 ppk[6]; |
102 | const u16 *p1k = ctx->p1k; | ||
103 | const u8 *tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; | ||
142 | int i; | 104 | int i; |
143 | 105 | ||
144 | ppk[0] = p1k[0]; | 106 | ppk[0] = p1k[0]; |
@@ -148,70 +110,51 @@ static void tkip_mixing_phase2(const u16 *p1k, const u8 *tk, u16 tsc_IV16, | |||
148 | ppk[4] = p1k[4]; | 110 | ppk[4] = p1k[4]; |
149 | ppk[5] = p1k[4] + tsc_IV16; | 111 | ppk[5] = p1k[4] + tsc_IV16; |
150 | 112 | ||
151 | ppk[0] += tkip_S(ppk[5] ^ Mk16(tk[ 1], tk[ 0])); | 113 | ppk[0] += tkipS(ppk[5] ^ get_unaligned_le16(tk + 0)); |
152 | ppk[1] += tkip_S(ppk[0] ^ Mk16(tk[ 3], tk[ 2])); | 114 | ppk[1] += tkipS(ppk[0] ^ get_unaligned_le16(tk + 2)); |
153 | ppk[2] += tkip_S(ppk[1] ^ Mk16(tk[ 5], tk[ 4])); | 115 | ppk[2] += tkipS(ppk[1] ^ get_unaligned_le16(tk + 4)); |
154 | ppk[3] += tkip_S(ppk[2] ^ Mk16(tk[ 7], tk[ 6])); | 116 | ppk[3] += tkipS(ppk[2] ^ get_unaligned_le16(tk + 6)); |
155 | ppk[4] += tkip_S(ppk[3] ^ Mk16(tk[ 9], tk[ 8])); | 117 | ppk[4] += tkipS(ppk[3] ^ get_unaligned_le16(tk + 8)); |
156 | ppk[5] += tkip_S(ppk[4] ^ Mk16(tk[11], tk[10])); | 118 | ppk[5] += tkipS(ppk[4] ^ get_unaligned_le16(tk + 10)); |
157 | ppk[0] += RotR1(ppk[5] ^ Mk16(tk[13], tk[12])); | 119 | ppk[0] += ror16(ppk[5] ^ get_unaligned_le16(tk + 12), 1); |
158 | ppk[1] += RotR1(ppk[0] ^ Mk16(tk[15], tk[14])); | 120 | ppk[1] += ror16(ppk[0] ^ get_unaligned_le16(tk + 14), 1); |
159 | ppk[2] += RotR1(ppk[1]); | 121 | ppk[2] += ror16(ppk[1], 1); |
160 | ppk[3] += RotR1(ppk[2]); | 122 | ppk[3] += ror16(ppk[2], 1); |
161 | ppk[4] += RotR1(ppk[3]); | 123 | ppk[4] += ror16(ppk[3], 1); |
162 | ppk[5] += RotR1(ppk[4]); | 124 | ppk[5] += ror16(ppk[4], 1); |
163 | 125 | ||
164 | rc4key[0] = Hi8(tsc_IV16); | 126 | rc4key[0] = tsc_IV16 >> 8; |
165 | rc4key[1] = (Hi8(tsc_IV16) | 0x20) & 0x7f; | 127 | rc4key[1] = ((tsc_IV16 >> 8) | 0x20) & 0x7f; |
166 | rc4key[2] = Lo8(tsc_IV16); | 128 | rc4key[2] = tsc_IV16 & 0xFF; |
167 | rc4key[3] = Lo8((ppk[5] ^ Mk16(tk[1], tk[0])) >> 1); | 129 | rc4key[3] = ((ppk[5] ^ get_unaligned_le16(tk)) >> 1) & 0xFF; |
168 | 130 | ||
169 | for (i = 0; i < 6; i++) { | 131 | rc4key += 4; |
170 | rc4key[4 + 2 * i] = Lo8(ppk[i]); | 132 | for (i = 0; i < 6; i++) |
171 | rc4key[5 + 2 * i] = Hi8(ppk[i]); | 133 | put_unaligned_le16(ppk[i], rc4key + 2 * i); |
172 | } | ||
173 | } | 134 | } |
174 | 135 | ||
175 | |||
176 | /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets | 136 | /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets |
177 | * of the IV. Returns pointer to the octet following IVs (i.e., beginning of | 137 | * of the IV. Returns pointer to the octet following IVs (i.e., beginning of |
178 | * the packet payload). */ | 138 | * the packet payload). */ |
179 | u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, | 139 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, |
180 | u8 iv0, u8 iv1, u8 iv2) | 140 | u8 iv0, u8 iv1, u8 iv2) |
181 | { | 141 | { |
182 | *pos++ = iv0; | 142 | *pos++ = iv0; |
183 | *pos++ = iv1; | 143 | *pos++ = iv1; |
184 | *pos++ = iv2; | 144 | *pos++ = iv2; |
185 | *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; | 145 | *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; |
186 | *pos++ = key->u.tkip.iv32 & 0xff; | 146 | put_unaligned_le32(key->u.tkip.tx.iv32, pos); |
187 | *pos++ = (key->u.tkip.iv32 >> 8) & 0xff; | 147 | return pos + 4; |
188 | *pos++ = (key->u.tkip.iv32 >> 16) & 0xff; | ||
189 | *pos++ = (key->u.tkip.iv32 >> 24) & 0xff; | ||
190 | return pos; | ||
191 | } | ||
192 | |||
193 | |||
194 | void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta, | ||
195 | u16 *phase1key) | ||
196 | { | ||
197 | tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], | ||
198 | key->u.tkip.iv32, phase1key); | ||
199 | } | 148 | } |
200 | 149 | ||
201 | void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta, | 150 | static void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta, |
202 | u8 *rc4key) | 151 | u8 *rc4key) |
203 | { | 152 | { |
204 | /* Calculate per-packet key */ | 153 | /* Calculate per-packet key */ |
205 | if (key->u.tkip.iv16 == 0 || !key->u.tkip.tx_initialized) { | 154 | if (key->u.tkip.tx.iv16 == 0 || !key->u.tkip.tx.initialized) |
206 | /* IV16 wrapped around - perform TKIP phase 1 */ | 155 | tkip_mixing_phase1(key, ta, &key->u.tkip.tx, key->u.tkip.tx.iv32); |
207 | tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], | ||
208 | key->u.tkip.iv32, key->u.tkip.p1k); | ||
209 | key->u.tkip.tx_initialized = 1; | ||
210 | } | ||
211 | 156 | ||
212 | tkip_mixing_phase2(key->u.tkip.p1k, | 157 | tkip_mixing_phase2(key, &key->u.tkip.tx, key->u.tkip.tx.iv16, rc4key); |
213 | &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], | ||
214 | key->u.tkip.iv16, rc4key); | ||
215 | } | 158 | } |
216 | 159 | ||
217 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | 160 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, |
@@ -228,18 +171,16 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
228 | u16 iv16; | 171 | u16 iv16; |
229 | u32 iv32; | 172 | u32 iv32; |
230 | 173 | ||
231 | iv16 = data[hdr_len] << 8; | 174 | iv16 = data[hdr_len + 2] | (data[hdr_len] << 8); |
232 | iv16 += data[hdr_len + 2]; | 175 | iv32 = get_unaligned_le32(data + hdr_len + 4); |
233 | iv32 = data[hdr_len + 4] | (data[hdr_len + 5] << 8) | | ||
234 | (data[hdr_len + 6] << 16) | (data[hdr_len + 7] << 24); | ||
235 | 176 | ||
236 | #ifdef CONFIG_TKIP_DEBUG | 177 | #ifdef CONFIG_TKIP_DEBUG |
237 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", | 178 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", |
238 | iv16, iv32); | 179 | iv16, iv32); |
239 | 180 | ||
240 | if (iv32 != key->u.tkip.iv32) { | 181 | if (iv32 != key->u.tkip.tx.iv32) { |
241 | printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n", | 182 | printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n", |
242 | iv32, key->u.tkip.iv32); | 183 | iv32, key->u.tkip.tx.iv32); |
243 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " | 184 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " |
244 | "fragmented packet\n"); | 185 | "fragmented packet\n"); |
245 | } | 186 | } |
@@ -248,20 +189,15 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
248 | /* Update the p1k only when the iv16 in the packet wraps around, this | 189 | /* Update the p1k only when the iv16 in the packet wraps around, this |
249 | * might occur after the wrap around of iv16 in the key in case of | 190 | * might occur after the wrap around of iv16 in the key in case of |
250 | * fragmented packets. */ | 191 | * fragmented packets. */ |
251 | if (iv16 == 0 || !key->u.tkip.tx_initialized) { | 192 | if (iv16 == 0 || !key->u.tkip.tx.initialized) |
252 | /* IV16 wrapped around - perform TKIP phase 1 */ | 193 | tkip_mixing_phase1(key, ta, &key->u.tkip.tx, iv32); |
253 | tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], | ||
254 | iv32, key->u.tkip.p1k); | ||
255 | key->u.tkip.tx_initialized = 1; | ||
256 | } | ||
257 | 194 | ||
258 | if (type == IEEE80211_TKIP_P1_KEY) { | 195 | if (type == IEEE80211_TKIP_P1_KEY) { |
259 | memcpy(outkey, key->u.tkip.p1k, sizeof(u16) * 5); | 196 | memcpy(outkey, key->u.tkip.tx.p1k, sizeof(u16) * 5); |
260 | return; | 197 | return; |
261 | } | 198 | } |
262 | 199 | ||
263 | tkip_mixing_phase2(key->u.tkip.p1k, | 200 | tkip_mixing_phase2(key, &key->u.tkip.tx, iv16, outkey); |
264 | &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], iv16, outkey); | ||
265 | } | 201 | } |
266 | EXPORT_SYMBOL(ieee80211_get_tkip_key); | 202 | EXPORT_SYMBOL(ieee80211_get_tkip_key); |
267 | 203 | ||
@@ -281,7 +217,6 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | |||
281 | ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); | 217 | ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); |
282 | } | 218 | } |
283 | 219 | ||
284 | |||
285 | /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the | 220 | /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the |
286 | * beginning of the buffer containing IEEE 802.11 header payload, i.e., | 221 | * beginning of the buffer containing IEEE 802.11 header payload, i.e., |
287 | * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the | 222 | * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the |
@@ -302,7 +237,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
302 | 237 | ||
303 | iv16 = (pos[0] << 8) | pos[2]; | 238 | iv16 = (pos[0] << 8) | pos[2]; |
304 | keyid = pos[3]; | 239 | keyid = pos[3]; |
305 | iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); | 240 | iv32 = get_unaligned_le32(pos + 4); |
306 | pos += 8; | 241 | pos += 8; |
307 | #ifdef CONFIG_TKIP_DEBUG | 242 | #ifdef CONFIG_TKIP_DEBUG |
308 | { | 243 | { |
@@ -322,33 +257,31 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
322 | if ((keyid >> 6) != key->conf.keyidx) | 257 | if ((keyid >> 6) != key->conf.keyidx) |
323 | return TKIP_DECRYPT_INVALID_KEYIDX; | 258 | return TKIP_DECRYPT_INVALID_KEYIDX; |
324 | 259 | ||
325 | if (key->u.tkip.rx_initialized[queue] && | 260 | if (key->u.tkip.rx[queue].initialized && |
326 | (iv32 < key->u.tkip.iv32_rx[queue] || | 261 | (iv32 < key->u.tkip.rx[queue].iv32 || |
327 | (iv32 == key->u.tkip.iv32_rx[queue] && | 262 | (iv32 == key->u.tkip.rx[queue].iv32 && |
328 | iv16 <= key->u.tkip.iv16_rx[queue]))) { | 263 | iv16 <= key->u.tkip.rx[queue].iv16))) { |
329 | #ifdef CONFIG_TKIP_DEBUG | 264 | #ifdef CONFIG_TKIP_DEBUG |
330 | DECLARE_MAC_BUF(mac); | 265 | DECLARE_MAC_BUF(mac); |
331 | printk(KERN_DEBUG "TKIP replay detected for RX frame from " | 266 | printk(KERN_DEBUG "TKIP replay detected for RX frame from " |
332 | "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", | 267 | "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", |
333 | print_mac(mac, ta), | 268 | print_mac(mac, ta), |
334 | iv32, iv16, key->u.tkip.iv32_rx[queue], | 269 | iv32, iv16, key->u.tkip.rx[queue].iv32, |
335 | key->u.tkip.iv16_rx[queue]); | 270 | key->u.tkip.rx[queue].iv16); |
336 | #endif /* CONFIG_TKIP_DEBUG */ | 271 | #endif /* CONFIG_TKIP_DEBUG */ |
337 | return TKIP_DECRYPT_REPLAY; | 272 | return TKIP_DECRYPT_REPLAY; |
338 | } | 273 | } |
339 | 274 | ||
340 | if (only_iv) { | 275 | if (only_iv) { |
341 | res = TKIP_DECRYPT_OK; | 276 | res = TKIP_DECRYPT_OK; |
342 | key->u.tkip.rx_initialized[queue] = 1; | 277 | key->u.tkip.rx[queue].initialized = 1; |
343 | goto done; | 278 | goto done; |
344 | } | 279 | } |
345 | 280 | ||
346 | if (!key->u.tkip.rx_initialized[queue] || | 281 | if (!key->u.tkip.rx[queue].initialized || |
347 | key->u.tkip.iv32_rx[queue] != iv32) { | 282 | key->u.tkip.rx[queue].iv32 != iv32) { |
348 | key->u.tkip.rx_initialized[queue] = 1; | ||
349 | /* IV16 wrapped around - perform TKIP phase 1 */ | 283 | /* IV16 wrapped around - perform TKIP phase 1 */ |
350 | tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], | 284 | tkip_mixing_phase1(key, ta, &key->u.tkip.rx[queue], iv32); |
351 | iv32, key->u.tkip.p1k_rx[queue]); | ||
352 | #ifdef CONFIG_TKIP_DEBUG | 285 | #ifdef CONFIG_TKIP_DEBUG |
353 | { | 286 | { |
354 | int i; | 287 | int i; |
@@ -362,7 +295,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
362 | printk("\n"); | 295 | printk("\n"); |
363 | printk(KERN_DEBUG "TKIP decrypt: P1K="); | 296 | printk(KERN_DEBUG "TKIP decrypt: P1K="); |
364 | for (i = 0; i < 5; i++) | 297 | for (i = 0; i < 5; i++) |
365 | printk("%04x ", key->u.tkip.p1k_rx[queue][i]); | 298 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); |
366 | printk("\n"); | 299 | printk("\n"); |
367 | } | 300 | } |
368 | #endif /* CONFIG_TKIP_DEBUG */ | 301 | #endif /* CONFIG_TKIP_DEBUG */ |
@@ -377,13 +310,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
377 | 310 | ||
378 | key->local->ops->update_tkip_key( | 311 | key->local->ops->update_tkip_key( |
379 | local_to_hw(key->local), &key->conf, | 312 | local_to_hw(key->local), &key->conf, |
380 | sta_addr, iv32, key->u.tkip.p1k_rx[queue]); | 313 | sta_addr, iv32, key->u.tkip.rx[queue].p1k); |
381 | } | 314 | } |
382 | } | 315 | } |
383 | 316 | ||
384 | tkip_mixing_phase2(key->u.tkip.p1k_rx[queue], | 317 | tkip_mixing_phase2(key, &key->u.tkip.rx[queue], iv16, rc4key); |
385 | &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], | ||
386 | iv16, rc4key); | ||
387 | #ifdef CONFIG_TKIP_DEBUG | 318 | #ifdef CONFIG_TKIP_DEBUG |
388 | { | 319 | { |
389 | int i; | 320 | int i; |
@@ -409,5 +340,3 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
409 | 340 | ||
410 | return res; | 341 | return res; |
411 | } | 342 | } |
412 | |||
413 | |||
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h index b7c2ee763d9d..b890427fc959 100644 --- a/net/mac80211/tkip.h +++ b/net/mac80211/tkip.h | |||
@@ -13,12 +13,8 @@ | |||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | #include "key.h" | 14 | #include "key.h" |
15 | 15 | ||
16 | u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, | 16 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, |
17 | u8 iv0, u8 iv1, u8 iv2); | 17 | u8 iv0, u8 iv1, u8 iv2); |
18 | void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta, | ||
19 | u16 *phase1key); | ||
20 | void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta, | ||
21 | u8 *rc4key); | ||
22 | void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | 18 | void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, |
23 | struct ieee80211_key *key, | 19 | struct ieee80211_key *key, |
24 | u8 *pos, size_t payload_len, u8 *ta); | 20 | u8 *pos, size_t payload_len, u8 *ta); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1d7dd54aacef..1ad9e664f287 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -91,11 +91,12 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
91 | int next_frag_len) | 91 | int next_frag_len) |
92 | { | 92 | { |
93 | int rate, mrate, erp, dur, i; | 93 | int rate, mrate, erp, dur, i; |
94 | struct ieee80211_rate *txrate = tx->rate; | 94 | struct ieee80211_rate *txrate; |
95 | struct ieee80211_local *local = tx->local; | 95 | struct ieee80211_local *local = tx->local; |
96 | struct ieee80211_supported_band *sband; | 96 | struct ieee80211_supported_band *sband; |
97 | 97 | ||
98 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 98 | sband = local->hw.wiphy->bands[tx->channel->band]; |
99 | txrate = &sband->bitrates[tx->rate_idx]; | ||
99 | 100 | ||
100 | erp = 0; | 101 | erp = 0; |
101 | if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 102 | if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
@@ -212,18 +213,6 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
212 | return dur; | 213 | return dur; |
213 | } | 214 | } |
214 | 215 | ||
215 | static inline int __ieee80211_queue_stopped(const struct ieee80211_local *local, | ||
216 | int queue) | ||
217 | { | ||
218 | return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]); | ||
219 | } | ||
220 | |||
221 | static inline int __ieee80211_queue_pending(const struct ieee80211_local *local, | ||
222 | int queue) | ||
223 | { | ||
224 | return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]); | ||
225 | } | ||
226 | |||
227 | static int inline is_ieee80211_device(struct net_device *dev, | 216 | static int inline is_ieee80211_device(struct net_device *dev, |
228 | struct net_device *master) | 217 | struct net_device *master) |
229 | { | 218 | { |
@@ -237,12 +226,12 @@ static ieee80211_tx_result | |||
237 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | 226 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) |
238 | { | 227 | { |
239 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 228 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
240 | struct sk_buff *skb = tx->skb; | 229 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
241 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
242 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 230 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
231 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
243 | u32 sta_flags; | 232 | u32 sta_flags; |
244 | 233 | ||
245 | if (unlikely(tx->flags & IEEE80211_TX_INJECTED)) | 234 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) |
246 | return TX_CONTINUE; | 235 | return TX_CONTINUE; |
247 | 236 | ||
248 | if (unlikely(tx->local->sta_sw_scanning) && | 237 | if (unlikely(tx->local->sta_sw_scanning) && |
@@ -256,7 +245,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
256 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) | 245 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) |
257 | return TX_CONTINUE; | 246 | return TX_CONTINUE; |
258 | 247 | ||
259 | sta_flags = tx->sta ? tx->sta->flags : 0; | 248 | sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; |
260 | 249 | ||
261 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { | 250 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { |
262 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && | 251 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && |
@@ -347,6 +336,8 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
347 | static ieee80211_tx_result | 336 | static ieee80211_tx_result |
348 | ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | 337 | ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) |
349 | { | 338 | { |
339 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
340 | |||
350 | /* | 341 | /* |
351 | * broadcast/multicast frame | 342 | * broadcast/multicast frame |
352 | * | 343 | * |
@@ -382,7 +373,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
382 | } | 373 | } |
383 | 374 | ||
384 | /* buffered in hardware */ | 375 | /* buffered in hardware */ |
385 | tx->control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM; | 376 | info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; |
386 | 377 | ||
387 | return TX_CONTINUE; | 378 | return TX_CONTINUE; |
388 | } | 379 | } |
@@ -391,6 +382,8 @@ static ieee80211_tx_result | |||
391 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | 382 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) |
392 | { | 383 | { |
393 | struct sta_info *sta = tx->sta; | 384 | struct sta_info *sta = tx->sta; |
385 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
386 | u32 staflags; | ||
394 | DECLARE_MAC_BUF(mac); | 387 | DECLARE_MAC_BUF(mac); |
395 | 388 | ||
396 | if (unlikely(!sta || | 389 | if (unlikely(!sta || |
@@ -398,9 +391,10 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
398 | (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP))) | 391 | (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP))) |
399 | return TX_CONTINUE; | 392 | return TX_CONTINUE; |
400 | 393 | ||
401 | if (unlikely((sta->flags & WLAN_STA_PS) && | 394 | staflags = get_sta_flags(sta); |
402 | !(sta->flags & WLAN_STA_PSPOLL))) { | 395 | |
403 | struct ieee80211_tx_packet_data *pkt_data; | 396 | if (unlikely((staflags & WLAN_STA_PS) && |
397 | !(staflags & WLAN_STA_PSPOLL))) { | ||
404 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 398 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
405 | printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " | 399 | printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " |
406 | "before %d)\n", | 400 | "before %d)\n", |
@@ -424,19 +418,18 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
424 | if (skb_queue_empty(&sta->ps_tx_buf)) | 418 | if (skb_queue_empty(&sta->ps_tx_buf)) |
425 | sta_info_set_tim_bit(sta); | 419 | sta_info_set_tim_bit(sta); |
426 | 420 | ||
427 | pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb; | 421 | info->control.jiffies = jiffies; |
428 | pkt_data->jiffies = jiffies; | ||
429 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 422 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); |
430 | return TX_QUEUED; | 423 | return TX_QUEUED; |
431 | } | 424 | } |
432 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 425 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
433 | else if (unlikely(sta->flags & WLAN_STA_PS)) { | 426 | else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { |
434 | printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " | 427 | printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " |
435 | "set -> send frame\n", tx->dev->name, | 428 | "set -> send frame\n", tx->dev->name, |
436 | print_mac(mac, sta->addr)); | 429 | print_mac(mac, sta->addr)); |
437 | } | 430 | } |
438 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 431 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
439 | sta->flags &= ~WLAN_STA_PSPOLL; | 432 | clear_sta_flags(sta, WLAN_STA_PSPOLL); |
440 | 433 | ||
441 | return TX_CONTINUE; | 434 | return TX_CONTINUE; |
442 | } | 435 | } |
@@ -457,17 +450,18 @@ static ieee80211_tx_result | |||
457 | ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | 450 | ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) |
458 | { | 451 | { |
459 | struct ieee80211_key *key; | 452 | struct ieee80211_key *key; |
453 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
460 | u16 fc = tx->fc; | 454 | u16 fc = tx->fc; |
461 | 455 | ||
462 | if (unlikely(tx->control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) | 456 | if (unlikely(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) |
463 | tx->key = NULL; | 457 | tx->key = NULL; |
464 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 458 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
465 | tx->key = key; | 459 | tx->key = key; |
466 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 460 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
467 | tx->key = key; | 461 | tx->key = key; |
468 | else if (tx->sdata->drop_unencrypted && | 462 | else if (tx->sdata->drop_unencrypted && |
469 | !(tx->control->flags & IEEE80211_TXCTL_EAPOL_FRAME) && | 463 | !(info->flags & IEEE80211_TX_CTL_EAPOL_FRAME) && |
470 | !(tx->flags & IEEE80211_TX_INJECTED)) { | 464 | !(info->flags & IEEE80211_TX_CTL_INJECTED)) { |
471 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 465 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
472 | return TX_DROP; | 466 | return TX_DROP; |
473 | } else | 467 | } else |
@@ -496,7 +490,156 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
496 | } | 490 | } |
497 | 491 | ||
498 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 492 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
499 | tx->control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT; | 493 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; |
494 | |||
495 | return TX_CONTINUE; | ||
496 | } | ||
497 | |||
498 | static ieee80211_tx_result | ||
499 | ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | ||
500 | { | ||
501 | struct rate_selection rsel; | ||
502 | struct ieee80211_supported_band *sband; | ||
503 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
504 | |||
505 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | ||
506 | |||
507 | if (likely(tx->rate_idx < 0)) { | ||
508 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); | ||
509 | tx->rate_idx = rsel.rate_idx; | ||
510 | if (unlikely(rsel.probe_idx >= 0)) { | ||
511 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | ||
512 | tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; | ||
513 | info->control.alt_retry_rate_idx = tx->rate_idx; | ||
514 | tx->rate_idx = rsel.probe_idx; | ||
515 | } else | ||
516 | info->control.alt_retry_rate_idx = -1; | ||
517 | |||
518 | if (unlikely(tx->rate_idx < 0)) | ||
519 | return TX_DROP; | ||
520 | } else | ||
521 | info->control.alt_retry_rate_idx = -1; | ||
522 | |||
523 | if (tx->sdata->bss_conf.use_cts_prot && | ||
524 | (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { | ||
525 | tx->last_frag_rate_idx = tx->rate_idx; | ||
526 | if (rsel.probe_idx >= 0) | ||
527 | tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG; | ||
528 | else | ||
529 | tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; | ||
530 | tx->rate_idx = rsel.nonerp_idx; | ||
531 | info->tx_rate_idx = rsel.nonerp_idx; | ||
532 | info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; | ||
533 | } else { | ||
534 | tx->last_frag_rate_idx = tx->rate_idx; | ||
535 | info->tx_rate_idx = tx->rate_idx; | ||
536 | } | ||
537 | info->tx_rate_idx = tx->rate_idx; | ||
538 | |||
539 | return TX_CONTINUE; | ||
540 | } | ||
541 | |||
542 | static ieee80211_tx_result | ||
543 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | ||
544 | { | ||
545 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | ||
546 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
547 | u16 dur; | ||
548 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
549 | struct ieee80211_supported_band *sband; | ||
550 | |||
551 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | ||
552 | |||
553 | if (tx->sta) | ||
554 | info->control.aid = tx->sta->aid; | ||
555 | |||
556 | if (!info->control.retry_limit) { | ||
557 | if (!is_multicast_ether_addr(hdr->addr1)) { | ||
558 | int len = min_t(int, tx->skb->len + FCS_LEN, | ||
559 | tx->local->fragmentation_threshold); | ||
560 | if (len > tx->local->rts_threshold | ||
561 | && tx->local->rts_threshold < | ||
562 | IEEE80211_MAX_RTS_THRESHOLD) { | ||
563 | info->flags |= IEEE80211_TX_CTL_USE_RTS_CTS; | ||
564 | info->flags |= | ||
565 | IEEE80211_TX_CTL_LONG_RETRY_LIMIT; | ||
566 | info->control.retry_limit = | ||
567 | tx->local->long_retry_limit; | ||
568 | } else { | ||
569 | info->control.retry_limit = | ||
570 | tx->local->short_retry_limit; | ||
571 | } | ||
572 | } else { | ||
573 | info->control.retry_limit = 1; | ||
574 | } | ||
575 | } | ||
576 | |||
577 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { | ||
578 | /* Do not use multiple retry rates when sending fragmented | ||
579 | * frames. | ||
580 | * TODO: The last fragment could still use multiple retry | ||
581 | * rates. */ | ||
582 | info->control.alt_retry_rate_idx = -1; | ||
583 | } | ||
584 | |||
585 | /* Use CTS protection for unicast frames sent using extended rates if | ||
586 | * there are associated non-ERP stations and RTS/CTS is not configured | ||
587 | * for the frame. */ | ||
588 | if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) && | ||
589 | (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_ERP_G) && | ||
590 | (tx->flags & IEEE80211_TX_UNICAST) && | ||
591 | tx->sdata->bss_conf.use_cts_prot && | ||
592 | !(info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)) | ||
593 | info->flags |= IEEE80211_TX_CTL_USE_CTS_PROTECT; | ||
594 | |||
595 | /* Transmit data frames using short preambles if the driver supports | ||
596 | * short preambles at the selected rate and short preambles are | ||
597 | * available on the network at the current point in time. */ | ||
598 | if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | ||
599 | (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && | ||
600 | tx->sdata->bss_conf.use_short_preamble && | ||
601 | (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { | ||
602 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | ||
603 | } | ||
604 | |||
605 | /* Setup duration field for the first fragment of the frame. Duration | ||
606 | * for remaining fragments will be updated when they are being sent | ||
607 | * to low-level driver in ieee80211_tx(). */ | ||
608 | dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1), | ||
609 | (tx->flags & IEEE80211_TX_FRAGMENTED) ? | ||
610 | tx->extra_frag[0]->len : 0); | ||
611 | hdr->duration_id = cpu_to_le16(dur); | ||
612 | |||
613 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || | ||
614 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { | ||
615 | struct ieee80211_rate *rate; | ||
616 | s8 baserate = -1; | ||
617 | int idx; | ||
618 | |||
619 | /* Do not use multiple retry rates when using RTS/CTS */ | ||
620 | info->control.alt_retry_rate_idx = -1; | ||
621 | |||
622 | /* Use min(data rate, max base rate) as CTS/RTS rate */ | ||
623 | rate = &sband->bitrates[tx->rate_idx]; | ||
624 | |||
625 | for (idx = 0; idx < sband->n_bitrates; idx++) { | ||
626 | if (sband->bitrates[idx].bitrate > rate->bitrate) | ||
627 | continue; | ||
628 | if (tx->sdata->basic_rates & BIT(idx) && | ||
629 | (baserate < 0 || | ||
630 | (sband->bitrates[baserate].bitrate | ||
631 | < sband->bitrates[idx].bitrate))) | ||
632 | baserate = idx; | ||
633 | } | ||
634 | |||
635 | if (baserate >= 0) | ||
636 | info->control.rts_cts_rate_idx = baserate; | ||
637 | else | ||
638 | info->control.rts_cts_rate_idx = 0; | ||
639 | } | ||
640 | |||
641 | if (tx->sta) | ||
642 | info->control.aid = tx->sta->aid; | ||
500 | 643 | ||
501 | return TX_CONTINUE; | 644 | return TX_CONTINUE; |
502 | } | 645 | } |
@@ -515,6 +658,17 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
515 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) | 658 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) |
516 | return TX_CONTINUE; | 659 | return TX_CONTINUE; |
517 | 660 | ||
661 | /* | ||
662 | * Warn when submitting a fragmented A-MPDU frame and drop it. | ||
663 | * This is an error and needs to be fixed elsewhere, but when | ||
664 | * done needs to take care of monitor interfaces (injection) | ||
665 | * etc. | ||
666 | */ | ||
667 | if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || | ||
668 | skb_get_queue_mapping(tx->skb) >= | ||
669 | ieee80211_num_regular_queues(&tx->local->hw))) | ||
670 | return TX_DROP; | ||
671 | |||
518 | first = tx->skb; | 672 | first = tx->skb; |
519 | 673 | ||
520 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 674 | hdrlen = ieee80211_get_hdrlen(tx->fc); |
@@ -602,215 +756,22 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | |||
602 | } | 756 | } |
603 | 757 | ||
604 | static ieee80211_tx_result | 758 | static ieee80211_tx_result |
605 | ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | 759 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
606 | { | 760 | { |
607 | struct rate_selection rsel; | 761 | int i; |
608 | struct ieee80211_supported_band *sband; | ||
609 | |||
610 | sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band]; | ||
611 | |||
612 | if (likely(!tx->rate)) { | ||
613 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); | ||
614 | tx->rate = rsel.rate; | ||
615 | if (unlikely(rsel.probe)) { | ||
616 | tx->control->flags |= | ||
617 | IEEE80211_TXCTL_RATE_CTRL_PROBE; | ||
618 | tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; | ||
619 | tx->control->alt_retry_rate = tx->rate; | ||
620 | tx->rate = rsel.probe; | ||
621 | } else | ||
622 | tx->control->alt_retry_rate = NULL; | ||
623 | |||
624 | if (!tx->rate) | ||
625 | return TX_DROP; | ||
626 | } else | ||
627 | tx->control->alt_retry_rate = NULL; | ||
628 | |||
629 | if (tx->sdata->bss_conf.use_cts_prot && | ||
630 | (tx->flags & IEEE80211_TX_FRAGMENTED) && rsel.nonerp) { | ||
631 | tx->last_frag_rate = tx->rate; | ||
632 | if (rsel.probe) | ||
633 | tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG; | ||
634 | else | ||
635 | tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; | ||
636 | tx->rate = rsel.nonerp; | ||
637 | tx->control->tx_rate = rsel.nonerp; | ||
638 | tx->control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE; | ||
639 | } else { | ||
640 | tx->last_frag_rate = tx->rate; | ||
641 | tx->control->tx_rate = tx->rate; | ||
642 | } | ||
643 | tx->control->tx_rate = tx->rate; | ||
644 | |||
645 | return TX_CONTINUE; | ||
646 | } | ||
647 | |||
648 | static ieee80211_tx_result | ||
649 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | ||
650 | { | ||
651 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | ||
652 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
653 | u16 dur; | ||
654 | struct ieee80211_tx_control *control = tx->control; | ||
655 | |||
656 | if (!control->retry_limit) { | ||
657 | if (!is_multicast_ether_addr(hdr->addr1)) { | ||
658 | if (tx->skb->len + FCS_LEN > tx->local->rts_threshold | ||
659 | && tx->local->rts_threshold < | ||
660 | IEEE80211_MAX_RTS_THRESHOLD) { | ||
661 | control->flags |= | ||
662 | IEEE80211_TXCTL_USE_RTS_CTS; | ||
663 | control->flags |= | ||
664 | IEEE80211_TXCTL_LONG_RETRY_LIMIT; | ||
665 | control->retry_limit = | ||
666 | tx->local->long_retry_limit; | ||
667 | } else { | ||
668 | control->retry_limit = | ||
669 | tx->local->short_retry_limit; | ||
670 | } | ||
671 | } else { | ||
672 | control->retry_limit = 1; | ||
673 | } | ||
674 | } | ||
675 | |||
676 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { | ||
677 | /* Do not use multiple retry rates when sending fragmented | ||
678 | * frames. | ||
679 | * TODO: The last fragment could still use multiple retry | ||
680 | * rates. */ | ||
681 | control->alt_retry_rate = NULL; | ||
682 | } | ||
683 | |||
684 | /* Use CTS protection for unicast frames sent using extended rates if | ||
685 | * there are associated non-ERP stations and RTS/CTS is not configured | ||
686 | * for the frame. */ | ||
687 | if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) && | ||
688 | (tx->rate->flags & IEEE80211_RATE_ERP_G) && | ||
689 | (tx->flags & IEEE80211_TX_UNICAST) && | ||
690 | tx->sdata->bss_conf.use_cts_prot && | ||
691 | !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) | ||
692 | control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT; | ||
693 | |||
694 | /* Transmit data frames using short preambles if the driver supports | ||
695 | * short preambles at the selected rate and short preambles are | ||
696 | * available on the network at the current point in time. */ | ||
697 | if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | ||
698 | (tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && | ||
699 | tx->sdata->bss_conf.use_short_preamble && | ||
700 | (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) { | ||
701 | tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; | ||
702 | } | ||
703 | |||
704 | /* Setup duration field for the first fragment of the frame. Duration | ||
705 | * for remaining fragments will be updated when they are being sent | ||
706 | * to low-level driver in ieee80211_tx(). */ | ||
707 | dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1), | ||
708 | (tx->flags & IEEE80211_TX_FRAGMENTED) ? | ||
709 | tx->extra_frag[0]->len : 0); | ||
710 | hdr->duration_id = cpu_to_le16(dur); | ||
711 | |||
712 | if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) || | ||
713 | (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) { | ||
714 | struct ieee80211_supported_band *sband; | ||
715 | struct ieee80211_rate *rate, *baserate; | ||
716 | int idx; | ||
717 | |||
718 | sband = tx->local->hw.wiphy->bands[ | ||
719 | tx->local->hw.conf.channel->band]; | ||
720 | |||
721 | /* Do not use multiple retry rates when using RTS/CTS */ | ||
722 | control->alt_retry_rate = NULL; | ||
723 | |||
724 | /* Use min(data rate, max base rate) as CTS/RTS rate */ | ||
725 | rate = tx->rate; | ||
726 | baserate = NULL; | ||
727 | |||
728 | for (idx = 0; idx < sband->n_bitrates; idx++) { | ||
729 | if (sband->bitrates[idx].bitrate > rate->bitrate) | ||
730 | continue; | ||
731 | if (tx->sdata->basic_rates & BIT(idx) && | ||
732 | (!baserate || | ||
733 | (baserate->bitrate < sband->bitrates[idx].bitrate))) | ||
734 | baserate = &sband->bitrates[idx]; | ||
735 | } | ||
736 | |||
737 | if (baserate) | ||
738 | control->rts_cts_rate = baserate; | ||
739 | else | ||
740 | control->rts_cts_rate = &sband->bitrates[0]; | ||
741 | } | ||
742 | |||
743 | if (tx->sta) { | ||
744 | control->aid = tx->sta->aid; | ||
745 | tx->sta->tx_packets++; | ||
746 | tx->sta->tx_fragments++; | ||
747 | tx->sta->tx_bytes += tx->skb->len; | ||
748 | if (tx->extra_frag) { | ||
749 | int i; | ||
750 | tx->sta->tx_fragments += tx->num_extra_frag; | ||
751 | for (i = 0; i < tx->num_extra_frag; i++) { | ||
752 | tx->sta->tx_bytes += | ||
753 | tx->extra_frag[i]->len; | ||
754 | } | ||
755 | } | ||
756 | } | ||
757 | |||
758 | return TX_CONTINUE; | ||
759 | } | ||
760 | |||
761 | static ieee80211_tx_result | ||
762 | ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx) | ||
763 | { | ||
764 | struct ieee80211_local *local = tx->local; | ||
765 | struct sk_buff *skb = tx->skb; | ||
766 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
767 | u32 load = 0, hdrtime; | ||
768 | struct ieee80211_rate *rate = tx->rate; | ||
769 | |||
770 | /* TODO: this could be part of tx_status handling, so that the number | ||
771 | * of retries would be known; TX rate should in that case be stored | ||
772 | * somewhere with the packet */ | ||
773 | |||
774 | /* Estimate total channel use caused by this frame */ | ||
775 | |||
776 | /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values, | ||
777 | * 1 usec = 1/8 * (1080 / 10) = 13.5 */ | ||
778 | |||
779 | if (tx->channel->band == IEEE80211_BAND_5GHZ || | ||
780 | (tx->channel->band == IEEE80211_BAND_2GHZ && | ||
781 | rate->flags & IEEE80211_RATE_ERP_G)) | ||
782 | hdrtime = CHAN_UTIL_HDR_SHORT; | ||
783 | else | ||
784 | hdrtime = CHAN_UTIL_HDR_LONG; | ||
785 | |||
786 | load = hdrtime; | ||
787 | if (!is_multicast_ether_addr(hdr->addr1)) | ||
788 | load += hdrtime; | ||
789 | |||
790 | if (tx->control->flags & IEEE80211_TXCTL_USE_RTS_CTS) | ||
791 | load += 2 * hdrtime; | ||
792 | else if (tx->control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) | ||
793 | load += hdrtime; | ||
794 | 762 | ||
795 | /* TODO: optimise again */ | 763 | if (!tx->sta) |
796 | load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate; | 764 | return TX_CONTINUE; |
797 | 765 | ||
766 | tx->sta->tx_packets++; | ||
767 | tx->sta->tx_fragments++; | ||
768 | tx->sta->tx_bytes += tx->skb->len; | ||
798 | if (tx->extra_frag) { | 769 | if (tx->extra_frag) { |
799 | int i; | 770 | tx->sta->tx_fragments += tx->num_extra_frag; |
800 | for (i = 0; i < tx->num_extra_frag; i++) { | 771 | for (i = 0; i < tx->num_extra_frag; i++) |
801 | load += 2 * hdrtime; | 772 | tx->sta->tx_bytes += tx->extra_frag[i]->len; |
802 | load += tx->extra_frag[i]->len * | ||
803 | tx->rate->bitrate; | ||
804 | } | ||
805 | } | 773 | } |
806 | 774 | ||
807 | /* Divide channel_use by 8 to avoid wrapping around the counter */ | ||
808 | load >>= CHAN_UTIL_SHIFT; | ||
809 | local->channel_use_raw += load; | ||
810 | if (tx->sta) | ||
811 | tx->sta->channel_use_raw += load; | ||
812 | tx->sdata->channel_use_raw += load; | ||
813 | |||
814 | return TX_CONTINUE; | 775 | return TX_CONTINUE; |
815 | } | 776 | } |
816 | 777 | ||
@@ -823,11 +784,12 @@ static ieee80211_tx_handler ieee80211_tx_handlers[] = | |||
823 | ieee80211_tx_h_ps_buf, | 784 | ieee80211_tx_h_ps_buf, |
824 | ieee80211_tx_h_select_key, | 785 | ieee80211_tx_h_select_key, |
825 | ieee80211_tx_h_michael_mic_add, | 786 | ieee80211_tx_h_michael_mic_add, |
826 | ieee80211_tx_h_fragment, | ||
827 | ieee80211_tx_h_encrypt, | ||
828 | ieee80211_tx_h_rate_ctrl, | 787 | ieee80211_tx_h_rate_ctrl, |
829 | ieee80211_tx_h_misc, | 788 | ieee80211_tx_h_misc, |
830 | ieee80211_tx_h_load_stats, | 789 | ieee80211_tx_h_fragment, |
790 | /* handlers after fragment must be aware of tx info fragmentation! */ | ||
791 | ieee80211_tx_h_encrypt, | ||
792 | ieee80211_tx_h_stats, | ||
831 | NULL | 793 | NULL |
832 | }; | 794 | }; |
833 | 795 | ||
@@ -854,12 +816,12 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
854 | (struct ieee80211_radiotap_header *) skb->data; | 816 | (struct ieee80211_radiotap_header *) skb->data; |
855 | struct ieee80211_supported_band *sband; | 817 | struct ieee80211_supported_band *sband; |
856 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | 818 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); |
857 | struct ieee80211_tx_control *control = tx->control; | 819 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
858 | 820 | ||
859 | sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band]; | 821 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
860 | 822 | ||
861 | control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT; | 823 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; |
862 | tx->flags |= IEEE80211_TX_INJECTED; | 824 | info->flags |= IEEE80211_TX_CTL_INJECTED; |
863 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 825 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
864 | 826 | ||
865 | /* | 827 | /* |
@@ -896,7 +858,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
896 | r = &sband->bitrates[i]; | 858 | r = &sband->bitrates[i]; |
897 | 859 | ||
898 | if (r->bitrate == target_rate) { | 860 | if (r->bitrate == target_rate) { |
899 | tx->rate = r; | 861 | tx->rate_idx = i; |
900 | break; | 862 | break; |
901 | } | 863 | } |
902 | } | 864 | } |
@@ -907,7 +869,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
907 | * radiotap uses 0 for 1st ant, mac80211 is 1 for | 869 | * radiotap uses 0 for 1st ant, mac80211 is 1 for |
908 | * 1st ant | 870 | * 1st ant |
909 | */ | 871 | */ |
910 | control->antenna_sel_tx = (*iterator.this_arg) + 1; | 872 | info->antenna_sel_tx = (*iterator.this_arg) + 1; |
911 | break; | 873 | break; |
912 | 874 | ||
913 | #if 0 | 875 | #if 0 |
@@ -931,8 +893,8 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
931 | skb_trim(skb, skb->len - FCS_LEN); | 893 | skb_trim(skb, skb->len - FCS_LEN); |
932 | } | 894 | } |
933 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | 895 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) |
934 | control->flags &= | 896 | info->flags &= |
935 | ~IEEE80211_TXCTL_DO_NOT_ENCRYPT; | 897 | ~IEEE80211_TX_CTL_DO_NOT_ENCRYPT; |
936 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | 898 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) |
937 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 899 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
938 | break; | 900 | break; |
@@ -967,12 +929,12 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
967 | static ieee80211_tx_result | 929 | static ieee80211_tx_result |
968 | __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 930 | __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, |
969 | struct sk_buff *skb, | 931 | struct sk_buff *skb, |
970 | struct net_device *dev, | 932 | struct net_device *dev) |
971 | struct ieee80211_tx_control *control) | ||
972 | { | 933 | { |
973 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 934 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
974 | struct ieee80211_hdr *hdr; | 935 | struct ieee80211_hdr *hdr; |
975 | struct ieee80211_sub_if_data *sdata; | 936 | struct ieee80211_sub_if_data *sdata; |
937 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
976 | 938 | ||
977 | int hdrlen; | 939 | int hdrlen; |
978 | 940 | ||
@@ -981,7 +943,9 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
981 | tx->dev = dev; /* use original interface */ | 943 | tx->dev = dev; /* use original interface */ |
982 | tx->local = local; | 944 | tx->local = local; |
983 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 945 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
984 | tx->control = control; | 946 | tx->channel = local->hw.conf.channel; |
947 | tx->rate_idx = -1; | ||
948 | tx->last_frag_rate_idx = -1; | ||
985 | /* | 949 | /* |
986 | * Set this flag (used below to indicate "automatic fragmentation"), | 950 | * Set this flag (used below to indicate "automatic fragmentation"), |
987 | * it will be cleared/left by radiotap as desired. | 951 | * it will be cleared/left by radiotap as desired. |
@@ -1008,10 +972,10 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1008 | 972 | ||
1009 | if (is_multicast_ether_addr(hdr->addr1)) { | 973 | if (is_multicast_ether_addr(hdr->addr1)) { |
1010 | tx->flags &= ~IEEE80211_TX_UNICAST; | 974 | tx->flags &= ~IEEE80211_TX_UNICAST; |
1011 | control->flags |= IEEE80211_TXCTL_NO_ACK; | 975 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
1012 | } else { | 976 | } else { |
1013 | tx->flags |= IEEE80211_TX_UNICAST; | 977 | tx->flags |= IEEE80211_TX_UNICAST; |
1014 | control->flags &= ~IEEE80211_TXCTL_NO_ACK; | 978 | info->flags &= ~IEEE80211_TX_CTL_NO_ACK; |
1015 | } | 979 | } |
1016 | 980 | ||
1017 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { | 981 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { |
@@ -1024,18 +988,16 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1024 | } | 988 | } |
1025 | 989 | ||
1026 | if (!tx->sta) | 990 | if (!tx->sta) |
1027 | control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; | 991 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1028 | else if (tx->sta->flags & WLAN_STA_CLEAR_PS_FILT) { | 992 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) |
1029 | control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; | 993 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1030 | tx->sta->flags &= ~WLAN_STA_CLEAR_PS_FILT; | ||
1031 | } | ||
1032 | 994 | ||
1033 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 995 | hdrlen = ieee80211_get_hdrlen(tx->fc); |
1034 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | 996 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { |
1035 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | 997 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; |
1036 | tx->ethertype = (pos[0] << 8) | pos[1]; | 998 | tx->ethertype = (pos[0] << 8) | pos[1]; |
1037 | } | 999 | } |
1038 | control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT; | 1000 | info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT; |
1039 | 1001 | ||
1040 | return TX_CONTINUE; | 1002 | return TX_CONTINUE; |
1041 | } | 1003 | } |
@@ -1045,14 +1007,12 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1045 | */ | 1007 | */ |
1046 | static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 1008 | static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, |
1047 | struct sk_buff *skb, | 1009 | struct sk_buff *skb, |
1048 | struct net_device *mdev, | 1010 | struct net_device *mdev) |
1049 | struct ieee80211_tx_control *control) | ||
1050 | { | 1011 | { |
1051 | struct ieee80211_tx_packet_data *pkt_data; | 1012 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1052 | struct net_device *dev; | 1013 | struct net_device *dev; |
1053 | 1014 | ||
1054 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | 1015 | dev = dev_get_by_index(&init_net, info->control.ifindex); |
1055 | dev = dev_get_by_index(&init_net, pkt_data->ifindex); | ||
1056 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { | 1016 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { |
1057 | dev_put(dev); | 1017 | dev_put(dev); |
1058 | dev = NULL; | 1018 | dev = NULL; |
@@ -1060,7 +1020,7 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1060 | if (unlikely(!dev)) | 1020 | if (unlikely(!dev)) |
1061 | return -ENODEV; | 1021 | return -ENODEV; |
1062 | /* initialises tx with control */ | 1022 | /* initialises tx with control */ |
1063 | __ieee80211_tx_prepare(tx, skb, dev, control); | 1023 | __ieee80211_tx_prepare(tx, skb, dev); |
1064 | dev_put(dev); | 1024 | dev_put(dev); |
1065 | return 0; | 1025 | return 0; |
1066 | } | 1026 | } |
@@ -1068,50 +1028,49 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1068 | static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | 1028 | static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, |
1069 | struct ieee80211_tx_data *tx) | 1029 | struct ieee80211_tx_data *tx) |
1070 | { | 1030 | { |
1071 | struct ieee80211_tx_control *control = tx->control; | 1031 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1072 | int ret, i; | 1032 | int ret, i; |
1073 | 1033 | ||
1074 | if (!ieee80211_qdisc_installed(local->mdev) && | 1034 | if (netif_subqueue_stopped(local->mdev, skb)) |
1075 | __ieee80211_queue_stopped(local, 0)) { | ||
1076 | netif_stop_queue(local->mdev); | ||
1077 | return IEEE80211_TX_AGAIN; | 1035 | return IEEE80211_TX_AGAIN; |
1078 | } | 1036 | |
1079 | if (skb) { | 1037 | if (skb) { |
1080 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | 1038 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), |
1081 | "TX to low-level driver", skb); | 1039 | "TX to low-level driver", skb); |
1082 | ret = local->ops->tx(local_to_hw(local), skb, control); | 1040 | ret = local->ops->tx(local_to_hw(local), skb); |
1083 | if (ret) | 1041 | if (ret) |
1084 | return IEEE80211_TX_AGAIN; | 1042 | return IEEE80211_TX_AGAIN; |
1085 | local->mdev->trans_start = jiffies; | 1043 | local->mdev->trans_start = jiffies; |
1086 | ieee80211_led_tx(local, 1); | 1044 | ieee80211_led_tx(local, 1); |
1087 | } | 1045 | } |
1088 | if (tx->extra_frag) { | 1046 | if (tx->extra_frag) { |
1089 | control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS | | ||
1090 | IEEE80211_TXCTL_USE_CTS_PROTECT | | ||
1091 | IEEE80211_TXCTL_CLEAR_PS_FILT | | ||
1092 | IEEE80211_TXCTL_FIRST_FRAGMENT); | ||
1093 | for (i = 0; i < tx->num_extra_frag; i++) { | 1047 | for (i = 0; i < tx->num_extra_frag; i++) { |
1094 | if (!tx->extra_frag[i]) | 1048 | if (!tx->extra_frag[i]) |
1095 | continue; | 1049 | continue; |
1096 | if (__ieee80211_queue_stopped(local, control->queue)) | 1050 | info = IEEE80211_SKB_CB(tx->extra_frag[i]); |
1051 | info->flags &= ~(IEEE80211_TX_CTL_USE_RTS_CTS | | ||
1052 | IEEE80211_TX_CTL_USE_CTS_PROTECT | | ||
1053 | IEEE80211_TX_CTL_CLEAR_PS_FILT | | ||
1054 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | ||
1055 | if (netif_subqueue_stopped(local->mdev, | ||
1056 | tx->extra_frag[i])) | ||
1097 | return IEEE80211_TX_FRAG_AGAIN; | 1057 | return IEEE80211_TX_FRAG_AGAIN; |
1098 | if (i == tx->num_extra_frag) { | 1058 | if (i == tx->num_extra_frag) { |
1099 | control->tx_rate = tx->last_frag_rate; | 1059 | info->tx_rate_idx = tx->last_frag_rate_idx; |
1100 | 1060 | ||
1101 | if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG) | 1061 | if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG) |
1102 | control->flags |= | 1062 | info->flags |= |
1103 | IEEE80211_TXCTL_RATE_CTRL_PROBE; | 1063 | IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
1104 | else | 1064 | else |
1105 | control->flags &= | 1065 | info->flags &= |
1106 | ~IEEE80211_TXCTL_RATE_CTRL_PROBE; | 1066 | ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
1107 | } | 1067 | } |
1108 | 1068 | ||
1109 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | 1069 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), |
1110 | "TX to low-level driver", | 1070 | "TX to low-level driver", |
1111 | tx->extra_frag[i]); | 1071 | tx->extra_frag[i]); |
1112 | ret = local->ops->tx(local_to_hw(local), | 1072 | ret = local->ops->tx(local_to_hw(local), |
1113 | tx->extra_frag[i], | 1073 | tx->extra_frag[i]); |
1114 | control); | ||
1115 | if (ret) | 1074 | if (ret) |
1116 | return IEEE80211_TX_FRAG_AGAIN; | 1075 | return IEEE80211_TX_FRAG_AGAIN; |
1117 | local->mdev->trans_start = jiffies; | 1076 | local->mdev->trans_start = jiffies; |
@@ -1124,17 +1083,20 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1124 | return IEEE80211_TX_OK; | 1083 | return IEEE80211_TX_OK; |
1125 | } | 1084 | } |
1126 | 1085 | ||
1127 | static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | 1086 | static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) |
1128 | struct ieee80211_tx_control *control) | ||
1129 | { | 1087 | { |
1130 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1088 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1131 | struct sta_info *sta; | 1089 | struct sta_info *sta; |
1132 | ieee80211_tx_handler *handler; | 1090 | ieee80211_tx_handler *handler; |
1133 | struct ieee80211_tx_data tx; | 1091 | struct ieee80211_tx_data tx; |
1134 | ieee80211_tx_result res = TX_DROP, res_prepare; | 1092 | ieee80211_tx_result res = TX_DROP, res_prepare; |
1093 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1135 | int ret, i; | 1094 | int ret, i; |
1095 | u16 queue; | ||
1096 | |||
1097 | queue = skb_get_queue_mapping(skb); | ||
1136 | 1098 | ||
1137 | WARN_ON(__ieee80211_queue_pending(local, control->queue)); | 1099 | WARN_ON(test_bit(queue, local->queues_pending)); |
1138 | 1100 | ||
1139 | if (unlikely(skb->len < 10)) { | 1101 | if (unlikely(skb->len < 10)) { |
1140 | dev_kfree_skb(skb); | 1102 | dev_kfree_skb(skb); |
@@ -1144,7 +1106,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1144 | rcu_read_lock(); | 1106 | rcu_read_lock(); |
1145 | 1107 | ||
1146 | /* initialises tx */ | 1108 | /* initialises tx */ |
1147 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control); | 1109 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev); |
1148 | 1110 | ||
1149 | if (res_prepare == TX_DROP) { | 1111 | if (res_prepare == TX_DROP) { |
1150 | dev_kfree_skb(skb); | 1112 | dev_kfree_skb(skb); |
@@ -1154,6 +1116,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1154 | 1116 | ||
1155 | sta = tx.sta; | 1117 | sta = tx.sta; |
1156 | tx.channel = local->hw.conf.channel; | 1118 | tx.channel = local->hw.conf.channel; |
1119 | info->band = tx.channel->band; | ||
1157 | 1120 | ||
1158 | for (handler = ieee80211_tx_handlers; *handler != NULL; | 1121 | for (handler = ieee80211_tx_handlers; *handler != NULL; |
1159 | handler++) { | 1122 | handler++) { |
@@ -1162,7 +1125,8 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1162 | break; | 1125 | break; |
1163 | } | 1126 | } |
1164 | 1127 | ||
1165 | skb = tx.skb; /* handlers are allowed to change skb */ | 1128 | if (WARN_ON(tx.skb != skb)) |
1129 | goto drop; | ||
1166 | 1130 | ||
1167 | if (unlikely(res == TX_DROP)) { | 1131 | if (unlikely(res == TX_DROP)) { |
1168 | I802_DEBUG_INC(local->tx_handlers_drop); | 1132 | I802_DEBUG_INC(local->tx_handlers_drop); |
@@ -1186,7 +1150,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1186 | next_len = tx.extra_frag[i + 1]->len; | 1150 | next_len = tx.extra_frag[i + 1]->len; |
1187 | } else { | 1151 | } else { |
1188 | next_len = 0; | 1152 | next_len = 0; |
1189 | tx.rate = tx.last_frag_rate; | 1153 | tx.rate_idx = tx.last_frag_rate_idx; |
1190 | } | 1154 | } |
1191 | dur = ieee80211_duration(&tx, 0, next_len); | 1155 | dur = ieee80211_duration(&tx, 0, next_len); |
1192 | hdr->duration_id = cpu_to_le16(dur); | 1156 | hdr->duration_id = cpu_to_le16(dur); |
@@ -1196,34 +1160,41 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1196 | retry: | 1160 | retry: |
1197 | ret = __ieee80211_tx(local, skb, &tx); | 1161 | ret = __ieee80211_tx(local, skb, &tx); |
1198 | if (ret) { | 1162 | if (ret) { |
1199 | struct ieee80211_tx_stored_packet *store = | 1163 | struct ieee80211_tx_stored_packet *store; |
1200 | &local->pending_packet[control->queue]; | 1164 | |
1165 | /* | ||
1166 | * Since there are no fragmented frames on A-MPDU | ||
1167 | * queues, there's no reason for a driver to reject | ||
1168 | * a frame there, warn and drop it. | ||
1169 | */ | ||
1170 | if (WARN_ON(queue >= ieee80211_num_regular_queues(&local->hw))) | ||
1171 | goto drop; | ||
1172 | |||
1173 | store = &local->pending_packet[queue]; | ||
1201 | 1174 | ||
1202 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1175 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1203 | skb = NULL; | 1176 | skb = NULL; |
1204 | set_bit(IEEE80211_LINK_STATE_PENDING, | 1177 | set_bit(queue, local->queues_pending); |
1205 | &local->state[control->queue]); | ||
1206 | smp_mb(); | 1178 | smp_mb(); |
1207 | /* When the driver gets out of buffers during sending of | 1179 | /* |
1208 | * fragments and calls ieee80211_stop_queue, there is | 1180 | * When the driver gets out of buffers during sending of |
1209 | * a small window between IEEE80211_LINK_STATE_XOFF and | 1181 | * fragments and calls ieee80211_stop_queue, the netif |
1210 | * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer | 1182 | * subqueue is stopped. There is, however, a small window |
1183 | * in which the PENDING bit is not yet set. If a buffer | ||
1211 | * gets available in that window (i.e. driver calls | 1184 | * gets available in that window (i.e. driver calls |
1212 | * ieee80211_wake_queue), we would end up with ieee80211_tx | 1185 | * ieee80211_wake_queue), we would end up with ieee80211_tx |
1213 | * called with IEEE80211_LINK_STATE_PENDING. Prevent this by | 1186 | * called with the PENDING bit still set. Prevent this by |
1214 | * continuing transmitting here when that situation is | 1187 | * continuing transmitting here when that situation is |
1215 | * possible to have happened. */ | 1188 | * possible to have happened. |
1216 | if (!__ieee80211_queue_stopped(local, control->queue)) { | 1189 | */ |
1217 | clear_bit(IEEE80211_LINK_STATE_PENDING, | 1190 | if (!__netif_subqueue_stopped(local->mdev, queue)) { |
1218 | &local->state[control->queue]); | 1191 | clear_bit(queue, local->queues_pending); |
1219 | goto retry; | 1192 | goto retry; |
1220 | } | 1193 | } |
1221 | memcpy(&store->control, control, | ||
1222 | sizeof(struct ieee80211_tx_control)); | ||
1223 | store->skb = skb; | 1194 | store->skb = skb; |
1224 | store->extra_frag = tx.extra_frag; | 1195 | store->extra_frag = tx.extra_frag; |
1225 | store->num_extra_frag = tx.num_extra_frag; | 1196 | store->num_extra_frag = tx.num_extra_frag; |
1226 | store->last_frag_rate = tx.last_frag_rate; | 1197 | store->last_frag_rate_idx = tx.last_frag_rate_idx; |
1227 | store->last_frag_rate_ctrl_probe = | 1198 | store->last_frag_rate_ctrl_probe = |
1228 | !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); | 1199 | !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); |
1229 | } | 1200 | } |
@@ -1243,24 +1214,57 @@ retry: | |||
1243 | 1214 | ||
1244 | /* device xmit handlers */ | 1215 | /* device xmit handlers */ |
1245 | 1216 | ||
1217 | static int ieee80211_skb_resize(struct ieee80211_local *local, | ||
1218 | struct sk_buff *skb, | ||
1219 | int head_need, bool may_encrypt) | ||
1220 | { | ||
1221 | int tail_need = 0; | ||
1222 | |||
1223 | /* | ||
1224 | * This could be optimised, devices that do full hardware | ||
1225 | * crypto (including TKIP MMIC) need no tailroom... But we | ||
1226 | * have no drivers for such devices currently. | ||
1227 | */ | ||
1228 | if (may_encrypt) { | ||
1229 | tail_need = IEEE80211_ENCRYPT_TAILROOM; | ||
1230 | tail_need -= skb_tailroom(skb); | ||
1231 | tail_need = max_t(int, tail_need, 0); | ||
1232 | } | ||
1233 | |||
1234 | if (head_need || tail_need) { | ||
1235 | /* Sorry. Can't account for this any more */ | ||
1236 | skb_orphan(skb); | ||
1237 | } | ||
1238 | |||
1239 | if (skb_header_cloned(skb)) | ||
1240 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | ||
1241 | else | ||
1242 | I802_DEBUG_INC(local->tx_expand_skb_head); | ||
1243 | |||
1244 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { | ||
1245 | printk(KERN_DEBUG "%s: failed to reallocate TX buffer\n", | ||
1246 | wiphy_name(local->hw.wiphy)); | ||
1247 | return -ENOMEM; | ||
1248 | } | ||
1249 | |||
1250 | /* update truesize too */ | ||
1251 | skb->truesize += head_need + tail_need; | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1246 | int ieee80211_master_start_xmit(struct sk_buff *skb, | 1256 | int ieee80211_master_start_xmit(struct sk_buff *skb, |
1247 | struct net_device *dev) | 1257 | struct net_device *dev) |
1248 | { | 1258 | { |
1249 | struct ieee80211_tx_control control; | 1259 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1250 | struct ieee80211_tx_packet_data *pkt_data; | ||
1251 | struct net_device *odev = NULL; | 1260 | struct net_device *odev = NULL; |
1252 | struct ieee80211_sub_if_data *osdata; | 1261 | struct ieee80211_sub_if_data *osdata; |
1253 | int headroom; | 1262 | int headroom; |
1263 | bool may_encrypt; | ||
1254 | int ret; | 1264 | int ret; |
1255 | 1265 | ||
1256 | /* | 1266 | if (info->control.ifindex) |
1257 | * copy control out of the skb so other people can use skb->cb | 1267 | odev = dev_get_by_index(&init_net, info->control.ifindex); |
1258 | */ | ||
1259 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | ||
1260 | memset(&control, 0, sizeof(struct ieee80211_tx_control)); | ||
1261 | |||
1262 | if (pkt_data->ifindex) | ||
1263 | odev = dev_get_by_index(&init_net, pkt_data->ifindex); | ||
1264 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { | 1268 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { |
1265 | dev_put(odev); | 1269 | dev_put(odev); |
1266 | odev = NULL; | 1270 | odev = NULL; |
@@ -1273,32 +1277,25 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1273 | dev_kfree_skb(skb); | 1277 | dev_kfree_skb(skb); |
1274 | return 0; | 1278 | return 0; |
1275 | } | 1279 | } |
1280 | |||
1276 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); | 1281 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); |
1277 | 1282 | ||
1278 | headroom = osdata->local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM; | 1283 | may_encrypt = !(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT); |
1279 | if (skb_headroom(skb) < headroom) { | 1284 | |
1280 | if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { | 1285 | headroom = osdata->local->tx_headroom; |
1281 | dev_kfree_skb(skb); | 1286 | if (may_encrypt) |
1282 | dev_put(odev); | 1287 | headroom += IEEE80211_ENCRYPT_HEADROOM; |
1283 | return 0; | 1288 | headroom -= skb_headroom(skb); |
1284 | } | 1289 | headroom = max_t(int, 0, headroom); |
1290 | |||
1291 | if (ieee80211_skb_resize(osdata->local, skb, headroom, may_encrypt)) { | ||
1292 | dev_kfree_skb(skb); | ||
1293 | dev_put(odev); | ||
1294 | return 0; | ||
1285 | } | 1295 | } |
1286 | 1296 | ||
1287 | control.vif = &osdata->vif; | 1297 | info->control.vif = &osdata->vif; |
1288 | control.type = osdata->vif.type; | 1298 | ret = ieee80211_tx(odev, skb); |
1289 | if (pkt_data->flags & IEEE80211_TXPD_REQ_TX_STATUS) | ||
1290 | control.flags |= IEEE80211_TXCTL_REQ_TX_STATUS; | ||
1291 | if (pkt_data->flags & IEEE80211_TXPD_DO_NOT_ENCRYPT) | ||
1292 | control.flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT; | ||
1293 | if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) | ||
1294 | control.flags |= IEEE80211_TXCTL_REQUEUE; | ||
1295 | if (pkt_data->flags & IEEE80211_TXPD_EAPOL_FRAME) | ||
1296 | control.flags |= IEEE80211_TXCTL_EAPOL_FRAME; | ||
1297 | if (pkt_data->flags & IEEE80211_TXPD_AMPDU) | ||
1298 | control.flags |= IEEE80211_TXCTL_AMPDU; | ||
1299 | control.queue = pkt_data->queue; | ||
1300 | |||
1301 | ret = ieee80211_tx(odev, skb, &control); | ||
1302 | dev_put(odev); | 1299 | dev_put(odev); |
1303 | 1300 | ||
1304 | return ret; | 1301 | return ret; |
@@ -1308,7 +1305,7 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1308 | struct net_device *dev) | 1305 | struct net_device *dev) |
1309 | { | 1306 | { |
1310 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1307 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1311 | struct ieee80211_tx_packet_data *pkt_data; | 1308 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1312 | struct ieee80211_radiotap_header *prthdr = | 1309 | struct ieee80211_radiotap_header *prthdr = |
1313 | (struct ieee80211_radiotap_header *)skb->data; | 1310 | (struct ieee80211_radiotap_header *)skb->data; |
1314 | u16 len_rthdr; | 1311 | u16 len_rthdr; |
@@ -1330,12 +1327,12 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1330 | 1327 | ||
1331 | skb->dev = local->mdev; | 1328 | skb->dev = local->mdev; |
1332 | 1329 | ||
1333 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | ||
1334 | memset(pkt_data, 0, sizeof(*pkt_data)); | ||
1335 | /* needed because we set skb device to master */ | 1330 | /* needed because we set skb device to master */ |
1336 | pkt_data->ifindex = dev->ifindex; | 1331 | info->control.ifindex = dev->ifindex; |
1337 | 1332 | ||
1338 | pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT; | 1333 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; |
1334 | /* Interfaces should always request a status report */ | ||
1335 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1339 | 1336 | ||
1340 | /* | 1337 | /* |
1341 | * fix up the pointers accounting for the radiotap | 1338 | * fix up the pointers accounting for the radiotap |
@@ -1379,7 +1376,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1379 | struct net_device *dev) | 1376 | struct net_device *dev) |
1380 | { | 1377 | { |
1381 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1378 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1382 | struct ieee80211_tx_packet_data *pkt_data; | 1379 | struct ieee80211_tx_info *info; |
1383 | struct ieee80211_sub_if_data *sdata; | 1380 | struct ieee80211_sub_if_data *sdata; |
1384 | int ret = 1, head_need; | 1381 | int ret = 1, head_need; |
1385 | u16 ethertype, hdrlen, meshhdrlen = 0, fc; | 1382 | u16 ethertype, hdrlen, meshhdrlen = 0, fc; |
@@ -1486,12 +1483,13 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1486 | rcu_read_lock(); | 1483 | rcu_read_lock(); |
1487 | sta = sta_info_get(local, hdr.addr1); | 1484 | sta = sta_info_get(local, hdr.addr1); |
1488 | if (sta) | 1485 | if (sta) |
1489 | sta_flags = sta->flags; | 1486 | sta_flags = get_sta_flags(sta); |
1490 | rcu_read_unlock(); | 1487 | rcu_read_unlock(); |
1491 | } | 1488 | } |
1492 | 1489 | ||
1493 | /* receiver is QoS enabled, use a QoS type frame */ | 1490 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1494 | if (sta_flags & WLAN_STA_WME) { | 1491 | if (sta_flags & WLAN_STA_WME && |
1492 | ieee80211_num_regular_queues(&local->hw) >= 4) { | ||
1495 | fc |= IEEE80211_STYPE_QOS_DATA; | 1493 | fc |= IEEE80211_STYPE_QOS_DATA; |
1496 | hdrlen += 2; | 1494 | hdrlen += 2; |
1497 | } | 1495 | } |
@@ -1555,32 +1553,26 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1555 | * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and | 1553 | * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and |
1556 | * alloc_skb() (net/core/skbuff.c) | 1554 | * alloc_skb() (net/core/skbuff.c) |
1557 | */ | 1555 | */ |
1558 | head_need = hdrlen + encaps_len + meshhdrlen + local->tx_headroom; | 1556 | head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); |
1559 | head_need -= skb_headroom(skb); | ||
1560 | 1557 | ||
1561 | /* We are going to modify skb data, so make a copy of it if happens to | 1558 | /* |
1562 | * be cloned. This could happen, e.g., with Linux bridge code passing | 1559 | * So we need to modify the skb header and hence need a copy of |
1563 | * us broadcast frames. */ | 1560 | * that. The head_need variable above doesn't, so far, include |
1561 | * the needed header space that we don't need right away. If we | ||
1562 | * can, then we don't reallocate right now but only after the | ||
1563 | * frame arrives at the master device (if it does...) | ||
1564 | * | ||
1565 | * If we cannot, however, then we will reallocate to include all | ||
1566 | * the ever needed space. Also, if we need to reallocate it anyway, | ||
1567 | * make it big enough for everything we may ever need. | ||
1568 | */ | ||
1564 | 1569 | ||
1565 | if (head_need > 0 || skb_header_cloned(skb)) { | 1570 | if (head_need > 0 || skb_header_cloned(skb)) { |
1566 | #if 0 | 1571 | head_need += IEEE80211_ENCRYPT_HEADROOM; |
1567 | printk(KERN_DEBUG "%s: need to reallocate buffer for %d bytes " | 1572 | head_need += local->tx_headroom; |
1568 | "of headroom\n", dev->name, head_need); | 1573 | head_need = max_t(int, 0, head_need); |
1569 | #endif | 1574 | if (ieee80211_skb_resize(local, skb, head_need, true)) |
1570 | |||
1571 | if (skb_header_cloned(skb)) | ||
1572 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | ||
1573 | else | ||
1574 | I802_DEBUG_INC(local->tx_expand_skb_head); | ||
1575 | /* Since we have to reallocate the buffer, make sure that there | ||
1576 | * is enough room for possible WEP IV/ICV and TKIP (8 bytes | ||
1577 | * before payload and 12 after). */ | ||
1578 | if (pskb_expand_head(skb, (head_need > 0 ? head_need + 8 : 8), | ||
1579 | 12, GFP_ATOMIC)) { | ||
1580 | printk(KERN_DEBUG "%s: failed to reallocate TX buffer" | ||
1581 | "\n", dev->name); | ||
1582 | goto fail; | 1575 | goto fail; |
1583 | } | ||
1584 | } | 1576 | } |
1585 | 1577 | ||
1586 | if (encaps_data) { | 1578 | if (encaps_data) { |
@@ -1611,11 +1603,14 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1611 | nh_pos += hdrlen; | 1603 | nh_pos += hdrlen; |
1612 | h_pos += hdrlen; | 1604 | h_pos += hdrlen; |
1613 | 1605 | ||
1614 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | 1606 | info = IEEE80211_SKB_CB(skb); |
1615 | memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); | 1607 | memset(info, 0, sizeof(*info)); |
1616 | pkt_data->ifindex = dev->ifindex; | 1608 | info->control.ifindex = dev->ifindex; |
1617 | if (ethertype == ETH_P_PAE) | 1609 | if (ethertype == ETH_P_PAE) |
1618 | pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME; | 1610 | info->flags |= IEEE80211_TX_CTL_EAPOL_FRAME; |
1611 | |||
1612 | /* Interfaces should always request a status report */ | ||
1613 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1619 | 1614 | ||
1620 | skb->dev = local->mdev; | 1615 | skb->dev = local->mdev; |
1621 | dev->stats.tx_packets++; | 1616 | dev->stats.tx_packets++; |
@@ -1640,46 +1635,55 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1640 | return ret; | 1635 | return ret; |
1641 | } | 1636 | } |
1642 | 1637 | ||
1643 | /* helper functions for pending packets for when queues are stopped */ | ||
1644 | 1638 | ||
1639 | /* | ||
1640 | * ieee80211_clear_tx_pending may not be called in a context where | ||
1641 | * it is possible that it packets could come in again. | ||
1642 | */ | ||
1645 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) | 1643 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) |
1646 | { | 1644 | { |
1647 | int i, j; | 1645 | int i, j; |
1648 | struct ieee80211_tx_stored_packet *store; | 1646 | struct ieee80211_tx_stored_packet *store; |
1649 | 1647 | ||
1650 | for (i = 0; i < local->hw.queues; i++) { | 1648 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1651 | if (!__ieee80211_queue_pending(local, i)) | 1649 | if (!test_bit(i, local->queues_pending)) |
1652 | continue; | 1650 | continue; |
1653 | store = &local->pending_packet[i]; | 1651 | store = &local->pending_packet[i]; |
1654 | kfree_skb(store->skb); | 1652 | kfree_skb(store->skb); |
1655 | for (j = 0; j < store->num_extra_frag; j++) | 1653 | for (j = 0; j < store->num_extra_frag; j++) |
1656 | kfree_skb(store->extra_frag[j]); | 1654 | kfree_skb(store->extra_frag[j]); |
1657 | kfree(store->extra_frag); | 1655 | kfree(store->extra_frag); |
1658 | clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]); | 1656 | clear_bit(i, local->queues_pending); |
1659 | } | 1657 | } |
1660 | } | 1658 | } |
1661 | 1659 | ||
1660 | /* | ||
1661 | * Transmit all pending packets. Called from tasklet, locks master device | ||
1662 | * TX lock so that no new packets can come in. | ||
1663 | */ | ||
1662 | void ieee80211_tx_pending(unsigned long data) | 1664 | void ieee80211_tx_pending(unsigned long data) |
1663 | { | 1665 | { |
1664 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1666 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1665 | struct net_device *dev = local->mdev; | 1667 | struct net_device *dev = local->mdev; |
1666 | struct ieee80211_tx_stored_packet *store; | 1668 | struct ieee80211_tx_stored_packet *store; |
1667 | struct ieee80211_tx_data tx; | 1669 | struct ieee80211_tx_data tx; |
1668 | int i, ret, reschedule = 0; | 1670 | int i, ret; |
1669 | 1671 | ||
1670 | netif_tx_lock_bh(dev); | 1672 | netif_tx_lock_bh(dev); |
1671 | for (i = 0; i < local->hw.queues; i++) { | 1673 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1672 | if (__ieee80211_queue_stopped(local, i)) | 1674 | /* Check that this queue is ok */ |
1675 | if (__netif_subqueue_stopped(local->mdev, i)) | ||
1673 | continue; | 1676 | continue; |
1674 | if (!__ieee80211_queue_pending(local, i)) { | 1677 | |
1675 | reschedule = 1; | 1678 | if (!test_bit(i, local->queues_pending)) { |
1679 | ieee80211_wake_queue(&local->hw, i); | ||
1676 | continue; | 1680 | continue; |
1677 | } | 1681 | } |
1682 | |||
1678 | store = &local->pending_packet[i]; | 1683 | store = &local->pending_packet[i]; |
1679 | tx.control = &store->control; | ||
1680 | tx.extra_frag = store->extra_frag; | 1684 | tx.extra_frag = store->extra_frag; |
1681 | tx.num_extra_frag = store->num_extra_frag; | 1685 | tx.num_extra_frag = store->num_extra_frag; |
1682 | tx.last_frag_rate = store->last_frag_rate; | 1686 | tx.last_frag_rate_idx = store->last_frag_rate_idx; |
1683 | tx.flags = 0; | 1687 | tx.flags = 0; |
1684 | if (store->last_frag_rate_ctrl_probe) | 1688 | if (store->last_frag_rate_ctrl_probe) |
1685 | tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG; | 1689 | tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG; |
@@ -1688,19 +1692,11 @@ void ieee80211_tx_pending(unsigned long data) | |||
1688 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1692 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1689 | store->skb = NULL; | 1693 | store->skb = NULL; |
1690 | } else { | 1694 | } else { |
1691 | clear_bit(IEEE80211_LINK_STATE_PENDING, | 1695 | clear_bit(i, local->queues_pending); |
1692 | &local->state[i]); | 1696 | ieee80211_wake_queue(&local->hw, i); |
1693 | reschedule = 1; | ||
1694 | } | 1697 | } |
1695 | } | 1698 | } |
1696 | netif_tx_unlock_bh(dev); | 1699 | netif_tx_unlock_bh(dev); |
1697 | if (reschedule) { | ||
1698 | if (!ieee80211_qdisc_installed(dev)) { | ||
1699 | if (!__ieee80211_queue_stopped(local, 0)) | ||
1700 | netif_wake_queue(dev); | ||
1701 | } else | ||
1702 | netif_schedule(dev); | ||
1703 | } | ||
1704 | } | 1700 | } |
1705 | 1701 | ||
1706 | /* functions for drivers to get certain frames */ | 1702 | /* functions for drivers to get certain frames */ |
@@ -1769,11 +1765,11 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local, | |||
1769 | } | 1765 | } |
1770 | 1766 | ||
1771 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | 1767 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, |
1772 | struct ieee80211_vif *vif, | 1768 | struct ieee80211_vif *vif) |
1773 | struct ieee80211_tx_control *control) | ||
1774 | { | 1769 | { |
1775 | struct ieee80211_local *local = hw_to_local(hw); | 1770 | struct ieee80211_local *local = hw_to_local(hw); |
1776 | struct sk_buff *skb; | 1771 | struct sk_buff *skb; |
1772 | struct ieee80211_tx_info *info; | ||
1777 | struct net_device *bdev; | 1773 | struct net_device *bdev; |
1778 | struct ieee80211_sub_if_data *sdata = NULL; | 1774 | struct ieee80211_sub_if_data *sdata = NULL; |
1779 | struct ieee80211_if_ap *ap = NULL; | 1775 | struct ieee80211_if_ap *ap = NULL; |
@@ -1783,9 +1779,10 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1783 | struct ieee80211_mgmt *mgmt; | 1779 | struct ieee80211_mgmt *mgmt; |
1784 | int *num_beacons; | 1780 | int *num_beacons; |
1785 | bool err = true; | 1781 | bool err = true; |
1782 | enum ieee80211_band band = local->hw.conf.channel->band; | ||
1786 | u8 *pos; | 1783 | u8 *pos; |
1787 | 1784 | ||
1788 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1785 | sband = local->hw.wiphy->bands[band]; |
1789 | 1786 | ||
1790 | rcu_read_lock(); | 1787 | rcu_read_lock(); |
1791 | 1788 | ||
@@ -1878,30 +1875,32 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1878 | goto out; | 1875 | goto out; |
1879 | } | 1876 | } |
1880 | 1877 | ||
1881 | if (control) { | 1878 | info = IEEE80211_SKB_CB(skb); |
1882 | rate_control_get_rate(local->mdev, sband, skb, &rsel); | ||
1883 | if (!rsel.rate) { | ||
1884 | if (net_ratelimit()) { | ||
1885 | printk(KERN_DEBUG "%s: ieee80211_beacon_get: " | ||
1886 | "no rate found\n", | ||
1887 | wiphy_name(local->hw.wiphy)); | ||
1888 | } | ||
1889 | dev_kfree_skb(skb); | ||
1890 | skb = NULL; | ||
1891 | goto out; | ||
1892 | } | ||
1893 | 1879 | ||
1894 | control->vif = vif; | 1880 | info->band = band; |
1895 | control->tx_rate = rsel.rate; | 1881 | rate_control_get_rate(local->mdev, sband, skb, &rsel); |
1896 | if (sdata->bss_conf.use_short_preamble && | 1882 | |
1897 | rsel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) | 1883 | if (unlikely(rsel.rate_idx < 0)) { |
1898 | control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; | 1884 | if (net_ratelimit()) { |
1899 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 1885 | printk(KERN_DEBUG "%s: ieee80211_beacon_get: " |
1900 | control->flags |= IEEE80211_TXCTL_NO_ACK; | 1886 | "no rate found\n", |
1901 | control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT; | 1887 | wiphy_name(local->hw.wiphy)); |
1902 | control->retry_limit = 1; | 1888 | } |
1903 | control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; | 1889 | dev_kfree_skb(skb); |
1890 | skb = NULL; | ||
1891 | goto out; | ||
1904 | } | 1892 | } |
1893 | |||
1894 | info->control.vif = vif; | ||
1895 | info->tx_rate_idx = rsel.rate_idx; | ||
1896 | if (sdata->bss_conf.use_short_preamble && | ||
1897 | sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) | ||
1898 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | ||
1899 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
1900 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1901 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
1902 | info->control.retry_limit = 1; | ||
1903 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1905 | (*num_beacons)++; | 1904 | (*num_beacons)++; |
1906 | out: | 1905 | out: |
1907 | rcu_read_unlock(); | 1906 | rcu_read_unlock(); |
@@ -1911,7 +1910,7 @@ EXPORT_SYMBOL(ieee80211_beacon_get); | |||
1911 | 1910 | ||
1912 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1911 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1913 | const void *frame, size_t frame_len, | 1912 | const void *frame, size_t frame_len, |
1914 | const struct ieee80211_tx_control *frame_txctl, | 1913 | const struct ieee80211_tx_info *frame_txctl, |
1915 | struct ieee80211_rts *rts) | 1914 | struct ieee80211_rts *rts) |
1916 | { | 1915 | { |
1917 | const struct ieee80211_hdr *hdr = frame; | 1916 | const struct ieee80211_hdr *hdr = frame; |
@@ -1928,7 +1927,7 @@ EXPORT_SYMBOL(ieee80211_rts_get); | |||
1928 | 1927 | ||
1929 | void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1928 | void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1930 | const void *frame, size_t frame_len, | 1929 | const void *frame, size_t frame_len, |
1931 | const struct ieee80211_tx_control *frame_txctl, | 1930 | const struct ieee80211_tx_info *frame_txctl, |
1932 | struct ieee80211_cts *cts) | 1931 | struct ieee80211_cts *cts) |
1933 | { | 1932 | { |
1934 | const struct ieee80211_hdr *hdr = frame; | 1933 | const struct ieee80211_hdr *hdr = frame; |
@@ -1944,11 +1943,10 @@ EXPORT_SYMBOL(ieee80211_ctstoself_get); | |||
1944 | 1943 | ||
1945 | struct sk_buff * | 1944 | struct sk_buff * |
1946 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | 1945 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, |
1947 | struct ieee80211_vif *vif, | 1946 | struct ieee80211_vif *vif) |
1948 | struct ieee80211_tx_control *control) | ||
1949 | { | 1947 | { |
1950 | struct ieee80211_local *local = hw_to_local(hw); | 1948 | struct ieee80211_local *local = hw_to_local(hw); |
1951 | struct sk_buff *skb; | 1949 | struct sk_buff *skb = NULL; |
1952 | struct sta_info *sta; | 1950 | struct sta_info *sta; |
1953 | ieee80211_tx_handler *handler; | 1951 | ieee80211_tx_handler *handler; |
1954 | struct ieee80211_tx_data tx; | 1952 | struct ieee80211_tx_data tx; |
@@ -1957,10 +1955,11 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
1957 | struct ieee80211_sub_if_data *sdata; | 1955 | struct ieee80211_sub_if_data *sdata; |
1958 | struct ieee80211_if_ap *bss = NULL; | 1956 | struct ieee80211_if_ap *bss = NULL; |
1959 | struct beacon_data *beacon; | 1957 | struct beacon_data *beacon; |
1958 | struct ieee80211_tx_info *info; | ||
1960 | 1959 | ||
1961 | sdata = vif_to_sdata(vif); | 1960 | sdata = vif_to_sdata(vif); |
1962 | bdev = sdata->dev; | 1961 | bdev = sdata->dev; |
1963 | 1962 | bss = &sdata->u.ap; | |
1964 | 1963 | ||
1965 | if (!bss) | 1964 | if (!bss) |
1966 | return NULL; | 1965 | return NULL; |
@@ -1968,19 +1967,16 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
1968 | rcu_read_lock(); | 1967 | rcu_read_lock(); |
1969 | beacon = rcu_dereference(bss->beacon); | 1968 | beacon = rcu_dereference(bss->beacon); |
1970 | 1969 | ||
1971 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon || | 1970 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon || !beacon->head) |
1972 | !beacon->head) { | 1971 | goto out; |
1973 | rcu_read_unlock(); | ||
1974 | return NULL; | ||
1975 | } | ||
1976 | 1972 | ||
1977 | if (bss->dtim_count != 0) | 1973 | if (bss->dtim_count != 0) |
1978 | return NULL; /* send buffered bc/mc only after DTIM beacon */ | 1974 | goto out; /* send buffered bc/mc only after DTIM beacon */ |
1979 | memset(control, 0, sizeof(*control)); | 1975 | |
1980 | while (1) { | 1976 | while (1) { |
1981 | skb = skb_dequeue(&bss->ps_bc_buf); | 1977 | skb = skb_dequeue(&bss->ps_bc_buf); |
1982 | if (!skb) | 1978 | if (!skb) |
1983 | return NULL; | 1979 | goto out; |
1984 | local->total_ps_buffered--; | 1980 | local->total_ps_buffered--; |
1985 | 1981 | ||
1986 | if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) { | 1982 | if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) { |
@@ -1993,20 +1989,26 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
1993 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1989 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
1994 | } | 1990 | } |
1995 | 1991 | ||
1996 | if (!ieee80211_tx_prepare(&tx, skb, local->mdev, control)) | 1992 | if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) |
1997 | break; | 1993 | break; |
1998 | dev_kfree_skb_any(skb); | 1994 | dev_kfree_skb_any(skb); |
1999 | } | 1995 | } |
1996 | |||
1997 | info = IEEE80211_SKB_CB(skb); | ||
1998 | |||
2000 | sta = tx.sta; | 1999 | sta = tx.sta; |
2001 | tx.flags |= IEEE80211_TX_PS_BUFFERED; | 2000 | tx.flags |= IEEE80211_TX_PS_BUFFERED; |
2002 | tx.channel = local->hw.conf.channel; | 2001 | tx.channel = local->hw.conf.channel; |
2002 | info->band = tx.channel->band; | ||
2003 | 2003 | ||
2004 | for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { | 2004 | for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { |
2005 | res = (*handler)(&tx); | 2005 | res = (*handler)(&tx); |
2006 | if (res == TX_DROP || res == TX_QUEUED) | 2006 | if (res == TX_DROP || res == TX_QUEUED) |
2007 | break; | 2007 | break; |
2008 | } | 2008 | } |
2009 | skb = tx.skb; /* handlers are allowed to change skb */ | 2009 | |
2010 | if (WARN_ON(tx.skb != skb)) | ||
2011 | res = TX_DROP; | ||
2010 | 2012 | ||
2011 | if (res == TX_DROP) { | 2013 | if (res == TX_DROP) { |
2012 | I802_DEBUG_INC(local->tx_handlers_drop); | 2014 | I802_DEBUG_INC(local->tx_handlers_drop); |
@@ -2017,6 +2019,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2017 | skb = NULL; | 2019 | skb = NULL; |
2018 | } | 2020 | } |
2019 | 2021 | ||
2022 | out: | ||
2020 | rcu_read_unlock(); | 2023 | rcu_read_unlock(); |
2021 | 2024 | ||
2022 | return skb; | 2025 | return skb; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 4e97b266f907..6513bc2d2707 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -258,7 +258,7 @@ EXPORT_SYMBOL(ieee80211_generic_frame_duration); | |||
258 | 258 | ||
259 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | 259 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, |
260 | struct ieee80211_vif *vif, size_t frame_len, | 260 | struct ieee80211_vif *vif, size_t frame_len, |
261 | const struct ieee80211_tx_control *frame_txctl) | 261 | const struct ieee80211_tx_info *frame_txctl) |
262 | { | 262 | { |
263 | struct ieee80211_local *local = hw_to_local(hw); | 263 | struct ieee80211_local *local = hw_to_local(hw); |
264 | struct ieee80211_rate *rate; | 264 | struct ieee80211_rate *rate; |
@@ -266,10 +266,13 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
266 | bool short_preamble; | 266 | bool short_preamble; |
267 | int erp; | 267 | int erp; |
268 | u16 dur; | 268 | u16 dur; |
269 | struct ieee80211_supported_band *sband; | ||
270 | |||
271 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
269 | 272 | ||
270 | short_preamble = sdata->bss_conf.use_short_preamble; | 273 | short_preamble = sdata->bss_conf.use_short_preamble; |
271 | 274 | ||
272 | rate = frame_txctl->rts_cts_rate; | 275 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
273 | 276 | ||
274 | erp = 0; | 277 | erp = 0; |
275 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 278 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
@@ -292,7 +295,7 @@ EXPORT_SYMBOL(ieee80211_rts_duration); | |||
292 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | 295 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, |
293 | struct ieee80211_vif *vif, | 296 | struct ieee80211_vif *vif, |
294 | size_t frame_len, | 297 | size_t frame_len, |
295 | const struct ieee80211_tx_control *frame_txctl) | 298 | const struct ieee80211_tx_info *frame_txctl) |
296 | { | 299 | { |
297 | struct ieee80211_local *local = hw_to_local(hw); | 300 | struct ieee80211_local *local = hw_to_local(hw); |
298 | struct ieee80211_rate *rate; | 301 | struct ieee80211_rate *rate; |
@@ -300,10 +303,13 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
300 | bool short_preamble; | 303 | bool short_preamble; |
301 | int erp; | 304 | int erp; |
302 | u16 dur; | 305 | u16 dur; |
306 | struct ieee80211_supported_band *sband; | ||
307 | |||
308 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
303 | 309 | ||
304 | short_preamble = sdata->bss_conf.use_short_preamble; | 310 | short_preamble = sdata->bss_conf.use_short_preamble; |
305 | 311 | ||
306 | rate = frame_txctl->rts_cts_rate; | 312 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
307 | erp = 0; | 313 | erp = 0; |
308 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 314 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
309 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 315 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
@@ -311,7 +317,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
311 | /* Data frame duration */ | 317 | /* Data frame duration */ |
312 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, | 318 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, |
313 | erp, short_preamble); | 319 | erp, short_preamble); |
314 | if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) { | 320 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { |
315 | /* ACK duration */ | 321 | /* ACK duration */ |
316 | dur += ieee80211_frame_duration(local, 10, rate->bitrate, | 322 | dur += ieee80211_frame_duration(local, 10, rate->bitrate, |
317 | erp, short_preamble); | 323 | erp, short_preamble); |
@@ -325,17 +331,15 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | |||
325 | { | 331 | { |
326 | struct ieee80211_local *local = hw_to_local(hw); | 332 | struct ieee80211_local *local = hw_to_local(hw); |
327 | 333 | ||
328 | if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF, | 334 | if (test_bit(queue, local->queues_pending)) { |
329 | &local->state[queue])) { | 335 | tasklet_schedule(&local->tx_pending_tasklet); |
330 | if (test_bit(IEEE80211_LINK_STATE_PENDING, | 336 | } else { |
331 | &local->state[queue])) | 337 | if (ieee80211_is_multiqueue(local)) { |
332 | tasklet_schedule(&local->tx_pending_tasklet); | 338 | netif_wake_subqueue(local->mdev, queue); |
333 | else | 339 | } else { |
334 | if (!ieee80211_qdisc_installed(local->mdev)) { | 340 | WARN_ON(queue != 0); |
335 | if (queue == 0) | 341 | netif_wake_queue(local->mdev); |
336 | netif_wake_queue(local->mdev); | 342 | } |
337 | } else | ||
338 | __netif_schedule(local->mdev); | ||
339 | } | 343 | } |
340 | } | 344 | } |
341 | EXPORT_SYMBOL(ieee80211_wake_queue); | 345 | EXPORT_SYMBOL(ieee80211_wake_queue); |
@@ -344,29 +348,20 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | |||
344 | { | 348 | { |
345 | struct ieee80211_local *local = hw_to_local(hw); | 349 | struct ieee80211_local *local = hw_to_local(hw); |
346 | 350 | ||
347 | if (!ieee80211_qdisc_installed(local->mdev) && queue == 0) | 351 | if (ieee80211_is_multiqueue(local)) { |
352 | netif_stop_subqueue(local->mdev, queue); | ||
353 | } else { | ||
354 | WARN_ON(queue != 0); | ||
348 | netif_stop_queue(local->mdev); | 355 | netif_stop_queue(local->mdev); |
349 | set_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]); | 356 | } |
350 | } | 357 | } |
351 | EXPORT_SYMBOL(ieee80211_stop_queue); | 358 | EXPORT_SYMBOL(ieee80211_stop_queue); |
352 | 359 | ||
353 | void ieee80211_start_queues(struct ieee80211_hw *hw) | ||
354 | { | ||
355 | struct ieee80211_local *local = hw_to_local(hw); | ||
356 | int i; | ||
357 | |||
358 | for (i = 0; i < local->hw.queues; i++) | ||
359 | clear_bit(IEEE80211_LINK_STATE_XOFF, &local->state[i]); | ||
360 | if (!ieee80211_qdisc_installed(local->mdev)) | ||
361 | netif_start_queue(local->mdev); | ||
362 | } | ||
363 | EXPORT_SYMBOL(ieee80211_start_queues); | ||
364 | |||
365 | void ieee80211_stop_queues(struct ieee80211_hw *hw) | 360 | void ieee80211_stop_queues(struct ieee80211_hw *hw) |
366 | { | 361 | { |
367 | int i; | 362 | int i; |
368 | 363 | ||
369 | for (i = 0; i < hw->queues; i++) | 364 | for (i = 0; i < ieee80211_num_queues(hw); i++) |
370 | ieee80211_stop_queue(hw, i); | 365 | ieee80211_stop_queue(hw, i); |
371 | } | 366 | } |
372 | EXPORT_SYMBOL(ieee80211_stop_queues); | 367 | EXPORT_SYMBOL(ieee80211_stop_queues); |
@@ -375,7 +370,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw) | |||
375 | { | 370 | { |
376 | int i; | 371 | int i; |
377 | 372 | ||
378 | for (i = 0; i < hw->queues; i++) | 373 | for (i = 0; i < hw->queues + hw->ampdu_queues; i++) |
379 | ieee80211_wake_queue(hw, i); | 374 | ieee80211_wake_queue(hw, i); |
380 | } | 375 | } |
381 | EXPORT_SYMBOL(ieee80211_wake_queues); | 376 | EXPORT_SYMBOL(ieee80211_wake_queues); |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index affcecd78c10..e7b6344c900a 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -93,13 +93,9 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, | |||
93 | fc |= IEEE80211_FCTL_PROTECTED; | 93 | fc |= IEEE80211_FCTL_PROTECTED; |
94 | hdr->frame_control = cpu_to_le16(fc); | 94 | hdr->frame_control = cpu_to_le16(fc); |
95 | 95 | ||
96 | if ((skb_headroom(skb) < WEP_IV_LEN || | 96 | if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || |
97 | skb_tailroom(skb) < WEP_ICV_LEN)) { | 97 | skb_headroom(skb) < WEP_IV_LEN)) |
98 | I802_DEBUG_INC(local->tx_expand_skb_head); | 98 | return NULL; |
99 | if (unlikely(pskb_expand_head(skb, WEP_IV_LEN, WEP_ICV_LEN, | ||
100 | GFP_ATOMIC))) | ||
101 | return NULL; | ||
102 | } | ||
103 | 99 | ||
104 | hdrlen = ieee80211_get_hdrlen(fc); | 100 | hdrlen = ieee80211_get_hdrlen(fc); |
105 | newhdr = skb_push(skb, WEP_IV_LEN); | 101 | newhdr = skb_push(skb, WEP_IV_LEN); |
@@ -333,11 +329,16 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | |||
333 | 329 | ||
334 | static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | 330 | static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
335 | { | 331 | { |
332 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
333 | |||
334 | info->control.iv_len = WEP_IV_LEN; | ||
335 | info->control.icv_len = WEP_ICV_LEN; | ||
336 | |||
336 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { | 337 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
337 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) | 338 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) |
338 | return -1; | 339 | return -1; |
339 | } else { | 340 | } else { |
340 | tx->control->key_idx = tx->key->conf.hw_key_idx; | 341 | info->control.hw_key = &tx->key->conf; |
341 | if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) { | 342 | if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) { |
342 | if (!ieee80211_wep_add_iv(tx->local, skb, tx->key)) | 343 | if (!ieee80211_wep_add_iv(tx->local, skb, tx->key)) |
343 | return -1; | 344 | return -1; |
@@ -349,8 +350,6 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
349 | ieee80211_tx_result | 350 | ieee80211_tx_result |
350 | ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx) | 351 | ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx) |
351 | { | 352 | { |
352 | tx->control->iv_len = WEP_IV_LEN; | ||
353 | tx->control->icv_len = WEP_ICV_LEN; | ||
354 | ieee80211_tx_set_protected(tx); | 353 | ieee80211_tx_set_protected(tx); |
355 | 354 | ||
356 | if (wep_encrypt_skb(tx, tx->skb) < 0) { | 355 | if (wep_encrypt_skb(tx, tx->skb) < 0) { |
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h index 363779c50658..e587172115b8 100644 --- a/net/mac80211/wep.h +++ b/net/mac80211/wep.h | |||
@@ -26,7 +26,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, | |||
26 | struct ieee80211_key *key); | 26 | struct ieee80211_key *key); |
27 | int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, | 27 | int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, |
28 | struct ieee80211_key *key); | 28 | struct ieee80211_key *key); |
29 | u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); | 29 | u8 *ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); |
30 | 30 | ||
31 | ieee80211_rx_result | 31 | ieee80211_rx_result |
32 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx); | 32 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx); |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index a8bb8e31b1ec..4806d96b9877 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -169,14 +169,26 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
169 | range->num_encoding_sizes = 2; | 169 | range->num_encoding_sizes = 2; |
170 | range->max_encoding_tokens = NUM_DEFAULT_KEYS; | 170 | range->max_encoding_tokens = NUM_DEFAULT_KEYS; |
171 | 171 | ||
172 | range->max_qual.qual = local->hw.max_signal; | 172 | if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC || |
173 | range->max_qual.level = local->hw.max_rssi; | 173 | local->hw.flags & IEEE80211_HW_SIGNAL_DB) |
174 | range->max_qual.noise = local->hw.max_noise; | 174 | range->max_qual.level = local->hw.max_signal; |
175 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
176 | range->max_qual.level = -110; | ||
177 | else | ||
178 | range->max_qual.level = 0; | ||
179 | |||
180 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | ||
181 | range->max_qual.noise = -110; | ||
182 | else | ||
183 | range->max_qual.noise = 0; | ||
184 | |||
185 | range->max_qual.qual = 100; | ||
175 | range->max_qual.updated = local->wstats_flags; | 186 | range->max_qual.updated = local->wstats_flags; |
176 | 187 | ||
177 | range->avg_qual.qual = local->hw.max_signal/2; | 188 | range->avg_qual.qual = 50; |
178 | range->avg_qual.level = 0; | 189 | /* not always true but better than nothing */ |
179 | range->avg_qual.noise = 0; | 190 | range->avg_qual.level = range->max_qual.level / 2; |
191 | range->avg_qual.noise = range->max_qual.noise / 2; | ||
180 | range->avg_qual.updated = local->wstats_flags; | 192 | range->avg_qual.updated = local->wstats_flags; |
181 | 193 | ||
182 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | 194 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | |
@@ -1007,8 +1019,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev | |||
1007 | wstats->qual.noise = 0; | 1019 | wstats->qual.noise = 0; |
1008 | wstats->qual.updated = IW_QUAL_ALL_INVALID; | 1020 | wstats->qual.updated = IW_QUAL_ALL_INVALID; |
1009 | } else { | 1021 | } else { |
1010 | wstats->qual.level = sta->last_rssi; | 1022 | wstats->qual.level = sta->last_signal; |
1011 | wstats->qual.qual = sta->last_signal; | 1023 | wstats->qual.qual = sta->last_qual; |
1012 | wstats->qual.noise = sta->last_noise; | 1024 | wstats->qual.noise = sta->last_noise; |
1013 | wstats->qual.updated = local->wstats_flags; | 1025 | wstats->qual.updated = local->wstats_flags; |
1014 | } | 1026 | } |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index dc1598b86004..14a9ff10a1e9 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -19,16 +19,22 @@ | |||
19 | #include "wme.h" | 19 | #include "wme.h" |
20 | 20 | ||
21 | /* maximum number of hardware queues we support. */ | 21 | /* maximum number of hardware queues we support. */ |
22 | #define TC_80211_MAX_QUEUES 16 | 22 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) |
23 | /* current number of hardware queues we support. */ | ||
24 | #define QD_NUM(hw) ((hw)->queues + (hw)->ampdu_queues) | ||
23 | 25 | ||
26 | /* | ||
27 | * Default mapping in classifier to work with default | ||
28 | * queue setup. | ||
29 | */ | ||
24 | const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; | 30 | const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; |
25 | 31 | ||
26 | struct ieee80211_sched_data | 32 | struct ieee80211_sched_data |
27 | { | 33 | { |
28 | unsigned long qdisc_pool[BITS_TO_LONGS(TC_80211_MAX_QUEUES)]; | 34 | unsigned long qdisc_pool[BITS_TO_LONGS(QD_MAX_QUEUES)]; |
29 | struct tcf_proto *filter_list; | 35 | struct tcf_proto *filter_list; |
30 | struct Qdisc *queues[TC_80211_MAX_QUEUES]; | 36 | struct Qdisc *queues[QD_MAX_QUEUES]; |
31 | struct sk_buff_head requeued[TC_80211_MAX_QUEUES]; | 37 | struct sk_buff_head requeued[QD_MAX_QUEUES]; |
32 | }; | 38 | }; |
33 | 39 | ||
34 | static const char llc_ip_hdr[8] = {0xAA, 0xAA, 0x3, 0, 0, 0, 0x08, 0}; | 40 | static const char llc_ip_hdr[8] = {0xAA, 0xAA, 0x3, 0, 0, 0, 0x08, 0}; |
@@ -95,7 +101,7 @@ static inline int wme_downgrade_ac(struct sk_buff *skb) | |||
95 | 101 | ||
96 | /* positive return value indicates which queue to use | 102 | /* positive return value indicates which queue to use |
97 | * negative return value indicates to drop the frame */ | 103 | * negative return value indicates to drop the frame */ |
98 | static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd) | 104 | static int classify80211(struct sk_buff *skb, struct Qdisc *qd) |
99 | { | 105 | { |
100 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); | 106 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); |
101 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 107 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -106,7 +112,7 @@ static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd) | |||
106 | if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) { | 112 | if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) { |
107 | /* management frames go on AC_VO queue, but are sent | 113 | /* management frames go on AC_VO queue, but are sent |
108 | * without QoS control fields */ | 114 | * without QoS control fields */ |
109 | return IEEE80211_TX_QUEUE_DATA0; | 115 | return 0; |
110 | } | 116 | } |
111 | 117 | ||
112 | if (0 /* injected */) { | 118 | if (0 /* injected */) { |
@@ -141,29 +147,29 @@ static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd) | |||
141 | static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | 147 | static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) |
142 | { | 148 | { |
143 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); | 149 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); |
150 | struct ieee80211_hw *hw = &local->hw; | ||
144 | struct ieee80211_sched_data *q = qdisc_priv(qd); | 151 | struct ieee80211_sched_data *q = qdisc_priv(qd); |
145 | struct ieee80211_tx_packet_data *pkt_data = | 152 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
146 | (struct ieee80211_tx_packet_data *) skb->cb; | ||
147 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 153 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
148 | unsigned short fc = le16_to_cpu(hdr->frame_control); | 154 | unsigned short fc = le16_to_cpu(hdr->frame_control); |
149 | struct Qdisc *qdisc; | 155 | struct Qdisc *qdisc; |
150 | int err, queue; | ||
151 | struct sta_info *sta; | 156 | struct sta_info *sta; |
157 | int err, queue; | ||
152 | u8 tid; | 158 | u8 tid; |
153 | 159 | ||
154 | if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) { | 160 | if (info->flags & IEEE80211_TX_CTL_REQUEUE) { |
155 | queue = pkt_data->queue; | 161 | queue = skb_get_queue_mapping(skb); |
156 | rcu_read_lock(); | 162 | rcu_read_lock(); |
157 | sta = sta_info_get(local, hdr->addr1); | 163 | sta = sta_info_get(local, hdr->addr1); |
158 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | 164 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; |
159 | if (sta) { | 165 | if (sta) { |
160 | int ampdu_queue = sta->tid_to_tx_q[tid]; | 166 | int ampdu_queue = sta->tid_to_tx_q[tid]; |
161 | if ((ampdu_queue < local->hw.queues) && | 167 | if ((ampdu_queue < QD_NUM(hw)) && |
162 | test_bit(ampdu_queue, q->qdisc_pool)) { | 168 | test_bit(ampdu_queue, q->qdisc_pool)) { |
163 | queue = ampdu_queue; | 169 | queue = ampdu_queue; |
164 | pkt_data->flags |= IEEE80211_TXPD_AMPDU; | 170 | info->flags |= IEEE80211_TX_CTL_AMPDU; |
165 | } else { | 171 | } else { |
166 | pkt_data->flags &= ~IEEE80211_TXPD_AMPDU; | 172 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
167 | } | 173 | } |
168 | } | 174 | } |
169 | rcu_read_unlock(); | 175 | rcu_read_unlock(); |
@@ -174,6 +180,9 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
174 | 180 | ||
175 | queue = classify80211(skb, qd); | 181 | queue = classify80211(skb, qd); |
176 | 182 | ||
183 | if (unlikely(queue >= local->hw.queues)) | ||
184 | queue = local->hw.queues - 1; | ||
185 | |||
177 | /* now we know the 1d priority, fill in the QoS header if there is one | 186 | /* now we know the 1d priority, fill in the QoS header if there is one |
178 | */ | 187 | */ |
179 | if (WLAN_FC_IS_QOS_DATA(fc)) { | 188 | if (WLAN_FC_IS_QOS_DATA(fc)) { |
@@ -193,35 +202,24 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
193 | sta = sta_info_get(local, hdr->addr1); | 202 | sta = sta_info_get(local, hdr->addr1); |
194 | if (sta) { | 203 | if (sta) { |
195 | int ampdu_queue = sta->tid_to_tx_q[tid]; | 204 | int ampdu_queue = sta->tid_to_tx_q[tid]; |
196 | if ((ampdu_queue < local->hw.queues) && | 205 | if ((ampdu_queue < QD_NUM(hw)) && |
197 | test_bit(ampdu_queue, q->qdisc_pool)) { | 206 | test_bit(ampdu_queue, q->qdisc_pool)) { |
198 | queue = ampdu_queue; | 207 | queue = ampdu_queue; |
199 | pkt_data->flags |= IEEE80211_TXPD_AMPDU; | 208 | info->flags |= IEEE80211_TX_CTL_AMPDU; |
200 | } else { | 209 | } else { |
201 | pkt_data->flags &= ~IEEE80211_TXPD_AMPDU; | 210 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
202 | } | 211 | } |
203 | } | 212 | } |
204 | 213 | ||
205 | rcu_read_unlock(); | 214 | rcu_read_unlock(); |
206 | } | 215 | } |
207 | 216 | ||
208 | if (unlikely(queue >= local->hw.queues)) { | ||
209 | #if 0 | ||
210 | if (net_ratelimit()) { | ||
211 | printk(KERN_DEBUG "%s - queue=%d (hw does not " | ||
212 | "support) -> %d\n", | ||
213 | __func__, queue, local->hw.queues - 1); | ||
214 | } | ||
215 | #endif | ||
216 | queue = local->hw.queues - 1; | ||
217 | } | ||
218 | |||
219 | if (unlikely(queue < 0)) { | 217 | if (unlikely(queue < 0)) { |
220 | kfree_skb(skb); | 218 | kfree_skb(skb); |
221 | err = NET_XMIT_DROP; | 219 | err = NET_XMIT_DROP; |
222 | } else { | 220 | } else { |
223 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | 221 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; |
224 | pkt_data->queue = (unsigned int) queue; | 222 | skb_set_queue_mapping(skb, queue); |
225 | qdisc = q->queues[queue]; | 223 | qdisc = q->queues[queue]; |
226 | err = qdisc->enqueue(skb, qdisc); | 224 | err = qdisc->enqueue(skb, qdisc); |
227 | if (err == NET_XMIT_SUCCESS) { | 225 | if (err == NET_XMIT_SUCCESS) { |
@@ -242,13 +240,11 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
242 | static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) | 240 | static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) |
243 | { | 241 | { |
244 | struct ieee80211_sched_data *q = qdisc_priv(qd); | 242 | struct ieee80211_sched_data *q = qdisc_priv(qd); |
245 | struct ieee80211_tx_packet_data *pkt_data = | ||
246 | (struct ieee80211_tx_packet_data *) skb->cb; | ||
247 | struct Qdisc *qdisc; | 243 | struct Qdisc *qdisc; |
248 | int err; | 244 | int err; |
249 | 245 | ||
250 | /* we recorded which queue to use earlier! */ | 246 | /* we recorded which queue to use earlier! */ |
251 | qdisc = q->queues[pkt_data->queue]; | 247 | qdisc = q->queues[skb_get_queue_mapping(skb)]; |
252 | 248 | ||
253 | if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) { | 249 | if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) { |
254 | qd->q.qlen++; | 250 | qd->q.qlen++; |
@@ -270,13 +266,10 @@ static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd) | |||
270 | int queue; | 266 | int queue; |
271 | 267 | ||
272 | /* check all the h/w queues in numeric/priority order */ | 268 | /* check all the h/w queues in numeric/priority order */ |
273 | for (queue = 0; queue < hw->queues; queue++) { | 269 | for (queue = 0; queue < QD_NUM(hw); queue++) { |
274 | /* see if there is room in this hardware queue */ | 270 | /* see if there is room in this hardware queue */ |
275 | if ((test_bit(IEEE80211_LINK_STATE_XOFF, | 271 | if (__netif_subqueue_stopped(local->mdev, queue) || |
276 | &local->state[queue])) || | 272 | !test_bit(queue, q->qdisc_pool)) |
277 | (test_bit(IEEE80211_LINK_STATE_PENDING, | ||
278 | &local->state[queue])) || | ||
279 | (!test_bit(queue, q->qdisc_pool))) | ||
280 | continue; | 273 | continue; |
281 | 274 | ||
282 | /* there is space - try and get a frame */ | 275 | /* there is space - try and get a frame */ |
@@ -308,7 +301,7 @@ static void wme_qdiscop_reset(struct Qdisc* qd) | |||
308 | 301 | ||
309 | /* QUESTION: should we have some hardware flush functionality here? */ | 302 | /* QUESTION: should we have some hardware flush functionality here? */ |
310 | 303 | ||
311 | for (queue = 0; queue < hw->queues; queue++) { | 304 | for (queue = 0; queue < QD_NUM(hw); queue++) { |
312 | skb_queue_purge(&q->requeued[queue]); | 305 | skb_queue_purge(&q->requeued[queue]); |
313 | qdisc_reset(q->queues[queue]); | 306 | qdisc_reset(q->queues[queue]); |
314 | } | 307 | } |
@@ -326,7 +319,7 @@ static void wme_qdiscop_destroy(struct Qdisc* qd) | |||
326 | tcf_destroy_chain(q->filter_list); | 319 | tcf_destroy_chain(q->filter_list); |
327 | q->filter_list = NULL; | 320 | q->filter_list = NULL; |
328 | 321 | ||
329 | for (queue=0; queue < hw->queues; queue++) { | 322 | for (queue = 0; queue < QD_NUM(hw); queue++) { |
330 | skb_queue_purge(&q->requeued[queue]); | 323 | skb_queue_purge(&q->requeued[queue]); |
331 | qdisc_destroy(q->queues[queue]); | 324 | qdisc_destroy(q->queues[queue]); |
332 | q->queues[queue] = &noop_qdisc; | 325 | q->queues[queue] = &noop_qdisc; |
@@ -337,17 +330,6 @@ static void wme_qdiscop_destroy(struct Qdisc* qd) | |||
337 | /* called whenever parameters are updated on existing qdisc */ | 330 | /* called whenever parameters are updated on existing qdisc */ |
338 | static int wme_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt) | 331 | static int wme_qdiscop_tune(struct Qdisc *qd, struct nlattr *opt) |
339 | { | 332 | { |
340 | /* struct ieee80211_sched_data *q = qdisc_priv(qd); | ||
341 | */ | ||
342 | /* check our options block is the right size */ | ||
343 | /* copy any options to our local structure */ | ||
344 | /* Ignore options block for now - always use static mapping | ||
345 | struct tc_ieee80211_qopt *qopt = nla_data(opt); | ||
346 | |||
347 | if (opt->nla_len < nla_attr_size(sizeof(*qopt))) | ||
348 | return -EINVAL; | ||
349 | memcpy(q->tag2queue, qopt->tag2queue, sizeof(qopt->tag2queue)); | ||
350 | */ | ||
351 | return 0; | 333 | return 0; |
352 | } | 334 | } |
353 | 335 | ||
@@ -358,7 +340,7 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) | |||
358 | struct ieee80211_sched_data *q = qdisc_priv(qd); | 340 | struct ieee80211_sched_data *q = qdisc_priv(qd); |
359 | struct net_device *dev = qd->dev; | 341 | struct net_device *dev = qd->dev; |
360 | struct ieee80211_local *local; | 342 | struct ieee80211_local *local; |
361 | int queues; | 343 | struct ieee80211_hw *hw; |
362 | int err = 0, i; | 344 | int err = 0, i; |
363 | 345 | ||
364 | /* check that device is a mac80211 device */ | 346 | /* check that device is a mac80211 device */ |
@@ -366,29 +348,26 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) | |||
366 | dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | 348 | dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) |
367 | return -EINVAL; | 349 | return -EINVAL; |
368 | 350 | ||
369 | /* check this device is an ieee80211 master type device */ | 351 | local = wdev_priv(dev->ieee80211_ptr); |
370 | if (dev->type != ARPHRD_IEEE80211) | 352 | hw = &local->hw; |
353 | |||
354 | /* only allow on master dev */ | ||
355 | if (dev != local->mdev) | ||
371 | return -EINVAL; | 356 | return -EINVAL; |
372 | 357 | ||
373 | /* check that there is no qdisc currently attached to device | 358 | /* ensure that we are root qdisc */ |
374 | * this ensures that we will be the root qdisc. (I can't find a better | 359 | if (qd->parent != TC_H_ROOT) |
375 | * way to test this explicitly) */ | ||
376 | if (dev->qdisc_sleeping != &noop_qdisc) | ||
377 | return -EINVAL; | 360 | return -EINVAL; |
378 | 361 | ||
379 | if (qd->flags & TCQ_F_INGRESS) | 362 | if (qd->flags & TCQ_F_INGRESS) |
380 | return -EINVAL; | 363 | return -EINVAL; |
381 | 364 | ||
382 | local = wdev_priv(dev->ieee80211_ptr); | ||
383 | queues = local->hw.queues; | ||
384 | |||
385 | /* if options were passed in, set them */ | 365 | /* if options were passed in, set them */ |
386 | if (opt) { | 366 | if (opt) |
387 | err = wme_qdiscop_tune(qd, opt); | 367 | err = wme_qdiscop_tune(qd, opt); |
388 | } | ||
389 | 368 | ||
390 | /* create child queues */ | 369 | /* create child queues */ |
391 | for (i = 0; i < queues; i++) { | 370 | for (i = 0; i < QD_NUM(hw); i++) { |
392 | skb_queue_head_init(&q->requeued[i]); | 371 | skb_queue_head_init(&q->requeued[i]); |
393 | q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops, | 372 | q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops, |
394 | qd->handle); | 373 | qd->handle); |
@@ -399,8 +378,8 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) | |||
399 | } | 378 | } |
400 | } | 379 | } |
401 | 380 | ||
402 | /* reserve all legacy QoS queues */ | 381 | /* non-aggregation queues: reserve/mark as used */ |
403 | for (i = 0; i < min(IEEE80211_TX_QUEUE_DATA4, queues); i++) | 382 | for (i = 0; i < local->hw.queues; i++) |
404 | set_bit(i, q->qdisc_pool); | 383 | set_bit(i, q->qdisc_pool); |
405 | 384 | ||
406 | return err; | 385 | return err; |
@@ -408,16 +387,6 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) | |||
408 | 387 | ||
409 | static int wme_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb) | 388 | static int wme_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb) |
410 | { | 389 | { |
411 | /* struct ieee80211_sched_data *q = qdisc_priv(qd); | ||
412 | unsigned char *p = skb->tail; | ||
413 | struct tc_ieee80211_qopt opt; | ||
414 | |||
415 | memcpy(&opt.tag2queue, q->tag2queue, TC_80211_MAX_TAG + 1); | ||
416 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | ||
417 | */ return skb->len; | ||
418 | /* | ||
419 | nla_put_failure: | ||
420 | skb_trim(skb, p - skb->data);*/ | ||
421 | return -1; | 390 | return -1; |
422 | } | 391 | } |
423 | 392 | ||
@@ -430,7 +399,7 @@ static int wme_classop_graft(struct Qdisc *qd, unsigned long arg, | |||
430 | struct ieee80211_hw *hw = &local->hw; | 399 | struct ieee80211_hw *hw = &local->hw; |
431 | unsigned long queue = arg - 1; | 400 | unsigned long queue = arg - 1; |
432 | 401 | ||
433 | if (queue >= hw->queues) | 402 | if (queue >= QD_NUM(hw)) |
434 | return -EINVAL; | 403 | return -EINVAL; |
435 | 404 | ||
436 | if (!new) | 405 | if (!new) |
@@ -454,7 +423,7 @@ wme_classop_leaf(struct Qdisc *qd, unsigned long arg) | |||
454 | struct ieee80211_hw *hw = &local->hw; | 423 | struct ieee80211_hw *hw = &local->hw; |
455 | unsigned long queue = arg - 1; | 424 | unsigned long queue = arg - 1; |
456 | 425 | ||
457 | if (queue >= hw->queues) | 426 | if (queue >= QD_NUM(hw)) |
458 | return NULL; | 427 | return NULL; |
459 | 428 | ||
460 | return q->queues[queue]; | 429 | return q->queues[queue]; |
@@ -467,7 +436,7 @@ static unsigned long wme_classop_get(struct Qdisc *qd, u32 classid) | |||
467 | struct ieee80211_hw *hw = &local->hw; | 436 | struct ieee80211_hw *hw = &local->hw; |
468 | unsigned long queue = TC_H_MIN(classid); | 437 | unsigned long queue = TC_H_MIN(classid); |
469 | 438 | ||
470 | if (queue - 1 >= hw->queues) | 439 | if (queue - 1 >= QD_NUM(hw)) |
471 | return 0; | 440 | return 0; |
472 | 441 | ||
473 | return queue; | 442 | return queue; |
@@ -493,7 +462,7 @@ static int wme_classop_change(struct Qdisc *qd, u32 handle, u32 parent, | |||
493 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); | 462 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); |
494 | struct ieee80211_hw *hw = &local->hw; | 463 | struct ieee80211_hw *hw = &local->hw; |
495 | 464 | ||
496 | if (cl - 1 > hw->queues) | 465 | if (cl - 1 > QD_NUM(hw)) |
497 | return -ENOENT; | 466 | return -ENOENT; |
498 | 467 | ||
499 | /* TODO: put code to program hardware queue parameters here, | 468 | /* TODO: put code to program hardware queue parameters here, |
@@ -510,7 +479,7 @@ static int wme_classop_delete(struct Qdisc *qd, unsigned long cl) | |||
510 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); | 479 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); |
511 | struct ieee80211_hw *hw = &local->hw; | 480 | struct ieee80211_hw *hw = &local->hw; |
512 | 481 | ||
513 | if (cl - 1 > hw->queues) | 482 | if (cl - 1 > QD_NUM(hw)) |
514 | return -ENOENT; | 483 | return -ENOENT; |
515 | return 0; | 484 | return 0; |
516 | } | 485 | } |
@@ -523,7 +492,7 @@ static int wme_classop_dump_class(struct Qdisc *qd, unsigned long cl, | |||
523 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); | 492 | struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr); |
524 | struct ieee80211_hw *hw = &local->hw; | 493 | struct ieee80211_hw *hw = &local->hw; |
525 | 494 | ||
526 | if (cl - 1 > hw->queues) | 495 | if (cl - 1 > QD_NUM(hw)) |
527 | return -ENOENT; | 496 | return -ENOENT; |
528 | tcm->tcm_handle = TC_H_MIN(cl); | 497 | tcm->tcm_handle = TC_H_MIN(cl); |
529 | tcm->tcm_parent = qd->handle; | 498 | tcm->tcm_parent = qd->handle; |
@@ -541,7 +510,7 @@ static void wme_classop_walk(struct Qdisc *qd, struct qdisc_walker *arg) | |||
541 | if (arg->stop) | 510 | if (arg->stop) |
542 | return; | 511 | return; |
543 | 512 | ||
544 | for (queue = 0; queue < hw->queues; queue++) { | 513 | for (queue = 0; queue < QD_NUM(hw); queue++) { |
545 | if (arg->count < arg->skip) { | 514 | if (arg->count < arg->skip) { |
546 | arg->count++; | 515 | arg->count++; |
547 | continue; | 516 | continue; |
@@ -658,10 +627,13 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, | |||
658 | DECLARE_MAC_BUF(mac); | 627 | DECLARE_MAC_BUF(mac); |
659 | 628 | ||
660 | /* prepare the filter and save it for the SW queue | 629 | /* prepare the filter and save it for the SW queue |
661 | * matching the recieved HW queue */ | 630 | * matching the received HW queue */ |
631 | |||
632 | if (!local->hw.ampdu_queues) | ||
633 | return -EPERM; | ||
662 | 634 | ||
663 | /* try to get a Qdisc from the pool */ | 635 | /* try to get a Qdisc from the pool */ |
664 | for (i = IEEE80211_TX_QUEUE_BEACON; i < local->hw.queues; i++) | 636 | for (i = local->hw.queues; i < QD_NUM(&local->hw); i++) |
665 | if (!test_and_set_bit(i, q->qdisc_pool)) { | 637 | if (!test_and_set_bit(i, q->qdisc_pool)) { |
666 | ieee80211_stop_queue(local_to_hw(local), i); | 638 | ieee80211_stop_queue(local_to_hw(local), i); |
667 | sta->tid_to_tx_q[tid] = i; | 639 | sta->tid_to_tx_q[tid] = i; |
@@ -690,13 +662,14 @@ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local, | |||
690 | struct sta_info *sta, u16 tid, | 662 | struct sta_info *sta, u16 tid, |
691 | u8 requeue) | 663 | u8 requeue) |
692 | { | 664 | { |
665 | struct ieee80211_hw *hw = &local->hw; | ||
693 | struct ieee80211_sched_data *q = | 666 | struct ieee80211_sched_data *q = |
694 | qdisc_priv(local->mdev->qdisc_sleeping); | 667 | qdisc_priv(local->mdev->qdisc_sleeping); |
695 | int agg_queue = sta->tid_to_tx_q[tid]; | 668 | int agg_queue = sta->tid_to_tx_q[tid]; |
696 | 669 | ||
697 | /* return the qdisc to the pool */ | 670 | /* return the qdisc to the pool */ |
698 | clear_bit(agg_queue, q->qdisc_pool); | 671 | clear_bit(agg_queue, q->qdisc_pool); |
699 | sta->tid_to_tx_q[tid] = local->hw.queues; | 672 | sta->tid_to_tx_q[tid] = QD_NUM(hw); |
700 | 673 | ||
701 | if (requeue) | 674 | if (requeue) |
702 | ieee80211_requeue(local, agg_queue); | 675 | ieee80211_requeue(local, agg_queue); |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index fcc6b05508cc..bbdb53344817 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -31,7 +31,7 @@ static inline int WLAN_FC_IS_QOS_DATA(u16 fc) | |||
31 | return (fc & 0x8C) == 0x88; | 31 | return (fc & 0x8C) == 0x88; |
32 | } | 32 | } |
33 | 33 | ||
34 | #ifdef CONFIG_NET_SCHED | 34 | #ifdef CONFIG_MAC80211_QOS |
35 | void ieee80211_install_qdisc(struct net_device *dev); | 35 | void ieee80211_install_qdisc(struct net_device *dev); |
36 | int ieee80211_qdisc_installed(struct net_device *dev); | 36 | int ieee80211_qdisc_installed(struct net_device *dev); |
37 | int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, | 37 | int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 45709ada8fee..9f6fd20374e1 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -79,6 +79,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
79 | struct sk_buff *skb = tx->skb; | 79 | struct sk_buff *skb = tx->skb; |
80 | int authenticator; | 80 | int authenticator; |
81 | int wpa_test = 0; | 81 | int wpa_test = 0; |
82 | int tail; | ||
82 | 83 | ||
83 | fc = tx->fc; | 84 | fc = tx->fc; |
84 | 85 | ||
@@ -98,16 +99,13 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
98 | return TX_CONTINUE; | 99 | return TX_CONTINUE; |
99 | } | 100 | } |
100 | 101 | ||
101 | if (skb_tailroom(skb) < MICHAEL_MIC_LEN) { | 102 | tail = MICHAEL_MIC_LEN; |
102 | I802_DEBUG_INC(tx->local->tx_expand_skb_head); | 103 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
103 | if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN, | 104 | tail += TKIP_ICV_LEN; |
104 | MICHAEL_MIC_LEN + TKIP_ICV_LEN, | 105 | |
105 | GFP_ATOMIC))) { | 106 | if (WARN_ON(skb_tailroom(skb) < tail || |
106 | printk(KERN_DEBUG "%s: failed to allocate more memory " | 107 | skb_headroom(skb) < TKIP_IV_LEN)) |
107 | "for Michael MIC\n", tx->dev->name); | 108 | return TX_DROP; |
108 | return TX_DROP; | ||
109 | } | ||
110 | } | ||
111 | 109 | ||
112 | #if 0 | 110 | #if 0 |
113 | authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */ | 111 | authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */ |
@@ -176,59 +174,65 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
176 | skb_trim(skb, skb->len - MICHAEL_MIC_LEN); | 174 | skb_trim(skb, skb->len - MICHAEL_MIC_LEN); |
177 | 175 | ||
178 | /* update IV in key information to be able to detect replays */ | 176 | /* update IV in key information to be able to detect replays */ |
179 | rx->key->u.tkip.iv32_rx[rx->queue] = rx->tkip_iv32; | 177 | rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32; |
180 | rx->key->u.tkip.iv16_rx[rx->queue] = rx->tkip_iv16; | 178 | rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16; |
181 | 179 | ||
182 | return RX_CONTINUE; | 180 | return RX_CONTINUE; |
183 | } | 181 | } |
184 | 182 | ||
185 | 183 | ||
186 | static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, | 184 | static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
187 | struct sk_buff *skb, int test) | ||
188 | { | 185 | { |
189 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 186 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
190 | struct ieee80211_key *key = tx->key; | 187 | struct ieee80211_key *key = tx->key; |
191 | int hdrlen, len, tailneed; | 188 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
189 | int hdrlen, len, tail; | ||
192 | u16 fc; | 190 | u16 fc; |
193 | u8 *pos; | 191 | u8 *pos; |
194 | 192 | ||
193 | info->control.icv_len = TKIP_ICV_LEN; | ||
194 | info->control.iv_len = TKIP_IV_LEN; | ||
195 | |||
196 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | ||
197 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | ||
198 | /* hwaccel - with no need for preallocated room for IV/ICV */ | ||
199 | info->control.hw_key = &tx->key->conf; | ||
200 | return 0; | ||
201 | } | ||
202 | |||
195 | fc = le16_to_cpu(hdr->frame_control); | 203 | fc = le16_to_cpu(hdr->frame_control); |
196 | hdrlen = ieee80211_get_hdrlen(fc); | 204 | hdrlen = ieee80211_get_hdrlen(fc); |
197 | len = skb->len - hdrlen; | 205 | len = skb->len - hdrlen; |
198 | 206 | ||
199 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 207 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
200 | tailneed = 0; | 208 | tail = 0; |
201 | else | 209 | else |
202 | tailneed = TKIP_ICV_LEN; | 210 | tail = TKIP_ICV_LEN; |
203 | 211 | ||
204 | if ((skb_headroom(skb) < TKIP_IV_LEN || | 212 | if (WARN_ON(skb_tailroom(skb) < tail || |
205 | skb_tailroom(skb) < tailneed)) { | 213 | skb_headroom(skb) < TKIP_IV_LEN)) |
206 | I802_DEBUG_INC(tx->local->tx_expand_skb_head); | 214 | return -1; |
207 | if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN, tailneed, | ||
208 | GFP_ATOMIC))) | ||
209 | return -1; | ||
210 | } | ||
211 | 215 | ||
212 | pos = skb_push(skb, TKIP_IV_LEN); | 216 | pos = skb_push(skb, TKIP_IV_LEN); |
213 | memmove(pos, pos + TKIP_IV_LEN, hdrlen); | 217 | memmove(pos, pos + TKIP_IV_LEN, hdrlen); |
214 | pos += hdrlen; | 218 | pos += hdrlen; |
215 | 219 | ||
216 | /* Increase IV for the frame */ | 220 | /* Increase IV for the frame */ |
217 | key->u.tkip.iv16++; | 221 | key->u.tkip.tx.iv16++; |
218 | if (key->u.tkip.iv16 == 0) | 222 | if (key->u.tkip.tx.iv16 == 0) |
219 | key->u.tkip.iv32++; | 223 | key->u.tkip.tx.iv32++; |
220 | 224 | ||
221 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 225 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
222 | hdr = (struct ieee80211_hdr *)skb->data; | 226 | hdr = (struct ieee80211_hdr *)skb->data; |
223 | 227 | ||
224 | /* hwaccel - with preallocated room for IV */ | 228 | /* hwaccel - with preallocated room for IV */ |
225 | ieee80211_tkip_add_iv(pos, key, | 229 | ieee80211_tkip_add_iv(pos, key, |
226 | (u8) (key->u.tkip.iv16 >> 8), | 230 | (u8) (key->u.tkip.tx.iv16 >> 8), |
227 | (u8) (((key->u.tkip.iv16 >> 8) | 0x20) & | 231 | (u8) (((key->u.tkip.tx.iv16 >> 8) | 0x20) & |
228 | 0x7f), | 232 | 0x7f), |
229 | (u8) key->u.tkip.iv16); | 233 | (u8) key->u.tkip.tx.iv16); |
230 | 234 | ||
231 | tx->control->key_idx = tx->key->conf.hw_key_idx; | 235 | info->control.hw_key = &tx->key->conf; |
232 | return 0; | 236 | return 0; |
233 | } | 237 | } |
234 | 238 | ||
@@ -246,28 +250,16 @@ ieee80211_tx_result | |||
246 | ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) | 250 | ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) |
247 | { | 251 | { |
248 | struct sk_buff *skb = tx->skb; | 252 | struct sk_buff *skb = tx->skb; |
249 | int wpa_test = 0, test = 0; | ||
250 | 253 | ||
251 | tx->control->icv_len = TKIP_ICV_LEN; | ||
252 | tx->control->iv_len = TKIP_IV_LEN; | ||
253 | ieee80211_tx_set_protected(tx); | 254 | ieee80211_tx_set_protected(tx); |
254 | 255 | ||
255 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 256 | if (tkip_encrypt_skb(tx, skb) < 0) |
256 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && | ||
257 | !wpa_test) { | ||
258 | /* hwaccel - with no need for preallocated room for IV/ICV */ | ||
259 | tx->control->key_idx = tx->key->conf.hw_key_idx; | ||
260 | return TX_CONTINUE; | ||
261 | } | ||
262 | |||
263 | if (tkip_encrypt_skb(tx, skb, test) < 0) | ||
264 | return TX_DROP; | 257 | return TX_DROP; |
265 | 258 | ||
266 | if (tx->extra_frag) { | 259 | if (tx->extra_frag) { |
267 | int i; | 260 | int i; |
268 | for (i = 0; i < tx->num_extra_frag; i++) { | 261 | for (i = 0; i < tx->num_extra_frag; i++) { |
269 | if (tkip_encrypt_skb(tx, tx->extra_frag[i], test) | 262 | if (tkip_encrypt_skb(tx, tx->extra_frag[i]) < 0) |
270 | < 0) | ||
271 | return TX_DROP; | 263 | return TX_DROP; |
272 | } | 264 | } |
273 | } | 265 | } |
@@ -429,16 +421,27 @@ static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr) | |||
429 | } | 421 | } |
430 | 422 | ||
431 | 423 | ||
432 | static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, | 424 | static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
433 | struct sk_buff *skb, int test) | ||
434 | { | 425 | { |
435 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 426 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
436 | struct ieee80211_key *key = tx->key; | 427 | struct ieee80211_key *key = tx->key; |
437 | int hdrlen, len, tailneed; | 428 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
429 | int hdrlen, len, tail; | ||
438 | u16 fc; | 430 | u16 fc; |
439 | u8 *pos, *pn, *b_0, *aad, *scratch; | 431 | u8 *pos, *pn, *b_0, *aad, *scratch; |
440 | int i; | 432 | int i; |
441 | 433 | ||
434 | info->control.icv_len = CCMP_MIC_LEN; | ||
435 | info->control.iv_len = CCMP_HDR_LEN; | ||
436 | |||
437 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | ||
438 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | ||
439 | /* hwaccel - with no need for preallocated room for CCMP " | ||
440 | * header or MIC fields */ | ||
441 | info->control.hw_key = &tx->key->conf; | ||
442 | return 0; | ||
443 | } | ||
444 | |||
442 | scratch = key->u.ccmp.tx_crypto_buf; | 445 | scratch = key->u.ccmp.tx_crypto_buf; |
443 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 446 | b_0 = scratch + 3 * AES_BLOCK_LEN; |
444 | aad = scratch + 4 * AES_BLOCK_LEN; | 447 | aad = scratch + 4 * AES_BLOCK_LEN; |
@@ -448,17 +451,13 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, | |||
448 | len = skb->len - hdrlen; | 451 | len = skb->len - hdrlen; |
449 | 452 | ||
450 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 453 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
451 | tailneed = 0; | 454 | tail = 0; |
452 | else | 455 | else |
453 | tailneed = CCMP_MIC_LEN; | 456 | tail = CCMP_MIC_LEN; |
454 | 457 | ||
455 | if ((skb_headroom(skb) < CCMP_HDR_LEN || | 458 | if (WARN_ON(skb_tailroom(skb) < tail || |
456 | skb_tailroom(skb) < tailneed)) { | 459 | skb_headroom(skb) < CCMP_HDR_LEN)) |
457 | I802_DEBUG_INC(tx->local->tx_expand_skb_head); | 460 | return -1; |
458 | if (unlikely(pskb_expand_head(skb, CCMP_HDR_LEN, tailneed, | ||
459 | GFP_ATOMIC))) | ||
460 | return -1; | ||
461 | } | ||
462 | 461 | ||
463 | pos = skb_push(skb, CCMP_HDR_LEN); | 462 | pos = skb_push(skb, CCMP_HDR_LEN); |
464 | memmove(pos, pos + CCMP_HDR_LEN, hdrlen); | 463 | memmove(pos, pos + CCMP_HDR_LEN, hdrlen); |
@@ -478,7 +477,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, | |||
478 | 477 | ||
479 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 478 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
480 | /* hwaccel - with preallocated room for CCMP header */ | 479 | /* hwaccel - with preallocated room for CCMP header */ |
481 | tx->control->key_idx = key->conf.hw_key_idx; | 480 | info->control.hw_key = &tx->key->conf; |
482 | return 0; | 481 | return 0; |
483 | } | 482 | } |
484 | 483 | ||
@@ -495,28 +494,16 @@ ieee80211_tx_result | |||
495 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) | 494 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) |
496 | { | 495 | { |
497 | struct sk_buff *skb = tx->skb; | 496 | struct sk_buff *skb = tx->skb; |
498 | int test = 0; | ||
499 | 497 | ||
500 | tx->control->icv_len = CCMP_MIC_LEN; | ||
501 | tx->control->iv_len = CCMP_HDR_LEN; | ||
502 | ieee80211_tx_set_protected(tx); | 498 | ieee80211_tx_set_protected(tx); |
503 | 499 | ||
504 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 500 | if (ccmp_encrypt_skb(tx, skb) < 0) |
505 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | ||
506 | /* hwaccel - with no need for preallocated room for CCMP " | ||
507 | * header or MIC fields */ | ||
508 | tx->control->key_idx = tx->key->conf.hw_key_idx; | ||
509 | return TX_CONTINUE; | ||
510 | } | ||
511 | |||
512 | if (ccmp_encrypt_skb(tx, skb, test) < 0) | ||
513 | return TX_DROP; | 501 | return TX_DROP; |
514 | 502 | ||
515 | if (tx->extra_frag) { | 503 | if (tx->extra_frag) { |
516 | int i; | 504 | int i; |
517 | for (i = 0; i < tx->num_extra_frag; i++) { | 505 | for (i = 0; i < tx->num_extra_frag; i++) { |
518 | if (ccmp_encrypt_skb(tx, tx->extra_frag[i], test) | 506 | if (ccmp_encrypt_skb(tx, tx->extra_frag[i]) < 0) |
519 | < 0) | ||
520 | return TX_DROP; | 507 | return TX_DROP; |
521 | } | 508 | } |
522 | } | 509 | } |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 662c1ccfee26..f27c99246a4c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -847,6 +847,25 @@ acct: | |||
847 | } | 847 | } |
848 | EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct); | 848 | EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct); |
849 | 849 | ||
850 | void __nf_ct_kill_acct(struct nf_conn *ct, | ||
851 | enum ip_conntrack_info ctinfo, | ||
852 | const struct sk_buff *skb, | ||
853 | int do_acct) | ||
854 | { | ||
855 | #ifdef CONFIG_NF_CT_ACCT | ||
856 | if (do_acct) { | ||
857 | spin_lock_bh(&nf_conntrack_lock); | ||
858 | ct->counters[CTINFO2DIR(ctinfo)].packets++; | ||
859 | ct->counters[CTINFO2DIR(ctinfo)].bytes += | ||
860 | skb->len - skb_network_offset(skb); | ||
861 | spin_unlock_bh(&nf_conntrack_lock); | ||
862 | } | ||
863 | #endif | ||
864 | if (del_timer(&ct->timeout)) | ||
865 | ct->timeout.function((unsigned long)ct); | ||
866 | } | ||
867 | EXPORT_SYMBOL_GPL(__nf_ct_kill_acct); | ||
868 | |||
850 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 869 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
851 | 870 | ||
852 | #include <linux/netfilter/nfnetlink.h> | 871 | #include <linux/netfilter/nfnetlink.h> |
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index bcc19fa4ed1e..ba1c4915e9eb 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c | |||
@@ -88,13 +88,11 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) | |||
88 | newlen = newoff + t->len; | 88 | newlen = newoff + t->len; |
89 | rcu_read_unlock(); | 89 | rcu_read_unlock(); |
90 | 90 | ||
91 | if (newlen >= ksize(ct->ext)) { | 91 | new = krealloc(ct->ext, newlen, gfp); |
92 | new = kmalloc(newlen, gfp); | 92 | if (!new) |
93 | if (!new) | 93 | return NULL; |
94 | return NULL; | ||
95 | |||
96 | memcpy(new, ct->ext, ct->ext->len); | ||
97 | 94 | ||
95 | if (new != ct->ext) { | ||
98 | for (i = 0; i < NF_CT_EXT_NUM; i++) { | 96 | for (i = 0; i < NF_CT_EXT_NUM; i++) { |
99 | if (!nf_ct_ext_exist(ct, i)) | 97 | if (!nf_ct_ext_exist(ct, i)) |
100 | continue; | 98 | continue; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 0edefcfc5949..63c4e1f299b8 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (C) 2001 by Jay Schulist <jschlst@samba.org> | 4 | * (C) 2001 by Jay Schulist <jschlst@samba.org> |
5 | * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org> | 5 | * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org> |
6 | * (C) 2003 by Patrick Mchardy <kaber@trash.net> | 6 | * (C) 2003 by Patrick Mchardy <kaber@trash.net> |
7 | * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org> | 7 | * (C) 2005-2008 by Pablo Neira Ayuso <pablo@netfilter.org> |
8 | * | 8 | * |
9 | * Initial connection tracking via netlink development funded and | 9 | * Initial connection tracking via netlink development funded and |
10 | * generally made possible by Network Robots, Inc. (www.networkrobots.com) | 10 | * generally made possible by Network Robots, Inc. (www.networkrobots.com) |
@@ -475,14 +475,14 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
475 | if (ctnetlink_dump_id(skb, ct) < 0) | 475 | if (ctnetlink_dump_id(skb, ct) < 0) |
476 | goto nla_put_failure; | 476 | goto nla_put_failure; |
477 | 477 | ||
478 | if (ctnetlink_dump_status(skb, ct) < 0) | ||
479 | goto nla_put_failure; | ||
480 | |||
478 | if (events & IPCT_DESTROY) { | 481 | if (events & IPCT_DESTROY) { |
479 | if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || | 482 | if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || |
480 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) | 483 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) |
481 | goto nla_put_failure; | 484 | goto nla_put_failure; |
482 | } else { | 485 | } else { |
483 | if (ctnetlink_dump_status(skb, ct) < 0) | ||
484 | goto nla_put_failure; | ||
485 | |||
486 | if (ctnetlink_dump_timeout(skb, ct) < 0) | 486 | if (ctnetlink_dump_timeout(skb, ct) < 0) |
487 | goto nla_put_failure; | 487 | goto nla_put_failure; |
488 | 488 | ||
@@ -812,9 +812,8 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
812 | return -ENOENT; | 812 | return -ENOENT; |
813 | } | 813 | } |
814 | } | 814 | } |
815 | if (del_timer(&ct->timeout)) | ||
816 | ct->timeout.function((unsigned long)ct); | ||
817 | 815 | ||
816 | nf_ct_kill(ct); | ||
818 | nf_ct_put(ct); | 817 | nf_ct_put(ct); |
819 | 818 | ||
820 | return 0; | 819 | return 0; |
@@ -891,20 +890,19 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[]) | |||
891 | 890 | ||
892 | if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING)) | 891 | if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING)) |
893 | /* unchangeable */ | 892 | /* unchangeable */ |
894 | return -EINVAL; | 893 | return -EBUSY; |
895 | 894 | ||
896 | if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY)) | 895 | if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY)) |
897 | /* SEEN_REPLY bit can only be set */ | 896 | /* SEEN_REPLY bit can only be set */ |
898 | return -EINVAL; | 897 | return -EBUSY; |
899 | |||
900 | 898 | ||
901 | if (d & IPS_ASSURED && !(status & IPS_ASSURED)) | 899 | if (d & IPS_ASSURED && !(status & IPS_ASSURED)) |
902 | /* ASSURED bit can only be set */ | 900 | /* ASSURED bit can only be set */ |
903 | return -EINVAL; | 901 | return -EBUSY; |
904 | 902 | ||
905 | if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { | 903 | if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { |
906 | #ifndef CONFIG_NF_NAT_NEEDED | 904 | #ifndef CONFIG_NF_NAT_NEEDED |
907 | return -EINVAL; | 905 | return -EOPNOTSUPP; |
908 | #else | 906 | #else |
909 | struct nf_nat_range range; | 907 | struct nf_nat_range range; |
910 | 908 | ||
@@ -945,7 +943,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[]) | |||
945 | 943 | ||
946 | /* don't change helper of sibling connections */ | 944 | /* don't change helper of sibling connections */ |
947 | if (ct->master) | 945 | if (ct->master) |
948 | return -EINVAL; | 946 | return -EBUSY; |
949 | 947 | ||
950 | err = ctnetlink_parse_help(cda[CTA_HELP], &helpname); | 948 | err = ctnetlink_parse_help(cda[CTA_HELP], &helpname); |
951 | if (err < 0) | 949 | if (err < 0) |
@@ -963,7 +961,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[]) | |||
963 | 961 | ||
964 | helper = __nf_conntrack_helper_find_byname(helpname); | 962 | helper = __nf_conntrack_helper_find_byname(helpname); |
965 | if (helper == NULL) | 963 | if (helper == NULL) |
966 | return -EINVAL; | 964 | return -EOPNOTSUPP; |
967 | 965 | ||
968 | if (help) { | 966 | if (help) { |
969 | if (help->helper == helper) | 967 | if (help->helper == helper) |
@@ -1258,12 +1256,12 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1258 | if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { | 1256 | if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { |
1259 | /* we only allow nat config for new conntracks */ | 1257 | /* we only allow nat config for new conntracks */ |
1260 | if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { | 1258 | if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { |
1261 | err = -EINVAL; | 1259 | err = -EOPNOTSUPP; |
1262 | goto out_unlock; | 1260 | goto out_unlock; |
1263 | } | 1261 | } |
1264 | /* can't link an existing conntrack to a master */ | 1262 | /* can't link an existing conntrack to a master */ |
1265 | if (cda[CTA_TUPLE_MASTER]) { | 1263 | if (cda[CTA_TUPLE_MASTER]) { |
1266 | err = -EINVAL; | 1264 | err = -EOPNOTSUPP; |
1267 | goto out_unlock; | 1265 | goto out_unlock; |
1268 | } | 1266 | } |
1269 | err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), | 1267 | err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h), |
@@ -1608,7 +1606,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1608 | h = __nf_conntrack_helper_find_byname(name); | 1606 | h = __nf_conntrack_helper_find_byname(name); |
1609 | if (!h) { | 1607 | if (!h) { |
1610 | spin_unlock_bh(&nf_conntrack_lock); | 1608 | spin_unlock_bh(&nf_conntrack_lock); |
1611 | return -EINVAL; | 1609 | return -EOPNOTSUPP; |
1612 | } | 1610 | } |
1613 | for (i = 0; i < nf_ct_expect_hsize; i++) { | 1611 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
1614 | hlist_for_each_entry_safe(exp, n, next, | 1612 | hlist_for_each_entry_safe(exp, n, next, |
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index afb4a1861d2c..e7866dd3cde6 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
@@ -475,8 +475,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, | |||
475 | if (type == DCCP_PKT_RESET && | 475 | if (type == DCCP_PKT_RESET && |
476 | !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { | 476 | !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { |
477 | /* Tear down connection immediately if only reply is a RESET */ | 477 | /* Tear down connection immediately if only reply is a RESET */ |
478 | if (del_timer(&ct->timeout)) | 478 | nf_ct_kill_acct(ct, ctinfo, skb); |
479 | ct->timeout.function((unsigned long)ct); | ||
480 | return NF_ACCEPT; | 479 | return NF_ACCEPT; |
481 | } | 480 | } |
482 | 481 | ||
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index cbf2e27a22b2..41183a4d2d62 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -463,6 +463,82 @@ static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
463 | return true; | 463 | return true; |
464 | } | 464 | } |
465 | 465 | ||
466 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
467 | |||
468 | #include <linux/netfilter/nfnetlink.h> | ||
469 | #include <linux/netfilter/nfnetlink_conntrack.h> | ||
470 | |||
471 | static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, | ||
472 | const struct nf_conn *ct) | ||
473 | { | ||
474 | struct nlattr *nest_parms; | ||
475 | |||
476 | read_lock_bh(&sctp_lock); | ||
477 | nest_parms = nla_nest_start(skb, CTA_PROTOINFO_SCTP | NLA_F_NESTED); | ||
478 | if (!nest_parms) | ||
479 | goto nla_put_failure; | ||
480 | |||
481 | NLA_PUT_U8(skb, CTA_PROTOINFO_SCTP_STATE, ct->proto.sctp.state); | ||
482 | |||
483 | NLA_PUT_BE32(skb, | ||
484 | CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, | ||
485 | htonl(ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL])); | ||
486 | |||
487 | NLA_PUT_BE32(skb, | ||
488 | CTA_PROTOINFO_SCTP_VTAG_REPLY, | ||
489 | htonl(ct->proto.sctp.vtag[IP_CT_DIR_REPLY])); | ||
490 | |||
491 | read_unlock_bh(&sctp_lock); | ||
492 | |||
493 | nla_nest_end(skb, nest_parms); | ||
494 | |||
495 | return 0; | ||
496 | |||
497 | nla_put_failure: | ||
498 | read_unlock_bh(&sctp_lock); | ||
499 | return -1; | ||
500 | } | ||
501 | |||
502 | static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = { | ||
503 | [CTA_PROTOINFO_SCTP_STATE] = { .type = NLA_U8 }, | ||
504 | [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 }, | ||
505 | [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 }, | ||
506 | }; | ||
507 | |||
508 | static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct) | ||
509 | { | ||
510 | struct nlattr *attr = cda[CTA_PROTOINFO_SCTP]; | ||
511 | struct nlattr *tb[CTA_PROTOINFO_SCTP_MAX+1]; | ||
512 | int err; | ||
513 | |||
514 | /* updates may not contain the internal protocol info, skip parsing */ | ||
515 | if (!attr) | ||
516 | return 0; | ||
517 | |||
518 | err = nla_parse_nested(tb, | ||
519 | CTA_PROTOINFO_SCTP_MAX, | ||
520 | attr, | ||
521 | sctp_nla_policy); | ||
522 | if (err < 0) | ||
523 | return err; | ||
524 | |||
525 | if (!tb[CTA_PROTOINFO_SCTP_STATE] || | ||
526 | !tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] || | ||
527 | !tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]) | ||
528 | return -EINVAL; | ||
529 | |||
530 | write_lock_bh(&sctp_lock); | ||
531 | ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]); | ||
532 | ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = | ||
533 | ntohl(nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL])); | ||
534 | ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = | ||
535 | ntohl(nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY])); | ||
536 | write_unlock_bh(&sctp_lock); | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | #endif | ||
541 | |||
466 | #ifdef CONFIG_SYSCTL | 542 | #ifdef CONFIG_SYSCTL |
467 | static unsigned int sctp_sysctl_table_users; | 543 | static unsigned int sctp_sysctl_table_users; |
468 | static struct ctl_table_header *sctp_sysctl_header; | 544 | static struct ctl_table_header *sctp_sysctl_header; |
@@ -591,6 +667,8 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { | |||
591 | .new = sctp_new, | 667 | .new = sctp_new, |
592 | .me = THIS_MODULE, | 668 | .me = THIS_MODULE, |
593 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 669 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
670 | .to_nlattr = sctp_to_nlattr, | ||
671 | .from_nlattr = nlattr_to_sctp, | ||
594 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, | 672 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
595 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, | 673 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
596 | .nla_policy = nf_ct_port_nla_policy, | 674 | .nla_policy = nf_ct_port_nla_policy, |
@@ -617,6 +695,8 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { | |||
617 | .new = sctp_new, | 695 | .new = sctp_new, |
618 | .me = THIS_MODULE, | 696 | .me = THIS_MODULE, |
619 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 697 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
698 | .to_nlattr = sctp_to_nlattr, | ||
699 | .from_nlattr = nlattr_to_sctp, | ||
620 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, | 700 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
621 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, | 701 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
622 | .nla_policy = nf_ct_port_nla_policy, | 702 | .nla_policy = nf_ct_port_nla_policy, |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index ba94004fe323..8db13fba10bc 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -843,8 +843,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
843 | /* Attempt to reopen a closed/aborted connection. | 843 | /* Attempt to reopen a closed/aborted connection. |
844 | * Delete this connection and look up again. */ | 844 | * Delete this connection and look up again. */ |
845 | write_unlock_bh(&tcp_lock); | 845 | write_unlock_bh(&tcp_lock); |
846 | if (del_timer(&ct->timeout)) | 846 | nf_ct_kill(ct); |
847 | ct->timeout.function((unsigned long)ct); | ||
848 | return -NF_REPEAT; | 847 | return -NF_REPEAT; |
849 | } | 848 | } |
850 | /* Fall through */ | 849 | /* Fall through */ |
@@ -877,8 +876,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
877 | if (LOG_INVALID(IPPROTO_TCP)) | 876 | if (LOG_INVALID(IPPROTO_TCP)) |
878 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 877 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, |
879 | "nf_ct_tcp: killing out of sync session "); | 878 | "nf_ct_tcp: killing out of sync session "); |
880 | if (del_timer(&ct->timeout)) | 879 | nf_ct_kill(ct); |
881 | ct->timeout.function((unsigned long)ct); | ||
882 | return -NF_DROP; | 880 | return -NF_DROP; |
883 | } | 881 | } |
884 | ct->proto.tcp.last_index = index; | 882 | ct->proto.tcp.last_index = index; |
@@ -961,8 +959,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
961 | problem case, so we can delete the conntrack | 959 | problem case, so we can delete the conntrack |
962 | immediately. --RR */ | 960 | immediately. --RR */ |
963 | if (th->rst) { | 961 | if (th->rst) { |
964 | if (del_timer(&ct->timeout)) | 962 | nf_ct_kill_acct(ct, ctinfo, skb); |
965 | ct->timeout.function((unsigned long)ct); | ||
966 | return NF_ACCEPT; | 963 | return NF_ACCEPT; |
967 | } | 964 | } |
968 | } else if (!test_bit(IPS_ASSURED_BIT, &ct->status) | 965 | } else if (!test_bit(IPS_ASSURED_BIT, &ct->status) |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 3447025ce068..04e9c965f8ca 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -243,7 +243,6 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
243 | switch ((enum nfqnl_config_mode)queue->copy_mode) { | 243 | switch ((enum nfqnl_config_mode)queue->copy_mode) { |
244 | case NFQNL_COPY_META: | 244 | case NFQNL_COPY_META: |
245 | case NFQNL_COPY_NONE: | 245 | case NFQNL_COPY_NONE: |
246 | data_len = 0; | ||
247 | break; | 246 | break; |
248 | 247 | ||
249 | case NFQNL_COPY_PACKET: | 248 | case NFQNL_COPY_PACKET: |
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c index 211189eb2b67..76ca1f2421eb 100644 --- a/net/netfilter/xt_CONNSECMARK.c +++ b/net/netfilter/xt_CONNSECMARK.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | 8 | * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> |
9 | * by Henrik Nordstrom <hno@marasystems.com> | 9 | * by Henrik Nordstrom <hno@marasystems.com> |
10 | * | 10 | * |
11 | * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com> | 11 | * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com> |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2 as | 14 | * it under the terms of the GNU General Public License version 2 as |
@@ -94,6 +94,12 @@ connsecmark_tg_check(const char *tablename, const void *entry, | |||
94 | { | 94 | { |
95 | const struct xt_connsecmark_target_info *info = targinfo; | 95 | const struct xt_connsecmark_target_info *info = targinfo; |
96 | 96 | ||
97 | if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) { | ||
98 | printk(KERN_INFO PFX "target only valid in the \'mangle\' " | ||
99 | "or \'security\' tables, not \'%s\'.\n", tablename); | ||
100 | return false; | ||
101 | } | ||
102 | |||
97 | switch (info->mode) { | 103 | switch (info->mode) { |
98 | case CONNSECMARK_SAVE: | 104 | case CONNSECMARK_SAVE: |
99 | case CONNSECMARK_RESTORE: | 105 | case CONNSECMARK_RESTORE: |
@@ -126,7 +132,6 @@ static struct xt_target connsecmark_tg_reg[] __read_mostly = { | |||
126 | .destroy = connsecmark_tg_destroy, | 132 | .destroy = connsecmark_tg_destroy, |
127 | .target = connsecmark_tg, | 133 | .target = connsecmark_tg, |
128 | .targetsize = sizeof(struct xt_connsecmark_target_info), | 134 | .targetsize = sizeof(struct xt_connsecmark_target_info), |
129 | .table = "mangle", | ||
130 | .me = THIS_MODULE, | 135 | .me = THIS_MODULE, |
131 | }, | 136 | }, |
132 | { | 137 | { |
@@ -136,7 +141,6 @@ static struct xt_target connsecmark_tg_reg[] __read_mostly = { | |||
136 | .destroy = connsecmark_tg_destroy, | 141 | .destroy = connsecmark_tg_destroy, |
137 | .target = connsecmark_tg, | 142 | .target = connsecmark_tg, |
138 | .targetsize = sizeof(struct xt_connsecmark_target_info), | 143 | .targetsize = sizeof(struct xt_connsecmark_target_info), |
139 | .table = "mangle", | ||
140 | .me = THIS_MODULE, | 144 | .me = THIS_MODULE, |
141 | }, | 145 | }, |
142 | }; | 146 | }; |
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index c0284856ccd4..94f87ee7552b 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Based on the nfmark match by: | 5 | * Based on the nfmark match by: |
6 | * (C) 1999-2001 Marc Boucher <marc@mbsi.ca> | 6 | * (C) 1999-2001 Marc Boucher <marc@mbsi.ca> |
7 | * | 7 | * |
8 | * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com> | 8 | * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
@@ -89,6 +89,12 @@ secmark_tg_check(const char *tablename, const void *entry, | |||
89 | { | 89 | { |
90 | struct xt_secmark_target_info *info = targinfo; | 90 | struct xt_secmark_target_info *info = targinfo; |
91 | 91 | ||
92 | if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) { | ||
93 | printk(KERN_INFO PFX "target only valid in the \'mangle\' " | ||
94 | "or \'security\' tables, not \'%s\'.\n", tablename); | ||
95 | return false; | ||
96 | } | ||
97 | |||
92 | if (mode && mode != info->mode) { | 98 | if (mode && mode != info->mode) { |
93 | printk(KERN_INFO PFX "mode already set to %hu cannot mix with " | 99 | printk(KERN_INFO PFX "mode already set to %hu cannot mix with " |
94 | "rules for mode %hu\n", mode, info->mode); | 100 | "rules for mode %hu\n", mode, info->mode); |
@@ -127,7 +133,6 @@ static struct xt_target secmark_tg_reg[] __read_mostly = { | |||
127 | .destroy = secmark_tg_destroy, | 133 | .destroy = secmark_tg_destroy, |
128 | .target = secmark_tg, | 134 | .target = secmark_tg, |
129 | .targetsize = sizeof(struct xt_secmark_target_info), | 135 | .targetsize = sizeof(struct xt_secmark_target_info), |
130 | .table = "mangle", | ||
131 | .me = THIS_MODULE, | 136 | .me = THIS_MODULE, |
132 | }, | 137 | }, |
133 | { | 138 | { |
@@ -137,7 +142,6 @@ static struct xt_target secmark_tg_reg[] __read_mostly = { | |||
137 | .destroy = secmark_tg_destroy, | 142 | .destroy = secmark_tg_destroy, |
138 | .target = secmark_tg, | 143 | .target = secmark_tg, |
139 | .targetsize = sizeof(struct xt_secmark_target_info), | 144 | .targetsize = sizeof(struct xt_secmark_target_info), |
140 | .table = "mangle", | ||
141 | .me = THIS_MODULE, | 145 | .me = THIS_MODULE, |
142 | }, | 146 | }, |
143 | }; | 147 | }; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9b97f8006c9c..6507c02dbe0d 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -759,7 +759,7 @@ struct sock *netlink_getsockbyfilp(struct file *filp) | |||
759 | * 0: continue | 759 | * 0: continue |
760 | * 1: repeat lookup - reference dropped while waiting for socket memory. | 760 | * 1: repeat lookup - reference dropped while waiting for socket memory. |
761 | */ | 761 | */ |
762 | int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, | 762 | int netlink_attachskb(struct sock *sk, struct sk_buff *skb, |
763 | long *timeo, struct sock *ssk) | 763 | long *timeo, struct sock *ssk) |
764 | { | 764 | { |
765 | struct netlink_sock *nlk; | 765 | struct netlink_sock *nlk; |
@@ -892,7 +892,7 @@ retry: | |||
892 | return err; | 892 | return err; |
893 | } | 893 | } |
894 | 894 | ||
895 | err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk); | 895 | err = netlink_attachskb(sk, skb, &timeo, ssk); |
896 | if (err == 1) | 896 | if (err == 1) |
897 | goto retry; | 897 | goto retry; |
898 | if (err) | 898 | if (err) |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2cee87da4441..beca6402f1cf 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * PACKET - implements raw packet sockets. | 6 | * PACKET - implements raw packet sockets. |
7 | * | 7 | * |
8 | * Version: $Id: af_packet.c,v 1.61 2002/02/08 03:57:19 davem Exp $ | ||
9 | * | ||
10 | * Authors: Ross Biro | 8 | * Authors: Ross Biro |
11 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | 9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
12 | * Alan Cox, <gw4pts@gw4pts.ampr.org> | 10 | * Alan Cox, <gw4pts@gw4pts.ampr.org> |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 5bc1ed490180..213071859030 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -24,8 +24,6 @@ | |||
24 | * Jiri Fojtasek | 24 | * Jiri Fojtasek |
25 | * fixed requeue routine | 25 | * fixed requeue routine |
26 | * and many others. thanks. | 26 | * and many others. thanks. |
27 | * | ||
28 | * $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $ | ||
29 | */ | 27 | */ |
30 | #include <linux/module.h> | 28 | #include <linux/module.h> |
31 | #include <linux/types.h> | 29 | #include <linux/types.h> |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 532634861db1..d5cc731b6798 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -136,6 +136,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
136 | 136 | ||
137 | /* Set association default SACK delay */ | 137 | /* Set association default SACK delay */ |
138 | asoc->sackdelay = msecs_to_jiffies(sp->sackdelay); | 138 | asoc->sackdelay = msecs_to_jiffies(sp->sackdelay); |
139 | asoc->sackfreq = sp->sackfreq; | ||
139 | 140 | ||
140 | /* Set the association default flags controlling | 141 | /* Set the association default flags controlling |
141 | * Heartbeat, SACK delay, and Path MTU Discovery. | 142 | * Heartbeat, SACK delay, and Path MTU Discovery. |
@@ -261,6 +262,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
261 | * already received one packet.] | 262 | * already received one packet.] |
262 | */ | 263 | */ |
263 | asoc->peer.sack_needed = 1; | 264 | asoc->peer.sack_needed = 1; |
265 | asoc->peer.sack_cnt = 0; | ||
264 | 266 | ||
265 | /* Assume that the peer will tell us if he recognizes ASCONF | 267 | /* Assume that the peer will tell us if he recognizes ASCONF |
266 | * as part of INIT exchange. | 268 | * as part of INIT exchange. |
@@ -615,6 +617,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
615 | * association configured value. | 617 | * association configured value. |
616 | */ | 618 | */ |
617 | peer->sackdelay = asoc->sackdelay; | 619 | peer->sackdelay = asoc->sackdelay; |
620 | peer->sackfreq = asoc->sackfreq; | ||
618 | 621 | ||
619 | /* Enable/disable heartbeat, SACK delay, and path MTU discovery | 622 | /* Enable/disable heartbeat, SACK delay, and path MTU discovery |
620 | * based on association setting. | 623 | * based on association setting. |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 0aba759cb9b7..5dd89831eceb 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -383,3 +383,144 @@ void sctp_assocs_proc_exit(void) | |||
383 | { | 383 | { |
384 | remove_proc_entry("assocs", proc_net_sctp); | 384 | remove_proc_entry("assocs", proc_net_sctp); |
385 | } | 385 | } |
386 | |||
387 | static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) | ||
388 | { | ||
389 | if (*pos >= sctp_assoc_hashsize) | ||
390 | return NULL; | ||
391 | |||
392 | if (*pos < 0) | ||
393 | *pos = 0; | ||
394 | |||
395 | if (*pos == 0) | ||
396 | seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " | ||
397 | "REM_ADDR_RTX START\n"); | ||
398 | |||
399 | return (void *)pos; | ||
400 | } | ||
401 | |||
402 | static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
403 | { | ||
404 | if (++*pos >= sctp_assoc_hashsize) | ||
405 | return NULL; | ||
406 | |||
407 | return pos; | ||
408 | } | ||
409 | |||
410 | static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) | ||
411 | { | ||
412 | return; | ||
413 | } | ||
414 | |||
415 | static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) | ||
416 | { | ||
417 | struct sctp_hashbucket *head; | ||
418 | struct sctp_ep_common *epb; | ||
419 | struct sctp_association *assoc; | ||
420 | struct hlist_node *node; | ||
421 | struct sctp_transport *tsp; | ||
422 | int hash = *(loff_t *)v; | ||
423 | |||
424 | if (hash >= sctp_assoc_hashsize) | ||
425 | return -ENOMEM; | ||
426 | |||
427 | head = &sctp_assoc_hashtable[hash]; | ||
428 | sctp_local_bh_disable(); | ||
429 | read_lock(&head->lock); | ||
430 | sctp_for_each_hentry(epb, node, &head->chain) { | ||
431 | assoc = sctp_assoc(epb); | ||
432 | list_for_each_entry(tsp, &assoc->peer.transport_addr_list, | ||
433 | transports) { | ||
434 | /* | ||
435 | * The remote address (ADDR) | ||
436 | */ | ||
437 | tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr); | ||
438 | seq_printf(seq, " "); | ||
439 | |||
440 | /* | ||
441 | * The association ID (ASSOC_ID) | ||
442 | */ | ||
443 | seq_printf(seq, "%d ", tsp->asoc->assoc_id); | ||
444 | |||
445 | /* | ||
446 | * If the Heartbeat is active (HB_ACT) | ||
447 | * Note: 1 = Active, 0 = Inactive | ||
448 | */ | ||
449 | seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer)); | ||
450 | |||
451 | /* | ||
452 | * Retransmit time out (RTO) | ||
453 | */ | ||
454 | seq_printf(seq, "%lu ", tsp->rto); | ||
455 | |||
456 | /* | ||
457 | * Maximum path retransmit count (PATH_MAX_RTX) | ||
458 | */ | ||
459 | seq_printf(seq, "%d ", tsp->pathmaxrxt); | ||
460 | |||
461 | /* | ||
462 | * remote address retransmit count (REM_ADDR_RTX) | ||
463 | * Note: We don't have a way to tally this at the moment | ||
464 | * so lets just leave it as zero for the moment | ||
465 | */ | ||
466 | seq_printf(seq, "0 "); | ||
467 | |||
468 | /* | ||
469 | * remote address start time (START). This is also not | ||
470 | * currently implemented, but we can record it with a | ||
471 | * jiffies marker in a subsequent patch | ||
472 | */ | ||
473 | seq_printf(seq, "0"); | ||
474 | |||
475 | seq_printf(seq, "\n"); | ||
476 | } | ||
477 | } | ||
478 | |||
479 | read_unlock(&head->lock); | ||
480 | sctp_local_bh_enable(); | ||
481 | |||
482 | return 0; | ||
483 | |||
484 | } | ||
485 | |||
486 | static const struct seq_operations sctp_remaddr_ops = { | ||
487 | .start = sctp_remaddr_seq_start, | ||
488 | .next = sctp_remaddr_seq_next, | ||
489 | .stop = sctp_remaddr_seq_stop, | ||
490 | .show = sctp_remaddr_seq_show, | ||
491 | }; | ||
492 | |||
493 | /* Cleanup the proc fs entry for 'remaddr' object. */ | ||
494 | void sctp_remaddr_proc_exit(void) | ||
495 | { | ||
496 | remove_proc_entry("remaddr", proc_net_sctp); | ||
497 | } | ||
498 | |||
499 | static int sctp_remaddr_seq_open(struct inode *inode, struct file *file) | ||
500 | { | ||
501 | return seq_open(file, &sctp_remaddr_ops); | ||
502 | } | ||
503 | |||
504 | static const struct file_operations sctp_remaddr_seq_fops = { | ||
505 | .open = sctp_remaddr_seq_open, | ||
506 | .read = seq_read, | ||
507 | .llseek = seq_lseek, | ||
508 | .release = seq_release, | ||
509 | }; | ||
510 | |||
511 | int __init sctp_remaddr_proc_init(void) | ||
512 | { | ||
513 | struct proc_dir_entry *p; | ||
514 | |||
515 | p = create_proc_entry("remaddr", S_IRUGO, proc_net_sctp); | ||
516 | if (!p) | ||
517 | return -ENOMEM; | ||
518 | p->proc_fops = &sctp_remaddr_seq_fops; | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | void sctp_assoc_proc_exit(void) | ||
524 | { | ||
525 | remove_proc_entry("remaddr", proc_net_sctp); | ||
526 | } | ||
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index b435a193c5df..d6af466091d2 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -113,6 +113,8 @@ static __init int sctp_proc_init(void) | |||
113 | goto out_nomem; | 113 | goto out_nomem; |
114 | if (sctp_assocs_proc_init()) | 114 | if (sctp_assocs_proc_init()) |
115 | goto out_nomem; | 115 | goto out_nomem; |
116 | if (sctp_remaddr_proc_init()) | ||
117 | goto out_nomem; | ||
116 | 118 | ||
117 | return 0; | 119 | return 0; |
118 | 120 | ||
@@ -129,6 +131,7 @@ static void sctp_proc_exit(void) | |||
129 | sctp_snmp_proc_exit(); | 131 | sctp_snmp_proc_exit(); |
130 | sctp_eps_proc_exit(); | 132 | sctp_eps_proc_exit(); |
131 | sctp_assocs_proc_exit(); | 133 | sctp_assocs_proc_exit(); |
134 | sctp_remaddr_proc_exit(); | ||
132 | 135 | ||
133 | if (proc_net_sctp) { | 136 | if (proc_net_sctp) { |
134 | proc_net_sctp = NULL; | 137 | proc_net_sctp = NULL; |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 23a9f1a95b7d..b083312c725a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -190,20 +190,28 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force, | |||
190 | * unacknowledged DATA chunk. ... | 190 | * unacknowledged DATA chunk. ... |
191 | */ | 191 | */ |
192 | if (!asoc->peer.sack_needed) { | 192 | if (!asoc->peer.sack_needed) { |
193 | /* We will need a SACK for the next packet. */ | 193 | asoc->peer.sack_cnt++; |
194 | asoc->peer.sack_needed = 1; | ||
195 | 194 | ||
196 | /* Set the SACK delay timeout based on the | 195 | /* Set the SACK delay timeout based on the |
197 | * SACK delay for the last transport | 196 | * SACK delay for the last transport |
198 | * data was received from, or the default | 197 | * data was received from, or the default |
199 | * for the association. | 198 | * for the association. |
200 | */ | 199 | */ |
201 | if (trans) | 200 | if (trans) { |
201 | /* We will need a SACK for the next packet. */ | ||
202 | if (asoc->peer.sack_cnt >= trans->sackfreq - 1) | ||
203 | asoc->peer.sack_needed = 1; | ||
204 | |||
202 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = | 205 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = |
203 | trans->sackdelay; | 206 | trans->sackdelay; |
204 | else | 207 | } else { |
208 | /* We will need a SACK for the next packet. */ | ||
209 | if (asoc->peer.sack_cnt >= asoc->sackfreq - 1) | ||
210 | asoc->peer.sack_needed = 1; | ||
211 | |||
205 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = | 212 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = |
206 | asoc->sackdelay; | 213 | asoc->sackdelay; |
214 | } | ||
207 | 215 | ||
208 | /* Restart the SACK timer. */ | 216 | /* Restart the SACK timer. */ |
209 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 217 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
@@ -216,6 +224,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force, | |||
216 | goto nomem; | 224 | goto nomem; |
217 | 225 | ||
218 | asoc->peer.sack_needed = 0; | 226 | asoc->peer.sack_needed = 0; |
227 | asoc->peer.sack_cnt = 0; | ||
219 | 228 | ||
220 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack)); | 229 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack)); |
221 | 230 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e7e3baf7009e..253e5ea7e1e8 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -956,7 +956,8 @@ out: | |||
956 | */ | 956 | */ |
957 | static int __sctp_connect(struct sock* sk, | 957 | static int __sctp_connect(struct sock* sk, |
958 | struct sockaddr *kaddrs, | 958 | struct sockaddr *kaddrs, |
959 | int addrs_size) | 959 | int addrs_size, |
960 | sctp_assoc_t *assoc_id) | ||
960 | { | 961 | { |
961 | struct sctp_sock *sp; | 962 | struct sctp_sock *sp; |
962 | struct sctp_endpoint *ep; | 963 | struct sctp_endpoint *ep; |
@@ -1111,6 +1112,8 @@ static int __sctp_connect(struct sock* sk, | |||
1111 | timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); | 1112 | timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); |
1112 | 1113 | ||
1113 | err = sctp_wait_for_connect(asoc, &timeo); | 1114 | err = sctp_wait_for_connect(asoc, &timeo); |
1115 | if (!err && assoc_id) | ||
1116 | *assoc_id = asoc->assoc_id; | ||
1114 | 1117 | ||
1115 | /* Don't free association on exit. */ | 1118 | /* Don't free association on exit. */ |
1116 | asoc = NULL; | 1119 | asoc = NULL; |
@@ -1128,7 +1131,8 @@ out_free: | |||
1128 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() | 1131 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() |
1129 | * | 1132 | * |
1130 | * API 8.9 | 1133 | * API 8.9 |
1131 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt); | 1134 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt, |
1135 | * sctp_assoc_t *asoc); | ||
1132 | * | 1136 | * |
1133 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. | 1137 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. |
1134 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 | 1138 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 |
@@ -1144,8 +1148,10 @@ out_free: | |||
1144 | * representation is termed a "packed array" of addresses). The caller | 1148 | * representation is termed a "packed array" of addresses). The caller |
1145 | * specifies the number of addresses in the array with addrcnt. | 1149 | * specifies the number of addresses in the array with addrcnt. |
1146 | * | 1150 | * |
1147 | * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns | 1151 | * On success, sctp_connectx() returns 0. It also sets the assoc_id to |
1148 | * -1, and sets errno to the appropriate error code. | 1152 | * the association id of the new association. On failure, sctp_connectx() |
1153 | * returns -1, and sets errno to the appropriate error code. The assoc_id | ||
1154 | * is not touched by the kernel. | ||
1149 | * | 1155 | * |
1150 | * For SCTP, the port given in each socket address must be the same, or | 1156 | * For SCTP, the port given in each socket address must be the same, or |
1151 | * sctp_connectx() will fail, setting errno to EINVAL. | 1157 | * sctp_connectx() will fail, setting errno to EINVAL. |
@@ -1182,11 +1188,12 @@ out_free: | |||
1182 | * addrs The pointer to the addresses in user land | 1188 | * addrs The pointer to the addresses in user land |
1183 | * addrssize Size of the addrs buffer | 1189 | * addrssize Size of the addrs buffer |
1184 | * | 1190 | * |
1185 | * Returns 0 if ok, <0 errno code on error. | 1191 | * Returns >=0 if ok, <0 errno code on error. |
1186 | */ | 1192 | */ |
1187 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | 1193 | SCTP_STATIC int __sctp_setsockopt_connectx(struct sock* sk, |
1188 | struct sockaddr __user *addrs, | 1194 | struct sockaddr __user *addrs, |
1189 | int addrs_size) | 1195 | int addrs_size, |
1196 | sctp_assoc_t *assoc_id) | ||
1190 | { | 1197 | { |
1191 | int err = 0; | 1198 | int err = 0; |
1192 | struct sockaddr *kaddrs; | 1199 | struct sockaddr *kaddrs; |
@@ -1209,13 +1216,46 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | |||
1209 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | 1216 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { |
1210 | err = -EFAULT; | 1217 | err = -EFAULT; |
1211 | } else { | 1218 | } else { |
1212 | err = __sctp_connect(sk, kaddrs, addrs_size); | 1219 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); |
1213 | } | 1220 | } |
1214 | 1221 | ||
1215 | kfree(kaddrs); | 1222 | kfree(kaddrs); |
1223 | |||
1216 | return err; | 1224 | return err; |
1217 | } | 1225 | } |
1218 | 1226 | ||
1227 | /* | ||
1228 | * This is an older interface. It's kept for backward compatibility | ||
1229 | * to the option that doesn't provide association id. | ||
1230 | */ | ||
1231 | SCTP_STATIC int sctp_setsockopt_connectx_old(struct sock* sk, | ||
1232 | struct sockaddr __user *addrs, | ||
1233 | int addrs_size) | ||
1234 | { | ||
1235 | return __sctp_setsockopt_connectx(sk, addrs, addrs_size, NULL); | ||
1236 | } | ||
1237 | |||
1238 | /* | ||
1239 | * New interface for the API. The since the API is done with a socket | ||
1240 | * option, to make it simple we feed back the association id is as a return | ||
1241 | * indication to the call. Error is always negative and association id is | ||
1242 | * always positive. | ||
1243 | */ | ||
1244 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | ||
1245 | struct sockaddr __user *addrs, | ||
1246 | int addrs_size) | ||
1247 | { | ||
1248 | sctp_assoc_t assoc_id = 0; | ||
1249 | int err = 0; | ||
1250 | |||
1251 | err = __sctp_setsockopt_connectx(sk, addrs, addrs_size, &assoc_id); | ||
1252 | |||
1253 | if (err) | ||
1254 | return err; | ||
1255 | else | ||
1256 | return assoc_id; | ||
1257 | } | ||
1258 | |||
1219 | /* API 3.1.4 close() - UDP Style Syntax | 1259 | /* API 3.1.4 close() - UDP Style Syntax |
1220 | * Applications use close() to perform graceful shutdown (as described in | 1260 | * Applications use close() to perform graceful shutdown (as described in |
1221 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1261 | * Section 10.1 of [SCTP]) on ALL the associations currently represented |
@@ -2305,74 +2345,98 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
2305 | return 0; | 2345 | return 0; |
2306 | } | 2346 | } |
2307 | 2347 | ||
2308 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 2348 | /* |
2309 | * | 2349 | * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK) |
2310 | * This options will get or set the delayed ack timer. The time is set | 2350 | * |
2311 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 2351 | * This option will effect the way delayed acks are performed. This |
2312 | * endpoints default delayed ack timer value. If the assoc_id field is | 2352 | * option allows you to get or set the delayed ack time, in |
2313 | * non-zero, then the set or get effects the specified association. | 2353 | * milliseconds. It also allows changing the delayed ack frequency. |
2314 | * | 2354 | * Changing the frequency to 1 disables the delayed sack algorithm. If |
2315 | * struct sctp_assoc_value { | 2355 | * the assoc_id is 0, then this sets or gets the endpoints default |
2316 | * sctp_assoc_t assoc_id; | 2356 | * values. If the assoc_id field is non-zero, then the set or get |
2317 | * uint32_t assoc_value; | 2357 | * effects the specified association for the one to many model (the |
2318 | * }; | 2358 | * assoc_id field is ignored by the one to one model). Note that if |
2359 | * sack_delay or sack_freq are 0 when setting this option, then the | ||
2360 | * current values will remain unchanged. | ||
2361 | * | ||
2362 | * struct sctp_sack_info { | ||
2363 | * sctp_assoc_t sack_assoc_id; | ||
2364 | * uint32_t sack_delay; | ||
2365 | * uint32_t sack_freq; | ||
2366 | * }; | ||
2319 | * | 2367 | * |
2320 | * assoc_id - This parameter, indicates which association the | 2368 | * sack_assoc_id - This parameter, indicates which association the user |
2321 | * user is preforming an action upon. Note that if | 2369 | * is performing an action upon. Note that if this field's value is |
2322 | * this field's value is zero then the endpoints | 2370 | * zero then the endpoints default value is changed (effecting future |
2323 | * default value is changed (effecting future | 2371 | * associations only). |
2324 | * associations only). | ||
2325 | * | 2372 | * |
2326 | * assoc_value - This parameter contains the number of milliseconds | 2373 | * sack_delay - This parameter contains the number of milliseconds that |
2327 | * that the user is requesting the delayed ACK timer | 2374 | * the user is requesting the delayed ACK timer be set to. Note that |
2328 | * be set to. Note that this value is defined in | 2375 | * this value is defined in the standard to be between 200 and 500 |
2329 | * the standard to be between 200 and 500 milliseconds. | 2376 | * milliseconds. |
2330 | * | 2377 | * |
2331 | * Note: a value of zero will leave the value alone, | 2378 | * sack_freq - This parameter contains the number of packets that must |
2332 | * but disable SACK delay. A non-zero value will also | 2379 | * be received before a sack is sent without waiting for the delay |
2333 | * enable SACK delay. | 2380 | * timer to expire. The default value for this is 2, setting this |
2381 | * value to 1 will disable the delayed sack algorithm. | ||
2334 | */ | 2382 | */ |
2335 | 2383 | ||
2336 | static int sctp_setsockopt_delayed_ack_time(struct sock *sk, | 2384 | static int sctp_setsockopt_delayed_ack(struct sock *sk, |
2337 | char __user *optval, int optlen) | 2385 | char __user *optval, int optlen) |
2338 | { | 2386 | { |
2339 | struct sctp_assoc_value params; | 2387 | struct sctp_sack_info params; |
2340 | struct sctp_transport *trans = NULL; | 2388 | struct sctp_transport *trans = NULL; |
2341 | struct sctp_association *asoc = NULL; | 2389 | struct sctp_association *asoc = NULL; |
2342 | struct sctp_sock *sp = sctp_sk(sk); | 2390 | struct sctp_sock *sp = sctp_sk(sk); |
2343 | 2391 | ||
2344 | if (optlen != sizeof(struct sctp_assoc_value)) | 2392 | if (optlen == sizeof(struct sctp_sack_info)) { |
2345 | return - EINVAL; | 2393 | if (copy_from_user(¶ms, optval, optlen)) |
2394 | return -EFAULT; | ||
2346 | 2395 | ||
2347 | if (copy_from_user(¶ms, optval, optlen)) | 2396 | if (params.sack_delay == 0 && params.sack_freq == 0) |
2348 | return -EFAULT; | 2397 | return 0; |
2398 | } else if (optlen == sizeof(struct sctp_assoc_value)) { | ||
2399 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | ||
2400 | "in delayed_ack socket option deprecated\n"); | ||
2401 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | ||
2402 | if (copy_from_user(¶ms, optval, optlen)) | ||
2403 | return -EFAULT; | ||
2404 | |||
2405 | if (params.sack_delay == 0) | ||
2406 | params.sack_freq = 1; | ||
2407 | else | ||
2408 | params.sack_freq = 0; | ||
2409 | } else | ||
2410 | return - EINVAL; | ||
2349 | 2411 | ||
2350 | /* Validate value parameter. */ | 2412 | /* Validate value parameter. */ |
2351 | if (params.assoc_value > 500) | 2413 | if (params.sack_delay > 500) |
2352 | return -EINVAL; | 2414 | return -EINVAL; |
2353 | 2415 | ||
2354 | /* Get association, if assoc_id != 0 and the socket is a one | 2416 | /* Get association, if sack_assoc_id != 0 and the socket is a one |
2355 | * to many style socket, and an association was not found, then | 2417 | * to many style socket, and an association was not found, then |
2356 | * the id was invalid. | 2418 | * the id was invalid. |
2357 | */ | 2419 | */ |
2358 | asoc = sctp_id2assoc(sk, params.assoc_id); | 2420 | asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
2359 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | 2421 | if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
2360 | return -EINVAL; | 2422 | return -EINVAL; |
2361 | 2423 | ||
2362 | if (params.assoc_value) { | 2424 | if (params.sack_delay) { |
2363 | if (asoc) { | 2425 | if (asoc) { |
2364 | asoc->sackdelay = | 2426 | asoc->sackdelay = |
2365 | msecs_to_jiffies(params.assoc_value); | 2427 | msecs_to_jiffies(params.sack_delay); |
2366 | asoc->param_flags = | 2428 | asoc->param_flags = |
2367 | (asoc->param_flags & ~SPP_SACKDELAY) | | 2429 | (asoc->param_flags & ~SPP_SACKDELAY) | |
2368 | SPP_SACKDELAY_ENABLE; | 2430 | SPP_SACKDELAY_ENABLE; |
2369 | } else { | 2431 | } else { |
2370 | sp->sackdelay = params.assoc_value; | 2432 | sp->sackdelay = params.sack_delay; |
2371 | sp->param_flags = | 2433 | sp->param_flags = |
2372 | (sp->param_flags & ~SPP_SACKDELAY) | | 2434 | (sp->param_flags & ~SPP_SACKDELAY) | |
2373 | SPP_SACKDELAY_ENABLE; | 2435 | SPP_SACKDELAY_ENABLE; |
2374 | } | 2436 | } |
2375 | } else { | 2437 | } |
2438 | |||
2439 | if (params.sack_freq == 1) { | ||
2376 | if (asoc) { | 2440 | if (asoc) { |
2377 | asoc->param_flags = | 2441 | asoc->param_flags = |
2378 | (asoc->param_flags & ~SPP_SACKDELAY) | | 2442 | (asoc->param_flags & ~SPP_SACKDELAY) | |
@@ -2382,22 +2446,40 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk, | |||
2382 | (sp->param_flags & ~SPP_SACKDELAY) | | 2446 | (sp->param_flags & ~SPP_SACKDELAY) | |
2383 | SPP_SACKDELAY_DISABLE; | 2447 | SPP_SACKDELAY_DISABLE; |
2384 | } | 2448 | } |
2449 | } else if (params.sack_freq > 1) { | ||
2450 | if (asoc) { | ||
2451 | asoc->sackfreq = params.sack_freq; | ||
2452 | asoc->param_flags = | ||
2453 | (asoc->param_flags & ~SPP_SACKDELAY) | | ||
2454 | SPP_SACKDELAY_ENABLE; | ||
2455 | } else { | ||
2456 | sp->sackfreq = params.sack_freq; | ||
2457 | sp->param_flags = | ||
2458 | (sp->param_flags & ~SPP_SACKDELAY) | | ||
2459 | SPP_SACKDELAY_ENABLE; | ||
2460 | } | ||
2385 | } | 2461 | } |
2386 | 2462 | ||
2387 | /* If change is for association, also apply to each transport. */ | 2463 | /* If change is for association, also apply to each transport. */ |
2388 | if (asoc) { | 2464 | if (asoc) { |
2389 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, | 2465 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, |
2390 | transports) { | 2466 | transports) { |
2391 | if (params.assoc_value) { | 2467 | if (params.sack_delay) { |
2392 | trans->sackdelay = | 2468 | trans->sackdelay = |
2393 | msecs_to_jiffies(params.assoc_value); | 2469 | msecs_to_jiffies(params.sack_delay); |
2394 | trans->param_flags = | 2470 | trans->param_flags = |
2395 | (trans->param_flags & ~SPP_SACKDELAY) | | 2471 | (trans->param_flags & ~SPP_SACKDELAY) | |
2396 | SPP_SACKDELAY_ENABLE; | 2472 | SPP_SACKDELAY_ENABLE; |
2397 | } else { | 2473 | } |
2474 | if (params.sack_freq == 1) { | ||
2398 | trans->param_flags = | 2475 | trans->param_flags = |
2399 | (trans->param_flags & ~SPP_SACKDELAY) | | 2476 | (trans->param_flags & ~SPP_SACKDELAY) | |
2400 | SPP_SACKDELAY_DISABLE; | 2477 | SPP_SACKDELAY_DISABLE; |
2478 | } else if (params.sack_freq > 1) { | ||
2479 | trans->sackfreq = params.sack_freq; | ||
2480 | trans->param_flags = | ||
2481 | (trans->param_flags & ~SPP_SACKDELAY) | | ||
2482 | SPP_SACKDELAY_ENABLE; | ||
2401 | } | 2483 | } |
2402 | } | 2484 | } |
2403 | } | 2485 | } |
@@ -3164,10 +3246,18 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3164 | optlen, SCTP_BINDX_REM_ADDR); | 3246 | optlen, SCTP_BINDX_REM_ADDR); |
3165 | break; | 3247 | break; |
3166 | 3248 | ||
3249 | case SCTP_SOCKOPT_CONNECTX_OLD: | ||
3250 | /* 'optlen' is the size of the addresses buffer. */ | ||
3251 | retval = sctp_setsockopt_connectx_old(sk, | ||
3252 | (struct sockaddr __user *)optval, | ||
3253 | optlen); | ||
3254 | break; | ||
3255 | |||
3167 | case SCTP_SOCKOPT_CONNECTX: | 3256 | case SCTP_SOCKOPT_CONNECTX: |
3168 | /* 'optlen' is the size of the addresses buffer. */ | 3257 | /* 'optlen' is the size of the addresses buffer. */ |
3169 | retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval, | 3258 | retval = sctp_setsockopt_connectx(sk, |
3170 | optlen); | 3259 | (struct sockaddr __user *)optval, |
3260 | optlen); | ||
3171 | break; | 3261 | break; |
3172 | 3262 | ||
3173 | case SCTP_DISABLE_FRAGMENTS: | 3263 | case SCTP_DISABLE_FRAGMENTS: |
@@ -3186,8 +3276,8 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3186 | retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); | 3276 | retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); |
3187 | break; | 3277 | break; |
3188 | 3278 | ||
3189 | case SCTP_DELAYED_ACK_TIME: | 3279 | case SCTP_DELAYED_ACK: |
3190 | retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen); | 3280 | retval = sctp_setsockopt_delayed_ack(sk, optval, optlen); |
3191 | break; | 3281 | break; |
3192 | case SCTP_PARTIAL_DELIVERY_POINT: | 3282 | case SCTP_PARTIAL_DELIVERY_POINT: |
3193 | retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); | 3283 | retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); |
@@ -3294,7 +3384,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, | |||
3294 | /* Pass correct addr len to common routine (so it knows there | 3384 | /* Pass correct addr len to common routine (so it knows there |
3295 | * is only one address being passed. | 3385 | * is only one address being passed. |
3296 | */ | 3386 | */ |
3297 | err = __sctp_connect(sk, addr, af->sockaddr_len); | 3387 | err = __sctp_connect(sk, addr, af->sockaddr_len, NULL); |
3298 | } | 3388 | } |
3299 | 3389 | ||
3300 | sctp_release_sock(sk); | 3390 | sctp_release_sock(sk); |
@@ -3446,6 +3536,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3446 | sp->pathmaxrxt = sctp_max_retrans_path; | 3536 | sp->pathmaxrxt = sctp_max_retrans_path; |
3447 | sp->pathmtu = 0; // allow default discovery | 3537 | sp->pathmtu = 0; // allow default discovery |
3448 | sp->sackdelay = sctp_sack_timeout; | 3538 | sp->sackdelay = sctp_sack_timeout; |
3539 | sp->sackfreq = 2; | ||
3449 | sp->param_flags = SPP_HB_ENABLE | | 3540 | sp->param_flags = SPP_HB_ENABLE | |
3450 | SPP_PMTUD_ENABLE | | 3541 | SPP_PMTUD_ENABLE | |
3451 | SPP_SACKDELAY_ENABLE; | 3542 | SPP_SACKDELAY_ENABLE; |
@@ -3999,70 +4090,91 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
3999 | return 0; | 4090 | return 0; |
4000 | } | 4091 | } |
4001 | 4092 | ||
4002 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 4093 | /* |
4003 | * | 4094 | * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK) |
4004 | * This options will get or set the delayed ack timer. The time is set | 4095 | * |
4005 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 4096 | * This option will effect the way delayed acks are performed. This |
4006 | * endpoints default delayed ack timer value. If the assoc_id field is | 4097 | * option allows you to get or set the delayed ack time, in |
4007 | * non-zero, then the set or get effects the specified association. | 4098 | * milliseconds. It also allows changing the delayed ack frequency. |
4008 | * | 4099 | * Changing the frequency to 1 disables the delayed sack algorithm. If |
4009 | * struct sctp_assoc_value { | 4100 | * the assoc_id is 0, then this sets or gets the endpoints default |
4010 | * sctp_assoc_t assoc_id; | 4101 | * values. If the assoc_id field is non-zero, then the set or get |
4011 | * uint32_t assoc_value; | 4102 | * effects the specified association for the one to many model (the |
4012 | * }; | 4103 | * assoc_id field is ignored by the one to one model). Note that if |
4104 | * sack_delay or sack_freq are 0 when setting this option, then the | ||
4105 | * current values will remain unchanged. | ||
4106 | * | ||
4107 | * struct sctp_sack_info { | ||
4108 | * sctp_assoc_t sack_assoc_id; | ||
4109 | * uint32_t sack_delay; | ||
4110 | * uint32_t sack_freq; | ||
4111 | * }; | ||
4013 | * | 4112 | * |
4014 | * assoc_id - This parameter, indicates which association the | 4113 | * sack_assoc_id - This parameter, indicates which association the user |
4015 | * user is preforming an action upon. Note that if | 4114 | * is performing an action upon. Note that if this field's value is |
4016 | * this field's value is zero then the endpoints | 4115 | * zero then the endpoints default value is changed (effecting future |
4017 | * default value is changed (effecting future | 4116 | * associations only). |
4018 | * associations only). | ||
4019 | * | 4117 | * |
4020 | * assoc_value - This parameter contains the number of milliseconds | 4118 | * sack_delay - This parameter contains the number of milliseconds that |
4021 | * that the user is requesting the delayed ACK timer | 4119 | * the user is requesting the delayed ACK timer be set to. Note that |
4022 | * be set to. Note that this value is defined in | 4120 | * this value is defined in the standard to be between 200 and 500 |
4023 | * the standard to be between 200 and 500 milliseconds. | 4121 | * milliseconds. |
4024 | * | 4122 | * |
4025 | * Note: a value of zero will leave the value alone, | 4123 | * sack_freq - This parameter contains the number of packets that must |
4026 | * but disable SACK delay. A non-zero value will also | 4124 | * be received before a sack is sent without waiting for the delay |
4027 | * enable SACK delay. | 4125 | * timer to expire. The default value for this is 2, setting this |
4126 | * value to 1 will disable the delayed sack algorithm. | ||
4028 | */ | 4127 | */ |
4029 | static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len, | 4128 | static int sctp_getsockopt_delayed_ack(struct sock *sk, int len, |
4030 | char __user *optval, | 4129 | char __user *optval, |
4031 | int __user *optlen) | 4130 | int __user *optlen) |
4032 | { | 4131 | { |
4033 | struct sctp_assoc_value params; | 4132 | struct sctp_sack_info params; |
4034 | struct sctp_association *asoc = NULL; | 4133 | struct sctp_association *asoc = NULL; |
4035 | struct sctp_sock *sp = sctp_sk(sk); | 4134 | struct sctp_sock *sp = sctp_sk(sk); |
4036 | 4135 | ||
4037 | if (len < sizeof(struct sctp_assoc_value)) | 4136 | if (len >= sizeof(struct sctp_sack_info)) { |
4038 | return - EINVAL; | 4137 | len = sizeof(struct sctp_sack_info); |
4039 | |||
4040 | len = sizeof(struct sctp_assoc_value); | ||
4041 | 4138 | ||
4042 | if (copy_from_user(¶ms, optval, len)) | 4139 | if (copy_from_user(¶ms, optval, len)) |
4043 | return -EFAULT; | 4140 | return -EFAULT; |
4141 | } else if (len == sizeof(struct sctp_assoc_value)) { | ||
4142 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | ||
4143 | "in delayed_ack socket option deprecated\n"); | ||
4144 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | ||
4145 | if (copy_from_user(¶ms, optval, len)) | ||
4146 | return -EFAULT; | ||
4147 | } else | ||
4148 | return - EINVAL; | ||
4044 | 4149 | ||
4045 | /* Get association, if assoc_id != 0 and the socket is a one | 4150 | /* Get association, if sack_assoc_id != 0 and the socket is a one |
4046 | * to many style socket, and an association was not found, then | 4151 | * to many style socket, and an association was not found, then |
4047 | * the id was invalid. | 4152 | * the id was invalid. |
4048 | */ | 4153 | */ |
4049 | asoc = sctp_id2assoc(sk, params.assoc_id); | 4154 | asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
4050 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | 4155 | if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
4051 | return -EINVAL; | 4156 | return -EINVAL; |
4052 | 4157 | ||
4053 | if (asoc) { | 4158 | if (asoc) { |
4054 | /* Fetch association values. */ | 4159 | /* Fetch association values. */ |
4055 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) | 4160 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) { |
4056 | params.assoc_value = jiffies_to_msecs( | 4161 | params.sack_delay = jiffies_to_msecs( |
4057 | asoc->sackdelay); | 4162 | asoc->sackdelay); |
4058 | else | 4163 | params.sack_freq = asoc->sackfreq; |
4059 | params.assoc_value = 0; | 4164 | |
4165 | } else { | ||
4166 | params.sack_delay = 0; | ||
4167 | params.sack_freq = 1; | ||
4168 | } | ||
4060 | } else { | 4169 | } else { |
4061 | /* Fetch socket values. */ | 4170 | /* Fetch socket values. */ |
4062 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) | 4171 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) { |
4063 | params.assoc_value = sp->sackdelay; | 4172 | params.sack_delay = sp->sackdelay; |
4064 | else | 4173 | params.sack_freq = sp->sackfreq; |
4065 | params.assoc_value = 0; | 4174 | } else { |
4175 | params.sack_delay = 0; | ||
4176 | params.sack_freq = 1; | ||
4177 | } | ||
4066 | } | 4178 | } |
4067 | 4179 | ||
4068 | if (copy_to_user(optval, ¶ms, len)) | 4180 | if (copy_to_user(optval, ¶ms, len)) |
@@ -5218,8 +5330,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5218 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, | 5330 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, |
5219 | optlen); | 5331 | optlen); |
5220 | break; | 5332 | break; |
5221 | case SCTP_DELAYED_ACK_TIME: | 5333 | case SCTP_DELAYED_ACK: |
5222 | retval = sctp_getsockopt_delayed_ack_time(sk, len, optval, | 5334 | retval = sctp_getsockopt_delayed_ack(sk, len, optval, |
5223 | optlen); | 5335 | optlen); |
5224 | break; | 5336 | break; |
5225 | case SCTP_INITMSG: | 5337 | case SCTP_INITMSG: |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index cc12d5f5d5da..019d4b4478c9 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -33,8 +33,6 @@ | |||
33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
34 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 34 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | * | ||
37 | * $Id$ | ||
38 | */ | 36 | */ |
39 | 37 | ||
40 | 38 | ||
diff --git a/net/sysctl_net.c b/net/sysctl_net.c index b4f0525f91af..007c1a6708ee 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c | |||
@@ -4,7 +4,6 @@ | |||
4 | * Begun April 1, 1996, Mike Shaver. | 4 | * Begun April 1, 1996, Mike Shaver. |
5 | * Added /proc/sys/net directories for each protocol family. [MS] | 5 | * Added /proc/sys/net directories for each protocol family. [MS] |
6 | * | 6 | * |
7 | * $Log: sysctl_net.c,v $ | ||
8 | * Revision 1.2 1996/05/08 20:24:40 shaver | 7 | * Revision 1.2 1996/05/08 20:24:40 shaver |
9 | * Added bits for NET_BRIDGE and the NET_IPV4_ARP stuff and | 8 | * Added bits for NET_BRIDGE and the NET_IPV4_ARP stuff and |
10 | * NET_IPV4_IP_FORWARD. | 9 | * NET_IPV4_IP_FORWARD. |
@@ -40,6 +39,27 @@ static struct ctl_table_root net_sysctl_root = { | |||
40 | .lookup = net_ctl_header_lookup, | 39 | .lookup = net_ctl_header_lookup, |
41 | }; | 40 | }; |
42 | 41 | ||
42 | static LIST_HEAD(net_sysctl_ro_tables); | ||
43 | static struct list_head *net_ctl_ro_header_lookup(struct ctl_table_root *root, | ||
44 | struct nsproxy *namespaces) | ||
45 | { | ||
46 | return &net_sysctl_ro_tables; | ||
47 | } | ||
48 | |||
49 | static int net_ctl_ro_header_perms(struct ctl_table_root *root, | ||
50 | struct nsproxy *namespaces, struct ctl_table *table) | ||
51 | { | ||
52 | if (namespaces->net_ns == &init_net) | ||
53 | return table->mode; | ||
54 | else | ||
55 | return table->mode & ~0222; | ||
56 | } | ||
57 | |||
58 | static struct ctl_table_root net_sysctl_ro_root = { | ||
59 | .lookup = net_ctl_ro_header_lookup, | ||
60 | .permissions = net_ctl_ro_header_perms, | ||
61 | }; | ||
62 | |||
43 | static int sysctl_net_init(struct net *net) | 63 | static int sysctl_net_init(struct net *net) |
44 | { | 64 | { |
45 | INIT_LIST_HEAD(&net->sysctl_table_headers); | 65 | INIT_LIST_HEAD(&net->sysctl_table_headers); |
@@ -64,6 +84,7 @@ static __init int sysctl_init(void) | |||
64 | if (ret) | 84 | if (ret) |
65 | goto out; | 85 | goto out; |
66 | register_sysctl_root(&net_sysctl_root); | 86 | register_sysctl_root(&net_sysctl_root); |
87 | register_sysctl_root(&net_sysctl_ro_root); | ||
67 | out: | 88 | out: |
68 | return ret; | 89 | return ret; |
69 | } | 90 | } |
@@ -80,6 +101,14 @@ struct ctl_table_header *register_net_sysctl_table(struct net *net, | |||
80 | } | 101 | } |
81 | EXPORT_SYMBOL_GPL(register_net_sysctl_table); | 102 | EXPORT_SYMBOL_GPL(register_net_sysctl_table); |
82 | 103 | ||
104 | struct ctl_table_header *register_net_sysctl_rotable(const | ||
105 | struct ctl_path *path, struct ctl_table *table) | ||
106 | { | ||
107 | return __register_sysctl_paths(&net_sysctl_ro_root, | ||
108 | &init_nsproxy, path, table); | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(register_net_sysctl_rotable); | ||
111 | |||
83 | void unregister_net_sysctl_table(struct ctl_table_header *header) | 112 | void unregister_net_sysctl_table(struct ctl_table_header *header) |
84 | { | 113 | { |
85 | unregister_sysctl_table(header); | 114 | unregister_sysctl_table(header); |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index e7880172ef19..a5883b1452ff 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -276,7 +276,7 @@ static void bclink_send_nack(struct node *n_ptr) | |||
276 | if (buf) { | 276 | if (buf) { |
277 | msg = buf_msg(buf); | 277 | msg = buf_msg(buf); |
278 | msg_init(msg, BCAST_PROTOCOL, STATE_MSG, | 278 | msg_init(msg, BCAST_PROTOCOL, STATE_MSG, |
279 | TIPC_OK, INT_H_SIZE, n_ptr->addr); | 279 | INT_H_SIZE, n_ptr->addr); |
280 | msg_set_mc_netid(msg, tipc_net_id); | 280 | msg_set_mc_netid(msg, tipc_net_id); |
281 | msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); | 281 | msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); |
282 | msg_set_bcgap_after(msg, n_ptr->bclink.gap_after); | 282 | msg_set_bcgap_after(msg, n_ptr->bclink.gap_after); |
@@ -571,7 +571,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
571 | assert(tipc_cltr_bcast_nodes.count != 0); | 571 | assert(tipc_cltr_bcast_nodes.count != 0); |
572 | bcbuf_set_acks(buf, tipc_cltr_bcast_nodes.count); | 572 | bcbuf_set_acks(buf, tipc_cltr_bcast_nodes.count); |
573 | msg = buf_msg(buf); | 573 | msg = buf_msg(buf); |
574 | msg_set_non_seq(msg); | 574 | msg_set_non_seq(msg, 1); |
575 | msg_set_mc_netid(msg, tipc_net_id); | 575 | msg_set_mc_netid(msg, tipc_net_id); |
576 | } | 576 | } |
577 | 577 | ||
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c index 4bb3404f610b..bc1db474fe01 100644 --- a/net/tipc/cluster.c +++ b/net/tipc/cluster.c | |||
@@ -238,7 +238,7 @@ static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest) | |||
238 | if (buf) { | 238 | if (buf) { |
239 | msg = buf_msg(buf); | 239 | msg = buf_msg(buf); |
240 | memset((char *)msg, 0, size); | 240 | memset((char *)msg, 0, size); |
241 | msg_init(msg, ROUTE_DISTRIBUTOR, 0, TIPC_OK, INT_H_SIZE, dest); | 241 | msg_init(msg, ROUTE_DISTRIBUTOR, 0, INT_H_SIZE, dest); |
242 | } | 242 | } |
243 | return buf; | 243 | return buf; |
244 | } | 244 | } |
diff --git a/net/tipc/config.c b/net/tipc/config.c index c71337a22d33..ca3544d030c7 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/config.c: TIPC configuration management code | 2 | * net/tipc/config.c: TIPC configuration management code |
3 | * | 3 | * |
4 | * Copyright (c) 2002-2006, Ericsson AB | 4 | * Copyright (c) 2002-2006, Ericsson AB |
5 | * Copyright (c) 2004-2006, Wind River Systems | 5 | * Copyright (c) 2004-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -293,7 +293,6 @@ static struct sk_buff *cfg_set_own_addr(void) | |||
293 | if (tipc_mode == TIPC_NET_MODE) | 293 | if (tipc_mode == TIPC_NET_MODE) |
294 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 294 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
295 | " (cannot change node address once assigned)"); | 295 | " (cannot change node address once assigned)"); |
296 | tipc_own_addr = addr; | ||
297 | 296 | ||
298 | /* | 297 | /* |
299 | * Must release all spinlocks before calling start_net() because | 298 | * Must release all spinlocks before calling start_net() because |
@@ -306,7 +305,7 @@ static struct sk_buff *cfg_set_own_addr(void) | |||
306 | */ | 305 | */ |
307 | 306 | ||
308 | spin_unlock_bh(&config_lock); | 307 | spin_unlock_bh(&config_lock); |
309 | tipc_core_start_net(); | 308 | tipc_core_start_net(addr); |
310 | spin_lock_bh(&config_lock); | 309 | spin_lock_bh(&config_lock); |
311 | return tipc_cfg_reply_none(); | 310 | return tipc_cfg_reply_none(); |
312 | } | 311 | } |
@@ -529,7 +528,7 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
529 | break; | 528 | break; |
530 | #endif | 529 | #endif |
531 | case TIPC_CMD_SET_LOG_SIZE: | 530 | case TIPC_CMD_SET_LOG_SIZE: |
532 | rep_tlv_buf = tipc_log_resize(req_tlv_area, req_tlv_space); | 531 | rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space); |
533 | break; | 532 | break; |
534 | case TIPC_CMD_DUMP_LOG: | 533 | case TIPC_CMD_DUMP_LOG: |
535 | rep_tlv_buf = tipc_log_dump(); | 534 | rep_tlv_buf = tipc_log_dump(); |
@@ -602,6 +601,10 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
602 | case TIPC_CMD_GET_NETID: | 601 | case TIPC_CMD_GET_NETID: |
603 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); | 602 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); |
604 | break; | 603 | break; |
604 | case TIPC_CMD_NOT_NET_ADMIN: | ||
605 | rep_tlv_buf = | ||
606 | tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); | ||
607 | break; | ||
605 | default: | 608 | default: |
606 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 609 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
607 | " (unknown command)"); | 610 | " (unknown command)"); |
diff --git a/net/tipc/core.c b/net/tipc/core.c index 740aac5cdfb6..3256bd7d398f 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #include "config.h" | 49 | #include "config.h" |
50 | 50 | ||
51 | 51 | ||
52 | #define TIPC_MOD_VER "1.6.3" | 52 | #define TIPC_MOD_VER "1.6.4" |
53 | 53 | ||
54 | #ifndef CONFIG_TIPC_ZONES | 54 | #ifndef CONFIG_TIPC_ZONES |
55 | #define CONFIG_TIPC_ZONES 3 | 55 | #define CONFIG_TIPC_ZONES 3 |
@@ -117,11 +117,11 @@ void tipc_core_stop_net(void) | |||
117 | * start_net - start TIPC networking sub-systems | 117 | * start_net - start TIPC networking sub-systems |
118 | */ | 118 | */ |
119 | 119 | ||
120 | int tipc_core_start_net(void) | 120 | int tipc_core_start_net(unsigned long addr) |
121 | { | 121 | { |
122 | int res; | 122 | int res; |
123 | 123 | ||
124 | if ((res = tipc_net_start()) || | 124 | if ((res = tipc_net_start(addr)) || |
125 | (res = tipc_eth_media_start())) { | 125 | (res = tipc_eth_media_start())) { |
126 | tipc_core_stop_net(); | 126 | tipc_core_stop_net(); |
127 | } | 127 | } |
@@ -164,8 +164,7 @@ int tipc_core_start(void) | |||
164 | tipc_mode = TIPC_NODE_MODE; | 164 | tipc_mode = TIPC_NODE_MODE; |
165 | 165 | ||
166 | if ((res = tipc_handler_start()) || | 166 | if ((res = tipc_handler_start()) || |
167 | (res = tipc_ref_table_init(tipc_max_ports + tipc_max_subscriptions, | 167 | (res = tipc_ref_table_init(tipc_max_ports, tipc_random)) || |
168 | tipc_random)) || | ||
169 | (res = tipc_reg_start()) || | 168 | (res = tipc_reg_start()) || |
170 | (res = tipc_nametbl_init()) || | 169 | (res = tipc_nametbl_init()) || |
171 | (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) || | 170 | (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) || |
@@ -182,7 +181,7 @@ static int __init tipc_init(void) | |||
182 | { | 181 | { |
183 | int res; | 182 | int res; |
184 | 183 | ||
185 | tipc_log_reinit(CONFIG_TIPC_LOG); | 184 | tipc_log_resize(CONFIG_TIPC_LOG); |
186 | info("Activated (version " TIPC_MOD_VER | 185 | info("Activated (version " TIPC_MOD_VER |
187 | " compiled " __DATE__ " " __TIME__ ")\n"); | 186 | " compiled " __DATE__ " " __TIME__ ")\n"); |
188 | 187 | ||
@@ -209,7 +208,7 @@ static void __exit tipc_exit(void) | |||
209 | tipc_core_stop_net(); | 208 | tipc_core_stop_net(); |
210 | tipc_core_stop(); | 209 | tipc_core_stop(); |
211 | info("Deactivated\n"); | 210 | info("Deactivated\n"); |
212 | tipc_log_stop(); | 211 | tipc_log_resize(0); |
213 | } | 212 | } |
214 | 213 | ||
215 | module_init(tipc_init); | 214 | module_init(tipc_init); |
diff --git a/net/tipc/core.h b/net/tipc/core.h index 5a0e4878d3b7..a881f92a8537 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/core.h: Include file for TIPC global declarations | 2 | * net/tipc/core.h: Include file for TIPC global declarations |
3 | * | 3 | * |
4 | * Copyright (c) 2005-2006, Ericsson AB | 4 | * Copyright (c) 2005-2006, Ericsson AB |
5 | * Copyright (c) 2005-2006, Wind River Systems | 5 | * Copyright (c) 2005-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -59,84 +59,108 @@ | |||
59 | #include <linux/vmalloc.h> | 59 | #include <linux/vmalloc.h> |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * TIPC debugging code | 62 | * TIPC sanity test macros |
63 | */ | 63 | */ |
64 | 64 | ||
65 | #define assert(i) BUG_ON(!(i)) | 65 | #define assert(i) BUG_ON(!(i)) |
66 | 66 | ||
67 | struct tipc_msg; | ||
68 | extern struct print_buf *TIPC_NULL, *TIPC_CONS, *TIPC_LOG; | ||
69 | extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *); | ||
70 | void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*); | ||
71 | void tipc_printf(struct print_buf *, const char *fmt, ...); | ||
72 | void tipc_dump(struct print_buf*,const char *fmt, ...); | ||
73 | |||
74 | #ifdef CONFIG_TIPC_DEBUG | ||
75 | |||
76 | /* | 67 | /* |
77 | * TIPC debug support included: | 68 | * TIPC system monitoring code |
78 | * - system messages are printed to TIPC_OUTPUT print buffer | ||
79 | * - debug messages are printed to DBG_OUTPUT print buffer | ||
80 | */ | 69 | */ |
81 | 70 | ||
82 | #define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_ERR "TIPC: " fmt, ## arg) | 71 | /* |
83 | #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg) | 72 | * TIPC's print buffer subsystem supports the following print buffers: |
84 | #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) | 73 | * |
74 | * TIPC_NULL : null buffer (i.e. print nowhere) | ||
75 | * TIPC_CONS : system console | ||
76 | * TIPC_LOG : TIPC log buffer | ||
77 | * &buf : user-defined buffer (struct print_buf *) | ||
78 | * | ||
79 | * Note: TIPC_LOG is configured to echo its output to the system console; | ||
80 | * user-defined buffers can be configured to do the same thing. | ||
81 | */ | ||
85 | 82 | ||
86 | #define dbg(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) | 83 | extern struct print_buf *const TIPC_NULL; |
87 | #define msg_dbg(msg, txt) do {if (DBG_OUTPUT != TIPC_NULL) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0) | 84 | extern struct print_buf *const TIPC_CONS; |
88 | #define dump(fmt, arg...) do {if (DBG_OUTPUT != TIPC_NULL) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) | 85 | extern struct print_buf *const TIPC_LOG; |
89 | 86 | ||
87 | void tipc_printf(struct print_buf *, const char *fmt, ...); | ||
90 | 88 | ||
91 | /* | 89 | /* |
92 | * By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer, | 90 | * TIPC_OUTPUT is the destination print buffer for system messages. |
93 | * while DBG_OUTPUT is the null print buffer. These defaults can be changed | ||
94 | * here, or on a per .c file basis, by redefining these symbols. The following | ||
95 | * print buffer options are available: | ||
96 | * | ||
97 | * TIPC_NULL : null buffer (i.e. print nowhere) | ||
98 | * TIPC_CONS : system console | ||
99 | * TIPC_LOG : TIPC log buffer | ||
100 | * &buf : user-defined buffer (struct print_buf *) | ||
101 | * TIPC_TEE(&buf_a,&buf_b) : list of buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG)) | ||
102 | */ | 91 | */ |
103 | 92 | ||
104 | #ifndef TIPC_OUTPUT | 93 | #ifndef TIPC_OUTPUT |
105 | #define TIPC_OUTPUT TIPC_TEE(TIPC_CONS,TIPC_LOG) | 94 | #define TIPC_OUTPUT TIPC_LOG |
106 | #endif | ||
107 | |||
108 | #ifndef DBG_OUTPUT | ||
109 | #define DBG_OUTPUT TIPC_NULL | ||
110 | #endif | 95 | #endif |
111 | 96 | ||
112 | #else | ||
113 | |||
114 | /* | 97 | /* |
115 | * TIPC debug support not included: | 98 | * TIPC can be configured to send system messages to TIPC_OUTPUT |
116 | * - system messages are printed to system console | 99 | * or to the system console only. |
117 | * - debug messages are not printed | ||
118 | */ | 100 | */ |
119 | 101 | ||
102 | #ifdef CONFIG_TIPC_DEBUG | ||
103 | |||
104 | #define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ | ||
105 | KERN_ERR "TIPC: " fmt, ## arg) | ||
106 | #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ | ||
107 | KERN_WARNING "TIPC: " fmt, ## arg) | ||
108 | #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, \ | ||
109 | KERN_NOTICE "TIPC: " fmt, ## arg) | ||
110 | |||
111 | #else | ||
112 | |||
120 | #define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg) | 113 | #define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg) |
121 | #define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg) | 114 | #define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg) |
122 | #define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg) | 115 | #define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg) |
123 | 116 | ||
124 | #define dbg(fmt, arg...) do {} while (0) | 117 | #endif |
125 | #define msg_dbg(msg,txt) do {} while (0) | ||
126 | #define dump(fmt,arg...) do {} while (0) | ||
127 | 118 | ||
119 | /* | ||
120 | * DBG_OUTPUT is the destination print buffer for debug messages. | ||
121 | * It defaults to the the null print buffer, but can be redefined | ||
122 | * (typically in the individual .c files being debugged) to allow | ||
123 | * selected debug messages to be generated where needed. | ||
124 | */ | ||
125 | |||
126 | #ifndef DBG_OUTPUT | ||
127 | #define DBG_OUTPUT TIPC_NULL | ||
128 | #endif | ||
128 | 129 | ||
129 | /* | 130 | /* |
130 | * TIPC_OUTPUT is defined to be the system console, while DBG_OUTPUT is | 131 | * TIPC can be configured to send debug messages to the specified print buffer |
131 | * the null print buffer. Thes ensures that any system or debug messages | 132 | * (typically DBG_OUTPUT) or to suppress them entirely. |
132 | * that are generated without using the above macros are handled correctly. | ||
133 | */ | 133 | */ |
134 | 134 | ||
135 | #undef TIPC_OUTPUT | 135 | #ifdef CONFIG_TIPC_DEBUG |
136 | #define TIPC_OUTPUT TIPC_CONS | ||
137 | 136 | ||
138 | #undef DBG_OUTPUT | 137 | #define dbg(fmt, arg...) \ |
139 | #define DBG_OUTPUT TIPC_NULL | 138 | do { \ |
139 | if (DBG_OUTPUT != TIPC_NULL) \ | ||
140 | tipc_printf(DBG_OUTPUT, fmt, ## arg); \ | ||
141 | } while (0) | ||
142 | #define msg_dbg(msg, txt) \ | ||
143 | do { \ | ||
144 | if (DBG_OUTPUT != TIPC_NULL) \ | ||
145 | tipc_msg_dbg(DBG_OUTPUT, msg, txt); \ | ||
146 | } while (0) | ||
147 | #define dump(fmt, arg...) \ | ||
148 | do { \ | ||
149 | if (DBG_OUTPUT != TIPC_NULL) \ | ||
150 | tipc_dump_dbg(DBG_OUTPUT, fmt, ##arg); \ | ||
151 | } while (0) | ||
152 | |||
153 | void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *); | ||
154 | void tipc_dump_dbg(struct print_buf *, const char *fmt, ...); | ||
155 | |||
156 | #else | ||
157 | |||
158 | #define dbg(fmt, arg...) do {} while (0) | ||
159 | #define msg_dbg(msg, txt) do {} while (0) | ||
160 | #define dump(fmt, arg...) do {} while (0) | ||
161 | |||
162 | #define tipc_msg_dbg(...) do {} while (0) | ||
163 | #define tipc_dump_dbg(...) do {} while (0) | ||
140 | 164 | ||
141 | #endif | 165 | #endif |
142 | 166 | ||
@@ -178,7 +202,7 @@ extern atomic_t tipc_user_count; | |||
178 | 202 | ||
179 | extern int tipc_core_start(void); | 203 | extern int tipc_core_start(void); |
180 | extern void tipc_core_stop(void); | 204 | extern void tipc_core_stop(void); |
181 | extern int tipc_core_start_net(void); | 205 | extern int tipc_core_start_net(unsigned long addr); |
182 | extern void tipc_core_stop_net(void); | 206 | extern void tipc_core_stop_net(void); |
183 | extern int tipc_handler_start(void); | 207 | extern int tipc_handler_start(void); |
184 | extern void tipc_handler_stop(void); | 208 | extern void tipc_handler_stop(void); |
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index e809d2a2ce06..29ecae851668 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/dbg.c: TIPC print buffer routines for debugging | 2 | * net/tipc/dbg.c: TIPC print buffer routines for debugging |
3 | * | 3 | * |
4 | * Copyright (c) 1996-2006, Ericsson AB | 4 | * Copyright (c) 1996-2006, Ericsson AB |
5 | * Copyright (c) 2005-2006, Wind River Systems | 5 | * Copyright (c) 2005-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -38,17 +38,43 @@ | |||
38 | #include "config.h" | 38 | #include "config.h" |
39 | #include "dbg.h" | 39 | #include "dbg.h" |
40 | 40 | ||
41 | static char print_string[TIPC_PB_MAX_STR]; | 41 | /* |
42 | static DEFINE_SPINLOCK(print_lock); | 42 | * TIPC pre-defines the following print buffers: |
43 | * | ||
44 | * TIPC_NULL : null buffer (i.e. print nowhere) | ||
45 | * TIPC_CONS : system console | ||
46 | * TIPC_LOG : TIPC log buffer | ||
47 | * | ||
48 | * Additional user-defined print buffers are also permitted. | ||
49 | */ | ||
43 | 50 | ||
44 | static struct print_buf null_buf = { NULL, 0, NULL, NULL }; | 51 | static struct print_buf null_buf = { NULL, 0, NULL, 0 }; |
45 | struct print_buf *TIPC_NULL = &null_buf; | 52 | struct print_buf *const TIPC_NULL = &null_buf; |
46 | 53 | ||
47 | static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; | 54 | static struct print_buf cons_buf = { NULL, 0, NULL, 1 }; |
48 | struct print_buf *TIPC_CONS = &cons_buf; | 55 | struct print_buf *const TIPC_CONS = &cons_buf; |
49 | 56 | ||
50 | static struct print_buf log_buf = { NULL, 0, NULL, NULL }; | 57 | static struct print_buf log_buf = { NULL, 0, NULL, 1 }; |
51 | struct print_buf *TIPC_LOG = &log_buf; | 58 | struct print_buf *const TIPC_LOG = &log_buf; |
59 | |||
60 | /* | ||
61 | * Locking policy when using print buffers. | ||
62 | * | ||
63 | * 1) tipc_printf() uses 'print_lock' to protect against concurrent access to | ||
64 | * 'print_string' when writing to a print buffer. This also protects against | ||
65 | * concurrent writes to the print buffer being written to. | ||
66 | * | ||
67 | * 2) tipc_dump() and tipc_log_XXX() leverage the aforementioned | ||
68 | * use of 'print_lock' to protect against all types of concurrent operations | ||
69 | * on their associated print buffer (not just write operations). | ||
70 | * | ||
71 | * Note: All routines of the form tipc_printbuf_XXX() are lock-free, and rely | ||
72 | * on the caller to prevent simultaneous use of the print buffer(s) being | ||
73 | * manipulated. | ||
74 | */ | ||
75 | |||
76 | static char print_string[TIPC_PB_MAX_STR]; | ||
77 | static DEFINE_SPINLOCK(print_lock); | ||
52 | 78 | ||
53 | 79 | ||
54 | #define FORMAT(PTR,LEN,FMT) \ | 80 | #define FORMAT(PTR,LEN,FMT) \ |
@@ -60,27 +86,14 @@ struct print_buf *TIPC_LOG = &log_buf; | |||
60 | *(PTR + LEN) = '\0';\ | 86 | *(PTR + LEN) = '\0';\ |
61 | } | 87 | } |
62 | 88 | ||
63 | /* | ||
64 | * Locking policy when using print buffers. | ||
65 | * | ||
66 | * The following routines use 'print_lock' for protection: | ||
67 | * 1) tipc_printf() - to protect its print buffer(s) and 'print_string' | ||
68 | * 2) TIPC_TEE() - to protect its print buffer(s) | ||
69 | * 3) tipc_dump() - to protect its print buffer(s) and 'print_string' | ||
70 | * 4) tipc_log_XXX() - to protect TIPC_LOG | ||
71 | * | ||
72 | * All routines of the form tipc_printbuf_XXX() rely on the caller to prevent | ||
73 | * simultaneous use of the print buffer(s) being manipulated. | ||
74 | */ | ||
75 | |||
76 | /** | 89 | /** |
77 | * tipc_printbuf_init - initialize print buffer to empty | 90 | * tipc_printbuf_init - initialize print buffer to empty |
78 | * @pb: pointer to print buffer structure | 91 | * @pb: pointer to print buffer structure |
79 | * @raw: pointer to character array used by print buffer | 92 | * @raw: pointer to character array used by print buffer |
80 | * @size: size of character array | 93 | * @size: size of character array |
81 | * | 94 | * |
82 | * Makes the print buffer a null device that discards anything written to it | 95 | * Note: If the character array is too small (or absent), the print buffer |
83 | * if the character array is too small (or absent). | 96 | * becomes a null device that discards anything written to it. |
84 | */ | 97 | */ |
85 | 98 | ||
86 | void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) | 99 | void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) |
@@ -88,13 +101,13 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) | |||
88 | pb->buf = raw; | 101 | pb->buf = raw; |
89 | pb->crs = raw; | 102 | pb->crs = raw; |
90 | pb->size = size; | 103 | pb->size = size; |
91 | pb->next = NULL; | 104 | pb->echo = 0; |
92 | 105 | ||
93 | if (size < TIPC_PB_MIN_SIZE) { | 106 | if (size < TIPC_PB_MIN_SIZE) { |
94 | pb->buf = NULL; | 107 | pb->buf = NULL; |
95 | } else if (raw) { | 108 | } else if (raw) { |
96 | pb->buf[0] = 0; | 109 | pb->buf[0] = 0; |
97 | pb->buf[size-1] = ~0; | 110 | pb->buf[size - 1] = ~0; |
98 | } | 111 | } |
99 | } | 112 | } |
100 | 113 | ||
@@ -105,7 +118,11 @@ void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 size) | |||
105 | 118 | ||
106 | void tipc_printbuf_reset(struct print_buf *pb) | 119 | void tipc_printbuf_reset(struct print_buf *pb) |
107 | { | 120 | { |
108 | tipc_printbuf_init(pb, pb->buf, pb->size); | 121 | if (pb->buf) { |
122 | pb->crs = pb->buf; | ||
123 | pb->buf[0] = 0; | ||
124 | pb->buf[pb->size - 1] = ~0; | ||
125 | } | ||
109 | } | 126 | } |
110 | 127 | ||
111 | /** | 128 | /** |
@@ -141,7 +158,7 @@ int tipc_printbuf_validate(struct print_buf *pb) | |||
141 | 158 | ||
142 | if (pb->buf[pb->size - 1] == 0) { | 159 | if (pb->buf[pb->size - 1] == 0) { |
143 | cp_buf = kmalloc(pb->size, GFP_ATOMIC); | 160 | cp_buf = kmalloc(pb->size, GFP_ATOMIC); |
144 | if (cp_buf != NULL){ | 161 | if (cp_buf) { |
145 | tipc_printbuf_init(&cb, cp_buf, pb->size); | 162 | tipc_printbuf_init(&cb, cp_buf, pb->size); |
146 | tipc_printbuf_move(&cb, pb); | 163 | tipc_printbuf_move(&cb, pb); |
147 | tipc_printbuf_move(pb, &cb); | 164 | tipc_printbuf_move(pb, &cb); |
@@ -179,15 +196,16 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) | |||
179 | } | 196 | } |
180 | 197 | ||
181 | if (pb_to->size < pb_from->size) { | 198 | if (pb_to->size < pb_from->size) { |
182 | tipc_printbuf_reset(pb_to); | 199 | strcpy(pb_to->buf, "*** PRINT BUFFER MOVE ERROR ***"); |
183 | tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***"); | 200 | pb_to->buf[pb_to->size - 1] = ~0; |
201 | pb_to->crs = strchr(pb_to->buf, 0); | ||
184 | return; | 202 | return; |
185 | } | 203 | } |
186 | 204 | ||
187 | /* Copy data from char after cursor to end (if used) */ | 205 | /* Copy data from char after cursor to end (if used) */ |
188 | 206 | ||
189 | len = pb_from->buf + pb_from->size - pb_from->crs - 2; | 207 | len = pb_from->buf + pb_from->size - pb_from->crs - 2; |
190 | if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) { | 208 | if ((pb_from->buf[pb_from->size - 1] == 0) && (len > 0)) { |
191 | strcpy(pb_to->buf, pb_from->crs + 1); | 209 | strcpy(pb_to->buf, pb_from->crs + 1); |
192 | pb_to->crs = pb_to->buf + len; | 210 | pb_to->crs = pb_to->buf + len; |
193 | } else | 211 | } else |
@@ -203,8 +221,8 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) | |||
203 | } | 221 | } |
204 | 222 | ||
205 | /** | 223 | /** |
206 | * tipc_printf - append formatted output to print buffer chain | 224 | * tipc_printf - append formatted output to print buffer |
207 | * @pb: pointer to chain of print buffers (may be NULL) | 225 | * @pb: pointer to print buffer |
208 | * @fmt: formatted info to be printed | 226 | * @fmt: formatted info to be printed |
209 | */ | 227 | */ |
210 | 228 | ||
@@ -213,68 +231,40 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) | |||
213 | int chars_to_add; | 231 | int chars_to_add; |
214 | int chars_left; | 232 | int chars_left; |
215 | char save_char; | 233 | char save_char; |
216 | struct print_buf *pb_next; | ||
217 | 234 | ||
218 | spin_lock_bh(&print_lock); | 235 | spin_lock_bh(&print_lock); |
236 | |||
219 | FORMAT(print_string, chars_to_add, fmt); | 237 | FORMAT(print_string, chars_to_add, fmt); |
220 | if (chars_to_add >= TIPC_PB_MAX_STR) | 238 | if (chars_to_add >= TIPC_PB_MAX_STR) |
221 | strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***"); | 239 | strcpy(print_string, "*** PRINT BUFFER STRING TOO LONG ***"); |
222 | 240 | ||
223 | while (pb) { | 241 | if (pb->buf) { |
224 | if (pb == TIPC_CONS) | 242 | chars_left = pb->buf + pb->size - pb->crs - 1; |
225 | printk(print_string); | 243 | if (chars_to_add <= chars_left) { |
226 | else if (pb->buf) { | 244 | strcpy(pb->crs, print_string); |
227 | chars_left = pb->buf + pb->size - pb->crs - 1; | 245 | pb->crs += chars_to_add; |
228 | if (chars_to_add <= chars_left) { | 246 | } else if (chars_to_add >= (pb->size - 1)) { |
229 | strcpy(pb->crs, print_string); | 247 | strcpy(pb->buf, print_string + chars_to_add + 1 |
230 | pb->crs += chars_to_add; | 248 | - pb->size); |
231 | } else if (chars_to_add >= (pb->size - 1)) { | 249 | pb->crs = pb->buf + pb->size - 1; |
232 | strcpy(pb->buf, print_string + chars_to_add + 1 | 250 | } else { |
233 | - pb->size); | 251 | strcpy(pb->buf, print_string + chars_left); |
234 | pb->crs = pb->buf + pb->size - 1; | 252 | save_char = print_string[chars_left]; |
235 | } else { | 253 | print_string[chars_left] = 0; |
236 | strcpy(pb->buf, print_string + chars_left); | 254 | strcpy(pb->crs, print_string); |
237 | save_char = print_string[chars_left]; | 255 | print_string[chars_left] = save_char; |
238 | print_string[chars_left] = 0; | 256 | pb->crs = pb->buf + chars_to_add - chars_left; |
239 | strcpy(pb->crs, print_string); | ||
240 | print_string[chars_left] = save_char; | ||
241 | pb->crs = pb->buf + chars_to_add - chars_left; | ||
242 | } | ||
243 | } | 257 | } |
244 | pb_next = pb->next; | ||
245 | pb->next = NULL; | ||
246 | pb = pb_next; | ||
247 | } | 258 | } |
248 | spin_unlock_bh(&print_lock); | ||
249 | } | ||
250 | 259 | ||
251 | /** | 260 | if (pb->echo) |
252 | * TIPC_TEE - perform next output operation on both print buffers | 261 | printk(print_string); |
253 | * @b0: pointer to chain of print buffers (may be NULL) | ||
254 | * @b1: pointer to print buffer to add to chain | ||
255 | * | ||
256 | * Returns pointer to print buffer chain. | ||
257 | */ | ||
258 | 262 | ||
259 | struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1) | ||
260 | { | ||
261 | struct print_buf *pb = b0; | ||
262 | |||
263 | if (!b0 || (b0 == b1)) | ||
264 | return b1; | ||
265 | |||
266 | spin_lock_bh(&print_lock); | ||
267 | while (pb->next) { | ||
268 | if ((pb->next == b1) || (pb->next == b0)) | ||
269 | pb->next = pb->next->next; | ||
270 | else | ||
271 | pb = pb->next; | ||
272 | } | ||
273 | pb->next = b1; | ||
274 | spin_unlock_bh(&print_lock); | 263 | spin_unlock_bh(&print_lock); |
275 | return b0; | ||
276 | } | 264 | } |
277 | 265 | ||
266 | #ifdef CONFIG_TIPC_DEBUG | ||
267 | |||
278 | /** | 268 | /** |
279 | * print_to_console - write string of bytes to console in multiple chunks | 269 | * print_to_console - write string of bytes to console in multiple chunks |
280 | */ | 270 | */ |
@@ -321,72 +311,66 @@ static void printbuf_dump(struct print_buf *pb) | |||
321 | } | 311 | } |
322 | 312 | ||
323 | /** | 313 | /** |
324 | * tipc_dump - dump non-console print buffer(s) to console | 314 | * tipc_dump_dbg - dump (non-console) print buffer to console |
325 | * @pb: pointer to chain of print buffers | 315 | * @pb: pointer to print buffer |
326 | */ | 316 | */ |
327 | 317 | ||
328 | void tipc_dump(struct print_buf *pb, const char *fmt, ...) | 318 | void tipc_dump_dbg(struct print_buf *pb, const char *fmt, ...) |
329 | { | 319 | { |
330 | struct print_buf *pb_next; | ||
331 | int len; | 320 | int len; |
332 | 321 | ||
322 | if (pb == TIPC_CONS) | ||
323 | return; | ||
324 | |||
333 | spin_lock_bh(&print_lock); | 325 | spin_lock_bh(&print_lock); |
326 | |||
334 | FORMAT(print_string, len, fmt); | 327 | FORMAT(print_string, len, fmt); |
335 | printk(print_string); | 328 | printk(print_string); |
336 | 329 | ||
337 | for (; pb; pb = pb->next) { | 330 | printk("\n---- Start of %s log dump ----\n\n", |
338 | if (pb != TIPC_CONS) { | 331 | (pb == TIPC_LOG) ? "global" : "local"); |
339 | printk("\n---- Start of %s log dump ----\n\n", | 332 | printbuf_dump(pb); |
340 | (pb == TIPC_LOG) ? "global" : "local"); | 333 | tipc_printbuf_reset(pb); |
341 | printbuf_dump(pb); | 334 | printk("\n---- End of dump ----\n"); |
342 | tipc_printbuf_reset(pb); | 335 | |
343 | printk("\n---- End of dump ----\n"); | ||
344 | } | ||
345 | pb_next = pb->next; | ||
346 | pb->next = NULL; | ||
347 | pb = pb_next; | ||
348 | } | ||
349 | spin_unlock_bh(&print_lock); | 336 | spin_unlock_bh(&print_lock); |
350 | } | 337 | } |
351 | 338 | ||
339 | #endif | ||
340 | |||
352 | /** | 341 | /** |
353 | * tipc_log_stop - free up TIPC log print buffer | 342 | * tipc_log_resize - change the size of the TIPC log buffer |
343 | * @log_size: print buffer size to use | ||
354 | */ | 344 | */ |
355 | 345 | ||
356 | void tipc_log_stop(void) | 346 | int tipc_log_resize(int log_size) |
357 | { | 347 | { |
348 | int res = 0; | ||
349 | |||
358 | spin_lock_bh(&print_lock); | 350 | spin_lock_bh(&print_lock); |
359 | if (TIPC_LOG->buf) { | 351 | if (TIPC_LOG->buf) { |
360 | kfree(TIPC_LOG->buf); | 352 | kfree(TIPC_LOG->buf); |
361 | TIPC_LOG->buf = NULL; | 353 | TIPC_LOG->buf = NULL; |
362 | } | 354 | } |
363 | spin_unlock_bh(&print_lock); | ||
364 | } | ||
365 | |||
366 | /** | ||
367 | * tipc_log_reinit - (re)initialize TIPC log print buffer | ||
368 | * @log_size: print buffer size to use | ||
369 | */ | ||
370 | |||
371 | void tipc_log_reinit(int log_size) | ||
372 | { | ||
373 | tipc_log_stop(); | ||
374 | |||
375 | if (log_size) { | 355 | if (log_size) { |
376 | if (log_size < TIPC_PB_MIN_SIZE) | 356 | if (log_size < TIPC_PB_MIN_SIZE) |
377 | log_size = TIPC_PB_MIN_SIZE; | 357 | log_size = TIPC_PB_MIN_SIZE; |
378 | spin_lock_bh(&print_lock); | 358 | res = TIPC_LOG->echo; |
379 | tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), | 359 | tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), |
380 | log_size); | 360 | log_size); |
381 | spin_unlock_bh(&print_lock); | 361 | TIPC_LOG->echo = res; |
362 | res = !TIPC_LOG->buf; | ||
382 | } | 363 | } |
364 | spin_unlock_bh(&print_lock); | ||
365 | |||
366 | return res; | ||
383 | } | 367 | } |
384 | 368 | ||
385 | /** | 369 | /** |
386 | * tipc_log_resize - reconfigure size of TIPC log buffer | 370 | * tipc_log_resize_cmd - reconfigure size of TIPC log buffer |
387 | */ | 371 | */ |
388 | 372 | ||
389 | struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space) | 373 | struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, int req_tlv_space) |
390 | { | 374 | { |
391 | u32 value; | 375 | u32 value; |
392 | 376 | ||
@@ -397,7 +381,9 @@ struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space) | |||
397 | if (value != delimit(value, 0, 32768)) | 381 | if (value != delimit(value, 0, 32768)) |
398 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 382 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
399 | " (log size must be 0-32768)"); | 383 | " (log size must be 0-32768)"); |
400 | tipc_log_reinit(value); | 384 | if (tipc_log_resize(value)) |
385 | return tipc_cfg_reply_error_string( | ||
386 | "unable to create specified log (log size is now 0)"); | ||
401 | return tipc_cfg_reply_none(); | 387 | return tipc_cfg_reply_none(); |
402 | } | 388 | } |
403 | 389 | ||
@@ -410,27 +396,32 @@ struct sk_buff *tipc_log_dump(void) | |||
410 | struct sk_buff *reply; | 396 | struct sk_buff *reply; |
411 | 397 | ||
412 | spin_lock_bh(&print_lock); | 398 | spin_lock_bh(&print_lock); |
413 | if (!TIPC_LOG->buf) | 399 | if (!TIPC_LOG->buf) { |
400 | spin_unlock_bh(&print_lock); | ||
414 | reply = tipc_cfg_reply_ultra_string("log not activated\n"); | 401 | reply = tipc_cfg_reply_ultra_string("log not activated\n"); |
415 | else if (tipc_printbuf_empty(TIPC_LOG)) | 402 | } else if (tipc_printbuf_empty(TIPC_LOG)) { |
403 | spin_unlock_bh(&print_lock); | ||
416 | reply = tipc_cfg_reply_ultra_string("log is empty\n"); | 404 | reply = tipc_cfg_reply_ultra_string("log is empty\n"); |
405 | } | ||
417 | else { | 406 | else { |
418 | struct tlv_desc *rep_tlv; | 407 | struct tlv_desc *rep_tlv; |
419 | struct print_buf pb; | 408 | struct print_buf pb; |
420 | int str_len; | 409 | int str_len; |
421 | 410 | ||
422 | str_len = min(TIPC_LOG->size, 32768u); | 411 | str_len = min(TIPC_LOG->size, 32768u); |
412 | spin_unlock_bh(&print_lock); | ||
423 | reply = tipc_cfg_reply_alloc(TLV_SPACE(str_len)); | 413 | reply = tipc_cfg_reply_alloc(TLV_SPACE(str_len)); |
424 | if (reply) { | 414 | if (reply) { |
425 | rep_tlv = (struct tlv_desc *)reply->data; | 415 | rep_tlv = (struct tlv_desc *)reply->data; |
426 | tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), str_len); | 416 | tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), str_len); |
417 | spin_lock_bh(&print_lock); | ||
427 | tipc_printbuf_move(&pb, TIPC_LOG); | 418 | tipc_printbuf_move(&pb, TIPC_LOG); |
419 | spin_unlock_bh(&print_lock); | ||
428 | str_len = strlen(TLV_DATA(rep_tlv)) + 1; | 420 | str_len = strlen(TLV_DATA(rep_tlv)) + 1; |
429 | skb_put(reply, TLV_SPACE(str_len)); | 421 | skb_put(reply, TLV_SPACE(str_len)); |
430 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | 422 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); |
431 | } | 423 | } |
432 | } | 424 | } |
433 | spin_unlock_bh(&print_lock); | ||
434 | return reply; | 425 | return reply; |
435 | } | 426 | } |
436 | 427 | ||
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h index c01b085000e0..5ef1bc8f64ef 100644 --- a/net/tipc/dbg.h +++ b/net/tipc/dbg.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/dbg.h: Include file for TIPC print buffer routines | 2 | * net/tipc/dbg.h: Include file for TIPC print buffer routines |
3 | * | 3 | * |
4 | * Copyright (c) 1997-2006, Ericsson AB | 4 | * Copyright (c) 1997-2006, Ericsson AB |
5 | * Copyright (c) 2005-2006, Wind River Systems | 5 | * Copyright (c) 2005-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -42,14 +42,14 @@ | |||
42 | * @buf: pointer to character array containing print buffer contents | 42 | * @buf: pointer to character array containing print buffer contents |
43 | * @size: size of character array | 43 | * @size: size of character array |
44 | * @crs: pointer to first unused space in character array (i.e. final NUL) | 44 | * @crs: pointer to first unused space in character array (i.e. final NUL) |
45 | * @next: used to link print buffers when printing to more than one at a time | 45 | * @echo: echo output to system console if non-zero |
46 | */ | 46 | */ |
47 | 47 | ||
48 | struct print_buf { | 48 | struct print_buf { |
49 | char *buf; | 49 | char *buf; |
50 | u32 size; | 50 | u32 size; |
51 | char *crs; | 51 | char *crs; |
52 | struct print_buf *next; | 52 | int echo; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | #define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */ | 55 | #define TIPC_PB_MIN_SIZE 64 /* minimum size for a print buffer's array */ |
@@ -61,10 +61,10 @@ int tipc_printbuf_empty(struct print_buf *pb); | |||
61 | int tipc_printbuf_validate(struct print_buf *pb); | 61 | int tipc_printbuf_validate(struct print_buf *pb); |
62 | void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); | 62 | void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); |
63 | 63 | ||
64 | void tipc_log_reinit(int log_size); | 64 | int tipc_log_resize(int log_size); |
65 | void tipc_log_stop(void); | ||
66 | 65 | ||
67 | struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space); | 66 | struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, |
67 | int req_tlv_space); | ||
68 | struct sk_buff *tipc_log_dump(void); | 68 | struct sk_buff *tipc_log_dump(void); |
69 | 69 | ||
70 | #endif | 70 | #endif |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 5d643e5721eb..1657f0e795ff 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -120,9 +120,8 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, | |||
120 | 120 | ||
121 | if (buf) { | 121 | if (buf) { |
122 | msg = buf_msg(buf); | 122 | msg = buf_msg(buf); |
123 | msg_init(msg, LINK_CONFIG, type, TIPC_OK, DSC_H_SIZE, | 123 | msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain); |
124 | dest_domain); | 124 | msg_set_non_seq(msg, 1); |
125 | msg_set_non_seq(msg); | ||
126 | msg_set_req_links(msg, req_links); | 125 | msg_set_req_links(msg, req_links); |
127 | msg_set_dest_domain(msg, dest_domain); | 126 | msg_set_dest_domain(msg, dest_domain); |
128 | msg_set_bc_netid(msg, tipc_net_id); | 127 | msg_set_bc_netid(msg, tipc_net_id); |
@@ -156,11 +155,11 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, | |||
156 | /** | 155 | /** |
157 | * tipc_disc_recv_msg - handle incoming link setup message (request or response) | 156 | * tipc_disc_recv_msg - handle incoming link setup message (request or response) |
158 | * @buf: buffer containing message | 157 | * @buf: buffer containing message |
158 | * @b_ptr: bearer that message arrived on | ||
159 | */ | 159 | */ |
160 | 160 | ||
161 | void tipc_disc_recv_msg(struct sk_buff *buf) | 161 | void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr) |
162 | { | 162 | { |
163 | struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle; | ||
164 | struct link *link; | 163 | struct link *link; |
165 | struct tipc_media_addr media_addr; | 164 | struct tipc_media_addr media_addr; |
166 | struct tipc_msg *msg = buf_msg(buf); | 165 | struct tipc_msg *msg = buf_msg(buf); |
@@ -200,9 +199,8 @@ void tipc_disc_recv_msg(struct sk_buff *buf) | |||
200 | dbg(" in own cluster\n"); | 199 | dbg(" in own cluster\n"); |
201 | if (n_ptr == NULL) { | 200 | if (n_ptr == NULL) { |
202 | n_ptr = tipc_node_create(orig); | 201 | n_ptr = tipc_node_create(orig); |
203 | } | 202 | if (!n_ptr) |
204 | if (n_ptr == NULL) { | 203 | return; |
205 | return; | ||
206 | } | 204 | } |
207 | spin_lock_bh(&n_ptr->lock); | 205 | spin_lock_bh(&n_ptr->lock); |
208 | link = n_ptr->links[b_ptr->identity]; | 206 | link = n_ptr->links[b_ptr->identity]; |
diff --git a/net/tipc/discover.h b/net/tipc/discover.h index 9fd7587b143a..c36eaeb7d5d0 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h | |||
@@ -48,7 +48,7 @@ struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, | |||
48 | void tipc_disc_update_link_req(struct link_req *req); | 48 | void tipc_disc_update_link_req(struct link_req *req); |
49 | void tipc_disc_stop_link_req(struct link_req *req); | 49 | void tipc_disc_stop_link_req(struct link_req *req); |
50 | 50 | ||
51 | void tipc_disc_recv_msg(struct sk_buff *buf); | 51 | void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr); |
52 | 52 | ||
53 | void tipc_disc_link_event(u32 addr, char *name, int up); | 53 | void tipc_disc_link_event(u32 addr, char *name, int up); |
54 | #if 0 | 54 | #if 0 |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 2a26a16e269f..9784a8e963b4 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -51,6 +51,12 @@ | |||
51 | 51 | ||
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Out-of-range value for link session numbers | ||
55 | */ | ||
56 | |||
57 | #define INVALID_SESSION 0x10000 | ||
58 | |||
59 | /* | ||
54 | * Limit for deferred reception queue: | 60 | * Limit for deferred reception queue: |
55 | */ | 61 | */ |
56 | 62 | ||
@@ -147,9 +153,21 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, | |||
147 | 153 | ||
148 | #define LINK_LOG_BUF_SIZE 0 | 154 | #define LINK_LOG_BUF_SIZE 0 |
149 | 155 | ||
150 | #define dbg_link(fmt, arg...) do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0) | 156 | #define dbg_link(fmt, arg...) \ |
151 | #define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) tipc_msg_print(&l_ptr->print_buf, msg, txt); } while(0) | 157 | do { \ |
152 | #define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0) | 158 | if (LINK_LOG_BUF_SIZE) \ |
159 | tipc_printf(&l_ptr->print_buf, fmt, ## arg); \ | ||
160 | } while (0) | ||
161 | #define dbg_link_msg(msg, txt) \ | ||
162 | do { \ | ||
163 | if (LINK_LOG_BUF_SIZE) \ | ||
164 | tipc_msg_dbg(&l_ptr->print_buf, msg, txt); \ | ||
165 | } while (0) | ||
166 | #define dbg_link_state(txt) \ | ||
167 | do { \ | ||
168 | if (LINK_LOG_BUF_SIZE) \ | ||
169 | link_print(l_ptr, &l_ptr->print_buf, txt); \ | ||
170 | } while (0) | ||
153 | #define dbg_link_dump() do { \ | 171 | #define dbg_link_dump() do { \ |
154 | if (LINK_LOG_BUF_SIZE) { \ | 172 | if (LINK_LOG_BUF_SIZE) { \ |
155 | tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \ | 173 | tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \ |
@@ -450,9 +468,9 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, | |||
450 | 468 | ||
451 | l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; | 469 | l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; |
452 | msg = l_ptr->pmsg; | 470 | msg = l_ptr->pmsg; |
453 | msg_init(msg, LINK_PROTOCOL, RESET_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | 471 | msg_init(msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, l_ptr->addr); |
454 | msg_set_size(msg, sizeof(l_ptr->proto_msg)); | 472 | msg_set_size(msg, sizeof(l_ptr->proto_msg)); |
455 | msg_set_session(msg, tipc_random); | 473 | msg_set_session(msg, (tipc_random & 0xffff)); |
456 | msg_set_bearer_id(msg, b_ptr->identity); | 474 | msg_set_bearer_id(msg, b_ptr->identity); |
457 | strcpy((char *)msg_data(msg), if_name); | 475 | strcpy((char *)msg_data(msg), if_name); |
458 | 476 | ||
@@ -693,10 +711,10 @@ void tipc_link_reset(struct link *l_ptr) | |||
693 | u32 checkpoint = l_ptr->next_in_no; | 711 | u32 checkpoint = l_ptr->next_in_no; |
694 | int was_active_link = tipc_link_is_active(l_ptr); | 712 | int was_active_link = tipc_link_is_active(l_ptr); |
695 | 713 | ||
696 | msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); | 714 | msg_set_session(l_ptr->pmsg, ((msg_session(l_ptr->pmsg) + 1) & 0xffff)); |
697 | 715 | ||
698 | /* Link is down, accept any session: */ | 716 | /* Link is down, accept any session */ |
699 | l_ptr->peer_session = 0; | 717 | l_ptr->peer_session = INVALID_SESSION; |
700 | 718 | ||
701 | /* Prepare for max packet size negotiation */ | 719 | /* Prepare for max packet size negotiation */ |
702 | link_init_max_pkt(l_ptr); | 720 | link_init_max_pkt(l_ptr); |
@@ -1110,7 +1128,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) | |||
1110 | 1128 | ||
1111 | if (bundler) { | 1129 | if (bundler) { |
1112 | msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, | 1130 | msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, |
1113 | TIPC_OK, INT_H_SIZE, l_ptr->addr); | 1131 | INT_H_SIZE, l_ptr->addr); |
1114 | skb_copy_to_linear_data(bundler, &bundler_hdr, | 1132 | skb_copy_to_linear_data(bundler, &bundler_hdr, |
1115 | INT_H_SIZE); | 1133 | INT_H_SIZE); |
1116 | skb_trim(bundler, INT_H_SIZE); | 1134 | skb_trim(bundler, INT_H_SIZE); |
@@ -1374,7 +1392,7 @@ again: | |||
1374 | 1392 | ||
1375 | msg_dbg(hdr, ">FRAGMENTING>"); | 1393 | msg_dbg(hdr, ">FRAGMENTING>"); |
1376 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | 1394 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, |
1377 | TIPC_OK, INT_H_SIZE, msg_destnode(hdr)); | 1395 | INT_H_SIZE, msg_destnode(hdr)); |
1378 | msg_set_link_selector(&fragm_hdr, sender->publ.ref); | 1396 | msg_set_link_selector(&fragm_hdr, sender->publ.ref); |
1379 | msg_set_size(&fragm_hdr, max_pkt); | 1397 | msg_set_size(&fragm_hdr, max_pkt); |
1380 | msg_set_fragm_no(&fragm_hdr, 1); | 1398 | msg_set_fragm_no(&fragm_hdr, 1); |
@@ -1651,7 +1669,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) | |||
1651 | struct tipc_msg *msg = buf_msg(buf); | 1669 | struct tipc_msg *msg = buf_msg(buf); |
1652 | 1670 | ||
1653 | warn("Retransmission failure on link <%s>\n", l_ptr->name); | 1671 | warn("Retransmission failure on link <%s>\n", l_ptr->name); |
1654 | tipc_msg_print(TIPC_OUTPUT, msg, ">RETR-FAIL>"); | 1672 | tipc_msg_dbg(TIPC_OUTPUT, msg, ">RETR-FAIL>"); |
1655 | 1673 | ||
1656 | if (l_ptr->addr) { | 1674 | if (l_ptr->addr) { |
1657 | 1675 | ||
@@ -1748,21 +1766,6 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | |||
1748 | l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; | 1766 | l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; |
1749 | } | 1767 | } |
1750 | 1768 | ||
1751 | /* | ||
1752 | * link_recv_non_seq: Receive packets which are outside | ||
1753 | * the link sequence flow | ||
1754 | */ | ||
1755 | |||
1756 | static void link_recv_non_seq(struct sk_buff *buf) | ||
1757 | { | ||
1758 | struct tipc_msg *msg = buf_msg(buf); | ||
1759 | |||
1760 | if (msg_user(msg) == LINK_CONFIG) | ||
1761 | tipc_disc_recv_msg(buf); | ||
1762 | else | ||
1763 | tipc_bclink_recv_pkt(buf); | ||
1764 | } | ||
1765 | |||
1766 | /** | 1769 | /** |
1767 | * link_insert_deferred_queue - insert deferred messages back into receive chain | 1770 | * link_insert_deferred_queue - insert deferred messages back into receive chain |
1768 | */ | 1771 | */ |
@@ -1839,7 +1842,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
1839 | { | 1842 | { |
1840 | read_lock_bh(&tipc_net_lock); | 1843 | read_lock_bh(&tipc_net_lock); |
1841 | while (head) { | 1844 | while (head) { |
1842 | struct bearer *b_ptr; | 1845 | struct bearer *b_ptr = (struct bearer *)tb_ptr; |
1843 | struct node *n_ptr; | 1846 | struct node *n_ptr; |
1844 | struct link *l_ptr; | 1847 | struct link *l_ptr; |
1845 | struct sk_buff *crs; | 1848 | struct sk_buff *crs; |
@@ -1850,9 +1853,6 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
1850 | u32 released = 0; | 1853 | u32 released = 0; |
1851 | int type; | 1854 | int type; |
1852 | 1855 | ||
1853 | b_ptr = (struct bearer *)tb_ptr; | ||
1854 | TIPC_SKB_CB(buf)->handle = b_ptr; | ||
1855 | |||
1856 | head = head->next; | 1856 | head = head->next; |
1857 | 1857 | ||
1858 | /* Ensure message is well-formed */ | 1858 | /* Ensure message is well-formed */ |
@@ -1871,7 +1871,10 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
1871 | msg = buf_msg(buf); | 1871 | msg = buf_msg(buf); |
1872 | 1872 | ||
1873 | if (unlikely(msg_non_seq(msg))) { | 1873 | if (unlikely(msg_non_seq(msg))) { |
1874 | link_recv_non_seq(buf); | 1874 | if (msg_user(msg) == LINK_CONFIG) |
1875 | tipc_disc_recv_msg(buf, b_ptr); | ||
1876 | else | ||
1877 | tipc_bclink_recv_pkt(buf); | ||
1875 | continue; | 1878 | continue; |
1876 | } | 1879 | } |
1877 | 1880 | ||
@@ -1978,8 +1981,6 @@ deliver: | |||
1978 | if (link_recv_changeover_msg(&l_ptr, &buf)) { | 1981 | if (link_recv_changeover_msg(&l_ptr, &buf)) { |
1979 | msg = buf_msg(buf); | 1982 | msg = buf_msg(buf); |
1980 | seq_no = msg_seqno(msg); | 1983 | seq_no = msg_seqno(msg); |
1981 | TIPC_SKB_CB(buf)->handle | ||
1982 | = b_ptr; | ||
1983 | if (type == ORIGINAL_MSG) | 1984 | if (type == ORIGINAL_MSG) |
1984 | goto deliver; | 1985 | goto deliver; |
1985 | goto protocol_check; | 1986 | goto protocol_check; |
@@ -2263,7 +2264,8 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) | |||
2263 | switch (msg_type(msg)) { | 2264 | switch (msg_type(msg)) { |
2264 | 2265 | ||
2265 | case RESET_MSG: | 2266 | case RESET_MSG: |
2266 | if (!link_working_unknown(l_ptr) && l_ptr->peer_session) { | 2267 | if (!link_working_unknown(l_ptr) && |
2268 | (l_ptr->peer_session != INVALID_SESSION)) { | ||
2267 | if (msg_session(msg) == l_ptr->peer_session) { | 2269 | if (msg_session(msg) == l_ptr->peer_session) { |
2268 | dbg("Duplicate RESET: %u<->%u\n", | 2270 | dbg("Duplicate RESET: %u<->%u\n", |
2269 | msg_session(msg), l_ptr->peer_session); | 2271 | msg_session(msg), l_ptr->peer_session); |
@@ -2424,7 +2426,7 @@ void tipc_link_changeover(struct link *l_ptr) | |||
2424 | } | 2426 | } |
2425 | 2427 | ||
2426 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | 2428 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, |
2427 | ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | 2429 | ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr); |
2428 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | 2430 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); |
2429 | msg_set_msgcnt(&tunnel_hdr, msgcount); | 2431 | msg_set_msgcnt(&tunnel_hdr, msgcount); |
2430 | dbg("Link changeover requires %u tunnel messages\n", msgcount); | 2432 | dbg("Link changeover requires %u tunnel messages\n", msgcount); |
@@ -2479,7 +2481,7 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel) | |||
2479 | struct tipc_msg tunnel_hdr; | 2481 | struct tipc_msg tunnel_hdr; |
2480 | 2482 | ||
2481 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | 2483 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, |
2482 | DUPLICATE_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | 2484 | DUPLICATE_MSG, INT_H_SIZE, l_ptr->addr); |
2483 | msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size); | 2485 | msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size); |
2484 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | 2486 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); |
2485 | iter = l_ptr->first_out; | 2487 | iter = l_ptr->first_out; |
@@ -2672,10 +2674,12 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2672 | u32 pack_sz = link_max_pkt(l_ptr); | 2674 | u32 pack_sz = link_max_pkt(l_ptr); |
2673 | u32 fragm_sz = pack_sz - INT_H_SIZE; | 2675 | u32 fragm_sz = pack_sz - INT_H_SIZE; |
2674 | u32 fragm_no = 1; | 2676 | u32 fragm_no = 1; |
2675 | u32 destaddr = msg_destnode(inmsg); | 2677 | u32 destaddr; |
2676 | 2678 | ||
2677 | if (msg_short(inmsg)) | 2679 | if (msg_short(inmsg)) |
2678 | destaddr = l_ptr->addr; | 2680 | destaddr = l_ptr->addr; |
2681 | else | ||
2682 | destaddr = msg_destnode(inmsg); | ||
2679 | 2683 | ||
2680 | if (msg_routed(inmsg)) | 2684 | if (msg_routed(inmsg)) |
2681 | msg_set_prevnode(inmsg, tipc_own_addr); | 2685 | msg_set_prevnode(inmsg, tipc_own_addr); |
@@ -2683,7 +2687,7 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2683 | /* Prepare reusable fragment header: */ | 2687 | /* Prepare reusable fragment header: */ |
2684 | 2688 | ||
2685 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | 2689 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, |
2686 | TIPC_OK, INT_H_SIZE, destaddr); | 2690 | INT_H_SIZE, destaddr); |
2687 | msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); | 2691 | msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); |
2688 | msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); | 2692 | msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); |
2689 | msg_set_fragm_no(&fragm_hdr, fragm_no); | 2693 | msg_set_fragm_no(&fragm_hdr, fragm_no); |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 696a8633df75..73dcd00d674e 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -41,7 +41,9 @@ | |||
41 | #include "bearer.h" | 41 | #include "bearer.h" |
42 | 42 | ||
43 | 43 | ||
44 | void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str) | 44 | #ifdef CONFIG_TIPC_DEBUG |
45 | |||
46 | void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) | ||
45 | { | 47 | { |
46 | u32 usr = msg_user(msg); | 48 | u32 usr = msg_user(msg); |
47 | tipc_printf(buf, str); | 49 | tipc_printf(buf, str); |
@@ -228,13 +230,10 @@ void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str | |||
228 | 230 | ||
229 | switch (usr) { | 231 | switch (usr) { |
230 | case CONN_MANAGER: | 232 | case CONN_MANAGER: |
231 | case NAME_DISTRIBUTOR: | ||
232 | case TIPC_LOW_IMPORTANCE: | 233 | case TIPC_LOW_IMPORTANCE: |
233 | case TIPC_MEDIUM_IMPORTANCE: | 234 | case TIPC_MEDIUM_IMPORTANCE: |
234 | case TIPC_HIGH_IMPORTANCE: | 235 | case TIPC_HIGH_IMPORTANCE: |
235 | case TIPC_CRITICAL_IMPORTANCE: | 236 | case TIPC_CRITICAL_IMPORTANCE: |
236 | if (msg_short(msg)) | ||
237 | break; /* No error */ | ||
238 | switch (msg_errcode(msg)) { | 237 | switch (msg_errcode(msg)) { |
239 | case TIPC_OK: | 238 | case TIPC_OK: |
240 | break; | 239 | break; |
@@ -315,9 +314,11 @@ void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str | |||
315 | } | 314 | } |
316 | tipc_printf(buf, "\n"); | 315 | tipc_printf(buf, "\n"); |
317 | if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) { | 316 | if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) { |
318 | tipc_msg_print(buf,msg_get_wrapped(msg)," /"); | 317 | tipc_msg_dbg(buf, msg_get_wrapped(msg), " /"); |
319 | } | 318 | } |
320 | if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) { | 319 | if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) { |
321 | tipc_msg_print(buf,msg_get_wrapped(msg)," /"); | 320 | tipc_msg_dbg(buf, msg_get_wrapped(msg), " /"); |
322 | } | 321 | } |
323 | } | 322 | } |
323 | |||
324 | #endif | ||
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index ad487e8abcc2..7ee6ae238147 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/msg.h: Include file for TIPC message header routines | 2 | * net/tipc/msg.h: Include file for TIPC message header routines |
3 | * | 3 | * |
4 | * Copyright (c) 2000-2007, Ericsson AB | 4 | * Copyright (c) 2000-2007, Ericsson AB |
5 | * Copyright (c) 2005-2007, Wind River Systems | 5 | * Copyright (c) 2005-2008, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -75,6 +75,14 @@ static inline void msg_set_bits(struct tipc_msg *m, u32 w, | |||
75 | m->hdr[w] |= htonl(val); | 75 | m->hdr[w] |= htonl(val); |
76 | } | 76 | } |
77 | 77 | ||
78 | static inline void msg_swap_words(struct tipc_msg *msg, u32 a, u32 b) | ||
79 | { | ||
80 | u32 temp = msg->hdr[a]; | ||
81 | |||
82 | msg->hdr[a] = msg->hdr[b]; | ||
83 | msg->hdr[b] = temp; | ||
84 | } | ||
85 | |||
78 | /* | 86 | /* |
79 | * Word 0 | 87 | * Word 0 |
80 | */ | 88 | */ |
@@ -119,9 +127,9 @@ static inline int msg_non_seq(struct tipc_msg *m) | |||
119 | return msg_bits(m, 0, 20, 1); | 127 | return msg_bits(m, 0, 20, 1); |
120 | } | 128 | } |
121 | 129 | ||
122 | static inline void msg_set_non_seq(struct tipc_msg *m) | 130 | static inline void msg_set_non_seq(struct tipc_msg *m, u32 n) |
123 | { | 131 | { |
124 | msg_set_bits(m, 0, 20, 1, 1); | 132 | msg_set_bits(m, 0, 20, 1, n); |
125 | } | 133 | } |
126 | 134 | ||
127 | static inline int msg_dest_droppable(struct tipc_msg *m) | 135 | static inline int msg_dest_droppable(struct tipc_msg *m) |
@@ -224,6 +232,25 @@ static inline void msg_set_seqno(struct tipc_msg *m, u32 n) | |||
224 | msg_set_bits(m, 2, 0, 0xffff, n); | 232 | msg_set_bits(m, 2, 0, 0xffff, n); |
225 | } | 233 | } |
226 | 234 | ||
235 | /* | ||
236 | * TIPC may utilize the "link ack #" and "link seq #" fields of a short | ||
237 | * message header to hold the destination node for the message, since the | ||
238 | * normal "dest node" field isn't present. This cache is only referenced | ||
239 | * when required, so populating the cache of a longer message header is | ||
240 | * harmless (as long as the header has the two link sequence fields present). | ||
241 | * | ||
242 | * Note: Host byte order is OK here, since the info never goes off-card. | ||
243 | */ | ||
244 | |||
245 | static inline u32 msg_destnode_cache(struct tipc_msg *m) | ||
246 | { | ||
247 | return m->hdr[2]; | ||
248 | } | ||
249 | |||
250 | static inline void msg_set_destnode_cache(struct tipc_msg *m, u32 dnode) | ||
251 | { | ||
252 | m->hdr[2] = dnode; | ||
253 | } | ||
227 | 254 | ||
228 | /* | 255 | /* |
229 | * Words 3-10 | 256 | * Words 3-10 |
@@ -325,7 +352,7 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) | |||
325 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 352 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
326 | w0:|vers |msg usr|hdr sz |n|resrv| packet size | | 353 | w0:|vers |msg usr|hdr sz |n|resrv| packet size | |
327 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 354 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
328 | w1:|m typ|rsv=0| sequence gap | broadcast ack no | | 355 | w1:|m typ| sequence gap | broadcast ack no | |
329 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 356 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
330 | w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | | 357 | w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | |
331 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 358 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
@@ -388,12 +415,12 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) | |||
388 | 415 | ||
389 | static inline u32 msg_seq_gap(struct tipc_msg *m) | 416 | static inline u32 msg_seq_gap(struct tipc_msg *m) |
390 | { | 417 | { |
391 | return msg_bits(m, 1, 16, 0xff); | 418 | return msg_bits(m, 1, 16, 0x1fff); |
392 | } | 419 | } |
393 | 420 | ||
394 | static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) | 421 | static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) |
395 | { | 422 | { |
396 | msg_set_bits(m, 1, 16, 0xff, n); | 423 | msg_set_bits(m, 1, 16, 0x1fff, n); |
397 | } | 424 | } |
398 | 425 | ||
399 | static inline u32 msg_req_links(struct tipc_msg *m) | 426 | static inline u32 msg_req_links(struct tipc_msg *m) |
@@ -696,7 +723,7 @@ static inline u32 msg_tot_importance(struct tipc_msg *m) | |||
696 | 723 | ||
697 | 724 | ||
698 | static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, | 725 | static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, |
699 | u32 err, u32 hsize, u32 destnode) | 726 | u32 hsize, u32 destnode) |
700 | { | 727 | { |
701 | memset(m, 0, hsize); | 728 | memset(m, 0, hsize); |
702 | msg_set_version(m); | 729 | msg_set_version(m); |
@@ -705,7 +732,6 @@ static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, | |||
705 | msg_set_size(m, hsize); | 732 | msg_set_size(m, hsize); |
706 | msg_set_prevnode(m, tipc_own_addr); | 733 | msg_set_prevnode(m, tipc_own_addr); |
707 | msg_set_type(m, type); | 734 | msg_set_type(m, type); |
708 | msg_set_errcode(m, err); | ||
709 | if (!msg_short(m)) { | 735 | if (!msg_short(m)) { |
710 | msg_set_orignode(m, tipc_own_addr); | 736 | msg_set_orignode(m, tipc_own_addr); |
711 | msg_set_destnode(m, destnode); | 737 | msg_set_destnode(m, destnode); |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 39fd1619febf..10a69894e2fd 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -41,9 +41,6 @@ | |||
41 | #include "msg.h" | 41 | #include "msg.h" |
42 | #include "name_distr.h" | 42 | #include "name_distr.h" |
43 | 43 | ||
44 | #undef DBG_OUTPUT | ||
45 | #define DBG_OUTPUT NULL | ||
46 | |||
47 | #define ITEM_SIZE sizeof(struct distr_item) | 44 | #define ITEM_SIZE sizeof(struct distr_item) |
48 | 45 | ||
49 | /** | 46 | /** |
@@ -106,8 +103,7 @@ static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) | |||
106 | 103 | ||
107 | if (buf != NULL) { | 104 | if (buf != NULL) { |
108 | msg = buf_msg(buf); | 105 | msg = buf_msg(buf); |
109 | msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK, | 106 | msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest); |
110 | LONG_H_SIZE, dest); | ||
111 | msg_set_size(msg, LONG_H_SIZE + size); | 107 | msg_set_size(msg, LONG_H_SIZE + size); |
112 | } | 108 | } |
113 | return buf; | 109 | return buf; |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index ac7dfdda7973..096f7bd240a0 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -74,7 +74,7 @@ struct sub_seq { | |||
74 | * @first_free: array index of first unused sub-sequence entry | 74 | * @first_free: array index of first unused sub-sequence entry |
75 | * @ns_list: links to adjacent name sequences in hash chain | 75 | * @ns_list: links to adjacent name sequences in hash chain |
76 | * @subscriptions: list of subscriptions for this 'type' | 76 | * @subscriptions: list of subscriptions for this 'type' |
77 | * @lock: spinlock controlling access to name sequence structure | 77 | * @lock: spinlock controlling access to publication lists of all sub-sequences |
78 | */ | 78 | */ |
79 | 79 | ||
80 | struct name_seq { | 80 | struct name_seq { |
@@ -905,6 +905,9 @@ static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, | |||
905 | struct sub_seq *sseq; | 905 | struct sub_seq *sseq; |
906 | char typearea[11]; | 906 | char typearea[11]; |
907 | 907 | ||
908 | if (seq->first_free == 0) | ||
909 | return; | ||
910 | |||
908 | sprintf(typearea, "%-10u", seq->type); | 911 | sprintf(typearea, "%-10u", seq->type); |
909 | 912 | ||
910 | if (depth == 1) { | 913 | if (depth == 1) { |
@@ -915,7 +918,9 @@ static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, | |||
915 | for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { | 918 | for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { |
916 | if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { | 919 | if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { |
917 | tipc_printf(buf, "%s ", typearea); | 920 | tipc_printf(buf, "%s ", typearea); |
921 | spin_lock_bh(&seq->lock); | ||
918 | subseq_list(sseq, buf, depth, index); | 922 | subseq_list(sseq, buf, depth, index); |
923 | spin_unlock_bh(&seq->lock); | ||
919 | sprintf(typearea, "%10s", " "); | 924 | sprintf(typearea, "%10s", " "); |
920 | } | 925 | } |
921 | } | 926 | } |
@@ -1050,15 +1055,12 @@ void tipc_nametbl_dump(void) | |||
1050 | 1055 | ||
1051 | int tipc_nametbl_init(void) | 1056 | int tipc_nametbl_init(void) |
1052 | { | 1057 | { |
1053 | int array_size = sizeof(struct hlist_head) * tipc_nametbl_size; | 1058 | table.types = kcalloc(tipc_nametbl_size, sizeof(struct hlist_head), |
1054 | 1059 | GFP_ATOMIC); | |
1055 | table.types = kzalloc(array_size, GFP_ATOMIC); | ||
1056 | if (!table.types) | 1060 | if (!table.types) |
1057 | return -ENOMEM; | 1061 | return -ENOMEM; |
1058 | 1062 | ||
1059 | write_lock_bh(&tipc_nametbl_lock); | ||
1060 | table.local_publ_count = 0; | 1063 | table.local_publ_count = 0; |
1061 | write_unlock_bh(&tipc_nametbl_lock); | ||
1062 | return 0; | 1064 | return 0; |
1063 | } | 1065 | } |
1064 | 1066 | ||
diff --git a/net/tipc/net.c b/net/tipc/net.c index c39c76201e8e..cc51fa483672 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -266,7 +266,7 @@ void tipc_net_route_msg(struct sk_buff *buf) | |||
266 | tipc_link_send(buf, dnode, msg_link_selector(msg)); | 266 | tipc_link_send(buf, dnode, msg_link_selector(msg)); |
267 | } | 267 | } |
268 | 268 | ||
269 | int tipc_net_start(void) | 269 | int tipc_net_start(u32 addr) |
270 | { | 270 | { |
271 | char addr_string[16]; | 271 | char addr_string[16]; |
272 | int res; | 272 | int res; |
@@ -274,6 +274,10 @@ int tipc_net_start(void) | |||
274 | if (tipc_mode != TIPC_NODE_MODE) | 274 | if (tipc_mode != TIPC_NODE_MODE) |
275 | return -ENOPROTOOPT; | 275 | return -ENOPROTOOPT; |
276 | 276 | ||
277 | tipc_subscr_stop(); | ||
278 | tipc_cfg_stop(); | ||
279 | |||
280 | tipc_own_addr = addr; | ||
277 | tipc_mode = TIPC_NET_MODE; | 281 | tipc_mode = TIPC_NET_MODE; |
278 | tipc_named_reinit(); | 282 | tipc_named_reinit(); |
279 | tipc_port_reinit(); | 283 | tipc_port_reinit(); |
@@ -284,10 +288,10 @@ int tipc_net_start(void) | |||
284 | (res = tipc_bclink_init())) { | 288 | (res = tipc_bclink_init())) { |
285 | return res; | 289 | return res; |
286 | } | 290 | } |
287 | tipc_subscr_stop(); | 291 | |
288 | tipc_cfg_stop(); | ||
289 | tipc_k_signal((Handler)tipc_subscr_start, 0); | 292 | tipc_k_signal((Handler)tipc_subscr_start, 0); |
290 | tipc_k_signal((Handler)tipc_cfg_init, 0); | 293 | tipc_k_signal((Handler)tipc_cfg_init, 0); |
294 | |||
291 | info("Started in network mode\n"); | 295 | info("Started in network mode\n"); |
292 | info("Own node address %s, network identity %u\n", | 296 | info("Own node address %s, network identity %u\n", |
293 | addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); | 297 | addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); |
diff --git a/net/tipc/net.h b/net/tipc/net.h index a6a0e9976ac9..d154ac2bda9a 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h | |||
@@ -58,7 +58,7 @@ void tipc_net_route_msg(struct sk_buff *buf); | |||
58 | struct node *tipc_net_select_remote_node(u32 addr, u32 ref); | 58 | struct node *tipc_net_select_remote_node(u32 addr, u32 ref); |
59 | u32 tipc_net_select_router(u32 addr, u32 ref); | 59 | u32 tipc_net_select_router(u32 addr, u32 ref); |
60 | 60 | ||
61 | int tipc_net_start(void); | 61 | int tipc_net_start(u32 addr); |
62 | void tipc_net_stop(void); | 62 | void tipc_net_stop(void); |
63 | 63 | ||
64 | #endif | 64 | #endif |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 6a7f7b4c2595..c387217bb230 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/netlink.c: TIPC configuration handling | 2 | * net/tipc/netlink.c: TIPC configuration handling |
3 | * | 3 | * |
4 | * Copyright (c) 2005-2006, Ericsson AB | 4 | * Copyright (c) 2005-2006, Ericsson AB |
5 | * Copyright (c) 2005, Wind River Systems | 5 | * Copyright (c) 2005-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -45,15 +45,17 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) | |||
45 | struct nlmsghdr *req_nlh = info->nlhdr; | 45 | struct nlmsghdr *req_nlh = info->nlhdr; |
46 | struct tipc_genlmsghdr *req_userhdr = info->userhdr; | 46 | struct tipc_genlmsghdr *req_userhdr = info->userhdr; |
47 | int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN); | 47 | int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN); |
48 | u16 cmd; | ||
48 | 49 | ||
49 | if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN))) | 50 | if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN))) |
50 | rep_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); | 51 | cmd = TIPC_CMD_NOT_NET_ADMIN; |
51 | else | 52 | else |
52 | rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, | 53 | cmd = req_userhdr->cmd; |
53 | req_userhdr->cmd, | 54 | |
54 | NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, | 55 | rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd, |
55 | NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), | 56 | NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, |
56 | hdr_space); | 57 | NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), |
58 | hdr_space); | ||
57 | 59 | ||
58 | if (rep_buf) { | 60 | if (rep_buf) { |
59 | skb_push(rep_buf, hdr_space); | 61 | skb_push(rep_buf, hdr_space); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 598f4d3a0098..34e9a2bb7c19 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -52,16 +52,40 @@ static void node_established_contact(struct node *n_ptr); | |||
52 | 52 | ||
53 | struct node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ | 53 | struct node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ |
54 | 54 | ||
55 | static DEFINE_SPINLOCK(node_create_lock); | ||
56 | |||
55 | u32 tipc_own_tag = 0; | 57 | u32 tipc_own_tag = 0; |
56 | 58 | ||
59 | /** | ||
60 | * tipc_node_create - create neighboring node | ||
61 | * | ||
62 | * Currently, this routine is called by neighbor discovery code, which holds | ||
63 | * net_lock for reading only. We must take node_create_lock to ensure a node | ||
64 | * isn't created twice if two different bearers discover the node at the same | ||
65 | * time. (It would be preferable to switch to holding net_lock in write mode, | ||
66 | * but this is a non-trivial change.) | ||
67 | */ | ||
68 | |||
57 | struct node *tipc_node_create(u32 addr) | 69 | struct node *tipc_node_create(u32 addr) |
58 | { | 70 | { |
59 | struct cluster *c_ptr; | 71 | struct cluster *c_ptr; |
60 | struct node *n_ptr; | 72 | struct node *n_ptr; |
61 | struct node **curr_node; | 73 | struct node **curr_node; |
62 | 74 | ||
75 | spin_lock_bh(&node_create_lock); | ||
76 | |||
77 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | ||
78 | if (addr < n_ptr->addr) | ||
79 | break; | ||
80 | if (addr == n_ptr->addr) { | ||
81 | spin_unlock_bh(&node_create_lock); | ||
82 | return n_ptr; | ||
83 | } | ||
84 | } | ||
85 | |||
63 | n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); | 86 | n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); |
64 | if (!n_ptr) { | 87 | if (!n_ptr) { |
88 | spin_unlock_bh(&node_create_lock); | ||
65 | warn("Node creation failed, no memory\n"); | 89 | warn("Node creation failed, no memory\n"); |
66 | return NULL; | 90 | return NULL; |
67 | } | 91 | } |
@@ -71,6 +95,7 @@ struct node *tipc_node_create(u32 addr) | |||
71 | c_ptr = tipc_cltr_create(addr); | 95 | c_ptr = tipc_cltr_create(addr); |
72 | } | 96 | } |
73 | if (!c_ptr) { | 97 | if (!c_ptr) { |
98 | spin_unlock_bh(&node_create_lock); | ||
74 | kfree(n_ptr); | 99 | kfree(n_ptr); |
75 | return NULL; | 100 | return NULL; |
76 | } | 101 | } |
@@ -91,6 +116,7 @@ struct node *tipc_node_create(u32 addr) | |||
91 | } | 116 | } |
92 | } | 117 | } |
93 | (*curr_node) = n_ptr; | 118 | (*curr_node) = n_ptr; |
119 | spin_unlock_bh(&node_create_lock); | ||
94 | return n_ptr; | 120 | return n_ptr; |
95 | } | 121 | } |
96 | 122 | ||
diff --git a/net/tipc/port.c b/net/tipc/port.c index 2f5806410c64..2e0cff408ff9 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -211,15 +211,18 @@ exit: | |||
211 | } | 211 | } |
212 | 212 | ||
213 | /** | 213 | /** |
214 | * tipc_createport_raw - create a native TIPC port | 214 | * tipc_createport_raw - create a generic TIPC port |
215 | * | 215 | * |
216 | * Returns local port reference | 216 | * Returns port reference, or 0 if unable to create it |
217 | * | ||
218 | * Note: The newly created port is returned in the locked state. | ||
217 | */ | 219 | */ |
218 | 220 | ||
219 | u32 tipc_createport_raw(void *usr_handle, | 221 | u32 tipc_createport_raw(void *usr_handle, |
220 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), | 222 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), |
221 | void (*wakeup)(struct tipc_port *), | 223 | void (*wakeup)(struct tipc_port *), |
222 | const u32 importance) | 224 | const u32 importance, |
225 | struct tipc_port **tp_ptr) | ||
223 | { | 226 | { |
224 | struct port *p_ptr; | 227 | struct port *p_ptr; |
225 | struct tipc_msg *msg; | 228 | struct tipc_msg *msg; |
@@ -237,17 +240,12 @@ u32 tipc_createport_raw(void *usr_handle, | |||
237 | return 0; | 240 | return 0; |
238 | } | 241 | } |
239 | 242 | ||
240 | tipc_port_lock(ref); | ||
241 | p_ptr->publ.usr_handle = usr_handle; | 243 | p_ptr->publ.usr_handle = usr_handle; |
242 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; | 244 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; |
243 | p_ptr->publ.ref = ref; | 245 | p_ptr->publ.ref = ref; |
244 | msg = &p_ptr->publ.phdr; | 246 | msg = &p_ptr->publ.phdr; |
245 | msg_init(msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, | 247 | msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0); |
246 | 0); | ||
247 | msg_set_orignode(msg, tipc_own_addr); | ||
248 | msg_set_prevnode(msg, tipc_own_addr); | ||
249 | msg_set_origport(msg, ref); | 248 | msg_set_origport(msg, ref); |
250 | msg_set_importance(msg,importance); | ||
251 | p_ptr->last_in_seqno = 41; | 249 | p_ptr->last_in_seqno = 41; |
252 | p_ptr->sent = 1; | 250 | p_ptr->sent = 1; |
253 | INIT_LIST_HEAD(&p_ptr->wait_list); | 251 | INIT_LIST_HEAD(&p_ptr->wait_list); |
@@ -262,7 +260,7 @@ u32 tipc_createport_raw(void *usr_handle, | |||
262 | INIT_LIST_HEAD(&p_ptr->port_list); | 260 | INIT_LIST_HEAD(&p_ptr->port_list); |
263 | list_add_tail(&p_ptr->port_list, &ports); | 261 | list_add_tail(&p_ptr->port_list, &ports); |
264 | spin_unlock_bh(&tipc_port_list_lock); | 262 | spin_unlock_bh(&tipc_port_list_lock); |
265 | tipc_port_unlock(p_ptr); | 263 | *tp_ptr = &p_ptr->publ; |
266 | return ref; | 264 | return ref; |
267 | } | 265 | } |
268 | 266 | ||
@@ -402,10 +400,10 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, | |||
402 | buf = buf_acquire(LONG_H_SIZE); | 400 | buf = buf_acquire(LONG_H_SIZE); |
403 | if (buf) { | 401 | if (buf) { |
404 | msg = buf_msg(buf); | 402 | msg = buf_msg(buf); |
405 | msg_init(msg, usr, type, err, LONG_H_SIZE, destnode); | 403 | msg_init(msg, usr, type, LONG_H_SIZE, destnode); |
404 | msg_set_errcode(msg, err); | ||
406 | msg_set_destport(msg, destport); | 405 | msg_set_destport(msg, destport); |
407 | msg_set_origport(msg, origport); | 406 | msg_set_origport(msg, origport); |
408 | msg_set_destnode(msg, destnode); | ||
409 | msg_set_orignode(msg, orignode); | 407 | msg_set_orignode(msg, orignode); |
410 | msg_set_transp_seqno(msg, seqno); | 408 | msg_set_transp_seqno(msg, seqno); |
411 | msg_set_msgcnt(msg, ack); | 409 | msg_set_msgcnt(msg, ack); |
@@ -446,17 +444,19 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) | |||
446 | return data_sz; | 444 | return data_sz; |
447 | } | 445 | } |
448 | rmsg = buf_msg(rbuf); | 446 | rmsg = buf_msg(rbuf); |
449 | msg_init(rmsg, imp, msg_type(msg), err, hdr_sz, msg_orignode(msg)); | 447 | msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); |
448 | msg_set_errcode(rmsg, err); | ||
450 | msg_set_destport(rmsg, msg_origport(msg)); | 449 | msg_set_destport(rmsg, msg_origport(msg)); |
451 | msg_set_prevnode(rmsg, tipc_own_addr); | ||
452 | msg_set_origport(rmsg, msg_destport(msg)); | 450 | msg_set_origport(rmsg, msg_destport(msg)); |
453 | if (msg_short(msg)) | 451 | if (msg_short(msg)) { |
454 | msg_set_orignode(rmsg, tipc_own_addr); | 452 | msg_set_orignode(rmsg, tipc_own_addr); |
455 | else | 453 | /* leave name type & instance as zeroes */ |
454 | } else { | ||
456 | msg_set_orignode(rmsg, msg_destnode(msg)); | 455 | msg_set_orignode(rmsg, msg_destnode(msg)); |
456 | msg_set_nametype(rmsg, msg_nametype(msg)); | ||
457 | msg_set_nameinst(rmsg, msg_nameinst(msg)); | ||
458 | } | ||
457 | msg_set_size(rmsg, data_sz + hdr_sz); | 459 | msg_set_size(rmsg, data_sz + hdr_sz); |
458 | msg_set_nametype(rmsg, msg_nametype(msg)); | ||
459 | msg_set_nameinst(rmsg, msg_nameinst(msg)); | ||
460 | skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz); | 460 | skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz); |
461 | 461 | ||
462 | /* send self-abort message when rejecting on a connected port */ | 462 | /* send self-abort message when rejecting on a connected port */ |
@@ -778,6 +778,7 @@ void tipc_port_reinit(void) | |||
778 | msg = &p_ptr->publ.phdr; | 778 | msg = &p_ptr->publ.phdr; |
779 | if (msg_orignode(msg) == tipc_own_addr) | 779 | if (msg_orignode(msg) == tipc_own_addr) |
780 | break; | 780 | break; |
781 | msg_set_prevnode(msg, tipc_own_addr); | ||
781 | msg_set_orignode(msg, tipc_own_addr); | 782 | msg_set_orignode(msg, tipc_own_addr); |
782 | } | 783 | } |
783 | spin_unlock_bh(&tipc_port_list_lock); | 784 | spin_unlock_bh(&tipc_port_list_lock); |
@@ -838,16 +839,13 @@ static void port_dispatcher_sigh(void *dummy) | |||
838 | u32 peer_node = port_peernode(p_ptr); | 839 | u32 peer_node = port_peernode(p_ptr); |
839 | 840 | ||
840 | tipc_port_unlock(p_ptr); | 841 | tipc_port_unlock(p_ptr); |
842 | if (unlikely(!cb)) | ||
843 | goto reject; | ||
841 | if (unlikely(!connected)) { | 844 | if (unlikely(!connected)) { |
842 | if (unlikely(published)) | 845 | if (tipc_connect2port(dref, &orig)) |
843 | goto reject; | 846 | goto reject; |
844 | tipc_connect2port(dref,&orig); | 847 | } else if ((msg_origport(msg) != peer_port) || |
845 | } | 848 | (msg_orignode(msg) != peer_node)) |
846 | if (unlikely(msg_origport(msg) != peer_port)) | ||
847 | goto reject; | ||
848 | if (unlikely(msg_orignode(msg) != peer_node)) | ||
849 | goto reject; | ||
850 | if (unlikely(!cb)) | ||
851 | goto reject; | 849 | goto reject; |
852 | if (unlikely(++p_ptr->publ.conn_unacked >= | 850 | if (unlikely(++p_ptr->publ.conn_unacked >= |
853 | TIPC_FLOW_CONTROL_WIN)) | 851 | TIPC_FLOW_CONTROL_WIN)) |
@@ -862,9 +860,7 @@ static void port_dispatcher_sigh(void *dummy) | |||
862 | tipc_msg_event cb = up_ptr->msg_cb; | 860 | tipc_msg_event cb = up_ptr->msg_cb; |
863 | 861 | ||
864 | tipc_port_unlock(p_ptr); | 862 | tipc_port_unlock(p_ptr); |
865 | if (unlikely(connected)) | 863 | if (unlikely(!cb || connected)) |
866 | goto reject; | ||
867 | if (unlikely(!cb)) | ||
868 | goto reject; | 864 | goto reject; |
869 | skb_pull(buf, msg_hdr_sz(msg)); | 865 | skb_pull(buf, msg_hdr_sz(msg)); |
870 | cb(usr_handle, dref, &buf, msg_data(msg), | 866 | cb(usr_handle, dref, &buf, msg_data(msg), |
@@ -877,11 +873,7 @@ static void port_dispatcher_sigh(void *dummy) | |||
877 | tipc_named_msg_event cb = up_ptr->named_msg_cb; | 873 | tipc_named_msg_event cb = up_ptr->named_msg_cb; |
878 | 874 | ||
879 | tipc_port_unlock(p_ptr); | 875 | tipc_port_unlock(p_ptr); |
880 | if (unlikely(connected)) | 876 | if (unlikely(!cb || connected || !published)) |
881 | goto reject; | ||
882 | if (unlikely(!cb)) | ||
883 | goto reject; | ||
884 | if (unlikely(!published)) | ||
885 | goto reject; | 877 | goto reject; |
886 | dseq.type = msg_nametype(msg); | 878 | dseq.type = msg_nametype(msg); |
887 | dseq.lower = msg_nameinst(msg); | 879 | dseq.lower = msg_nameinst(msg); |
@@ -908,11 +900,10 @@ err: | |||
908 | u32 peer_node = port_peernode(p_ptr); | 900 | u32 peer_node = port_peernode(p_ptr); |
909 | 901 | ||
910 | tipc_port_unlock(p_ptr); | 902 | tipc_port_unlock(p_ptr); |
911 | if (!connected || !cb) | 903 | if (!cb || !connected) |
912 | break; | ||
913 | if (msg_origport(msg) != peer_port) | ||
914 | break; | 904 | break; |
915 | if (msg_orignode(msg) != peer_node) | 905 | if ((msg_origport(msg) != peer_port) || |
906 | (msg_orignode(msg) != peer_node)) | ||
916 | break; | 907 | break; |
917 | tipc_disconnect(dref); | 908 | tipc_disconnect(dref); |
918 | skb_pull(buf, msg_hdr_sz(msg)); | 909 | skb_pull(buf, msg_hdr_sz(msg)); |
@@ -924,7 +915,7 @@ err: | |||
924 | tipc_msg_err_event cb = up_ptr->err_cb; | 915 | tipc_msg_err_event cb = up_ptr->err_cb; |
925 | 916 | ||
926 | tipc_port_unlock(p_ptr); | 917 | tipc_port_unlock(p_ptr); |
927 | if (connected || !cb) | 918 | if (!cb || connected) |
928 | break; | 919 | break; |
929 | skb_pull(buf, msg_hdr_sz(msg)); | 920 | skb_pull(buf, msg_hdr_sz(msg)); |
930 | cb(usr_handle, dref, &buf, msg_data(msg), | 921 | cb(usr_handle, dref, &buf, msg_data(msg), |
@@ -937,7 +928,7 @@ err: | |||
937 | up_ptr->named_err_cb; | 928 | up_ptr->named_err_cb; |
938 | 929 | ||
939 | tipc_port_unlock(p_ptr); | 930 | tipc_port_unlock(p_ptr); |
940 | if (connected || !cb) | 931 | if (!cb || connected) |
941 | break; | 932 | break; |
942 | dseq.type = msg_nametype(msg); | 933 | dseq.type = msg_nametype(msg); |
943 | dseq.lower = msg_nameinst(msg); | 934 | dseq.lower = msg_nameinst(msg); |
@@ -1053,6 +1044,7 @@ int tipc_createport(u32 user_ref, | |||
1053 | { | 1044 | { |
1054 | struct user_port *up_ptr; | 1045 | struct user_port *up_ptr; |
1055 | struct port *p_ptr; | 1046 | struct port *p_ptr; |
1047 | struct tipc_port *tp_ptr; | ||
1056 | u32 ref; | 1048 | u32 ref; |
1057 | 1049 | ||
1058 | up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); | 1050 | up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); |
@@ -1060,12 +1052,13 @@ int tipc_createport(u32 user_ref, | |||
1060 | warn("Port creation failed, no memory\n"); | 1052 | warn("Port creation failed, no memory\n"); |
1061 | return -ENOMEM; | 1053 | return -ENOMEM; |
1062 | } | 1054 | } |
1063 | ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, importance); | 1055 | ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, |
1064 | p_ptr = tipc_port_lock(ref); | 1056 | importance, &tp_ptr); |
1065 | if (!p_ptr) { | 1057 | if (ref == 0) { |
1066 | kfree(up_ptr); | 1058 | kfree(up_ptr); |
1067 | return -ENOMEM; | 1059 | return -ENOMEM; |
1068 | } | 1060 | } |
1061 | p_ptr = (struct port *)tp_ptr; | ||
1069 | 1062 | ||
1070 | p_ptr->user_port = up_ptr; | 1063 | p_ptr->user_port = up_ptr; |
1071 | up_ptr->user_ref = user_ref; | 1064 | up_ptr->user_ref = user_ref; |
diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 89cbab24d08f..a101de86824d 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c | |||
@@ -142,9 +142,13 @@ void tipc_ref_table_stop(void) | |||
142 | /** | 142 | /** |
143 | * tipc_ref_acquire - create reference to an object | 143 | * tipc_ref_acquire - create reference to an object |
144 | * | 144 | * |
145 | * Return a unique reference value which can be translated back to the pointer | 145 | * Register an object pointer in reference table and lock the object. |
146 | * 'object' at a later time. Also, pass back a pointer to the lock protecting | 146 | * Returns a unique reference value that is used from then on to retrieve the |
147 | * the object, but without locking it. | 147 | * object pointer, or to determine that the object has been deregistered. |
148 | * | ||
149 | * Note: The object is returned in the locked state so that the caller can | ||
150 | * register a partially initialized object, without running the risk that | ||
151 | * the object will be accessed before initialization is complete. | ||
148 | */ | 152 | */ |
149 | 153 | ||
150 | u32 tipc_ref_acquire(void *object, spinlock_t **lock) | 154 | u32 tipc_ref_acquire(void *object, spinlock_t **lock) |
@@ -178,13 +182,13 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) | |||
178 | ref = (next_plus_upper & ~index_mask) + index; | 182 | ref = (next_plus_upper & ~index_mask) + index; |
179 | entry->ref = ref; | 183 | entry->ref = ref; |
180 | entry->object = object; | 184 | entry->object = object; |
181 | spin_unlock_bh(&entry->lock); | ||
182 | *lock = &entry->lock; | 185 | *lock = &entry->lock; |
183 | } | 186 | } |
184 | else if (tipc_ref_table.init_point < tipc_ref_table.capacity) { | 187 | else if (tipc_ref_table.init_point < tipc_ref_table.capacity) { |
185 | index = tipc_ref_table.init_point++; | 188 | index = tipc_ref_table.init_point++; |
186 | entry = &(tipc_ref_table.entries[index]); | 189 | entry = &(tipc_ref_table.entries[index]); |
187 | spin_lock_init(&entry->lock); | 190 | spin_lock_init(&entry->lock); |
191 | spin_lock_bh(&entry->lock); | ||
188 | ref = tipc_ref_table.start_mask + index; | 192 | ref = tipc_ref_table.start_mask + index; |
189 | entry->ref = ref; | 193 | entry->ref = ref; |
190 | entry->object = object; | 194 | entry->object = object; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 230f9ca2ad6b..38f48795b40e 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -188,6 +188,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol) | |||
188 | const struct proto_ops *ops; | 188 | const struct proto_ops *ops; |
189 | socket_state state; | 189 | socket_state state; |
190 | struct sock *sk; | 190 | struct sock *sk; |
191 | struct tipc_port *tp_ptr; | ||
191 | u32 portref; | 192 | u32 portref; |
192 | 193 | ||
193 | /* Validate arguments */ | 194 | /* Validate arguments */ |
@@ -225,7 +226,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol) | |||
225 | /* Allocate TIPC port for socket to use */ | 226 | /* Allocate TIPC port for socket to use */ |
226 | 227 | ||
227 | portref = tipc_createport_raw(sk, &dispatch, &wakeupdispatch, | 228 | portref = tipc_createport_raw(sk, &dispatch, &wakeupdispatch, |
228 | TIPC_LOW_IMPORTANCE); | 229 | TIPC_LOW_IMPORTANCE, &tp_ptr); |
229 | if (unlikely(portref == 0)) { | 230 | if (unlikely(portref == 0)) { |
230 | sk_free(sk); | 231 | sk_free(sk); |
231 | return -ENOMEM; | 232 | return -ENOMEM; |
@@ -241,6 +242,8 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol) | |||
241 | sk->sk_backlog_rcv = backlog_rcv; | 242 | sk->sk_backlog_rcv = backlog_rcv; |
242 | tipc_sk(sk)->p = tipc_get_port(portref); | 243 | tipc_sk(sk)->p = tipc_get_port(portref); |
243 | 244 | ||
245 | spin_unlock_bh(tp_ptr->lock); | ||
246 | |||
244 | if (sock->state == SS_READY) { | 247 | if (sock->state == SS_READY) { |
245 | tipc_set_portunreturnable(portref, 1); | 248 | tipc_set_portunreturnable(portref, 1); |
246 | if (sock->type == SOCK_DGRAM) | 249 | if (sock->type == SOCK_DGRAM) |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 8c01ccd3626c..0326d3060bc7 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/subscr.c: TIPC subscription service | 2 | * net/tipc/subscr.c: TIPC network topology service |
3 | * | 3 | * |
4 | * Copyright (c) 2000-2006, Ericsson AB | 4 | * Copyright (c) 2000-2006, Ericsson AB |
5 | * Copyright (c) 2005, Wind River Systems | 5 | * Copyright (c) 2005-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -36,27 +36,24 @@ | |||
36 | 36 | ||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "dbg.h" | 38 | #include "dbg.h" |
39 | #include "subscr.h" | ||
40 | #include "name_table.h" | 39 | #include "name_table.h" |
40 | #include "port.h" | ||
41 | #include "ref.h" | 41 | #include "ref.h" |
42 | #include "subscr.h" | ||
42 | 43 | ||
43 | /** | 44 | /** |
44 | * struct subscriber - TIPC network topology subscriber | 45 | * struct subscriber - TIPC network topology subscriber |
45 | * @ref: object reference to subscriber object itself | 46 | * @port_ref: object reference to server port connecting to subscriber |
46 | * @lock: pointer to spinlock controlling access to subscriber object | 47 | * @lock: pointer to spinlock controlling access to subscriber's server port |
47 | * @subscriber_list: adjacent subscribers in top. server's list of subscribers | 48 | * @subscriber_list: adjacent subscribers in top. server's list of subscribers |
48 | * @subscription_list: list of subscription objects for this subscriber | 49 | * @subscription_list: list of subscription objects for this subscriber |
49 | * @port_ref: object reference to port used to communicate with subscriber | ||
50 | * @swap: indicates if subscriber uses opposite endianness in its messages | ||
51 | */ | 50 | */ |
52 | 51 | ||
53 | struct subscriber { | 52 | struct subscriber { |
54 | u32 ref; | 53 | u32 port_ref; |
55 | spinlock_t *lock; | 54 | spinlock_t *lock; |
56 | struct list_head subscriber_list; | 55 | struct list_head subscriber_list; |
57 | struct list_head subscription_list; | 56 | struct list_head subscription_list; |
58 | u32 port_ref; | ||
59 | int swap; | ||
60 | }; | 57 | }; |
61 | 58 | ||
62 | /** | 59 | /** |
@@ -88,13 +85,14 @@ static struct top_srv topsrv = { 0 }; | |||
88 | 85 | ||
89 | static u32 htohl(u32 in, int swap) | 86 | static u32 htohl(u32 in, int swap) |
90 | { | 87 | { |
91 | char *c = (char *)∈ | 88 | return swap ? (u32)___constant_swab32(in) : in; |
92 | |||
93 | return swap ? ((c[3] << 3) + (c[2] << 2) + (c[1] << 1) + c[0]) : in; | ||
94 | } | 89 | } |
95 | 90 | ||
96 | /** | 91 | /** |
97 | * subscr_send_event - send a message containing a tipc_event to the subscriber | 92 | * subscr_send_event - send a message containing a tipc_event to the subscriber |
93 | * | ||
94 | * Note: Must not hold subscriber's server port lock, since tipc_send() will | ||
95 | * try to take the lock if the message is rejected and returned! | ||
98 | */ | 96 | */ |
99 | 97 | ||
100 | static void subscr_send_event(struct subscription *sub, | 98 | static void subscr_send_event(struct subscription *sub, |
@@ -109,12 +107,12 @@ static void subscr_send_event(struct subscription *sub, | |||
109 | msg_sect.iov_base = (void *)&sub->evt; | 107 | msg_sect.iov_base = (void *)&sub->evt; |
110 | msg_sect.iov_len = sizeof(struct tipc_event); | 108 | msg_sect.iov_len = sizeof(struct tipc_event); |
111 | 109 | ||
112 | sub->evt.event = htohl(event, sub->owner->swap); | 110 | sub->evt.event = htohl(event, sub->swap); |
113 | sub->evt.found_lower = htohl(found_lower, sub->owner->swap); | 111 | sub->evt.found_lower = htohl(found_lower, sub->swap); |
114 | sub->evt.found_upper = htohl(found_upper, sub->owner->swap); | 112 | sub->evt.found_upper = htohl(found_upper, sub->swap); |
115 | sub->evt.port.ref = htohl(port_ref, sub->owner->swap); | 113 | sub->evt.port.ref = htohl(port_ref, sub->swap); |
116 | sub->evt.port.node = htohl(node, sub->owner->swap); | 114 | sub->evt.port.node = htohl(node, sub->swap); |
117 | tipc_send(sub->owner->port_ref, 1, &msg_sect); | 115 | tipc_send(sub->server_ref, 1, &msg_sect); |
118 | } | 116 | } |
119 | 117 | ||
120 | /** | 118 | /** |
@@ -151,13 +149,12 @@ void tipc_subscr_report_overlap(struct subscription *sub, | |||
151 | u32 node, | 149 | u32 node, |
152 | int must) | 150 | int must) |
153 | { | 151 | { |
154 | dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower, | ||
155 | sub->seq.upper, found_lower, found_upper); | ||
156 | if (!tipc_subscr_overlap(sub, found_lower, found_upper)) | 152 | if (!tipc_subscr_overlap(sub, found_lower, found_upper)) |
157 | return; | 153 | return; |
158 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) | 154 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) |
159 | return; | 155 | return; |
160 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); | 156 | |
157 | sub->event_cb(sub, found_lower, found_upper, event, port_ref, node); | ||
161 | } | 158 | } |
162 | 159 | ||
163 | /** | 160 | /** |
@@ -166,20 +163,18 @@ void tipc_subscr_report_overlap(struct subscription *sub, | |||
166 | 163 | ||
167 | static void subscr_timeout(struct subscription *sub) | 164 | static void subscr_timeout(struct subscription *sub) |
168 | { | 165 | { |
169 | struct subscriber *subscriber; | 166 | struct port *server_port; |
170 | u32 subscriber_ref; | ||
171 | 167 | ||
172 | /* Validate subscriber reference (in case subscriber is terminating) */ | 168 | /* Validate server port reference (in case subscriber is terminating) */ |
173 | 169 | ||
174 | subscriber_ref = sub->owner->ref; | 170 | server_port = tipc_port_lock(sub->server_ref); |
175 | subscriber = (struct subscriber *)tipc_ref_lock(subscriber_ref); | 171 | if (server_port == NULL) |
176 | if (subscriber == NULL) | ||
177 | return; | 172 | return; |
178 | 173 | ||
179 | /* Validate timeout (in case subscription is being cancelled) */ | 174 | /* Validate timeout (in case subscription is being cancelled) */ |
180 | 175 | ||
181 | if (sub->timeout == TIPC_WAIT_FOREVER) { | 176 | if (sub->timeout == TIPC_WAIT_FOREVER) { |
182 | tipc_ref_unlock(subscriber_ref); | 177 | tipc_port_unlock(server_port); |
183 | return; | 178 | return; |
184 | } | 179 | } |
185 | 180 | ||
@@ -187,19 +182,21 @@ static void subscr_timeout(struct subscription *sub) | |||
187 | 182 | ||
188 | tipc_nametbl_unsubscribe(sub); | 183 | tipc_nametbl_unsubscribe(sub); |
189 | 184 | ||
190 | /* Notify subscriber of timeout, then unlink subscription */ | 185 | /* Unlink subscription from subscriber */ |
191 | 186 | ||
192 | subscr_send_event(sub, | ||
193 | sub->evt.s.seq.lower, | ||
194 | sub->evt.s.seq.upper, | ||
195 | TIPC_SUBSCR_TIMEOUT, | ||
196 | 0, | ||
197 | 0); | ||
198 | list_del(&sub->subscription_list); | 187 | list_del(&sub->subscription_list); |
199 | 188 | ||
189 | /* Release subscriber's server port */ | ||
190 | |||
191 | tipc_port_unlock(server_port); | ||
192 | |||
193 | /* Notify subscriber of timeout */ | ||
194 | |||
195 | subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, | ||
196 | TIPC_SUBSCR_TIMEOUT, 0, 0); | ||
197 | |||
200 | /* Now destroy subscription */ | 198 | /* Now destroy subscription */ |
201 | 199 | ||
202 | tipc_ref_unlock(subscriber_ref); | ||
203 | k_term_timer(&sub->timer); | 200 | k_term_timer(&sub->timer); |
204 | kfree(sub); | 201 | kfree(sub); |
205 | atomic_dec(&topsrv.subscription_count); | 202 | atomic_dec(&topsrv.subscription_count); |
@@ -208,7 +205,7 @@ static void subscr_timeout(struct subscription *sub) | |||
208 | /** | 205 | /** |
209 | * subscr_del - delete a subscription within a subscription list | 206 | * subscr_del - delete a subscription within a subscription list |
210 | * | 207 | * |
211 | * Called with subscriber locked. | 208 | * Called with subscriber port locked. |
212 | */ | 209 | */ |
213 | 210 | ||
214 | static void subscr_del(struct subscription *sub) | 211 | static void subscr_del(struct subscription *sub) |
@@ -222,7 +219,7 @@ static void subscr_del(struct subscription *sub) | |||
222 | /** | 219 | /** |
223 | * subscr_terminate - terminate communication with a subscriber | 220 | * subscr_terminate - terminate communication with a subscriber |
224 | * | 221 | * |
225 | * Called with subscriber locked. Routine must temporarily release this lock | 222 | * Called with subscriber port locked. Routine must temporarily release lock |
226 | * to enable subscription timeout routine(s) to finish without deadlocking; | 223 | * to enable subscription timeout routine(s) to finish without deadlocking; |
227 | * the lock is then reclaimed to allow caller to release it upon return. | 224 | * the lock is then reclaimed to allow caller to release it upon return. |
228 | * (This should work even in the unlikely event some other thread creates | 225 | * (This should work even in the unlikely event some other thread creates |
@@ -232,14 +229,21 @@ static void subscr_del(struct subscription *sub) | |||
232 | 229 | ||
233 | static void subscr_terminate(struct subscriber *subscriber) | 230 | static void subscr_terminate(struct subscriber *subscriber) |
234 | { | 231 | { |
232 | u32 port_ref; | ||
235 | struct subscription *sub; | 233 | struct subscription *sub; |
236 | struct subscription *sub_temp; | 234 | struct subscription *sub_temp; |
237 | 235 | ||
238 | /* Invalidate subscriber reference */ | 236 | /* Invalidate subscriber reference */ |
239 | 237 | ||
240 | tipc_ref_discard(subscriber->ref); | 238 | port_ref = subscriber->port_ref; |
239 | subscriber->port_ref = 0; | ||
241 | spin_unlock_bh(subscriber->lock); | 240 | spin_unlock_bh(subscriber->lock); |
242 | 241 | ||
242 | /* Sever connection to subscriber */ | ||
243 | |||
244 | tipc_shutdown(port_ref); | ||
245 | tipc_deleteport(port_ref); | ||
246 | |||
243 | /* Destroy any existing subscriptions for subscriber */ | 247 | /* Destroy any existing subscriptions for subscriber */ |
244 | 248 | ||
245 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 249 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, |
@@ -253,27 +257,25 @@ static void subscr_terminate(struct subscriber *subscriber) | |||
253 | subscr_del(sub); | 257 | subscr_del(sub); |
254 | } | 258 | } |
255 | 259 | ||
256 | /* Sever connection to subscriber */ | ||
257 | |||
258 | tipc_shutdown(subscriber->port_ref); | ||
259 | tipc_deleteport(subscriber->port_ref); | ||
260 | |||
261 | /* Remove subscriber from topology server's subscriber list */ | 260 | /* Remove subscriber from topology server's subscriber list */ |
262 | 261 | ||
263 | spin_lock_bh(&topsrv.lock); | 262 | spin_lock_bh(&topsrv.lock); |
264 | list_del(&subscriber->subscriber_list); | 263 | list_del(&subscriber->subscriber_list); |
265 | spin_unlock_bh(&topsrv.lock); | 264 | spin_unlock_bh(&topsrv.lock); |
266 | 265 | ||
267 | /* Now destroy subscriber */ | 266 | /* Reclaim subscriber lock */ |
268 | 267 | ||
269 | spin_lock_bh(subscriber->lock); | 268 | spin_lock_bh(subscriber->lock); |
269 | |||
270 | /* Now destroy subscriber */ | ||
271 | |||
270 | kfree(subscriber); | 272 | kfree(subscriber); |
271 | } | 273 | } |
272 | 274 | ||
273 | /** | 275 | /** |
274 | * subscr_cancel - handle subscription cancellation request | 276 | * subscr_cancel - handle subscription cancellation request |
275 | * | 277 | * |
276 | * Called with subscriber locked. Routine must temporarily release this lock | 278 | * Called with subscriber port locked. Routine must temporarily release lock |
277 | * to enable the subscription timeout routine to finish without deadlocking; | 279 | * to enable the subscription timeout routine to finish without deadlocking; |
278 | * the lock is then reclaimed to allow caller to release it upon return. | 280 | * the lock is then reclaimed to allow caller to release it upon return. |
279 | * | 281 | * |
@@ -316,27 +318,25 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
316 | /** | 318 | /** |
317 | * subscr_subscribe - create subscription for subscriber | 319 | * subscr_subscribe - create subscription for subscriber |
318 | * | 320 | * |
319 | * Called with subscriber locked | 321 | * Called with subscriber port locked. |
320 | */ | 322 | */ |
321 | 323 | ||
322 | static void subscr_subscribe(struct tipc_subscr *s, | 324 | static struct subscription *subscr_subscribe(struct tipc_subscr *s, |
323 | struct subscriber *subscriber) | 325 | struct subscriber *subscriber) |
324 | { | 326 | { |
325 | struct subscription *sub; | 327 | struct subscription *sub; |
328 | int swap; | ||
326 | 329 | ||
327 | /* Determine/update subscriber's endianness */ | 330 | /* Determine subscriber's endianness */ |
328 | 331 | ||
329 | if (s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)) | 332 | swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); |
330 | subscriber->swap = 0; | ||
331 | else | ||
332 | subscriber->swap = 1; | ||
333 | 333 | ||
334 | /* Detect & process a subscription cancellation request */ | 334 | /* Detect & process a subscription cancellation request */ |
335 | 335 | ||
336 | if (s->filter & htohl(TIPC_SUB_CANCEL, subscriber->swap)) { | 336 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { |
337 | s->filter &= ~htohl(TIPC_SUB_CANCEL, subscriber->swap); | 337 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); |
338 | subscr_cancel(s, subscriber); | 338 | subscr_cancel(s, subscriber); |
339 | return; | 339 | return NULL; |
340 | } | 340 | } |
341 | 341 | ||
342 | /* Refuse subscription if global limit exceeded */ | 342 | /* Refuse subscription if global limit exceeded */ |
@@ -345,63 +345,66 @@ static void subscr_subscribe(struct tipc_subscr *s, | |||
345 | warn("Subscription rejected, subscription limit reached (%u)\n", | 345 | warn("Subscription rejected, subscription limit reached (%u)\n", |
346 | tipc_max_subscriptions); | 346 | tipc_max_subscriptions); |
347 | subscr_terminate(subscriber); | 347 | subscr_terminate(subscriber); |
348 | return; | 348 | return NULL; |
349 | } | 349 | } |
350 | 350 | ||
351 | /* Allocate subscription object */ | 351 | /* Allocate subscription object */ |
352 | 352 | ||
353 | sub = kzalloc(sizeof(*sub), GFP_ATOMIC); | 353 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); |
354 | if (!sub) { | 354 | if (!sub) { |
355 | warn("Subscription rejected, no memory\n"); | 355 | warn("Subscription rejected, no memory\n"); |
356 | subscr_terminate(subscriber); | 356 | subscr_terminate(subscriber); |
357 | return; | 357 | return NULL; |
358 | } | 358 | } |
359 | 359 | ||
360 | /* Initialize subscription object */ | 360 | /* Initialize subscription object */ |
361 | 361 | ||
362 | sub->seq.type = htohl(s->seq.type, subscriber->swap); | 362 | sub->seq.type = htohl(s->seq.type, swap); |
363 | sub->seq.lower = htohl(s->seq.lower, subscriber->swap); | 363 | sub->seq.lower = htohl(s->seq.lower, swap); |
364 | sub->seq.upper = htohl(s->seq.upper, subscriber->swap); | 364 | sub->seq.upper = htohl(s->seq.upper, swap); |
365 | sub->timeout = htohl(s->timeout, subscriber->swap); | 365 | sub->timeout = htohl(s->timeout, swap); |
366 | sub->filter = htohl(s->filter, subscriber->swap); | 366 | sub->filter = htohl(s->filter, swap); |
367 | if ((!(sub->filter & TIPC_SUB_PORTS) | 367 | if ((!(sub->filter & TIPC_SUB_PORTS) |
368 | == !(sub->filter & TIPC_SUB_SERVICE)) | 368 | == !(sub->filter & TIPC_SUB_SERVICE)) |
369 | || (sub->seq.lower > sub->seq.upper)) { | 369 | || (sub->seq.lower > sub->seq.upper)) { |
370 | warn("Subscription rejected, illegal request\n"); | 370 | warn("Subscription rejected, illegal request\n"); |
371 | kfree(sub); | 371 | kfree(sub); |
372 | subscr_terminate(subscriber); | 372 | subscr_terminate(subscriber); |
373 | return; | 373 | return NULL; |
374 | } | 374 | } |
375 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | 375 | sub->event_cb = subscr_send_event; |
376 | INIT_LIST_HEAD(&sub->subscription_list); | ||
377 | INIT_LIST_HEAD(&sub->nameseq_list); | 376 | INIT_LIST_HEAD(&sub->nameseq_list); |
378 | list_add(&sub->subscription_list, &subscriber->subscription_list); | 377 | list_add(&sub->subscription_list, &subscriber->subscription_list); |
378 | sub->server_ref = subscriber->port_ref; | ||
379 | sub->swap = swap; | ||
380 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | ||
379 | atomic_inc(&topsrv.subscription_count); | 381 | atomic_inc(&topsrv.subscription_count); |
380 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 382 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
381 | k_init_timer(&sub->timer, | 383 | k_init_timer(&sub->timer, |
382 | (Handler)subscr_timeout, (unsigned long)sub); | 384 | (Handler)subscr_timeout, (unsigned long)sub); |
383 | k_start_timer(&sub->timer, sub->timeout); | 385 | k_start_timer(&sub->timer, sub->timeout); |
384 | } | 386 | } |
385 | sub->owner = subscriber; | 387 | |
386 | tipc_nametbl_subscribe(sub); | 388 | return sub; |
387 | } | 389 | } |
388 | 390 | ||
389 | /** | 391 | /** |
390 | * subscr_conn_shutdown_event - handle termination request from subscriber | 392 | * subscr_conn_shutdown_event - handle termination request from subscriber |
393 | * | ||
394 | * Called with subscriber's server port unlocked. | ||
391 | */ | 395 | */ |
392 | 396 | ||
393 | static void subscr_conn_shutdown_event(void *usr_handle, | 397 | static void subscr_conn_shutdown_event(void *usr_handle, |
394 | u32 portref, | 398 | u32 port_ref, |
395 | struct sk_buff **buf, | 399 | struct sk_buff **buf, |
396 | unsigned char const *data, | 400 | unsigned char const *data, |
397 | unsigned int size, | 401 | unsigned int size, |
398 | int reason) | 402 | int reason) |
399 | { | 403 | { |
400 | struct subscriber *subscriber; | 404 | struct subscriber *subscriber = usr_handle; |
401 | spinlock_t *subscriber_lock; | 405 | spinlock_t *subscriber_lock; |
402 | 406 | ||
403 | subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle); | 407 | if (tipc_port_lock(port_ref) == NULL) |
404 | if (subscriber == NULL) | ||
405 | return; | 408 | return; |
406 | 409 | ||
407 | subscriber_lock = subscriber->lock; | 410 | subscriber_lock = subscriber->lock; |
@@ -411,6 +414,8 @@ static void subscr_conn_shutdown_event(void *usr_handle, | |||
411 | 414 | ||
412 | /** | 415 | /** |
413 | * subscr_conn_msg_event - handle new subscription request from subscriber | 416 | * subscr_conn_msg_event - handle new subscription request from subscriber |
417 | * | ||
418 | * Called with subscriber's server port unlocked. | ||
414 | */ | 419 | */ |
415 | 420 | ||
416 | static void subscr_conn_msg_event(void *usr_handle, | 421 | static void subscr_conn_msg_event(void *usr_handle, |
@@ -419,20 +424,46 @@ static void subscr_conn_msg_event(void *usr_handle, | |||
419 | const unchar *data, | 424 | const unchar *data, |
420 | u32 size) | 425 | u32 size) |
421 | { | 426 | { |
422 | struct subscriber *subscriber; | 427 | struct subscriber *subscriber = usr_handle; |
423 | spinlock_t *subscriber_lock; | 428 | spinlock_t *subscriber_lock; |
429 | struct subscription *sub; | ||
430 | |||
431 | /* | ||
432 | * Lock subscriber's server port (& make a local copy of lock pointer, | ||
433 | * in case subscriber is deleted while processing subscription request) | ||
434 | */ | ||
424 | 435 | ||
425 | subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle); | 436 | if (tipc_port_lock(port_ref) == NULL) |
426 | if (subscriber == NULL) | ||
427 | return; | 437 | return; |
428 | 438 | ||
429 | subscriber_lock = subscriber->lock; | 439 | subscriber_lock = subscriber->lock; |
430 | if (size != sizeof(struct tipc_subscr)) | ||
431 | subscr_terminate(subscriber); | ||
432 | else | ||
433 | subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
434 | 440 | ||
435 | spin_unlock_bh(subscriber_lock); | 441 | if (size != sizeof(struct tipc_subscr)) { |
442 | subscr_terminate(subscriber); | ||
443 | spin_unlock_bh(subscriber_lock); | ||
444 | } else { | ||
445 | sub = subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
446 | spin_unlock_bh(subscriber_lock); | ||
447 | if (sub != NULL) { | ||
448 | |||
449 | /* | ||
450 | * We must release the server port lock before adding a | ||
451 | * subscription to the name table since TIPC needs to be | ||
452 | * able to (re)acquire the port lock if an event message | ||
453 | * issued by the subscription process is rejected and | ||
454 | * returned. The subscription cannot be deleted while | ||
455 | * it is being added to the name table because: | ||
456 | * a) the single-threading of the native API port code | ||
457 | * ensures the subscription cannot be cancelled and | ||
458 | * the subscriber connection cannot be broken, and | ||
459 | * b) the name table lock ensures the subscription | ||
460 | * timeout code cannot delete the subscription, | ||
461 | * so the subscription object is still protected. | ||
462 | */ | ||
463 | |||
464 | tipc_nametbl_subscribe(sub); | ||
465 | } | ||
466 | } | ||
436 | } | 467 | } |
437 | 468 | ||
438 | /** | 469 | /** |
@@ -448,16 +479,10 @@ static void subscr_named_msg_event(void *usr_handle, | |||
448 | struct tipc_portid const *orig, | 479 | struct tipc_portid const *orig, |
449 | struct tipc_name_seq const *dest) | 480 | struct tipc_name_seq const *dest) |
450 | { | 481 | { |
451 | struct subscriber *subscriber; | 482 | static struct iovec msg_sect = {NULL, 0}; |
452 | struct iovec msg_sect = {NULL, 0}; | ||
453 | spinlock_t *subscriber_lock; | ||
454 | 483 | ||
455 | dbg("subscr_named_msg_event: orig = %x own = %x,\n", | 484 | struct subscriber *subscriber; |
456 | orig->node, tipc_own_addr); | 485 | u32 server_port_ref; |
457 | if (size && (size != sizeof(struct tipc_subscr))) { | ||
458 | warn("Subscriber rejected, invalid subscription size\n"); | ||
459 | return; | ||
460 | } | ||
461 | 486 | ||
462 | /* Create subscriber object */ | 487 | /* Create subscriber object */ |
463 | 488 | ||
@@ -468,17 +493,11 @@ static void subscr_named_msg_event(void *usr_handle, | |||
468 | } | 493 | } |
469 | INIT_LIST_HEAD(&subscriber->subscription_list); | 494 | INIT_LIST_HEAD(&subscriber->subscription_list); |
470 | INIT_LIST_HEAD(&subscriber->subscriber_list); | 495 | INIT_LIST_HEAD(&subscriber->subscriber_list); |
471 | subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock); | ||
472 | if (subscriber->ref == 0) { | ||
473 | warn("Subscriber rejected, reference table exhausted\n"); | ||
474 | kfree(subscriber); | ||
475 | return; | ||
476 | } | ||
477 | 496 | ||
478 | /* Establish a connection to subscriber */ | 497 | /* Create server port & establish connection to subscriber */ |
479 | 498 | ||
480 | tipc_createport(topsrv.user_ref, | 499 | tipc_createport(topsrv.user_ref, |
481 | (void *)(unsigned long)subscriber->ref, | 500 | subscriber, |
482 | importance, | 501 | importance, |
483 | NULL, | 502 | NULL, |
484 | NULL, | 503 | NULL, |
@@ -490,32 +509,36 @@ static void subscr_named_msg_event(void *usr_handle, | |||
490 | &subscriber->port_ref); | 509 | &subscriber->port_ref); |
491 | if (subscriber->port_ref == 0) { | 510 | if (subscriber->port_ref == 0) { |
492 | warn("Subscriber rejected, unable to create port\n"); | 511 | warn("Subscriber rejected, unable to create port\n"); |
493 | tipc_ref_discard(subscriber->ref); | ||
494 | kfree(subscriber); | 512 | kfree(subscriber); |
495 | return; | 513 | return; |
496 | } | 514 | } |
497 | tipc_connect2port(subscriber->port_ref, orig); | 515 | tipc_connect2port(subscriber->port_ref, orig); |
498 | 516 | ||
517 | /* Lock server port (& save lock address for future use) */ | ||
518 | |||
519 | subscriber->lock = tipc_port_lock(subscriber->port_ref)->publ.lock; | ||
499 | 520 | ||
500 | /* Add subscriber to topology server's subscriber list */ | 521 | /* Add subscriber to topology server's subscriber list */ |
501 | 522 | ||
502 | tipc_ref_lock(subscriber->ref); | ||
503 | spin_lock_bh(&topsrv.lock); | 523 | spin_lock_bh(&topsrv.lock); |
504 | list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); | 524 | list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); |
505 | spin_unlock_bh(&topsrv.lock); | 525 | spin_unlock_bh(&topsrv.lock); |
506 | 526 | ||
507 | /* | 527 | /* Unlock server port */ |
508 | * Subscribe now if message contains a subscription, | ||
509 | * otherwise send an empty response to complete connection handshaking | ||
510 | */ | ||
511 | 528 | ||
512 | subscriber_lock = subscriber->lock; | 529 | server_port_ref = subscriber->port_ref; |
513 | if (size) | 530 | spin_unlock_bh(subscriber->lock); |
514 | subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
515 | else | ||
516 | tipc_send(subscriber->port_ref, 1, &msg_sect); | ||
517 | 531 | ||
518 | spin_unlock_bh(subscriber_lock); | 532 | /* Send an ACK- to complete connection handshaking */ |
533 | |||
534 | tipc_send(server_port_ref, 1, &msg_sect); | ||
535 | |||
536 | /* Handle optional subscription request */ | ||
537 | |||
538 | if (size != 0) { | ||
539 | subscr_conn_msg_event(subscriber, server_port_ref, | ||
540 | buf, data, size); | ||
541 | } | ||
519 | } | 542 | } |
520 | 543 | ||
521 | int tipc_subscr_start(void) | 544 | int tipc_subscr_start(void) |
@@ -574,8 +597,8 @@ void tipc_subscr_stop(void) | |||
574 | list_for_each_entry_safe(subscriber, subscriber_temp, | 597 | list_for_each_entry_safe(subscriber, subscriber_temp, |
575 | &topsrv.subscriber_list, | 598 | &topsrv.subscriber_list, |
576 | subscriber_list) { | 599 | subscriber_list) { |
577 | tipc_ref_lock(subscriber->ref); | ||
578 | subscriber_lock = subscriber->lock; | 600 | subscriber_lock = subscriber->lock; |
601 | spin_lock_bh(subscriber_lock); | ||
579 | subscr_terminate(subscriber); | 602 | subscr_terminate(subscriber); |
580 | spin_unlock_bh(subscriber_lock); | 603 | spin_unlock_bh(subscriber_lock); |
581 | } | 604 | } |
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 93a8e674fac1..45d89bf4d202 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/subscr.h: Include file for TIPC subscription service | 2 | * net/tipc/subscr.h: Include file for TIPC network topology service |
3 | * | 3 | * |
4 | * Copyright (c) 2003-2006, Ericsson AB | 4 | * Copyright (c) 2003-2006, Ericsson AB |
5 | * Copyright (c) 2005, Wind River Systems | 5 | * Copyright (c) 2005-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -37,34 +37,44 @@ | |||
37 | #ifndef _TIPC_SUBSCR_H | 37 | #ifndef _TIPC_SUBSCR_H |
38 | #define _TIPC_SUBSCR_H | 38 | #define _TIPC_SUBSCR_H |
39 | 39 | ||
40 | struct subscription; | ||
41 | |||
42 | typedef void (*tipc_subscr_event) (struct subscription *sub, | ||
43 | u32 found_lower, u32 found_upper, | ||
44 | u32 event, u32 port_ref, u32 node); | ||
45 | |||
40 | /** | 46 | /** |
41 | * struct subscription - TIPC network topology subscription object | 47 | * struct subscription - TIPC network topology subscription object |
42 | * @seq: name sequence associated with subscription | 48 | * @seq: name sequence associated with subscription |
43 | * @timeout: duration of subscription (in ms) | 49 | * @timeout: duration of subscription (in ms) |
44 | * @filter: event filtering to be done for subscription | 50 | * @filter: event filtering to be done for subscription |
45 | * @evt: template for events generated by subscription | 51 | * @event_cb: routine invoked when a subscription event is detected |
46 | * @subscription_list: adjacent subscriptions in subscriber's subscription list | 52 | * @timer: timer governing subscription duration (optional) |
47 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list | 53 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list |
48 | * @timer_ref: reference to timer governing subscription duration (may be NULL) | 54 | * @subscription_list: adjacent subscriptions in subscriber's subscription list |
49 | * @owner: pointer to subscriber object associated with this subscription | 55 | * @server_ref: object reference of server port associated with subscription |
56 | * @swap: indicates if subscriber uses opposite endianness in its messages | ||
57 | * @evt: template for events generated by subscription | ||
50 | */ | 58 | */ |
51 | 59 | ||
52 | struct subscription { | 60 | struct subscription { |
53 | struct tipc_name_seq seq; | 61 | struct tipc_name_seq seq; |
54 | u32 timeout; | 62 | u32 timeout; |
55 | u32 filter; | 63 | u32 filter; |
56 | struct tipc_event evt; | 64 | tipc_subscr_event event_cb; |
57 | struct list_head subscription_list; | ||
58 | struct list_head nameseq_list; | ||
59 | struct timer_list timer; | 65 | struct timer_list timer; |
60 | struct subscriber *owner; | 66 | struct list_head nameseq_list; |
67 | struct list_head subscription_list; | ||
68 | u32 server_ref; | ||
69 | int swap; | ||
70 | struct tipc_event evt; | ||
61 | }; | 71 | }; |
62 | 72 | ||
63 | int tipc_subscr_overlap(struct subscription * sub, | 73 | int tipc_subscr_overlap(struct subscription *sub, |
64 | u32 found_lower, | 74 | u32 found_lower, |
65 | u32 found_upper); | 75 | u32 found_upper); |
66 | 76 | ||
67 | void tipc_subscr_report_overlap(struct subscription * sub, | 77 | void tipc_subscr_report_overlap(struct subscription *sub, |
68 | u32 found_lower, | 78 | u32 found_lower, |
69 | u32 found_upper, | 79 | u32 found_upper, |
70 | u32 event, | 80 | u32 event, |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e18cd3628db4..392e80e3268d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -8,8 +8,6 @@ | |||
8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | * | 10 | * |
11 | * Version: $Id: af_unix.c,v 1.133 2002/02/08 03:57:19 davem Exp $ | ||
12 | * | ||
13 | * Fixes: | 11 | * Fixes: |
14 | * Linus Torvalds : Assorted bug cures. | 12 | * Linus Torvalds : Assorted bug cures. |
15 | * Niibe Yutaka : async I/O support. | 13 | * Niibe Yutaka : async I/O support. |
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 9ab31a3ce3ad..b210a88d0960 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c | |||
@@ -350,9 +350,9 @@ __be16 wanrouter_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
350 | * o execute requested action or pass command to the device driver | 350 | * o execute requested action or pass command to the device driver |
351 | */ | 351 | */ |
352 | 352 | ||
353 | int wanrouter_ioctl(struct inode *inode, struct file *file, | 353 | long wanrouter_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
354 | unsigned int cmd, unsigned long arg) | ||
355 | { | 354 | { |
355 | struct inode *inode = file->f_path.dentry->d_inode; | ||
356 | int err = 0; | 356 | int err = 0; |
357 | struct proc_dir_entry *dent; | 357 | struct proc_dir_entry *dent; |
358 | struct wan_device *wandev; | 358 | struct wan_device *wandev; |
@@ -372,6 +372,7 @@ int wanrouter_ioctl(struct inode *inode, struct file *file, | |||
372 | if (wandev->magic != ROUTER_MAGIC) | 372 | if (wandev->magic != ROUTER_MAGIC) |
373 | return -EINVAL; | 373 | return -EINVAL; |
374 | 374 | ||
375 | lock_kernel(); | ||
375 | switch (cmd) { | 376 | switch (cmd) { |
376 | case ROUTER_SETUP: | 377 | case ROUTER_SETUP: |
377 | err = wanrouter_device_setup(wandev, data); | 378 | err = wanrouter_device_setup(wandev, data); |
@@ -403,6 +404,7 @@ int wanrouter_ioctl(struct inode *inode, struct file *file, | |||
403 | err = wandev->ioctl(wandev, cmd, arg); | 404 | err = wandev->ioctl(wandev, cmd, arg); |
404 | else err = -EINVAL; | 405 | else err = -EINVAL; |
405 | } | 406 | } |
407 | unlock_kernel(); | ||
406 | return err; | 408 | return err; |
407 | } | 409 | } |
408 | 410 | ||
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 5bebe40bf4e6..267f7ff49827 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c | |||
@@ -278,7 +278,7 @@ static const struct file_operations wandev_fops = { | |||
278 | .read = seq_read, | 278 | .read = seq_read, |
279 | .llseek = seq_lseek, | 279 | .llseek = seq_lseek, |
280 | .release = single_release, | 280 | .release = single_release, |
281 | .ioctl = wanrouter_ioctl, | 281 | .unlocked_ioctl = wanrouter_ioctl, |
282 | }; | 282 | }; |
283 | 283 | ||
284 | /* | 284 | /* |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 80afacdae46c..f1da0b93bc56 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -143,8 +143,11 @@ void cfg80211_put_dev(struct cfg80211_registered_device *drv) | |||
143 | int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | 143 | int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, |
144 | char *newname) | 144 | char *newname) |
145 | { | 145 | { |
146 | struct cfg80211_registered_device *drv; | ||
146 | int idx, taken = -1, result, digits; | 147 | int idx, taken = -1, result, digits; |
147 | 148 | ||
149 | mutex_lock(&cfg80211_drv_mutex); | ||
150 | |||
148 | /* prohibit calling the thing phy%d when %d is not its number */ | 151 | /* prohibit calling the thing phy%d when %d is not its number */ |
149 | sscanf(newname, PHY_NAME "%d%n", &idx, &taken); | 152 | sscanf(newname, PHY_NAME "%d%n", &idx, &taken); |
150 | if (taken == strlen(newname) && idx != rdev->idx) { | 153 | if (taken == strlen(newname) && idx != rdev->idx) { |
@@ -156,14 +159,30 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
156 | * deny the name if it is phy<idx> where <idx> is printed | 159 | * deny the name if it is phy<idx> where <idx> is printed |
157 | * without leading zeroes. taken == strlen(newname) here | 160 | * without leading zeroes. taken == strlen(newname) here |
158 | */ | 161 | */ |
162 | result = -EINVAL; | ||
159 | if (taken == strlen(PHY_NAME) + digits) | 163 | if (taken == strlen(PHY_NAME) + digits) |
160 | return -EINVAL; | 164 | goto out_unlock; |
165 | } | ||
166 | |||
167 | |||
168 | /* Ignore nop renames */ | ||
169 | result = 0; | ||
170 | if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) | ||
171 | goto out_unlock; | ||
172 | |||
173 | /* Ensure another device does not already have this name. */ | ||
174 | list_for_each_entry(drv, &cfg80211_drv_list, list) { | ||
175 | result = -EINVAL; | ||
176 | if (strcmp(newname, dev_name(&drv->wiphy.dev)) == 0) | ||
177 | goto out_unlock; | ||
161 | } | 178 | } |
162 | 179 | ||
163 | /* this will check for collisions */ | 180 | /* this will only check for collisions in sysfs |
181 | * which is not even always compiled in. | ||
182 | */ | ||
164 | result = device_rename(&rdev->wiphy.dev, newname); | 183 | result = device_rename(&rdev->wiphy.dev, newname); |
165 | if (result) | 184 | if (result) |
166 | return result; | 185 | goto out_unlock; |
167 | 186 | ||
168 | if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent, | 187 | if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent, |
169 | rdev->wiphy.debugfsdir, | 188 | rdev->wiphy.debugfsdir, |
@@ -172,9 +191,13 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
172 | printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n", | 191 | printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n", |
173 | newname); | 192 | newname); |
174 | 193 | ||
175 | nl80211_notify_dev_rename(rdev); | 194 | result = 0; |
195 | out_unlock: | ||
196 | mutex_unlock(&cfg80211_drv_mutex); | ||
197 | if (result == 0) | ||
198 | nl80211_notify_dev_rename(rdev); | ||
176 | 199 | ||
177 | return 0; | 200 | return result; |
178 | } | 201 | } |
179 | 202 | ||
180 | /* exported functions */ | 203 | /* exported functions */ |
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index 28fbd0b0b568..f591871a7b4f 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c | |||
@@ -59,23 +59,21 @@ int ieee80211_radiotap_iterator_init( | |||
59 | return -EINVAL; | 59 | return -EINVAL; |
60 | 60 | ||
61 | /* sanity check for allowed length and radiotap length field */ | 61 | /* sanity check for allowed length and radiotap length field */ |
62 | if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) | 62 | if (max_length < get_unaligned_le16(&radiotap_header->it_len)) |
63 | return -EINVAL; | 63 | return -EINVAL; |
64 | 64 | ||
65 | iterator->rtheader = radiotap_header; | 65 | iterator->rtheader = radiotap_header; |
66 | iterator->max_length = le16_to_cpu(get_unaligned( | 66 | iterator->max_length = get_unaligned_le16(&radiotap_header->it_len); |
67 | &radiotap_header->it_len)); | ||
68 | iterator->arg_index = 0; | 67 | iterator->arg_index = 0; |
69 | iterator->bitmap_shifter = le32_to_cpu(get_unaligned( | 68 | iterator->bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present); |
70 | &radiotap_header->it_present)); | ||
71 | iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); | 69 | iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); |
72 | iterator->this_arg = NULL; | 70 | iterator->this_arg = NULL; |
73 | 71 | ||
74 | /* find payload start allowing for extended bitmap(s) */ | 72 | /* find payload start allowing for extended bitmap(s) */ |
75 | 73 | ||
76 | if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) { | 74 | if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) { |
77 | while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) & | 75 | while (get_unaligned_le32(iterator->arg) & |
78 | (1<<IEEE80211_RADIOTAP_EXT)) { | 76 | (1 << IEEE80211_RADIOTAP_EXT)) { |
79 | iterator->arg += sizeof(u32); | 77 | iterator->arg += sizeof(u32); |
80 | 78 | ||
81 | /* | 79 | /* |
@@ -241,8 +239,8 @@ int ieee80211_radiotap_iterator_next( | |||
241 | if (iterator->bitmap_shifter & 1) { | 239 | if (iterator->bitmap_shifter & 1) { |
242 | /* b31 was set, there is more */ | 240 | /* b31 was set, there is more */ |
243 | /* move to next u32 bitmap */ | 241 | /* move to next u32 bitmap */ |
244 | iterator->bitmap_shifter = le32_to_cpu( | 242 | iterator->bitmap_shifter = |
245 | get_unaligned(iterator->next_bitmap)); | 243 | get_unaligned_le32(iterator->next_bitmap); |
246 | iterator->next_bitmap++; | 244 | iterator->next_bitmap++; |
247 | } else | 245 | } else |
248 | /* no more bitmaps: end */ | 246 | /* no more bitmaps: end */ |