diff options
Diffstat (limited to 'net')
331 files changed, 12231 insertions, 7307 deletions
diff --git a/net/6lowpan/6lowpan_i.h b/net/6lowpan/6lowpan_i.h new file mode 100644 index 000000000000..d16bb4b14aa1 --- /dev/null +++ b/net/6lowpan/6lowpan_i.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef __6LOWPAN_I_H | ||
2 | #define __6LOWPAN_I_H | ||
3 | |||
4 | #include <linux/netdevice.h> | ||
5 | |||
6 | #ifdef CONFIG_6LOWPAN_DEBUGFS | ||
7 | int lowpan_dev_debugfs_init(struct net_device *dev); | ||
8 | void lowpan_dev_debugfs_exit(struct net_device *dev); | ||
9 | |||
10 | int __init lowpan_debugfs_init(void); | ||
11 | void lowpan_debugfs_exit(void); | ||
12 | #else | ||
13 | static inline int lowpan_dev_debugfs_init(struct net_device *dev) | ||
14 | { | ||
15 | return 0; | ||
16 | } | ||
17 | |||
18 | static inline void lowpan_dev_debugfs_exit(struct net_device *dev) { } | ||
19 | |||
20 | static inline int __init lowpan_debugfs_init(void) | ||
21 | { | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | static inline void lowpan_debugfs_exit(void) { } | ||
26 | #endif /* CONFIG_6LOWPAN_DEBUGFS */ | ||
27 | |||
28 | #endif /* __6LOWPAN_I_H */ | ||
diff --git a/net/6lowpan/Kconfig b/net/6lowpan/Kconfig index 7fa0f382e7d1..9c051512d14f 100644 --- a/net/6lowpan/Kconfig +++ b/net/6lowpan/Kconfig | |||
@@ -5,12 +5,21 @@ menuconfig 6LOWPAN | |||
5 | This enables IPv6 over Low power Wireless Personal Area Network - | 5 | This enables IPv6 over Low power Wireless Personal Area Network - |
6 | "6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks. | 6 | "6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks. |
7 | 7 | ||
8 | config 6LOWPAN_DEBUGFS | ||
9 | bool "6LoWPAN debugfs support" | ||
10 | depends on 6LOWPAN | ||
11 | depends on DEBUG_FS | ||
12 | ---help--- | ||
13 | This enables 6LoWPAN debugfs support. For example to manipulate | ||
14 | IPHC context information at runtime. | ||
15 | |||
8 | menuconfig 6LOWPAN_NHC | 16 | menuconfig 6LOWPAN_NHC |
9 | tristate "Next Header Compression Support" | 17 | tristate "Next Header and Generic Header Compression Support" |
10 | depends on 6LOWPAN | 18 | depends on 6LOWPAN |
11 | default y | 19 | default y |
12 | ---help--- | 20 | ---help--- |
13 | Support for next header compression. | 21 | Support for next header and generic header compression defined in |
22 | RFC6282 and RFC7400. | ||
14 | 23 | ||
15 | if 6LOWPAN_NHC | 24 | if 6LOWPAN_NHC |
16 | 25 | ||
@@ -58,4 +67,38 @@ config 6LOWPAN_NHC_UDP | |||
58 | ---help--- | 67 | ---help--- |
59 | 6LoWPAN IPv6 UDP Header compression according to RFC6282. | 68 | 6LoWPAN IPv6 UDP Header compression according to RFC6282. |
60 | 69 | ||
70 | config 6LOWPAN_GHC_EXT_HDR_HOP | ||
71 | tristate "GHC Hop-by-Hop Options Header Support" | ||
72 | ---help--- | ||
73 | 6LoWPAN IPv6 Hop-by-Hop option generic header compression according | ||
74 | to RFC7400. | ||
75 | |||
76 | config 6LOWPAN_GHC_UDP | ||
77 | tristate "GHC UDP Support" | ||
78 | ---help--- | ||
79 | 6LoWPAN IPv6 UDP generic header compression according to RFC7400. | ||
80 | |||
81 | config 6LOWPAN_GHC_ICMPV6 | ||
82 | tristate "GHC ICMPv6 Support" | ||
83 | ---help--- | ||
84 | 6LoWPAN IPv6 ICMPv6 generic header compression according to RFC7400. | ||
85 | |||
86 | config 6LOWPAN_GHC_EXT_HDR_DEST | ||
87 | tristate "GHC Destination Options Header Support" | ||
88 | ---help--- | ||
89 | 6LoWPAN IPv6 destination option generic header compression according | ||
90 | to RFC7400. | ||
91 | |||
92 | config 6LOWPAN_GHC_EXT_HDR_FRAG | ||
93 | tristate "GHC Fragmentation Options Header Support" | ||
94 | ---help--- | ||
95 | 6LoWPAN IPv6 fragmentation option generic header compression | ||
96 | according to RFC7400. | ||
97 | |||
98 | config 6LOWPAN_GHC_EXT_HDR_ROUTE | ||
99 | tristate "GHC Routing Options Header Support" | ||
100 | ---help--- | ||
101 | 6LoWPAN IPv6 routing option generic header compression according | ||
102 | to RFC7400. | ||
103 | |||
61 | endif | 104 | endif |
diff --git a/net/6lowpan/Makefile b/net/6lowpan/Makefile index c6ffc55ee0d7..e44f3bf2dd42 100644 --- a/net/6lowpan/Makefile +++ b/net/6lowpan/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | obj-$(CONFIG_6LOWPAN) += 6lowpan.o | 1 | obj-$(CONFIG_6LOWPAN) += 6lowpan.o |
2 | 2 | ||
3 | 6lowpan-y := core.o iphc.o nhc.o | 3 | 6lowpan-y := core.o iphc.o nhc.o |
4 | 6lowpan-$(CONFIG_6LOWPAN_DEBUGFS) += debugfs.o | ||
4 | 5 | ||
5 | #rfc6282 nhcs | 6 | #rfc6282 nhcs |
6 | obj-$(CONFIG_6LOWPAN_NHC_DEST) += nhc_dest.o | 7 | obj-$(CONFIG_6LOWPAN_NHC_DEST) += nhc_dest.o |
@@ -10,3 +11,11 @@ obj-$(CONFIG_6LOWPAN_NHC_IPV6) += nhc_ipv6.o | |||
10 | obj-$(CONFIG_6LOWPAN_NHC_MOBILITY) += nhc_mobility.o | 11 | obj-$(CONFIG_6LOWPAN_NHC_MOBILITY) += nhc_mobility.o |
11 | obj-$(CONFIG_6LOWPAN_NHC_ROUTING) += nhc_routing.o | 12 | obj-$(CONFIG_6LOWPAN_NHC_ROUTING) += nhc_routing.o |
12 | obj-$(CONFIG_6LOWPAN_NHC_UDP) += nhc_udp.o | 13 | obj-$(CONFIG_6LOWPAN_NHC_UDP) += nhc_udp.o |
14 | |||
15 | #rfc7400 ghcs | ||
16 | obj-$(CONFIG_6LOWPAN_GHC_EXT_HDR_HOP) += nhc_ghc_ext_hop.o | ||
17 | obj-$(CONFIG_6LOWPAN_GHC_UDP) += nhc_ghc_udp.o | ||
18 | obj-$(CONFIG_6LOWPAN_GHC_ICMPV6) += nhc_ghc_icmpv6.o | ||
19 | obj-$(CONFIG_6LOWPAN_GHC_EXT_HDR_DEST) += nhc_ghc_ext_dest.o | ||
20 | obj-$(CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG) += nhc_ghc_ext_frag.o | ||
21 | obj-$(CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE) += nhc_ghc_ext_route.o | ||
diff --git a/net/6lowpan/core.c b/net/6lowpan/core.c index 83b19e072224..faf65baed617 100644 --- a/net/6lowpan/core.c +++ b/net/6lowpan/core.c | |||
@@ -15,19 +15,67 @@ | |||
15 | 15 | ||
16 | #include <net/6lowpan.h> | 16 | #include <net/6lowpan.h> |
17 | 17 | ||
18 | void lowpan_netdev_setup(struct net_device *dev, enum lowpan_lltypes lltype) | 18 | #include "6lowpan_i.h" |
19 | |||
20 | int lowpan_register_netdevice(struct net_device *dev, | ||
21 | enum lowpan_lltypes lltype) | ||
19 | { | 22 | { |
23 | int ret; | ||
24 | |||
20 | dev->addr_len = EUI64_ADDR_LEN; | 25 | dev->addr_len = EUI64_ADDR_LEN; |
21 | dev->type = ARPHRD_6LOWPAN; | 26 | dev->type = ARPHRD_6LOWPAN; |
22 | dev->mtu = IPV6_MIN_MTU; | 27 | dev->mtu = IPV6_MIN_MTU; |
23 | dev->priv_flags |= IFF_NO_QUEUE; | 28 | dev->priv_flags |= IFF_NO_QUEUE; |
24 | 29 | ||
25 | lowpan_priv(dev)->lltype = lltype; | 30 | lowpan_priv(dev)->lltype = lltype; |
31 | |||
32 | ret = register_netdevice(dev); | ||
33 | if (ret < 0) | ||
34 | return ret; | ||
35 | |||
36 | ret = lowpan_dev_debugfs_init(dev); | ||
37 | if (ret < 0) | ||
38 | unregister_netdevice(dev); | ||
39 | |||
40 | return ret; | ||
26 | } | 41 | } |
27 | EXPORT_SYMBOL(lowpan_netdev_setup); | 42 | EXPORT_SYMBOL(lowpan_register_netdevice); |
43 | |||
44 | int lowpan_register_netdev(struct net_device *dev, | ||
45 | enum lowpan_lltypes lltype) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | rtnl_lock(); | ||
50 | ret = lowpan_register_netdevice(dev, lltype); | ||
51 | rtnl_unlock(); | ||
52 | return ret; | ||
53 | } | ||
54 | EXPORT_SYMBOL(lowpan_register_netdev); | ||
55 | |||
56 | void lowpan_unregister_netdevice(struct net_device *dev) | ||
57 | { | ||
58 | unregister_netdevice(dev); | ||
59 | lowpan_dev_debugfs_exit(dev); | ||
60 | } | ||
61 | EXPORT_SYMBOL(lowpan_unregister_netdevice); | ||
62 | |||
63 | void lowpan_unregister_netdev(struct net_device *dev) | ||
64 | { | ||
65 | rtnl_lock(); | ||
66 | lowpan_unregister_netdevice(dev); | ||
67 | rtnl_unlock(); | ||
68 | } | ||
69 | EXPORT_SYMBOL(lowpan_unregister_netdev); | ||
28 | 70 | ||
29 | static int __init lowpan_module_init(void) | 71 | static int __init lowpan_module_init(void) |
30 | { | 72 | { |
73 | int ret; | ||
74 | |||
75 | ret = lowpan_debugfs_init(); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | |||
31 | request_module_nowait("ipv6"); | 79 | request_module_nowait("ipv6"); |
32 | 80 | ||
33 | request_module_nowait("nhc_dest"); | 81 | request_module_nowait("nhc_dest"); |
@@ -40,6 +88,13 @@ static int __init lowpan_module_init(void) | |||
40 | 88 | ||
41 | return 0; | 89 | return 0; |
42 | } | 90 | } |
91 | |||
92 | static void __exit lowpan_module_exit(void) | ||
93 | { | ||
94 | lowpan_debugfs_exit(); | ||
95 | } | ||
96 | |||
43 | module_init(lowpan_module_init); | 97 | module_init(lowpan_module_init); |
98 | module_exit(lowpan_module_exit); | ||
44 | 99 | ||
45 | MODULE_LICENSE("GPL"); | 100 | MODULE_LICENSE("GPL"); |
diff --git a/net/6lowpan/debugfs.c b/net/6lowpan/debugfs.c new file mode 100644 index 000000000000..88eef84df0fc --- /dev/null +++ b/net/6lowpan/debugfs.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* This program is free software; you can redistribute it and/or modify | ||
2 | * it under the terms of the GNU General Public License version 2 | ||
3 | * as published by the Free Software Foundation. | ||
4 | * | ||
5 | * This program is distributed in the hope that it will be useful, | ||
6 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
7 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
8 | * GNU General Public License for more details. | ||
9 | * | ||
10 | * Authors: | ||
11 | * (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de> | ||
12 | * Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. | ||
13 | */ | ||
14 | |||
15 | #include <net/6lowpan.h> | ||
16 | |||
17 | #include "6lowpan_i.h" | ||
18 | |||
19 | static struct dentry *lowpan_debugfs; | ||
20 | |||
21 | int lowpan_dev_debugfs_init(struct net_device *dev) | ||
22 | { | ||
23 | struct lowpan_priv *lpriv = lowpan_priv(dev); | ||
24 | |||
25 | /* creating the root */ | ||
26 | lpriv->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs); | ||
27 | if (!lpriv->iface_debugfs) | ||
28 | goto fail; | ||
29 | |||
30 | return 0; | ||
31 | |||
32 | fail: | ||
33 | return -EINVAL; | ||
34 | } | ||
35 | |||
36 | void lowpan_dev_debugfs_exit(struct net_device *dev) | ||
37 | { | ||
38 | debugfs_remove_recursive(lowpan_priv(dev)->iface_debugfs); | ||
39 | } | ||
40 | |||
41 | int __init lowpan_debugfs_init(void) | ||
42 | { | ||
43 | lowpan_debugfs = debugfs_create_dir("6lowpan", NULL); | ||
44 | if (!lowpan_debugfs) | ||
45 | return -EINVAL; | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | void lowpan_debugfs_exit(void) | ||
51 | { | ||
52 | debugfs_remove_recursive(lowpan_debugfs); | ||
53 | } | ||
diff --git a/net/6lowpan/nhc_ghc_ext_dest.c b/net/6lowpan/nhc_ghc_ext_dest.c new file mode 100644 index 000000000000..9887b3a15348 --- /dev/null +++ b/net/6lowpan/nhc_ghc_ext_dest.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * 6LoWPAN Extension Header compression according to RFC7400 | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "nhc.h" | ||
11 | |||
12 | #define LOWPAN_GHC_EXT_DEST_IDLEN 1 | ||
13 | #define LOWPAN_GHC_EXT_DEST_ID_0 0xb6 | ||
14 | #define LOWPAN_GHC_EXT_DEST_MASK_0 0xfe | ||
15 | |||
16 | static void dest_ghid_setup(struct lowpan_nhc *nhc) | ||
17 | { | ||
18 | nhc->id[0] = LOWPAN_GHC_EXT_DEST_ID_0; | ||
19 | nhc->idmask[0] = LOWPAN_GHC_EXT_DEST_MASK_0; | ||
20 | } | ||
21 | |||
22 | LOWPAN_NHC(ghc_ext_dest, "RFC7400 Destination Extension Header", NEXTHDR_DEST, | ||
23 | 0, dest_ghid_setup, LOWPAN_GHC_EXT_DEST_IDLEN, NULL, NULL); | ||
24 | |||
25 | module_lowpan_nhc(ghc_ext_dest); | ||
26 | MODULE_DESCRIPTION("6LoWPAN generic header destination extension compression"); | ||
27 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/6lowpan/nhc_ghc_ext_frag.c b/net/6lowpan/nhc_ghc_ext_frag.c new file mode 100644 index 000000000000..1308b79e939d --- /dev/null +++ b/net/6lowpan/nhc_ghc_ext_frag.c | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * 6LoWPAN Extension Header compression according to RFC7400 | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "nhc.h" | ||
11 | |||
12 | #define LOWPAN_GHC_EXT_FRAG_IDLEN 1 | ||
13 | #define LOWPAN_GHC_EXT_FRAG_ID_0 0xb4 | ||
14 | #define LOWPAN_GHC_EXT_FRAG_MASK_0 0xfe | ||
15 | |||
16 | static void frag_ghid_setup(struct lowpan_nhc *nhc) | ||
17 | { | ||
18 | nhc->id[0] = LOWPAN_GHC_EXT_FRAG_ID_0; | ||
19 | nhc->idmask[0] = LOWPAN_GHC_EXT_FRAG_MASK_0; | ||
20 | } | ||
21 | |||
22 | LOWPAN_NHC(ghc_ext_frag, "RFC7400 Fragmentation Extension Header", | ||
23 | NEXTHDR_FRAGMENT, 0, frag_ghid_setup, | ||
24 | LOWPAN_GHC_EXT_FRAG_IDLEN, NULL, NULL); | ||
25 | |||
26 | module_lowpan_nhc(ghc_ext_frag); | ||
27 | MODULE_DESCRIPTION("6LoWPAN generic header fragmentation extension compression"); | ||
28 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/6lowpan/nhc_ghc_ext_hop.c b/net/6lowpan/nhc_ghc_ext_hop.c new file mode 100644 index 000000000000..baec86fd1974 --- /dev/null +++ b/net/6lowpan/nhc_ghc_ext_hop.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * 6LoWPAN Extension Header compression according to RFC7400 | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "nhc.h" | ||
11 | |||
12 | #define LOWPAN_GHC_EXT_HOP_IDLEN 1 | ||
13 | #define LOWPAN_GHC_EXT_HOP_ID_0 0xb0 | ||
14 | #define LOWPAN_GHC_EXT_HOP_MASK_0 0xfe | ||
15 | |||
16 | static void hop_ghid_setup(struct lowpan_nhc *nhc) | ||
17 | { | ||
18 | nhc->id[0] = LOWPAN_GHC_EXT_HOP_ID_0; | ||
19 | nhc->idmask[0] = LOWPAN_GHC_EXT_HOP_MASK_0; | ||
20 | } | ||
21 | |||
22 | LOWPAN_NHC(ghc_ext_hop, "RFC7400 Hop-by-Hop Extension Header", NEXTHDR_HOP, 0, | ||
23 | hop_ghid_setup, LOWPAN_GHC_EXT_HOP_IDLEN, NULL, NULL); | ||
24 | |||
25 | module_lowpan_nhc(ghc_ext_hop); | ||
26 | MODULE_DESCRIPTION("6LoWPAN generic header hop-by-hop extension compression"); | ||
27 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/6lowpan/nhc_ghc_ext_route.c b/net/6lowpan/nhc_ghc_ext_route.c new file mode 100644 index 000000000000..d7e5bd791c62 --- /dev/null +++ b/net/6lowpan/nhc_ghc_ext_route.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * 6LoWPAN Extension Header compression according to RFC7400 | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "nhc.h" | ||
11 | |||
12 | #define LOWPAN_GHC_EXT_ROUTE_IDLEN 1 | ||
13 | #define LOWPAN_GHC_EXT_ROUTE_ID_0 0xb2 | ||
14 | #define LOWPAN_GHC_EXT_ROUTE_MASK_0 0xfe | ||
15 | |||
16 | static void route_ghid_setup(struct lowpan_nhc *nhc) | ||
17 | { | ||
18 | nhc->id[0] = LOWPAN_GHC_EXT_ROUTE_ID_0; | ||
19 | nhc->idmask[0] = LOWPAN_GHC_EXT_ROUTE_MASK_0; | ||
20 | } | ||
21 | |||
22 | LOWPAN_NHC(ghc_ext_route, "RFC7400 Routing Extension Header", NEXTHDR_ROUTING, | ||
23 | 0, route_ghid_setup, LOWPAN_GHC_EXT_ROUTE_IDLEN, NULL, NULL); | ||
24 | |||
25 | module_lowpan_nhc(ghc_ext_route); | ||
26 | MODULE_DESCRIPTION("6LoWPAN generic header routing extension compression"); | ||
27 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/6lowpan/nhc_ghc_icmpv6.c b/net/6lowpan/nhc_ghc_icmpv6.c new file mode 100644 index 000000000000..32e7c2c66bbc --- /dev/null +++ b/net/6lowpan/nhc_ghc_icmpv6.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * 6LoWPAN ICMPv6 compression according to RFC7400 | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "nhc.h" | ||
11 | |||
12 | #define LOWPAN_GHC_ICMPV6_IDLEN 1 | ||
13 | #define LOWPAN_GHC_ICMPV6_ID_0 0xdf | ||
14 | #define LOWPAN_GHC_ICMPV6_MASK_0 0xff | ||
15 | |||
16 | static void icmpv6_ghid_setup(struct lowpan_nhc *nhc) | ||
17 | { | ||
18 | nhc->id[0] = LOWPAN_GHC_ICMPV6_ID_0; | ||
19 | nhc->idmask[0] = LOWPAN_GHC_ICMPV6_MASK_0; | ||
20 | } | ||
21 | |||
22 | LOWPAN_NHC(ghc_icmpv6, "RFC7400 ICMPv6", NEXTHDR_ICMP, 0, | ||
23 | icmpv6_ghid_setup, LOWPAN_GHC_ICMPV6_IDLEN, NULL, NULL); | ||
24 | |||
25 | module_lowpan_nhc(ghc_icmpv6); | ||
26 | MODULE_DESCRIPTION("6LoWPAN generic header ICMPv6 compression"); | ||
27 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/6lowpan/nhc_ghc_udp.c b/net/6lowpan/nhc_ghc_udp.c new file mode 100644 index 000000000000..17beefa52ca8 --- /dev/null +++ b/net/6lowpan/nhc_ghc_udp.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * 6LoWPAN UDP compression according to RFC7400 | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "nhc.h" | ||
11 | |||
12 | #define LOWPAN_GHC_UDP_IDLEN 1 | ||
13 | #define LOWPAN_GHC_UDP_ID_0 0xd0 | ||
14 | #define LOWPAN_GHC_UDP_MASK_0 0xf8 | ||
15 | |||
16 | static void udp_ghid_setup(struct lowpan_nhc *nhc) | ||
17 | { | ||
18 | nhc->id[0] = LOWPAN_GHC_UDP_ID_0; | ||
19 | nhc->idmask[0] = LOWPAN_GHC_UDP_MASK_0; | ||
20 | } | ||
21 | |||
22 | LOWPAN_NHC(ghc_udp, "RFC7400 UDP", NEXTHDR_UDP, 0, | ||
23 | udp_ghid_setup, LOWPAN_GHC_UDP_IDLEN, NULL, NULL); | ||
24 | |||
25 | module_lowpan_nhc(ghc_udp); | ||
26 | MODULE_DESCRIPTION("6LoWPAN generic header UDP compression"); | ||
27 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index fded86508117..ad5e2fd1012c 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <linux/ethtool.h> | 31 | #include <linux/ethtool.h> |
32 | #include <net/arp.h> | 32 | #include <net/arp.h> |
33 | #include <net/switchdev.h> | ||
33 | 34 | ||
34 | #include "vlan.h" | 35 | #include "vlan.h" |
35 | #include "vlanproc.h" | 36 | #include "vlanproc.h" |
@@ -542,9 +543,9 @@ static int vlan_dev_init(struct net_device *dev) | |||
542 | (1<<__LINK_STATE_DORMANT))) | | 543 | (1<<__LINK_STATE_DORMANT))) | |
543 | (1<<__LINK_STATE_PRESENT); | 544 | (1<<__LINK_STATE_PRESENT); |
544 | 545 | ||
545 | dev->hw_features = NETIF_F_ALL_CSUM | NETIF_F_SG | | 546 | dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | |
546 | NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | | 547 | NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | |
547 | NETIF_F_HIGHDMA | NETIF_F_SCTP_CSUM | | 548 | NETIF_F_HIGHDMA | NETIF_F_SCTP_CRC | |
548 | NETIF_F_ALL_FCOE; | 549 | NETIF_F_ALL_FCOE; |
549 | 550 | ||
550 | dev->features |= real_dev->vlan_features | NETIF_F_LLTX | | 551 | dev->features |= real_dev->vlan_features | NETIF_F_LLTX | |
@@ -774,6 +775,12 @@ static const struct net_device_ops vlan_netdev_ops = { | |||
774 | .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, | 775 | .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, |
775 | #endif | 776 | #endif |
776 | .ndo_fix_features = vlan_dev_fix_features, | 777 | .ndo_fix_features = vlan_dev_fix_features, |
778 | .ndo_fdb_add = switchdev_port_fdb_add, | ||
779 | .ndo_fdb_del = switchdev_port_fdb_del, | ||
780 | .ndo_fdb_dump = switchdev_port_fdb_dump, | ||
781 | .ndo_bridge_setlink = switchdev_port_bridge_setlink, | ||
782 | .ndo_bridge_getlink = switchdev_port_bridge_getlink, | ||
783 | .ndo_bridge_dellink = switchdev_port_bridge_dellink, | ||
777 | .ndo_get_lock_subclass = vlan_dev_get_lock_subclass, | 784 | .ndo_get_lock_subclass = vlan_dev_get_lock_subclass, |
778 | .ndo_get_iflink = vlan_dev_get_iflink, | 785 | .ndo_get_iflink = vlan_dev_get_iflink, |
779 | }; | 786 | }; |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 6e70ddb158b4..199bc76202d2 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -105,7 +105,7 @@ static struct list_head virtio_chan_list; | |||
105 | /* How many bytes left in this page. */ | 105 | /* How many bytes left in this page. */ |
106 | static unsigned int rest_of_page(void *data) | 106 | static unsigned int rest_of_page(void *data) |
107 | { | 107 | { |
108 | return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); | 108 | return PAGE_SIZE - offset_in_page(data); |
109 | } | 109 | } |
110 | 110 | ||
111 | /** | 111 | /** |
@@ -143,7 +143,6 @@ static void p9_virtio_close(struct p9_client *client) | |||
143 | static void req_done(struct virtqueue *vq) | 143 | static void req_done(struct virtqueue *vq) |
144 | { | 144 | { |
145 | struct virtio_chan *chan = vq->vdev->priv; | 145 | struct virtio_chan *chan = vq->vdev->priv; |
146 | struct p9_fcall *rc; | ||
147 | unsigned int len; | 146 | unsigned int len; |
148 | struct p9_req_t *req; | 147 | struct p9_req_t *req; |
149 | unsigned long flags; | 148 | unsigned long flags; |
@@ -152,8 +151,8 @@ static void req_done(struct virtqueue *vq) | |||
152 | 151 | ||
153 | while (1) { | 152 | while (1) { |
154 | spin_lock_irqsave(&chan->lock, flags); | 153 | spin_lock_irqsave(&chan->lock, flags); |
155 | rc = virtqueue_get_buf(chan->vq, &len); | 154 | req = virtqueue_get_buf(chan->vq, &len); |
156 | if (rc == NULL) { | 155 | if (req == NULL) { |
157 | spin_unlock_irqrestore(&chan->lock, flags); | 156 | spin_unlock_irqrestore(&chan->lock, flags); |
158 | break; | 157 | break; |
159 | } | 158 | } |
@@ -161,9 +160,6 @@ static void req_done(struct virtqueue *vq) | |||
161 | spin_unlock_irqrestore(&chan->lock, flags); | 160 | spin_unlock_irqrestore(&chan->lock, flags); |
162 | /* Wakeup if anyone waiting for VirtIO ring space. */ | 161 | /* Wakeup if anyone waiting for VirtIO ring space. */ |
163 | wake_up(chan->vc_wq); | 162 | wake_up(chan->vc_wq); |
164 | p9_debug(P9_DEBUG_TRANS, ": rc %p\n", rc); | ||
165 | p9_debug(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); | ||
166 | req = p9_tag_lookup(chan->client, rc->tag); | ||
167 | p9_client_cb(chan->client, req, REQ_STATUS_RCVD); | 163 | p9_client_cb(chan->client, req, REQ_STATUS_RCVD); |
168 | } | 164 | } |
169 | } | 165 | } |
@@ -284,7 +280,7 @@ req_retry: | |||
284 | if (in) | 280 | if (in) |
285 | sgs[out_sgs + in_sgs++] = chan->sg + out; | 281 | sgs[out_sgs + in_sgs++] = chan->sg + out; |
286 | 282 | ||
287 | err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc, | 283 | err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req, |
288 | GFP_ATOMIC); | 284 | GFP_ATOMIC); |
289 | if (err < 0) { | 285 | if (err < 0) { |
290 | if (err == -ENOSPC) { | 286 | if (err == -ENOSPC) { |
@@ -369,7 +365,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, | |||
369 | return -ENOMEM; | 365 | return -ENOMEM; |
370 | 366 | ||
371 | *need_drop = 0; | 367 | *need_drop = 0; |
372 | p -= (*offs = (unsigned long)p % PAGE_SIZE); | 368 | p -= (*offs = offset_in_page(p)); |
373 | for (index = 0; index < nr_pages; index++) { | 369 | for (index = 0; index < nr_pages; index++) { |
374 | if (is_vmalloc_addr(p)) | 370 | if (is_vmalloc_addr(p)) |
375 | (*pages)[index] = vmalloc_to_page(p); | 371 | (*pages)[index] = vmalloc_to_page(p); |
@@ -469,7 +465,7 @@ req_retry_pinned: | |||
469 | } | 465 | } |
470 | 466 | ||
471 | BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs)); | 467 | BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs)); |
472 | err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc, | 468 | err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req, |
473 | GFP_ATOMIC); | 469 | GFP_ATOMIC); |
474 | if (err < 0) { | 470 | if (err < 0) { |
475 | if (err == -ENOSPC) { | 471 | if (err == -ENOSPC) { |
diff --git a/net/Kconfig b/net/Kconfig index 127da94ae25e..174354618f8a 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -48,6 +48,9 @@ config COMPAT_NETLINK_MESSAGES | |||
48 | config NET_INGRESS | 48 | config NET_INGRESS |
49 | bool | 49 | bool |
50 | 50 | ||
51 | config NET_EGRESS | ||
52 | bool | ||
53 | |||
51 | menu "Networking options" | 54 | menu "Networking options" |
52 | 55 | ||
53 | source "net/packet/Kconfig" | 56 | source "net/packet/Kconfig" |
@@ -250,9 +253,14 @@ config XPS | |||
250 | depends on SMP | 253 | depends on SMP |
251 | default y | 254 | default y |
252 | 255 | ||
256 | config SOCK_CGROUP_DATA | ||
257 | bool | ||
258 | default n | ||
259 | |||
253 | config CGROUP_NET_PRIO | 260 | config CGROUP_NET_PRIO |
254 | bool "Network priority cgroup" | 261 | bool "Network priority cgroup" |
255 | depends on CGROUPS | 262 | depends on CGROUPS |
263 | select SOCK_CGROUP_DATA | ||
256 | ---help--- | 264 | ---help--- |
257 | Cgroup subsystem for use in assigning processes to network priorities on | 265 | Cgroup subsystem for use in assigning processes to network priorities on |
258 | a per-interface basis. | 266 | a per-interface basis. |
@@ -260,6 +268,7 @@ config CGROUP_NET_PRIO | |||
260 | config CGROUP_NET_CLASSID | 268 | config CGROUP_NET_CLASSID |
261 | bool "Network classid cgroup" | 269 | bool "Network classid cgroup" |
262 | depends on CGROUPS | 270 | depends on CGROUPS |
271 | select SOCK_CGROUP_DATA | ||
263 | ---help--- | 272 | ---help--- |
264 | Cgroup subsystem for use as general purpose socket classid marker that is | 273 | Cgroup subsystem for use as general purpose socket classid marker that is |
265 | being used in cls_cgroup and for netfilter matching. | 274 | being used in cls_cgroup and for netfilter matching. |
diff --git a/net/atm/common.c b/net/atm/common.c index 49a872db7e42..6dc12305799e 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -96,7 +96,7 @@ static void vcc_def_wakeup(struct sock *sk) | |||
96 | 96 | ||
97 | rcu_read_lock(); | 97 | rcu_read_lock(); |
98 | wq = rcu_dereference(sk->sk_wq); | 98 | wq = rcu_dereference(sk->sk_wq); |
99 | if (wq_has_sleeper(wq)) | 99 | if (skwq_has_sleeper(wq)) |
100 | wake_up(&wq->wait); | 100 | wake_up(&wq->wait); |
101 | rcu_read_unlock(); | 101 | rcu_read_unlock(); |
102 | } | 102 | } |
@@ -117,7 +117,7 @@ static void vcc_write_space(struct sock *sk) | |||
117 | 117 | ||
118 | if (vcc_writable(sk)) { | 118 | if (vcc_writable(sk)) { |
119 | wq = rcu_dereference(sk->sk_wq); | 119 | wq = rcu_dereference(sk->sk_wq); |
120 | if (wq_has_sleeper(wq)) | 120 | if (skwq_has_sleeper(wq)) |
121 | wake_up_interruptible(&wq->wait); | 121 | wake_up_interruptible(&wq->wait); |
122 | 122 | ||
123 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 123 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
diff --git a/net/atm/mpc.h b/net/atm/mpc.h index 0919a88bbc70..cfc7b745aa91 100644 --- a/net/atm/mpc.h +++ b/net/atm/mpc.h | |||
@@ -21,11 +21,11 @@ struct mpoa_client { | |||
21 | uint8_t our_ctrl_addr[ATM_ESA_LEN]; /* MPC's control ATM address */ | 21 | uint8_t our_ctrl_addr[ATM_ESA_LEN]; /* MPC's control ATM address */ |
22 | 22 | ||
23 | rwlock_t ingress_lock; | 23 | rwlock_t ingress_lock; |
24 | struct in_cache_ops *in_ops; /* ingress cache operations */ | 24 | const struct in_cache_ops *in_ops; /* ingress cache operations */ |
25 | in_cache_entry *in_cache; /* the ingress cache of this MPC */ | 25 | in_cache_entry *in_cache; /* the ingress cache of this MPC */ |
26 | 26 | ||
27 | rwlock_t egress_lock; | 27 | rwlock_t egress_lock; |
28 | struct eg_cache_ops *eg_ops; /* egress cache operations */ | 28 | const struct eg_cache_ops *eg_ops; /* egress cache operations */ |
29 | eg_cache_entry *eg_cache; /* the egress cache of this MPC */ | 29 | eg_cache_entry *eg_cache; /* the egress cache of this MPC */ |
30 | 30 | ||
31 | uint8_t *mps_macs; /* array of MPS MAC addresses, >=1 */ | 31 | uint8_t *mps_macs; /* array of MPS MAC addresses, >=1 */ |
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index d1b2d9a03144..9e60e74c807d 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c | |||
@@ -534,7 +534,7 @@ static void eg_destroy_cache(struct mpoa_client *mpc) | |||
534 | } | 534 | } |
535 | 535 | ||
536 | 536 | ||
537 | static struct in_cache_ops ingress_ops = { | 537 | static const struct in_cache_ops ingress_ops = { |
538 | in_cache_add_entry, /* add_entry */ | 538 | in_cache_add_entry, /* add_entry */ |
539 | in_cache_get, /* get */ | 539 | in_cache_get, /* get */ |
540 | in_cache_get_with_mask, /* get_with_mask */ | 540 | in_cache_get_with_mask, /* get_with_mask */ |
@@ -548,7 +548,7 @@ static struct in_cache_ops ingress_ops = { | |||
548 | in_destroy_cache /* destroy_cache */ | 548 | in_destroy_cache /* destroy_cache */ |
549 | }; | 549 | }; |
550 | 550 | ||
551 | static struct eg_cache_ops egress_ops = { | 551 | static const struct eg_cache_ops egress_ops = { |
552 | eg_cache_add_entry, /* add_entry */ | 552 | eg_cache_add_entry, /* add_entry */ |
553 | eg_cache_get_by_cache_id, /* get_by_cache_id */ | 553 | eg_cache_get_by_cache_id, /* get_by_cache_id */ |
554 | eg_cache_get_by_tag, /* get_by_tag */ | 554 | eg_cache_get_by_tag, /* get_by_tag */ |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index ae3a47f9d1d5..fbd0acf80b13 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -805,6 +805,9 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol, | |||
805 | struct sock *sk; | 805 | struct sock *sk; |
806 | ax25_cb *ax25; | 806 | ax25_cb *ax25; |
807 | 807 | ||
808 | if (protocol < 0 || protocol > SK_PROTOCOL_MAX) | ||
809 | return -EINVAL; | ||
810 | |||
808 | if (!net_eq(net, &init_net)) | 811 | if (!net_eq(net, &init_net)) |
809 | return -EAFNOSUPPORT; | 812 | return -EAFNOSUPPORT; |
810 | 813 | ||
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 912d9c36fb1c..df625de55ef2 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -185,7 +185,8 @@ unlock: | |||
185 | static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node, | 185 | static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node, |
186 | int max_if_num, int del_if_num) | 186 | int max_if_num, int del_if_num) |
187 | { | 187 | { |
188 | int chunk_size, ret = -ENOMEM, if_offset; | 188 | int ret = -ENOMEM; |
189 | size_t chunk_size, if_offset; | ||
189 | void *data_ptr = NULL; | 190 | void *data_ptr = NULL; |
190 | 191 | ||
191 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); | 192 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); |
@@ -203,8 +204,9 @@ static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node, | |||
203 | memcpy(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size); | 204 | memcpy(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size); |
204 | 205 | ||
205 | /* copy second part */ | 206 | /* copy second part */ |
207 | if_offset = (del_if_num + 1) * chunk_size; | ||
206 | memcpy((char *)data_ptr + del_if_num * chunk_size, | 208 | memcpy((char *)data_ptr + del_if_num * chunk_size, |
207 | orig_node->bat_iv.bcast_own + ((del_if_num + 1) * chunk_size), | 209 | (uint8_t *)orig_node->bat_iv.bcast_own + if_offset, |
208 | (max_if_num - del_if_num) * chunk_size); | 210 | (max_if_num - del_if_num) * chunk_size); |
209 | 211 | ||
210 | free_bcast_own: | 212 | free_bcast_own: |
@@ -361,7 +363,6 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface) | |||
361 | unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; | 363 | unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; |
362 | 364 | ||
363 | batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; | 365 | batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; |
364 | batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP; | ||
365 | batadv_ogm_packet->ttl = BATADV_TTL; | 366 | batadv_ogm_packet->ttl = BATADV_TTL; |
366 | } | 367 | } |
367 | 368 | ||
@@ -842,8 +843,6 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, | |||
842 | "Forwarding packet: tq: %i, ttl: %i\n", | 843 | "Forwarding packet: tq: %i, ttl: %i\n", |
843 | batadv_ogm_packet->tq, batadv_ogm_packet->ttl); | 844 | batadv_ogm_packet->tq, batadv_ogm_packet->ttl); |
844 | 845 | ||
845 | /* switch of primaries first hop flag when forwarding */ | ||
846 | batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP; | ||
847 | if (is_single_hop_neigh) | 846 | if (is_single_hop_neigh) |
848 | batadv_ogm_packet->flags |= BATADV_DIRECTLINK; | 847 | batadv_ogm_packet->flags |= BATADV_DIRECTLINK; |
849 | else | 848 | else |
@@ -1379,6 +1378,7 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset, | |||
1379 | struct batadv_hard_iface *if_outgoing) | 1378 | struct batadv_hard_iface *if_outgoing) |
1380 | { | 1379 | { |
1381 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 1380 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
1381 | struct batadv_hardif_neigh_node *hardif_neigh = NULL; | ||
1382 | struct batadv_neigh_node *router = NULL; | 1382 | struct batadv_neigh_node *router = NULL; |
1383 | struct batadv_neigh_node *router_router = NULL; | 1383 | struct batadv_neigh_node *router_router = NULL; |
1384 | struct batadv_orig_node *orig_neigh_node; | 1384 | struct batadv_orig_node *orig_neigh_node; |
@@ -1423,6 +1423,13 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset, | |||
1423 | goto out; | 1423 | goto out; |
1424 | } | 1424 | } |
1425 | 1425 | ||
1426 | if (is_single_hop_neigh) { | ||
1427 | hardif_neigh = batadv_hardif_neigh_get(if_incoming, | ||
1428 | ethhdr->h_source); | ||
1429 | if (hardif_neigh) | ||
1430 | hardif_neigh->last_seen = jiffies; | ||
1431 | } | ||
1432 | |||
1426 | router = batadv_orig_router_get(orig_node, if_outgoing); | 1433 | router = batadv_orig_router_get(orig_node, if_outgoing); |
1427 | if (router) { | 1434 | if (router) { |
1428 | router_router = batadv_orig_router_get(router->orig_node, | 1435 | router_router = batadv_orig_router_get(router->orig_node, |
@@ -1557,6 +1564,8 @@ out: | |||
1557 | batadv_neigh_node_free_ref(router_router); | 1564 | batadv_neigh_node_free_ref(router_router); |
1558 | if (orig_neigh_router) | 1565 | if (orig_neigh_router) |
1559 | batadv_neigh_node_free_ref(orig_neigh_router); | 1566 | batadv_neigh_node_free_ref(orig_neigh_router); |
1567 | if (hardif_neigh) | ||
1568 | batadv_hardif_neigh_free_ref(hardif_neigh); | ||
1560 | 1569 | ||
1561 | kfree_skb(skb_priv); | 1570 | kfree_skb(skb_priv); |
1562 | } | 1571 | } |
@@ -1862,6 +1871,58 @@ next: | |||
1862 | } | 1871 | } |
1863 | 1872 | ||
1864 | /** | 1873 | /** |
1874 | * batadv_iv_hardif_neigh_print - print a single hop neighbour node | ||
1875 | * @seq: neighbour table seq_file struct | ||
1876 | * @hardif_neigh: hardif neighbour information | ||
1877 | */ | ||
1878 | static void | ||
1879 | batadv_iv_hardif_neigh_print(struct seq_file *seq, | ||
1880 | struct batadv_hardif_neigh_node *hardif_neigh) | ||
1881 | { | ||
1882 | int last_secs, last_msecs; | ||
1883 | |||
1884 | last_secs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) / 1000; | ||
1885 | last_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) % 1000; | ||
1886 | |||
1887 | seq_printf(seq, " %10s %pM %4i.%03is\n", | ||
1888 | hardif_neigh->if_incoming->net_dev->name, | ||
1889 | hardif_neigh->addr, last_secs, last_msecs); | ||
1890 | } | ||
1891 | |||
1892 | /** | ||
1893 | * batadv_iv_ogm_neigh_print - print the single hop neighbour list | ||
1894 | * @bat_priv: the bat priv with all the soft interface information | ||
1895 | * @seq: neighbour table seq_file struct | ||
1896 | */ | ||
1897 | static void batadv_iv_neigh_print(struct batadv_priv *bat_priv, | ||
1898 | struct seq_file *seq) | ||
1899 | { | ||
1900 | struct net_device *net_dev = (struct net_device *)seq->private; | ||
1901 | struct batadv_hardif_neigh_node *hardif_neigh; | ||
1902 | struct batadv_hard_iface *hard_iface; | ||
1903 | int batman_count = 0; | ||
1904 | |||
1905 | seq_printf(seq, " %10s %-13s %s\n", | ||
1906 | "IF", "Neighbor", "last-seen"); | ||
1907 | |||
1908 | rcu_read_lock(); | ||
1909 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | ||
1910 | if (hard_iface->soft_iface != net_dev) | ||
1911 | continue; | ||
1912 | |||
1913 | hlist_for_each_entry_rcu(hardif_neigh, | ||
1914 | &hard_iface->neigh_list, list) { | ||
1915 | batadv_iv_hardif_neigh_print(seq, hardif_neigh); | ||
1916 | batman_count++; | ||
1917 | } | ||
1918 | } | ||
1919 | rcu_read_unlock(); | ||
1920 | |||
1921 | if (batman_count == 0) | ||
1922 | seq_puts(seq, "No batman nodes in range ...\n"); | ||
1923 | } | ||
1924 | |||
1925 | /** | ||
1865 | * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors | 1926 | * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors |
1866 | * @neigh1: the first neighbor object of the comparison | 1927 | * @neigh1: the first neighbor object of the comparison |
1867 | * @if_outgoing1: outgoing interface for the first neighbor | 1928 | * @if_outgoing1: outgoing interface for the first neighbor |
@@ -1902,8 +1963,8 @@ out: | |||
1902 | } | 1963 | } |
1903 | 1964 | ||
1904 | /** | 1965 | /** |
1905 | * batadv_iv_ogm_neigh_is_eob - check if neigh1 is equally good or better than | 1966 | * batadv_iv_ogm_neigh_is_sob - check if neigh1 is similarly good or better |
1906 | * neigh2 from the metric prospective | 1967 | * than neigh2 from the metric prospective |
1907 | * @neigh1: the first neighbor object of the comparison | 1968 | * @neigh1: the first neighbor object of the comparison |
1908 | * @if_outgoing1: outgoing interface for the first neighbor | 1969 | * @if_outgoing1: outgoing interface for the first neighbor |
1909 | * @neigh2: the second neighbor object of the comparison | 1970 | * @neigh2: the second neighbor object of the comparison |
@@ -1913,7 +1974,7 @@ out: | |||
1913 | * the metric via neigh2, false otherwise. | 1974 | * the metric via neigh2, false otherwise. |
1914 | */ | 1975 | */ |
1915 | static bool | 1976 | static bool |
1916 | batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1, | 1977 | batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1, |
1917 | struct batadv_hard_iface *if_outgoing1, | 1978 | struct batadv_hard_iface *if_outgoing1, |
1918 | struct batadv_neigh_node *neigh2, | 1979 | struct batadv_neigh_node *neigh2, |
1919 | struct batadv_hard_iface *if_outgoing2) | 1980 | struct batadv_hard_iface *if_outgoing2) |
@@ -1953,7 +2014,8 @@ static struct batadv_algo_ops batadv_batman_iv __read_mostly = { | |||
1953 | .bat_ogm_schedule = batadv_iv_ogm_schedule, | 2014 | .bat_ogm_schedule = batadv_iv_ogm_schedule, |
1954 | .bat_ogm_emit = batadv_iv_ogm_emit, | 2015 | .bat_ogm_emit = batadv_iv_ogm_emit, |
1955 | .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp, | 2016 | .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp, |
1956 | .bat_neigh_is_equiv_or_better = batadv_iv_ogm_neigh_is_eob, | 2017 | .bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob, |
2018 | .bat_neigh_print = batadv_iv_neigh_print, | ||
1957 | .bat_orig_print = batadv_iv_ogm_orig_print, | 2019 | .bat_orig_print = batadv_iv_ogm_orig_print, |
1958 | .bat_orig_free = batadv_iv_ogm_orig_free, | 2020 | .bat_orig_free = batadv_iv_ogm_orig_free, |
1959 | .bat_orig_add_if = batadv_iv_ogm_orig_add_if, | 2021 | .bat_orig_add_if = batadv_iv_ogm_orig_add_if, |
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 191a70290dca..d5d71ac96c8a 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
@@ -260,7 +260,9 @@ batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw) | |||
260 | } | 260 | } |
261 | 261 | ||
262 | /* all claims gone, initialize CRC */ | 262 | /* all claims gone, initialize CRC */ |
263 | spin_lock_bh(&backbone_gw->crc_lock); | ||
263 | backbone_gw->crc = BATADV_BLA_CRC_INIT; | 264 | backbone_gw->crc = BATADV_BLA_CRC_INIT; |
265 | spin_unlock_bh(&backbone_gw->crc_lock); | ||
264 | } | 266 | } |
265 | 267 | ||
266 | /** | 268 | /** |
@@ -408,6 +410,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig, | |||
408 | entry->lasttime = jiffies; | 410 | entry->lasttime = jiffies; |
409 | entry->crc = BATADV_BLA_CRC_INIT; | 411 | entry->crc = BATADV_BLA_CRC_INIT; |
410 | entry->bat_priv = bat_priv; | 412 | entry->bat_priv = bat_priv; |
413 | spin_lock_init(&entry->crc_lock); | ||
411 | atomic_set(&entry->request_sent, 0); | 414 | atomic_set(&entry->request_sent, 0); |
412 | atomic_set(&entry->wait_periods, 0); | 415 | atomic_set(&entry->wait_periods, 0); |
413 | ether_addr_copy(entry->orig, orig); | 416 | ether_addr_copy(entry->orig, orig); |
@@ -557,7 +560,9 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv, | |||
557 | __be16 crc; | 560 | __be16 crc; |
558 | 561 | ||
559 | memcpy(mac, batadv_announce_mac, 4); | 562 | memcpy(mac, batadv_announce_mac, 4); |
563 | spin_lock_bh(&backbone_gw->crc_lock); | ||
560 | crc = htons(backbone_gw->crc); | 564 | crc = htons(backbone_gw->crc); |
565 | spin_unlock_bh(&backbone_gw->crc_lock); | ||
561 | memcpy(&mac[4], &crc, 2); | 566 | memcpy(&mac[4], &crc, 2); |
562 | 567 | ||
563 | batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid, | 568 | batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid, |
@@ -618,14 +623,18 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, | |||
618 | "bla_add_claim(): changing ownership for %pM, vid %d\n", | 623 | "bla_add_claim(): changing ownership for %pM, vid %d\n", |
619 | mac, BATADV_PRINT_VID(vid)); | 624 | mac, BATADV_PRINT_VID(vid)); |
620 | 625 | ||
626 | spin_lock_bh(&claim->backbone_gw->crc_lock); | ||
621 | claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); | 627 | claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); |
628 | spin_unlock_bh(&claim->backbone_gw->crc_lock); | ||
622 | batadv_backbone_gw_free_ref(claim->backbone_gw); | 629 | batadv_backbone_gw_free_ref(claim->backbone_gw); |
623 | } | 630 | } |
624 | /* set (new) backbone gw */ | 631 | /* set (new) backbone gw */ |
625 | atomic_inc(&backbone_gw->refcount); | 632 | atomic_inc(&backbone_gw->refcount); |
626 | claim->backbone_gw = backbone_gw; | 633 | claim->backbone_gw = backbone_gw; |
627 | 634 | ||
635 | spin_lock_bh(&backbone_gw->crc_lock); | ||
628 | backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); | 636 | backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); |
637 | spin_unlock_bh(&backbone_gw->crc_lock); | ||
629 | backbone_gw->lasttime = jiffies; | 638 | backbone_gw->lasttime = jiffies; |
630 | 639 | ||
631 | claim_free_ref: | 640 | claim_free_ref: |
@@ -653,7 +662,9 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, | |||
653 | batadv_choose_claim, claim); | 662 | batadv_choose_claim, claim); |
654 | batadv_claim_free_ref(claim); /* reference from the hash is gone */ | 663 | batadv_claim_free_ref(claim); /* reference from the hash is gone */ |
655 | 664 | ||
665 | spin_lock_bh(&claim->backbone_gw->crc_lock); | ||
656 | claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); | 666 | claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); |
667 | spin_unlock_bh(&claim->backbone_gw->crc_lock); | ||
657 | 668 | ||
658 | /* don't need the reference from hash_find() anymore */ | 669 | /* don't need the reference from hash_find() anymore */ |
659 | batadv_claim_free_ref(claim); | 670 | batadv_claim_free_ref(claim); |
@@ -664,7 +675,7 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr, | |||
664 | u8 *backbone_addr, unsigned short vid) | 675 | u8 *backbone_addr, unsigned short vid) |
665 | { | 676 | { |
666 | struct batadv_bla_backbone_gw *backbone_gw; | 677 | struct batadv_bla_backbone_gw *backbone_gw; |
667 | u16 crc; | 678 | u16 backbone_crc, crc; |
668 | 679 | ||
669 | if (memcmp(an_addr, batadv_announce_mac, 4) != 0) | 680 | if (memcmp(an_addr, batadv_announce_mac, 4) != 0) |
670 | return 0; | 681 | return 0; |
@@ -683,12 +694,16 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr, | |||
683 | "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n", | 694 | "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n", |
684 | BATADV_PRINT_VID(vid), backbone_gw->orig, crc); | 695 | BATADV_PRINT_VID(vid), backbone_gw->orig, crc); |
685 | 696 | ||
686 | if (backbone_gw->crc != crc) { | 697 | spin_lock_bh(&backbone_gw->crc_lock); |
698 | backbone_crc = backbone_gw->crc; | ||
699 | spin_unlock_bh(&backbone_gw->crc_lock); | ||
700 | |||
701 | if (backbone_crc != crc) { | ||
687 | batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv, | 702 | batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv, |
688 | "handle_announce(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n", | 703 | "handle_announce(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n", |
689 | backbone_gw->orig, | 704 | backbone_gw->orig, |
690 | BATADV_PRINT_VID(backbone_gw->vid), | 705 | BATADV_PRINT_VID(backbone_gw->vid), |
691 | backbone_gw->crc, crc); | 706 | backbone_crc, crc); |
692 | 707 | ||
693 | batadv_bla_send_request(backbone_gw); | 708 | batadv_bla_send_request(backbone_gw); |
694 | } else { | 709 | } else { |
@@ -1153,6 +1168,26 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, | |||
1153 | } | 1168 | } |
1154 | } | 1169 | } |
1155 | 1170 | ||
1171 | /** | ||
1172 | * batadv_bla_status_update - purge bla interfaces if necessary | ||
1173 | * @net_dev: the soft interface net device | ||
1174 | */ | ||
1175 | void batadv_bla_status_update(struct net_device *net_dev) | ||
1176 | { | ||
1177 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | ||
1178 | struct batadv_hard_iface *primary_if; | ||
1179 | |||
1180 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
1181 | if (!primary_if) | ||
1182 | return; | ||
1183 | |||
1184 | /* this function already purges everything when bla is disabled, | ||
1185 | * so just call that one. | ||
1186 | */ | ||
1187 | batadv_bla_update_orig_address(bat_priv, primary_if, primary_if); | ||
1188 | batadv_hardif_free_ref(primary_if); | ||
1189 | } | ||
1190 | |||
1156 | /* periodic work to do: | 1191 | /* periodic work to do: |
1157 | * * purge structures when they are too old | 1192 | * * purge structures when they are too old |
1158 | * * send announcements | 1193 | * * send announcements |
@@ -1647,6 +1682,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1647 | struct batadv_bla_claim *claim; | 1682 | struct batadv_bla_claim *claim; |
1648 | struct batadv_hard_iface *primary_if; | 1683 | struct batadv_hard_iface *primary_if; |
1649 | struct hlist_head *head; | 1684 | struct hlist_head *head; |
1685 | u16 backbone_crc; | ||
1650 | u32 i; | 1686 | u32 i; |
1651 | bool is_own; | 1687 | bool is_own; |
1652 | u8 *primary_addr; | 1688 | u8 *primary_addr; |
@@ -1669,11 +1705,15 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1669 | hlist_for_each_entry_rcu(claim, head, hash_entry) { | 1705 | hlist_for_each_entry_rcu(claim, head, hash_entry) { |
1670 | is_own = batadv_compare_eth(claim->backbone_gw->orig, | 1706 | is_own = batadv_compare_eth(claim->backbone_gw->orig, |
1671 | primary_addr); | 1707 | primary_addr); |
1708 | |||
1709 | spin_lock_bh(&claim->backbone_gw->crc_lock); | ||
1710 | backbone_crc = claim->backbone_gw->crc; | ||
1711 | spin_unlock_bh(&claim->backbone_gw->crc_lock); | ||
1672 | seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n", | 1712 | seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n", |
1673 | claim->addr, BATADV_PRINT_VID(claim->vid), | 1713 | claim->addr, BATADV_PRINT_VID(claim->vid), |
1674 | claim->backbone_gw->orig, | 1714 | claim->backbone_gw->orig, |
1675 | (is_own ? 'x' : ' '), | 1715 | (is_own ? 'x' : ' '), |
1676 | claim->backbone_gw->crc); | 1716 | backbone_crc); |
1677 | } | 1717 | } |
1678 | rcu_read_unlock(); | 1718 | rcu_read_unlock(); |
1679 | } | 1719 | } |
@@ -1692,6 +1732,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1692 | struct batadv_hard_iface *primary_if; | 1732 | struct batadv_hard_iface *primary_if; |
1693 | struct hlist_head *head; | 1733 | struct hlist_head *head; |
1694 | int secs, msecs; | 1734 | int secs, msecs; |
1735 | u16 backbone_crc; | ||
1695 | u32 i; | 1736 | u32 i; |
1696 | bool is_own; | 1737 | bool is_own; |
1697 | u8 *primary_addr; | 1738 | u8 *primary_addr; |
@@ -1722,10 +1763,14 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1722 | if (is_own) | 1763 | if (is_own) |
1723 | continue; | 1764 | continue; |
1724 | 1765 | ||
1766 | spin_lock_bh(&backbone_gw->crc_lock); | ||
1767 | backbone_crc = backbone_gw->crc; | ||
1768 | spin_unlock_bh(&backbone_gw->crc_lock); | ||
1769 | |||
1725 | seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n", | 1770 | seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n", |
1726 | backbone_gw->orig, | 1771 | backbone_gw->orig, |
1727 | BATADV_PRINT_VID(backbone_gw->vid), secs, | 1772 | BATADV_PRINT_VID(backbone_gw->vid), secs, |
1728 | msecs, backbone_gw->crc); | 1773 | msecs, backbone_crc); |
1729 | } | 1774 | } |
1730 | rcu_read_unlock(); | 1775 | rcu_read_unlock(); |
1731 | } | 1776 | } |
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h index 025152b34282..7ea199b8b5ab 100644 --- a/net/batman-adv/bridge_loop_avoidance.h +++ b/net/batman-adv/bridge_loop_avoidance.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | 24 | ||
25 | struct net_device; | ||
25 | struct seq_file; | 26 | struct seq_file; |
26 | struct sk_buff; | 27 | struct sk_buff; |
27 | 28 | ||
@@ -42,6 +43,7 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | |||
42 | void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, | 43 | void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, |
43 | struct batadv_hard_iface *primary_if, | 44 | struct batadv_hard_iface *primary_if, |
44 | struct batadv_hard_iface *oldif); | 45 | struct batadv_hard_iface *oldif); |
46 | void batadv_bla_status_update(struct net_device *net_dev); | ||
45 | int batadv_bla_init(struct batadv_priv *bat_priv); | 47 | int batadv_bla_init(struct batadv_priv *bat_priv); |
46 | void batadv_bla_free(struct batadv_priv *bat_priv); | 48 | void batadv_bla_free(struct batadv_priv *bat_priv); |
47 | 49 | ||
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index c4c1e8030ba0..037ad0a5f485 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c | |||
@@ -262,6 +262,13 @@ static int batadv_algorithms_open(struct inode *inode, struct file *file) | |||
262 | return single_open(file, batadv_algo_seq_print_text, NULL); | 262 | return single_open(file, batadv_algo_seq_print_text, NULL); |
263 | } | 263 | } |
264 | 264 | ||
265 | static int neighbors_open(struct inode *inode, struct file *file) | ||
266 | { | ||
267 | struct net_device *net_dev = (struct net_device *)inode->i_private; | ||
268 | |||
269 | return single_open(file, batadv_hardif_neigh_seq_print_text, net_dev); | ||
270 | } | ||
271 | |||
265 | static int batadv_originators_open(struct inode *inode, struct file *file) | 272 | static int batadv_originators_open(struct inode *inode, struct file *file) |
266 | { | 273 | { |
267 | struct net_device *net_dev = (struct net_device *)inode->i_private; | 274 | struct net_device *net_dev = (struct net_device *)inode->i_private; |
@@ -375,6 +382,7 @@ static struct batadv_debuginfo *batadv_general_debuginfos[] = { | |||
375 | }; | 382 | }; |
376 | 383 | ||
377 | /* The following attributes are per soft interface */ | 384 | /* The following attributes are per soft interface */ |
385 | static BATADV_DEBUGINFO(neighbors, S_IRUGO, neighbors_open); | ||
378 | static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open); | 386 | static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open); |
379 | static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open); | 387 | static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open); |
380 | static BATADV_DEBUGINFO(transtable_global, S_IRUGO, | 388 | static BATADV_DEBUGINFO(transtable_global, S_IRUGO, |
@@ -394,6 +402,7 @@ static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); | |||
394 | #endif | 402 | #endif |
395 | 403 | ||
396 | static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { | 404 | static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { |
405 | &batadv_debuginfo_neighbors, | ||
397 | &batadv_debuginfo_originators, | 406 | &batadv_debuginfo_originators, |
398 | &batadv_debuginfo_gateways, | 407 | &batadv_debuginfo_gateways, |
399 | &batadv_debuginfo_transtable_global, | 408 | &batadv_debuginfo_transtable_global, |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 83bc1aaf5800..a49c705fb86b 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -566,6 +566,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) | |||
566 | int select; | 566 | int select; |
567 | batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key; | 567 | batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key; |
568 | struct batadv_dat_candidate *res; | 568 | struct batadv_dat_candidate *res; |
569 | struct batadv_dat_entry dat; | ||
569 | 570 | ||
570 | if (!bat_priv->orig_hash) | 571 | if (!bat_priv->orig_hash) |
571 | return NULL; | 572 | return NULL; |
@@ -575,7 +576,9 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) | |||
575 | if (!res) | 576 | if (!res) |
576 | return NULL; | 577 | return NULL; |
577 | 578 | ||
578 | ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst, | 579 | dat.ip = ip_dst; |
580 | dat.vid = 0; | ||
581 | ip_key = (batadv_dat_addr_t)batadv_hash_dat(&dat, | ||
579 | BATADV_DAT_ADDR_MAX); | 582 | BATADV_DAT_ADDR_MAX); |
580 | 583 | ||
581 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | 584 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 700c96c82a15..20d9282f895b 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
@@ -71,14 +71,14 @@ void batadv_frag_purge_orig(struct batadv_orig_node *orig_node, | |||
71 | 71 | ||
72 | for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) { | 72 | for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) { |
73 | chain = &orig_node->fragments[i]; | 73 | chain = &orig_node->fragments[i]; |
74 | spin_lock_bh(&orig_node->fragments[i].lock); | 74 | spin_lock_bh(&chain->lock); |
75 | 75 | ||
76 | if (!check_cb || check_cb(chain)) { | 76 | if (!check_cb || check_cb(chain)) { |
77 | batadv_frag_clear_chain(&orig_node->fragments[i].head); | 77 | batadv_frag_clear_chain(&chain->head); |
78 | orig_node->fragments[i].size = 0; | 78 | chain->size = 0; |
79 | } | 79 | } |
80 | 80 | ||
81 | spin_unlock_bh(&orig_node->fragments[i].lock); | 81 | spin_unlock_bh(&chain->lock); |
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 0cb5e6b6f6d4..b51bface8bdd 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c | |||
@@ -31,27 +31,23 @@ | |||
31 | #include "packet.h" | 31 | #include "packet.h" |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * batadv_parse_gw_bandwidth - parse supplied string buffer to extract download | 34 | * batadv_parse_throughput - parse supplied string buffer to extract throughput |
35 | * and upload bandwidth information | 35 | * information |
36 | * @net_dev: the soft interface net device | 36 | * @net_dev: the soft interface net device |
37 | * @buff: string buffer to parse | 37 | * @buff: string buffer to parse |
38 | * @down: pointer holding the returned download bandwidth information | 38 | * @description: text shown when throughput string cannot be parsed |
39 | * @up: pointer holding the returned upload bandwidth information | 39 | * @throughput: pointer holding the returned throughput information |
40 | * | 40 | * |
41 | * Returns false on parse error and true otherwise. | 41 | * Returns false on parse error and true otherwise. |
42 | */ | 42 | */ |
43 | static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | 43 | static bool batadv_parse_throughput(struct net_device *net_dev, char *buff, |
44 | u32 *down, u32 *up) | 44 | const char *description, u32 *throughput) |
45 | { | 45 | { |
46 | enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT; | 46 | enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT; |
47 | char *slash_ptr, *tmp_ptr; | 47 | u64 lthroughput; |
48 | u64 ldown, lup; | 48 | char *tmp_ptr; |
49 | int ret; | 49 | int ret; |
50 | 50 | ||
51 | slash_ptr = strchr(buff, '/'); | ||
52 | if (slash_ptr) | ||
53 | *slash_ptr = 0; | ||
54 | |||
55 | if (strlen(buff) > 4) { | 51 | if (strlen(buff) > 4) { |
56 | tmp_ptr = buff + strlen(buff) - 4; | 52 | tmp_ptr = buff + strlen(buff) - 4; |
57 | 53 | ||
@@ -63,90 +59,75 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | |||
63 | *tmp_ptr = '\0'; | 59 | *tmp_ptr = '\0'; |
64 | } | 60 | } |
65 | 61 | ||
66 | ret = kstrtou64(buff, 10, &ldown); | 62 | ret = kstrtou64(buff, 10, <hroughput); |
67 | if (ret) { | 63 | if (ret) { |
68 | batadv_err(net_dev, | 64 | batadv_err(net_dev, |
69 | "Download speed of gateway mode invalid: %s\n", | 65 | "Invalid throughput speed for %s: %s\n", |
70 | buff); | 66 | description, buff); |
71 | return false; | 67 | return false; |
72 | } | 68 | } |
73 | 69 | ||
74 | switch (bw_unit_type) { | 70 | switch (bw_unit_type) { |
75 | case BATADV_BW_UNIT_MBIT: | 71 | case BATADV_BW_UNIT_MBIT: |
76 | /* prevent overflow */ | 72 | /* prevent overflow */ |
77 | if (U64_MAX / 10 < ldown) { | 73 | if (U64_MAX / 10 < lthroughput) { |
78 | batadv_err(net_dev, | 74 | batadv_err(net_dev, |
79 | "Download speed of gateway mode too large: %s\n", | 75 | "Throughput speed for %s too large: %s\n", |
80 | buff); | 76 | description, buff); |
81 | return false; | 77 | return false; |
82 | } | 78 | } |
83 | 79 | ||
84 | ldown *= 10; | 80 | lthroughput *= 10; |
85 | break; | 81 | break; |
86 | case BATADV_BW_UNIT_KBIT: | 82 | case BATADV_BW_UNIT_KBIT: |
87 | default: | 83 | default: |
88 | ldown = div_u64(ldown, 100); | 84 | lthroughput = div_u64(lthroughput, 100); |
89 | break; | 85 | break; |
90 | } | 86 | } |
91 | 87 | ||
92 | if (U32_MAX < ldown) { | 88 | if (lthroughput > U32_MAX) { |
93 | batadv_err(net_dev, | 89 | batadv_err(net_dev, |
94 | "Download speed of gateway mode too large: %s\n", | 90 | "Throughput speed for %s too large: %s\n", |
95 | buff); | 91 | description, buff); |
96 | return false; | 92 | return false; |
97 | } | 93 | } |
98 | 94 | ||
99 | *down = ldown; | 95 | *throughput = lthroughput; |
100 | |||
101 | /* we also got some upload info */ | ||
102 | if (slash_ptr) { | ||
103 | bw_unit_type = BATADV_BW_UNIT_KBIT; | ||
104 | |||
105 | if (strlen(slash_ptr + 1) > 4) { | ||
106 | tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1); | ||
107 | 96 | ||
108 | if (strncasecmp(tmp_ptr, "mbit", 4) == 0) | 97 | return true; |
109 | bw_unit_type = BATADV_BW_UNIT_MBIT; | 98 | } |
110 | 99 | ||
111 | if ((strncasecmp(tmp_ptr, "kbit", 4) == 0) || | 100 | /** |
112 | (bw_unit_type == BATADV_BW_UNIT_MBIT)) | 101 | * batadv_parse_gw_bandwidth - parse supplied string buffer to extract download |
113 | *tmp_ptr = '\0'; | 102 | * and upload bandwidth information |
114 | } | 103 | * @net_dev: the soft interface net device |
104 | * @buff: string buffer to parse | ||
105 | * @down: pointer holding the returned download bandwidth information | ||
106 | * @up: pointer holding the returned upload bandwidth information | ||
107 | * | ||
108 | * Return: false on parse error and true otherwise. | ||
109 | */ | ||
110 | static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | ||
111 | u32 *down, u32 *up) | ||
112 | { | ||
113 | char *slash_ptr; | ||
114 | bool ret; | ||
115 | 115 | ||
116 | ret = kstrtou64(slash_ptr + 1, 10, &lup); | 116 | slash_ptr = strchr(buff, '/'); |
117 | if (ret) { | 117 | if (slash_ptr) |
118 | batadv_err(net_dev, | 118 | *slash_ptr = 0; |
119 | "Upload speed of gateway mode invalid: %s\n", | ||
120 | slash_ptr + 1); | ||
121 | return false; | ||
122 | } | ||
123 | 119 | ||
124 | switch (bw_unit_type) { | 120 | ret = batadv_parse_throughput(net_dev, buff, "download gateway speed", |
125 | case BATADV_BW_UNIT_MBIT: | 121 | down); |
126 | /* prevent overflow */ | 122 | if (!ret) |
127 | if (U64_MAX / 10 < lup) { | 123 | return false; |
128 | batadv_err(net_dev, | ||
129 | "Upload speed of gateway mode too large: %s\n", | ||
130 | slash_ptr + 1); | ||
131 | return false; | ||
132 | } | ||
133 | |||
134 | lup *= 10; | ||
135 | break; | ||
136 | case BATADV_BW_UNIT_KBIT: | ||
137 | default: | ||
138 | lup = div_u64(lup, 100); | ||
139 | break; | ||
140 | } | ||
141 | 124 | ||
142 | if (U32_MAX < lup) { | 125 | /* we also got some upload info */ |
143 | batadv_err(net_dev, | 126 | if (slash_ptr) { |
144 | "Upload speed of gateway mode too large: %s\n", | 127 | ret = batadv_parse_throughput(net_dev, slash_ptr + 1, |
145 | slash_ptr + 1); | 128 | "upload gateway speed", up); |
129 | if (!ret) | ||
146 | return false; | 130 | return false; |
147 | } | ||
148 | |||
149 | *up = lup; | ||
150 | } | 131 | } |
151 | 132 | ||
152 | return true; | 133 | return true; |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index f11345e163d7..01acccc4d218 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/rculist.h> | 32 | #include <linux/rculist.h> |
33 | #include <linux/rtnetlink.h> | 33 | #include <linux/rtnetlink.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/spinlock.h> | ||
35 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
36 | #include <net/net_namespace.h> | 37 | #include <net/net_namespace.h> |
37 | 38 | ||
@@ -464,7 +465,8 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, | |||
464 | hard_iface->soft_iface = soft_iface; | 465 | hard_iface->soft_iface = soft_iface; |
465 | bat_priv = netdev_priv(hard_iface->soft_iface); | 466 | bat_priv = netdev_priv(hard_iface->soft_iface); |
466 | 467 | ||
467 | ret = netdev_master_upper_dev_link(hard_iface->net_dev, soft_iface); | 468 | ret = netdev_master_upper_dev_link(hard_iface->net_dev, |
469 | soft_iface, NULL, NULL); | ||
468 | if (ret) | 470 | if (ret) |
469 | goto err_dev; | 471 | goto err_dev; |
470 | 472 | ||
@@ -638,9 +640,12 @@ batadv_hardif_add_interface(struct net_device *net_dev) | |||
638 | goto free_sysfs; | 640 | goto free_sysfs; |
639 | 641 | ||
640 | INIT_LIST_HEAD(&hard_iface->list); | 642 | INIT_LIST_HEAD(&hard_iface->list); |
643 | INIT_HLIST_HEAD(&hard_iface->neigh_list); | ||
641 | INIT_WORK(&hard_iface->cleanup_work, | 644 | INIT_WORK(&hard_iface->cleanup_work, |
642 | batadv_hardif_remove_interface_finish); | 645 | batadv_hardif_remove_interface_finish); |
643 | 646 | ||
647 | spin_lock_init(&hard_iface->neigh_list_lock); | ||
648 | |||
644 | hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT; | 649 | hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT; |
645 | if (batadv_is_wifi_netdev(net_dev)) | 650 | if (batadv_is_wifi_netdev(net_dev)) |
646 | hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; | 651 | hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; |
@@ -708,7 +713,8 @@ static int batadv_hard_if_event(struct notifier_block *this, | |||
708 | } | 713 | } |
709 | 714 | ||
710 | hard_iface = batadv_hardif_get_by_netdev(net_dev); | 715 | hard_iface = batadv_hardif_get_by_netdev(net_dev); |
711 | if (!hard_iface && event == NETDEV_REGISTER) | 716 | if (!hard_iface && (event == NETDEV_REGISTER || |
717 | event == NETDEV_POST_TYPE_CHANGE)) | ||
712 | hard_iface = batadv_hardif_add_interface(net_dev); | 718 | hard_iface = batadv_hardif_add_interface(net_dev); |
713 | 719 | ||
714 | if (!hard_iface) | 720 | if (!hard_iface) |
@@ -723,6 +729,7 @@ static int batadv_hard_if_event(struct notifier_block *this, | |||
723 | batadv_hardif_deactivate_interface(hard_iface); | 729 | batadv_hardif_deactivate_interface(hard_iface); |
724 | break; | 730 | break; |
725 | case NETDEV_UNREGISTER: | 731 | case NETDEV_UNREGISTER: |
732 | case NETDEV_PRE_TYPE_CHANGE: | ||
726 | list_del_rcu(&hard_iface->list); | 733 | list_del_rcu(&hard_iface->list); |
727 | 734 | ||
728 | batadv_hardif_remove_interface(hard_iface); | 735 | batadv_hardif_remove_interface(hard_iface); |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index d7f17c1aa4a4..4b5d61fbadb1 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -552,7 +552,7 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops) | |||
552 | !bat_algo_ops->bat_ogm_schedule || | 552 | !bat_algo_ops->bat_ogm_schedule || |
553 | !bat_algo_ops->bat_ogm_emit || | 553 | !bat_algo_ops->bat_ogm_emit || |
554 | !bat_algo_ops->bat_neigh_cmp || | 554 | !bat_algo_ops->bat_neigh_cmp || |
555 | !bat_algo_ops->bat_neigh_is_equiv_or_better) { | 555 | !bat_algo_ops->bat_neigh_is_similar_or_better) { |
556 | pr_info("Routing algo '%s' does not implement required ops\n", | 556 | pr_info("Routing algo '%s' does not implement required ops\n", |
557 | bat_algo_ops->name); | 557 | bat_algo_ops->name); |
558 | return -EINVAL; | 558 | return -EINVAL; |
@@ -747,7 +747,7 @@ static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv) | |||
747 | static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv, | 747 | static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv, |
748 | struct batadv_tvlv_container *tvlv) | 748 | struct batadv_tvlv_container *tvlv) |
749 | { | 749 | { |
750 | lockdep_assert_held(&bat_priv->tvlv.handler_list_lock); | 750 | lockdep_assert_held(&bat_priv->tvlv.container_list_lock); |
751 | 751 | ||
752 | if (!tvlv) | 752 | if (!tvlv) |
753 | return; | 753 | return; |
@@ -908,7 +908,7 @@ end: | |||
908 | * appropriate handlers | 908 | * appropriate handlers |
909 | * @bat_priv: the bat priv with all the soft interface information | 909 | * @bat_priv: the bat priv with all the soft interface information |
910 | * @tvlv_handler: tvlv callback function handling the tvlv content | 910 | * @tvlv_handler: tvlv callback function handling the tvlv content |
911 | * @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet | 911 | * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet |
912 | * @orig_node: orig node emitting the ogm packet | 912 | * @orig_node: orig node emitting the ogm packet |
913 | * @src: source mac address of the unicast packet | 913 | * @src: source mac address of the unicast packet |
914 | * @dst: destination mac address of the unicast packet | 914 | * @dst: destination mac address of the unicast packet |
@@ -961,7 +961,7 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv, | |||
961 | * batadv_tvlv_containers_process - parse the given tvlv buffer to call the | 961 | * batadv_tvlv_containers_process - parse the given tvlv buffer to call the |
962 | * appropriate handlers | 962 | * appropriate handlers |
963 | * @bat_priv: the bat priv with all the soft interface information | 963 | * @bat_priv: the bat priv with all the soft interface information |
964 | * @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet | 964 | * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet |
965 | * @orig_node: orig node emitting the ogm packet | 965 | * @orig_node: orig node emitting the ogm packet |
966 | * @src: source mac address of the unicast packet | 966 | * @src: source mac address of the unicast packet |
967 | * @dst: destination mac address of the unicast packet | 967 | * @dst: destination mac address of the unicast packet |
@@ -1143,15 +1143,14 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src, | |||
1143 | struct batadv_unicast_tvlv_packet *unicast_tvlv_packet; | 1143 | struct batadv_unicast_tvlv_packet *unicast_tvlv_packet; |
1144 | struct batadv_tvlv_hdr *tvlv_hdr; | 1144 | struct batadv_tvlv_hdr *tvlv_hdr; |
1145 | struct batadv_orig_node *orig_node; | 1145 | struct batadv_orig_node *orig_node; |
1146 | struct sk_buff *skb = NULL; | 1146 | struct sk_buff *skb; |
1147 | unsigned char *tvlv_buff; | 1147 | unsigned char *tvlv_buff; |
1148 | unsigned int tvlv_len; | 1148 | unsigned int tvlv_len; |
1149 | ssize_t hdr_len = sizeof(*unicast_tvlv_packet); | 1149 | ssize_t hdr_len = sizeof(*unicast_tvlv_packet); |
1150 | bool ret = false; | ||
1151 | 1150 | ||
1152 | orig_node = batadv_orig_hash_find(bat_priv, dst); | 1151 | orig_node = batadv_orig_hash_find(bat_priv, dst); |
1153 | if (!orig_node) | 1152 | if (!orig_node) |
1154 | goto out; | 1153 | return; |
1155 | 1154 | ||
1156 | tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len; | 1155 | tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len; |
1157 | 1156 | ||
@@ -1180,14 +1179,10 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src, | |||
1180 | tvlv_buff += sizeof(*tvlv_hdr); | 1179 | tvlv_buff += sizeof(*tvlv_hdr); |
1181 | memcpy(tvlv_buff, tvlv_value, tvlv_value_len); | 1180 | memcpy(tvlv_buff, tvlv_value, tvlv_value_len); |
1182 | 1181 | ||
1183 | if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) | 1182 | if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP) |
1184 | ret = true; | ||
1185 | |||
1186 | out: | ||
1187 | if (skb && !ret) | ||
1188 | kfree_skb(skb); | 1183 | kfree_skb(skb); |
1189 | if (orig_node) | 1184 | out: |
1190 | batadv_orig_node_free_ref(orig_node); | 1185 | batadv_orig_node_free_ref(orig_node); |
1191 | } | 1186 | } |
1192 | 1187 | ||
1193 | /** | 1188 | /** |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index ebd8af0a1eb0..9dbd9107e7e1 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #define BATADV_DRIVER_DEVICE "batman-adv" | 24 | #define BATADV_DRIVER_DEVICE "batman-adv" |
25 | 25 | ||
26 | #ifndef BATADV_SOURCE_VERSION | 26 | #ifndef BATADV_SOURCE_VERSION |
27 | #define BATADV_SOURCE_VERSION "2015.2" | 27 | #define BATADV_SOURCE_VERSION "2016.0" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | /* B.A.T.M.A.N. parameters */ | 30 | /* B.A.T.M.A.N. parameters */ |
@@ -109,7 +109,7 @@ | |||
109 | #define BATADV_MAX_AGGREGATION_MS 100 | 109 | #define BATADV_MAX_AGGREGATION_MS 100 |
110 | 110 | ||
111 | #define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ | 111 | #define BATADV_BLA_PERIOD_LENGTH 10000 /* 10 seconds */ |
112 | #define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3) | 112 | #define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 6) |
113 | #define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) | 113 | #define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10) |
114 | #define BATADV_BLA_WAIT_PERIODS 3 | 114 | #define BATADV_BLA_WAIT_PERIODS 3 |
115 | 115 | ||
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index f5276be2c77c..c98b0ab85449 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
@@ -244,9 +244,7 @@ static void batadv_nc_path_free_ref(struct batadv_nc_path *nc_path) | |||
244 | */ | 244 | */ |
245 | static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet) | 245 | static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet) |
246 | { | 246 | { |
247 | if (nc_packet->skb) | 247 | kfree_skb(nc_packet->skb); |
248 | kfree_skb(nc_packet->skb); | ||
249 | |||
250 | batadv_nc_path_free_ref(nc_packet->nc_path); | 248 | batadv_nc_path_free_ref(nc_packet->nc_path); |
251 | kfree(nc_packet); | 249 | kfree(nc_packet); |
252 | } | 250 | } |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 7486df9ed48d..3c782a33bdac 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -202,6 +202,47 @@ void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) | |||
202 | } | 202 | } |
203 | 203 | ||
204 | /** | 204 | /** |
205 | * batadv_hardif_neigh_free_rcu - free the hardif neigh_node | ||
206 | * @rcu: rcu pointer of the neigh_node | ||
207 | */ | ||
208 | static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu) | ||
209 | { | ||
210 | struct batadv_hardif_neigh_node *hardif_neigh; | ||
211 | |||
212 | hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu); | ||
213 | |||
214 | spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); | ||
215 | hlist_del_init_rcu(&hardif_neigh->list); | ||
216 | spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); | ||
217 | |||
218 | batadv_hardif_free_ref_now(hardif_neigh->if_incoming); | ||
219 | kfree(hardif_neigh); | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * batadv_hardif_neigh_free_now - decrement the hardif neighbors refcounter | ||
224 | * and possibly free it (without rcu callback) | ||
225 | * @hardif_neigh: hardif neigh neighbor to free | ||
226 | */ | ||
227 | static void | ||
228 | batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) | ||
229 | { | ||
230 | if (atomic_dec_and_test(&hardif_neigh->refcount)) | ||
231 | batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu); | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * batadv_hardif_neigh_free_ref - decrement the hardif neighbors refcounter | ||
236 | * and possibly free it | ||
237 | * @hardif_neigh: hardif neigh neighbor to free | ||
238 | */ | ||
239 | void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) | ||
240 | { | ||
241 | if (atomic_dec_and_test(&hardif_neigh->refcount)) | ||
242 | call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu); | ||
243 | } | ||
244 | |||
245 | /** | ||
205 | * batadv_neigh_node_free_rcu - free the neigh_node | 246 | * batadv_neigh_node_free_rcu - free the neigh_node |
206 | * @rcu: rcu pointer of the neigh_node | 247 | * @rcu: rcu pointer of the neigh_node |
207 | */ | 248 | */ |
@@ -209,6 +250,7 @@ static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) | |||
209 | { | 250 | { |
210 | struct hlist_node *node_tmp; | 251 | struct hlist_node *node_tmp; |
211 | struct batadv_neigh_node *neigh_node; | 252 | struct batadv_neigh_node *neigh_node; |
253 | struct batadv_hardif_neigh_node *hardif_neigh; | ||
212 | struct batadv_neigh_ifinfo *neigh_ifinfo; | 254 | struct batadv_neigh_ifinfo *neigh_ifinfo; |
213 | struct batadv_algo_ops *bao; | 255 | struct batadv_algo_ops *bao; |
214 | 256 | ||
@@ -220,6 +262,14 @@ static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) | |||
220 | batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo); | 262 | batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo); |
221 | } | 263 | } |
222 | 264 | ||
265 | hardif_neigh = batadv_hardif_neigh_get(neigh_node->if_incoming, | ||
266 | neigh_node->addr); | ||
267 | if (hardif_neigh) { | ||
268 | /* batadv_hardif_neigh_get() increases refcount too */ | ||
269 | batadv_hardif_neigh_free_now(hardif_neigh); | ||
270 | batadv_hardif_neigh_free_now(hardif_neigh); | ||
271 | } | ||
272 | |||
223 | if (bao->bat_neigh_free) | 273 | if (bao->bat_neigh_free) |
224 | bao->bat_neigh_free(neigh_node); | 274 | bao->bat_neigh_free(neigh_node); |
225 | 275 | ||
@@ -479,6 +529,106 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node, | |||
479 | } | 529 | } |
480 | 530 | ||
481 | /** | 531 | /** |
532 | * batadv_hardif_neigh_create - create a hardif neighbour node | ||
533 | * @hard_iface: the interface this neighbour is connected to | ||
534 | * @neigh_addr: the interface address of the neighbour to retrieve | ||
535 | * | ||
536 | * Returns the hardif neighbour node if found or created or NULL otherwise. | ||
537 | */ | ||
538 | static struct batadv_hardif_neigh_node * | ||
539 | batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface, | ||
540 | const u8 *neigh_addr) | ||
541 | { | ||
542 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | ||
543 | struct batadv_hardif_neigh_node *hardif_neigh = NULL; | ||
544 | |||
545 | spin_lock_bh(&hard_iface->neigh_list_lock); | ||
546 | |||
547 | /* check if neighbor hasn't been added in the meantime */ | ||
548 | hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr); | ||
549 | if (hardif_neigh) | ||
550 | goto out; | ||
551 | |||
552 | if (!atomic_inc_not_zero(&hard_iface->refcount)) | ||
553 | goto out; | ||
554 | |||
555 | hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC); | ||
556 | if (!hardif_neigh) { | ||
557 | batadv_hardif_free_ref(hard_iface); | ||
558 | goto out; | ||
559 | } | ||
560 | |||
561 | INIT_HLIST_NODE(&hardif_neigh->list); | ||
562 | ether_addr_copy(hardif_neigh->addr, neigh_addr); | ||
563 | hardif_neigh->if_incoming = hard_iface; | ||
564 | hardif_neigh->last_seen = jiffies; | ||
565 | |||
566 | atomic_set(&hardif_neigh->refcount, 1); | ||
567 | |||
568 | if (bat_priv->bat_algo_ops->bat_hardif_neigh_init) | ||
569 | bat_priv->bat_algo_ops->bat_hardif_neigh_init(hardif_neigh); | ||
570 | |||
571 | hlist_add_head(&hardif_neigh->list, &hard_iface->neigh_list); | ||
572 | |||
573 | out: | ||
574 | spin_unlock_bh(&hard_iface->neigh_list_lock); | ||
575 | return hardif_neigh; | ||
576 | } | ||
577 | |||
578 | /** | ||
579 | * batadv_hardif_neigh_get_or_create - retrieve or create a hardif neighbour | ||
580 | * node | ||
581 | * @hard_iface: the interface this neighbour is connected to | ||
582 | * @neigh_addr: the interface address of the neighbour to retrieve | ||
583 | * | ||
584 | * Returns the hardif neighbour node if found or created or NULL otherwise. | ||
585 | */ | ||
586 | static struct batadv_hardif_neigh_node * | ||
587 | batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface, | ||
588 | const u8 *neigh_addr) | ||
589 | { | ||
590 | struct batadv_hardif_neigh_node *hardif_neigh = NULL; | ||
591 | |||
592 | /* first check without locking to avoid the overhead */ | ||
593 | hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr); | ||
594 | if (hardif_neigh) | ||
595 | return hardif_neigh; | ||
596 | |||
597 | return batadv_hardif_neigh_create(hard_iface, neigh_addr); | ||
598 | } | ||
599 | |||
600 | /** | ||
601 | * batadv_hardif_neigh_get - retrieve a hardif neighbour from the list | ||
602 | * @hard_iface: the interface where this neighbour is connected to | ||
603 | * @neigh_addr: the address of the neighbour | ||
604 | * | ||
605 | * Looks for and possibly returns a neighbour belonging to this hard interface. | ||
606 | * Returns NULL if the neighbour is not found. | ||
607 | */ | ||
608 | struct batadv_hardif_neigh_node * | ||
609 | batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, | ||
610 | const u8 *neigh_addr) | ||
611 | { | ||
612 | struct batadv_hardif_neigh_node *tmp_hardif_neigh, *hardif_neigh = NULL; | ||
613 | |||
614 | rcu_read_lock(); | ||
615 | hlist_for_each_entry_rcu(tmp_hardif_neigh, | ||
616 | &hard_iface->neigh_list, list) { | ||
617 | if (!batadv_compare_eth(tmp_hardif_neigh->addr, neigh_addr)) | ||
618 | continue; | ||
619 | |||
620 | if (!atomic_inc_not_zero(&tmp_hardif_neigh->refcount)) | ||
621 | continue; | ||
622 | |||
623 | hardif_neigh = tmp_hardif_neigh; | ||
624 | break; | ||
625 | } | ||
626 | rcu_read_unlock(); | ||
627 | |||
628 | return hardif_neigh; | ||
629 | } | ||
630 | |||
631 | /** | ||
482 | * batadv_neigh_node_new - create and init a new neigh_node object | 632 | * batadv_neigh_node_new - create and init a new neigh_node object |
483 | * @orig_node: originator object representing the neighbour | 633 | * @orig_node: originator object representing the neighbour |
484 | * @hard_iface: the interface where the neighbour is connected to | 634 | * @hard_iface: the interface where the neighbour is connected to |
@@ -493,11 +643,17 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node, | |||
493 | const u8 *neigh_addr) | 643 | const u8 *neigh_addr) |
494 | { | 644 | { |
495 | struct batadv_neigh_node *neigh_node; | 645 | struct batadv_neigh_node *neigh_node; |
646 | struct batadv_hardif_neigh_node *hardif_neigh = NULL; | ||
496 | 647 | ||
497 | neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); | 648 | neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); |
498 | if (neigh_node) | 649 | if (neigh_node) |
499 | goto out; | 650 | goto out; |
500 | 651 | ||
652 | hardif_neigh = batadv_hardif_neigh_get_or_create(hard_iface, | ||
653 | neigh_addr); | ||
654 | if (!hardif_neigh) | ||
655 | goto out; | ||
656 | |||
501 | neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC); | 657 | neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC); |
502 | if (!neigh_node) | 658 | if (!neigh_node) |
503 | goto out; | 659 | goto out; |
@@ -523,15 +679,54 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node, | |||
523 | hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); | 679 | hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); |
524 | spin_unlock_bh(&orig_node->neigh_list_lock); | 680 | spin_unlock_bh(&orig_node->neigh_list_lock); |
525 | 681 | ||
682 | /* increment unique neighbor refcount */ | ||
683 | atomic_inc(&hardif_neigh->refcount); | ||
684 | |||
526 | batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv, | 685 | batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv, |
527 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", | 686 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", |
528 | neigh_addr, orig_node->orig, hard_iface->net_dev->name); | 687 | neigh_addr, orig_node->orig, hard_iface->net_dev->name); |
529 | 688 | ||
530 | out: | 689 | out: |
690 | if (hardif_neigh) | ||
691 | batadv_hardif_neigh_free_ref(hardif_neigh); | ||
531 | return neigh_node; | 692 | return neigh_node; |
532 | } | 693 | } |
533 | 694 | ||
534 | /** | 695 | /** |
696 | * batadv_hardif_neigh_seq_print_text - print the single hop neighbour list | ||
697 | * @seq: neighbour table seq_file struct | ||
698 | * @offset: not used | ||
699 | * | ||
700 | * Always returns 0. | ||
701 | */ | ||
702 | int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset) | ||
703 | { | ||
704 | struct net_device *net_dev = (struct net_device *)seq->private; | ||
705 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | ||
706 | struct batadv_hard_iface *primary_if; | ||
707 | |||
708 | primary_if = batadv_seq_print_text_primary_if_get(seq); | ||
709 | if (!primary_if) | ||
710 | return 0; | ||
711 | |||
712 | seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s %s)]\n", | ||
713 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, | ||
714 | primary_if->net_dev->dev_addr, net_dev->name, | ||
715 | bat_priv->bat_algo_ops->name); | ||
716 | |||
717 | batadv_hardif_free_ref(primary_if); | ||
718 | |||
719 | if (!bat_priv->bat_algo_ops->bat_neigh_print) { | ||
720 | seq_puts(seq, | ||
721 | "No printing function for this routing protocol\n"); | ||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | bat_priv->bat_algo_ops->bat_neigh_print(bat_priv, seq); | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | /** | ||
535 | * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object | 730 | * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object |
536 | * @rcu: rcu pointer of the orig_ifinfo object | 731 | * @rcu: rcu pointer of the orig_ifinfo object |
537 | */ | 732 | */ |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index fa18f9bf266b..29557753d552 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
@@ -41,6 +41,11 @@ void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); | |||
41 | void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); | 41 | void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); |
42 | struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, | 42 | struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, |
43 | const u8 *addr); | 43 | const u8 *addr); |
44 | struct batadv_hardif_neigh_node * | ||
45 | batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, | ||
46 | const u8 *neigh_addr); | ||
47 | void | ||
48 | batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh); | ||
44 | struct batadv_neigh_node * | 49 | struct batadv_neigh_node * |
45 | batadv_neigh_node_new(struct batadv_orig_node *orig_node, | 50 | batadv_neigh_node_new(struct batadv_orig_node *orig_node, |
46 | struct batadv_hard_iface *hard_iface, | 51 | struct batadv_hard_iface *hard_iface, |
@@ -57,6 +62,8 @@ batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, | |||
57 | struct batadv_hard_iface *if_outgoing); | 62 | struct batadv_hard_iface *if_outgoing); |
58 | void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo); | 63 | void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo); |
59 | 64 | ||
65 | int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset); | ||
66 | |||
60 | struct batadv_orig_ifinfo * | 67 | struct batadv_orig_ifinfo * |
61 | batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, | 68 | batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, |
62 | struct batadv_hard_iface *if_outgoing); | 69 | struct batadv_hard_iface *if_outgoing); |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 11f996b39fef..0558e3237e0e 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -72,8 +72,7 @@ enum batadv_subtype { | |||
72 | * enum batadv_iv_flags - flags used in B.A.T.M.A.N. IV OGM packets | 72 | * enum batadv_iv_flags - flags used in B.A.T.M.A.N. IV OGM packets |
73 | * @BATADV_NOT_BEST_NEXT_HOP: flag is set when ogm packet is forwarded and was | 73 | * @BATADV_NOT_BEST_NEXT_HOP: flag is set when ogm packet is forwarded and was |
74 | * previously received from someone else than the best neighbor. | 74 | * previously received from someone else than the best neighbor. |
75 | * @BATADV_PRIMARIES_FIRST_HOP: flag is set when the primary interface address | 75 | * @BATADV_PRIMARIES_FIRST_HOP: flag unused. |
76 | * is used, and the packet travels its first hop. | ||
77 | * @BATADV_DIRECTLINK: flag is for the first hop or if rebroadcasted from a | 76 | * @BATADV_DIRECTLINK: flag is for the first hop or if rebroadcasted from a |
78 | * one hop neighbor on the interface where it was originally received. | 77 | * one hop neighbor on the interface where it was originally received. |
79 | */ | 78 | */ |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 8d990b070a2e..e4f2646d9246 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -497,9 +497,9 @@ batadv_find_router(struct batadv_priv *bat_priv, | |||
497 | /* alternative candidate should be good enough to be | 497 | /* alternative candidate should be good enough to be |
498 | * considered | 498 | * considered |
499 | */ | 499 | */ |
500 | if (!bao->bat_neigh_is_equiv_or_better(cand_router, | 500 | if (!bao->bat_neigh_is_similar_or_better(cand_router, |
501 | cand->if_outgoing, | 501 | cand->if_outgoing, |
502 | router, recv_if)) | 502 | router, recv_if)) |
503 | goto next; | 503 | goto next; |
504 | 504 | ||
505 | /* don't use the same router twice */ | 505 | /* don't use the same router twice */ |
@@ -836,6 +836,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
836 | u8 *orig_addr; | 836 | u8 *orig_addr; |
837 | struct batadv_orig_node *orig_node = NULL; | 837 | struct batadv_orig_node *orig_node = NULL; |
838 | int check, hdr_size = sizeof(*unicast_packet); | 838 | int check, hdr_size = sizeof(*unicast_packet); |
839 | enum batadv_subtype subtype; | ||
839 | bool is4addr; | 840 | bool is4addr; |
840 | 841 | ||
841 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 842 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
@@ -863,10 +864,20 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
863 | /* packet for me */ | 864 | /* packet for me */ |
864 | if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) { | 865 | if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) { |
865 | if (is4addr) { | 866 | if (is4addr) { |
866 | batadv_dat_inc_counter(bat_priv, | 867 | subtype = unicast_4addr_packet->subtype; |
867 | unicast_4addr_packet->subtype); | 868 | batadv_dat_inc_counter(bat_priv, subtype); |
868 | orig_addr = unicast_4addr_packet->src; | 869 | |
869 | orig_node = batadv_orig_hash_find(bat_priv, orig_addr); | 870 | /* Only payload data should be considered for speedy |
871 | * join. For example, DAT also uses unicast 4addr | ||
872 | * types, but those packets should not be considered | ||
873 | * for speedy join, since the clients do not actually | ||
874 | * reside at the sending originator. | ||
875 | */ | ||
876 | if (subtype == BATADV_P_DATA) { | ||
877 | orig_addr = unicast_4addr_packet->src; | ||
878 | orig_node = batadv_orig_hash_find(bat_priv, | ||
879 | orig_addr); | ||
880 | } | ||
870 | } | 881 | } |
871 | 882 | ||
872 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, | 883 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index f664324805eb..782fa33ec296 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -407,8 +407,7 @@ void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface) | |||
407 | 407 | ||
408 | static void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet) | 408 | static void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet) |
409 | { | 409 | { |
410 | if (forw_packet->skb) | 410 | kfree_skb(forw_packet->skb); |
411 | kfree_skb(forw_packet->skb); | ||
412 | if (forw_packet->if_incoming) | 411 | if (forw_packet->if_incoming) |
413 | batadv_hardif_free_ref(forw_packet->if_incoming); | 412 | batadv_hardif_free_ref(forw_packet->if_incoming); |
414 | if (forw_packet->if_outgoing) | 413 | if (forw_packet->if_outgoing) |
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 9de3c8804ff4..fe87777fda8a 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "distributed-arp-table.h" | 40 | #include "distributed-arp-table.h" |
41 | #include "gateway_client.h" | 41 | #include "gateway_client.h" |
42 | #include "gateway_common.h" | 42 | #include "gateway_common.h" |
43 | #include "bridge_loop_avoidance.h" | ||
43 | #include "hard-interface.h" | 44 | #include "hard-interface.h" |
44 | #include "network-coding.h" | 45 | #include "network-coding.h" |
45 | #include "packet.h" | 46 | #include "packet.h" |
@@ -241,10 +242,13 @@ ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \ | |||
241 | 242 | ||
242 | static int batadv_store_bool_attr(char *buff, size_t count, | 243 | static int batadv_store_bool_attr(char *buff, size_t count, |
243 | struct net_device *net_dev, | 244 | struct net_device *net_dev, |
244 | const char *attr_name, atomic_t *attr) | 245 | const char *attr_name, atomic_t *attr, |
246 | bool *changed) | ||
245 | { | 247 | { |
246 | int enabled = -1; | 248 | int enabled = -1; |
247 | 249 | ||
250 | *changed = false; | ||
251 | |||
248 | if (buff[count - 1] == '\n') | 252 | if (buff[count - 1] == '\n') |
249 | buff[count - 1] = '\0'; | 253 | buff[count - 1] = '\0'; |
250 | 254 | ||
@@ -271,6 +275,8 @@ static int batadv_store_bool_attr(char *buff, size_t count, | |||
271 | atomic_read(attr) == 1 ? "enabled" : "disabled", | 275 | atomic_read(attr) == 1 ? "enabled" : "disabled", |
272 | enabled == 1 ? "enabled" : "disabled"); | 276 | enabled == 1 ? "enabled" : "disabled"); |
273 | 277 | ||
278 | *changed = true; | ||
279 | |||
274 | atomic_set(attr, (unsigned int)enabled); | 280 | atomic_set(attr, (unsigned int)enabled); |
275 | return count; | 281 | return count; |
276 | } | 282 | } |
@@ -281,11 +287,12 @@ __batadv_store_bool_attr(char *buff, size_t count, | |||
281 | struct attribute *attr, | 287 | struct attribute *attr, |
282 | atomic_t *attr_store, struct net_device *net_dev) | 288 | atomic_t *attr_store, struct net_device *net_dev) |
283 | { | 289 | { |
290 | bool changed; | ||
284 | int ret; | 291 | int ret; |
285 | 292 | ||
286 | ret = batadv_store_bool_attr(buff, count, net_dev, attr->name, | 293 | ret = batadv_store_bool_attr(buff, count, net_dev, attr->name, |
287 | attr_store); | 294 | attr_store, &changed); |
288 | if (post_func && ret) | 295 | if (post_func && changed) |
289 | post_func(net_dev); | 296 | post_func(net_dev); |
290 | 297 | ||
291 | return ret; | 298 | return ret; |
@@ -549,7 +556,8 @@ static ssize_t batadv_store_isolation_mark(struct kobject *kobj, | |||
549 | BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); | 556 | BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); |
550 | BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); | 557 | BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); |
551 | #ifdef CONFIG_BATMAN_ADV_BLA | 558 | #ifdef CONFIG_BATMAN_ADV_BLA |
552 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); | 559 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, |
560 | batadv_bla_status_update); | ||
553 | #endif | 561 | #endif |
554 | #ifdef CONFIG_BATMAN_ADV_DAT | 562 | #ifdef CONFIG_BATMAN_ADV_DAT |
555 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, | 563 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 4228b10c47ea..a22080c53401 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -68,13 +68,15 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, | |||
68 | unsigned short vid, const char *message, | 68 | unsigned short vid, const char *message, |
69 | bool roaming); | 69 | bool roaming); |
70 | 70 | ||
71 | /* returns 1 if they are the same mac addr */ | 71 | /* returns 1 if they are the same mac addr and vid */ |
72 | static int batadv_compare_tt(const struct hlist_node *node, const void *data2) | 72 | static int batadv_compare_tt(const struct hlist_node *node, const void *data2) |
73 | { | 73 | { |
74 | const void *data1 = container_of(node, struct batadv_tt_common_entry, | 74 | const void *data1 = container_of(node, struct batadv_tt_common_entry, |
75 | hash_entry); | 75 | hash_entry); |
76 | const struct batadv_tt_common_entry *tt1 = data1; | ||
77 | const struct batadv_tt_common_entry *tt2 = data2; | ||
76 | 78 | ||
77 | return batadv_compare_eth(data1, data2); | 79 | return (tt1->vid == tt2->vid) && batadv_compare_eth(data1, data2); |
78 | } | 80 | } |
79 | 81 | ||
80 | /** | 82 | /** |
@@ -1427,15 +1429,21 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
1427 | } | 1429 | } |
1428 | 1430 | ||
1429 | /* if the client was temporary added before receiving the first | 1431 | /* if the client was temporary added before receiving the first |
1430 | * OGM announcing it, we have to clear the TEMP flag | 1432 | * OGM announcing it, we have to clear the TEMP flag. Also, |
1433 | * remove the previous temporary orig node and re-add it | ||
1434 | * if required. If the orig entry changed, the new one which | ||
1435 | * is a non-temporary entry is preferred. | ||
1431 | */ | 1436 | */ |
1432 | common->flags &= ~BATADV_TT_CLIENT_TEMP; | 1437 | if (common->flags & BATADV_TT_CLIENT_TEMP) { |
1438 | batadv_tt_global_del_orig_list(tt_global_entry); | ||
1439 | common->flags &= ~BATADV_TT_CLIENT_TEMP; | ||
1440 | } | ||
1433 | 1441 | ||
1434 | /* the change can carry possible "attribute" flags like the | 1442 | /* the change can carry possible "attribute" flags like the |
1435 | * TT_CLIENT_WIFI, therefore they have to be copied in the | 1443 | * TT_CLIENT_WIFI, therefore they have to be copied in the |
1436 | * client entry | 1444 | * client entry |
1437 | */ | 1445 | */ |
1438 | tt_global_entry->common.flags |= flags; | 1446 | common->flags |= flags; |
1439 | 1447 | ||
1440 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only | 1448 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only |
1441 | * one originator left in the list and we previously received a | 1449 | * one originator left in the list and we previously received a |
@@ -2411,8 +2419,8 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, | |||
2411 | { | 2419 | { |
2412 | struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp; | 2420 | struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp; |
2413 | struct batadv_orig_node_vlan *vlan; | 2421 | struct batadv_orig_node_vlan *vlan; |
2422 | int i, orig_num_vlan; | ||
2414 | u32 crc; | 2423 | u32 crc; |
2415 | int i; | ||
2416 | 2424 | ||
2417 | /* check if each received CRC matches the locally stored one */ | 2425 | /* check if each received CRC matches the locally stored one */ |
2418 | for (i = 0; i < num_vlan; i++) { | 2426 | for (i = 0; i < num_vlan; i++) { |
@@ -2438,6 +2446,18 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, | |||
2438 | return false; | 2446 | return false; |
2439 | } | 2447 | } |
2440 | 2448 | ||
2449 | /* check if any excess VLANs exist locally for the originator | ||
2450 | * which are not mentioned in the TVLV from the originator. | ||
2451 | */ | ||
2452 | rcu_read_lock(); | ||
2453 | orig_num_vlan = 0; | ||
2454 | hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) | ||
2455 | orig_num_vlan++; | ||
2456 | rcu_read_unlock(); | ||
2457 | |||
2458 | if (orig_num_vlan > num_vlan) | ||
2459 | return false; | ||
2460 | |||
2441 | return true; | 2461 | return true; |
2442 | } | 2462 | } |
2443 | 2463 | ||
@@ -3319,7 +3339,10 @@ bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst, | |||
3319 | bool ret = false; | 3339 | bool ret = false; |
3320 | 3340 | ||
3321 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 3341 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
3322 | if (!vlan || !atomic_read(&vlan->ap_isolation)) | 3342 | if (!vlan) |
3343 | return false; | ||
3344 | |||
3345 | if (!atomic_read(&vlan->ap_isolation)) | ||
3323 | goto out; | 3346 | goto out; |
3324 | 3347 | ||
3325 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid); | 3348 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid); |
@@ -3336,8 +3359,7 @@ bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst, | |||
3336 | ret = true; | 3359 | ret = true; |
3337 | 3360 | ||
3338 | out: | 3361 | out: |
3339 | if (vlan) | 3362 | batadv_softif_vlan_free_ref(vlan); |
3340 | batadv_softif_vlan_free_ref(vlan); | ||
3341 | if (tt_global_entry) | 3363 | if (tt_global_entry) |
3342 | batadv_tt_global_entry_free_ref(tt_global_entry); | 3364 | batadv_tt_global_entry_free_ref(tt_global_entry); |
3343 | if (tt_local_entry) | 3365 | if (tt_local_entry) |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index d260efd70499..3437b667a2cd 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -100,6 +100,8 @@ struct batadv_hard_iface_bat_iv { | |||
100 | * @bat_iv: BATMAN IV specific per hard interface data | 100 | * @bat_iv: BATMAN IV specific per hard interface data |
101 | * @cleanup_work: work queue callback item for hard interface deinit | 101 | * @cleanup_work: work queue callback item for hard interface deinit |
102 | * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs | 102 | * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs |
103 | * @neigh_list: list of unique single hop neighbors via this interface | ||
104 | * @neigh_list_lock: lock protecting neigh_list | ||
103 | */ | 105 | */ |
104 | struct batadv_hard_iface { | 106 | struct batadv_hard_iface { |
105 | struct list_head list; | 107 | struct list_head list; |
@@ -115,6 +117,9 @@ struct batadv_hard_iface { | |||
115 | struct batadv_hard_iface_bat_iv bat_iv; | 117 | struct batadv_hard_iface_bat_iv bat_iv; |
116 | struct work_struct cleanup_work; | 118 | struct work_struct cleanup_work; |
117 | struct dentry *debug_dir; | 119 | struct dentry *debug_dir; |
120 | struct hlist_head neigh_list; | ||
121 | /* neigh_list_lock protects: neigh_list */ | ||
122 | spinlock_t neigh_list_lock; | ||
118 | }; | 123 | }; |
119 | 124 | ||
120 | /** | 125 | /** |
@@ -218,12 +223,12 @@ struct batadv_orig_bat_iv { | |||
218 | * @orig: originator ethernet address | 223 | * @orig: originator ethernet address |
219 | * @ifinfo_list: list for routers per outgoing interface | 224 | * @ifinfo_list: list for routers per outgoing interface |
220 | * @last_bonding_candidate: pointer to last ifinfo of last used router | 225 | * @last_bonding_candidate: pointer to last ifinfo of last used router |
221 | * @batadv_dat_addr_t: address of the orig node in the distributed hash | 226 | * @dat_addr: address of the orig node in the distributed hash |
222 | * @last_seen: time when last packet from this node was received | 227 | * @last_seen: time when last packet from this node was received |
223 | * @bcast_seqno_reset: time when the broadcast seqno window was reset | 228 | * @bcast_seqno_reset: time when the broadcast seqno window was reset |
224 | * @mcast_handler_lock: synchronizes mcast-capability and -flag changes | 229 | * @mcast_handler_lock: synchronizes mcast-capability and -flag changes |
225 | * @mcast_flags: multicast flags announced by the orig node | 230 | * @mcast_flags: multicast flags announced by the orig node |
226 | * @mcast_want_all_unsnoop_node: a list node for the | 231 | * @mcast_want_all_unsnoopables_node: a list node for the |
227 | * mcast.want_all_unsnoopables list | 232 | * mcast.want_all_unsnoopables list |
228 | * @mcast_want_all_ipv4_node: a list node for the mcast.want_all_ipv4 list | 233 | * @mcast_want_all_ipv4_node: a list node for the mcast.want_all_ipv4 list |
229 | * @mcast_want_all_ipv6_node: a list node for the mcast.want_all_ipv6 list | 234 | * @mcast_want_all_ipv6_node: a list node for the mcast.want_all_ipv6 list |
@@ -341,6 +346,23 @@ struct batadv_gw_node { | |||
341 | }; | 346 | }; |
342 | 347 | ||
343 | /** | 348 | /** |
349 | * batadv_hardif_neigh_node - unique neighbor per hard interface | ||
350 | * @list: list node for batadv_hard_iface::neigh_list | ||
351 | * @addr: the MAC address of the neighboring interface | ||
352 | * @if_incoming: pointer to incoming hard interface | ||
353 | * @refcount: number of contexts the object is used | ||
354 | * @rcu: struct used for freeing in a RCU-safe manner | ||
355 | */ | ||
356 | struct batadv_hardif_neigh_node { | ||
357 | struct hlist_node list; | ||
358 | u8 addr[ETH_ALEN]; | ||
359 | struct batadv_hard_iface *if_incoming; | ||
360 | unsigned long last_seen; | ||
361 | atomic_t refcount; | ||
362 | struct rcu_head rcu; | ||
363 | }; | ||
364 | |||
365 | /** | ||
344 | * struct batadv_neigh_node - structure for single hops neighbors | 366 | * struct batadv_neigh_node - structure for single hops neighbors |
345 | * @list: list node for batadv_orig_node::neigh_list | 367 | * @list: list node for batadv_orig_node::neigh_list |
346 | * @orig_node: pointer to corresponding orig_node | 368 | * @orig_node: pointer to corresponding orig_node |
@@ -349,9 +371,8 @@ struct batadv_gw_node { | |||
349 | * @ifinfo_lock: lock protecting private ifinfo members and list | 371 | * @ifinfo_lock: lock protecting private ifinfo members and list |
350 | * @if_incoming: pointer to incoming hard interface | 372 | * @if_incoming: pointer to incoming hard interface |
351 | * @last_seen: when last packet via this neighbor was received | 373 | * @last_seen: when last packet via this neighbor was received |
352 | * @last_ttl: last received ttl from this neigh node | 374 | * @refcount: number of contexts the object is used |
353 | * @rcu: struct used for freeing in an RCU-safe manner | 375 | * @rcu: struct used for freeing in an RCU-safe manner |
354 | * @bat_iv: B.A.T.M.A.N. IV private structure | ||
355 | */ | 376 | */ |
356 | struct batadv_neigh_node { | 377 | struct batadv_neigh_node { |
357 | struct hlist_node list; | 378 | struct hlist_node list; |
@@ -401,13 +422,14 @@ struct batadv_neigh_ifinfo { | |||
401 | struct rcu_head rcu; | 422 | struct rcu_head rcu; |
402 | }; | 423 | }; |
403 | 424 | ||
425 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
426 | |||
404 | /** | 427 | /** |
405 | * struct batadv_bcast_duplist_entry - structure for LAN broadcast suppression | 428 | * struct batadv_bcast_duplist_entry - structure for LAN broadcast suppression |
406 | * @orig[ETH_ALEN]: mac address of orig node orginating the broadcast | 429 | * @orig: mac address of orig node orginating the broadcast |
407 | * @crc: crc32 checksum of broadcast payload | 430 | * @crc: crc32 checksum of broadcast payload |
408 | * @entrytime: time when the broadcast packet was received | 431 | * @entrytime: time when the broadcast packet was received |
409 | */ | 432 | */ |
410 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
411 | struct batadv_bcast_duplist_entry { | 433 | struct batadv_bcast_duplist_entry { |
412 | u8 orig[ETH_ALEN]; | 434 | u8 orig[ETH_ALEN]; |
413 | __be32 crc; | 435 | __be32 crc; |
@@ -549,9 +571,11 @@ struct batadv_priv_tt { | |||
549 | struct delayed_work work; | 571 | struct delayed_work work; |
550 | }; | 572 | }; |
551 | 573 | ||
574 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
575 | |||
552 | /** | 576 | /** |
553 | * struct batadv_priv_bla - per mesh interface bridge loope avoidance data | 577 | * struct batadv_priv_bla - per mesh interface bridge loope avoidance data |
554 | * @num_requests; number of bla requests in flight | 578 | * @num_requests: number of bla requests in flight |
555 | * @claim_hash: hash table containing mesh nodes this host has claimed | 579 | * @claim_hash: hash table containing mesh nodes this host has claimed |
556 | * @backbone_hash: hash table containing all detected backbone gateways | 580 | * @backbone_hash: hash table containing all detected backbone gateways |
557 | * @bcast_duplist: recently received broadcast packets array (for broadcast | 581 | * @bcast_duplist: recently received broadcast packets array (for broadcast |
@@ -561,7 +585,6 @@ struct batadv_priv_tt { | |||
561 | * @claim_dest: local claim data (e.g. claim group) | 585 | * @claim_dest: local claim data (e.g. claim group) |
562 | * @work: work queue callback item for cleanups & bla announcements | 586 | * @work: work queue callback item for cleanups & bla announcements |
563 | */ | 587 | */ |
564 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
565 | struct batadv_priv_bla { | 588 | struct batadv_priv_bla { |
566 | atomic_t num_requests; | 589 | atomic_t num_requests; |
567 | struct batadv_hashtable *claim_hash; | 590 | struct batadv_hashtable *claim_hash; |
@@ -575,6 +598,8 @@ struct batadv_priv_bla { | |||
575 | }; | 598 | }; |
576 | #endif | 599 | #endif |
577 | 600 | ||
601 | #ifdef CONFIG_BATMAN_ADV_DEBUG | ||
602 | |||
578 | /** | 603 | /** |
579 | * struct batadv_priv_debug_log - debug logging data | 604 | * struct batadv_priv_debug_log - debug logging data |
580 | * @log_buff: buffer holding the logs (ring bufer) | 605 | * @log_buff: buffer holding the logs (ring bufer) |
@@ -583,7 +608,6 @@ struct batadv_priv_bla { | |||
583 | * @lock: lock protecting log_buff, log_start & log_end | 608 | * @lock: lock protecting log_buff, log_start & log_end |
584 | * @queue_wait: log reader's wait queue | 609 | * @queue_wait: log reader's wait queue |
585 | */ | 610 | */ |
586 | #ifdef CONFIG_BATMAN_ADV_DEBUG | ||
587 | struct batadv_priv_debug_log { | 611 | struct batadv_priv_debug_log { |
588 | char log_buff[BATADV_LOG_BUF_LEN]; | 612 | char log_buff[BATADV_LOG_BUF_LEN]; |
589 | unsigned long log_start; | 613 | unsigned long log_start; |
@@ -625,13 +649,14 @@ struct batadv_priv_tvlv { | |||
625 | spinlock_t handler_list_lock; /* protects handler_list */ | 649 | spinlock_t handler_list_lock; /* protects handler_list */ |
626 | }; | 650 | }; |
627 | 651 | ||
652 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
653 | |||
628 | /** | 654 | /** |
629 | * struct batadv_priv_dat - per mesh interface DAT private data | 655 | * struct batadv_priv_dat - per mesh interface DAT private data |
630 | * @addr: node DAT address | 656 | * @addr: node DAT address |
631 | * @hash: hashtable representing the local ARP cache | 657 | * @hash: hashtable representing the local ARP cache |
632 | * @work: work queue callback item for cache purging | 658 | * @work: work queue callback item for cache purging |
633 | */ | 659 | */ |
634 | #ifdef CONFIG_BATMAN_ADV_DAT | ||
635 | struct batadv_priv_dat { | 660 | struct batadv_priv_dat { |
636 | batadv_dat_addr_t addr; | 661 | batadv_dat_addr_t addr; |
637 | struct batadv_hashtable *hash; | 662 | struct batadv_hashtable *hash; |
@@ -773,7 +798,7 @@ struct batadv_softif_vlan { | |||
773 | * @dat: distributed arp table data | 798 | * @dat: distributed arp table data |
774 | * @mcast: multicast data | 799 | * @mcast: multicast data |
775 | * @network_coding: bool indicating whether network coding is enabled | 800 | * @network_coding: bool indicating whether network coding is enabled |
776 | * @batadv_priv_nc: network coding data | 801 | * @nc: network coding data |
777 | */ | 802 | */ |
778 | struct batadv_priv { | 803 | struct batadv_priv { |
779 | atomic_t mesh_state; | 804 | atomic_t mesh_state; |
@@ -871,6 +896,8 @@ struct batadv_socket_packet { | |||
871 | u8 icmp_packet[BATADV_ICMP_MAX_PACKET_SIZE]; | 896 | u8 icmp_packet[BATADV_ICMP_MAX_PACKET_SIZE]; |
872 | }; | 897 | }; |
873 | 898 | ||
899 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
900 | |||
874 | /** | 901 | /** |
875 | * struct batadv_bla_backbone_gw - batman-adv gateway bridged into the LAN | 902 | * struct batadv_bla_backbone_gw - batman-adv gateway bridged into the LAN |
876 | * @orig: originator address of backbone node (mac address of primary iface) | 903 | * @orig: originator address of backbone node (mac address of primary iface) |
@@ -884,10 +911,10 @@ struct batadv_socket_packet { | |||
884 | * backbone gateway - no bcast traffic is formwared until the situation was | 911 | * backbone gateway - no bcast traffic is formwared until the situation was |
885 | * resolved | 912 | * resolved |
886 | * @crc: crc16 checksum over all claims | 913 | * @crc: crc16 checksum over all claims |
914 | * @crc_lock: lock protecting crc | ||
887 | * @refcount: number of contexts the object is used | 915 | * @refcount: number of contexts the object is used |
888 | * @rcu: struct used for freeing in an RCU-safe manner | 916 | * @rcu: struct used for freeing in an RCU-safe manner |
889 | */ | 917 | */ |
890 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
891 | struct batadv_bla_backbone_gw { | 918 | struct batadv_bla_backbone_gw { |
892 | u8 orig[ETH_ALEN]; | 919 | u8 orig[ETH_ALEN]; |
893 | unsigned short vid; | 920 | unsigned short vid; |
@@ -897,6 +924,7 @@ struct batadv_bla_backbone_gw { | |||
897 | atomic_t wait_periods; | 924 | atomic_t wait_periods; |
898 | atomic_t request_sent; | 925 | atomic_t request_sent; |
899 | u16 crc; | 926 | u16 crc; |
927 | spinlock_t crc_lock; /* protects crc */ | ||
900 | atomic_t refcount; | 928 | atomic_t refcount; |
901 | struct rcu_head rcu; | 929 | struct rcu_head rcu; |
902 | }; | 930 | }; |
@@ -905,7 +933,7 @@ struct batadv_bla_backbone_gw { | |||
905 | * struct batadv_bla_claim - claimed non-mesh client structure | 933 | * struct batadv_bla_claim - claimed non-mesh client structure |
906 | * @addr: mac address of claimed non-mesh client | 934 | * @addr: mac address of claimed non-mesh client |
907 | * @vid: vlan id this client was detected on | 935 | * @vid: vlan id this client was detected on |
908 | * @batadv_bla_backbone_gw: pointer to backbone gw claiming this client | 936 | * @backbone_gw: pointer to backbone gw claiming this client |
909 | * @lasttime: last time we heard of claim (locals only) | 937 | * @lasttime: last time we heard of claim (locals only) |
910 | * @hash_entry: hlist node for batadv_priv_bla::claim_hash | 938 | * @hash_entry: hlist node for batadv_priv_bla::claim_hash |
911 | * @refcount: number of contexts the object is used | 939 | * @refcount: number of contexts the object is used |
@@ -1131,11 +1159,13 @@ struct batadv_forw_packet { | |||
1131 | * @bat_primary_iface_set: called when primary interface is selected / changed | 1159 | * @bat_primary_iface_set: called when primary interface is selected / changed |
1132 | * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue | 1160 | * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue |
1133 | * @bat_ogm_emit: send scheduled OGM | 1161 | * @bat_ogm_emit: send scheduled OGM |
1162 | * @bat_hardif_neigh_init: called on creation of single hop entry | ||
1134 | * @bat_neigh_cmp: compare the metrics of two neighbors for their respective | 1163 | * @bat_neigh_cmp: compare the metrics of two neighbors for their respective |
1135 | * outgoing interfaces | 1164 | * outgoing interfaces |
1136 | * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or better | 1165 | * @bat_neigh_is_similar_or_better: check if neigh1 is equally similar or |
1137 | * than neigh2 for their respective outgoing interface from the metric | 1166 | * better than neigh2 for their respective outgoing interface from the metric |
1138 | * prospective | 1167 | * prospective |
1168 | * @bat_neigh_print: print the single hop neighbor list (optional) | ||
1139 | * @bat_neigh_free: free the resources allocated by the routing algorithm for a | 1169 | * @bat_neigh_free: free the resources allocated by the routing algorithm for a |
1140 | * neigh_node object | 1170 | * neigh_node object |
1141 | * @bat_orig_print: print the originator table (optional) | 1171 | * @bat_orig_print: print the originator table (optional) |
@@ -1156,15 +1186,17 @@ struct batadv_algo_ops { | |||
1156 | void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface); | 1186 | void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface); |
1157 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); | 1187 | void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); |
1158 | /* neigh_node handling API */ | 1188 | /* neigh_node handling API */ |
1189 | void (*bat_hardif_neigh_init)(struct batadv_hardif_neigh_node *neigh); | ||
1159 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, | 1190 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, |
1160 | struct batadv_hard_iface *if_outgoing1, | 1191 | struct batadv_hard_iface *if_outgoing1, |
1161 | struct batadv_neigh_node *neigh2, | 1192 | struct batadv_neigh_node *neigh2, |
1162 | struct batadv_hard_iface *if_outgoing2); | 1193 | struct batadv_hard_iface *if_outgoing2); |
1163 | bool (*bat_neigh_is_equiv_or_better) | 1194 | bool (*bat_neigh_is_similar_or_better) |
1164 | (struct batadv_neigh_node *neigh1, | 1195 | (struct batadv_neigh_node *neigh1, |
1165 | struct batadv_hard_iface *if_outgoing1, | 1196 | struct batadv_hard_iface *if_outgoing1, |
1166 | struct batadv_neigh_node *neigh2, | 1197 | struct batadv_neigh_node *neigh2, |
1167 | struct batadv_hard_iface *if_outgoing2); | 1198 | struct batadv_hard_iface *if_outgoing2); |
1199 | void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq); | ||
1168 | void (*bat_neigh_free)(struct batadv_neigh_node *neigh); | 1200 | void (*bat_neigh_free)(struct batadv_neigh_node *neigh); |
1169 | /* orig_node handling API */ | 1201 | /* orig_node handling API */ |
1170 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, | 1202 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, |
@@ -1224,8 +1256,6 @@ struct batadv_dat_candidate { | |||
1224 | * struct batadv_tvlv_container - container for tvlv appended to OGMs | 1256 | * struct batadv_tvlv_container - container for tvlv appended to OGMs |
1225 | * @list: hlist node for batadv_priv_tvlv::container_list | 1257 | * @list: hlist node for batadv_priv_tvlv::container_list |
1226 | * @tvlv_hdr: tvlv header information needed to construct the tvlv | 1258 | * @tvlv_hdr: tvlv header information needed to construct the tvlv |
1227 | * @value_len: length of the buffer following this struct which contains | ||
1228 | * the actual tvlv payload | ||
1229 | * @refcount: number of contexts the object is used | 1259 | * @refcount: number of contexts the object is used |
1230 | */ | 1260 | */ |
1231 | struct batadv_tvlv_container { | 1261 | struct batadv_tvlv_container { |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 9e9cca3689a0..d040365ba98e 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
@@ -825,9 +825,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev) | |||
825 | list_add_rcu(&(*dev)->list, &bt_6lowpan_devices); | 825 | list_add_rcu(&(*dev)->list, &bt_6lowpan_devices); |
826 | spin_unlock(&devices_lock); | 826 | spin_unlock(&devices_lock); |
827 | 827 | ||
828 | lowpan_netdev_setup(netdev, LOWPAN_LLTYPE_BTLE); | 828 | err = lowpan_register_netdev(netdev, LOWPAN_LLTYPE_BTLE); |
829 | |||
830 | err = register_netdev(netdev); | ||
831 | if (err < 0) { | 829 | if (err < 0) { |
832 | BT_INFO("register_netdev failed %d", err); | 830 | BT_INFO("register_netdev failed %d", err); |
833 | spin_lock(&devices_lock); | 831 | spin_lock(&devices_lock); |
@@ -890,7 +888,7 @@ static void delete_netdev(struct work_struct *work) | |||
890 | struct lowpan_dev *entry = container_of(work, struct lowpan_dev, | 888 | struct lowpan_dev *entry = container_of(work, struct lowpan_dev, |
891 | delete_netdev); | 889 | delete_netdev); |
892 | 890 | ||
893 | unregister_netdev(entry->netdev); | 891 | lowpan_unregister_netdev(entry->netdev); |
894 | 892 | ||
895 | /* The entry pointer is deleted by the netdev destructor. */ | 893 | /* The entry pointer is deleted by the netdev destructor. */ |
896 | } | 894 | } |
@@ -1348,7 +1346,7 @@ static void disconnect_devices(void) | |||
1348 | ifdown(entry->netdev); | 1346 | ifdown(entry->netdev); |
1349 | BT_DBG("Unregistering netdev %s %p", | 1347 | BT_DBG("Unregistering netdev %s %p", |
1350 | entry->netdev->name, entry->netdev); | 1348 | entry->netdev->name, entry->netdev); |
1351 | unregister_netdev(entry->netdev); | 1349 | lowpan_unregister_netdev(entry->netdev); |
1352 | kfree(entry); | 1350 | kfree(entry); |
1353 | } | 1351 | } |
1354 | } | 1352 | } |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index a3bffd1ec2b4..955eda93e66f 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -33,8 +33,6 @@ | |||
33 | 33 | ||
34 | #include "selftest.h" | 34 | #include "selftest.h" |
35 | 35 | ||
36 | #define VERSION "2.21" | ||
37 | |||
38 | /* Bluetooth sockets */ | 36 | /* Bluetooth sockets */ |
39 | #define BT_MAX_PROTO 8 | 37 | #define BT_MAX_PROTO 8 |
40 | static const struct net_proto_family *bt_proto[BT_MAX_PROTO]; | 38 | static const struct net_proto_family *bt_proto[BT_MAX_PROTO]; |
@@ -176,20 +174,20 @@ EXPORT_SYMBOL(bt_accept_unlink); | |||
176 | 174 | ||
177 | struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) | 175 | struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) |
178 | { | 176 | { |
179 | struct list_head *p, *n; | 177 | struct bt_sock *s, *n; |
180 | struct sock *sk; | 178 | struct sock *sk; |
181 | 179 | ||
182 | BT_DBG("parent %p", parent); | 180 | BT_DBG("parent %p", parent); |
183 | 181 | ||
184 | list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { | 182 | list_for_each_entry_safe(s, n, &bt_sk(parent)->accept_q, accept_q) { |
185 | sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); | 183 | sk = (struct sock *)s; |
186 | 184 | ||
187 | lock_sock(sk); | 185 | lock_sock(sk); |
188 | 186 | ||
189 | /* FIXME: Is this check still needed */ | 187 | /* FIXME: Is this check still needed */ |
190 | if (sk->sk_state == BT_CLOSED) { | 188 | if (sk->sk_state == BT_CLOSED) { |
191 | release_sock(sk); | ||
192 | bt_accept_unlink(sk); | 189 | bt_accept_unlink(sk); |
190 | release_sock(sk); | ||
193 | continue; | 191 | continue; |
194 | } | 192 | } |
195 | 193 | ||
@@ -271,11 +269,11 @@ static long bt_sock_data_wait(struct sock *sk, long timeo) | |||
271 | if (signal_pending(current) || !timeo) | 269 | if (signal_pending(current) || !timeo) |
272 | break; | 270 | break; |
273 | 271 | ||
274 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 272 | sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
275 | release_sock(sk); | 273 | release_sock(sk); |
276 | timeo = schedule_timeout(timeo); | 274 | timeo = schedule_timeout(timeo); |
277 | lock_sock(sk); | 275 | lock_sock(sk); |
278 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 276 | sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
279 | } | 277 | } |
280 | 278 | ||
281 | __set_current_state(TASK_RUNNING); | 279 | __set_current_state(TASK_RUNNING); |
@@ -390,11 +388,11 @@ EXPORT_SYMBOL(bt_sock_stream_recvmsg); | |||
390 | 388 | ||
391 | static inline unsigned int bt_accept_poll(struct sock *parent) | 389 | static inline unsigned int bt_accept_poll(struct sock *parent) |
392 | { | 390 | { |
393 | struct list_head *p, *n; | 391 | struct bt_sock *s, *n; |
394 | struct sock *sk; | 392 | struct sock *sk; |
395 | 393 | ||
396 | list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { | 394 | list_for_each_entry_safe(s, n, &bt_sk(parent)->accept_q, accept_q) { |
397 | sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); | 395 | sk = (struct sock *)s; |
398 | if (sk->sk_state == BT_CONNECTED || | 396 | if (sk->sk_state == BT_CONNECTED || |
399 | (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) && | 397 | (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) && |
400 | sk->sk_state == BT_CONNECT2)) | 398 | sk->sk_state == BT_CONNECT2)) |
@@ -441,7 +439,7 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock, | |||
441 | if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk)) | 439 | if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk)) |
442 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | 440 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; |
443 | else | 441 | else |
444 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 442 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
445 | 443 | ||
446 | return mask; | 444 | return mask; |
447 | } | 445 | } |
@@ -671,7 +669,7 @@ static const struct file_operations bt_fops = { | |||
671 | }; | 669 | }; |
672 | 670 | ||
673 | int bt_procfs_init(struct net *net, const char *name, | 671 | int bt_procfs_init(struct net *net, const char *name, |
674 | struct bt_sock_list* sk_list, | 672 | struct bt_sock_list *sk_list, |
675 | int (* seq_show)(struct seq_file *, void *)) | 673 | int (* seq_show)(struct seq_file *, void *)) |
676 | { | 674 | { |
677 | sk_list->custom_seq_show = seq_show; | 675 | sk_list->custom_seq_show = seq_show; |
@@ -687,7 +685,7 @@ void bt_procfs_cleanup(struct net *net, const char *name) | |||
687 | } | 685 | } |
688 | #else | 686 | #else |
689 | int bt_procfs_init(struct net *net, const char *name, | 687 | int bt_procfs_init(struct net *net, const char *name, |
690 | struct bt_sock_list* sk_list, | 688 | struct bt_sock_list *sk_list, |
691 | int (* seq_show)(struct seq_file *, void *)) | 689 | int (* seq_show)(struct seq_file *, void *)) |
692 | { | 690 | { |
693 | return 0; | 691 | return 0; |
@@ -715,7 +713,7 @@ static int __init bt_init(void) | |||
715 | 713 | ||
716 | sock_skb_cb_check_size(sizeof(struct bt_skb_cb)); | 714 | sock_skb_cb_check_size(sizeof(struct bt_skb_cb)); |
717 | 715 | ||
718 | BT_INFO("Core ver %s", VERSION); | 716 | BT_INFO("Core ver %s", BT_SUBSYS_VERSION); |
719 | 717 | ||
720 | err = bt_selftest(); | 718 | err = bt_selftest(); |
721 | if (err < 0) | 719 | if (err < 0) |
@@ -789,7 +787,7 @@ subsys_initcall(bt_init); | |||
789 | module_exit(bt_exit); | 787 | module_exit(bt_exit); |
790 | 788 | ||
791 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | 789 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
792 | MODULE_DESCRIPTION("Bluetooth Core ver " VERSION); | 790 | MODULE_DESCRIPTION("Bluetooth Core ver " BT_SUBSYS_VERSION); |
793 | MODULE_VERSION(VERSION); | 791 | MODULE_VERSION(BT_SUBSYS_VERSION); |
794 | MODULE_LICENSE("GPL"); | 792 | MODULE_LICENSE("GPL"); |
795 | MODULE_ALIAS_NETPROTO(PF_BLUETOOTH); | 793 | MODULE_ALIAS_NETPROTO(PF_BLUETOOTH); |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 1641367e54ca..fbf251fef70f 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -608,8 +608,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
608 | s->msg.msg_flags = MSG_NOSIGNAL; | 608 | s->msg.msg_flags = MSG_NOSIGNAL; |
609 | 609 | ||
610 | #ifdef CONFIG_BT_BNEP_MC_FILTER | 610 | #ifdef CONFIG_BT_BNEP_MC_FILTER |
611 | /* Set default mc filter */ | 611 | /* Set default mc filter to not filter out any mc addresses |
612 | set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter); | 612 | * as defined in the BNEP specification (revision 0.95a) |
613 | * http://grouper.ieee.org/groups/802/15/Bluetooth/BNEP.pdf | ||
614 | */ | ||
615 | s->mc_filter = ~0LL; | ||
613 | #endif | 616 | #endif |
614 | 617 | ||
615 | #ifdef CONFIG_BT_BNEP_PROTO_FILTER | 618 | #ifdef CONFIG_BT_BNEP_PROTO_FILTER |
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index 9a50338772f3..46ac686c8911 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c | |||
@@ -100,10 +100,8 @@ static void cmtp_application_del(struct cmtp_session *session, struct cmtp_appli | |||
100 | static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value) | 100 | static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value) |
101 | { | 101 | { |
102 | struct cmtp_application *app; | 102 | struct cmtp_application *app; |
103 | struct list_head *p; | ||
104 | 103 | ||
105 | list_for_each(p, &session->applications) { | 104 | list_for_each_entry(app, &session->applications, list) { |
106 | app = list_entry(p, struct cmtp_application, list); | ||
107 | switch (pattern) { | 105 | switch (pattern) { |
108 | case CMTP_MSGNUM: | 106 | case CMTP_MSGNUM: |
109 | if (app->msgnum == value) | 107 | if (app->msgnum == value) |
@@ -511,14 +509,12 @@ static int cmtp_proc_show(struct seq_file *m, void *v) | |||
511 | struct capi_ctr *ctrl = m->private; | 509 | struct capi_ctr *ctrl = m->private; |
512 | struct cmtp_session *session = ctrl->driverdata; | 510 | struct cmtp_session *session = ctrl->driverdata; |
513 | struct cmtp_application *app; | 511 | struct cmtp_application *app; |
514 | struct list_head *p; | ||
515 | 512 | ||
516 | seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl)); | 513 | seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl)); |
517 | seq_printf(m, "addr %s\n", session->name); | 514 | seq_printf(m, "addr %s\n", session->name); |
518 | seq_printf(m, "ctrl %d\n", session->num); | 515 | seq_printf(m, "ctrl %d\n", session->num); |
519 | 516 | ||
520 | list_for_each(p, &session->applications) { | 517 | list_for_each_entry(app, &session->applications, list) { |
521 | app = list_entry(p, struct cmtp_application, list); | ||
522 | seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping); | 518 | seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping); |
523 | } | 519 | } |
524 | 520 | ||
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 298ed37010e6..9e59b6654126 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
@@ -178,8 +178,7 @@ static inline int cmtp_recv_frame(struct cmtp_session *session, struct sk_buff * | |||
178 | cmtp_add_msgpart(session, id, skb->data + hdrlen, len); | 178 | cmtp_add_msgpart(session, id, skb->data + hdrlen, len); |
179 | break; | 179 | break; |
180 | default: | 180 | default: |
181 | if (session->reassembly[id] != NULL) | 181 | kfree_skb(session->reassembly[id]); |
182 | kfree_skb(session->reassembly[id]); | ||
183 | session->reassembly[id] = NULL; | 182 | session->reassembly[id] = NULL; |
184 | break; | 183 | break; |
185 | } | 184 | } |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 85b82f7adbd2..32575b49f4a0 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -178,6 +178,10 @@ static void hci_connect_le_scan_remove(struct hci_conn *conn) | |||
178 | hci_dev_hold(conn->hdev); | 178 | hci_dev_hold(conn->hdev); |
179 | hci_conn_get(conn); | 179 | hci_conn_get(conn); |
180 | 180 | ||
181 | /* Even though we hold a reference to the hdev, many other | ||
182 | * things might get cleaned up meanwhile, including the hdev's | ||
183 | * own workqueue, so we can't use that for scheduling. | ||
184 | */ | ||
181 | schedule_work(&conn->le_scan_cleanup); | 185 | schedule_work(&conn->le_scan_cleanup); |
182 | } | 186 | } |
183 | 187 | ||
@@ -664,8 +668,16 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status) | |||
664 | 668 | ||
665 | conn->state = BT_CLOSED; | 669 | conn->state = BT_CLOSED; |
666 | 670 | ||
667 | mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, | 671 | /* If the status indicates successful cancellation of |
668 | status); | 672 | * the attempt (i.e. Unkown Connection Id) there's no point of |
673 | * notifying failure since we'll go back to keep trying to | ||
674 | * connect. The only exception is explicit connect requests | ||
675 | * where a timeout + cancel does indicate an actual failure. | ||
676 | */ | ||
677 | if (status != HCI_ERROR_UNKNOWN_CONN_ID || | ||
678 | (params && params->explicit_connect)) | ||
679 | mgmt_connect_failed(hdev, &conn->dst, conn->type, | ||
680 | conn->dst_type, status); | ||
669 | 681 | ||
670 | hci_connect_cfm(conn, status); | 682 | hci_connect_cfm(conn, status); |
671 | 683 | ||
@@ -679,7 +691,7 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status) | |||
679 | /* Re-enable advertising in case this was a failed connection | 691 | /* Re-enable advertising in case this was a failed connection |
680 | * attempt as a peripheral. | 692 | * attempt as a peripheral. |
681 | */ | 693 | */ |
682 | mgmt_reenable_advertising(hdev); | 694 | hci_req_reenable_advertising(hdev); |
683 | } | 695 | } |
684 | 696 | ||
685 | static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode) | 697 | static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode) |
@@ -722,8 +734,12 @@ static void hci_req_add_le_create_conn(struct hci_request *req, | |||
722 | if (hci_update_random_address(req, false, &own_addr_type)) | 734 | if (hci_update_random_address(req, false, &own_addr_type)) |
723 | return; | 735 | return; |
724 | 736 | ||
737 | /* Set window to be the same value as the interval to enable | ||
738 | * continuous scanning. | ||
739 | */ | ||
725 | cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); | 740 | cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); |
726 | cp.scan_window = cpu_to_le16(hdev->le_scan_window); | 741 | cp.scan_window = cp.scan_interval; |
742 | |||
727 | bacpy(&cp.peer_addr, &conn->dst); | 743 | bacpy(&cp.peer_addr, &conn->dst); |
728 | cp.peer_addr_type = conn->dst_type; | 744 | cp.peer_addr_type = conn->dst_type; |
729 | cp.own_address_type = own_addr_type; | 745 | cp.own_address_type = own_addr_type; |
@@ -781,7 +797,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
781 | u8 role) | 797 | u8 role) |
782 | { | 798 | { |
783 | struct hci_conn_params *params; | 799 | struct hci_conn_params *params; |
784 | struct hci_conn *conn, *conn_unfinished; | 800 | struct hci_conn *conn; |
785 | struct smp_irk *irk; | 801 | struct smp_irk *irk; |
786 | struct hci_request req; | 802 | struct hci_request req; |
787 | int err; | 803 | int err; |
@@ -794,35 +810,22 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
794 | return ERR_PTR(-EOPNOTSUPP); | 810 | return ERR_PTR(-EOPNOTSUPP); |
795 | } | 811 | } |
796 | 812 | ||
797 | /* Some devices send ATT messages as soon as the physical link is | ||
798 | * established. To be able to handle these ATT messages, the user- | ||
799 | * space first establishes the connection and then starts the pairing | ||
800 | * process. | ||
801 | * | ||
802 | * So if a hci_conn object already exists for the following connection | ||
803 | * attempt, we simply update pending_sec_level and auth_type fields | ||
804 | * and return the object found. | ||
805 | */ | ||
806 | conn = hci_conn_hash_lookup_le(hdev, dst, dst_type); | ||
807 | conn_unfinished = NULL; | ||
808 | if (conn) { | ||
809 | if (conn->state == BT_CONNECT && | ||
810 | test_bit(HCI_CONN_SCANNING, &conn->flags)) { | ||
811 | BT_DBG("will continue unfinished conn %pMR", dst); | ||
812 | conn_unfinished = conn; | ||
813 | } else { | ||
814 | if (conn->pending_sec_level < sec_level) | ||
815 | conn->pending_sec_level = sec_level; | ||
816 | goto done; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | /* Since the controller supports only one LE connection attempt at a | 813 | /* Since the controller supports only one LE connection attempt at a |
821 | * time, we return -EBUSY if there is any connection attempt running. | 814 | * time, we return -EBUSY if there is any connection attempt running. |
822 | */ | 815 | */ |
823 | if (hci_lookup_le_connect(hdev)) | 816 | if (hci_lookup_le_connect(hdev)) |
824 | return ERR_PTR(-EBUSY); | 817 | return ERR_PTR(-EBUSY); |
825 | 818 | ||
819 | /* If there's already a connection object but it's not in | ||
820 | * scanning state it means it must already be established, in | ||
821 | * which case we can't do anything else except report a failure | ||
822 | * to connect. | ||
823 | */ | ||
824 | conn = hci_conn_hash_lookup_le(hdev, dst, dst_type); | ||
825 | if (conn && !test_bit(HCI_CONN_SCANNING, &conn->flags)) { | ||
826 | return ERR_PTR(-EBUSY); | ||
827 | } | ||
828 | |||
826 | /* When given an identity address with existing identity | 829 | /* When given an identity address with existing identity |
827 | * resolving key, the connection needs to be established | 830 | * resolving key, the connection needs to be established |
828 | * to a resolvable random address. | 831 | * to a resolvable random address. |
@@ -838,23 +841,20 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
838 | dst_type = ADDR_LE_DEV_RANDOM; | 841 | dst_type = ADDR_LE_DEV_RANDOM; |
839 | } | 842 | } |
840 | 843 | ||
841 | if (conn_unfinished) { | 844 | if (conn) { |
842 | conn = conn_unfinished; | ||
843 | bacpy(&conn->dst, dst); | 845 | bacpy(&conn->dst, dst); |
844 | } else { | 846 | } else { |
845 | conn = hci_conn_add(hdev, LE_LINK, dst, role); | 847 | conn = hci_conn_add(hdev, LE_LINK, dst, role); |
848 | if (!conn) | ||
849 | return ERR_PTR(-ENOMEM); | ||
850 | hci_conn_hold(conn); | ||
851 | conn->pending_sec_level = sec_level; | ||
846 | } | 852 | } |
847 | 853 | ||
848 | if (!conn) | ||
849 | return ERR_PTR(-ENOMEM); | ||
850 | |||
851 | conn->dst_type = dst_type; | 854 | conn->dst_type = dst_type; |
852 | conn->sec_level = BT_SECURITY_LOW; | 855 | conn->sec_level = BT_SECURITY_LOW; |
853 | conn->conn_timeout = conn_timeout; | 856 | conn->conn_timeout = conn_timeout; |
854 | 857 | ||
855 | if (!conn_unfinished) | ||
856 | conn->pending_sec_level = sec_level; | ||
857 | |||
858 | hci_req_init(&req, hdev); | 858 | hci_req_init(&req, hdev); |
859 | 859 | ||
860 | /* Disable advertising if we're active. For master role | 860 | /* Disable advertising if we're active. For master role |
@@ -918,37 +918,9 @@ create_conn: | |||
918 | return ERR_PTR(err); | 918 | return ERR_PTR(err); |
919 | } | 919 | } |
920 | 920 | ||
921 | done: | ||
922 | /* If this is continuation of connect started by hci_connect_le_scan, | ||
923 | * it already called hci_conn_hold and calling it again would mess the | ||
924 | * counter. | ||
925 | */ | ||
926 | if (!conn_unfinished) | ||
927 | hci_conn_hold(conn); | ||
928 | |||
929 | return conn; | 921 | return conn; |
930 | } | 922 | } |
931 | 923 | ||
932 | static void hci_connect_le_scan_complete(struct hci_dev *hdev, u8 status, | ||
933 | u16 opcode) | ||
934 | { | ||
935 | struct hci_conn *conn; | ||
936 | |||
937 | if (!status) | ||
938 | return; | ||
939 | |||
940 | BT_ERR("Failed to add device to auto conn whitelist: status 0x%2.2x", | ||
941 | status); | ||
942 | |||
943 | hci_dev_lock(hdev); | ||
944 | |||
945 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
946 | if (conn) | ||
947 | hci_le_conn_failed(conn, status); | ||
948 | |||
949 | hci_dev_unlock(hdev); | ||
950 | } | ||
951 | |||
952 | static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type) | 924 | static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type) |
953 | { | 925 | { |
954 | struct hci_conn *conn; | 926 | struct hci_conn *conn; |
@@ -964,10 +936,9 @@ static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type) | |||
964 | } | 936 | } |
965 | 937 | ||
966 | /* This function requires the caller holds hdev->lock */ | 938 | /* This function requires the caller holds hdev->lock */ |
967 | static int hci_explicit_conn_params_set(struct hci_request *req, | 939 | static int hci_explicit_conn_params_set(struct hci_dev *hdev, |
968 | bdaddr_t *addr, u8 addr_type) | 940 | bdaddr_t *addr, u8 addr_type) |
969 | { | 941 | { |
970 | struct hci_dev *hdev = req->hdev; | ||
971 | struct hci_conn_params *params; | 942 | struct hci_conn_params *params; |
972 | 943 | ||
973 | if (is_connected(hdev, addr, addr_type)) | 944 | if (is_connected(hdev, addr, addr_type)) |
@@ -995,7 +966,6 @@ static int hci_explicit_conn_params_set(struct hci_request *req, | |||
995 | } | 966 | } |
996 | 967 | ||
997 | params->explicit_connect = true; | 968 | params->explicit_connect = true; |
998 | __hci_update_background_scan(req); | ||
999 | 969 | ||
1000 | BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type, | 970 | BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type, |
1001 | params->auto_connect); | 971 | params->auto_connect); |
@@ -1006,11 +976,9 @@ static int hci_explicit_conn_params_set(struct hci_request *req, | |||
1006 | /* This function requires the caller holds hdev->lock */ | 976 | /* This function requires the caller holds hdev->lock */ |
1007 | struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, | 977 | struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, |
1008 | u8 dst_type, u8 sec_level, | 978 | u8 dst_type, u8 sec_level, |
1009 | u16 conn_timeout, u8 role) | 979 | u16 conn_timeout) |
1010 | { | 980 | { |
1011 | struct hci_conn *conn; | 981 | struct hci_conn *conn; |
1012 | struct hci_request req; | ||
1013 | int err; | ||
1014 | 982 | ||
1015 | /* Let's make sure that le is enabled.*/ | 983 | /* Let's make sure that le is enabled.*/ |
1016 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) { | 984 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) { |
@@ -1038,29 +1006,22 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, | |||
1038 | 1006 | ||
1039 | BT_DBG("requesting refresh of dst_addr"); | 1007 | BT_DBG("requesting refresh of dst_addr"); |
1040 | 1008 | ||
1041 | conn = hci_conn_add(hdev, LE_LINK, dst, role); | 1009 | conn = hci_conn_add(hdev, LE_LINK, dst, HCI_ROLE_MASTER); |
1042 | if (!conn) | 1010 | if (!conn) |
1043 | return ERR_PTR(-ENOMEM); | 1011 | return ERR_PTR(-ENOMEM); |
1044 | 1012 | ||
1045 | hci_req_init(&req, hdev); | 1013 | if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) |
1046 | |||
1047 | if (hci_explicit_conn_params_set(&req, dst, dst_type) < 0) | ||
1048 | return ERR_PTR(-EBUSY); | 1014 | return ERR_PTR(-EBUSY); |
1049 | 1015 | ||
1050 | conn->state = BT_CONNECT; | 1016 | conn->state = BT_CONNECT; |
1051 | set_bit(HCI_CONN_SCANNING, &conn->flags); | 1017 | set_bit(HCI_CONN_SCANNING, &conn->flags); |
1052 | |||
1053 | err = hci_req_run(&req, hci_connect_le_scan_complete); | ||
1054 | if (err && err != -ENODATA) { | ||
1055 | hci_conn_del(conn); | ||
1056 | return ERR_PTR(err); | ||
1057 | } | ||
1058 | |||
1059 | conn->dst_type = dst_type; | 1018 | conn->dst_type = dst_type; |
1060 | conn->sec_level = BT_SECURITY_LOW; | 1019 | conn->sec_level = BT_SECURITY_LOW; |
1061 | conn->pending_sec_level = sec_level; | 1020 | conn->pending_sec_level = sec_level; |
1062 | conn->conn_timeout = conn_timeout; | 1021 | conn->conn_timeout = conn_timeout; |
1063 | 1022 | ||
1023 | hci_update_background_scan(hdev); | ||
1024 | |||
1064 | done: | 1025 | done: |
1065 | hci_conn_hold(conn); | 1026 | hci_conn_hold(conn); |
1066 | return conn; | 1027 | return conn; |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 62edbf1b114e..47bcef754796 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -56,15 +56,6 @@ DEFINE_MUTEX(hci_cb_list_lock); | |||
56 | /* HCI ID Numbering */ | 56 | /* HCI ID Numbering */ |
57 | static DEFINE_IDA(hci_index_ida); | 57 | static DEFINE_IDA(hci_index_ida); |
58 | 58 | ||
59 | /* ----- HCI requests ----- */ | ||
60 | |||
61 | #define HCI_REQ_DONE 0 | ||
62 | #define HCI_REQ_PEND 1 | ||
63 | #define HCI_REQ_CANCELED 2 | ||
64 | |||
65 | #define hci_req_lock(d) mutex_lock(&d->req_lock) | ||
66 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) | ||
67 | |||
68 | /* ---- HCI debugfs entries ---- */ | 59 | /* ---- HCI debugfs entries ---- */ |
69 | 60 | ||
70 | static ssize_t dut_mode_read(struct file *file, char __user *user_buf, | 61 | static ssize_t dut_mode_read(struct file *file, char __user *user_buf, |
@@ -73,7 +64,7 @@ static ssize_t dut_mode_read(struct file *file, char __user *user_buf, | |||
73 | struct hci_dev *hdev = file->private_data; | 64 | struct hci_dev *hdev = file->private_data; |
74 | char buf[3]; | 65 | char buf[3]; |
75 | 66 | ||
76 | buf[0] = hci_dev_test_flag(hdev, HCI_DUT_MODE) ? 'Y': 'N'; | 67 | buf[0] = hci_dev_test_flag(hdev, HCI_DUT_MODE) ? 'Y' : 'N'; |
77 | buf[1] = '\n'; | 68 | buf[1] = '\n'; |
78 | buf[2] = '\0'; | 69 | buf[2] = '\0'; |
79 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 70 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); |
@@ -101,14 +92,14 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf, | |||
101 | if (enable == hci_dev_test_flag(hdev, HCI_DUT_MODE)) | 92 | if (enable == hci_dev_test_flag(hdev, HCI_DUT_MODE)) |
102 | return -EALREADY; | 93 | return -EALREADY; |
103 | 94 | ||
104 | hci_req_lock(hdev); | 95 | hci_req_sync_lock(hdev); |
105 | if (enable) | 96 | if (enable) |
106 | skb = __hci_cmd_sync(hdev, HCI_OP_ENABLE_DUT_MODE, 0, NULL, | 97 | skb = __hci_cmd_sync(hdev, HCI_OP_ENABLE_DUT_MODE, 0, NULL, |
107 | HCI_CMD_TIMEOUT); | 98 | HCI_CMD_TIMEOUT); |
108 | else | 99 | else |
109 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, | 100 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, |
110 | HCI_CMD_TIMEOUT); | 101 | HCI_CMD_TIMEOUT); |
111 | hci_req_unlock(hdev); | 102 | hci_req_sync_unlock(hdev); |
112 | 103 | ||
113 | if (IS_ERR(skb)) | 104 | if (IS_ERR(skb)) |
114 | return PTR_ERR(skb); | 105 | return PTR_ERR(skb); |
@@ -133,7 +124,7 @@ static ssize_t vendor_diag_read(struct file *file, char __user *user_buf, | |||
133 | struct hci_dev *hdev = file->private_data; | 124 | struct hci_dev *hdev = file->private_data; |
134 | char buf[3]; | 125 | char buf[3]; |
135 | 126 | ||
136 | buf[0] = hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) ? 'Y': 'N'; | 127 | buf[0] = hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) ? 'Y' : 'N'; |
137 | buf[1] = '\n'; | 128 | buf[1] = '\n'; |
138 | buf[2] = '\0'; | 129 | buf[2] = '\0'; |
139 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 130 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); |
@@ -165,9 +156,9 @@ static ssize_t vendor_diag_write(struct file *file, const char __user *user_buf, | |||
165 | !test_bit(HCI_RUNNING, &hdev->flags)) | 156 | !test_bit(HCI_RUNNING, &hdev->flags)) |
166 | goto done; | 157 | goto done; |
167 | 158 | ||
168 | hci_req_lock(hdev); | 159 | hci_req_sync_lock(hdev); |
169 | err = hdev->set_diag(hdev, enable); | 160 | err = hdev->set_diag(hdev, enable); |
170 | hci_req_unlock(hdev); | 161 | hci_req_sync_unlock(hdev); |
171 | 162 | ||
172 | if (err < 0) | 163 | if (err < 0) |
173 | return err; | 164 | return err; |
@@ -198,197 +189,14 @@ static void hci_debugfs_create_basic(struct hci_dev *hdev) | |||
198 | &vendor_diag_fops); | 189 | &vendor_diag_fops); |
199 | } | 190 | } |
200 | 191 | ||
201 | /* ---- HCI requests ---- */ | 192 | static int hci_reset_req(struct hci_request *req, unsigned long opt) |
202 | |||
203 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode, | ||
204 | struct sk_buff *skb) | ||
205 | { | ||
206 | BT_DBG("%s result 0x%2.2x", hdev->name, result); | ||
207 | |||
208 | if (hdev->req_status == HCI_REQ_PEND) { | ||
209 | hdev->req_result = result; | ||
210 | hdev->req_status = HCI_REQ_DONE; | ||
211 | if (skb) | ||
212 | hdev->req_skb = skb_get(skb); | ||
213 | wake_up_interruptible(&hdev->req_wait_q); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | static void hci_req_cancel(struct hci_dev *hdev, int err) | ||
218 | { | ||
219 | BT_DBG("%s err 0x%2.2x", hdev->name, err); | ||
220 | |||
221 | if (hdev->req_status == HCI_REQ_PEND) { | ||
222 | hdev->req_result = err; | ||
223 | hdev->req_status = HCI_REQ_CANCELED; | ||
224 | wake_up_interruptible(&hdev->req_wait_q); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, | ||
229 | const void *param, u8 event, u32 timeout) | ||
230 | { | ||
231 | DECLARE_WAITQUEUE(wait, current); | ||
232 | struct hci_request req; | ||
233 | struct sk_buff *skb; | ||
234 | int err = 0; | ||
235 | |||
236 | BT_DBG("%s", hdev->name); | ||
237 | |||
238 | hci_req_init(&req, hdev); | ||
239 | |||
240 | hci_req_add_ev(&req, opcode, plen, param, event); | ||
241 | |||
242 | hdev->req_status = HCI_REQ_PEND; | ||
243 | |||
244 | add_wait_queue(&hdev->req_wait_q, &wait); | ||
245 | set_current_state(TASK_INTERRUPTIBLE); | ||
246 | |||
247 | err = hci_req_run_skb(&req, hci_req_sync_complete); | ||
248 | if (err < 0) { | ||
249 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
250 | set_current_state(TASK_RUNNING); | ||
251 | return ERR_PTR(err); | ||
252 | } | ||
253 | |||
254 | schedule_timeout(timeout); | ||
255 | |||
256 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
257 | |||
258 | if (signal_pending(current)) | ||
259 | return ERR_PTR(-EINTR); | ||
260 | |||
261 | switch (hdev->req_status) { | ||
262 | case HCI_REQ_DONE: | ||
263 | err = -bt_to_errno(hdev->req_result); | ||
264 | break; | ||
265 | |||
266 | case HCI_REQ_CANCELED: | ||
267 | err = -hdev->req_result; | ||
268 | break; | ||
269 | |||
270 | default: | ||
271 | err = -ETIMEDOUT; | ||
272 | break; | ||
273 | } | ||
274 | |||
275 | hdev->req_status = hdev->req_result = 0; | ||
276 | skb = hdev->req_skb; | ||
277 | hdev->req_skb = NULL; | ||
278 | |||
279 | BT_DBG("%s end: err %d", hdev->name, err); | ||
280 | |||
281 | if (err < 0) { | ||
282 | kfree_skb(skb); | ||
283 | return ERR_PTR(err); | ||
284 | } | ||
285 | |||
286 | if (!skb) | ||
287 | return ERR_PTR(-ENODATA); | ||
288 | |||
289 | return skb; | ||
290 | } | ||
291 | EXPORT_SYMBOL(__hci_cmd_sync_ev); | ||
292 | |||
293 | struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, | ||
294 | const void *param, u32 timeout) | ||
295 | { | ||
296 | return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout); | ||
297 | } | ||
298 | EXPORT_SYMBOL(__hci_cmd_sync); | ||
299 | |||
300 | /* Execute request and wait for completion. */ | ||
301 | static int __hci_req_sync(struct hci_dev *hdev, | ||
302 | void (*func)(struct hci_request *req, | ||
303 | unsigned long opt), | ||
304 | unsigned long opt, __u32 timeout) | ||
305 | { | ||
306 | struct hci_request req; | ||
307 | DECLARE_WAITQUEUE(wait, current); | ||
308 | int err = 0; | ||
309 | |||
310 | BT_DBG("%s start", hdev->name); | ||
311 | |||
312 | hci_req_init(&req, hdev); | ||
313 | |||
314 | hdev->req_status = HCI_REQ_PEND; | ||
315 | |||
316 | func(&req, opt); | ||
317 | |||
318 | add_wait_queue(&hdev->req_wait_q, &wait); | ||
319 | set_current_state(TASK_INTERRUPTIBLE); | ||
320 | |||
321 | err = hci_req_run_skb(&req, hci_req_sync_complete); | ||
322 | if (err < 0) { | ||
323 | hdev->req_status = 0; | ||
324 | |||
325 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
326 | set_current_state(TASK_RUNNING); | ||
327 | |||
328 | /* ENODATA means the HCI request command queue is empty. | ||
329 | * This can happen when a request with conditionals doesn't | ||
330 | * trigger any commands to be sent. This is normal behavior | ||
331 | * and should not trigger an error return. | ||
332 | */ | ||
333 | if (err == -ENODATA) | ||
334 | return 0; | ||
335 | |||
336 | return err; | ||
337 | } | ||
338 | |||
339 | schedule_timeout(timeout); | ||
340 | |||
341 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
342 | |||
343 | if (signal_pending(current)) | ||
344 | return -EINTR; | ||
345 | |||
346 | switch (hdev->req_status) { | ||
347 | case HCI_REQ_DONE: | ||
348 | err = -bt_to_errno(hdev->req_result); | ||
349 | break; | ||
350 | |||
351 | case HCI_REQ_CANCELED: | ||
352 | err = -hdev->req_result; | ||
353 | break; | ||
354 | |||
355 | default: | ||
356 | err = -ETIMEDOUT; | ||
357 | break; | ||
358 | } | ||
359 | |||
360 | hdev->req_status = hdev->req_result = 0; | ||
361 | |||
362 | BT_DBG("%s end: err %d", hdev->name, err); | ||
363 | |||
364 | return err; | ||
365 | } | ||
366 | |||
367 | static int hci_req_sync(struct hci_dev *hdev, | ||
368 | void (*req)(struct hci_request *req, | ||
369 | unsigned long opt), | ||
370 | unsigned long opt, __u32 timeout) | ||
371 | { | ||
372 | int ret; | ||
373 | |||
374 | if (!test_bit(HCI_UP, &hdev->flags)) | ||
375 | return -ENETDOWN; | ||
376 | |||
377 | /* Serialize all requests */ | ||
378 | hci_req_lock(hdev); | ||
379 | ret = __hci_req_sync(hdev, req, opt, timeout); | ||
380 | hci_req_unlock(hdev); | ||
381 | |||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | static void hci_reset_req(struct hci_request *req, unsigned long opt) | ||
386 | { | 193 | { |
387 | BT_DBG("%s %ld", req->hdev->name, opt); | 194 | BT_DBG("%s %ld", req->hdev->name, opt); |
388 | 195 | ||
389 | /* Reset device */ | 196 | /* Reset device */ |
390 | set_bit(HCI_RESET, &req->hdev->flags); | 197 | set_bit(HCI_RESET, &req->hdev->flags); |
391 | hci_req_add(req, HCI_OP_RESET, 0, NULL); | 198 | hci_req_add(req, HCI_OP_RESET, 0, NULL); |
199 | return 0; | ||
392 | } | 200 | } |
393 | 201 | ||
394 | static void bredr_init(struct hci_request *req) | 202 | static void bredr_init(struct hci_request *req) |
@@ -428,7 +236,7 @@ static void amp_init1(struct hci_request *req) | |||
428 | hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL); | 236 | hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL); |
429 | } | 237 | } |
430 | 238 | ||
431 | static void amp_init2(struct hci_request *req) | 239 | static int amp_init2(struct hci_request *req) |
432 | { | 240 | { |
433 | /* Read Local Supported Features. Not all AMP controllers | 241 | /* Read Local Supported Features. Not all AMP controllers |
434 | * support this so it's placed conditionally in the second | 242 | * support this so it's placed conditionally in the second |
@@ -436,9 +244,11 @@ static void amp_init2(struct hci_request *req) | |||
436 | */ | 244 | */ |
437 | if (req->hdev->commands[14] & 0x20) | 245 | if (req->hdev->commands[14] & 0x20) |
438 | hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); | 246 | hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); |
247 | |||
248 | return 0; | ||
439 | } | 249 | } |
440 | 250 | ||
441 | static void hci_init1_req(struct hci_request *req, unsigned long opt) | 251 | static int hci_init1_req(struct hci_request *req, unsigned long opt) |
442 | { | 252 | { |
443 | struct hci_dev *hdev = req->hdev; | 253 | struct hci_dev *hdev = req->hdev; |
444 | 254 | ||
@@ -461,6 +271,8 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt) | |||
461 | BT_ERR("Unknown device type %d", hdev->dev_type); | 271 | BT_ERR("Unknown device type %d", hdev->dev_type); |
462 | break; | 272 | break; |
463 | } | 273 | } |
274 | |||
275 | return 0; | ||
464 | } | 276 | } |
465 | 277 | ||
466 | static void bredr_setup(struct hci_request *req) | 278 | static void bredr_setup(struct hci_request *req) |
@@ -531,20 +343,30 @@ static void hci_setup_event_mask(struct hci_request *req) | |||
531 | 343 | ||
532 | if (lmp_bredr_capable(hdev)) { | 344 | if (lmp_bredr_capable(hdev)) { |
533 | events[4] |= 0x01; /* Flow Specification Complete */ | 345 | events[4] |= 0x01; /* Flow Specification Complete */ |
534 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
535 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ | ||
536 | events[5] |= 0x08; /* Synchronous Connection Complete */ | ||
537 | events[5] |= 0x10; /* Synchronous Connection Changed */ | ||
538 | } else { | 346 | } else { |
539 | /* Use a different default for LE-only devices */ | 347 | /* Use a different default for LE-only devices */ |
540 | memset(events, 0, sizeof(events)); | 348 | memset(events, 0, sizeof(events)); |
541 | events[0] |= 0x10; /* Disconnection Complete */ | ||
542 | events[1] |= 0x08; /* Read Remote Version Information Complete */ | ||
543 | events[1] |= 0x20; /* Command Complete */ | 349 | events[1] |= 0x20; /* Command Complete */ |
544 | events[1] |= 0x40; /* Command Status */ | 350 | events[1] |= 0x40; /* Command Status */ |
545 | events[1] |= 0x80; /* Hardware Error */ | 351 | events[1] |= 0x80; /* Hardware Error */ |
546 | events[2] |= 0x04; /* Number of Completed Packets */ | 352 | |
547 | events[3] |= 0x02; /* Data Buffer Overflow */ | 353 | /* If the controller supports the Disconnect command, enable |
354 | * the corresponding event. In addition enable packet flow | ||
355 | * control related events. | ||
356 | */ | ||
357 | if (hdev->commands[0] & 0x20) { | ||
358 | events[0] |= 0x10; /* Disconnection Complete */ | ||
359 | events[2] |= 0x04; /* Number of Completed Packets */ | ||
360 | events[3] |= 0x02; /* Data Buffer Overflow */ | ||
361 | } | ||
362 | |||
363 | /* If the controller supports the Read Remote Version | ||
364 | * Information command, enable the corresponding event. | ||
365 | */ | ||
366 | if (hdev->commands[2] & 0x80) | ||
367 | events[1] |= 0x08; /* Read Remote Version Information | ||
368 | * Complete | ||
369 | */ | ||
548 | 370 | ||
549 | if (hdev->le_features[0] & HCI_LE_ENCRYPTION) { | 371 | if (hdev->le_features[0] & HCI_LE_ENCRYPTION) { |
550 | events[0] |= 0x80; /* Encryption Change */ | 372 | events[0] |= 0x80; /* Encryption Change */ |
@@ -552,9 +374,18 @@ static void hci_setup_event_mask(struct hci_request *req) | |||
552 | } | 374 | } |
553 | } | 375 | } |
554 | 376 | ||
555 | if (lmp_inq_rssi_capable(hdev)) | 377 | if (lmp_inq_rssi_capable(hdev) || |
378 | test_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks)) | ||
556 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | 379 | events[4] |= 0x02; /* Inquiry Result with RSSI */ |
557 | 380 | ||
381 | if (lmp_ext_feat_capable(hdev)) | ||
382 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ | ||
383 | |||
384 | if (lmp_esco_capable(hdev)) { | ||
385 | events[5] |= 0x08; /* Synchronous Connection Complete */ | ||
386 | events[5] |= 0x10; /* Synchronous Connection Changed */ | ||
387 | } | ||
388 | |||
558 | if (lmp_sniffsubr_capable(hdev)) | 389 | if (lmp_sniffsubr_capable(hdev)) |
559 | events[5] |= 0x20; /* Sniff Subrating */ | 390 | events[5] |= 0x20; /* Sniff Subrating */ |
560 | 391 | ||
@@ -590,7 +421,7 @@ static void hci_setup_event_mask(struct hci_request *req) | |||
590 | hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | 421 | hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events); |
591 | } | 422 | } |
592 | 423 | ||
593 | static void hci_init2_req(struct hci_request *req, unsigned long opt) | 424 | static int hci_init2_req(struct hci_request *req, unsigned long opt) |
594 | { | 425 | { |
595 | struct hci_dev *hdev = req->hdev; | 426 | struct hci_dev *hdev = req->hdev; |
596 | 427 | ||
@@ -670,6 +501,8 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) | |||
670 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), | 501 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), |
671 | &enable); | 502 | &enable); |
672 | } | 503 | } |
504 | |||
505 | return 0; | ||
673 | } | 506 | } |
674 | 507 | ||
675 | static void hci_setup_link_policy(struct hci_request *req) | 508 | static void hci_setup_link_policy(struct hci_request *req) |
@@ -744,7 +577,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req) | |||
744 | hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); | 577 | hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); |
745 | } | 578 | } |
746 | 579 | ||
747 | static void hci_init3_req(struct hci_request *req, unsigned long opt) | 580 | static int hci_init3_req(struct hci_request *req, unsigned long opt) |
748 | { | 581 | { |
749 | struct hci_dev *hdev = req->hdev; | 582 | struct hci_dev *hdev = req->hdev; |
750 | u8 p; | 583 | u8 p; |
@@ -777,7 +610,6 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
777 | u8 events[8]; | 610 | u8 events[8]; |
778 | 611 | ||
779 | memset(events, 0, sizeof(events)); | 612 | memset(events, 0, sizeof(events)); |
780 | events[0] = 0x0f; | ||
781 | 613 | ||
782 | if (hdev->le_features[0] & HCI_LE_ENCRYPTION) | 614 | if (hdev->le_features[0] & HCI_LE_ENCRYPTION) |
783 | events[0] |= 0x10; /* LE Long Term Key Request */ | 615 | events[0] |= 0x10; /* LE Long Term Key Request */ |
@@ -804,6 +636,34 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
804 | * Report | 636 | * Report |
805 | */ | 637 | */ |
806 | 638 | ||
639 | /* If the controller supports the LE Set Scan Enable command, | ||
640 | * enable the corresponding advertising report event. | ||
641 | */ | ||
642 | if (hdev->commands[26] & 0x08) | ||
643 | events[0] |= 0x02; /* LE Advertising Report */ | ||
644 | |||
645 | /* If the controller supports the LE Create Connection | ||
646 | * command, enable the corresponding event. | ||
647 | */ | ||
648 | if (hdev->commands[26] & 0x10) | ||
649 | events[0] |= 0x01; /* LE Connection Complete */ | ||
650 | |||
651 | /* If the controller supports the LE Connection Update | ||
652 | * command, enable the corresponding event. | ||
653 | */ | ||
654 | if (hdev->commands[27] & 0x04) | ||
655 | events[0] |= 0x04; /* LE Connection Update | ||
656 | * Complete | ||
657 | */ | ||
658 | |||
659 | /* If the controller supports the LE Read Remote Used Features | ||
660 | * command, enable the corresponding event. | ||
661 | */ | ||
662 | if (hdev->commands[27] & 0x20) | ||
663 | events[0] |= 0x08; /* LE Read Remote Used | ||
664 | * Features Complete | ||
665 | */ | ||
666 | |||
807 | /* If the controller supports the LE Read Local P-256 | 667 | /* If the controller supports the LE Read Local P-256 |
808 | * Public Key command, enable the corresponding event. | 668 | * Public Key command, enable the corresponding event. |
809 | */ | 669 | */ |
@@ -856,9 +716,11 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
856 | hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES, | 716 | hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES, |
857 | sizeof(cp), &cp); | 717 | sizeof(cp), &cp); |
858 | } | 718 | } |
719 | |||
720 | return 0; | ||
859 | } | 721 | } |
860 | 722 | ||
861 | static void hci_init4_req(struct hci_request *req, unsigned long opt) | 723 | static int hci_init4_req(struct hci_request *req, unsigned long opt) |
862 | { | 724 | { |
863 | struct hci_dev *hdev = req->hdev; | 725 | struct hci_dev *hdev = req->hdev; |
864 | 726 | ||
@@ -909,20 +771,22 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt) | |||
909 | hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT, | 771 | hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT, |
910 | sizeof(support), &support); | 772 | sizeof(support), &support); |
911 | } | 773 | } |
774 | |||
775 | return 0; | ||
912 | } | 776 | } |
913 | 777 | ||
914 | static int __hci_init(struct hci_dev *hdev) | 778 | static int __hci_init(struct hci_dev *hdev) |
915 | { | 779 | { |
916 | int err; | 780 | int err; |
917 | 781 | ||
918 | err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT); | 782 | err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT, NULL); |
919 | if (err < 0) | 783 | if (err < 0) |
920 | return err; | 784 | return err; |
921 | 785 | ||
922 | if (hci_dev_test_flag(hdev, HCI_SETUP)) | 786 | if (hci_dev_test_flag(hdev, HCI_SETUP)) |
923 | hci_debugfs_create_basic(hdev); | 787 | hci_debugfs_create_basic(hdev); |
924 | 788 | ||
925 | err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT); | 789 | err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT, NULL); |
926 | if (err < 0) | 790 | if (err < 0) |
927 | return err; | 791 | return err; |
928 | 792 | ||
@@ -933,11 +797,11 @@ static int __hci_init(struct hci_dev *hdev) | |||
933 | if (hdev->dev_type != HCI_BREDR) | 797 | if (hdev->dev_type != HCI_BREDR) |
934 | return 0; | 798 | return 0; |
935 | 799 | ||
936 | err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT); | 800 | err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT, NULL); |
937 | if (err < 0) | 801 | if (err < 0) |
938 | return err; | 802 | return err; |
939 | 803 | ||
940 | err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT); | 804 | err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT, NULL); |
941 | if (err < 0) | 805 | if (err < 0) |
942 | return err; | 806 | return err; |
943 | 807 | ||
@@ -968,7 +832,7 @@ static int __hci_init(struct hci_dev *hdev) | |||
968 | return 0; | 832 | return 0; |
969 | } | 833 | } |
970 | 834 | ||
971 | static void hci_init0_req(struct hci_request *req, unsigned long opt) | 835 | static int hci_init0_req(struct hci_request *req, unsigned long opt) |
972 | { | 836 | { |
973 | struct hci_dev *hdev = req->hdev; | 837 | struct hci_dev *hdev = req->hdev; |
974 | 838 | ||
@@ -984,6 +848,8 @@ static void hci_init0_req(struct hci_request *req, unsigned long opt) | |||
984 | /* Read BD Address */ | 848 | /* Read BD Address */ |
985 | if (hdev->set_bdaddr) | 849 | if (hdev->set_bdaddr) |
986 | hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL); | 850 | hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL); |
851 | |||
852 | return 0; | ||
987 | } | 853 | } |
988 | 854 | ||
989 | static int __hci_unconf_init(struct hci_dev *hdev) | 855 | static int __hci_unconf_init(struct hci_dev *hdev) |
@@ -993,7 +859,7 @@ static int __hci_unconf_init(struct hci_dev *hdev) | |||
993 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) | 859 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) |
994 | return 0; | 860 | return 0; |
995 | 861 | ||
996 | err = __hci_req_sync(hdev, hci_init0_req, 0, HCI_INIT_TIMEOUT); | 862 | err = __hci_req_sync(hdev, hci_init0_req, 0, HCI_INIT_TIMEOUT, NULL); |
997 | if (err < 0) | 863 | if (err < 0) |
998 | return err; | 864 | return err; |
999 | 865 | ||
@@ -1003,7 +869,7 @@ static int __hci_unconf_init(struct hci_dev *hdev) | |||
1003 | return 0; | 869 | return 0; |
1004 | } | 870 | } |
1005 | 871 | ||
1006 | static void hci_scan_req(struct hci_request *req, unsigned long opt) | 872 | static int hci_scan_req(struct hci_request *req, unsigned long opt) |
1007 | { | 873 | { |
1008 | __u8 scan = opt; | 874 | __u8 scan = opt; |
1009 | 875 | ||
@@ -1011,9 +877,10 @@ static void hci_scan_req(struct hci_request *req, unsigned long opt) | |||
1011 | 877 | ||
1012 | /* Inquiry and Page scans */ | 878 | /* Inquiry and Page scans */ |
1013 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 879 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
880 | return 0; | ||
1014 | } | 881 | } |
1015 | 882 | ||
1016 | static void hci_auth_req(struct hci_request *req, unsigned long opt) | 883 | static int hci_auth_req(struct hci_request *req, unsigned long opt) |
1017 | { | 884 | { |
1018 | __u8 auth = opt; | 885 | __u8 auth = opt; |
1019 | 886 | ||
@@ -1021,9 +888,10 @@ static void hci_auth_req(struct hci_request *req, unsigned long opt) | |||
1021 | 888 | ||
1022 | /* Authentication */ | 889 | /* Authentication */ |
1023 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); | 890 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); |
891 | return 0; | ||
1024 | } | 892 | } |
1025 | 893 | ||
1026 | static void hci_encrypt_req(struct hci_request *req, unsigned long opt) | 894 | static int hci_encrypt_req(struct hci_request *req, unsigned long opt) |
1027 | { | 895 | { |
1028 | __u8 encrypt = opt; | 896 | __u8 encrypt = opt; |
1029 | 897 | ||
@@ -1031,9 +899,10 @@ static void hci_encrypt_req(struct hci_request *req, unsigned long opt) | |||
1031 | 899 | ||
1032 | /* Encryption */ | 900 | /* Encryption */ |
1033 | hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); | 901 | hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); |
902 | return 0; | ||
1034 | } | 903 | } |
1035 | 904 | ||
1036 | static void hci_linkpol_req(struct hci_request *req, unsigned long opt) | 905 | static int hci_linkpol_req(struct hci_request *req, unsigned long opt) |
1037 | { | 906 | { |
1038 | __le16 policy = cpu_to_le16(opt); | 907 | __le16 policy = cpu_to_le16(opt); |
1039 | 908 | ||
@@ -1041,6 +910,7 @@ static void hci_linkpol_req(struct hci_request *req, unsigned long opt) | |||
1041 | 910 | ||
1042 | /* Default link policy */ | 911 | /* Default link policy */ |
1043 | hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); | 912 | hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); |
913 | return 0; | ||
1044 | } | 914 | } |
1045 | 915 | ||
1046 | /* Get HCI device by index. | 916 | /* Get HCI device by index. |
@@ -1285,7 +1155,7 @@ static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf) | |||
1285 | return copied; | 1155 | return copied; |
1286 | } | 1156 | } |
1287 | 1157 | ||
1288 | static void hci_inq_req(struct hci_request *req, unsigned long opt) | 1158 | static int hci_inq_req(struct hci_request *req, unsigned long opt) |
1289 | { | 1159 | { |
1290 | struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt; | 1160 | struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt; |
1291 | struct hci_dev *hdev = req->hdev; | 1161 | struct hci_dev *hdev = req->hdev; |
@@ -1294,13 +1164,15 @@ static void hci_inq_req(struct hci_request *req, unsigned long opt) | |||
1294 | BT_DBG("%s", hdev->name); | 1164 | BT_DBG("%s", hdev->name); |
1295 | 1165 | ||
1296 | if (test_bit(HCI_INQUIRY, &hdev->flags)) | 1166 | if (test_bit(HCI_INQUIRY, &hdev->flags)) |
1297 | return; | 1167 | return 0; |
1298 | 1168 | ||
1299 | /* Start Inquiry */ | 1169 | /* Start Inquiry */ |
1300 | memcpy(&cp.lap, &ir->lap, 3); | 1170 | memcpy(&cp.lap, &ir->lap, 3); |
1301 | cp.length = ir->length; | 1171 | cp.length = ir->length; |
1302 | cp.num_rsp = ir->num_rsp; | 1172 | cp.num_rsp = ir->num_rsp; |
1303 | hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); | 1173 | hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); |
1174 | |||
1175 | return 0; | ||
1304 | } | 1176 | } |
1305 | 1177 | ||
1306 | int hci_inquiry(void __user *arg) | 1178 | int hci_inquiry(void __user *arg) |
@@ -1351,7 +1223,7 @@ int hci_inquiry(void __user *arg) | |||
1351 | 1223 | ||
1352 | if (do_inquiry) { | 1224 | if (do_inquiry) { |
1353 | err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir, | 1225 | err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir, |
1354 | timeo); | 1226 | timeo, NULL); |
1355 | if (err < 0) | 1227 | if (err < 0) |
1356 | goto done; | 1228 | goto done; |
1357 | 1229 | ||
@@ -1404,7 +1276,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
1404 | 1276 | ||
1405 | BT_DBG("%s %p", hdev->name, hdev); | 1277 | BT_DBG("%s %p", hdev->name, hdev); |
1406 | 1278 | ||
1407 | hci_req_lock(hdev); | 1279 | hci_req_sync_lock(hdev); |
1408 | 1280 | ||
1409 | if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) { | 1281 | if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) { |
1410 | ret = -ENODEV; | 1282 | ret = -ENODEV; |
@@ -1527,10 +1399,10 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
1527 | !hci_dev_test_flag(hdev, HCI_CONFIG) && | 1399 | !hci_dev_test_flag(hdev, HCI_CONFIG) && |
1528 | !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && | 1400 | !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && |
1529 | !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && | 1401 | !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && |
1402 | hci_dev_test_flag(hdev, HCI_MGMT) && | ||
1530 | hdev->dev_type == HCI_BREDR) { | 1403 | hdev->dev_type == HCI_BREDR) { |
1531 | hci_dev_lock(hdev); | 1404 | ret = __hci_req_hci_power_on(hdev); |
1532 | mgmt_powered(hdev, 1); | 1405 | mgmt_power_on(hdev, ret); |
1533 | hci_dev_unlock(hdev); | ||
1534 | } | 1406 | } |
1535 | } else { | 1407 | } else { |
1536 | /* Init failed, cleanup */ | 1408 | /* Init failed, cleanup */ |
@@ -1557,7 +1429,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
1557 | } | 1429 | } |
1558 | 1430 | ||
1559 | done: | 1431 | done: |
1560 | hci_req_unlock(hdev); | 1432 | hci_req_sync_unlock(hdev); |
1561 | return ret; | 1433 | return ret; |
1562 | } | 1434 | } |
1563 | 1435 | ||
@@ -1651,12 +1523,12 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1651 | 1523 | ||
1652 | cancel_delayed_work(&hdev->power_off); | 1524 | cancel_delayed_work(&hdev->power_off); |
1653 | 1525 | ||
1654 | hci_req_cancel(hdev, ENODEV); | 1526 | hci_request_cancel_all(hdev); |
1655 | hci_req_lock(hdev); | 1527 | hci_req_sync_lock(hdev); |
1656 | 1528 | ||
1657 | if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { | 1529 | if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { |
1658 | cancel_delayed_work_sync(&hdev->cmd_timer); | 1530 | cancel_delayed_work_sync(&hdev->cmd_timer); |
1659 | hci_req_unlock(hdev); | 1531 | hci_req_sync_unlock(hdev); |
1660 | return 0; | 1532 | return 0; |
1661 | } | 1533 | } |
1662 | 1534 | ||
@@ -1665,7 +1537,6 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1665 | flush_work(&hdev->rx_work); | 1537 | flush_work(&hdev->rx_work); |
1666 | 1538 | ||
1667 | if (hdev->discov_timeout > 0) { | 1539 | if (hdev->discov_timeout > 0) { |
1668 | cancel_delayed_work(&hdev->discov_off); | ||
1669 | hdev->discov_timeout = 0; | 1540 | hdev->discov_timeout = 0; |
1670 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); | 1541 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); |
1671 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | 1542 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); |
@@ -1674,17 +1545,9 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1674 | if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) | 1545 | if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) |
1675 | cancel_delayed_work(&hdev->service_cache); | 1546 | cancel_delayed_work(&hdev->service_cache); |
1676 | 1547 | ||
1677 | cancel_delayed_work_sync(&hdev->le_scan_disable); | ||
1678 | cancel_delayed_work_sync(&hdev->le_scan_restart); | ||
1679 | |||
1680 | if (hci_dev_test_flag(hdev, HCI_MGMT)) | 1548 | if (hci_dev_test_flag(hdev, HCI_MGMT)) |
1681 | cancel_delayed_work_sync(&hdev->rpa_expired); | 1549 | cancel_delayed_work_sync(&hdev->rpa_expired); |
1682 | 1550 | ||
1683 | if (hdev->adv_instance_timeout) { | ||
1684 | cancel_delayed_work_sync(&hdev->adv_instance_expire); | ||
1685 | hdev->adv_instance_timeout = 0; | ||
1686 | } | ||
1687 | |||
1688 | /* Avoid potential lockdep warnings from the *_flush() calls by | 1551 | /* Avoid potential lockdep warnings from the *_flush() calls by |
1689 | * ensuring the workqueue is empty up front. | 1552 | * ensuring the workqueue is empty up front. |
1690 | */ | 1553 | */ |
@@ -1696,8 +1559,9 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1696 | 1559 | ||
1697 | auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF); | 1560 | auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF); |
1698 | 1561 | ||
1699 | if (!auto_off && hdev->dev_type == HCI_BREDR) | 1562 | if (!auto_off && hdev->dev_type == HCI_BREDR && |
1700 | mgmt_powered(hdev, 0); | 1563 | hci_dev_test_flag(hdev, HCI_MGMT)) |
1564 | __mgmt_power_off(hdev); | ||
1701 | 1565 | ||
1702 | hci_inquiry_cache_flush(hdev); | 1566 | hci_inquiry_cache_flush(hdev); |
1703 | hci_pend_le_actions_clear(hdev); | 1567 | hci_pend_le_actions_clear(hdev); |
@@ -1717,7 +1581,7 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1717 | if (test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks) && | 1581 | if (test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks) && |
1718 | !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { | 1582 | !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { |
1719 | set_bit(HCI_INIT, &hdev->flags); | 1583 | set_bit(HCI_INIT, &hdev->flags); |
1720 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); | 1584 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT, NULL); |
1721 | clear_bit(HCI_INIT, &hdev->flags); | 1585 | clear_bit(HCI_INIT, &hdev->flags); |
1722 | } | 1586 | } |
1723 | 1587 | ||
@@ -1754,7 +1618,7 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1754 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); | 1618 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); |
1755 | bacpy(&hdev->random_addr, BDADDR_ANY); | 1619 | bacpy(&hdev->random_addr, BDADDR_ANY); |
1756 | 1620 | ||
1757 | hci_req_unlock(hdev); | 1621 | hci_req_sync_unlock(hdev); |
1758 | 1622 | ||
1759 | hci_dev_put(hdev); | 1623 | hci_dev_put(hdev); |
1760 | return 0; | 1624 | return 0; |
@@ -1790,7 +1654,7 @@ static int hci_dev_do_reset(struct hci_dev *hdev) | |||
1790 | 1654 | ||
1791 | BT_DBG("%s %p", hdev->name, hdev); | 1655 | BT_DBG("%s %p", hdev->name, hdev); |
1792 | 1656 | ||
1793 | hci_req_lock(hdev); | 1657 | hci_req_sync_lock(hdev); |
1794 | 1658 | ||
1795 | /* Drop queues */ | 1659 | /* Drop queues */ |
1796 | skb_queue_purge(&hdev->rx_q); | 1660 | skb_queue_purge(&hdev->rx_q); |
@@ -1812,9 +1676,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev) | |||
1812 | atomic_set(&hdev->cmd_cnt, 1); | 1676 | atomic_set(&hdev->cmd_cnt, 1); |
1813 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; | 1677 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; |
1814 | 1678 | ||
1815 | ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); | 1679 | ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT, NULL); |
1816 | 1680 | ||
1817 | hci_req_unlock(hdev); | 1681 | hci_req_sync_unlock(hdev); |
1818 | return ret; | 1682 | return ret; |
1819 | } | 1683 | } |
1820 | 1684 | ||
@@ -1905,7 +1769,7 @@ static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) | |||
1905 | hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); | 1769 | hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); |
1906 | 1770 | ||
1907 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | 1771 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) |
1908 | mgmt_update_adv_data(hdev); | 1772 | hci_req_update_adv_data(hdev, hdev->cur_adv_instance); |
1909 | 1773 | ||
1910 | mgmt_new_settings(hdev); | 1774 | mgmt_new_settings(hdev); |
1911 | } | 1775 | } |
@@ -1947,7 +1811,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
1947 | switch (cmd) { | 1811 | switch (cmd) { |
1948 | case HCISETAUTH: | 1812 | case HCISETAUTH: |
1949 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, | 1813 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, |
1950 | HCI_INIT_TIMEOUT); | 1814 | HCI_INIT_TIMEOUT, NULL); |
1951 | break; | 1815 | break; |
1952 | 1816 | ||
1953 | case HCISETENCRYPT: | 1817 | case HCISETENCRYPT: |
@@ -1959,18 +1823,18 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
1959 | if (!test_bit(HCI_AUTH, &hdev->flags)) { | 1823 | if (!test_bit(HCI_AUTH, &hdev->flags)) { |
1960 | /* Auth must be enabled first */ | 1824 | /* Auth must be enabled first */ |
1961 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, | 1825 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, |
1962 | HCI_INIT_TIMEOUT); | 1826 | HCI_INIT_TIMEOUT, NULL); |
1963 | if (err) | 1827 | if (err) |
1964 | break; | 1828 | break; |
1965 | } | 1829 | } |
1966 | 1830 | ||
1967 | err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt, | 1831 | err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt, |
1968 | HCI_INIT_TIMEOUT); | 1832 | HCI_INIT_TIMEOUT, NULL); |
1969 | break; | 1833 | break; |
1970 | 1834 | ||
1971 | case HCISETSCAN: | 1835 | case HCISETSCAN: |
1972 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, | 1836 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, |
1973 | HCI_INIT_TIMEOUT); | 1837 | HCI_INIT_TIMEOUT, NULL); |
1974 | 1838 | ||
1975 | /* Ensure that the connectable and discoverable states | 1839 | /* Ensure that the connectable and discoverable states |
1976 | * get correctly modified as this was a non-mgmt change. | 1840 | * get correctly modified as this was a non-mgmt change. |
@@ -1981,7 +1845,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
1981 | 1845 | ||
1982 | case HCISETLINKPOL: | 1846 | case HCISETLINKPOL: |
1983 | err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt, | 1847 | err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt, |
1984 | HCI_INIT_TIMEOUT); | 1848 | HCI_INIT_TIMEOUT, NULL); |
1985 | break; | 1849 | break; |
1986 | 1850 | ||
1987 | case HCISETLINKMODE: | 1851 | case HCISETLINKMODE: |
@@ -2150,6 +2014,16 @@ static void hci_power_on(struct work_struct *work) | |||
2150 | 2014 | ||
2151 | BT_DBG("%s", hdev->name); | 2015 | BT_DBG("%s", hdev->name); |
2152 | 2016 | ||
2017 | if (test_bit(HCI_UP, &hdev->flags) && | ||
2018 | hci_dev_test_flag(hdev, HCI_MGMT) && | ||
2019 | hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) { | ||
2020 | hci_req_sync_lock(hdev); | ||
2021 | err = __hci_req_hci_power_on(hdev); | ||
2022 | hci_req_sync_unlock(hdev); | ||
2023 | mgmt_power_on(hdev, err); | ||
2024 | return; | ||
2025 | } | ||
2026 | |||
2153 | err = hci_dev_do_open(hdev); | 2027 | err = hci_dev_do_open(hdev); |
2154 | if (err < 0) { | 2028 | if (err < 0) { |
2155 | hci_dev_lock(hdev); | 2029 | hci_dev_lock(hdev); |
@@ -2232,28 +2106,6 @@ static void hci_error_reset(struct work_struct *work) | |||
2232 | hci_dev_do_open(hdev); | 2106 | hci_dev_do_open(hdev); |
2233 | } | 2107 | } |
2234 | 2108 | ||
2235 | static void hci_discov_off(struct work_struct *work) | ||
2236 | { | ||
2237 | struct hci_dev *hdev; | ||
2238 | |||
2239 | hdev = container_of(work, struct hci_dev, discov_off.work); | ||
2240 | |||
2241 | BT_DBG("%s", hdev->name); | ||
2242 | |||
2243 | mgmt_discoverable_timeout(hdev); | ||
2244 | } | ||
2245 | |||
2246 | static void hci_adv_timeout_expire(struct work_struct *work) | ||
2247 | { | ||
2248 | struct hci_dev *hdev; | ||
2249 | |||
2250 | hdev = container_of(work, struct hci_dev, adv_instance_expire.work); | ||
2251 | |||
2252 | BT_DBG("%s", hdev->name); | ||
2253 | |||
2254 | mgmt_adv_timeout_expired(hdev); | ||
2255 | } | ||
2256 | |||
2257 | void hci_uuids_clear(struct hci_dev *hdev) | 2109 | void hci_uuids_clear(struct hci_dev *hdev) |
2258 | { | 2110 | { |
2259 | struct bt_uuid *uuid, *tmp; | 2111 | struct bt_uuid *uuid, *tmp; |
@@ -2731,7 +2583,8 @@ struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance) | |||
2731 | } | 2583 | } |
2732 | 2584 | ||
2733 | /* This function requires the caller holds hdev->lock */ | 2585 | /* This function requires the caller holds hdev->lock */ |
2734 | struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance) { | 2586 | struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance) |
2587 | { | ||
2735 | struct adv_info *cur_instance; | 2588 | struct adv_info *cur_instance; |
2736 | 2589 | ||
2737 | cur_instance = hci_find_adv_instance(hdev, instance); | 2590 | cur_instance = hci_find_adv_instance(hdev, instance); |
@@ -2757,9 +2610,12 @@ int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance) | |||
2757 | 2610 | ||
2758 | BT_DBG("%s removing %dMR", hdev->name, instance); | 2611 | BT_DBG("%s removing %dMR", hdev->name, instance); |
2759 | 2612 | ||
2760 | if (hdev->cur_adv_instance == instance && hdev->adv_instance_timeout) { | 2613 | if (hdev->cur_adv_instance == instance) { |
2761 | cancel_delayed_work(&hdev->adv_instance_expire); | 2614 | if (hdev->adv_instance_timeout) { |
2762 | hdev->adv_instance_timeout = 0; | 2615 | cancel_delayed_work(&hdev->adv_instance_expire); |
2616 | hdev->adv_instance_timeout = 0; | ||
2617 | } | ||
2618 | hdev->cur_adv_instance = 0x00; | ||
2763 | } | 2619 | } |
2764 | 2620 | ||
2765 | list_del(&adv_instance->list); | 2621 | list_del(&adv_instance->list); |
@@ -2786,6 +2642,7 @@ void hci_adv_instances_clear(struct hci_dev *hdev) | |||
2786 | } | 2642 | } |
2787 | 2643 | ||
2788 | hdev->adv_instance_cnt = 0; | 2644 | hdev->adv_instance_cnt = 0; |
2645 | hdev->cur_adv_instance = 0x00; | ||
2789 | } | 2646 | } |
2790 | 2647 | ||
2791 | /* This function requires the caller holds hdev->lock */ | 2648 | /* This function requires the caller holds hdev->lock */ |
@@ -2856,12 +2713,10 @@ struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list, | |||
2856 | 2713 | ||
2857 | void hci_bdaddr_list_clear(struct list_head *bdaddr_list) | 2714 | void hci_bdaddr_list_clear(struct list_head *bdaddr_list) |
2858 | { | 2715 | { |
2859 | struct list_head *p, *n; | 2716 | struct bdaddr_list *b, *n; |
2860 | 2717 | ||
2861 | list_for_each_safe(p, n, bdaddr_list) { | 2718 | list_for_each_entry_safe(b, n, bdaddr_list, list) { |
2862 | struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list); | 2719 | list_del(&b->list); |
2863 | |||
2864 | list_del(p); | ||
2865 | kfree(b); | 2720 | kfree(b); |
2866 | } | 2721 | } |
2867 | } | 2722 | } |
@@ -3024,181 +2879,16 @@ void hci_conn_params_clear_disabled(struct hci_dev *hdev) | |||
3024 | } | 2879 | } |
3025 | 2880 | ||
3026 | /* This function requires the caller holds hdev->lock */ | 2881 | /* This function requires the caller holds hdev->lock */ |
3027 | void hci_conn_params_clear_all(struct hci_dev *hdev) | 2882 | static void hci_conn_params_clear_all(struct hci_dev *hdev) |
3028 | { | 2883 | { |
3029 | struct hci_conn_params *params, *tmp; | 2884 | struct hci_conn_params *params, *tmp; |
3030 | 2885 | ||
3031 | list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) | 2886 | list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) |
3032 | hci_conn_params_free(params); | 2887 | hci_conn_params_free(params); |
3033 | 2888 | ||
3034 | hci_update_background_scan(hdev); | ||
3035 | |||
3036 | BT_DBG("All LE connection parameters were removed"); | 2889 | BT_DBG("All LE connection parameters were removed"); |
3037 | } | 2890 | } |
3038 | 2891 | ||
3039 | static void inquiry_complete(struct hci_dev *hdev, u8 status, u16 opcode) | ||
3040 | { | ||
3041 | if (status) { | ||
3042 | BT_ERR("Failed to start inquiry: status %d", status); | ||
3043 | |||
3044 | hci_dev_lock(hdev); | ||
3045 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
3046 | hci_dev_unlock(hdev); | ||
3047 | return; | ||
3048 | } | ||
3049 | } | ||
3050 | |||
3051 | static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status, | ||
3052 | u16 opcode) | ||
3053 | { | ||
3054 | /* General inquiry access code (GIAC) */ | ||
3055 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; | ||
3056 | struct hci_cp_inquiry cp; | ||
3057 | int err; | ||
3058 | |||
3059 | if (status) { | ||
3060 | BT_ERR("Failed to disable LE scanning: status %d", status); | ||
3061 | return; | ||
3062 | } | ||
3063 | |||
3064 | hdev->discovery.scan_start = 0; | ||
3065 | |||
3066 | switch (hdev->discovery.type) { | ||
3067 | case DISCOV_TYPE_LE: | ||
3068 | hci_dev_lock(hdev); | ||
3069 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
3070 | hci_dev_unlock(hdev); | ||
3071 | break; | ||
3072 | |||
3073 | case DISCOV_TYPE_INTERLEAVED: | ||
3074 | hci_dev_lock(hdev); | ||
3075 | |||
3076 | if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, | ||
3077 | &hdev->quirks)) { | ||
3078 | /* If we were running LE only scan, change discovery | ||
3079 | * state. If we were running both LE and BR/EDR inquiry | ||
3080 | * simultaneously, and BR/EDR inquiry is already | ||
3081 | * finished, stop discovery, otherwise BR/EDR inquiry | ||
3082 | * will stop discovery when finished. If we will resolve | ||
3083 | * remote device name, do not change discovery state. | ||
3084 | */ | ||
3085 | if (!test_bit(HCI_INQUIRY, &hdev->flags) && | ||
3086 | hdev->discovery.state != DISCOVERY_RESOLVING) | ||
3087 | hci_discovery_set_state(hdev, | ||
3088 | DISCOVERY_STOPPED); | ||
3089 | } else { | ||
3090 | struct hci_request req; | ||
3091 | |||
3092 | hci_inquiry_cache_flush(hdev); | ||
3093 | |||
3094 | hci_req_init(&req, hdev); | ||
3095 | |||
3096 | memset(&cp, 0, sizeof(cp)); | ||
3097 | memcpy(&cp.lap, lap, sizeof(cp.lap)); | ||
3098 | cp.length = DISCOV_INTERLEAVED_INQUIRY_LEN; | ||
3099 | hci_req_add(&req, HCI_OP_INQUIRY, sizeof(cp), &cp); | ||
3100 | |||
3101 | err = hci_req_run(&req, inquiry_complete); | ||
3102 | if (err) { | ||
3103 | BT_ERR("Inquiry request failed: err %d", err); | ||
3104 | hci_discovery_set_state(hdev, | ||
3105 | DISCOVERY_STOPPED); | ||
3106 | } | ||
3107 | } | ||
3108 | |||
3109 | hci_dev_unlock(hdev); | ||
3110 | break; | ||
3111 | } | ||
3112 | } | ||
3113 | |||
3114 | static void le_scan_disable_work(struct work_struct *work) | ||
3115 | { | ||
3116 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
3117 | le_scan_disable.work); | ||
3118 | struct hci_request req; | ||
3119 | int err; | ||
3120 | |||
3121 | BT_DBG("%s", hdev->name); | ||
3122 | |||
3123 | cancel_delayed_work_sync(&hdev->le_scan_restart); | ||
3124 | |||
3125 | hci_req_init(&req, hdev); | ||
3126 | |||
3127 | hci_req_add_le_scan_disable(&req); | ||
3128 | |||
3129 | err = hci_req_run(&req, le_scan_disable_work_complete); | ||
3130 | if (err) | ||
3131 | BT_ERR("Disable LE scanning request failed: err %d", err); | ||
3132 | } | ||
3133 | |||
3134 | static void le_scan_restart_work_complete(struct hci_dev *hdev, u8 status, | ||
3135 | u16 opcode) | ||
3136 | { | ||
3137 | unsigned long timeout, duration, scan_start, now; | ||
3138 | |||
3139 | BT_DBG("%s", hdev->name); | ||
3140 | |||
3141 | if (status) { | ||
3142 | BT_ERR("Failed to restart LE scan: status %d", status); | ||
3143 | return; | ||
3144 | } | ||
3145 | |||
3146 | if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || | ||
3147 | !hdev->discovery.scan_start) | ||
3148 | return; | ||
3149 | |||
3150 | /* When the scan was started, hdev->le_scan_disable has been queued | ||
3151 | * after duration from scan_start. During scan restart this job | ||
3152 | * has been canceled, and we need to queue it again after proper | ||
3153 | * timeout, to make sure that scan does not run indefinitely. | ||
3154 | */ | ||
3155 | duration = hdev->discovery.scan_duration; | ||
3156 | scan_start = hdev->discovery.scan_start; | ||
3157 | now = jiffies; | ||
3158 | if (now - scan_start <= duration) { | ||
3159 | int elapsed; | ||
3160 | |||
3161 | if (now >= scan_start) | ||
3162 | elapsed = now - scan_start; | ||
3163 | else | ||
3164 | elapsed = ULONG_MAX - scan_start + now; | ||
3165 | |||
3166 | timeout = duration - elapsed; | ||
3167 | } else { | ||
3168 | timeout = 0; | ||
3169 | } | ||
3170 | queue_delayed_work(hdev->workqueue, | ||
3171 | &hdev->le_scan_disable, timeout); | ||
3172 | } | ||
3173 | |||
3174 | static void le_scan_restart_work(struct work_struct *work) | ||
3175 | { | ||
3176 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
3177 | le_scan_restart.work); | ||
3178 | struct hci_request req; | ||
3179 | struct hci_cp_le_set_scan_enable cp; | ||
3180 | int err; | ||
3181 | |||
3182 | BT_DBG("%s", hdev->name); | ||
3183 | |||
3184 | /* If controller is not scanning we are done. */ | ||
3185 | if (!hci_dev_test_flag(hdev, HCI_LE_SCAN)) | ||
3186 | return; | ||
3187 | |||
3188 | hci_req_init(&req, hdev); | ||
3189 | |||
3190 | hci_req_add_le_scan_disable(&req); | ||
3191 | |||
3192 | memset(&cp, 0, sizeof(cp)); | ||
3193 | cp.enable = LE_SCAN_ENABLE; | ||
3194 | cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; | ||
3195 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | ||
3196 | |||
3197 | err = hci_req_run(&req, le_scan_restart_work_complete); | ||
3198 | if (err) | ||
3199 | BT_ERR("Restart LE scan request failed: err %d", err); | ||
3200 | } | ||
3201 | |||
3202 | /* Copy the Identity Address of the controller. | 2892 | /* Copy the Identity Address of the controller. |
3203 | * | 2893 | * |
3204 | * If the controller has a public BD_ADDR, then by default use that one. | 2894 | * If the controller has a public BD_ADDR, then by default use that one. |
@@ -3297,10 +2987,6 @@ struct hci_dev *hci_alloc_dev(void) | |||
3297 | INIT_WORK(&hdev->error_reset, hci_error_reset); | 2987 | INIT_WORK(&hdev->error_reset, hci_error_reset); |
3298 | 2988 | ||
3299 | INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); | 2989 | INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); |
3300 | INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off); | ||
3301 | INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work); | ||
3302 | INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work); | ||
3303 | INIT_DELAYED_WORK(&hdev->adv_instance_expire, hci_adv_timeout_expire); | ||
3304 | 2990 | ||
3305 | skb_queue_head_init(&hdev->rx_q); | 2991 | skb_queue_head_init(&hdev->rx_q); |
3306 | skb_queue_head_init(&hdev->cmd_q); | 2992 | skb_queue_head_init(&hdev->cmd_q); |
@@ -3310,6 +2996,8 @@ struct hci_dev *hci_alloc_dev(void) | |||
3310 | 2996 | ||
3311 | INIT_DELAYED_WORK(&hdev->cmd_timer, hci_cmd_timeout); | 2997 | INIT_DELAYED_WORK(&hdev->cmd_timer, hci_cmd_timeout); |
3312 | 2998 | ||
2999 | hci_request_setup(hdev); | ||
3000 | |||
3313 | hci_init_sysfs(hdev); | 3001 | hci_init_sysfs(hdev); |
3314 | discovery_init(hdev); | 3002 | discovery_init(hdev); |
3315 | 3003 | ||
@@ -3520,7 +3208,7 @@ int hci_reset_dev(struct hci_dev *hdev) | |||
3520 | if (!skb) | 3208 | if (!skb) |
3521 | return -ENOMEM; | 3209 | return -ENOMEM; |
3522 | 3210 | ||
3523 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; | 3211 | hci_skb_pkt_type(skb) = HCI_EVENT_PKT; |
3524 | memcpy(skb_put(skb, 3), hw_err, 3); | 3212 | memcpy(skb_put(skb, 3), hw_err, 3); |
3525 | 3213 | ||
3526 | /* Send Hardware Error to upper stack */ | 3214 | /* Send Hardware Error to upper stack */ |
@@ -3537,9 +3225,9 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
3537 | return -ENXIO; | 3225 | return -ENXIO; |
3538 | } | 3226 | } |
3539 | 3227 | ||
3540 | if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT && | 3228 | if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT && |
3541 | bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && | 3229 | hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
3542 | bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) { | 3230 | hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { |
3543 | kfree_skb(skb); | 3231 | kfree_skb(skb); |
3544 | return -EINVAL; | 3232 | return -EINVAL; |
3545 | } | 3233 | } |
@@ -3561,7 +3249,7 @@ EXPORT_SYMBOL(hci_recv_frame); | |||
3561 | int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb) | 3249 | int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb) |
3562 | { | 3250 | { |
3563 | /* Mark as diagnostic packet */ | 3251 | /* Mark as diagnostic packet */ |
3564 | bt_cb(skb)->pkt_type = HCI_DIAG_PKT; | 3252 | hci_skb_pkt_type(skb) = HCI_DIAG_PKT; |
3565 | 3253 | ||
3566 | /* Time stamp */ | 3254 | /* Time stamp */ |
3567 | __net_timestamp(skb); | 3255 | __net_timestamp(skb); |
@@ -3603,7 +3291,8 @@ static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
3603 | { | 3291 | { |
3604 | int err; | 3292 | int err; |
3605 | 3293 | ||
3606 | BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); | 3294 | BT_DBG("%s type %d len %d", hdev->name, hci_skb_pkt_type(skb), |
3295 | skb->len); | ||
3607 | 3296 | ||
3608 | /* Time stamp */ | 3297 | /* Time stamp */ |
3609 | __net_timestamp(skb); | 3298 | __net_timestamp(skb); |
@@ -3648,7 +3337,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, | |||
3648 | /* Stand-alone HCI commands must be flagged as | 3337 | /* Stand-alone HCI commands must be flagged as |
3649 | * single-command requests. | 3338 | * single-command requests. |
3650 | */ | 3339 | */ |
3651 | bt_cb(skb)->hci.req_start = true; | 3340 | bt_cb(skb)->hci.req_flags |= HCI_REQ_START; |
3652 | 3341 | ||
3653 | skb_queue_tail(&hdev->cmd_q, skb); | 3342 | skb_queue_tail(&hdev->cmd_q, skb); |
3654 | queue_work(hdev->workqueue, &hdev->cmd_work); | 3343 | queue_work(hdev->workqueue, &hdev->cmd_work); |
@@ -3685,9 +3374,9 @@ struct sk_buff *hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, | |||
3685 | 3374 | ||
3686 | bt_dev_dbg(hdev, "opcode 0x%4.4x plen %d", opcode, plen); | 3375 | bt_dev_dbg(hdev, "opcode 0x%4.4x plen %d", opcode, plen); |
3687 | 3376 | ||
3688 | hci_req_lock(hdev); | 3377 | hci_req_sync_lock(hdev); |
3689 | skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout); | 3378 | skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout); |
3690 | hci_req_unlock(hdev); | 3379 | hci_req_sync_unlock(hdev); |
3691 | 3380 | ||
3692 | return skb; | 3381 | return skb; |
3693 | } | 3382 | } |
@@ -3716,7 +3405,7 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, | |||
3716 | skb->len = skb_headlen(skb); | 3405 | skb->len = skb_headlen(skb); |
3717 | skb->data_len = 0; | 3406 | skb->data_len = 0; |
3718 | 3407 | ||
3719 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; | 3408 | hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT; |
3720 | 3409 | ||
3721 | switch (hdev->dev_type) { | 3410 | switch (hdev->dev_type) { |
3722 | case HCI_BREDR: | 3411 | case HCI_BREDR: |
@@ -3756,7 +3445,7 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, | |||
3756 | do { | 3445 | do { |
3757 | skb = list; list = list->next; | 3446 | skb = list; list = list->next; |
3758 | 3447 | ||
3759 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; | 3448 | hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT; |
3760 | hci_add_acl_hdr(skb, conn->handle, flags); | 3449 | hci_add_acl_hdr(skb, conn->handle, flags); |
3761 | 3450 | ||
3762 | BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); | 3451 | BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); |
@@ -3794,7 +3483,7 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) | |||
3794 | skb_reset_transport_header(skb); | 3483 | skb_reset_transport_header(skb); |
3795 | memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE); | 3484 | memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE); |
3796 | 3485 | ||
3797 | bt_cb(skb)->pkt_type = HCI_SCODATA_PKT; | 3486 | hci_skb_pkt_type(skb) = HCI_SCODATA_PKT; |
3798 | 3487 | ||
3799 | skb_queue_tail(&conn->data_q, skb); | 3488 | skb_queue_tail(&conn->data_q, skb); |
3800 | queue_work(hdev->workqueue, &hdev->tx_work); | 3489 | queue_work(hdev->workqueue, &hdev->tx_work); |
@@ -4345,7 +4034,7 @@ static bool hci_req_is_complete(struct hci_dev *hdev) | |||
4345 | if (!skb) | 4034 | if (!skb) |
4346 | return true; | 4035 | return true; |
4347 | 4036 | ||
4348 | return bt_cb(skb)->hci.req_start; | 4037 | return (bt_cb(skb)->hci.req_flags & HCI_REQ_START); |
4349 | } | 4038 | } |
4350 | 4039 | ||
4351 | static void hci_resend_last(struct hci_dev *hdev) | 4040 | static void hci_resend_last(struct hci_dev *hdev) |
@@ -4405,20 +4094,20 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, | |||
4405 | * callback would be found in hdev->sent_cmd instead of the | 4094 | * callback would be found in hdev->sent_cmd instead of the |
4406 | * command queue (hdev->cmd_q). | 4095 | * command queue (hdev->cmd_q). |
4407 | */ | 4096 | */ |
4408 | if (bt_cb(hdev->sent_cmd)->hci.req_complete) { | 4097 | if (bt_cb(hdev->sent_cmd)->hci.req_flags & HCI_REQ_SKB) { |
4409 | *req_complete = bt_cb(hdev->sent_cmd)->hci.req_complete; | 4098 | *req_complete_skb = bt_cb(hdev->sent_cmd)->hci.req_complete_skb; |
4410 | return; | 4099 | return; |
4411 | } | 4100 | } |
4412 | 4101 | ||
4413 | if (bt_cb(hdev->sent_cmd)->hci.req_complete_skb) { | 4102 | if (bt_cb(hdev->sent_cmd)->hci.req_complete) { |
4414 | *req_complete_skb = bt_cb(hdev->sent_cmd)->hci.req_complete_skb; | 4103 | *req_complete = bt_cb(hdev->sent_cmd)->hci.req_complete; |
4415 | return; | 4104 | return; |
4416 | } | 4105 | } |
4417 | 4106 | ||
4418 | /* Remove all pending commands belonging to this request */ | 4107 | /* Remove all pending commands belonging to this request */ |
4419 | spin_lock_irqsave(&hdev->cmd_q.lock, flags); | 4108 | spin_lock_irqsave(&hdev->cmd_q.lock, flags); |
4420 | while ((skb = __skb_dequeue(&hdev->cmd_q))) { | 4109 | while ((skb = __skb_dequeue(&hdev->cmd_q))) { |
4421 | if (bt_cb(skb)->hci.req_start) { | 4110 | if (bt_cb(skb)->hci.req_flags & HCI_REQ_START) { |
4422 | __skb_queue_head(&hdev->cmd_q, skb); | 4111 | __skb_queue_head(&hdev->cmd_q, skb); |
4423 | break; | 4112 | break; |
4424 | } | 4113 | } |
@@ -4453,7 +4142,7 @@ static void hci_rx_work(struct work_struct *work) | |||
4453 | 4142 | ||
4454 | if (test_bit(HCI_INIT, &hdev->flags)) { | 4143 | if (test_bit(HCI_INIT, &hdev->flags)) { |
4455 | /* Don't process data packets in this states. */ | 4144 | /* Don't process data packets in this states. */ |
4456 | switch (bt_cb(skb)->pkt_type) { | 4145 | switch (hci_skb_pkt_type(skb)) { |
4457 | case HCI_ACLDATA_PKT: | 4146 | case HCI_ACLDATA_PKT: |
4458 | case HCI_SCODATA_PKT: | 4147 | case HCI_SCODATA_PKT: |
4459 | kfree_skb(skb); | 4148 | kfree_skb(skb); |
@@ -4462,7 +4151,7 @@ static void hci_rx_work(struct work_struct *work) | |||
4462 | } | 4151 | } |
4463 | 4152 | ||
4464 | /* Process frame */ | 4153 | /* Process frame */ |
4465 | switch (bt_cb(skb)->pkt_type) { | 4154 | switch (hci_skb_pkt_type(skb)) { |
4466 | case HCI_EVENT_PKT: | 4155 | case HCI_EVENT_PKT: |
4467 | BT_DBG("%s Event packet", hdev->name); | 4156 | BT_DBG("%s Event packet", hdev->name); |
4468 | hci_event_packet(hdev, skb); | 4157 | hci_event_packet(hdev, skb); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d57c11c1c6b5..c162af5d16bf 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1183,7 +1183,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1183 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | 1183 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); |
1184 | else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) && | 1184 | else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) && |
1185 | hdev->discovery.state == DISCOVERY_FINDING) | 1185 | hdev->discovery.state == DISCOVERY_FINDING) |
1186 | mgmt_reenable_advertising(hdev); | 1186 | hci_req_reenable_advertising(hdev); |
1187 | 1187 | ||
1188 | break; | 1188 | break; |
1189 | 1189 | ||
@@ -2176,7 +2176,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2176 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, | 2176 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, |
2177 | sizeof(cp), &cp); | 2177 | sizeof(cp), &cp); |
2178 | 2178 | ||
2179 | hci_update_page_scan(hdev); | 2179 | hci_req_update_scan(hdev); |
2180 | } | 2180 | } |
2181 | 2181 | ||
2182 | /* Set packet type for incoming connection */ | 2182 | /* Set packet type for incoming connection */ |
@@ -2362,7 +2362,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2362 | if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) | 2362 | if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) |
2363 | hci_remove_link_key(hdev, &conn->dst); | 2363 | hci_remove_link_key(hdev, &conn->dst); |
2364 | 2364 | ||
2365 | hci_update_page_scan(hdev); | 2365 | hci_req_update_scan(hdev); |
2366 | } | 2366 | } |
2367 | 2367 | ||
2368 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); | 2368 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); |
@@ -2401,7 +2401,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2401 | * is timed out due to Directed Advertising." | 2401 | * is timed out due to Directed Advertising." |
2402 | */ | 2402 | */ |
2403 | if (type == LE_LINK) | 2403 | if (type == LE_LINK) |
2404 | mgmt_reenable_advertising(hdev); | 2404 | hci_req_reenable_advertising(hdev); |
2405 | 2405 | ||
2406 | unlock: | 2406 | unlock: |
2407 | hci_dev_unlock(hdev); | 2407 | hci_dev_unlock(hdev); |
@@ -3833,9 +3833,9 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, | |||
3833 | data.ssp_mode = 0x01; | 3833 | data.ssp_mode = 0x01; |
3834 | 3834 | ||
3835 | if (hci_dev_test_flag(hdev, HCI_MGMT)) | 3835 | if (hci_dev_test_flag(hdev, HCI_MGMT)) |
3836 | name_known = eir_has_data_type(info->data, | 3836 | name_known = eir_get_data(info->data, |
3837 | sizeof(info->data), | 3837 | sizeof(info->data), |
3838 | EIR_NAME_COMPLETE); | 3838 | EIR_NAME_COMPLETE, NULL); |
3839 | else | 3839 | else |
3840 | name_known = true; | 3840 | name_known = true; |
3841 | 3841 | ||
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 981f8a202c27..41b5f3813f02 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -21,12 +21,19 @@ | |||
21 | SOFTWARE IS DISCLAIMED. | 21 | SOFTWARE IS DISCLAIMED. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <asm/unaligned.h> | ||
25 | |||
24 | #include <net/bluetooth/bluetooth.h> | 26 | #include <net/bluetooth/bluetooth.h> |
25 | #include <net/bluetooth/hci_core.h> | 27 | #include <net/bluetooth/hci_core.h> |
28 | #include <net/bluetooth/mgmt.h> | ||
26 | 29 | ||
27 | #include "smp.h" | 30 | #include "smp.h" |
28 | #include "hci_request.h" | 31 | #include "hci_request.h" |
29 | 32 | ||
33 | #define HCI_REQ_DONE 0 | ||
34 | #define HCI_REQ_PEND 1 | ||
35 | #define HCI_REQ_CANCELED 2 | ||
36 | |||
30 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev) | 37 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev) |
31 | { | 38 | { |
32 | skb_queue_head_init(&req->cmd_q); | 39 | skb_queue_head_init(&req->cmd_q); |
@@ -56,8 +63,12 @@ static int req_run(struct hci_request *req, hci_req_complete_t complete, | |||
56 | return -ENODATA; | 63 | return -ENODATA; |
57 | 64 | ||
58 | skb = skb_peek_tail(&req->cmd_q); | 65 | skb = skb_peek_tail(&req->cmd_q); |
59 | bt_cb(skb)->hci.req_complete = complete; | 66 | if (complete) { |
60 | bt_cb(skb)->hci.req_complete_skb = complete_skb; | 67 | bt_cb(skb)->hci.req_complete = complete; |
68 | } else if (complete_skb) { | ||
69 | bt_cb(skb)->hci.req_complete_skb = complete_skb; | ||
70 | bt_cb(skb)->hci.req_flags |= HCI_REQ_SKB; | ||
71 | } | ||
61 | 72 | ||
62 | spin_lock_irqsave(&hdev->cmd_q.lock, flags); | 73 | spin_lock_irqsave(&hdev->cmd_q.lock, flags); |
63 | skb_queue_splice_tail(&req->cmd_q, &hdev->cmd_q); | 74 | skb_queue_splice_tail(&req->cmd_q, &hdev->cmd_q); |
@@ -78,6 +89,203 @@ int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete) | |||
78 | return req_run(req, NULL, complete); | 89 | return req_run(req, NULL, complete); |
79 | } | 90 | } |
80 | 91 | ||
92 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode, | ||
93 | struct sk_buff *skb) | ||
94 | { | ||
95 | BT_DBG("%s result 0x%2.2x", hdev->name, result); | ||
96 | |||
97 | if (hdev->req_status == HCI_REQ_PEND) { | ||
98 | hdev->req_result = result; | ||
99 | hdev->req_status = HCI_REQ_DONE; | ||
100 | if (skb) | ||
101 | hdev->req_skb = skb_get(skb); | ||
102 | wake_up_interruptible(&hdev->req_wait_q); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | void hci_req_sync_cancel(struct hci_dev *hdev, int err) | ||
107 | { | ||
108 | BT_DBG("%s err 0x%2.2x", hdev->name, err); | ||
109 | |||
110 | if (hdev->req_status == HCI_REQ_PEND) { | ||
111 | hdev->req_result = err; | ||
112 | hdev->req_status = HCI_REQ_CANCELED; | ||
113 | wake_up_interruptible(&hdev->req_wait_q); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, | ||
118 | const void *param, u8 event, u32 timeout) | ||
119 | { | ||
120 | DECLARE_WAITQUEUE(wait, current); | ||
121 | struct hci_request req; | ||
122 | struct sk_buff *skb; | ||
123 | int err = 0; | ||
124 | |||
125 | BT_DBG("%s", hdev->name); | ||
126 | |||
127 | hci_req_init(&req, hdev); | ||
128 | |||
129 | hci_req_add_ev(&req, opcode, plen, param, event); | ||
130 | |||
131 | hdev->req_status = HCI_REQ_PEND; | ||
132 | |||
133 | add_wait_queue(&hdev->req_wait_q, &wait); | ||
134 | set_current_state(TASK_INTERRUPTIBLE); | ||
135 | |||
136 | err = hci_req_run_skb(&req, hci_req_sync_complete); | ||
137 | if (err < 0) { | ||
138 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
139 | set_current_state(TASK_RUNNING); | ||
140 | return ERR_PTR(err); | ||
141 | } | ||
142 | |||
143 | schedule_timeout(timeout); | ||
144 | |||
145 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
146 | |||
147 | if (signal_pending(current)) | ||
148 | return ERR_PTR(-EINTR); | ||
149 | |||
150 | switch (hdev->req_status) { | ||
151 | case HCI_REQ_DONE: | ||
152 | err = -bt_to_errno(hdev->req_result); | ||
153 | break; | ||
154 | |||
155 | case HCI_REQ_CANCELED: | ||
156 | err = -hdev->req_result; | ||
157 | break; | ||
158 | |||
159 | default: | ||
160 | err = -ETIMEDOUT; | ||
161 | break; | ||
162 | } | ||
163 | |||
164 | hdev->req_status = hdev->req_result = 0; | ||
165 | skb = hdev->req_skb; | ||
166 | hdev->req_skb = NULL; | ||
167 | |||
168 | BT_DBG("%s end: err %d", hdev->name, err); | ||
169 | |||
170 | if (err < 0) { | ||
171 | kfree_skb(skb); | ||
172 | return ERR_PTR(err); | ||
173 | } | ||
174 | |||
175 | if (!skb) | ||
176 | return ERR_PTR(-ENODATA); | ||
177 | |||
178 | return skb; | ||
179 | } | ||
180 | EXPORT_SYMBOL(__hci_cmd_sync_ev); | ||
181 | |||
182 | struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, | ||
183 | const void *param, u32 timeout) | ||
184 | { | ||
185 | return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout); | ||
186 | } | ||
187 | EXPORT_SYMBOL(__hci_cmd_sync); | ||
188 | |||
189 | /* Execute request and wait for completion. */ | ||
190 | int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req, | ||
191 | unsigned long opt), | ||
192 | unsigned long opt, u32 timeout, u8 *hci_status) | ||
193 | { | ||
194 | struct hci_request req; | ||
195 | DECLARE_WAITQUEUE(wait, current); | ||
196 | int err = 0; | ||
197 | |||
198 | BT_DBG("%s start", hdev->name); | ||
199 | |||
200 | hci_req_init(&req, hdev); | ||
201 | |||
202 | hdev->req_status = HCI_REQ_PEND; | ||
203 | |||
204 | err = func(&req, opt); | ||
205 | if (err) { | ||
206 | if (hci_status) | ||
207 | *hci_status = HCI_ERROR_UNSPECIFIED; | ||
208 | return err; | ||
209 | } | ||
210 | |||
211 | add_wait_queue(&hdev->req_wait_q, &wait); | ||
212 | set_current_state(TASK_INTERRUPTIBLE); | ||
213 | |||
214 | err = hci_req_run_skb(&req, hci_req_sync_complete); | ||
215 | if (err < 0) { | ||
216 | hdev->req_status = 0; | ||
217 | |||
218 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
219 | set_current_state(TASK_RUNNING); | ||
220 | |||
221 | /* ENODATA means the HCI request command queue is empty. | ||
222 | * This can happen when a request with conditionals doesn't | ||
223 | * trigger any commands to be sent. This is normal behavior | ||
224 | * and should not trigger an error return. | ||
225 | */ | ||
226 | if (err == -ENODATA) { | ||
227 | if (hci_status) | ||
228 | *hci_status = 0; | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | if (hci_status) | ||
233 | *hci_status = HCI_ERROR_UNSPECIFIED; | ||
234 | |||
235 | return err; | ||
236 | } | ||
237 | |||
238 | schedule_timeout(timeout); | ||
239 | |||
240 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
241 | |||
242 | if (signal_pending(current)) | ||
243 | return -EINTR; | ||
244 | |||
245 | switch (hdev->req_status) { | ||
246 | case HCI_REQ_DONE: | ||
247 | err = -bt_to_errno(hdev->req_result); | ||
248 | if (hci_status) | ||
249 | *hci_status = hdev->req_result; | ||
250 | break; | ||
251 | |||
252 | case HCI_REQ_CANCELED: | ||
253 | err = -hdev->req_result; | ||
254 | if (hci_status) | ||
255 | *hci_status = HCI_ERROR_UNSPECIFIED; | ||
256 | break; | ||
257 | |||
258 | default: | ||
259 | err = -ETIMEDOUT; | ||
260 | if (hci_status) | ||
261 | *hci_status = HCI_ERROR_UNSPECIFIED; | ||
262 | break; | ||
263 | } | ||
264 | |||
265 | hdev->req_status = hdev->req_result = 0; | ||
266 | |||
267 | BT_DBG("%s end: err %d", hdev->name, err); | ||
268 | |||
269 | return err; | ||
270 | } | ||
271 | |||
272 | int hci_req_sync(struct hci_dev *hdev, int (*req)(struct hci_request *req, | ||
273 | unsigned long opt), | ||
274 | unsigned long opt, u32 timeout, u8 *hci_status) | ||
275 | { | ||
276 | int ret; | ||
277 | |||
278 | if (!test_bit(HCI_UP, &hdev->flags)) | ||
279 | return -ENETDOWN; | ||
280 | |||
281 | /* Serialize all requests */ | ||
282 | hci_req_sync_lock(hdev); | ||
283 | ret = __hci_req_sync(hdev, req, opt, timeout, hci_status); | ||
284 | hci_req_sync_unlock(hdev); | ||
285 | |||
286 | return ret; | ||
287 | } | ||
288 | |||
81 | struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, | 289 | struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, |
82 | const void *param) | 290 | const void *param) |
83 | { | 291 | { |
@@ -98,8 +306,8 @@ struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, | |||
98 | 306 | ||
99 | BT_DBG("skb len %d", skb->len); | 307 | BT_DBG("skb len %d", skb->len); |
100 | 308 | ||
101 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; | 309 | hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; |
102 | bt_cb(skb)->hci.opcode = opcode; | 310 | hci_skb_opcode(skb) = opcode; |
103 | 311 | ||
104 | return skb; | 312 | return skb; |
105 | } | 313 | } |
@@ -128,7 +336,7 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, | |||
128 | } | 336 | } |
129 | 337 | ||
130 | if (skb_queue_empty(&req->cmd_q)) | 338 | if (skb_queue_empty(&req->cmd_q)) |
131 | bt_cb(skb)->hci.req_start = true; | 339 | bt_cb(skb)->hci.req_flags |= HCI_REQ_START; |
132 | 340 | ||
133 | bt_cb(skb)->hci.req_event = event; | 341 | bt_cb(skb)->hci.req_event = event; |
134 | 342 | ||
@@ -141,6 +349,311 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, | |||
141 | hci_req_add_ev(req, opcode, plen, param, 0); | 349 | hci_req_add_ev(req, opcode, plen, param, 0); |
142 | } | 350 | } |
143 | 351 | ||
352 | void __hci_req_write_fast_connectable(struct hci_request *req, bool enable) | ||
353 | { | ||
354 | struct hci_dev *hdev = req->hdev; | ||
355 | struct hci_cp_write_page_scan_activity acp; | ||
356 | u8 type; | ||
357 | |||
358 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
359 | return; | ||
360 | |||
361 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
362 | return; | ||
363 | |||
364 | if (enable) { | ||
365 | type = PAGE_SCAN_TYPE_INTERLACED; | ||
366 | |||
367 | /* 160 msec page scan interval */ | ||
368 | acp.interval = cpu_to_le16(0x0100); | ||
369 | } else { | ||
370 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | ||
371 | |||
372 | /* default 1.28 sec page scan */ | ||
373 | acp.interval = cpu_to_le16(0x0800); | ||
374 | } | ||
375 | |||
376 | acp.window = cpu_to_le16(0x0012); | ||
377 | |||
378 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || | ||
379 | __cpu_to_le16(hdev->page_scan_window) != acp.window) | ||
380 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, | ||
381 | sizeof(acp), &acp); | ||
382 | |||
383 | if (hdev->page_scan_type != type) | ||
384 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | ||
385 | } | ||
386 | |||
387 | /* This function controls the background scanning based on hdev->pend_le_conns | ||
388 | * list. If there are pending LE connection we start the background scanning, | ||
389 | * otherwise we stop it. | ||
390 | * | ||
391 | * This function requires the caller holds hdev->lock. | ||
392 | */ | ||
393 | static void __hci_update_background_scan(struct hci_request *req) | ||
394 | { | ||
395 | struct hci_dev *hdev = req->hdev; | ||
396 | |||
397 | if (!test_bit(HCI_UP, &hdev->flags) || | ||
398 | test_bit(HCI_INIT, &hdev->flags) || | ||
399 | hci_dev_test_flag(hdev, HCI_SETUP) || | ||
400 | hci_dev_test_flag(hdev, HCI_CONFIG) || | ||
401 | hci_dev_test_flag(hdev, HCI_AUTO_OFF) || | ||
402 | hci_dev_test_flag(hdev, HCI_UNREGISTER)) | ||
403 | return; | ||
404 | |||
405 | /* No point in doing scanning if LE support hasn't been enabled */ | ||
406 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
407 | return; | ||
408 | |||
409 | /* If discovery is active don't interfere with it */ | ||
410 | if (hdev->discovery.state != DISCOVERY_STOPPED) | ||
411 | return; | ||
412 | |||
413 | /* Reset RSSI and UUID filters when starting background scanning | ||
414 | * since these filters are meant for service discovery only. | ||
415 | * | ||
416 | * The Start Discovery and Start Service Discovery operations | ||
417 | * ensure to set proper values for RSSI threshold and UUID | ||
418 | * filter list. So it is safe to just reset them here. | ||
419 | */ | ||
420 | hci_discovery_filter_clear(hdev); | ||
421 | |||
422 | if (list_empty(&hdev->pend_le_conns) && | ||
423 | list_empty(&hdev->pend_le_reports)) { | ||
424 | /* If there is no pending LE connections or devices | ||
425 | * to be scanned for, we should stop the background | ||
426 | * scanning. | ||
427 | */ | ||
428 | |||
429 | /* If controller is not scanning we are done. */ | ||
430 | if (!hci_dev_test_flag(hdev, HCI_LE_SCAN)) | ||
431 | return; | ||
432 | |||
433 | hci_req_add_le_scan_disable(req); | ||
434 | |||
435 | BT_DBG("%s stopping background scanning", hdev->name); | ||
436 | } else { | ||
437 | /* If there is at least one pending LE connection, we should | ||
438 | * keep the background scan running. | ||
439 | */ | ||
440 | |||
441 | /* If controller is connecting, we should not start scanning | ||
442 | * since some controllers are not able to scan and connect at | ||
443 | * the same time. | ||
444 | */ | ||
445 | if (hci_lookup_le_connect(hdev)) | ||
446 | return; | ||
447 | |||
448 | /* If controller is currently scanning, we stop it to ensure we | ||
449 | * don't miss any advertising (due to duplicates filter). | ||
450 | */ | ||
451 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) | ||
452 | hci_req_add_le_scan_disable(req); | ||
453 | |||
454 | hci_req_add_le_passive_scan(req); | ||
455 | |||
456 | BT_DBG("%s starting background scanning", hdev->name); | ||
457 | } | ||
458 | } | ||
459 | |||
460 | void __hci_req_update_name(struct hci_request *req) | ||
461 | { | ||
462 | struct hci_dev *hdev = req->hdev; | ||
463 | struct hci_cp_write_local_name cp; | ||
464 | |||
465 | memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); | ||
466 | |||
467 | hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); | ||
468 | } | ||
469 | |||
470 | #define PNP_INFO_SVCLASS_ID 0x1200 | ||
471 | |||
472 | static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
473 | { | ||
474 | u8 *ptr = data, *uuids_start = NULL; | ||
475 | struct bt_uuid *uuid; | ||
476 | |||
477 | if (len < 4) | ||
478 | return ptr; | ||
479 | |||
480 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
481 | u16 uuid16; | ||
482 | |||
483 | if (uuid->size != 16) | ||
484 | continue; | ||
485 | |||
486 | uuid16 = get_unaligned_le16(&uuid->uuid[12]); | ||
487 | if (uuid16 < 0x1100) | ||
488 | continue; | ||
489 | |||
490 | if (uuid16 == PNP_INFO_SVCLASS_ID) | ||
491 | continue; | ||
492 | |||
493 | if (!uuids_start) { | ||
494 | uuids_start = ptr; | ||
495 | uuids_start[0] = 1; | ||
496 | uuids_start[1] = EIR_UUID16_ALL; | ||
497 | ptr += 2; | ||
498 | } | ||
499 | |||
500 | /* Stop if not enough space to put next UUID */ | ||
501 | if ((ptr - data) + sizeof(u16) > len) { | ||
502 | uuids_start[1] = EIR_UUID16_SOME; | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | *ptr++ = (uuid16 & 0x00ff); | ||
507 | *ptr++ = (uuid16 & 0xff00) >> 8; | ||
508 | uuids_start[0] += sizeof(uuid16); | ||
509 | } | ||
510 | |||
511 | return ptr; | ||
512 | } | ||
513 | |||
514 | static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
515 | { | ||
516 | u8 *ptr = data, *uuids_start = NULL; | ||
517 | struct bt_uuid *uuid; | ||
518 | |||
519 | if (len < 6) | ||
520 | return ptr; | ||
521 | |||
522 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
523 | if (uuid->size != 32) | ||
524 | continue; | ||
525 | |||
526 | if (!uuids_start) { | ||
527 | uuids_start = ptr; | ||
528 | uuids_start[0] = 1; | ||
529 | uuids_start[1] = EIR_UUID32_ALL; | ||
530 | ptr += 2; | ||
531 | } | ||
532 | |||
533 | /* Stop if not enough space to put next UUID */ | ||
534 | if ((ptr - data) + sizeof(u32) > len) { | ||
535 | uuids_start[1] = EIR_UUID32_SOME; | ||
536 | break; | ||
537 | } | ||
538 | |||
539 | memcpy(ptr, &uuid->uuid[12], sizeof(u32)); | ||
540 | ptr += sizeof(u32); | ||
541 | uuids_start[0] += sizeof(u32); | ||
542 | } | ||
543 | |||
544 | return ptr; | ||
545 | } | ||
546 | |||
547 | static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
548 | { | ||
549 | u8 *ptr = data, *uuids_start = NULL; | ||
550 | struct bt_uuid *uuid; | ||
551 | |||
552 | if (len < 18) | ||
553 | return ptr; | ||
554 | |||
555 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
556 | if (uuid->size != 128) | ||
557 | continue; | ||
558 | |||
559 | if (!uuids_start) { | ||
560 | uuids_start = ptr; | ||
561 | uuids_start[0] = 1; | ||
562 | uuids_start[1] = EIR_UUID128_ALL; | ||
563 | ptr += 2; | ||
564 | } | ||
565 | |||
566 | /* Stop if not enough space to put next UUID */ | ||
567 | if ((ptr - data) + 16 > len) { | ||
568 | uuids_start[1] = EIR_UUID128_SOME; | ||
569 | break; | ||
570 | } | ||
571 | |||
572 | memcpy(ptr, uuid->uuid, 16); | ||
573 | ptr += 16; | ||
574 | uuids_start[0] += 16; | ||
575 | } | ||
576 | |||
577 | return ptr; | ||
578 | } | ||
579 | |||
580 | static void create_eir(struct hci_dev *hdev, u8 *data) | ||
581 | { | ||
582 | u8 *ptr = data; | ||
583 | size_t name_len; | ||
584 | |||
585 | name_len = strlen(hdev->dev_name); | ||
586 | |||
587 | if (name_len > 0) { | ||
588 | /* EIR Data type */ | ||
589 | if (name_len > 48) { | ||
590 | name_len = 48; | ||
591 | ptr[1] = EIR_NAME_SHORT; | ||
592 | } else | ||
593 | ptr[1] = EIR_NAME_COMPLETE; | ||
594 | |||
595 | /* EIR Data length */ | ||
596 | ptr[0] = name_len + 1; | ||
597 | |||
598 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
599 | |||
600 | ptr += (name_len + 2); | ||
601 | } | ||
602 | |||
603 | if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) { | ||
604 | ptr[0] = 2; | ||
605 | ptr[1] = EIR_TX_POWER; | ||
606 | ptr[2] = (u8) hdev->inq_tx_power; | ||
607 | |||
608 | ptr += 3; | ||
609 | } | ||
610 | |||
611 | if (hdev->devid_source > 0) { | ||
612 | ptr[0] = 9; | ||
613 | ptr[1] = EIR_DEVICE_ID; | ||
614 | |||
615 | put_unaligned_le16(hdev->devid_source, ptr + 2); | ||
616 | put_unaligned_le16(hdev->devid_vendor, ptr + 4); | ||
617 | put_unaligned_le16(hdev->devid_product, ptr + 6); | ||
618 | put_unaligned_le16(hdev->devid_version, ptr + 8); | ||
619 | |||
620 | ptr += 10; | ||
621 | } | ||
622 | |||
623 | ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
624 | ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
625 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
626 | } | ||
627 | |||
628 | void __hci_req_update_eir(struct hci_request *req) | ||
629 | { | ||
630 | struct hci_dev *hdev = req->hdev; | ||
631 | struct hci_cp_write_eir cp; | ||
632 | |||
633 | if (!hdev_is_powered(hdev)) | ||
634 | return; | ||
635 | |||
636 | if (!lmp_ext_inq_capable(hdev)) | ||
637 | return; | ||
638 | |||
639 | if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) | ||
640 | return; | ||
641 | |||
642 | if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE)) | ||
643 | return; | ||
644 | |||
645 | memset(&cp, 0, sizeof(cp)); | ||
646 | |||
647 | create_eir(hdev, cp.data); | ||
648 | |||
649 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) | ||
650 | return; | ||
651 | |||
652 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); | ||
653 | |||
654 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | ||
655 | } | ||
656 | |||
144 | void hci_req_add_le_scan_disable(struct hci_request *req) | 657 | void hci_req_add_le_scan_disable(struct hci_request *req) |
145 | { | 658 | { |
146 | struct hci_cp_le_set_scan_enable cp; | 659 | struct hci_cp_le_set_scan_enable cp; |
@@ -302,6 +815,483 @@ void hci_req_add_le_passive_scan(struct hci_request *req) | |||
302 | &enable_cp); | 815 | &enable_cp); |
303 | } | 816 | } |
304 | 817 | ||
818 | static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev) | ||
819 | { | ||
820 | u8 instance = hdev->cur_adv_instance; | ||
821 | struct adv_info *adv_instance; | ||
822 | |||
823 | /* Ignore instance 0 */ | ||
824 | if (instance == 0x00) | ||
825 | return 0; | ||
826 | |||
827 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
828 | if (!adv_instance) | ||
829 | return 0; | ||
830 | |||
831 | /* TODO: Take into account the "appearance" and "local-name" flags here. | ||
832 | * These are currently being ignored as they are not supported. | ||
833 | */ | ||
834 | return adv_instance->scan_rsp_len; | ||
835 | } | ||
836 | |||
837 | void __hci_req_disable_advertising(struct hci_request *req) | ||
838 | { | ||
839 | u8 enable = 0x00; | ||
840 | |||
841 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
842 | } | ||
843 | |||
844 | static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) | ||
845 | { | ||
846 | u32 flags; | ||
847 | struct adv_info *adv_instance; | ||
848 | |||
849 | if (instance == 0x00) { | ||
850 | /* Instance 0 always manages the "Tx Power" and "Flags" | ||
851 | * fields | ||
852 | */ | ||
853 | flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS; | ||
854 | |||
855 | /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting | ||
856 | * corresponds to the "connectable" instance flag. | ||
857 | */ | ||
858 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) | ||
859 | flags |= MGMT_ADV_FLAG_CONNECTABLE; | ||
860 | |||
861 | return flags; | ||
862 | } | ||
863 | |||
864 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
865 | |||
866 | /* Return 0 when we got an invalid instance identifier. */ | ||
867 | if (!adv_instance) | ||
868 | return 0; | ||
869 | |||
870 | return adv_instance->flags; | ||
871 | } | ||
872 | |||
873 | void __hci_req_enable_advertising(struct hci_request *req) | ||
874 | { | ||
875 | struct hci_dev *hdev = req->hdev; | ||
876 | struct hci_cp_le_set_adv_param cp; | ||
877 | u8 own_addr_type, enable = 0x01; | ||
878 | bool connectable; | ||
879 | u32 flags; | ||
880 | |||
881 | if (hci_conn_num(hdev, LE_LINK) > 0) | ||
882 | return; | ||
883 | |||
884 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | ||
885 | __hci_req_disable_advertising(req); | ||
886 | |||
887 | /* Clear the HCI_LE_ADV bit temporarily so that the | ||
888 | * hci_update_random_address knows that it's safe to go ahead | ||
889 | * and write a new random address. The flag will be set back on | ||
890 | * as soon as the SET_ADV_ENABLE HCI command completes. | ||
891 | */ | ||
892 | hci_dev_clear_flag(hdev, HCI_LE_ADV); | ||
893 | |||
894 | flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance); | ||
895 | |||
896 | /* If the "connectable" instance flag was not set, then choose between | ||
897 | * ADV_IND and ADV_NONCONN_IND based on the global connectable setting. | ||
898 | */ | ||
899 | connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) || | ||
900 | mgmt_get_connectable(hdev); | ||
901 | |||
902 | /* Set require_privacy to true only when non-connectable | ||
903 | * advertising is used. In that case it is fine to use a | ||
904 | * non-resolvable private address. | ||
905 | */ | ||
906 | if (hci_update_random_address(req, !connectable, &own_addr_type) < 0) | ||
907 | return; | ||
908 | |||
909 | memset(&cp, 0, sizeof(cp)); | ||
910 | cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval); | ||
911 | cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval); | ||
912 | |||
913 | if (connectable) | ||
914 | cp.type = LE_ADV_IND; | ||
915 | else if (get_cur_adv_instance_scan_rsp_len(hdev)) | ||
916 | cp.type = LE_ADV_SCAN_IND; | ||
917 | else | ||
918 | cp.type = LE_ADV_NONCONN_IND; | ||
919 | |||
920 | cp.own_address_type = own_addr_type; | ||
921 | cp.channel_map = hdev->le_adv_channel_map; | ||
922 | |||
923 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); | ||
924 | |||
925 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
926 | } | ||
927 | |||
928 | static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) | ||
929 | { | ||
930 | u8 ad_len = 0; | ||
931 | size_t name_len; | ||
932 | |||
933 | name_len = strlen(hdev->dev_name); | ||
934 | if (name_len > 0) { | ||
935 | size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||
936 | |||
937 | if (name_len > max_len) { | ||
938 | name_len = max_len; | ||
939 | ptr[1] = EIR_NAME_SHORT; | ||
940 | } else | ||
941 | ptr[1] = EIR_NAME_COMPLETE; | ||
942 | |||
943 | ptr[0] = name_len + 1; | ||
944 | |||
945 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
946 | |||
947 | ad_len += (name_len + 2); | ||
948 | ptr += (name_len + 2); | ||
949 | } | ||
950 | |||
951 | return ad_len; | ||
952 | } | ||
953 | |||
954 | static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance, | ||
955 | u8 *ptr) | ||
956 | { | ||
957 | struct adv_info *adv_instance; | ||
958 | |||
959 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
960 | if (!adv_instance) | ||
961 | return 0; | ||
962 | |||
963 | /* TODO: Set the appropriate entries based on advertising instance flags | ||
964 | * here once flags other than 0 are supported. | ||
965 | */ | ||
966 | memcpy(ptr, adv_instance->scan_rsp_data, | ||
967 | adv_instance->scan_rsp_len); | ||
968 | |||
969 | return adv_instance->scan_rsp_len; | ||
970 | } | ||
971 | |||
972 | void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance) | ||
973 | { | ||
974 | struct hci_dev *hdev = req->hdev; | ||
975 | struct hci_cp_le_set_scan_rsp_data cp; | ||
976 | u8 len; | ||
977 | |||
978 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
979 | return; | ||
980 | |||
981 | memset(&cp, 0, sizeof(cp)); | ||
982 | |||
983 | if (instance) | ||
984 | len = create_instance_scan_rsp_data(hdev, instance, cp.data); | ||
985 | else | ||
986 | len = create_default_scan_rsp_data(hdev, cp.data); | ||
987 | |||
988 | if (hdev->scan_rsp_data_len == len && | ||
989 | !memcmp(cp.data, hdev->scan_rsp_data, len)) | ||
990 | return; | ||
991 | |||
992 | memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data)); | ||
993 | hdev->scan_rsp_data_len = len; | ||
994 | |||
995 | cp.length = len; | ||
996 | |||
997 | hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp); | ||
998 | } | ||
999 | |||
1000 | static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) | ||
1001 | { | ||
1002 | struct adv_info *adv_instance = NULL; | ||
1003 | u8 ad_len = 0, flags = 0; | ||
1004 | u32 instance_flags; | ||
1005 | |||
1006 | /* Return 0 when the current instance identifier is invalid. */ | ||
1007 | if (instance) { | ||
1008 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1009 | if (!adv_instance) | ||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | instance_flags = get_adv_instance_flags(hdev, instance); | ||
1014 | |||
1015 | /* The Add Advertising command allows userspace to set both the general | ||
1016 | * and limited discoverable flags. | ||
1017 | */ | ||
1018 | if (instance_flags & MGMT_ADV_FLAG_DISCOV) | ||
1019 | flags |= LE_AD_GENERAL; | ||
1020 | |||
1021 | if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV) | ||
1022 | flags |= LE_AD_LIMITED; | ||
1023 | |||
1024 | if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { | ||
1025 | /* If a discovery flag wasn't provided, simply use the global | ||
1026 | * settings. | ||
1027 | */ | ||
1028 | if (!flags) | ||
1029 | flags |= mgmt_get_adv_discov_flags(hdev); | ||
1030 | |||
1031 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
1032 | flags |= LE_AD_NO_BREDR; | ||
1033 | |||
1034 | /* If flags would still be empty, then there is no need to | ||
1035 | * include the "Flags" AD field". | ||
1036 | */ | ||
1037 | if (flags) { | ||
1038 | ptr[0] = 0x02; | ||
1039 | ptr[1] = EIR_FLAGS; | ||
1040 | ptr[2] = flags; | ||
1041 | |||
1042 | ad_len += 3; | ||
1043 | ptr += 3; | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1047 | if (adv_instance) { | ||
1048 | memcpy(ptr, adv_instance->adv_data, | ||
1049 | adv_instance->adv_data_len); | ||
1050 | ad_len += adv_instance->adv_data_len; | ||
1051 | ptr += adv_instance->adv_data_len; | ||
1052 | } | ||
1053 | |||
1054 | /* Provide Tx Power only if we can provide a valid value for it */ | ||
1055 | if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && | ||
1056 | (instance_flags & MGMT_ADV_FLAG_TX_POWER)) { | ||
1057 | ptr[0] = 0x02; | ||
1058 | ptr[1] = EIR_TX_POWER; | ||
1059 | ptr[2] = (u8)hdev->adv_tx_power; | ||
1060 | |||
1061 | ad_len += 3; | ||
1062 | ptr += 3; | ||
1063 | } | ||
1064 | |||
1065 | return ad_len; | ||
1066 | } | ||
1067 | |||
1068 | void __hci_req_update_adv_data(struct hci_request *req, u8 instance) | ||
1069 | { | ||
1070 | struct hci_dev *hdev = req->hdev; | ||
1071 | struct hci_cp_le_set_adv_data cp; | ||
1072 | u8 len; | ||
1073 | |||
1074 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
1075 | return; | ||
1076 | |||
1077 | memset(&cp, 0, sizeof(cp)); | ||
1078 | |||
1079 | len = create_instance_adv_data(hdev, instance, cp.data); | ||
1080 | |||
1081 | /* There's nothing to do if the data hasn't changed */ | ||
1082 | if (hdev->adv_data_len == len && | ||
1083 | memcmp(cp.data, hdev->adv_data, len) == 0) | ||
1084 | return; | ||
1085 | |||
1086 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||
1087 | hdev->adv_data_len = len; | ||
1088 | |||
1089 | cp.length = len; | ||
1090 | |||
1091 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
1092 | } | ||
1093 | |||
1094 | int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance) | ||
1095 | { | ||
1096 | struct hci_request req; | ||
1097 | |||
1098 | hci_req_init(&req, hdev); | ||
1099 | __hci_req_update_adv_data(&req, instance); | ||
1100 | |||
1101 | return hci_req_run(&req, NULL); | ||
1102 | } | ||
1103 | |||
1104 | static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) | ||
1105 | { | ||
1106 | BT_DBG("%s status %u", hdev->name, status); | ||
1107 | } | ||
1108 | |||
1109 | void hci_req_reenable_advertising(struct hci_dev *hdev) | ||
1110 | { | ||
1111 | struct hci_request req; | ||
1112 | |||
1113 | if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) && | ||
1114 | list_empty(&hdev->adv_instances)) | ||
1115 | return; | ||
1116 | |||
1117 | hci_req_init(&req, hdev); | ||
1118 | |||
1119 | if (hdev->cur_adv_instance) { | ||
1120 | __hci_req_schedule_adv_instance(&req, hdev->cur_adv_instance, | ||
1121 | true); | ||
1122 | } else { | ||
1123 | __hci_req_update_adv_data(&req, 0x00); | ||
1124 | __hci_req_update_scan_rsp_data(&req, 0x00); | ||
1125 | __hci_req_enable_advertising(&req); | ||
1126 | } | ||
1127 | |||
1128 | hci_req_run(&req, adv_enable_complete); | ||
1129 | } | ||
1130 | |||
1131 | static void adv_timeout_expire(struct work_struct *work) | ||
1132 | { | ||
1133 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
1134 | adv_instance_expire.work); | ||
1135 | |||
1136 | struct hci_request req; | ||
1137 | u8 instance; | ||
1138 | |||
1139 | BT_DBG("%s", hdev->name); | ||
1140 | |||
1141 | hci_dev_lock(hdev); | ||
1142 | |||
1143 | hdev->adv_instance_timeout = 0; | ||
1144 | |||
1145 | instance = hdev->cur_adv_instance; | ||
1146 | if (instance == 0x00) | ||
1147 | goto unlock; | ||
1148 | |||
1149 | hci_req_init(&req, hdev); | ||
1150 | |||
1151 | hci_req_clear_adv_instance(hdev, &req, instance, false); | ||
1152 | |||
1153 | if (list_empty(&hdev->adv_instances)) | ||
1154 | __hci_req_disable_advertising(&req); | ||
1155 | |||
1156 | hci_req_run(&req, NULL); | ||
1157 | |||
1158 | unlock: | ||
1159 | hci_dev_unlock(hdev); | ||
1160 | } | ||
1161 | |||
1162 | int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, | ||
1163 | bool force) | ||
1164 | { | ||
1165 | struct hci_dev *hdev = req->hdev; | ||
1166 | struct adv_info *adv_instance = NULL; | ||
1167 | u16 timeout; | ||
1168 | |||
1169 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
1170 | list_empty(&hdev->adv_instances)) | ||
1171 | return -EPERM; | ||
1172 | |||
1173 | if (hdev->adv_instance_timeout) | ||
1174 | return -EBUSY; | ||
1175 | |||
1176 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1177 | if (!adv_instance) | ||
1178 | return -ENOENT; | ||
1179 | |||
1180 | /* A zero timeout means unlimited advertising. As long as there is | ||
1181 | * only one instance, duration should be ignored. We still set a timeout | ||
1182 | * in case further instances are being added later on. | ||
1183 | * | ||
1184 | * If the remaining lifetime of the instance is more than the duration | ||
1185 | * then the timeout corresponds to the duration, otherwise it will be | ||
1186 | * reduced to the remaining instance lifetime. | ||
1187 | */ | ||
1188 | if (adv_instance->timeout == 0 || | ||
1189 | adv_instance->duration <= adv_instance->remaining_time) | ||
1190 | timeout = adv_instance->duration; | ||
1191 | else | ||
1192 | timeout = adv_instance->remaining_time; | ||
1193 | |||
1194 | /* The remaining time is being reduced unless the instance is being | ||
1195 | * advertised without time limit. | ||
1196 | */ | ||
1197 | if (adv_instance->timeout) | ||
1198 | adv_instance->remaining_time = | ||
1199 | adv_instance->remaining_time - timeout; | ||
1200 | |||
1201 | hdev->adv_instance_timeout = timeout; | ||
1202 | queue_delayed_work(hdev->req_workqueue, | ||
1203 | &hdev->adv_instance_expire, | ||
1204 | msecs_to_jiffies(timeout * 1000)); | ||
1205 | |||
1206 | /* If we're just re-scheduling the same instance again then do not | ||
1207 | * execute any HCI commands. This happens when a single instance is | ||
1208 | * being advertised. | ||
1209 | */ | ||
1210 | if (!force && hdev->cur_adv_instance == instance && | ||
1211 | hci_dev_test_flag(hdev, HCI_LE_ADV)) | ||
1212 | return 0; | ||
1213 | |||
1214 | hdev->cur_adv_instance = instance; | ||
1215 | __hci_req_update_adv_data(req, instance); | ||
1216 | __hci_req_update_scan_rsp_data(req, instance); | ||
1217 | __hci_req_enable_advertising(req); | ||
1218 | |||
1219 | return 0; | ||
1220 | } | ||
1221 | |||
1222 | static void cancel_adv_timeout(struct hci_dev *hdev) | ||
1223 | { | ||
1224 | if (hdev->adv_instance_timeout) { | ||
1225 | hdev->adv_instance_timeout = 0; | ||
1226 | cancel_delayed_work(&hdev->adv_instance_expire); | ||
1227 | } | ||
1228 | } | ||
1229 | |||
1230 | /* For a single instance: | ||
1231 | * - force == true: The instance will be removed even when its remaining | ||
1232 | * lifetime is not zero. | ||
1233 | * - force == false: the instance will be deactivated but kept stored unless | ||
1234 | * the remaining lifetime is zero. | ||
1235 | * | ||
1236 | * For instance == 0x00: | ||
1237 | * - force == true: All instances will be removed regardless of their timeout | ||
1238 | * setting. | ||
1239 | * - force == false: Only instances that have a timeout will be removed. | ||
1240 | */ | ||
1241 | void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, | ||
1242 | u8 instance, bool force) | ||
1243 | { | ||
1244 | struct adv_info *adv_instance, *n, *next_instance = NULL; | ||
1245 | int err; | ||
1246 | u8 rem_inst; | ||
1247 | |||
1248 | /* Cancel any timeout concerning the removed instance(s). */ | ||
1249 | if (!instance || hdev->cur_adv_instance == instance) | ||
1250 | cancel_adv_timeout(hdev); | ||
1251 | |||
1252 | /* Get the next instance to advertise BEFORE we remove | ||
1253 | * the current one. This can be the same instance again | ||
1254 | * if there is only one instance. | ||
1255 | */ | ||
1256 | if (instance && hdev->cur_adv_instance == instance) | ||
1257 | next_instance = hci_get_next_instance(hdev, instance); | ||
1258 | |||
1259 | if (instance == 0x00) { | ||
1260 | list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, | ||
1261 | list) { | ||
1262 | if (!(force || adv_instance->timeout)) | ||
1263 | continue; | ||
1264 | |||
1265 | rem_inst = adv_instance->instance; | ||
1266 | err = hci_remove_adv_instance(hdev, rem_inst); | ||
1267 | if (!err) | ||
1268 | mgmt_advertising_removed(NULL, hdev, rem_inst); | ||
1269 | } | ||
1270 | } else { | ||
1271 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1272 | |||
1273 | if (force || (adv_instance && adv_instance->timeout && | ||
1274 | !adv_instance->remaining_time)) { | ||
1275 | /* Don't advertise a removed instance. */ | ||
1276 | if (next_instance && | ||
1277 | next_instance->instance == instance) | ||
1278 | next_instance = NULL; | ||
1279 | |||
1280 | err = hci_remove_adv_instance(hdev, instance); | ||
1281 | if (!err) | ||
1282 | mgmt_advertising_removed(NULL, hdev, instance); | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | if (!req || !hdev_is_powered(hdev) || | ||
1287 | hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
1288 | return; | ||
1289 | |||
1290 | if (next_instance) | ||
1291 | __hci_req_schedule_adv_instance(req, next_instance->instance, | ||
1292 | false); | ||
1293 | } | ||
1294 | |||
305 | static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) | 1295 | static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) |
306 | { | 1296 | { |
307 | struct hci_dev *hdev = req->hdev; | 1297 | struct hci_dev *hdev = req->hdev; |
@@ -432,7 +1422,7 @@ static bool disconnected_whitelist_entries(struct hci_dev *hdev) | |||
432 | return false; | 1422 | return false; |
433 | } | 1423 | } |
434 | 1424 | ||
435 | void __hci_update_page_scan(struct hci_request *req) | 1425 | void __hci_req_update_scan(struct hci_request *req) |
436 | { | 1426 | { |
437 | struct hci_dev *hdev = req->hdev; | 1427 | struct hci_dev *hdev = req->hdev; |
438 | u8 scan; | 1428 | u8 scan; |
@@ -452,117 +1442,168 @@ void __hci_update_page_scan(struct hci_request *req) | |||
452 | else | 1442 | else |
453 | scan = SCAN_DISABLED; | 1443 | scan = SCAN_DISABLED; |
454 | 1444 | ||
455 | if (test_bit(HCI_PSCAN, &hdev->flags) == !!(scan & SCAN_PAGE)) | ||
456 | return; | ||
457 | |||
458 | if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) | 1445 | if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) |
459 | scan |= SCAN_INQUIRY; | 1446 | scan |= SCAN_INQUIRY; |
460 | 1447 | ||
1448 | if (test_bit(HCI_PSCAN, &hdev->flags) == !!(scan & SCAN_PAGE) && | ||
1449 | test_bit(HCI_ISCAN, &hdev->flags) == !!(scan & SCAN_INQUIRY)) | ||
1450 | return; | ||
1451 | |||
461 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1452 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
462 | } | 1453 | } |
463 | 1454 | ||
464 | void hci_update_page_scan(struct hci_dev *hdev) | 1455 | static int update_scan(struct hci_request *req, unsigned long opt) |
465 | { | 1456 | { |
466 | struct hci_request req; | 1457 | hci_dev_lock(req->hdev); |
1458 | __hci_req_update_scan(req); | ||
1459 | hci_dev_unlock(req->hdev); | ||
1460 | return 0; | ||
1461 | } | ||
467 | 1462 | ||
468 | hci_req_init(&req, hdev); | 1463 | static void scan_update_work(struct work_struct *work) |
469 | __hci_update_page_scan(&req); | 1464 | { |
470 | hci_req_run(&req, NULL); | 1465 | struct hci_dev *hdev = container_of(work, struct hci_dev, scan_update); |
1466 | |||
1467 | hci_req_sync(hdev, update_scan, 0, HCI_CMD_TIMEOUT, NULL); | ||
471 | } | 1468 | } |
472 | 1469 | ||
473 | /* This function controls the background scanning based on hdev->pend_le_conns | 1470 | static int connectable_update(struct hci_request *req, unsigned long opt) |
474 | * list. If there are pending LE connection we start the background scanning, | ||
475 | * otherwise we stop it. | ||
476 | * | ||
477 | * This function requires the caller holds hdev->lock. | ||
478 | */ | ||
479 | void __hci_update_background_scan(struct hci_request *req) | ||
480 | { | 1471 | { |
481 | struct hci_dev *hdev = req->hdev; | 1472 | struct hci_dev *hdev = req->hdev; |
482 | 1473 | ||
483 | if (!test_bit(HCI_UP, &hdev->flags) || | 1474 | hci_dev_lock(hdev); |
484 | test_bit(HCI_INIT, &hdev->flags) || | 1475 | |
485 | hci_dev_test_flag(hdev, HCI_SETUP) || | 1476 | __hci_req_update_scan(req); |
486 | hci_dev_test_flag(hdev, HCI_CONFIG) || | 1477 | |
487 | hci_dev_test_flag(hdev, HCI_AUTO_OFF) || | 1478 | /* If BR/EDR is not enabled and we disable advertising as a |
488 | hci_dev_test_flag(hdev, HCI_UNREGISTER)) | 1479 | * by-product of disabling connectable, we need to update the |
1480 | * advertising flags. | ||
1481 | */ | ||
1482 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
1483 | __hci_req_update_adv_data(req, hdev->cur_adv_instance); | ||
1484 | |||
1485 | /* Update the advertising parameters if necessary */ | ||
1486 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
1487 | !list_empty(&hdev->adv_instances)) | ||
1488 | __hci_req_enable_advertising(req); | ||
1489 | |||
1490 | __hci_update_background_scan(req); | ||
1491 | |||
1492 | hci_dev_unlock(hdev); | ||
1493 | |||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1497 | static void connectable_update_work(struct work_struct *work) | ||
1498 | { | ||
1499 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
1500 | connectable_update); | ||
1501 | u8 status; | ||
1502 | |||
1503 | hci_req_sync(hdev, connectable_update, 0, HCI_CMD_TIMEOUT, &status); | ||
1504 | mgmt_set_connectable_complete(hdev, status); | ||
1505 | } | ||
1506 | |||
1507 | static u8 get_service_classes(struct hci_dev *hdev) | ||
1508 | { | ||
1509 | struct bt_uuid *uuid; | ||
1510 | u8 val = 0; | ||
1511 | |||
1512 | list_for_each_entry(uuid, &hdev->uuids, list) | ||
1513 | val |= uuid->svc_hint; | ||
1514 | |||
1515 | return val; | ||
1516 | } | ||
1517 | |||
1518 | void __hci_req_update_class(struct hci_request *req) | ||
1519 | { | ||
1520 | struct hci_dev *hdev = req->hdev; | ||
1521 | u8 cod[3]; | ||
1522 | |||
1523 | BT_DBG("%s", hdev->name); | ||
1524 | |||
1525 | if (!hdev_is_powered(hdev)) | ||
489 | return; | 1526 | return; |
490 | 1527 | ||
491 | /* No point in doing scanning if LE support hasn't been enabled */ | 1528 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) |
492 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
493 | return; | 1529 | return; |
494 | 1530 | ||
495 | /* If discovery is active don't interfere with it */ | 1531 | if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE)) |
496 | if (hdev->discovery.state != DISCOVERY_STOPPED) | ||
497 | return; | 1532 | return; |
498 | 1533 | ||
499 | /* Reset RSSI and UUID filters when starting background scanning | 1534 | cod[0] = hdev->minor_class; |
500 | * since these filters are meant for service discovery only. | 1535 | cod[1] = hdev->major_class; |
501 | * | 1536 | cod[2] = get_service_classes(hdev); |
502 | * The Start Discovery and Start Service Discovery operations | ||
503 | * ensure to set proper values for RSSI threshold and UUID | ||
504 | * filter list. So it is safe to just reset them here. | ||
505 | */ | ||
506 | hci_discovery_filter_clear(hdev); | ||
507 | 1537 | ||
508 | if (list_empty(&hdev->pend_le_conns) && | 1538 | if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) |
509 | list_empty(&hdev->pend_le_reports)) { | 1539 | cod[1] |= 0x20; |
510 | /* If there is no pending LE connections or devices | ||
511 | * to be scanned for, we should stop the background | ||
512 | * scanning. | ||
513 | */ | ||
514 | 1540 | ||
515 | /* If controller is not scanning we are done. */ | 1541 | if (memcmp(cod, hdev->dev_class, 3) == 0) |
516 | if (!hci_dev_test_flag(hdev, HCI_LE_SCAN)) | 1542 | return; |
517 | return; | ||
518 | 1543 | ||
519 | hci_req_add_le_scan_disable(req); | 1544 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
1545 | } | ||
520 | 1546 | ||
521 | BT_DBG("%s stopping background scanning", hdev->name); | 1547 | static void write_iac(struct hci_request *req) |
1548 | { | ||
1549 | struct hci_dev *hdev = req->hdev; | ||
1550 | struct hci_cp_write_current_iac_lap cp; | ||
1551 | |||
1552 | if (!hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) | ||
1553 | return; | ||
1554 | |||
1555 | if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) { | ||
1556 | /* Limited discoverable mode */ | ||
1557 | cp.num_iac = min_t(u8, hdev->num_iac, 2); | ||
1558 | cp.iac_lap[0] = 0x00; /* LIAC */ | ||
1559 | cp.iac_lap[1] = 0x8b; | ||
1560 | cp.iac_lap[2] = 0x9e; | ||
1561 | cp.iac_lap[3] = 0x33; /* GIAC */ | ||
1562 | cp.iac_lap[4] = 0x8b; | ||
1563 | cp.iac_lap[5] = 0x9e; | ||
522 | } else { | 1564 | } else { |
523 | /* If there is at least one pending LE connection, we should | 1565 | /* General discoverable mode */ |
524 | * keep the background scan running. | 1566 | cp.num_iac = 1; |
525 | */ | 1567 | cp.iac_lap[0] = 0x33; /* GIAC */ |
1568 | cp.iac_lap[1] = 0x8b; | ||
1569 | cp.iac_lap[2] = 0x9e; | ||
1570 | } | ||
526 | 1571 | ||
527 | /* If controller is connecting, we should not start scanning | 1572 | hci_req_add(req, HCI_OP_WRITE_CURRENT_IAC_LAP, |
528 | * since some controllers are not able to scan and connect at | 1573 | (cp.num_iac * 3) + 1, &cp); |
529 | * the same time. | 1574 | } |
530 | */ | ||
531 | if (hci_lookup_le_connect(hdev)) | ||
532 | return; | ||
533 | 1575 | ||
534 | /* If controller is currently scanning, we stop it to ensure we | 1576 | static int discoverable_update(struct hci_request *req, unsigned long opt) |
535 | * don't miss any advertising (due to duplicates filter). | 1577 | { |
536 | */ | 1578 | struct hci_dev *hdev = req->hdev; |
537 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) | ||
538 | hci_req_add_le_scan_disable(req); | ||
539 | 1579 | ||
540 | hci_req_add_le_passive_scan(req); | 1580 | hci_dev_lock(hdev); |
541 | 1581 | ||
542 | BT_DBG("%s starting background scanning", hdev->name); | 1582 | if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { |
1583 | write_iac(req); | ||
1584 | __hci_req_update_scan(req); | ||
1585 | __hci_req_update_class(req); | ||
543 | } | 1586 | } |
544 | } | ||
545 | 1587 | ||
546 | static void update_background_scan_complete(struct hci_dev *hdev, u8 status, | 1588 | /* Advertising instances don't use the global discoverable setting, so |
547 | u16 opcode) | 1589 | * only update AD if advertising was enabled using Set Advertising. |
548 | { | 1590 | */ |
549 | if (status) | 1591 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) |
550 | BT_DBG("HCI request failed to update background scanning: " | 1592 | __hci_req_update_adv_data(req, 0x00); |
551 | "status 0x%2.2x", status); | ||
552 | } | ||
553 | 1593 | ||
554 | void hci_update_background_scan(struct hci_dev *hdev) | 1594 | hci_dev_unlock(hdev); |
555 | { | ||
556 | int err; | ||
557 | struct hci_request req; | ||
558 | 1595 | ||
559 | hci_req_init(&req, hdev); | 1596 | return 0; |
1597 | } | ||
560 | 1598 | ||
561 | __hci_update_background_scan(&req); | 1599 | static void discoverable_update_work(struct work_struct *work) |
1600 | { | ||
1601 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
1602 | discoverable_update); | ||
1603 | u8 status; | ||
562 | 1604 | ||
563 | err = hci_req_run(&req, update_background_scan_complete); | 1605 | hci_req_sync(hdev, discoverable_update, 0, HCI_CMD_TIMEOUT, &status); |
564 | if (err && err != -ENODATA) | 1606 | mgmt_set_discoverable_complete(hdev, status); |
565 | BT_ERR("Failed to run HCI request: err %d", err); | ||
566 | } | 1607 | } |
567 | 1608 | ||
568 | void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, | 1609 | void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, |
@@ -657,3 +1698,574 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason) | |||
657 | 1698 | ||
658 | return 0; | 1699 | return 0; |
659 | } | 1700 | } |
1701 | |||
1702 | static int update_bg_scan(struct hci_request *req, unsigned long opt) | ||
1703 | { | ||
1704 | hci_dev_lock(req->hdev); | ||
1705 | __hci_update_background_scan(req); | ||
1706 | hci_dev_unlock(req->hdev); | ||
1707 | return 0; | ||
1708 | } | ||
1709 | |||
1710 | static void bg_scan_update(struct work_struct *work) | ||
1711 | { | ||
1712 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
1713 | bg_scan_update); | ||
1714 | struct hci_conn *conn; | ||
1715 | u8 status; | ||
1716 | int err; | ||
1717 | |||
1718 | err = hci_req_sync(hdev, update_bg_scan, 0, HCI_CMD_TIMEOUT, &status); | ||
1719 | if (!err) | ||
1720 | return; | ||
1721 | |||
1722 | hci_dev_lock(hdev); | ||
1723 | |||
1724 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
1725 | if (conn) | ||
1726 | hci_le_conn_failed(conn, status); | ||
1727 | |||
1728 | hci_dev_unlock(hdev); | ||
1729 | } | ||
1730 | |||
1731 | static int le_scan_disable(struct hci_request *req, unsigned long opt) | ||
1732 | { | ||
1733 | hci_req_add_le_scan_disable(req); | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static int bredr_inquiry(struct hci_request *req, unsigned long opt) | ||
1738 | { | ||
1739 | u8 length = opt; | ||
1740 | const u8 giac[3] = { 0x33, 0x8b, 0x9e }; | ||
1741 | const u8 liac[3] = { 0x00, 0x8b, 0x9e }; | ||
1742 | struct hci_cp_inquiry cp; | ||
1743 | |||
1744 | BT_DBG("%s", req->hdev->name); | ||
1745 | |||
1746 | hci_dev_lock(req->hdev); | ||
1747 | hci_inquiry_cache_flush(req->hdev); | ||
1748 | hci_dev_unlock(req->hdev); | ||
1749 | |||
1750 | memset(&cp, 0, sizeof(cp)); | ||
1751 | |||
1752 | if (req->hdev->discovery.limited) | ||
1753 | memcpy(&cp.lap, liac, sizeof(cp.lap)); | ||
1754 | else | ||
1755 | memcpy(&cp.lap, giac, sizeof(cp.lap)); | ||
1756 | |||
1757 | cp.length = length; | ||
1758 | |||
1759 | hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); | ||
1760 | |||
1761 | return 0; | ||
1762 | } | ||
1763 | |||
1764 | static void le_scan_disable_work(struct work_struct *work) | ||
1765 | { | ||
1766 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
1767 | le_scan_disable.work); | ||
1768 | u8 status; | ||
1769 | |||
1770 | BT_DBG("%s", hdev->name); | ||
1771 | |||
1772 | if (!hci_dev_test_flag(hdev, HCI_LE_SCAN)) | ||
1773 | return; | ||
1774 | |||
1775 | cancel_delayed_work(&hdev->le_scan_restart); | ||
1776 | |||
1777 | hci_req_sync(hdev, le_scan_disable, 0, HCI_CMD_TIMEOUT, &status); | ||
1778 | if (status) { | ||
1779 | BT_ERR("Failed to disable LE scan: status 0x%02x", status); | ||
1780 | return; | ||
1781 | } | ||
1782 | |||
1783 | hdev->discovery.scan_start = 0; | ||
1784 | |||
1785 | /* If we were running LE only scan, change discovery state. If | ||
1786 | * we were running both LE and BR/EDR inquiry simultaneously, | ||
1787 | * and BR/EDR inquiry is already finished, stop discovery, | ||
1788 | * otherwise BR/EDR inquiry will stop discovery when finished. | ||
1789 | * If we will resolve remote device name, do not change | ||
1790 | * discovery state. | ||
1791 | */ | ||
1792 | |||
1793 | if (hdev->discovery.type == DISCOV_TYPE_LE) | ||
1794 | goto discov_stopped; | ||
1795 | |||
1796 | if (hdev->discovery.type != DISCOV_TYPE_INTERLEAVED) | ||
1797 | return; | ||
1798 | |||
1799 | if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) { | ||
1800 | if (!test_bit(HCI_INQUIRY, &hdev->flags) && | ||
1801 | hdev->discovery.state != DISCOVERY_RESOLVING) | ||
1802 | goto discov_stopped; | ||
1803 | |||
1804 | return; | ||
1805 | } | ||
1806 | |||
1807 | hci_req_sync(hdev, bredr_inquiry, DISCOV_INTERLEAVED_INQUIRY_LEN, | ||
1808 | HCI_CMD_TIMEOUT, &status); | ||
1809 | if (status) { | ||
1810 | BT_ERR("Inquiry failed: status 0x%02x", status); | ||
1811 | goto discov_stopped; | ||
1812 | } | ||
1813 | |||
1814 | return; | ||
1815 | |||
1816 | discov_stopped: | ||
1817 | hci_dev_lock(hdev); | ||
1818 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
1819 | hci_dev_unlock(hdev); | ||
1820 | } | ||
1821 | |||
1822 | static int le_scan_restart(struct hci_request *req, unsigned long opt) | ||
1823 | { | ||
1824 | struct hci_dev *hdev = req->hdev; | ||
1825 | struct hci_cp_le_set_scan_enable cp; | ||
1826 | |||
1827 | /* If controller is not scanning we are done. */ | ||
1828 | if (!hci_dev_test_flag(hdev, HCI_LE_SCAN)) | ||
1829 | return 0; | ||
1830 | |||
1831 | hci_req_add_le_scan_disable(req); | ||
1832 | |||
1833 | memset(&cp, 0, sizeof(cp)); | ||
1834 | cp.enable = LE_SCAN_ENABLE; | ||
1835 | cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; | ||
1836 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | ||
1837 | |||
1838 | return 0; | ||
1839 | } | ||
1840 | |||
1841 | static void le_scan_restart_work(struct work_struct *work) | ||
1842 | { | ||
1843 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
1844 | le_scan_restart.work); | ||
1845 | unsigned long timeout, duration, scan_start, now; | ||
1846 | u8 status; | ||
1847 | |||
1848 | BT_DBG("%s", hdev->name); | ||
1849 | |||
1850 | hci_req_sync(hdev, le_scan_restart, 0, HCI_CMD_TIMEOUT, &status); | ||
1851 | if (status) { | ||
1852 | BT_ERR("Failed to restart LE scan: status %d", status); | ||
1853 | return; | ||
1854 | } | ||
1855 | |||
1856 | hci_dev_lock(hdev); | ||
1857 | |||
1858 | if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || | ||
1859 | !hdev->discovery.scan_start) | ||
1860 | goto unlock; | ||
1861 | |||
1862 | /* When the scan was started, hdev->le_scan_disable has been queued | ||
1863 | * after duration from scan_start. During scan restart this job | ||
1864 | * has been canceled, and we need to queue it again after proper | ||
1865 | * timeout, to make sure that scan does not run indefinitely. | ||
1866 | */ | ||
1867 | duration = hdev->discovery.scan_duration; | ||
1868 | scan_start = hdev->discovery.scan_start; | ||
1869 | now = jiffies; | ||
1870 | if (now - scan_start <= duration) { | ||
1871 | int elapsed; | ||
1872 | |||
1873 | if (now >= scan_start) | ||
1874 | elapsed = now - scan_start; | ||
1875 | else | ||
1876 | elapsed = ULONG_MAX - scan_start + now; | ||
1877 | |||
1878 | timeout = duration - elapsed; | ||
1879 | } else { | ||
1880 | timeout = 0; | ||
1881 | } | ||
1882 | |||
1883 | queue_delayed_work(hdev->req_workqueue, | ||
1884 | &hdev->le_scan_disable, timeout); | ||
1885 | |||
1886 | unlock: | ||
1887 | hci_dev_unlock(hdev); | ||
1888 | } | ||
1889 | |||
1890 | static void disable_advertising(struct hci_request *req) | ||
1891 | { | ||
1892 | u8 enable = 0x00; | ||
1893 | |||
1894 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
1895 | } | ||
1896 | |||
1897 | static int active_scan(struct hci_request *req, unsigned long opt) | ||
1898 | { | ||
1899 | uint16_t interval = opt; | ||
1900 | struct hci_dev *hdev = req->hdev; | ||
1901 | struct hci_cp_le_set_scan_param param_cp; | ||
1902 | struct hci_cp_le_set_scan_enable enable_cp; | ||
1903 | u8 own_addr_type; | ||
1904 | int err; | ||
1905 | |||
1906 | BT_DBG("%s", hdev->name); | ||
1907 | |||
1908 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) { | ||
1909 | hci_dev_lock(hdev); | ||
1910 | |||
1911 | /* Don't let discovery abort an outgoing connection attempt | ||
1912 | * that's using directed advertising. | ||
1913 | */ | ||
1914 | if (hci_lookup_le_connect(hdev)) { | ||
1915 | hci_dev_unlock(hdev); | ||
1916 | return -EBUSY; | ||
1917 | } | ||
1918 | |||
1919 | cancel_adv_timeout(hdev); | ||
1920 | hci_dev_unlock(hdev); | ||
1921 | |||
1922 | disable_advertising(req); | ||
1923 | } | ||
1924 | |||
1925 | /* If controller is scanning, it means the background scanning is | ||
1926 | * running. Thus, we should temporarily stop it in order to set the | ||
1927 | * discovery scanning parameters. | ||
1928 | */ | ||
1929 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) | ||
1930 | hci_req_add_le_scan_disable(req); | ||
1931 | |||
1932 | /* All active scans will be done with either a resolvable private | ||
1933 | * address (when privacy feature has been enabled) or non-resolvable | ||
1934 | * private address. | ||
1935 | */ | ||
1936 | err = hci_update_random_address(req, true, &own_addr_type); | ||
1937 | if (err < 0) | ||
1938 | own_addr_type = ADDR_LE_DEV_PUBLIC; | ||
1939 | |||
1940 | memset(¶m_cp, 0, sizeof(param_cp)); | ||
1941 | param_cp.type = LE_SCAN_ACTIVE; | ||
1942 | param_cp.interval = cpu_to_le16(interval); | ||
1943 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); | ||
1944 | param_cp.own_address_type = own_addr_type; | ||
1945 | |||
1946 | hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), | ||
1947 | ¶m_cp); | ||
1948 | |||
1949 | memset(&enable_cp, 0, sizeof(enable_cp)); | ||
1950 | enable_cp.enable = LE_SCAN_ENABLE; | ||
1951 | enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; | ||
1952 | |||
1953 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp), | ||
1954 | &enable_cp); | ||
1955 | |||
1956 | return 0; | ||
1957 | } | ||
1958 | |||
1959 | static int interleaved_discov(struct hci_request *req, unsigned long opt) | ||
1960 | { | ||
1961 | int err; | ||
1962 | |||
1963 | BT_DBG("%s", req->hdev->name); | ||
1964 | |||
1965 | err = active_scan(req, opt); | ||
1966 | if (err) | ||
1967 | return err; | ||
1968 | |||
1969 | return bredr_inquiry(req, DISCOV_BREDR_INQUIRY_LEN); | ||
1970 | } | ||
1971 | |||
1972 | static void start_discovery(struct hci_dev *hdev, u8 *status) | ||
1973 | { | ||
1974 | unsigned long timeout; | ||
1975 | |||
1976 | BT_DBG("%s type %u", hdev->name, hdev->discovery.type); | ||
1977 | |||
1978 | switch (hdev->discovery.type) { | ||
1979 | case DISCOV_TYPE_BREDR: | ||
1980 | if (!hci_dev_test_flag(hdev, HCI_INQUIRY)) | ||
1981 | hci_req_sync(hdev, bredr_inquiry, | ||
1982 | DISCOV_BREDR_INQUIRY_LEN, HCI_CMD_TIMEOUT, | ||
1983 | status); | ||
1984 | return; | ||
1985 | case DISCOV_TYPE_INTERLEAVED: | ||
1986 | /* When running simultaneous discovery, the LE scanning time | ||
1987 | * should occupy the whole discovery time sine BR/EDR inquiry | ||
1988 | * and LE scanning are scheduled by the controller. | ||
1989 | * | ||
1990 | * For interleaving discovery in comparison, BR/EDR inquiry | ||
1991 | * and LE scanning are done sequentially with separate | ||
1992 | * timeouts. | ||
1993 | */ | ||
1994 | if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, | ||
1995 | &hdev->quirks)) { | ||
1996 | timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT); | ||
1997 | /* During simultaneous discovery, we double LE scan | ||
1998 | * interval. We must leave some time for the controller | ||
1999 | * to do BR/EDR inquiry. | ||
2000 | */ | ||
2001 | hci_req_sync(hdev, interleaved_discov, | ||
2002 | DISCOV_LE_SCAN_INT * 2, HCI_CMD_TIMEOUT, | ||
2003 | status); | ||
2004 | break; | ||
2005 | } | ||
2006 | |||
2007 | timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout); | ||
2008 | hci_req_sync(hdev, active_scan, DISCOV_LE_SCAN_INT, | ||
2009 | HCI_CMD_TIMEOUT, status); | ||
2010 | break; | ||
2011 | case DISCOV_TYPE_LE: | ||
2012 | timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT); | ||
2013 | hci_req_sync(hdev, active_scan, DISCOV_LE_SCAN_INT, | ||
2014 | HCI_CMD_TIMEOUT, status); | ||
2015 | break; | ||
2016 | default: | ||
2017 | *status = HCI_ERROR_UNSPECIFIED; | ||
2018 | return; | ||
2019 | } | ||
2020 | |||
2021 | if (*status) | ||
2022 | return; | ||
2023 | |||
2024 | BT_DBG("%s timeout %u ms", hdev->name, jiffies_to_msecs(timeout)); | ||
2025 | |||
2026 | /* When service discovery is used and the controller has a | ||
2027 | * strict duplicate filter, it is important to remember the | ||
2028 | * start and duration of the scan. This is required for | ||
2029 | * restarting scanning during the discovery phase. | ||
2030 | */ | ||
2031 | if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) && | ||
2032 | hdev->discovery.result_filtering) { | ||
2033 | hdev->discovery.scan_start = jiffies; | ||
2034 | hdev->discovery.scan_duration = timeout; | ||
2035 | } | ||
2036 | |||
2037 | queue_delayed_work(hdev->req_workqueue, &hdev->le_scan_disable, | ||
2038 | timeout); | ||
2039 | } | ||
2040 | |||
2041 | bool hci_req_stop_discovery(struct hci_request *req) | ||
2042 | { | ||
2043 | struct hci_dev *hdev = req->hdev; | ||
2044 | struct discovery_state *d = &hdev->discovery; | ||
2045 | struct hci_cp_remote_name_req_cancel cp; | ||
2046 | struct inquiry_entry *e; | ||
2047 | bool ret = false; | ||
2048 | |||
2049 | BT_DBG("%s state %u", hdev->name, hdev->discovery.state); | ||
2050 | |||
2051 | if (d->state == DISCOVERY_FINDING || d->state == DISCOVERY_STOPPING) { | ||
2052 | if (test_bit(HCI_INQUIRY, &hdev->flags)) | ||
2053 | hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL); | ||
2054 | |||
2055 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { | ||
2056 | cancel_delayed_work(&hdev->le_scan_disable); | ||
2057 | hci_req_add_le_scan_disable(req); | ||
2058 | } | ||
2059 | |||
2060 | ret = true; | ||
2061 | } else { | ||
2062 | /* Passive scanning */ | ||
2063 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { | ||
2064 | hci_req_add_le_scan_disable(req); | ||
2065 | ret = true; | ||
2066 | } | ||
2067 | } | ||
2068 | |||
2069 | /* No further actions needed for LE-only discovery */ | ||
2070 | if (d->type == DISCOV_TYPE_LE) | ||
2071 | return ret; | ||
2072 | |||
2073 | if (d->state == DISCOVERY_RESOLVING || d->state == DISCOVERY_STOPPING) { | ||
2074 | e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, | ||
2075 | NAME_PENDING); | ||
2076 | if (!e) | ||
2077 | return ret; | ||
2078 | |||
2079 | bacpy(&cp.bdaddr, &e->data.bdaddr); | ||
2080 | hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp), | ||
2081 | &cp); | ||
2082 | ret = true; | ||
2083 | } | ||
2084 | |||
2085 | return ret; | ||
2086 | } | ||
2087 | |||
2088 | static int stop_discovery(struct hci_request *req, unsigned long opt) | ||
2089 | { | ||
2090 | hci_dev_lock(req->hdev); | ||
2091 | hci_req_stop_discovery(req); | ||
2092 | hci_dev_unlock(req->hdev); | ||
2093 | |||
2094 | return 0; | ||
2095 | } | ||
2096 | |||
2097 | static void discov_update(struct work_struct *work) | ||
2098 | { | ||
2099 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
2100 | discov_update); | ||
2101 | u8 status = 0; | ||
2102 | |||
2103 | switch (hdev->discovery.state) { | ||
2104 | case DISCOVERY_STARTING: | ||
2105 | start_discovery(hdev, &status); | ||
2106 | mgmt_start_discovery_complete(hdev, status); | ||
2107 | if (status) | ||
2108 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
2109 | else | ||
2110 | hci_discovery_set_state(hdev, DISCOVERY_FINDING); | ||
2111 | break; | ||
2112 | case DISCOVERY_STOPPING: | ||
2113 | hci_req_sync(hdev, stop_discovery, 0, HCI_CMD_TIMEOUT, &status); | ||
2114 | mgmt_stop_discovery_complete(hdev, status); | ||
2115 | if (!status) | ||
2116 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
2117 | break; | ||
2118 | case DISCOVERY_STOPPED: | ||
2119 | default: | ||
2120 | return; | ||
2121 | } | ||
2122 | } | ||
2123 | |||
2124 | static void discov_off(struct work_struct *work) | ||
2125 | { | ||
2126 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
2127 | discov_off.work); | ||
2128 | |||
2129 | BT_DBG("%s", hdev->name); | ||
2130 | |||
2131 | hci_dev_lock(hdev); | ||
2132 | |||
2133 | /* When discoverable timeout triggers, then just make sure | ||
2134 | * the limited discoverable flag is cleared. Even in the case | ||
2135 | * of a timeout triggered from general discoverable, it is | ||
2136 | * safe to unconditionally clear the flag. | ||
2137 | */ | ||
2138 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | ||
2139 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); | ||
2140 | hdev->discov_timeout = 0; | ||
2141 | |||
2142 | hci_dev_unlock(hdev); | ||
2143 | |||
2144 | hci_req_sync(hdev, discoverable_update, 0, HCI_CMD_TIMEOUT, NULL); | ||
2145 | mgmt_new_settings(hdev); | ||
2146 | } | ||
2147 | |||
2148 | static int powered_update_hci(struct hci_request *req, unsigned long opt) | ||
2149 | { | ||
2150 | struct hci_dev *hdev = req->hdev; | ||
2151 | u8 link_sec; | ||
2152 | |||
2153 | hci_dev_lock(hdev); | ||
2154 | |||
2155 | if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) && | ||
2156 | !lmp_host_ssp_capable(hdev)) { | ||
2157 | u8 mode = 0x01; | ||
2158 | |||
2159 | hci_req_add(req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); | ||
2160 | |||
2161 | if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) { | ||
2162 | u8 support = 0x01; | ||
2163 | |||
2164 | hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT, | ||
2165 | sizeof(support), &support); | ||
2166 | } | ||
2167 | } | ||
2168 | |||
2169 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) && | ||
2170 | lmp_bredr_capable(hdev)) { | ||
2171 | struct hci_cp_write_le_host_supported cp; | ||
2172 | |||
2173 | cp.le = 0x01; | ||
2174 | cp.simul = 0x00; | ||
2175 | |||
2176 | /* Check first if we already have the right | ||
2177 | * host state (host features set) | ||
2178 | */ | ||
2179 | if (cp.le != lmp_host_le_capable(hdev) || | ||
2180 | cp.simul != lmp_host_le_br_capable(hdev)) | ||
2181 | hci_req_add(req, HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
2182 | sizeof(cp), &cp); | ||
2183 | } | ||
2184 | |||
2185 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) { | ||
2186 | /* Make sure the controller has a good default for | ||
2187 | * advertising data. This also applies to the case | ||
2188 | * where BR/EDR was toggled during the AUTO_OFF phase. | ||
2189 | */ | ||
2190 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
2191 | list_empty(&hdev->adv_instances)) { | ||
2192 | __hci_req_update_adv_data(req, 0x00); | ||
2193 | __hci_req_update_scan_rsp_data(req, 0x00); | ||
2194 | |||
2195 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
2196 | __hci_req_enable_advertising(req); | ||
2197 | } else if (!list_empty(&hdev->adv_instances)) { | ||
2198 | struct adv_info *adv_instance; | ||
2199 | |||
2200 | adv_instance = list_first_entry(&hdev->adv_instances, | ||
2201 | struct adv_info, list); | ||
2202 | __hci_req_schedule_adv_instance(req, | ||
2203 | adv_instance->instance, | ||
2204 | true); | ||
2205 | } | ||
2206 | } | ||
2207 | |||
2208 | link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY); | ||
2209 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | ||
2210 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, | ||
2211 | sizeof(link_sec), &link_sec); | ||
2212 | |||
2213 | if (lmp_bredr_capable(hdev)) { | ||
2214 | if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) | ||
2215 | __hci_req_write_fast_connectable(req, true); | ||
2216 | else | ||
2217 | __hci_req_write_fast_connectable(req, false); | ||
2218 | __hci_req_update_scan(req); | ||
2219 | __hci_req_update_class(req); | ||
2220 | __hci_req_update_name(req); | ||
2221 | __hci_req_update_eir(req); | ||
2222 | } | ||
2223 | |||
2224 | hci_dev_unlock(hdev); | ||
2225 | return 0; | ||
2226 | } | ||
2227 | |||
2228 | int __hci_req_hci_power_on(struct hci_dev *hdev) | ||
2229 | { | ||
2230 | /* Register the available SMP channels (BR/EDR and LE) only when | ||
2231 | * successfully powering on the controller. This late | ||
2232 | * registration is required so that LE SMP can clearly decide if | ||
2233 | * the public address or static address is used. | ||
2234 | */ | ||
2235 | smp_register(hdev); | ||
2236 | |||
2237 | return __hci_req_sync(hdev, powered_update_hci, 0, HCI_CMD_TIMEOUT, | ||
2238 | NULL); | ||
2239 | } | ||
2240 | |||
2241 | void hci_request_setup(struct hci_dev *hdev) | ||
2242 | { | ||
2243 | INIT_WORK(&hdev->discov_update, discov_update); | ||
2244 | INIT_WORK(&hdev->bg_scan_update, bg_scan_update); | ||
2245 | INIT_WORK(&hdev->scan_update, scan_update_work); | ||
2246 | INIT_WORK(&hdev->connectable_update, connectable_update_work); | ||
2247 | INIT_WORK(&hdev->discoverable_update, discoverable_update_work); | ||
2248 | INIT_DELAYED_WORK(&hdev->discov_off, discov_off); | ||
2249 | INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work); | ||
2250 | INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work); | ||
2251 | INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire); | ||
2252 | } | ||
2253 | |||
2254 | void hci_request_cancel_all(struct hci_dev *hdev) | ||
2255 | { | ||
2256 | hci_req_sync_cancel(hdev, ENODEV); | ||
2257 | |||
2258 | cancel_work_sync(&hdev->discov_update); | ||
2259 | cancel_work_sync(&hdev->bg_scan_update); | ||
2260 | cancel_work_sync(&hdev->scan_update); | ||
2261 | cancel_work_sync(&hdev->connectable_update); | ||
2262 | cancel_work_sync(&hdev->discoverable_update); | ||
2263 | cancel_delayed_work_sync(&hdev->discov_off); | ||
2264 | cancel_delayed_work_sync(&hdev->le_scan_disable); | ||
2265 | cancel_delayed_work_sync(&hdev->le_scan_restart); | ||
2266 | |||
2267 | if (hdev->adv_instance_timeout) { | ||
2268 | cancel_delayed_work_sync(&hdev->adv_instance_expire); | ||
2269 | hdev->adv_instance_timeout = 0; | ||
2270 | } | ||
2271 | } | ||
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h index 25c7f1305dcb..64ff8c040d50 100644 --- a/net/bluetooth/hci_request.h +++ b/net/bluetooth/hci_request.h | |||
@@ -20,6 +20,9 @@ | |||
20 | SOFTWARE IS DISCLAIMED. | 20 | SOFTWARE IS DISCLAIMED. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #define hci_req_sync_lock(hdev) mutex_lock(&hdev->req_lock) | ||
24 | #define hci_req_sync_unlock(hdev) mutex_unlock(&hdev->req_lock) | ||
25 | |||
23 | struct hci_request { | 26 | struct hci_request { |
24 | struct hci_dev *hdev; | 27 | struct hci_dev *hdev; |
25 | struct sk_buff_head cmd_q; | 28 | struct sk_buff_head cmd_q; |
@@ -41,21 +44,61 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, | |||
41 | hci_req_complete_t *req_complete, | 44 | hci_req_complete_t *req_complete, |
42 | hci_req_complete_skb_t *req_complete_skb); | 45 | hci_req_complete_skb_t *req_complete_skb); |
43 | 46 | ||
47 | int hci_req_sync(struct hci_dev *hdev, int (*req)(struct hci_request *req, | ||
48 | unsigned long opt), | ||
49 | unsigned long opt, u32 timeout, u8 *hci_status); | ||
50 | int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req, | ||
51 | unsigned long opt), | ||
52 | unsigned long opt, u32 timeout, u8 *hci_status); | ||
53 | void hci_req_sync_cancel(struct hci_dev *hdev, int err); | ||
54 | |||
44 | struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, | 55 | struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, |
45 | const void *param); | 56 | const void *param); |
46 | 57 | ||
58 | int __hci_req_hci_power_on(struct hci_dev *hdev); | ||
59 | |||
60 | void __hci_req_write_fast_connectable(struct hci_request *req, bool enable); | ||
61 | void __hci_req_update_name(struct hci_request *req); | ||
62 | void __hci_req_update_eir(struct hci_request *req); | ||
63 | |||
47 | void hci_req_add_le_scan_disable(struct hci_request *req); | 64 | void hci_req_add_le_scan_disable(struct hci_request *req); |
48 | void hci_req_add_le_passive_scan(struct hci_request *req); | 65 | void hci_req_add_le_passive_scan(struct hci_request *req); |
49 | 66 | ||
50 | void hci_update_page_scan(struct hci_dev *hdev); | 67 | void hci_req_reenable_advertising(struct hci_dev *hdev); |
51 | void __hci_update_page_scan(struct hci_request *req); | 68 | void __hci_req_enable_advertising(struct hci_request *req); |
69 | void __hci_req_disable_advertising(struct hci_request *req); | ||
70 | void __hci_req_update_adv_data(struct hci_request *req, u8 instance); | ||
71 | int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance); | ||
72 | void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance); | ||
73 | |||
74 | int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, | ||
75 | bool force); | ||
76 | void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, | ||
77 | u8 instance, bool force); | ||
78 | |||
79 | void __hci_req_update_class(struct hci_request *req); | ||
80 | |||
81 | /* Returns true if HCI commands were queued */ | ||
82 | bool hci_req_stop_discovery(struct hci_request *req); | ||
83 | |||
84 | static inline void hci_req_update_scan(struct hci_dev *hdev) | ||
85 | { | ||
86 | queue_work(hdev->req_workqueue, &hdev->scan_update); | ||
87 | } | ||
88 | |||
89 | void __hci_req_update_scan(struct hci_request *req); | ||
52 | 90 | ||
53 | int hci_update_random_address(struct hci_request *req, bool require_privacy, | 91 | int hci_update_random_address(struct hci_request *req, bool require_privacy, |
54 | u8 *own_addr_type); | 92 | u8 *own_addr_type); |
55 | 93 | ||
56 | void hci_update_background_scan(struct hci_dev *hdev); | ||
57 | void __hci_update_background_scan(struct hci_request *req); | ||
58 | |||
59 | int hci_abort_conn(struct hci_conn *conn, u8 reason); | 94 | int hci_abort_conn(struct hci_conn *conn, u8 reason); |
60 | void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, | 95 | void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, |
61 | u8 reason); | 96 | u8 reason); |
97 | |||
98 | static inline void hci_update_background_scan(struct hci_dev *hdev) | ||
99 | { | ||
100 | queue_work(hdev->req_workqueue, &hdev->bg_scan_update); | ||
101 | } | ||
102 | |||
103 | void hci_request_setup(struct hci_dev *hdev); | ||
104 | void hci_request_cancel_all(struct hci_dev *hdev); | ||
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index b1eb8c09a660..1298d723c0e0 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -25,6 +25,7 @@ | |||
25 | /* Bluetooth HCI sockets. */ | 25 | /* Bluetooth HCI sockets. */ |
26 | 26 | ||
27 | #include <linux/export.h> | 27 | #include <linux/export.h> |
28 | #include <linux/utsname.h> | ||
28 | #include <asm/unaligned.h> | 29 | #include <asm/unaligned.h> |
29 | 30 | ||
30 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
@@ -120,13 +121,13 @@ static bool is_filtered_packet(struct sock *sk, struct sk_buff *skb) | |||
120 | /* Apply filter */ | 121 | /* Apply filter */ |
121 | flt = &hci_pi(sk)->filter; | 122 | flt = &hci_pi(sk)->filter; |
122 | 123 | ||
123 | flt_type = bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS; | 124 | flt_type = hci_skb_pkt_type(skb) & HCI_FLT_TYPE_BITS; |
124 | 125 | ||
125 | if (!test_bit(flt_type, &flt->type_mask)) | 126 | if (!test_bit(flt_type, &flt->type_mask)) |
126 | return true; | 127 | return true; |
127 | 128 | ||
128 | /* Extra filter for event packets only */ | 129 | /* Extra filter for event packets only */ |
129 | if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT) | 130 | if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT) |
130 | return false; | 131 | return false; |
131 | 132 | ||
132 | flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); | 133 | flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); |
@@ -170,19 +171,19 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) | |||
170 | continue; | 171 | continue; |
171 | 172 | ||
172 | if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) { | 173 | if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) { |
173 | if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT && | 174 | if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && |
174 | bt_cb(skb)->pkt_type != HCI_EVENT_PKT && | 175 | hci_skb_pkt_type(skb) != HCI_EVENT_PKT && |
175 | bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && | 176 | hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
176 | bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) | 177 | hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) |
177 | continue; | 178 | continue; |
178 | if (is_filtered_packet(sk, skb)) | 179 | if (is_filtered_packet(sk, skb)) |
179 | continue; | 180 | continue; |
180 | } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { | 181 | } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { |
181 | if (!bt_cb(skb)->incoming) | 182 | if (!bt_cb(skb)->incoming) |
182 | continue; | 183 | continue; |
183 | if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT && | 184 | if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT && |
184 | bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && | 185 | hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
185 | bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) | 186 | hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) |
186 | continue; | 187 | continue; |
187 | } else { | 188 | } else { |
188 | /* Don't send frame to other channel types */ | 189 | /* Don't send frame to other channel types */ |
@@ -196,7 +197,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) | |||
196 | continue; | 197 | continue; |
197 | 198 | ||
198 | /* Put type byte before the data */ | 199 | /* Put type byte before the data */ |
199 | memcpy(skb_push(skb_copy, 1), &bt_cb(skb)->pkt_type, 1); | 200 | memcpy(skb_push(skb_copy, 1), &hci_skb_pkt_type(skb), 1); |
200 | } | 201 | } |
201 | 202 | ||
202 | nskb = skb_clone(skb_copy, GFP_ATOMIC); | 203 | nskb = skb_clone(skb_copy, GFP_ATOMIC); |
@@ -262,7 +263,7 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) | |||
262 | 263 | ||
263 | BT_DBG("hdev %p len %d", hdev, skb->len); | 264 | BT_DBG("hdev %p len %d", hdev, skb->len); |
264 | 265 | ||
265 | switch (bt_cb(skb)->pkt_type) { | 266 | switch (hci_skb_pkt_type(skb)) { |
266 | case HCI_COMMAND_PKT: | 267 | case HCI_COMMAND_PKT: |
267 | opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); | 268 | opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); |
268 | break; | 269 | break; |
@@ -294,7 +295,7 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) | |||
294 | return; | 295 | return; |
295 | 296 | ||
296 | /* Put header before the data */ | 297 | /* Put header before the data */ |
297 | hdr = (void *) skb_push(skb_copy, HCI_MON_HDR_SIZE); | 298 | hdr = (void *)skb_push(skb_copy, HCI_MON_HDR_SIZE); |
298 | hdr->opcode = opcode; | 299 | hdr->opcode = opcode; |
299 | hdr->index = cpu_to_le16(hdev->id); | 300 | hdr->index = cpu_to_le16(hdev->id); |
300 | hdr->len = cpu_to_le16(skb->len); | 301 | hdr->len = cpu_to_le16(skb->len); |
@@ -375,7 +376,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) | |||
375 | 376 | ||
376 | __net_timestamp(skb); | 377 | __net_timestamp(skb); |
377 | 378 | ||
378 | hdr = (void *) skb_push(skb, HCI_MON_HDR_SIZE); | 379 | hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE); |
379 | hdr->opcode = opcode; | 380 | hdr->opcode = opcode; |
380 | hdr->index = cpu_to_le16(hdev->id); | 381 | hdr->index = cpu_to_le16(hdev->id); |
381 | hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); | 382 | hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); |
@@ -383,6 +384,38 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) | |||
383 | return skb; | 384 | return skb; |
384 | } | 385 | } |
385 | 386 | ||
387 | static void __printf(2, 3) | ||
388 | send_monitor_note(struct sock *sk, const char *fmt, ...) | ||
389 | { | ||
390 | size_t len; | ||
391 | struct hci_mon_hdr *hdr; | ||
392 | struct sk_buff *skb; | ||
393 | va_list args; | ||
394 | |||
395 | va_start(args, fmt); | ||
396 | len = vsnprintf(NULL, 0, fmt, args); | ||
397 | va_end(args); | ||
398 | |||
399 | skb = bt_skb_alloc(len + 1, GFP_ATOMIC); | ||
400 | if (!skb) | ||
401 | return; | ||
402 | |||
403 | va_start(args, fmt); | ||
404 | vsprintf(skb_put(skb, len), fmt, args); | ||
405 | *skb_put(skb, 1) = 0; | ||
406 | va_end(args); | ||
407 | |||
408 | __net_timestamp(skb); | ||
409 | |||
410 | hdr = (void *)skb_push(skb, HCI_MON_HDR_SIZE); | ||
411 | hdr->opcode = cpu_to_le16(HCI_MON_SYSTEM_NOTE); | ||
412 | hdr->index = cpu_to_le16(HCI_DEV_NONE); | ||
413 | hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE); | ||
414 | |||
415 | if (sock_queue_rcv_skb(sk, skb)) | ||
416 | kfree_skb(skb); | ||
417 | } | ||
418 | |||
386 | static void send_monitor_replay(struct sock *sk) | 419 | static void send_monitor_replay(struct sock *sk) |
387 | { | 420 | { |
388 | struct hci_dev *hdev; | 421 | struct hci_dev *hdev; |
@@ -436,18 +469,18 @@ static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) | |||
436 | if (!skb) | 469 | if (!skb) |
437 | return; | 470 | return; |
438 | 471 | ||
439 | hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); | 472 | hdr = (void *)skb_put(skb, HCI_EVENT_HDR_SIZE); |
440 | hdr->evt = HCI_EV_STACK_INTERNAL; | 473 | hdr->evt = HCI_EV_STACK_INTERNAL; |
441 | hdr->plen = sizeof(*ev) + dlen; | 474 | hdr->plen = sizeof(*ev) + dlen; |
442 | 475 | ||
443 | ev = (void *) skb_put(skb, sizeof(*ev) + dlen); | 476 | ev = (void *)skb_put(skb, sizeof(*ev) + dlen); |
444 | ev->type = type; | 477 | ev->type = type; |
445 | memcpy(ev->data, data, dlen); | 478 | memcpy(ev->data, data, dlen); |
446 | 479 | ||
447 | bt_cb(skb)->incoming = 1; | 480 | bt_cb(skb)->incoming = 1; |
448 | __net_timestamp(skb); | 481 | __net_timestamp(skb); |
449 | 482 | ||
450 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; | 483 | hci_skb_pkt_type(skb) = HCI_EVENT_PKT; |
451 | hci_send_to_sock(hdev, skb); | 484 | hci_send_to_sock(hdev, skb); |
452 | kfree_skb(skb); | 485 | kfree_skb(skb); |
453 | } | 486 | } |
@@ -653,20 +686,20 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, | |||
653 | return -EOPNOTSUPP; | 686 | return -EOPNOTSUPP; |
654 | 687 | ||
655 | case HCIGETCONNINFO: | 688 | case HCIGETCONNINFO: |
656 | return hci_get_conn_info(hdev, (void __user *) arg); | 689 | return hci_get_conn_info(hdev, (void __user *)arg); |
657 | 690 | ||
658 | case HCIGETAUTHINFO: | 691 | case HCIGETAUTHINFO: |
659 | return hci_get_auth_info(hdev, (void __user *) arg); | 692 | return hci_get_auth_info(hdev, (void __user *)arg); |
660 | 693 | ||
661 | case HCIBLOCKADDR: | 694 | case HCIBLOCKADDR: |
662 | if (!capable(CAP_NET_ADMIN)) | 695 | if (!capable(CAP_NET_ADMIN)) |
663 | return -EPERM; | 696 | return -EPERM; |
664 | return hci_sock_blacklist_add(hdev, (void __user *) arg); | 697 | return hci_sock_blacklist_add(hdev, (void __user *)arg); |
665 | 698 | ||
666 | case HCIUNBLOCKADDR: | 699 | case HCIUNBLOCKADDR: |
667 | if (!capable(CAP_NET_ADMIN)) | 700 | if (!capable(CAP_NET_ADMIN)) |
668 | return -EPERM; | 701 | return -EPERM; |
669 | return hci_sock_blacklist_del(hdev, (void __user *) arg); | 702 | return hci_sock_blacklist_del(hdev, (void __user *)arg); |
670 | } | 703 | } |
671 | 704 | ||
672 | return -ENOIOCTLCMD; | 705 | return -ENOIOCTLCMD; |
@@ -675,7 +708,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, | |||
675 | static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, | 708 | static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, |
676 | unsigned long arg) | 709 | unsigned long arg) |
677 | { | 710 | { |
678 | void __user *argp = (void __user *) arg; | 711 | void __user *argp = (void __user *)arg; |
679 | struct sock *sk = sock->sk; | 712 | struct sock *sk = sock->sk; |
680 | int err; | 713 | int err; |
681 | 714 | ||
@@ -872,11 +905,28 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, | |||
872 | */ | 905 | */ |
873 | hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); | 906 | hci_sock_set_flag(sk, HCI_SOCK_TRUSTED); |
874 | 907 | ||
908 | send_monitor_note(sk, "Linux version %s (%s)", | ||
909 | init_utsname()->release, | ||
910 | init_utsname()->machine); | ||
911 | send_monitor_note(sk, "Bluetooth subsystem version %s", | ||
912 | BT_SUBSYS_VERSION); | ||
875 | send_monitor_replay(sk); | 913 | send_monitor_replay(sk); |
876 | 914 | ||
877 | atomic_inc(&monitor_promisc); | 915 | atomic_inc(&monitor_promisc); |
878 | break; | 916 | break; |
879 | 917 | ||
918 | case HCI_CHANNEL_LOGGING: | ||
919 | if (haddr.hci_dev != HCI_DEV_NONE) { | ||
920 | err = -EINVAL; | ||
921 | goto done; | ||
922 | } | ||
923 | |||
924 | if (!capable(CAP_NET_ADMIN)) { | ||
925 | err = -EPERM; | ||
926 | goto done; | ||
927 | } | ||
928 | break; | ||
929 | |||
880 | default: | 930 | default: |
881 | if (!hci_mgmt_chan_find(haddr.hci_channel)) { | 931 | if (!hci_mgmt_chan_find(haddr.hci_channel)) { |
882 | err = -EINVAL; | 932 | err = -EINVAL; |
@@ -926,7 +976,7 @@ done: | |||
926 | static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, | 976 | static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, |
927 | int *addr_len, int peer) | 977 | int *addr_len, int peer) |
928 | { | 978 | { |
929 | struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; | 979 | struct sockaddr_hci *haddr = (struct sockaddr_hci *)addr; |
930 | struct sock *sk = sock->sk; | 980 | struct sock *sk = sock->sk; |
931 | struct hci_dev *hdev; | 981 | struct hci_dev *hdev; |
932 | int err = 0; | 982 | int err = 0; |
@@ -991,8 +1041,8 @@ static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, | |||
991 | } | 1041 | } |
992 | } | 1042 | } |
993 | 1043 | ||
994 | static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | 1044 | static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, |
995 | int flags) | 1045 | size_t len, int flags) |
996 | { | 1046 | { |
997 | int noblock = flags & MSG_DONTWAIT; | 1047 | int noblock = flags & MSG_DONTWAIT; |
998 | struct sock *sk = sock->sk; | 1048 | struct sock *sk = sock->sk; |
@@ -1004,6 +1054,9 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1004 | if (flags & MSG_OOB) | 1054 | if (flags & MSG_OOB) |
1005 | return -EOPNOTSUPP; | 1055 | return -EOPNOTSUPP; |
1006 | 1056 | ||
1057 | if (hci_pi(sk)->channel == HCI_CHANNEL_LOGGING) | ||
1058 | return -EOPNOTSUPP; | ||
1059 | |||
1007 | if (sk->sk_state == BT_CLOSED) | 1060 | if (sk->sk_state == BT_CLOSED) |
1008 | return 0; | 1061 | return 0; |
1009 | 1062 | ||
@@ -1150,6 +1203,90 @@ done: | |||
1150 | return err; | 1203 | return err; |
1151 | } | 1204 | } |
1152 | 1205 | ||
1206 | static int hci_logging_frame(struct sock *sk, struct msghdr *msg, int len) | ||
1207 | { | ||
1208 | struct hci_mon_hdr *hdr; | ||
1209 | struct sk_buff *skb; | ||
1210 | struct hci_dev *hdev; | ||
1211 | u16 index; | ||
1212 | int err; | ||
1213 | |||
1214 | /* The logging frame consists at minimum of the standard header, | ||
1215 | * the priority byte, the ident length byte and at least one string | ||
1216 | * terminator NUL byte. Anything shorter are invalid packets. | ||
1217 | */ | ||
1218 | if (len < sizeof(*hdr) + 3) | ||
1219 | return -EINVAL; | ||
1220 | |||
1221 | skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); | ||
1222 | if (!skb) | ||
1223 | return err; | ||
1224 | |||
1225 | if (memcpy_from_msg(skb_put(skb, len), msg, len)) { | ||
1226 | err = -EFAULT; | ||
1227 | goto drop; | ||
1228 | } | ||
1229 | |||
1230 | hdr = (void *)skb->data; | ||
1231 | |||
1232 | if (__le16_to_cpu(hdr->len) != len - sizeof(*hdr)) { | ||
1233 | err = -EINVAL; | ||
1234 | goto drop; | ||
1235 | } | ||
1236 | |||
1237 | if (__le16_to_cpu(hdr->opcode) == 0x0000) { | ||
1238 | __u8 priority = skb->data[sizeof(*hdr)]; | ||
1239 | __u8 ident_len = skb->data[sizeof(*hdr) + 1]; | ||
1240 | |||
1241 | /* Only the priorities 0-7 are valid and with that any other | ||
1242 | * value results in an invalid packet. | ||
1243 | * | ||
1244 | * The priority byte is followed by an ident length byte and | ||
1245 | * the NUL terminated ident string. Check that the ident | ||
1246 | * length is not overflowing the packet and also that the | ||
1247 | * ident string itself is NUL terminated. In case the ident | ||
1248 | * length is zero, the length value actually doubles as NUL | ||
1249 | * terminator identifier. | ||
1250 | * | ||
1251 | * The message follows the ident string (if present) and | ||
1252 | * must be NUL terminated. Otherwise it is not a valid packet. | ||
1253 | */ | ||
1254 | if (priority > 7 || skb->data[len - 1] != 0x00 || | ||
1255 | ident_len > len - sizeof(*hdr) - 3 || | ||
1256 | skb->data[sizeof(*hdr) + ident_len + 1] != 0x00) { | ||
1257 | err = -EINVAL; | ||
1258 | goto drop; | ||
1259 | } | ||
1260 | } else { | ||
1261 | err = -EINVAL; | ||
1262 | goto drop; | ||
1263 | } | ||
1264 | |||
1265 | index = __le16_to_cpu(hdr->index); | ||
1266 | |||
1267 | if (index != MGMT_INDEX_NONE) { | ||
1268 | hdev = hci_dev_get(index); | ||
1269 | if (!hdev) { | ||
1270 | err = -ENODEV; | ||
1271 | goto drop; | ||
1272 | } | ||
1273 | } else { | ||
1274 | hdev = NULL; | ||
1275 | } | ||
1276 | |||
1277 | hdr->opcode = cpu_to_le16(HCI_MON_USER_LOGGING); | ||
1278 | |||
1279 | hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, HCI_SOCK_TRUSTED, NULL); | ||
1280 | err = len; | ||
1281 | |||
1282 | if (hdev) | ||
1283 | hci_dev_put(hdev); | ||
1284 | |||
1285 | drop: | ||
1286 | kfree_skb(skb); | ||
1287 | return err; | ||
1288 | } | ||
1289 | |||
1153 | static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | 1290 | static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, |
1154 | size_t len) | 1291 | size_t len) |
1155 | { | 1292 | { |
@@ -1179,6 +1316,9 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1179 | case HCI_CHANNEL_MONITOR: | 1316 | case HCI_CHANNEL_MONITOR: |
1180 | err = -EOPNOTSUPP; | 1317 | err = -EOPNOTSUPP; |
1181 | goto done; | 1318 | goto done; |
1319 | case HCI_CHANNEL_LOGGING: | ||
1320 | err = hci_logging_frame(sk, msg, len); | ||
1321 | goto done; | ||
1182 | default: | 1322 | default: |
1183 | mutex_lock(&mgmt_chan_list_lock); | 1323 | mutex_lock(&mgmt_chan_list_lock); |
1184 | chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); | 1324 | chan = __hci_mgmt_chan_find(hci_pi(sk)->channel); |
@@ -1211,7 +1351,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1211 | goto drop; | 1351 | goto drop; |
1212 | } | 1352 | } |
1213 | 1353 | ||
1214 | bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); | 1354 | hci_skb_pkt_type(skb) = skb->data[0]; |
1215 | skb_pull(skb, 1); | 1355 | skb_pull(skb, 1); |
1216 | 1356 | ||
1217 | if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { | 1357 | if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { |
@@ -1220,16 +1360,16 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1220 | * | 1360 | * |
1221 | * However check that the packet type is valid. | 1361 | * However check that the packet type is valid. |
1222 | */ | 1362 | */ |
1223 | if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT && | 1363 | if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT && |
1224 | bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && | 1364 | hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
1225 | bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) { | 1365 | hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { |
1226 | err = -EINVAL; | 1366 | err = -EINVAL; |
1227 | goto drop; | 1367 | goto drop; |
1228 | } | 1368 | } |
1229 | 1369 | ||
1230 | skb_queue_tail(&hdev->raw_q, skb); | 1370 | skb_queue_tail(&hdev->raw_q, skb); |
1231 | queue_work(hdev->workqueue, &hdev->tx_work); | 1371 | queue_work(hdev->workqueue, &hdev->tx_work); |
1232 | } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { | 1372 | } else if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT) { |
1233 | u16 opcode = get_unaligned_le16(skb->data); | 1373 | u16 opcode = get_unaligned_le16(skb->data); |
1234 | u16 ogf = hci_opcode_ogf(opcode); | 1374 | u16 ogf = hci_opcode_ogf(opcode); |
1235 | u16 ocf = hci_opcode_ocf(opcode); | 1375 | u16 ocf = hci_opcode_ocf(opcode); |
@@ -1242,6 +1382,11 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1242 | goto drop; | 1382 | goto drop; |
1243 | } | 1383 | } |
1244 | 1384 | ||
1385 | /* Since the opcode has already been extracted here, store | ||
1386 | * a copy of the value for later use by the drivers. | ||
1387 | */ | ||
1388 | hci_skb_opcode(skb) = opcode; | ||
1389 | |||
1245 | if (ogf == 0x3f) { | 1390 | if (ogf == 0x3f) { |
1246 | skb_queue_tail(&hdev->raw_q, skb); | 1391 | skb_queue_tail(&hdev->raw_q, skb); |
1247 | queue_work(hdev->workqueue, &hdev->tx_work); | 1392 | queue_work(hdev->workqueue, &hdev->tx_work); |
@@ -1249,7 +1394,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1249 | /* Stand-alone HCI commands must be flagged as | 1394 | /* Stand-alone HCI commands must be flagged as |
1250 | * single-command requests. | 1395 | * single-command requests. |
1251 | */ | 1396 | */ |
1252 | bt_cb(skb)->hci.req_start = true; | 1397 | bt_cb(skb)->hci.req_flags |= HCI_REQ_START; |
1253 | 1398 | ||
1254 | skb_queue_tail(&hdev->cmd_q, skb); | 1399 | skb_queue_tail(&hdev->cmd_q, skb); |
1255 | queue_work(hdev->workqueue, &hdev->cmd_work); | 1400 | queue_work(hdev->workqueue, &hdev->cmd_work); |
@@ -1260,8 +1405,8 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1260 | goto drop; | 1405 | goto drop; |
1261 | } | 1406 | } |
1262 | 1407 | ||
1263 | if (bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT && | 1408 | if (hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && |
1264 | bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) { | 1409 | hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) { |
1265 | err = -EINVAL; | 1410 | err = -EINVAL; |
1266 | goto drop; | 1411 | goto drop; |
1267 | } | 1412 | } |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 66e8b6ee19a5..39a5149f3010 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -6538,8 +6538,6 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | |||
6538 | static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | 6538 | static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, |
6539 | struct sk_buff *skb) | 6539 | struct sk_buff *skb) |
6540 | { | 6540 | { |
6541 | int err = 0; | ||
6542 | |||
6543 | BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, | 6541 | BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, |
6544 | chan->rx_state); | 6542 | chan->rx_state); |
6545 | 6543 | ||
@@ -6570,7 +6568,7 @@ static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | |||
6570 | chan->last_acked_seq = control->txseq; | 6568 | chan->last_acked_seq = control->txseq; |
6571 | chan->expected_tx_seq = __next_seq(chan, control->txseq); | 6569 | chan->expected_tx_seq = __next_seq(chan, control->txseq); |
6572 | 6570 | ||
6573 | return err; | 6571 | return 0; |
6574 | } | 6572 | } |
6575 | 6573 | ||
6576 | static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | 6574 | static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) |
@@ -7113,8 +7111,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7113 | chan->dcid = cid; | 7111 | chan->dcid = cid; |
7114 | 7112 | ||
7115 | if (bdaddr_type_is_le(dst_type)) { | 7113 | if (bdaddr_type_is_le(dst_type)) { |
7116 | u8 role; | ||
7117 | |||
7118 | /* Convert from L2CAP channel address type to HCI address type | 7114 | /* Convert from L2CAP channel address type to HCI address type |
7119 | */ | 7115 | */ |
7120 | if (dst_type == BDADDR_LE_PUBLIC) | 7116 | if (dst_type == BDADDR_LE_PUBLIC) |
@@ -7123,14 +7119,15 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7123 | dst_type = ADDR_LE_DEV_RANDOM; | 7119 | dst_type = ADDR_LE_DEV_RANDOM; |
7124 | 7120 | ||
7125 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | 7121 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) |
7126 | role = HCI_ROLE_SLAVE; | 7122 | hcon = hci_connect_le(hdev, dst, dst_type, |
7123 | chan->sec_level, | ||
7124 | HCI_LE_CONN_TIMEOUT, | ||
7125 | HCI_ROLE_SLAVE); | ||
7127 | else | 7126 | else |
7128 | role = HCI_ROLE_MASTER; | 7127 | hcon = hci_connect_le_scan(hdev, dst, dst_type, |
7128 | chan->sec_level, | ||
7129 | HCI_LE_CONN_TIMEOUT); | ||
7129 | 7130 | ||
7130 | hcon = hci_connect_le_scan(hdev, dst, dst_type, | ||
7131 | chan->sec_level, | ||
7132 | HCI_LE_CONN_TIMEOUT, | ||
7133 | role); | ||
7134 | } else { | 7131 | } else { |
7135 | u8 auth_type = l2cap_get_auth_type(chan); | 7132 | u8 auth_type = l2cap_get_auth_type(chan); |
7136 | hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); | 7133 | hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7f22119276f3..5a5089cb6570 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "mgmt_util.h" | 38 | #include "mgmt_util.h" |
39 | 39 | ||
40 | #define MGMT_VERSION 1 | 40 | #define MGMT_VERSION 1 |
41 | #define MGMT_REVISION 10 | 41 | #define MGMT_REVISION 11 |
42 | 42 | ||
43 | static const u16 mgmt_commands[] = { | 43 | static const u16 mgmt_commands[] = { |
44 | MGMT_OP_READ_INDEX_LIST, | 44 | MGMT_OP_READ_INDEX_LIST, |
@@ -102,6 +102,8 @@ static const u16 mgmt_commands[] = { | |||
102 | MGMT_OP_READ_ADV_FEATURES, | 102 | MGMT_OP_READ_ADV_FEATURES, |
103 | MGMT_OP_ADD_ADVERTISING, | 103 | MGMT_OP_ADD_ADVERTISING, |
104 | MGMT_OP_REMOVE_ADVERTISING, | 104 | MGMT_OP_REMOVE_ADVERTISING, |
105 | MGMT_OP_GET_ADV_SIZE_INFO, | ||
106 | MGMT_OP_START_LIMITED_DISCOVERY, | ||
105 | }; | 107 | }; |
106 | 108 | ||
107 | static const u16 mgmt_events[] = { | 109 | static const u16 mgmt_events[] = { |
@@ -718,116 +720,6 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
718 | return settings; | 720 | return settings; |
719 | } | 721 | } |
720 | 722 | ||
721 | #define PNP_INFO_SVCLASS_ID 0x1200 | ||
722 | |||
723 | static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
724 | { | ||
725 | u8 *ptr = data, *uuids_start = NULL; | ||
726 | struct bt_uuid *uuid; | ||
727 | |||
728 | if (len < 4) | ||
729 | return ptr; | ||
730 | |||
731 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
732 | u16 uuid16; | ||
733 | |||
734 | if (uuid->size != 16) | ||
735 | continue; | ||
736 | |||
737 | uuid16 = get_unaligned_le16(&uuid->uuid[12]); | ||
738 | if (uuid16 < 0x1100) | ||
739 | continue; | ||
740 | |||
741 | if (uuid16 == PNP_INFO_SVCLASS_ID) | ||
742 | continue; | ||
743 | |||
744 | if (!uuids_start) { | ||
745 | uuids_start = ptr; | ||
746 | uuids_start[0] = 1; | ||
747 | uuids_start[1] = EIR_UUID16_ALL; | ||
748 | ptr += 2; | ||
749 | } | ||
750 | |||
751 | /* Stop if not enough space to put next UUID */ | ||
752 | if ((ptr - data) + sizeof(u16) > len) { | ||
753 | uuids_start[1] = EIR_UUID16_SOME; | ||
754 | break; | ||
755 | } | ||
756 | |||
757 | *ptr++ = (uuid16 & 0x00ff); | ||
758 | *ptr++ = (uuid16 & 0xff00) >> 8; | ||
759 | uuids_start[0] += sizeof(uuid16); | ||
760 | } | ||
761 | |||
762 | return ptr; | ||
763 | } | ||
764 | |||
765 | static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
766 | { | ||
767 | u8 *ptr = data, *uuids_start = NULL; | ||
768 | struct bt_uuid *uuid; | ||
769 | |||
770 | if (len < 6) | ||
771 | return ptr; | ||
772 | |||
773 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
774 | if (uuid->size != 32) | ||
775 | continue; | ||
776 | |||
777 | if (!uuids_start) { | ||
778 | uuids_start = ptr; | ||
779 | uuids_start[0] = 1; | ||
780 | uuids_start[1] = EIR_UUID32_ALL; | ||
781 | ptr += 2; | ||
782 | } | ||
783 | |||
784 | /* Stop if not enough space to put next UUID */ | ||
785 | if ((ptr - data) + sizeof(u32) > len) { | ||
786 | uuids_start[1] = EIR_UUID32_SOME; | ||
787 | break; | ||
788 | } | ||
789 | |||
790 | memcpy(ptr, &uuid->uuid[12], sizeof(u32)); | ||
791 | ptr += sizeof(u32); | ||
792 | uuids_start[0] += sizeof(u32); | ||
793 | } | ||
794 | |||
795 | return ptr; | ||
796 | } | ||
797 | |||
798 | static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
799 | { | ||
800 | u8 *ptr = data, *uuids_start = NULL; | ||
801 | struct bt_uuid *uuid; | ||
802 | |||
803 | if (len < 18) | ||
804 | return ptr; | ||
805 | |||
806 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
807 | if (uuid->size != 128) | ||
808 | continue; | ||
809 | |||
810 | if (!uuids_start) { | ||
811 | uuids_start = ptr; | ||
812 | uuids_start[0] = 1; | ||
813 | uuids_start[1] = EIR_UUID128_ALL; | ||
814 | ptr += 2; | ||
815 | } | ||
816 | |||
817 | /* Stop if not enough space to put next UUID */ | ||
818 | if ((ptr - data) + 16 > len) { | ||
819 | uuids_start[1] = EIR_UUID128_SOME; | ||
820 | break; | ||
821 | } | ||
822 | |||
823 | memcpy(ptr, uuid->uuid, 16); | ||
824 | ptr += 16; | ||
825 | uuids_start[0] += 16; | ||
826 | } | ||
827 | |||
828 | return ptr; | ||
829 | } | ||
830 | |||
831 | static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev) | 723 | static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev) |
832 | { | 724 | { |
833 | return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev); | 725 | return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev); |
@@ -840,98 +732,7 @@ static struct mgmt_pending_cmd *pending_find_data(u16 opcode, | |||
840 | return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data); | 732 | return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data); |
841 | } | 733 | } |
842 | 734 | ||
843 | static u8 get_current_adv_instance(struct hci_dev *hdev) | 735 | u8 mgmt_get_adv_discov_flags(struct hci_dev *hdev) |
844 | { | ||
845 | /* The "Set Advertising" setting supersedes the "Add Advertising" | ||
846 | * setting. Here we set the advertising data based on which | ||
847 | * setting was set. When neither apply, default to the global settings, | ||
848 | * represented by instance "0". | ||
849 | */ | ||
850 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | ||
851 | !hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
852 | return hdev->cur_adv_instance; | ||
853 | |||
854 | return 0x00; | ||
855 | } | ||
856 | |||
857 | static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) | ||
858 | { | ||
859 | u8 ad_len = 0; | ||
860 | size_t name_len; | ||
861 | |||
862 | name_len = strlen(hdev->dev_name); | ||
863 | if (name_len > 0) { | ||
864 | size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||
865 | |||
866 | if (name_len > max_len) { | ||
867 | name_len = max_len; | ||
868 | ptr[1] = EIR_NAME_SHORT; | ||
869 | } else | ||
870 | ptr[1] = EIR_NAME_COMPLETE; | ||
871 | |||
872 | ptr[0] = name_len + 1; | ||
873 | |||
874 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
875 | |||
876 | ad_len += (name_len + 2); | ||
877 | ptr += (name_len + 2); | ||
878 | } | ||
879 | |||
880 | return ad_len; | ||
881 | } | ||
882 | |||
883 | static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance, | ||
884 | u8 *ptr) | ||
885 | { | ||
886 | struct adv_info *adv_instance; | ||
887 | |||
888 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
889 | if (!adv_instance) | ||
890 | return 0; | ||
891 | |||
892 | /* TODO: Set the appropriate entries based on advertising instance flags | ||
893 | * here once flags other than 0 are supported. | ||
894 | */ | ||
895 | memcpy(ptr, adv_instance->scan_rsp_data, | ||
896 | adv_instance->scan_rsp_len); | ||
897 | |||
898 | return adv_instance->scan_rsp_len; | ||
899 | } | ||
900 | |||
901 | static void update_inst_scan_rsp_data(struct hci_request *req, u8 instance) | ||
902 | { | ||
903 | struct hci_dev *hdev = req->hdev; | ||
904 | struct hci_cp_le_set_scan_rsp_data cp; | ||
905 | u8 len; | ||
906 | |||
907 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
908 | return; | ||
909 | |||
910 | memset(&cp, 0, sizeof(cp)); | ||
911 | |||
912 | if (instance) | ||
913 | len = create_instance_scan_rsp_data(hdev, instance, cp.data); | ||
914 | else | ||
915 | len = create_default_scan_rsp_data(hdev, cp.data); | ||
916 | |||
917 | if (hdev->scan_rsp_data_len == len && | ||
918 | !memcmp(cp.data, hdev->scan_rsp_data, len)) | ||
919 | return; | ||
920 | |||
921 | memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data)); | ||
922 | hdev->scan_rsp_data_len = len; | ||
923 | |||
924 | cp.length = len; | ||
925 | |||
926 | hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp); | ||
927 | } | ||
928 | |||
929 | static void update_scan_rsp_data(struct hci_request *req) | ||
930 | { | ||
931 | update_inst_scan_rsp_data(req, get_current_adv_instance(req->hdev)); | ||
932 | } | ||
933 | |||
934 | static u8 get_adv_discov_flags(struct hci_dev *hdev) | ||
935 | { | 736 | { |
936 | struct mgmt_pending_cmd *cmd; | 737 | struct mgmt_pending_cmd *cmd; |
937 | 738 | ||
@@ -955,7 +756,7 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev) | |||
955 | return 0; | 756 | return 0; |
956 | } | 757 | } |
957 | 758 | ||
958 | static bool get_connectable(struct hci_dev *hdev) | 759 | bool mgmt_get_connectable(struct hci_dev *hdev) |
959 | { | 760 | { |
960 | struct mgmt_pending_cmd *cmd; | 761 | struct mgmt_pending_cmd *cmd; |
961 | 762 | ||
@@ -972,344 +773,6 @@ static bool get_connectable(struct hci_dev *hdev) | |||
972 | return hci_dev_test_flag(hdev, HCI_CONNECTABLE); | 773 | return hci_dev_test_flag(hdev, HCI_CONNECTABLE); |
973 | } | 774 | } |
974 | 775 | ||
975 | static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) | ||
976 | { | ||
977 | u32 flags; | ||
978 | struct adv_info *adv_instance; | ||
979 | |||
980 | if (instance == 0x00) { | ||
981 | /* Instance 0 always manages the "Tx Power" and "Flags" | ||
982 | * fields | ||
983 | */ | ||
984 | flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS; | ||
985 | |||
986 | /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting | ||
987 | * corresponds to the "connectable" instance flag. | ||
988 | */ | ||
989 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) | ||
990 | flags |= MGMT_ADV_FLAG_CONNECTABLE; | ||
991 | |||
992 | return flags; | ||
993 | } | ||
994 | |||
995 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
996 | |||
997 | /* Return 0 when we got an invalid instance identifier. */ | ||
998 | if (!adv_instance) | ||
999 | return 0; | ||
1000 | |||
1001 | return adv_instance->flags; | ||
1002 | } | ||
1003 | |||
1004 | static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev) | ||
1005 | { | ||
1006 | u8 instance = get_current_adv_instance(hdev); | ||
1007 | struct adv_info *adv_instance; | ||
1008 | |||
1009 | /* Ignore instance 0 */ | ||
1010 | if (instance == 0x00) | ||
1011 | return 0; | ||
1012 | |||
1013 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1014 | if (!adv_instance) | ||
1015 | return 0; | ||
1016 | |||
1017 | /* TODO: Take into account the "appearance" and "local-name" flags here. | ||
1018 | * These are currently being ignored as they are not supported. | ||
1019 | */ | ||
1020 | return adv_instance->scan_rsp_len; | ||
1021 | } | ||
1022 | |||
1023 | static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) | ||
1024 | { | ||
1025 | struct adv_info *adv_instance = NULL; | ||
1026 | u8 ad_len = 0, flags = 0; | ||
1027 | u32 instance_flags; | ||
1028 | |||
1029 | /* Return 0 when the current instance identifier is invalid. */ | ||
1030 | if (instance) { | ||
1031 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1032 | if (!adv_instance) | ||
1033 | return 0; | ||
1034 | } | ||
1035 | |||
1036 | instance_flags = get_adv_instance_flags(hdev, instance); | ||
1037 | |||
1038 | /* The Add Advertising command allows userspace to set both the general | ||
1039 | * and limited discoverable flags. | ||
1040 | */ | ||
1041 | if (instance_flags & MGMT_ADV_FLAG_DISCOV) | ||
1042 | flags |= LE_AD_GENERAL; | ||
1043 | |||
1044 | if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV) | ||
1045 | flags |= LE_AD_LIMITED; | ||
1046 | |||
1047 | if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { | ||
1048 | /* If a discovery flag wasn't provided, simply use the global | ||
1049 | * settings. | ||
1050 | */ | ||
1051 | if (!flags) | ||
1052 | flags |= get_adv_discov_flags(hdev); | ||
1053 | |||
1054 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
1055 | flags |= LE_AD_NO_BREDR; | ||
1056 | |||
1057 | /* If flags would still be empty, then there is no need to | ||
1058 | * include the "Flags" AD field". | ||
1059 | */ | ||
1060 | if (flags) { | ||
1061 | ptr[0] = 0x02; | ||
1062 | ptr[1] = EIR_FLAGS; | ||
1063 | ptr[2] = flags; | ||
1064 | |||
1065 | ad_len += 3; | ||
1066 | ptr += 3; | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | if (adv_instance) { | ||
1071 | memcpy(ptr, adv_instance->adv_data, | ||
1072 | adv_instance->adv_data_len); | ||
1073 | ad_len += adv_instance->adv_data_len; | ||
1074 | ptr += adv_instance->adv_data_len; | ||
1075 | } | ||
1076 | |||
1077 | /* Provide Tx Power only if we can provide a valid value for it */ | ||
1078 | if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && | ||
1079 | (instance_flags & MGMT_ADV_FLAG_TX_POWER)) { | ||
1080 | ptr[0] = 0x02; | ||
1081 | ptr[1] = EIR_TX_POWER; | ||
1082 | ptr[2] = (u8)hdev->adv_tx_power; | ||
1083 | |||
1084 | ad_len += 3; | ||
1085 | ptr += 3; | ||
1086 | } | ||
1087 | |||
1088 | return ad_len; | ||
1089 | } | ||
1090 | |||
1091 | static void update_inst_adv_data(struct hci_request *req, u8 instance) | ||
1092 | { | ||
1093 | struct hci_dev *hdev = req->hdev; | ||
1094 | struct hci_cp_le_set_adv_data cp; | ||
1095 | u8 len; | ||
1096 | |||
1097 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
1098 | return; | ||
1099 | |||
1100 | memset(&cp, 0, sizeof(cp)); | ||
1101 | |||
1102 | len = create_instance_adv_data(hdev, instance, cp.data); | ||
1103 | |||
1104 | /* There's nothing to do if the data hasn't changed */ | ||
1105 | if (hdev->adv_data_len == len && | ||
1106 | memcmp(cp.data, hdev->adv_data, len) == 0) | ||
1107 | return; | ||
1108 | |||
1109 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||
1110 | hdev->adv_data_len = len; | ||
1111 | |||
1112 | cp.length = len; | ||
1113 | |||
1114 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
1115 | } | ||
1116 | |||
1117 | static void update_adv_data(struct hci_request *req) | ||
1118 | { | ||
1119 | update_inst_adv_data(req, get_current_adv_instance(req->hdev)); | ||
1120 | } | ||
1121 | |||
1122 | int mgmt_update_adv_data(struct hci_dev *hdev) | ||
1123 | { | ||
1124 | struct hci_request req; | ||
1125 | |||
1126 | hci_req_init(&req, hdev); | ||
1127 | update_adv_data(&req); | ||
1128 | |||
1129 | return hci_req_run(&req, NULL); | ||
1130 | } | ||
1131 | |||
1132 | static void create_eir(struct hci_dev *hdev, u8 *data) | ||
1133 | { | ||
1134 | u8 *ptr = data; | ||
1135 | size_t name_len; | ||
1136 | |||
1137 | name_len = strlen(hdev->dev_name); | ||
1138 | |||
1139 | if (name_len > 0) { | ||
1140 | /* EIR Data type */ | ||
1141 | if (name_len > 48) { | ||
1142 | name_len = 48; | ||
1143 | ptr[1] = EIR_NAME_SHORT; | ||
1144 | } else | ||
1145 | ptr[1] = EIR_NAME_COMPLETE; | ||
1146 | |||
1147 | /* EIR Data length */ | ||
1148 | ptr[0] = name_len + 1; | ||
1149 | |||
1150 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
1151 | |||
1152 | ptr += (name_len + 2); | ||
1153 | } | ||
1154 | |||
1155 | if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) { | ||
1156 | ptr[0] = 2; | ||
1157 | ptr[1] = EIR_TX_POWER; | ||
1158 | ptr[2] = (u8) hdev->inq_tx_power; | ||
1159 | |||
1160 | ptr += 3; | ||
1161 | } | ||
1162 | |||
1163 | if (hdev->devid_source > 0) { | ||
1164 | ptr[0] = 9; | ||
1165 | ptr[1] = EIR_DEVICE_ID; | ||
1166 | |||
1167 | put_unaligned_le16(hdev->devid_source, ptr + 2); | ||
1168 | put_unaligned_le16(hdev->devid_vendor, ptr + 4); | ||
1169 | put_unaligned_le16(hdev->devid_product, ptr + 6); | ||
1170 | put_unaligned_le16(hdev->devid_version, ptr + 8); | ||
1171 | |||
1172 | ptr += 10; | ||
1173 | } | ||
1174 | |||
1175 | ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
1176 | ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
1177 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
1178 | } | ||
1179 | |||
1180 | static void update_eir(struct hci_request *req) | ||
1181 | { | ||
1182 | struct hci_dev *hdev = req->hdev; | ||
1183 | struct hci_cp_write_eir cp; | ||
1184 | |||
1185 | if (!hdev_is_powered(hdev)) | ||
1186 | return; | ||
1187 | |||
1188 | if (!lmp_ext_inq_capable(hdev)) | ||
1189 | return; | ||
1190 | |||
1191 | if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) | ||
1192 | return; | ||
1193 | |||
1194 | if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE)) | ||
1195 | return; | ||
1196 | |||
1197 | memset(&cp, 0, sizeof(cp)); | ||
1198 | |||
1199 | create_eir(hdev, cp.data); | ||
1200 | |||
1201 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) | ||
1202 | return; | ||
1203 | |||
1204 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); | ||
1205 | |||
1206 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | ||
1207 | } | ||
1208 | |||
1209 | static u8 get_service_classes(struct hci_dev *hdev) | ||
1210 | { | ||
1211 | struct bt_uuid *uuid; | ||
1212 | u8 val = 0; | ||
1213 | |||
1214 | list_for_each_entry(uuid, &hdev->uuids, list) | ||
1215 | val |= uuid->svc_hint; | ||
1216 | |||
1217 | return val; | ||
1218 | } | ||
1219 | |||
1220 | static void update_class(struct hci_request *req) | ||
1221 | { | ||
1222 | struct hci_dev *hdev = req->hdev; | ||
1223 | u8 cod[3]; | ||
1224 | |||
1225 | BT_DBG("%s", hdev->name); | ||
1226 | |||
1227 | if (!hdev_is_powered(hdev)) | ||
1228 | return; | ||
1229 | |||
1230 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
1231 | return; | ||
1232 | |||
1233 | if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE)) | ||
1234 | return; | ||
1235 | |||
1236 | cod[0] = hdev->minor_class; | ||
1237 | cod[1] = hdev->major_class; | ||
1238 | cod[2] = get_service_classes(hdev); | ||
1239 | |||
1240 | if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) | ||
1241 | cod[1] |= 0x20; | ||
1242 | |||
1243 | if (memcmp(cod, hdev->dev_class, 3) == 0) | ||
1244 | return; | ||
1245 | |||
1246 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | ||
1247 | } | ||
1248 | |||
1249 | static void disable_advertising(struct hci_request *req) | ||
1250 | { | ||
1251 | u8 enable = 0x00; | ||
1252 | |||
1253 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
1254 | } | ||
1255 | |||
1256 | static void enable_advertising(struct hci_request *req) | ||
1257 | { | ||
1258 | struct hci_dev *hdev = req->hdev; | ||
1259 | struct hci_cp_le_set_adv_param cp; | ||
1260 | u8 own_addr_type, enable = 0x01; | ||
1261 | bool connectable; | ||
1262 | u8 instance; | ||
1263 | u32 flags; | ||
1264 | |||
1265 | if (hci_conn_num(hdev, LE_LINK) > 0) | ||
1266 | return; | ||
1267 | |||
1268 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | ||
1269 | disable_advertising(req); | ||
1270 | |||
1271 | /* Clear the HCI_LE_ADV bit temporarily so that the | ||
1272 | * hci_update_random_address knows that it's safe to go ahead | ||
1273 | * and write a new random address. The flag will be set back on | ||
1274 | * as soon as the SET_ADV_ENABLE HCI command completes. | ||
1275 | */ | ||
1276 | hci_dev_clear_flag(hdev, HCI_LE_ADV); | ||
1277 | |||
1278 | instance = get_current_adv_instance(hdev); | ||
1279 | flags = get_adv_instance_flags(hdev, instance); | ||
1280 | |||
1281 | /* If the "connectable" instance flag was not set, then choose between | ||
1282 | * ADV_IND and ADV_NONCONN_IND based on the global connectable setting. | ||
1283 | */ | ||
1284 | connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) || | ||
1285 | get_connectable(hdev); | ||
1286 | |||
1287 | /* Set require_privacy to true only when non-connectable | ||
1288 | * advertising is used. In that case it is fine to use a | ||
1289 | * non-resolvable private address. | ||
1290 | */ | ||
1291 | if (hci_update_random_address(req, !connectable, &own_addr_type) < 0) | ||
1292 | return; | ||
1293 | |||
1294 | memset(&cp, 0, sizeof(cp)); | ||
1295 | cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval); | ||
1296 | cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval); | ||
1297 | |||
1298 | if (connectable) | ||
1299 | cp.type = LE_ADV_IND; | ||
1300 | else if (get_cur_adv_instance_scan_rsp_len(hdev)) | ||
1301 | cp.type = LE_ADV_SCAN_IND; | ||
1302 | else | ||
1303 | cp.type = LE_ADV_NONCONN_IND; | ||
1304 | |||
1305 | cp.own_address_type = own_addr_type; | ||
1306 | cp.channel_map = hdev->le_adv_channel_map; | ||
1307 | |||
1308 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); | ||
1309 | |||
1310 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
1311 | } | ||
1312 | |||
1313 | static void service_cache_off(struct work_struct *work) | 776 | static void service_cache_off(struct work_struct *work) |
1314 | { | 777 | { |
1315 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 778 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
@@ -1323,8 +786,8 @@ static void service_cache_off(struct work_struct *work) | |||
1323 | 786 | ||
1324 | hci_dev_lock(hdev); | 787 | hci_dev_lock(hdev); |
1325 | 788 | ||
1326 | update_eir(&req); | 789 | __hci_req_update_eir(&req); |
1327 | update_class(&req); | 790 | __hci_req_update_class(&req); |
1328 | 791 | ||
1329 | hci_dev_unlock(hdev); | 792 | hci_dev_unlock(hdev); |
1330 | 793 | ||
@@ -1345,10 +808,11 @@ static void rpa_expired(struct work_struct *work) | |||
1345 | return; | 808 | return; |
1346 | 809 | ||
1347 | /* The generation of a new RPA and programming it into the | 810 | /* The generation of a new RPA and programming it into the |
1348 | * controller happens in the enable_advertising() function. | 811 | * controller happens in the hci_req_enable_advertising() |
812 | * function. | ||
1349 | */ | 813 | */ |
1350 | hci_req_init(&req, hdev); | 814 | hci_req_init(&req, hdev); |
1351 | enable_advertising(&req); | 815 | __hci_req_enable_advertising(&req); |
1352 | hci_req_run(&req, NULL); | 816 | hci_req_run(&req, NULL); |
1353 | } | 817 | } |
1354 | 818 | ||
@@ -1416,51 +880,7 @@ static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode) | |||
1416 | } | 880 | } |
1417 | } | 881 | } |
1418 | 882 | ||
1419 | static bool hci_stop_discovery(struct hci_request *req) | 883 | void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev, u8 instance) |
1420 | { | ||
1421 | struct hci_dev *hdev = req->hdev; | ||
1422 | struct hci_cp_remote_name_req_cancel cp; | ||
1423 | struct inquiry_entry *e; | ||
1424 | |||
1425 | switch (hdev->discovery.state) { | ||
1426 | case DISCOVERY_FINDING: | ||
1427 | if (test_bit(HCI_INQUIRY, &hdev->flags)) | ||
1428 | hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL); | ||
1429 | |||
1430 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { | ||
1431 | cancel_delayed_work(&hdev->le_scan_disable); | ||
1432 | hci_req_add_le_scan_disable(req); | ||
1433 | } | ||
1434 | |||
1435 | return true; | ||
1436 | |||
1437 | case DISCOVERY_RESOLVING: | ||
1438 | e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, | ||
1439 | NAME_PENDING); | ||
1440 | if (!e) | ||
1441 | break; | ||
1442 | |||
1443 | bacpy(&cp.bdaddr, &e->data.bdaddr); | ||
1444 | hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp), | ||
1445 | &cp); | ||
1446 | |||
1447 | return true; | ||
1448 | |||
1449 | default: | ||
1450 | /* Passive scanning */ | ||
1451 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { | ||
1452 | hci_req_add_le_scan_disable(req); | ||
1453 | return true; | ||
1454 | } | ||
1455 | |||
1456 | break; | ||
1457 | } | ||
1458 | |||
1459 | return false; | ||
1460 | } | ||
1461 | |||
1462 | static void advertising_added(struct sock *sk, struct hci_dev *hdev, | ||
1463 | u8 instance) | ||
1464 | { | 884 | { |
1465 | struct mgmt_ev_advertising_added ev; | 885 | struct mgmt_ev_advertising_added ev; |
1466 | 886 | ||
@@ -1469,8 +889,8 @@ static void advertising_added(struct sock *sk, struct hci_dev *hdev, | |||
1469 | mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk); | 889 | mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk); |
1470 | } | 890 | } |
1471 | 891 | ||
1472 | static void advertising_removed(struct sock *sk, struct hci_dev *hdev, | 892 | void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev, |
1473 | u8 instance) | 893 | u8 instance) |
1474 | { | 894 | { |
1475 | struct mgmt_ev_advertising_removed ev; | 895 | struct mgmt_ev_advertising_removed ev; |
1476 | 896 | ||
@@ -1479,65 +899,6 @@ static void advertising_removed(struct sock *sk, struct hci_dev *hdev, | |||
1479 | mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk); | 899 | mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk); |
1480 | } | 900 | } |
1481 | 901 | ||
1482 | static int schedule_adv_instance(struct hci_request *req, u8 instance, | ||
1483 | bool force) { | ||
1484 | struct hci_dev *hdev = req->hdev; | ||
1485 | struct adv_info *adv_instance = NULL; | ||
1486 | u16 timeout; | ||
1487 | |||
1488 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
1489 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
1490 | return -EPERM; | ||
1491 | |||
1492 | if (hdev->adv_instance_timeout) | ||
1493 | return -EBUSY; | ||
1494 | |||
1495 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1496 | if (!adv_instance) | ||
1497 | return -ENOENT; | ||
1498 | |||
1499 | /* A zero timeout means unlimited advertising. As long as there is | ||
1500 | * only one instance, duration should be ignored. We still set a timeout | ||
1501 | * in case further instances are being added later on. | ||
1502 | * | ||
1503 | * If the remaining lifetime of the instance is more than the duration | ||
1504 | * then the timeout corresponds to the duration, otherwise it will be | ||
1505 | * reduced to the remaining instance lifetime. | ||
1506 | */ | ||
1507 | if (adv_instance->timeout == 0 || | ||
1508 | adv_instance->duration <= adv_instance->remaining_time) | ||
1509 | timeout = adv_instance->duration; | ||
1510 | else | ||
1511 | timeout = adv_instance->remaining_time; | ||
1512 | |||
1513 | /* The remaining time is being reduced unless the instance is being | ||
1514 | * advertised without time limit. | ||
1515 | */ | ||
1516 | if (adv_instance->timeout) | ||
1517 | adv_instance->remaining_time = | ||
1518 | adv_instance->remaining_time - timeout; | ||
1519 | |||
1520 | hdev->adv_instance_timeout = timeout; | ||
1521 | queue_delayed_work(hdev->workqueue, | ||
1522 | &hdev->adv_instance_expire, | ||
1523 | msecs_to_jiffies(timeout * 1000)); | ||
1524 | |||
1525 | /* If we're just re-scheduling the same instance again then do not | ||
1526 | * execute any HCI commands. This happens when a single instance is | ||
1527 | * being advertised. | ||
1528 | */ | ||
1529 | if (!force && hdev->cur_adv_instance == instance && | ||
1530 | hci_dev_test_flag(hdev, HCI_LE_ADV)) | ||
1531 | return 0; | ||
1532 | |||
1533 | hdev->cur_adv_instance = instance; | ||
1534 | update_adv_data(req); | ||
1535 | update_scan_rsp_data(req); | ||
1536 | enable_advertising(req); | ||
1537 | |||
1538 | return 0; | ||
1539 | } | ||
1540 | |||
1541 | static void cancel_adv_timeout(struct hci_dev *hdev) | 902 | static void cancel_adv_timeout(struct hci_dev *hdev) |
1542 | { | 903 | { |
1543 | if (hdev->adv_instance_timeout) { | 904 | if (hdev->adv_instance_timeout) { |
@@ -1546,76 +907,6 @@ static void cancel_adv_timeout(struct hci_dev *hdev) | |||
1546 | } | 907 | } |
1547 | } | 908 | } |
1548 | 909 | ||
1549 | /* For a single instance: | ||
1550 | * - force == true: The instance will be removed even when its remaining | ||
1551 | * lifetime is not zero. | ||
1552 | * - force == false: the instance will be deactivated but kept stored unless | ||
1553 | * the remaining lifetime is zero. | ||
1554 | * | ||
1555 | * For instance == 0x00: | ||
1556 | * - force == true: All instances will be removed regardless of their timeout | ||
1557 | * setting. | ||
1558 | * - force == false: Only instances that have a timeout will be removed. | ||
1559 | */ | ||
1560 | static void clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, | ||
1561 | u8 instance, bool force) | ||
1562 | { | ||
1563 | struct adv_info *adv_instance, *n, *next_instance = NULL; | ||
1564 | int err; | ||
1565 | u8 rem_inst; | ||
1566 | |||
1567 | /* Cancel any timeout concerning the removed instance(s). */ | ||
1568 | if (!instance || hdev->cur_adv_instance == instance) | ||
1569 | cancel_adv_timeout(hdev); | ||
1570 | |||
1571 | /* Get the next instance to advertise BEFORE we remove | ||
1572 | * the current one. This can be the same instance again | ||
1573 | * if there is only one instance. | ||
1574 | */ | ||
1575 | if (instance && hdev->cur_adv_instance == instance) | ||
1576 | next_instance = hci_get_next_instance(hdev, instance); | ||
1577 | |||
1578 | if (instance == 0x00) { | ||
1579 | list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, | ||
1580 | list) { | ||
1581 | if (!(force || adv_instance->timeout)) | ||
1582 | continue; | ||
1583 | |||
1584 | rem_inst = adv_instance->instance; | ||
1585 | err = hci_remove_adv_instance(hdev, rem_inst); | ||
1586 | if (!err) | ||
1587 | advertising_removed(NULL, hdev, rem_inst); | ||
1588 | } | ||
1589 | hdev->cur_adv_instance = 0x00; | ||
1590 | } else { | ||
1591 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1592 | |||
1593 | if (force || (adv_instance && adv_instance->timeout && | ||
1594 | !adv_instance->remaining_time)) { | ||
1595 | /* Don't advertise a removed instance. */ | ||
1596 | if (next_instance && | ||
1597 | next_instance->instance == instance) | ||
1598 | next_instance = NULL; | ||
1599 | |||
1600 | err = hci_remove_adv_instance(hdev, instance); | ||
1601 | if (!err) | ||
1602 | advertising_removed(NULL, hdev, instance); | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1606 | if (list_empty(&hdev->adv_instances)) { | ||
1607 | hdev->cur_adv_instance = 0x00; | ||
1608 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE); | ||
1609 | } | ||
1610 | |||
1611 | if (!req || !hdev_is_powered(hdev) || | ||
1612 | hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
1613 | return; | ||
1614 | |||
1615 | if (next_instance) | ||
1616 | schedule_adv_instance(req, next_instance->instance, false); | ||
1617 | } | ||
1618 | |||
1619 | static int clean_up_hci_state(struct hci_dev *hdev) | 910 | static int clean_up_hci_state(struct hci_dev *hdev) |
1620 | { | 911 | { |
1621 | struct hci_request req; | 912 | struct hci_request req; |
@@ -1631,12 +922,12 @@ static int clean_up_hci_state(struct hci_dev *hdev) | |||
1631 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 922 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
1632 | } | 923 | } |
1633 | 924 | ||
1634 | clear_adv_instance(hdev, NULL, 0x00, false); | 925 | hci_req_clear_adv_instance(hdev, NULL, 0x00, false); |
1635 | 926 | ||
1636 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | 927 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) |
1637 | disable_advertising(&req); | 928 | __hci_req_disable_advertising(&req); |
1638 | 929 | ||
1639 | discov_stopped = hci_stop_discovery(&req); | 930 | discov_stopped = hci_req_stop_discovery(&req); |
1640 | 931 | ||
1641 | list_for_each_entry(conn, &hdev->conn_hash.list, list) { | 932 | list_for_each_entry(conn, &hdev->conn_hash.list, list) { |
1642 | /* 0x15 == Terminated due to Power Off */ | 933 | /* 0x15 == Terminated due to Power Off */ |
@@ -1671,17 +962,6 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1671 | goto failed; | 962 | goto failed; |
1672 | } | 963 | } |
1673 | 964 | ||
1674 | if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) { | ||
1675 | cancel_delayed_work(&hdev->power_off); | ||
1676 | |||
1677 | if (cp->val) { | ||
1678 | mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, | ||
1679 | data, len); | ||
1680 | err = mgmt_powered(hdev, 1); | ||
1681 | goto failed; | ||
1682 | } | ||
1683 | } | ||
1684 | |||
1685 | if (!!cp->val == hdev_is_powered(hdev)) { | 965 | if (!!cp->val == hdev_is_powered(hdev)) { |
1686 | err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev); | 966 | err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev); |
1687 | goto failed; | 967 | goto failed; |
@@ -1805,13 +1085,9 @@ static u8 mgmt_le_support(struct hci_dev *hdev) | |||
1805 | return MGMT_STATUS_SUCCESS; | 1085 | return MGMT_STATUS_SUCCESS; |
1806 | } | 1086 | } |
1807 | 1087 | ||
1808 | static void set_discoverable_complete(struct hci_dev *hdev, u8 status, | 1088 | void mgmt_set_discoverable_complete(struct hci_dev *hdev, u8 status) |
1809 | u16 opcode) | ||
1810 | { | 1089 | { |
1811 | struct mgmt_pending_cmd *cmd; | 1090 | struct mgmt_pending_cmd *cmd; |
1812 | struct mgmt_mode *cp; | ||
1813 | struct hci_request req; | ||
1814 | bool changed; | ||
1815 | 1091 | ||
1816 | BT_DBG("status 0x%02x", status); | 1092 | BT_DBG("status 0x%02x", status); |
1817 | 1093 | ||
@@ -1828,33 +1104,14 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status, | |||
1828 | goto remove_cmd; | 1104 | goto remove_cmd; |
1829 | } | 1105 | } |
1830 | 1106 | ||
1831 | cp = cmd->param; | 1107 | if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE) && |
1832 | if (cp->val) { | 1108 | hdev->discov_timeout > 0) { |
1833 | changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE); | 1109 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); |
1834 | 1110 | queue_delayed_work(hdev->req_workqueue, &hdev->discov_off, to); | |
1835 | if (hdev->discov_timeout > 0) { | ||
1836 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); | ||
1837 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, | ||
1838 | to); | ||
1839 | } | ||
1840 | } else { | ||
1841 | changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE); | ||
1842 | } | 1111 | } |
1843 | 1112 | ||
1844 | send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); | 1113 | send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); |
1845 | 1114 | new_settings(hdev, cmd->sk); | |
1846 | if (changed) | ||
1847 | new_settings(hdev, cmd->sk); | ||
1848 | |||
1849 | /* When the discoverable mode gets changed, make sure | ||
1850 | * that class of device has the limited discoverable | ||
1851 | * bit correctly set. Also update page scan based on whitelist | ||
1852 | * entries. | ||
1853 | */ | ||
1854 | hci_req_init(&req, hdev); | ||
1855 | __hci_update_page_scan(&req); | ||
1856 | update_class(&req); | ||
1857 | hci_req_run(&req, NULL); | ||
1858 | 1115 | ||
1859 | remove_cmd: | 1116 | remove_cmd: |
1860 | mgmt_pending_remove(cmd); | 1117 | mgmt_pending_remove(cmd); |
@@ -1868,9 +1125,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1868 | { | 1125 | { |
1869 | struct mgmt_cp_set_discoverable *cp = data; | 1126 | struct mgmt_cp_set_discoverable *cp = data; |
1870 | struct mgmt_pending_cmd *cmd; | 1127 | struct mgmt_pending_cmd *cmd; |
1871 | struct hci_request req; | ||
1872 | u16 timeout; | 1128 | u16 timeout; |
1873 | u8 scan; | ||
1874 | int err; | 1129 | int err; |
1875 | 1130 | ||
1876 | BT_DBG("request for %s", hdev->name); | 1131 | BT_DBG("request for %s", hdev->name); |
@@ -1949,8 +1204,8 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1949 | 1204 | ||
1950 | if (cp->val && hdev->discov_timeout > 0) { | 1205 | if (cp->val && hdev->discov_timeout > 0) { |
1951 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); | 1206 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); |
1952 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, | 1207 | queue_delayed_work(hdev->req_workqueue, |
1953 | to); | 1208 | &hdev->discov_off, to); |
1954 | } | 1209 | } |
1955 | 1210 | ||
1956 | err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); | 1211 | err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); |
@@ -1970,105 +1225,28 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1970 | cancel_delayed_work(&hdev->discov_off); | 1225 | cancel_delayed_work(&hdev->discov_off); |
1971 | hdev->discov_timeout = timeout; | 1226 | hdev->discov_timeout = timeout; |
1972 | 1227 | ||
1228 | if (cp->val) | ||
1229 | hci_dev_set_flag(hdev, HCI_DISCOVERABLE); | ||
1230 | else | ||
1231 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); | ||
1232 | |||
1973 | /* Limited discoverable mode */ | 1233 | /* Limited discoverable mode */ |
1974 | if (cp->val == 0x02) | 1234 | if (cp->val == 0x02) |
1975 | hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE); | 1235 | hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE); |
1976 | else | 1236 | else |
1977 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | 1237 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); |
1978 | 1238 | ||
1979 | hci_req_init(&req, hdev); | 1239 | queue_work(hdev->req_workqueue, &hdev->discoverable_update); |
1980 | 1240 | err = 0; | |
1981 | /* The procedure for LE-only controllers is much simpler - just | ||
1982 | * update the advertising data. | ||
1983 | */ | ||
1984 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
1985 | goto update_ad; | ||
1986 | |||
1987 | scan = SCAN_PAGE; | ||
1988 | |||
1989 | if (cp->val) { | ||
1990 | struct hci_cp_write_current_iac_lap hci_cp; | ||
1991 | |||
1992 | if (cp->val == 0x02) { | ||
1993 | /* Limited discoverable mode */ | ||
1994 | hci_cp.num_iac = min_t(u8, hdev->num_iac, 2); | ||
1995 | hci_cp.iac_lap[0] = 0x00; /* LIAC */ | ||
1996 | hci_cp.iac_lap[1] = 0x8b; | ||
1997 | hci_cp.iac_lap[2] = 0x9e; | ||
1998 | hci_cp.iac_lap[3] = 0x33; /* GIAC */ | ||
1999 | hci_cp.iac_lap[4] = 0x8b; | ||
2000 | hci_cp.iac_lap[5] = 0x9e; | ||
2001 | } else { | ||
2002 | /* General discoverable mode */ | ||
2003 | hci_cp.num_iac = 1; | ||
2004 | hci_cp.iac_lap[0] = 0x33; /* GIAC */ | ||
2005 | hci_cp.iac_lap[1] = 0x8b; | ||
2006 | hci_cp.iac_lap[2] = 0x9e; | ||
2007 | } | ||
2008 | |||
2009 | hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP, | ||
2010 | (hci_cp.num_iac * 3) + 1, &hci_cp); | ||
2011 | |||
2012 | scan |= SCAN_INQUIRY; | ||
2013 | } else { | ||
2014 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | ||
2015 | } | ||
2016 | |||
2017 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); | ||
2018 | |||
2019 | update_ad: | ||
2020 | update_adv_data(&req); | ||
2021 | |||
2022 | err = hci_req_run(&req, set_discoverable_complete); | ||
2023 | if (err < 0) | ||
2024 | mgmt_pending_remove(cmd); | ||
2025 | 1241 | ||
2026 | failed: | 1242 | failed: |
2027 | hci_dev_unlock(hdev); | 1243 | hci_dev_unlock(hdev); |
2028 | return err; | 1244 | return err; |
2029 | } | 1245 | } |
2030 | 1246 | ||
2031 | static void write_fast_connectable(struct hci_request *req, bool enable) | 1247 | void mgmt_set_connectable_complete(struct hci_dev *hdev, u8 status) |
2032 | { | ||
2033 | struct hci_dev *hdev = req->hdev; | ||
2034 | struct hci_cp_write_page_scan_activity acp; | ||
2035 | u8 type; | ||
2036 | |||
2037 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
2038 | return; | ||
2039 | |||
2040 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
2041 | return; | ||
2042 | |||
2043 | if (enable) { | ||
2044 | type = PAGE_SCAN_TYPE_INTERLACED; | ||
2045 | |||
2046 | /* 160 msec page scan interval */ | ||
2047 | acp.interval = cpu_to_le16(0x0100); | ||
2048 | } else { | ||
2049 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | ||
2050 | |||
2051 | /* default 1.28 sec page scan */ | ||
2052 | acp.interval = cpu_to_le16(0x0800); | ||
2053 | } | ||
2054 | |||
2055 | acp.window = cpu_to_le16(0x0012); | ||
2056 | |||
2057 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || | ||
2058 | __cpu_to_le16(hdev->page_scan_window) != acp.window) | ||
2059 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, | ||
2060 | sizeof(acp), &acp); | ||
2061 | |||
2062 | if (hdev->page_scan_type != type) | ||
2063 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | ||
2064 | } | ||
2065 | |||
2066 | static void set_connectable_complete(struct hci_dev *hdev, u8 status, | ||
2067 | u16 opcode) | ||
2068 | { | 1248 | { |
2069 | struct mgmt_pending_cmd *cmd; | 1249 | struct mgmt_pending_cmd *cmd; |
2070 | struct mgmt_mode *cp; | ||
2071 | bool conn_changed, discov_changed; | ||
2072 | 1250 | ||
2073 | BT_DBG("status 0x%02x", status); | 1251 | BT_DBG("status 0x%02x", status); |
2074 | 1252 | ||
@@ -2084,27 +1262,8 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status, | |||
2084 | goto remove_cmd; | 1262 | goto remove_cmd; |
2085 | } | 1263 | } |
2086 | 1264 | ||
2087 | cp = cmd->param; | ||
2088 | if (cp->val) { | ||
2089 | conn_changed = !hci_dev_test_and_set_flag(hdev, | ||
2090 | HCI_CONNECTABLE); | ||
2091 | discov_changed = false; | ||
2092 | } else { | ||
2093 | conn_changed = hci_dev_test_and_clear_flag(hdev, | ||
2094 | HCI_CONNECTABLE); | ||
2095 | discov_changed = hci_dev_test_and_clear_flag(hdev, | ||
2096 | HCI_DISCOVERABLE); | ||
2097 | } | ||
2098 | |||
2099 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); | 1265 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); |
2100 | 1266 | new_settings(hdev, cmd->sk); | |
2101 | if (conn_changed || discov_changed) { | ||
2102 | new_settings(hdev, cmd->sk); | ||
2103 | hci_update_page_scan(hdev); | ||
2104 | if (discov_changed) | ||
2105 | mgmt_update_adv_data(hdev); | ||
2106 | hci_update_background_scan(hdev); | ||
2107 | } | ||
2108 | 1267 | ||
2109 | remove_cmd: | 1268 | remove_cmd: |
2110 | mgmt_pending_remove(cmd); | 1269 | mgmt_pending_remove(cmd); |
@@ -2134,7 +1293,7 @@ static int set_connectable_update_settings(struct hci_dev *hdev, | |||
2134 | return err; | 1293 | return err; |
2135 | 1294 | ||
2136 | if (changed) { | 1295 | if (changed) { |
2137 | hci_update_page_scan(hdev); | 1296 | hci_req_update_scan(hdev); |
2138 | hci_update_background_scan(hdev); | 1297 | hci_update_background_scan(hdev); |
2139 | return new_settings(hdev, sk); | 1298 | return new_settings(hdev, sk); |
2140 | } | 1299 | } |
@@ -2147,8 +1306,6 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2147 | { | 1306 | { |
2148 | struct mgmt_mode *cp = data; | 1307 | struct mgmt_mode *cp = data; |
2149 | struct mgmt_pending_cmd *cmd; | 1308 | struct mgmt_pending_cmd *cmd; |
2150 | struct hci_request req; | ||
2151 | u8 scan; | ||
2152 | int err; | 1309 | int err; |
2153 | 1310 | ||
2154 | BT_DBG("request for %s", hdev->name); | 1311 | BT_DBG("request for %s", hdev->name); |
@@ -2182,57 +1339,19 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2182 | goto failed; | 1339 | goto failed; |
2183 | } | 1340 | } |
2184 | 1341 | ||
2185 | hci_req_init(&req, hdev); | 1342 | if (cp->val) { |
2186 | 1343 | hci_dev_set_flag(hdev, HCI_CONNECTABLE); | |
2187 | /* If BR/EDR is not enabled and we disable advertising as a | 1344 | } else { |
2188 | * by-product of disabling connectable, we need to update the | 1345 | if (hdev->discov_timeout > 0) |
2189 | * advertising flags. | 1346 | cancel_delayed_work(&hdev->discov_off); |
2190 | */ | ||
2191 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { | ||
2192 | if (!cp->val) { | ||
2193 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | ||
2194 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); | ||
2195 | } | ||
2196 | update_adv_data(&req); | ||
2197 | } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { | ||
2198 | if (cp->val) { | ||
2199 | scan = SCAN_PAGE; | ||
2200 | } else { | ||
2201 | /* If we don't have any whitelist entries just | ||
2202 | * disable all scanning. If there are entries | ||
2203 | * and we had both page and inquiry scanning | ||
2204 | * enabled then fall back to only page scanning. | ||
2205 | * Otherwise no changes are needed. | ||
2206 | */ | ||
2207 | if (list_empty(&hdev->whitelist)) | ||
2208 | scan = SCAN_DISABLED; | ||
2209 | else if (test_bit(HCI_ISCAN, &hdev->flags)) | ||
2210 | scan = SCAN_PAGE; | ||
2211 | else | ||
2212 | goto no_scan_update; | ||
2213 | |||
2214 | if (test_bit(HCI_ISCAN, &hdev->flags) && | ||
2215 | hdev->discov_timeout > 0) | ||
2216 | cancel_delayed_work(&hdev->discov_off); | ||
2217 | } | ||
2218 | 1347 | ||
2219 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1348 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); |
1349 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); | ||
1350 | hci_dev_clear_flag(hdev, HCI_CONNECTABLE); | ||
2220 | } | 1351 | } |
2221 | 1352 | ||
2222 | no_scan_update: | 1353 | queue_work(hdev->req_workqueue, &hdev->connectable_update); |
2223 | /* Update the advertising parameters if necessary */ | 1354 | err = 0; |
2224 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
2225 | hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
2226 | enable_advertising(&req); | ||
2227 | |||
2228 | err = hci_req_run(&req, set_connectable_complete); | ||
2229 | if (err < 0) { | ||
2230 | mgmt_pending_remove(cmd); | ||
2231 | if (err == -ENODATA) | ||
2232 | err = set_connectable_update_settings(hdev, sk, | ||
2233 | cp->val); | ||
2234 | goto failed; | ||
2235 | } | ||
2236 | 1355 | ||
2237 | failed: | 1356 | failed: |
2238 | hci_dev_unlock(hdev); | 1357 | hci_dev_unlock(hdev); |
@@ -2508,10 +1627,10 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) | |||
2508 | struct hci_request req; | 1627 | struct hci_request req; |
2509 | 1628 | ||
2510 | hci_req_init(&req, hdev); | 1629 | hci_req_init(&req, hdev); |
2511 | update_adv_data(&req); | 1630 | __hci_req_update_adv_data(&req, 0x00); |
2512 | update_scan_rsp_data(&req); | 1631 | __hci_req_update_scan_rsp_data(&req, 0x00); |
2513 | __hci_update_background_scan(&req); | ||
2514 | hci_req_run(&req, NULL); | 1632 | hci_req_run(&req, NULL); |
1633 | hci_update_background_scan(hdev); | ||
2515 | } | 1634 | } |
2516 | 1635 | ||
2517 | unlock: | 1636 | unlock: |
@@ -2560,7 +1679,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
2560 | enabled = lmp_host_le_capable(hdev); | 1679 | enabled = lmp_host_le_capable(hdev); |
2561 | 1680 | ||
2562 | if (!val) | 1681 | if (!val) |
2563 | clear_adv_instance(hdev, NULL, 0x00, true); | 1682 | hci_req_clear_adv_instance(hdev, NULL, 0x00, true); |
2564 | 1683 | ||
2565 | if (!hdev_is_powered(hdev) || val == enabled) { | 1684 | if (!hdev_is_powered(hdev) || val == enabled) { |
2566 | bool changed = false; | 1685 | bool changed = false; |
@@ -2607,7 +1726,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
2607 | hci_cp.simul = 0x00; | 1726 | hci_cp.simul = 0x00; |
2608 | } else { | 1727 | } else { |
2609 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | 1728 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) |
2610 | disable_advertising(&req); | 1729 | __hci_req_disable_advertising(&req); |
2611 | } | 1730 | } |
2612 | 1731 | ||
2613 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), | 1732 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), |
@@ -2722,8 +1841,8 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
2722 | 1841 | ||
2723 | hci_req_init(&req, hdev); | 1842 | hci_req_init(&req, hdev); |
2724 | 1843 | ||
2725 | update_class(&req); | 1844 | __hci_req_update_class(&req); |
2726 | update_eir(&req); | 1845 | __hci_req_update_eir(&req); |
2727 | 1846 | ||
2728 | err = hci_req_run(&req, add_uuid_complete); | 1847 | err = hci_req_run(&req, add_uuid_complete); |
2729 | if (err < 0) { | 1848 | if (err < 0) { |
@@ -2822,8 +1941,8 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2822 | update_class: | 1941 | update_class: |
2823 | hci_req_init(&req, hdev); | 1942 | hci_req_init(&req, hdev); |
2824 | 1943 | ||
2825 | update_class(&req); | 1944 | __hci_req_update_class(&req); |
2826 | update_eir(&req); | 1945 | __hci_req_update_eir(&req); |
2827 | 1946 | ||
2828 | err = hci_req_run(&req, remove_uuid_complete); | 1947 | err = hci_req_run(&req, remove_uuid_complete); |
2829 | if (err < 0) { | 1948 | if (err < 0) { |
@@ -2898,10 +2017,10 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2898 | hci_dev_unlock(hdev); | 2017 | hci_dev_unlock(hdev); |
2899 | cancel_delayed_work_sync(&hdev->service_cache); | 2018 | cancel_delayed_work_sync(&hdev->service_cache); |
2900 | hci_dev_lock(hdev); | 2019 | hci_dev_lock(hdev); |
2901 | update_eir(&req); | 2020 | __hci_req_update_eir(&req); |
2902 | } | 2021 | } |
2903 | 2022 | ||
2904 | update_class(&req); | 2023 | __hci_req_update_class(&req); |
2905 | 2024 | ||
2906 | err = hci_req_run(&req, set_class_complete); | 2025 | err = hci_req_run(&req, set_class_complete); |
2907 | if (err < 0) { | 2026 | if (err < 0) { |
@@ -3561,8 +2680,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3561 | 2680 | ||
3562 | conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr, | 2681 | conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr, |
3563 | addr_type, sec_level, | 2682 | addr_type, sec_level, |
3564 | HCI_LE_CONN_TIMEOUT, | 2683 | HCI_LE_CONN_TIMEOUT); |
3565 | HCI_ROLE_MASTER); | ||
3566 | } | 2684 | } |
3567 | 2685 | ||
3568 | if (IS_ERR(conn)) { | 2686 | if (IS_ERR(conn)) { |
@@ -3803,16 +2921,6 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
3803 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); | 2921 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); |
3804 | } | 2922 | } |
3805 | 2923 | ||
3806 | static void update_name(struct hci_request *req) | ||
3807 | { | ||
3808 | struct hci_dev *hdev = req->hdev; | ||
3809 | struct hci_cp_write_local_name cp; | ||
3810 | |||
3811 | memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); | ||
3812 | |||
3813 | hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); | ||
3814 | } | ||
3815 | |||
3816 | static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode) | 2924 | static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode) |
3817 | { | 2925 | { |
3818 | struct mgmt_cp_set_local_name *cp; | 2926 | struct mgmt_cp_set_local_name *cp; |
@@ -3891,15 +2999,15 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3891 | hci_req_init(&req, hdev); | 2999 | hci_req_init(&req, hdev); |
3892 | 3000 | ||
3893 | if (lmp_bredr_capable(hdev)) { | 3001 | if (lmp_bredr_capable(hdev)) { |
3894 | update_name(&req); | 3002 | __hci_req_update_name(&req); |
3895 | update_eir(&req); | 3003 | __hci_req_update_eir(&req); |
3896 | } | 3004 | } |
3897 | 3005 | ||
3898 | /* The name is stored in the scan response data and so | 3006 | /* The name is stored in the scan response data and so |
3899 | * no need to udpate the advertising data here. | 3007 | * no need to udpate the advertising data here. |
3900 | */ | 3008 | */ |
3901 | if (lmp_le_capable(hdev)) | 3009 | if (lmp_le_capable(hdev)) |
3902 | update_scan_rsp_data(&req); | 3010 | __hci_req_update_scan_rsp_data(&req, hdev->cur_adv_instance); |
3903 | 3011 | ||
3904 | err = hci_req_run(&req, set_name_complete); | 3012 | err = hci_req_run(&req, set_name_complete); |
3905 | if (err < 0) | 3013 | if (err < 0) |
@@ -4164,145 +3272,9 @@ done: | |||
4164 | return err; | 3272 | return err; |
4165 | } | 3273 | } |
4166 | 3274 | ||
4167 | static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status) | 3275 | void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status) |
4168 | { | ||
4169 | struct hci_dev *hdev = req->hdev; | ||
4170 | struct hci_cp_inquiry cp; | ||
4171 | /* General inquiry access code (GIAC) */ | ||
4172 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; | ||
4173 | |||
4174 | *status = mgmt_bredr_support(hdev); | ||
4175 | if (*status) | ||
4176 | return false; | ||
4177 | |||
4178 | if (hci_dev_test_flag(hdev, HCI_INQUIRY)) { | ||
4179 | *status = MGMT_STATUS_BUSY; | ||
4180 | return false; | ||
4181 | } | ||
4182 | |||
4183 | hci_inquiry_cache_flush(hdev); | ||
4184 | |||
4185 | memset(&cp, 0, sizeof(cp)); | ||
4186 | memcpy(&cp.lap, lap, sizeof(cp.lap)); | ||
4187 | cp.length = DISCOV_BREDR_INQUIRY_LEN; | ||
4188 | |||
4189 | hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); | ||
4190 | |||
4191 | return true; | ||
4192 | } | ||
4193 | |||
4194 | static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status) | ||
4195 | { | ||
4196 | struct hci_dev *hdev = req->hdev; | ||
4197 | struct hci_cp_le_set_scan_param param_cp; | ||
4198 | struct hci_cp_le_set_scan_enable enable_cp; | ||
4199 | u8 own_addr_type; | ||
4200 | int err; | ||
4201 | |||
4202 | *status = mgmt_le_support(hdev); | ||
4203 | if (*status) | ||
4204 | return false; | ||
4205 | |||
4206 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) { | ||
4207 | /* Don't let discovery abort an outgoing connection attempt | ||
4208 | * that's using directed advertising. | ||
4209 | */ | ||
4210 | if (hci_lookup_le_connect(hdev)) { | ||
4211 | *status = MGMT_STATUS_REJECTED; | ||
4212 | return false; | ||
4213 | } | ||
4214 | |||
4215 | cancel_adv_timeout(hdev); | ||
4216 | disable_advertising(req); | ||
4217 | } | ||
4218 | |||
4219 | /* If controller is scanning, it means the background scanning is | ||
4220 | * running. Thus, we should temporarily stop it in order to set the | ||
4221 | * discovery scanning parameters. | ||
4222 | */ | ||
4223 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) | ||
4224 | hci_req_add_le_scan_disable(req); | ||
4225 | |||
4226 | /* All active scans will be done with either a resolvable private | ||
4227 | * address (when privacy feature has been enabled) or non-resolvable | ||
4228 | * private address. | ||
4229 | */ | ||
4230 | err = hci_update_random_address(req, true, &own_addr_type); | ||
4231 | if (err < 0) { | ||
4232 | *status = MGMT_STATUS_FAILED; | ||
4233 | return false; | ||
4234 | } | ||
4235 | |||
4236 | memset(¶m_cp, 0, sizeof(param_cp)); | ||
4237 | param_cp.type = LE_SCAN_ACTIVE; | ||
4238 | param_cp.interval = cpu_to_le16(interval); | ||
4239 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); | ||
4240 | param_cp.own_address_type = own_addr_type; | ||
4241 | |||
4242 | hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), | ||
4243 | ¶m_cp); | ||
4244 | |||
4245 | memset(&enable_cp, 0, sizeof(enable_cp)); | ||
4246 | enable_cp.enable = LE_SCAN_ENABLE; | ||
4247 | enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; | ||
4248 | |||
4249 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp), | ||
4250 | &enable_cp); | ||
4251 | |||
4252 | return true; | ||
4253 | } | ||
4254 | |||
4255 | static bool trigger_discovery(struct hci_request *req, u8 *status) | ||
4256 | { | ||
4257 | struct hci_dev *hdev = req->hdev; | ||
4258 | |||
4259 | switch (hdev->discovery.type) { | ||
4260 | case DISCOV_TYPE_BREDR: | ||
4261 | if (!trigger_bredr_inquiry(req, status)) | ||
4262 | return false; | ||
4263 | break; | ||
4264 | |||
4265 | case DISCOV_TYPE_INTERLEAVED: | ||
4266 | if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, | ||
4267 | &hdev->quirks)) { | ||
4268 | /* During simultaneous discovery, we double LE scan | ||
4269 | * interval. We must leave some time for the controller | ||
4270 | * to do BR/EDR inquiry. | ||
4271 | */ | ||
4272 | if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2, | ||
4273 | status)) | ||
4274 | return false; | ||
4275 | |||
4276 | if (!trigger_bredr_inquiry(req, status)) | ||
4277 | return false; | ||
4278 | |||
4279 | return true; | ||
4280 | } | ||
4281 | |||
4282 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { | ||
4283 | *status = MGMT_STATUS_NOT_SUPPORTED; | ||
4284 | return false; | ||
4285 | } | ||
4286 | /* fall through */ | ||
4287 | |||
4288 | case DISCOV_TYPE_LE: | ||
4289 | if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status)) | ||
4290 | return false; | ||
4291 | break; | ||
4292 | |||
4293 | default: | ||
4294 | *status = MGMT_STATUS_INVALID_PARAMS; | ||
4295 | return false; | ||
4296 | } | ||
4297 | |||
4298 | return true; | ||
4299 | } | ||
4300 | |||
4301 | static void start_discovery_complete(struct hci_dev *hdev, u8 status, | ||
4302 | u16 opcode) | ||
4303 | { | 3276 | { |
4304 | struct mgmt_pending_cmd *cmd; | 3277 | struct mgmt_pending_cmd *cmd; |
4305 | unsigned long timeout; | ||
4306 | 3278 | ||
4307 | BT_DBG("status %d", status); | 3279 | BT_DBG("status %d", status); |
4308 | 3280 | ||
@@ -4312,75 +3284,49 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status, | |||
4312 | if (!cmd) | 3284 | if (!cmd) |
4313 | cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev); | 3285 | cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev); |
4314 | 3286 | ||
3287 | if (!cmd) | ||
3288 | cmd = pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev); | ||
3289 | |||
4315 | if (cmd) { | 3290 | if (cmd) { |
4316 | cmd->cmd_complete(cmd, mgmt_status(status)); | 3291 | cmd->cmd_complete(cmd, mgmt_status(status)); |
4317 | mgmt_pending_remove(cmd); | 3292 | mgmt_pending_remove(cmd); |
4318 | } | 3293 | } |
4319 | 3294 | ||
4320 | if (status) { | 3295 | hci_dev_unlock(hdev); |
4321 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | 3296 | } |
4322 | goto unlock; | ||
4323 | } | ||
4324 | |||
4325 | hci_discovery_set_state(hdev, DISCOVERY_FINDING); | ||
4326 | 3297 | ||
4327 | /* If the scan involves LE scan, pick proper timeout to schedule | 3298 | static bool discovery_type_is_valid(struct hci_dev *hdev, uint8_t type, |
4328 | * hdev->le_scan_disable that will stop it. | 3299 | uint8_t *mgmt_status) |
4329 | */ | 3300 | { |
4330 | switch (hdev->discovery.type) { | 3301 | switch (type) { |
4331 | case DISCOV_TYPE_LE: | 3302 | case DISCOV_TYPE_LE: |
4332 | timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT); | 3303 | *mgmt_status = mgmt_le_support(hdev); |
3304 | if (*mgmt_status) | ||
3305 | return false; | ||
4333 | break; | 3306 | break; |
4334 | case DISCOV_TYPE_INTERLEAVED: | 3307 | case DISCOV_TYPE_INTERLEAVED: |
4335 | /* When running simultaneous discovery, the LE scanning time | 3308 | *mgmt_status = mgmt_le_support(hdev); |
4336 | * should occupy the whole discovery time sine BR/EDR inquiry | 3309 | if (*mgmt_status) |
4337 | * and LE scanning are scheduled by the controller. | 3310 | return false; |
4338 | * | 3311 | /* Intentional fall-through */ |
4339 | * For interleaving discovery in comparison, BR/EDR inquiry | ||
4340 | * and LE scanning are done sequentially with separate | ||
4341 | * timeouts. | ||
4342 | */ | ||
4343 | if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) | ||
4344 | timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT); | ||
4345 | else | ||
4346 | timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout); | ||
4347 | break; | ||
4348 | case DISCOV_TYPE_BREDR: | 3312 | case DISCOV_TYPE_BREDR: |
4349 | timeout = 0; | 3313 | *mgmt_status = mgmt_bredr_support(hdev); |
3314 | if (*mgmt_status) | ||
3315 | return false; | ||
4350 | break; | 3316 | break; |
4351 | default: | 3317 | default: |
4352 | BT_ERR("Invalid discovery type %d", hdev->discovery.type); | 3318 | *mgmt_status = MGMT_STATUS_INVALID_PARAMS; |
4353 | timeout = 0; | 3319 | return false; |
4354 | break; | ||
4355 | } | ||
4356 | |||
4357 | if (timeout) { | ||
4358 | /* When service discovery is used and the controller has | ||
4359 | * a strict duplicate filter, it is important to remember | ||
4360 | * the start and duration of the scan. This is required | ||
4361 | * for restarting scanning during the discovery phase. | ||
4362 | */ | ||
4363 | if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, | ||
4364 | &hdev->quirks) && | ||
4365 | hdev->discovery.result_filtering) { | ||
4366 | hdev->discovery.scan_start = jiffies; | ||
4367 | hdev->discovery.scan_duration = timeout; | ||
4368 | } | ||
4369 | |||
4370 | queue_delayed_work(hdev->workqueue, | ||
4371 | &hdev->le_scan_disable, timeout); | ||
4372 | } | 3320 | } |
4373 | 3321 | ||
4374 | unlock: | 3322 | return true; |
4375 | hci_dev_unlock(hdev); | ||
4376 | } | 3323 | } |
4377 | 3324 | ||
4378 | static int start_discovery(struct sock *sk, struct hci_dev *hdev, | 3325 | static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev, |
4379 | void *data, u16 len) | 3326 | u16 op, void *data, u16 len) |
4380 | { | 3327 | { |
4381 | struct mgmt_cp_start_discovery *cp = data; | 3328 | struct mgmt_cp_start_discovery *cp = data; |
4382 | struct mgmt_pending_cmd *cmd; | 3329 | struct mgmt_pending_cmd *cmd; |
4383 | struct hci_request req; | ||
4384 | u8 status; | 3330 | u8 status; |
4385 | int err; | 3331 | int err; |
4386 | 3332 | ||
@@ -4389,7 +3335,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
4389 | hci_dev_lock(hdev); | 3335 | hci_dev_lock(hdev); |
4390 | 3336 | ||
4391 | if (!hdev_is_powered(hdev)) { | 3337 | if (!hdev_is_powered(hdev)) { |
4392 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3338 | err = mgmt_cmd_complete(sk, hdev->id, op, |
4393 | MGMT_STATUS_NOT_POWERED, | 3339 | MGMT_STATUS_NOT_POWERED, |
4394 | &cp->type, sizeof(cp->type)); | 3340 | &cp->type, sizeof(cp->type)); |
4395 | goto failed; | 3341 | goto failed; |
@@ -4397,20 +3343,17 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
4397 | 3343 | ||
4398 | if (hdev->discovery.state != DISCOVERY_STOPPED || | 3344 | if (hdev->discovery.state != DISCOVERY_STOPPED || |
4399 | hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) { | 3345 | hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) { |
4400 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3346 | err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY, |
4401 | MGMT_STATUS_BUSY, &cp->type, | 3347 | &cp->type, sizeof(cp->type)); |
4402 | sizeof(cp->type)); | ||
4403 | goto failed; | 3348 | goto failed; |
4404 | } | 3349 | } |
4405 | 3350 | ||
4406 | cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len); | 3351 | if (!discovery_type_is_valid(hdev, cp->type, &status)) { |
4407 | if (!cmd) { | 3352 | err = mgmt_cmd_complete(sk, hdev->id, op, status, |
4408 | err = -ENOMEM; | 3353 | &cp->type, sizeof(cp->type)); |
4409 | goto failed; | 3354 | goto failed; |
4410 | } | 3355 | } |
4411 | 3356 | ||
4412 | cmd->cmd_complete = generic_cmd_complete; | ||
4413 | |||
4414 | /* Clear the discovery filter first to free any previously | 3357 | /* Clear the discovery filter first to free any previously |
4415 | * allocated memory for the UUID list. | 3358 | * allocated memory for the UUID list. |
4416 | */ | 3359 | */ |
@@ -4418,29 +3361,43 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
4418 | 3361 | ||
4419 | hdev->discovery.type = cp->type; | 3362 | hdev->discovery.type = cp->type; |
4420 | hdev->discovery.report_invalid_rssi = false; | 3363 | hdev->discovery.report_invalid_rssi = false; |
3364 | if (op == MGMT_OP_START_LIMITED_DISCOVERY) | ||
3365 | hdev->discovery.limited = true; | ||
3366 | else | ||
3367 | hdev->discovery.limited = false; | ||
4421 | 3368 | ||
4422 | hci_req_init(&req, hdev); | 3369 | cmd = mgmt_pending_add(sk, op, hdev, data, len); |
4423 | 3370 | if (!cmd) { | |
4424 | if (!trigger_discovery(&req, &status)) { | 3371 | err = -ENOMEM; |
4425 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, | ||
4426 | status, &cp->type, sizeof(cp->type)); | ||
4427 | mgmt_pending_remove(cmd); | ||
4428 | goto failed; | 3372 | goto failed; |
4429 | } | 3373 | } |
4430 | 3374 | ||
4431 | err = hci_req_run(&req, start_discovery_complete); | 3375 | cmd->cmd_complete = generic_cmd_complete; |
4432 | if (err < 0) { | ||
4433 | mgmt_pending_remove(cmd); | ||
4434 | goto failed; | ||
4435 | } | ||
4436 | 3376 | ||
4437 | hci_discovery_set_state(hdev, DISCOVERY_STARTING); | 3377 | hci_discovery_set_state(hdev, DISCOVERY_STARTING); |
3378 | queue_work(hdev->req_workqueue, &hdev->discov_update); | ||
3379 | err = 0; | ||
4438 | 3380 | ||
4439 | failed: | 3381 | failed: |
4440 | hci_dev_unlock(hdev); | 3382 | hci_dev_unlock(hdev); |
4441 | return err; | 3383 | return err; |
4442 | } | 3384 | } |
4443 | 3385 | ||
3386 | static int start_discovery(struct sock *sk, struct hci_dev *hdev, | ||
3387 | void *data, u16 len) | ||
3388 | { | ||
3389 | return start_discovery_internal(sk, hdev, MGMT_OP_START_DISCOVERY, | ||
3390 | data, len); | ||
3391 | } | ||
3392 | |||
3393 | static int start_limited_discovery(struct sock *sk, struct hci_dev *hdev, | ||
3394 | void *data, u16 len) | ||
3395 | { | ||
3396 | return start_discovery_internal(sk, hdev, | ||
3397 | MGMT_OP_START_LIMITED_DISCOVERY, | ||
3398 | data, len); | ||
3399 | } | ||
3400 | |||
4444 | static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd, | 3401 | static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd, |
4445 | u8 status) | 3402 | u8 status) |
4446 | { | 3403 | { |
@@ -4453,7 +3410,6 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, | |||
4453 | { | 3410 | { |
4454 | struct mgmt_cp_start_service_discovery *cp = data; | 3411 | struct mgmt_cp_start_service_discovery *cp = data; |
4455 | struct mgmt_pending_cmd *cmd; | 3412 | struct mgmt_pending_cmd *cmd; |
4456 | struct hci_request req; | ||
4457 | const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16); | 3413 | const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16); |
4458 | u16 uuid_count, expected_len; | 3414 | u16 uuid_count, expected_len; |
4459 | u8 status; | 3415 | u8 status; |
@@ -4502,6 +3458,13 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, | |||
4502 | goto failed; | 3458 | goto failed; |
4503 | } | 3459 | } |
4504 | 3460 | ||
3461 | if (!discovery_type_is_valid(hdev, cp->type, &status)) { | ||
3462 | err = mgmt_cmd_complete(sk, hdev->id, | ||
3463 | MGMT_OP_START_SERVICE_DISCOVERY, | ||
3464 | status, &cp->type, sizeof(cp->type)); | ||
3465 | goto failed; | ||
3466 | } | ||
3467 | |||
4505 | cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY, | 3468 | cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY, |
4506 | hdev, data, len); | 3469 | hdev, data, len); |
4507 | if (!cmd) { | 3470 | if (!cmd) { |
@@ -4534,30 +3497,16 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, | |||
4534 | } | 3497 | } |
4535 | } | 3498 | } |
4536 | 3499 | ||
4537 | hci_req_init(&req, hdev); | ||
4538 | |||
4539 | if (!trigger_discovery(&req, &status)) { | ||
4540 | err = mgmt_cmd_complete(sk, hdev->id, | ||
4541 | MGMT_OP_START_SERVICE_DISCOVERY, | ||
4542 | status, &cp->type, sizeof(cp->type)); | ||
4543 | mgmt_pending_remove(cmd); | ||
4544 | goto failed; | ||
4545 | } | ||
4546 | |||
4547 | err = hci_req_run(&req, start_discovery_complete); | ||
4548 | if (err < 0) { | ||
4549 | mgmt_pending_remove(cmd); | ||
4550 | goto failed; | ||
4551 | } | ||
4552 | |||
4553 | hci_discovery_set_state(hdev, DISCOVERY_STARTING); | 3500 | hci_discovery_set_state(hdev, DISCOVERY_STARTING); |
3501 | queue_work(hdev->req_workqueue, &hdev->discov_update); | ||
3502 | err = 0; | ||
4554 | 3503 | ||
4555 | failed: | 3504 | failed: |
4556 | hci_dev_unlock(hdev); | 3505 | hci_dev_unlock(hdev); |
4557 | return err; | 3506 | return err; |
4558 | } | 3507 | } |
4559 | 3508 | ||
4560 | static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode) | 3509 | void mgmt_stop_discovery_complete(struct hci_dev *hdev, u8 status) |
4561 | { | 3510 | { |
4562 | struct mgmt_pending_cmd *cmd; | 3511 | struct mgmt_pending_cmd *cmd; |
4563 | 3512 | ||
@@ -4571,9 +3520,6 @@ static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode) | |||
4571 | mgmt_pending_remove(cmd); | 3520 | mgmt_pending_remove(cmd); |
4572 | } | 3521 | } |
4573 | 3522 | ||
4574 | if (!status) | ||
4575 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
4576 | |||
4577 | hci_dev_unlock(hdev); | 3523 | hci_dev_unlock(hdev); |
4578 | } | 3524 | } |
4579 | 3525 | ||
@@ -4582,7 +3528,6 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4582 | { | 3528 | { |
4583 | struct mgmt_cp_stop_discovery *mgmt_cp = data; | 3529 | struct mgmt_cp_stop_discovery *mgmt_cp = data; |
4584 | struct mgmt_pending_cmd *cmd; | 3530 | struct mgmt_pending_cmd *cmd; |
4585 | struct hci_request req; | ||
4586 | int err; | 3531 | int err; |
4587 | 3532 | ||
4588 | BT_DBG("%s", hdev->name); | 3533 | BT_DBG("%s", hdev->name); |
@@ -4611,24 +3556,9 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4611 | 3556 | ||
4612 | cmd->cmd_complete = generic_cmd_complete; | 3557 | cmd->cmd_complete = generic_cmd_complete; |
4613 | 3558 | ||
4614 | hci_req_init(&req, hdev); | 3559 | hci_discovery_set_state(hdev, DISCOVERY_STOPPING); |
4615 | 3560 | queue_work(hdev->req_workqueue, &hdev->discov_update); | |
4616 | hci_stop_discovery(&req); | 3561 | err = 0; |
4617 | |||
4618 | err = hci_req_run(&req, stop_discovery_complete); | ||
4619 | if (!err) { | ||
4620 | hci_discovery_set_state(hdev, DISCOVERY_STOPPING); | ||
4621 | goto unlock; | ||
4622 | } | ||
4623 | |||
4624 | mgmt_pending_remove(cmd); | ||
4625 | |||
4626 | /* If no HCI commands were sent we're done */ | ||
4627 | if (err == -ENODATA) { | ||
4628 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0, | ||
4629 | &mgmt_cp->type, sizeof(mgmt_cp->type)); | ||
4630 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
4631 | } | ||
4632 | 3562 | ||
4633 | unlock: | 3563 | unlock: |
4634 | hci_dev_unlock(hdev); | 3564 | hci_dev_unlock(hdev); |
@@ -4776,7 +3706,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4776 | NULL, 0); | 3706 | NULL, 0); |
4777 | 3707 | ||
4778 | hci_req_init(&req, hdev); | 3708 | hci_req_init(&req, hdev); |
4779 | update_eir(&req); | 3709 | __hci_req_update_eir(&req); |
4780 | hci_req_run(&req, NULL); | 3710 | hci_req_run(&req, NULL); |
4781 | 3711 | ||
4782 | hci_dev_unlock(hdev); | 3712 | hci_dev_unlock(hdev); |
@@ -4826,7 +3756,6 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status, | |||
4826 | * set up earlier, then re-enable multi-instance advertising. | 3756 | * set up earlier, then re-enable multi-instance advertising. |
4827 | */ | 3757 | */ |
4828 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | 3758 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || |
4829 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) || | ||
4830 | list_empty(&hdev->adv_instances)) | 3759 | list_empty(&hdev->adv_instances)) |
4831 | goto unlock; | 3760 | goto unlock; |
4832 | 3761 | ||
@@ -4842,7 +3771,7 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status, | |||
4842 | 3771 | ||
4843 | hci_req_init(&req, hdev); | 3772 | hci_req_init(&req, hdev); |
4844 | 3773 | ||
4845 | err = schedule_adv_instance(&req, instance, true); | 3774 | err = __hci_req_schedule_adv_instance(&req, instance, true); |
4846 | 3775 | ||
4847 | if (!err) | 3776 | if (!err) |
4848 | err = hci_req_run(&req, enable_advertising_instance); | 3777 | err = hci_req_run(&req, enable_advertising_instance); |
@@ -4892,6 +3821,7 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4892 | bool changed; | 3821 | bool changed; |
4893 | 3822 | ||
4894 | if (cp->val) { | 3823 | if (cp->val) { |
3824 | hdev->cur_adv_instance = 0x00; | ||
4895 | changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING); | 3825 | changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING); |
4896 | if (cp->val == 0x02) | 3826 | if (cp->val == 0x02) |
4897 | hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE); | 3827 | hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE); |
@@ -4939,11 +3869,12 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4939 | * We cannot use update_[adv|scan_rsp]_data() here as the | 3869 | * We cannot use update_[adv|scan_rsp]_data() here as the |
4940 | * HCI_ADVERTISING flag is not yet set. | 3870 | * HCI_ADVERTISING flag is not yet set. |
4941 | */ | 3871 | */ |
4942 | update_inst_adv_data(&req, 0x00); | 3872 | hdev->cur_adv_instance = 0x00; |
4943 | update_inst_scan_rsp_data(&req, 0x00); | 3873 | __hci_req_update_adv_data(&req, 0x00); |
4944 | enable_advertising(&req); | 3874 | __hci_req_update_scan_rsp_data(&req, 0x00); |
3875 | __hci_req_enable_advertising(&req); | ||
4945 | } else { | 3876 | } else { |
4946 | disable_advertising(&req); | 3877 | __hci_req_disable_advertising(&req); |
4947 | } | 3878 | } |
4948 | 3879 | ||
4949 | err = hci_req_run(&req, set_advertising_complete); | 3880 | err = hci_req_run(&req, set_advertising_complete); |
@@ -5140,7 +4071,7 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | |||
5140 | 4071 | ||
5141 | hci_req_init(&req, hdev); | 4072 | hci_req_init(&req, hdev); |
5142 | 4073 | ||
5143 | write_fast_connectable(&req, cp->val); | 4074 | __hci_req_write_fast_connectable(&req, cp->val); |
5144 | 4075 | ||
5145 | err = hci_req_run(&req, fast_connectable_complete); | 4076 | err = hci_req_run(&req, fast_connectable_complete); |
5146 | if (err < 0) { | 4077 | if (err < 0) { |
@@ -5275,20 +4206,20 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
5275 | goto unlock; | 4206 | goto unlock; |
5276 | } | 4207 | } |
5277 | 4208 | ||
5278 | /* We need to flip the bit already here so that update_adv_data | 4209 | /* We need to flip the bit already here so that |
5279 | * generates the correct flags. | 4210 | * hci_req_update_adv_data generates the correct flags. |
5280 | */ | 4211 | */ |
5281 | hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); | 4212 | hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); |
5282 | 4213 | ||
5283 | hci_req_init(&req, hdev); | 4214 | hci_req_init(&req, hdev); |
5284 | 4215 | ||
5285 | write_fast_connectable(&req, false); | 4216 | __hci_req_write_fast_connectable(&req, false); |
5286 | __hci_update_page_scan(&req); | 4217 | __hci_req_update_scan(&req); |
5287 | 4218 | ||
5288 | /* Since only the advertising data flags will change, there | 4219 | /* Since only the advertising data flags will change, there |
5289 | * is no need to update the scan response data. | 4220 | * is no need to update the scan response data. |
5290 | */ | 4221 | */ |
5291 | update_adv_data(&req); | 4222 | __hci_req_update_adv_data(&req, hdev->cur_adv_instance); |
5292 | 4223 | ||
5293 | err = hci_req_run(&req, set_bredr_complete); | 4224 | err = hci_req_run(&req, set_bredr_complete); |
5294 | if (err < 0) | 4225 | if (err < 0) |
@@ -6076,10 +5007,9 @@ static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type) | |||
6076 | } | 5007 | } |
6077 | 5008 | ||
6078 | /* This function requires the caller holds hdev->lock */ | 5009 | /* This function requires the caller holds hdev->lock */ |
6079 | static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr, | 5010 | static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, |
6080 | u8 addr_type, u8 auto_connect) | 5011 | u8 addr_type, u8 auto_connect) |
6081 | { | 5012 | { |
6082 | struct hci_dev *hdev = req->hdev; | ||
6083 | struct hci_conn_params *params; | 5013 | struct hci_conn_params *params; |
6084 | 5014 | ||
6085 | params = hci_conn_params_add(hdev, addr, addr_type); | 5015 | params = hci_conn_params_add(hdev, addr, addr_type); |
@@ -6099,26 +5029,17 @@ static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr, | |||
6099 | */ | 5029 | */ |
6100 | if (params->explicit_connect) | 5030 | if (params->explicit_connect) |
6101 | list_add(¶ms->action, &hdev->pend_le_conns); | 5031 | list_add(¶ms->action, &hdev->pend_le_conns); |
6102 | |||
6103 | __hci_update_background_scan(req); | ||
6104 | break; | 5032 | break; |
6105 | case HCI_AUTO_CONN_REPORT: | 5033 | case HCI_AUTO_CONN_REPORT: |
6106 | if (params->explicit_connect) | 5034 | if (params->explicit_connect) |
6107 | list_add(¶ms->action, &hdev->pend_le_conns); | 5035 | list_add(¶ms->action, &hdev->pend_le_conns); |
6108 | else | 5036 | else |
6109 | list_add(¶ms->action, &hdev->pend_le_reports); | 5037 | list_add(¶ms->action, &hdev->pend_le_reports); |
6110 | __hci_update_background_scan(req); | ||
6111 | break; | 5038 | break; |
6112 | case HCI_AUTO_CONN_DIRECT: | 5039 | case HCI_AUTO_CONN_DIRECT: |
6113 | case HCI_AUTO_CONN_ALWAYS: | 5040 | case HCI_AUTO_CONN_ALWAYS: |
6114 | if (!is_connected(hdev, addr, addr_type)) { | 5041 | if (!is_connected(hdev, addr, addr_type)) |
6115 | list_add(¶ms->action, &hdev->pend_le_conns); | 5042 | list_add(¶ms->action, &hdev->pend_le_conns); |
6116 | /* If we are in scan phase of connecting, we were | ||
6117 | * already added to pend_le_conns and scanning. | ||
6118 | */ | ||
6119 | if (params->auto_connect != HCI_AUTO_CONN_EXPLICIT) | ||
6120 | __hci_update_background_scan(req); | ||
6121 | } | ||
6122 | break; | 5043 | break; |
6123 | } | 5044 | } |
6124 | 5045 | ||
@@ -6142,31 +5063,10 @@ static void device_added(struct sock *sk, struct hci_dev *hdev, | |||
6142 | mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk); | 5063 | mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk); |
6143 | } | 5064 | } |
6144 | 5065 | ||
6145 | static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode) | ||
6146 | { | ||
6147 | struct mgmt_pending_cmd *cmd; | ||
6148 | |||
6149 | BT_DBG("status 0x%02x", status); | ||
6150 | |||
6151 | hci_dev_lock(hdev); | ||
6152 | |||
6153 | cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev); | ||
6154 | if (!cmd) | ||
6155 | goto unlock; | ||
6156 | |||
6157 | cmd->cmd_complete(cmd, mgmt_status(status)); | ||
6158 | mgmt_pending_remove(cmd); | ||
6159 | |||
6160 | unlock: | ||
6161 | hci_dev_unlock(hdev); | ||
6162 | } | ||
6163 | |||
6164 | static int add_device(struct sock *sk, struct hci_dev *hdev, | 5066 | static int add_device(struct sock *sk, struct hci_dev *hdev, |
6165 | void *data, u16 len) | 5067 | void *data, u16 len) |
6166 | { | 5068 | { |
6167 | struct mgmt_cp_add_device *cp = data; | 5069 | struct mgmt_cp_add_device *cp = data; |
6168 | struct mgmt_pending_cmd *cmd; | ||
6169 | struct hci_request req; | ||
6170 | u8 auto_conn, addr_type; | 5070 | u8 auto_conn, addr_type; |
6171 | int err; | 5071 | int err; |
6172 | 5072 | ||
@@ -6183,24 +5083,15 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, | |||
6183 | MGMT_STATUS_INVALID_PARAMS, | 5083 | MGMT_STATUS_INVALID_PARAMS, |
6184 | &cp->addr, sizeof(cp->addr)); | 5084 | &cp->addr, sizeof(cp->addr)); |
6185 | 5085 | ||
6186 | hci_req_init(&req, hdev); | ||
6187 | |||
6188 | hci_dev_lock(hdev); | 5086 | hci_dev_lock(hdev); |
6189 | 5087 | ||
6190 | cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len); | ||
6191 | if (!cmd) { | ||
6192 | err = -ENOMEM; | ||
6193 | goto unlock; | ||
6194 | } | ||
6195 | |||
6196 | cmd->cmd_complete = addr_cmd_complete; | ||
6197 | |||
6198 | if (cp->addr.type == BDADDR_BREDR) { | 5088 | if (cp->addr.type == BDADDR_BREDR) { |
6199 | /* Only incoming connections action is supported for now */ | 5089 | /* Only incoming connections action is supported for now */ |
6200 | if (cp->action != 0x01) { | 5090 | if (cp->action != 0x01) { |
6201 | err = cmd->cmd_complete(cmd, | 5091 | err = mgmt_cmd_complete(sk, hdev->id, |
6202 | MGMT_STATUS_INVALID_PARAMS); | 5092 | MGMT_OP_ADD_DEVICE, |
6203 | mgmt_pending_remove(cmd); | 5093 | MGMT_STATUS_INVALID_PARAMS, |
5094 | &cp->addr, sizeof(cp->addr)); | ||
6204 | goto unlock; | 5095 | goto unlock; |
6205 | } | 5096 | } |
6206 | 5097 | ||
@@ -6209,7 +5100,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, | |||
6209 | if (err) | 5100 | if (err) |
6210 | goto unlock; | 5101 | goto unlock; |
6211 | 5102 | ||
6212 | __hci_update_page_scan(&req); | 5103 | hci_req_update_scan(hdev); |
6213 | 5104 | ||
6214 | goto added; | 5105 | goto added; |
6215 | } | 5106 | } |
@@ -6229,33 +5120,31 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, | |||
6229 | * hci_conn_params_lookup. | 5120 | * hci_conn_params_lookup. |
6230 | */ | 5121 | */ |
6231 | if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) { | 5122 | if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) { |
6232 | err = cmd->cmd_complete(cmd, MGMT_STATUS_INVALID_PARAMS); | 5123 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, |
6233 | mgmt_pending_remove(cmd); | 5124 | MGMT_STATUS_INVALID_PARAMS, |
5125 | &cp->addr, sizeof(cp->addr)); | ||
6234 | goto unlock; | 5126 | goto unlock; |
6235 | } | 5127 | } |
6236 | 5128 | ||
6237 | /* If the connection parameters don't exist for this device, | 5129 | /* If the connection parameters don't exist for this device, |
6238 | * they will be created and configured with defaults. | 5130 | * they will be created and configured with defaults. |
6239 | */ | 5131 | */ |
6240 | if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type, | 5132 | if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type, |
6241 | auto_conn) < 0) { | 5133 | auto_conn) < 0) { |
6242 | err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED); | 5134 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, |
6243 | mgmt_pending_remove(cmd); | 5135 | MGMT_STATUS_FAILED, &cp->addr, |
5136 | sizeof(cp->addr)); | ||
6244 | goto unlock; | 5137 | goto unlock; |
6245 | } | 5138 | } |
6246 | 5139 | ||
5140 | hci_update_background_scan(hdev); | ||
5141 | |||
6247 | added: | 5142 | added: |
6248 | device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action); | 5143 | device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action); |
6249 | 5144 | ||
6250 | err = hci_req_run(&req, add_device_complete); | 5145 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, |
6251 | if (err < 0) { | 5146 | MGMT_STATUS_SUCCESS, &cp->addr, |
6252 | /* ENODATA means no HCI commands were needed (e.g. if | 5147 | sizeof(cp->addr)); |
6253 | * the adapter is powered off). | ||
6254 | */ | ||
6255 | if (err == -ENODATA) | ||
6256 | err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS); | ||
6257 | mgmt_pending_remove(cmd); | ||
6258 | } | ||
6259 | 5148 | ||
6260 | unlock: | 5149 | unlock: |
6261 | hci_dev_unlock(hdev); | 5150 | hci_dev_unlock(hdev); |
@@ -6273,55 +5162,25 @@ static void device_removed(struct sock *sk, struct hci_dev *hdev, | |||
6273 | mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk); | 5162 | mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk); |
6274 | } | 5163 | } |
6275 | 5164 | ||
6276 | static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode) | ||
6277 | { | ||
6278 | struct mgmt_pending_cmd *cmd; | ||
6279 | |||
6280 | BT_DBG("status 0x%02x", status); | ||
6281 | |||
6282 | hci_dev_lock(hdev); | ||
6283 | |||
6284 | cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev); | ||
6285 | if (!cmd) | ||
6286 | goto unlock; | ||
6287 | |||
6288 | cmd->cmd_complete(cmd, mgmt_status(status)); | ||
6289 | mgmt_pending_remove(cmd); | ||
6290 | |||
6291 | unlock: | ||
6292 | hci_dev_unlock(hdev); | ||
6293 | } | ||
6294 | |||
6295 | static int remove_device(struct sock *sk, struct hci_dev *hdev, | 5165 | static int remove_device(struct sock *sk, struct hci_dev *hdev, |
6296 | void *data, u16 len) | 5166 | void *data, u16 len) |
6297 | { | 5167 | { |
6298 | struct mgmt_cp_remove_device *cp = data; | 5168 | struct mgmt_cp_remove_device *cp = data; |
6299 | struct mgmt_pending_cmd *cmd; | ||
6300 | struct hci_request req; | ||
6301 | int err; | 5169 | int err; |
6302 | 5170 | ||
6303 | BT_DBG("%s", hdev->name); | 5171 | BT_DBG("%s", hdev->name); |
6304 | 5172 | ||
6305 | hci_req_init(&req, hdev); | ||
6306 | |||
6307 | hci_dev_lock(hdev); | 5173 | hci_dev_lock(hdev); |
6308 | 5174 | ||
6309 | cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len); | ||
6310 | if (!cmd) { | ||
6311 | err = -ENOMEM; | ||
6312 | goto unlock; | ||
6313 | } | ||
6314 | |||
6315 | cmd->cmd_complete = addr_cmd_complete; | ||
6316 | |||
6317 | if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) { | 5175 | if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) { |
6318 | struct hci_conn_params *params; | 5176 | struct hci_conn_params *params; |
6319 | u8 addr_type; | 5177 | u8 addr_type; |
6320 | 5178 | ||
6321 | if (!bdaddr_type_is_valid(cp->addr.type)) { | 5179 | if (!bdaddr_type_is_valid(cp->addr.type)) { |
6322 | err = cmd->cmd_complete(cmd, | 5180 | err = mgmt_cmd_complete(sk, hdev->id, |
6323 | MGMT_STATUS_INVALID_PARAMS); | 5181 | MGMT_OP_REMOVE_DEVICE, |
6324 | mgmt_pending_remove(cmd); | 5182 | MGMT_STATUS_INVALID_PARAMS, |
5183 | &cp->addr, sizeof(cp->addr)); | ||
6325 | goto unlock; | 5184 | goto unlock; |
6326 | } | 5185 | } |
6327 | 5186 | ||
@@ -6330,13 +5189,15 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, | |||
6330 | &cp->addr.bdaddr, | 5189 | &cp->addr.bdaddr, |
6331 | cp->addr.type); | 5190 | cp->addr.type); |
6332 | if (err) { | 5191 | if (err) { |
6333 | err = cmd->cmd_complete(cmd, | 5192 | err = mgmt_cmd_complete(sk, hdev->id, |
6334 | MGMT_STATUS_INVALID_PARAMS); | 5193 | MGMT_OP_REMOVE_DEVICE, |
6335 | mgmt_pending_remove(cmd); | 5194 | MGMT_STATUS_INVALID_PARAMS, |
5195 | &cp->addr, | ||
5196 | sizeof(cp->addr)); | ||
6336 | goto unlock; | 5197 | goto unlock; |
6337 | } | 5198 | } |
6338 | 5199 | ||
6339 | __hci_update_page_scan(&req); | 5200 | hci_req_update_scan(hdev); |
6340 | 5201 | ||
6341 | device_removed(sk, hdev, &cp->addr.bdaddr, | 5202 | device_removed(sk, hdev, &cp->addr.bdaddr, |
6342 | cp->addr.type); | 5203 | cp->addr.type); |
@@ -6351,33 +5212,36 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, | |||
6351 | * hci_conn_params_lookup. | 5212 | * hci_conn_params_lookup. |
6352 | */ | 5213 | */ |
6353 | if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) { | 5214 | if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) { |
6354 | err = cmd->cmd_complete(cmd, | 5215 | err = mgmt_cmd_complete(sk, hdev->id, |
6355 | MGMT_STATUS_INVALID_PARAMS); | 5216 | MGMT_OP_REMOVE_DEVICE, |
6356 | mgmt_pending_remove(cmd); | 5217 | MGMT_STATUS_INVALID_PARAMS, |
5218 | &cp->addr, sizeof(cp->addr)); | ||
6357 | goto unlock; | 5219 | goto unlock; |
6358 | } | 5220 | } |
6359 | 5221 | ||
6360 | params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, | 5222 | params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, |
6361 | addr_type); | 5223 | addr_type); |
6362 | if (!params) { | 5224 | if (!params) { |
6363 | err = cmd->cmd_complete(cmd, | 5225 | err = mgmt_cmd_complete(sk, hdev->id, |
6364 | MGMT_STATUS_INVALID_PARAMS); | 5226 | MGMT_OP_REMOVE_DEVICE, |
6365 | mgmt_pending_remove(cmd); | 5227 | MGMT_STATUS_INVALID_PARAMS, |
5228 | &cp->addr, sizeof(cp->addr)); | ||
6366 | goto unlock; | 5229 | goto unlock; |
6367 | } | 5230 | } |
6368 | 5231 | ||
6369 | if (params->auto_connect == HCI_AUTO_CONN_DISABLED || | 5232 | if (params->auto_connect == HCI_AUTO_CONN_DISABLED || |
6370 | params->auto_connect == HCI_AUTO_CONN_EXPLICIT) { | 5233 | params->auto_connect == HCI_AUTO_CONN_EXPLICIT) { |
6371 | err = cmd->cmd_complete(cmd, | 5234 | err = mgmt_cmd_complete(sk, hdev->id, |
6372 | MGMT_STATUS_INVALID_PARAMS); | 5235 | MGMT_OP_REMOVE_DEVICE, |
6373 | mgmt_pending_remove(cmd); | 5236 | MGMT_STATUS_INVALID_PARAMS, |
5237 | &cp->addr, sizeof(cp->addr)); | ||
6374 | goto unlock; | 5238 | goto unlock; |
6375 | } | 5239 | } |
6376 | 5240 | ||
6377 | list_del(¶ms->action); | 5241 | list_del(¶ms->action); |
6378 | list_del(¶ms->list); | 5242 | list_del(¶ms->list); |
6379 | kfree(params); | 5243 | kfree(params); |
6380 | __hci_update_background_scan(&req); | 5244 | hci_update_background_scan(hdev); |
6381 | 5245 | ||
6382 | device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type); | 5246 | device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type); |
6383 | } else { | 5247 | } else { |
@@ -6385,9 +5249,10 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, | |||
6385 | struct bdaddr_list *b, *btmp; | 5249 | struct bdaddr_list *b, *btmp; |
6386 | 5250 | ||
6387 | if (cp->addr.type) { | 5251 | if (cp->addr.type) { |
6388 | err = cmd->cmd_complete(cmd, | 5252 | err = mgmt_cmd_complete(sk, hdev->id, |
6389 | MGMT_STATUS_INVALID_PARAMS); | 5253 | MGMT_OP_REMOVE_DEVICE, |
6390 | mgmt_pending_remove(cmd); | 5254 | MGMT_STATUS_INVALID_PARAMS, |
5255 | &cp->addr, sizeof(cp->addr)); | ||
6391 | goto unlock; | 5256 | goto unlock; |
6392 | } | 5257 | } |
6393 | 5258 | ||
@@ -6397,7 +5262,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, | |||
6397 | kfree(b); | 5262 | kfree(b); |
6398 | } | 5263 | } |
6399 | 5264 | ||
6400 | __hci_update_page_scan(&req); | 5265 | hci_req_update_scan(hdev); |
6401 | 5266 | ||
6402 | list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) { | 5267 | list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) { |
6403 | if (p->auto_connect == HCI_AUTO_CONN_DISABLED) | 5268 | if (p->auto_connect == HCI_AUTO_CONN_DISABLED) |
@@ -6414,20 +5279,13 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, | |||
6414 | 5279 | ||
6415 | BT_DBG("All LE connection parameters were removed"); | 5280 | BT_DBG("All LE connection parameters were removed"); |
6416 | 5281 | ||
6417 | __hci_update_background_scan(&req); | 5282 | hci_update_background_scan(hdev); |
6418 | } | 5283 | } |
6419 | 5284 | ||
6420 | complete: | 5285 | complete: |
6421 | err = hci_req_run(&req, remove_device_complete); | 5286 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, |
6422 | if (err < 0) { | 5287 | MGMT_STATUS_SUCCESS, &cp->addr, |
6423 | /* ENODATA means no HCI commands were needed (e.g. if | 5288 | sizeof(cp->addr)); |
6424 | * the adapter is powered off). | ||
6425 | */ | ||
6426 | if (err == -ENODATA) | ||
6427 | err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS); | ||
6428 | mgmt_pending_remove(cmd); | ||
6429 | } | ||
6430 | |||
6431 | unlock: | 5289 | unlock: |
6432 | hci_dev_unlock(hdev); | 5290 | hci_dev_unlock(hdev); |
6433 | return err; | 5291 | return err; |
@@ -6898,7 +5756,7 @@ static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev, | |||
6898 | rand, sizeof(rand)); | 5756 | rand, sizeof(rand)); |
6899 | } | 5757 | } |
6900 | 5758 | ||
6901 | flags = get_adv_discov_flags(hdev); | 5759 | flags = mgmt_get_adv_discov_flags(hdev); |
6902 | 5760 | ||
6903 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | 5761 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) |
6904 | flags |= LE_AD_NO_BREDR; | 5762 | flags |= LE_AD_NO_BREDR; |
@@ -6953,10 +5811,10 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev, | |||
6953 | { | 5811 | { |
6954 | struct mgmt_rp_read_adv_features *rp; | 5812 | struct mgmt_rp_read_adv_features *rp; |
6955 | size_t rp_len; | 5813 | size_t rp_len; |
6956 | int err, i; | 5814 | int err; |
6957 | bool instance; | ||
6958 | struct adv_info *adv_instance; | 5815 | struct adv_info *adv_instance; |
6959 | u32 supported_flags; | 5816 | u32 supported_flags; |
5817 | u8 *instance; | ||
6960 | 5818 | ||
6961 | BT_DBG("%s", hdev->name); | 5819 | BT_DBG("%s", hdev->name); |
6962 | 5820 | ||
@@ -6966,12 +5824,7 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev, | |||
6966 | 5824 | ||
6967 | hci_dev_lock(hdev); | 5825 | hci_dev_lock(hdev); |
6968 | 5826 | ||
6969 | rp_len = sizeof(*rp); | 5827 | rp_len = sizeof(*rp) + hdev->adv_instance_cnt; |
6970 | |||
6971 | instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE); | ||
6972 | if (instance) | ||
6973 | rp_len += hdev->adv_instance_cnt; | ||
6974 | |||
6975 | rp = kmalloc(rp_len, GFP_ATOMIC); | 5828 | rp = kmalloc(rp_len, GFP_ATOMIC); |
6976 | if (!rp) { | 5829 | if (!rp) { |
6977 | hci_dev_unlock(hdev); | 5830 | hci_dev_unlock(hdev); |
@@ -6984,19 +5837,12 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev, | |||
6984 | rp->max_adv_data_len = HCI_MAX_AD_LENGTH; | 5837 | rp->max_adv_data_len = HCI_MAX_AD_LENGTH; |
6985 | rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH; | 5838 | rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH; |
6986 | rp->max_instances = HCI_MAX_ADV_INSTANCES; | 5839 | rp->max_instances = HCI_MAX_ADV_INSTANCES; |
5840 | rp->num_instances = hdev->adv_instance_cnt; | ||
6987 | 5841 | ||
6988 | if (instance) { | 5842 | instance = rp->instance; |
6989 | i = 0; | 5843 | list_for_each_entry(adv_instance, &hdev->adv_instances, list) { |
6990 | list_for_each_entry(adv_instance, &hdev->adv_instances, list) { | 5844 | *instance = adv_instance->instance; |
6991 | if (i >= hdev->adv_instance_cnt) | 5845 | instance++; |
6992 | break; | ||
6993 | |||
6994 | rp->instance[i] = adv_instance->instance; | ||
6995 | i++; | ||
6996 | } | ||
6997 | rp->num_instances = hdev->adv_instance_cnt; | ||
6998 | } else { | ||
6999 | rp->num_instances = 0; | ||
7000 | } | 5846 | } |
7001 | 5847 | ||
7002 | hci_dev_unlock(hdev); | 5848 | hci_dev_unlock(hdev); |
@@ -7016,17 +5862,19 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data, | |||
7016 | int i, cur_len; | 5862 | int i, cur_len; |
7017 | bool flags_managed = false; | 5863 | bool flags_managed = false; |
7018 | bool tx_power_managed = false; | 5864 | bool tx_power_managed = false; |
7019 | u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV | | ||
7020 | MGMT_ADV_FLAG_MANAGED_FLAGS; | ||
7021 | 5865 | ||
7022 | if (is_adv_data && (adv_flags & flags_params)) { | 5866 | if (is_adv_data) { |
7023 | flags_managed = true; | 5867 | if (adv_flags & (MGMT_ADV_FLAG_DISCOV | |
7024 | max_len -= 3; | 5868 | MGMT_ADV_FLAG_LIMITED_DISCOV | |
7025 | } | 5869 | MGMT_ADV_FLAG_MANAGED_FLAGS)) { |
5870 | flags_managed = true; | ||
5871 | max_len -= 3; | ||
5872 | } | ||
7026 | 5873 | ||
7027 | if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) { | 5874 | if (adv_flags & MGMT_ADV_FLAG_TX_POWER) { |
7028 | tx_power_managed = true; | 5875 | tx_power_managed = true; |
7029 | max_len -= 3; | 5876 | max_len -= 3; |
5877 | } | ||
7030 | } | 5878 | } |
7031 | 5879 | ||
7032 | if (len > max_len) | 5880 | if (len > max_len) |
@@ -7067,9 +5915,6 @@ static void add_advertising_complete(struct hci_dev *hdev, u8 status, | |||
7067 | 5915 | ||
7068 | cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev); | 5916 | cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev); |
7069 | 5917 | ||
7070 | if (status) | ||
7071 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE); | ||
7072 | |||
7073 | list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) { | 5918 | list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) { |
7074 | if (!adv_instance->pending) | 5919 | if (!adv_instance->pending) |
7075 | continue; | 5920 | continue; |
@@ -7085,7 +5930,7 @@ static void add_advertising_complete(struct hci_dev *hdev, u8 status, | |||
7085 | cancel_adv_timeout(hdev); | 5930 | cancel_adv_timeout(hdev); |
7086 | 5931 | ||
7087 | hci_remove_adv_instance(hdev, instance); | 5932 | hci_remove_adv_instance(hdev, instance); |
7088 | advertising_removed(cmd ? cmd->sk : NULL, hdev, instance); | 5933 | mgmt_advertising_removed(cmd ? cmd->sk : NULL, hdev, instance); |
7089 | } | 5934 | } |
7090 | 5935 | ||
7091 | if (!cmd) | 5936 | if (!cmd) |
@@ -7107,31 +5952,6 @@ unlock: | |||
7107 | hci_dev_unlock(hdev); | 5952 | hci_dev_unlock(hdev); |
7108 | } | 5953 | } |
7109 | 5954 | ||
7110 | void mgmt_adv_timeout_expired(struct hci_dev *hdev) | ||
7111 | { | ||
7112 | u8 instance; | ||
7113 | struct hci_request req; | ||
7114 | |||
7115 | hdev->adv_instance_timeout = 0; | ||
7116 | |||
7117 | instance = get_current_adv_instance(hdev); | ||
7118 | if (instance == 0x00) | ||
7119 | return; | ||
7120 | |||
7121 | hci_dev_lock(hdev); | ||
7122 | hci_req_init(&req, hdev); | ||
7123 | |||
7124 | clear_adv_instance(hdev, &req, instance, false); | ||
7125 | |||
7126 | if (list_empty(&hdev->adv_instances)) | ||
7127 | disable_advertising(&req); | ||
7128 | |||
7129 | if (!skb_queue_empty(&req.cmd_q)) | ||
7130 | hci_req_run(&req, NULL); | ||
7131 | |||
7132 | hci_dev_unlock(hdev); | ||
7133 | } | ||
7134 | |||
7135 | static int add_advertising(struct sock *sk, struct hci_dev *hdev, | 5955 | static int add_advertising(struct sock *sk, struct hci_dev *hdev, |
7136 | void *data, u16 data_len) | 5956 | void *data, u16 data_len) |
7137 | { | 5957 | { |
@@ -7155,6 +5975,10 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, | |||
7155 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, | 5975 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, |
7156 | status); | 5976 | status); |
7157 | 5977 | ||
5978 | if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES) | ||
5979 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, | ||
5980 | MGMT_STATUS_INVALID_PARAMS); | ||
5981 | |||
7158 | flags = __le32_to_cpu(cp->flags); | 5982 | flags = __le32_to_cpu(cp->flags); |
7159 | timeout = __le16_to_cpu(cp->timeout); | 5983 | timeout = __le16_to_cpu(cp->timeout); |
7160 | duration = __le16_to_cpu(cp->duration); | 5984 | duration = __le16_to_cpu(cp->duration); |
@@ -7206,9 +6030,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, | |||
7206 | * actually added. | 6030 | * actually added. |
7207 | */ | 6031 | */ |
7208 | if (hdev->adv_instance_cnt > prev_instance_cnt) | 6032 | if (hdev->adv_instance_cnt > prev_instance_cnt) |
7209 | advertising_added(sk, hdev, cp->instance); | 6033 | mgmt_advertising_added(sk, hdev, cp->instance); |
7210 | |||
7211 | hci_dev_set_flag(hdev, HCI_ADVERTISING_INSTANCE); | ||
7212 | 6034 | ||
7213 | if (hdev->cur_adv_instance == cp->instance) { | 6035 | if (hdev->cur_adv_instance == cp->instance) { |
7214 | /* If the currently advertised instance is being changed then | 6036 | /* If the currently advertised instance is being changed then |
@@ -7253,7 +6075,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, | |||
7253 | 6075 | ||
7254 | hci_req_init(&req, hdev); | 6076 | hci_req_init(&req, hdev); |
7255 | 6077 | ||
7256 | err = schedule_adv_instance(&req, schedule_instance, true); | 6078 | err = __hci_req_schedule_adv_instance(&req, schedule_instance, true); |
7257 | 6079 | ||
7258 | if (!err) | 6080 | if (!err) |
7259 | err = hci_req_run(&req, add_advertising_complete); | 6081 | err = hci_req_run(&req, add_advertising_complete); |
@@ -7325,7 +6147,7 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev, | |||
7325 | goto unlock; | 6147 | goto unlock; |
7326 | } | 6148 | } |
7327 | 6149 | ||
7328 | if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) { | 6150 | if (list_empty(&hdev->adv_instances)) { |
7329 | err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING, | 6151 | err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING, |
7330 | MGMT_STATUS_INVALID_PARAMS); | 6152 | MGMT_STATUS_INVALID_PARAMS); |
7331 | goto unlock; | 6153 | goto unlock; |
@@ -7333,10 +6155,10 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev, | |||
7333 | 6155 | ||
7334 | hci_req_init(&req, hdev); | 6156 | hci_req_init(&req, hdev); |
7335 | 6157 | ||
7336 | clear_adv_instance(hdev, &req, cp->instance, true); | 6158 | hci_req_clear_adv_instance(hdev, &req, cp->instance, true); |
7337 | 6159 | ||
7338 | if (list_empty(&hdev->adv_instances)) | 6160 | if (list_empty(&hdev->adv_instances)) |
7339 | disable_advertising(&req); | 6161 | __hci_req_disable_advertising(&req); |
7340 | 6162 | ||
7341 | /* If no HCI commands have been collected so far or the HCI_ADVERTISING | 6163 | /* If no HCI commands have been collected so far or the HCI_ADVERTISING |
7342 | * flag is set or the device isn't powered then we have no HCI | 6164 | * flag is set or the device isn't powered then we have no HCI |
@@ -7369,6 +6191,62 @@ unlock: | |||
7369 | return err; | 6191 | return err; |
7370 | } | 6192 | } |
7371 | 6193 | ||
6194 | static u8 tlv_data_max_len(u32 adv_flags, bool is_adv_data) | ||
6195 | { | ||
6196 | u8 max_len = HCI_MAX_AD_LENGTH; | ||
6197 | |||
6198 | if (is_adv_data) { | ||
6199 | if (adv_flags & (MGMT_ADV_FLAG_DISCOV | | ||
6200 | MGMT_ADV_FLAG_LIMITED_DISCOV | | ||
6201 | MGMT_ADV_FLAG_MANAGED_FLAGS)) | ||
6202 | max_len -= 3; | ||
6203 | |||
6204 | if (adv_flags & MGMT_ADV_FLAG_TX_POWER) | ||
6205 | max_len -= 3; | ||
6206 | } | ||
6207 | |||
6208 | return max_len; | ||
6209 | } | ||
6210 | |||
6211 | static int get_adv_size_info(struct sock *sk, struct hci_dev *hdev, | ||
6212 | void *data, u16 data_len) | ||
6213 | { | ||
6214 | struct mgmt_cp_get_adv_size_info *cp = data; | ||
6215 | struct mgmt_rp_get_adv_size_info rp; | ||
6216 | u32 flags, supported_flags; | ||
6217 | int err; | ||
6218 | |||
6219 | BT_DBG("%s", hdev->name); | ||
6220 | |||
6221 | if (!lmp_le_capable(hdev)) | ||
6222 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO, | ||
6223 | MGMT_STATUS_REJECTED); | ||
6224 | |||
6225 | if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES) | ||
6226 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO, | ||
6227 | MGMT_STATUS_INVALID_PARAMS); | ||
6228 | |||
6229 | flags = __le32_to_cpu(cp->flags); | ||
6230 | |||
6231 | /* The current implementation only supports a subset of the specified | ||
6232 | * flags. | ||
6233 | */ | ||
6234 | supported_flags = get_supported_adv_flags(hdev); | ||
6235 | if (flags & ~supported_flags) | ||
6236 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO, | ||
6237 | MGMT_STATUS_INVALID_PARAMS); | ||
6238 | |||
6239 | rp.instance = cp->instance; | ||
6240 | rp.flags = cp->flags; | ||
6241 | rp.max_adv_data_len = tlv_data_max_len(flags, true); | ||
6242 | rp.max_scan_rsp_len = tlv_data_max_len(flags, false); | ||
6243 | |||
6244 | err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO, | ||
6245 | MGMT_STATUS_SUCCESS, &rp, sizeof(rp)); | ||
6246 | |||
6247 | return err; | ||
6248 | } | ||
6249 | |||
7372 | static const struct hci_mgmt_handler mgmt_handlers[] = { | 6250 | static const struct hci_mgmt_handler mgmt_handlers[] = { |
7373 | { NULL }, /* 0x0000 (no command) */ | 6251 | { NULL }, /* 0x0000 (no command) */ |
7374 | { read_version, MGMT_READ_VERSION_SIZE, | 6252 | { read_version, MGMT_READ_VERSION_SIZE, |
@@ -7456,6 +6334,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = { | |||
7456 | { add_advertising, MGMT_ADD_ADVERTISING_SIZE, | 6334 | { add_advertising, MGMT_ADD_ADVERTISING_SIZE, |
7457 | HCI_MGMT_VAR_LEN }, | 6335 | HCI_MGMT_VAR_LEN }, |
7458 | { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE }, | 6336 | { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE }, |
6337 | { get_adv_size_info, MGMT_GET_ADV_SIZE_INFO_SIZE }, | ||
6338 | { start_limited_discovery, MGMT_START_DISCOVERY_SIZE }, | ||
7459 | }; | 6339 | }; |
7460 | 6340 | ||
7461 | void mgmt_index_added(struct hci_dev *hdev) | 6341 | void mgmt_index_added(struct hci_dev *hdev) |
@@ -7526,9 +6406,8 @@ void mgmt_index_removed(struct hci_dev *hdev) | |||
7526 | } | 6406 | } |
7527 | 6407 | ||
7528 | /* This function requires the caller holds hdev->lock */ | 6408 | /* This function requires the caller holds hdev->lock */ |
7529 | static void restart_le_actions(struct hci_request *req) | 6409 | static void restart_le_actions(struct hci_dev *hdev) |
7530 | { | 6410 | { |
7531 | struct hci_dev *hdev = req->hdev; | ||
7532 | struct hci_conn_params *p; | 6411 | struct hci_conn_params *p; |
7533 | 6412 | ||
7534 | list_for_each_entry(p, &hdev->le_conn_params, list) { | 6413 | list_for_each_entry(p, &hdev->le_conn_params, list) { |
@@ -7549,141 +6428,35 @@ static void restart_le_actions(struct hci_request *req) | |||
7549 | break; | 6428 | break; |
7550 | } | 6429 | } |
7551 | } | 6430 | } |
7552 | |||
7553 | __hci_update_background_scan(req); | ||
7554 | } | 6431 | } |
7555 | 6432 | ||
7556 | static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode) | 6433 | void mgmt_power_on(struct hci_dev *hdev, int err) |
7557 | { | 6434 | { |
7558 | struct cmd_lookup match = { NULL, hdev }; | 6435 | struct cmd_lookup match = { NULL, hdev }; |
7559 | 6436 | ||
7560 | BT_DBG("status 0x%02x", status); | 6437 | BT_DBG("err %d", err); |
7561 | |||
7562 | if (!status) { | ||
7563 | /* Register the available SMP channels (BR/EDR and LE) only | ||
7564 | * when successfully powering on the controller. This late | ||
7565 | * registration is required so that LE SMP can clearly | ||
7566 | * decide if the public address or static address is used. | ||
7567 | */ | ||
7568 | smp_register(hdev); | ||
7569 | } | ||
7570 | 6438 | ||
7571 | hci_dev_lock(hdev); | 6439 | hci_dev_lock(hdev); |
7572 | 6440 | ||
6441 | if (!err) { | ||
6442 | restart_le_actions(hdev); | ||
6443 | hci_update_background_scan(hdev); | ||
6444 | } | ||
6445 | |||
7573 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 6446 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
7574 | 6447 | ||
7575 | new_settings(hdev, match.sk); | 6448 | new_settings(hdev, match.sk); |
7576 | 6449 | ||
7577 | hci_dev_unlock(hdev); | ||
7578 | |||
7579 | if (match.sk) | 6450 | if (match.sk) |
7580 | sock_put(match.sk); | 6451 | sock_put(match.sk); |
7581 | } | ||
7582 | |||
7583 | static int powered_update_hci(struct hci_dev *hdev) | ||
7584 | { | ||
7585 | struct hci_request req; | ||
7586 | struct adv_info *adv_instance; | ||
7587 | u8 link_sec; | ||
7588 | |||
7589 | hci_req_init(&req, hdev); | ||
7590 | |||
7591 | if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) && | ||
7592 | !lmp_host_ssp_capable(hdev)) { | ||
7593 | u8 mode = 0x01; | ||
7594 | |||
7595 | hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); | ||
7596 | |||
7597 | if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) { | ||
7598 | u8 support = 0x01; | ||
7599 | |||
7600 | hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, | ||
7601 | sizeof(support), &support); | ||
7602 | } | ||
7603 | } | ||
7604 | |||
7605 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) && | ||
7606 | lmp_bredr_capable(hdev)) { | ||
7607 | struct hci_cp_write_le_host_supported cp; | ||
7608 | |||
7609 | cp.le = 0x01; | ||
7610 | cp.simul = 0x00; | ||
7611 | |||
7612 | /* Check first if we already have the right | ||
7613 | * host state (host features set) | ||
7614 | */ | ||
7615 | if (cp.le != lmp_host_le_capable(hdev) || | ||
7616 | cp.simul != lmp_host_le_br_capable(hdev)) | ||
7617 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
7618 | sizeof(cp), &cp); | ||
7619 | } | ||
7620 | |||
7621 | if (lmp_le_capable(hdev)) { | ||
7622 | /* Make sure the controller has a good default for | ||
7623 | * advertising data. This also applies to the case | ||
7624 | * where BR/EDR was toggled during the AUTO_OFF phase. | ||
7625 | */ | ||
7626 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) && | ||
7627 | (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
7628 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))) { | ||
7629 | update_adv_data(&req); | ||
7630 | update_scan_rsp_data(&req); | ||
7631 | } | ||
7632 | |||
7633 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | ||
7634 | hdev->cur_adv_instance == 0x00 && | ||
7635 | !list_empty(&hdev->adv_instances)) { | ||
7636 | adv_instance = list_first_entry(&hdev->adv_instances, | ||
7637 | struct adv_info, list); | ||
7638 | hdev->cur_adv_instance = adv_instance->instance; | ||
7639 | } | ||
7640 | |||
7641 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
7642 | enable_advertising(&req); | ||
7643 | else if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | ||
7644 | hdev->cur_adv_instance) | ||
7645 | schedule_adv_instance(&req, hdev->cur_adv_instance, | ||
7646 | true); | ||
7647 | 6452 | ||
7648 | restart_le_actions(&req); | 6453 | hci_dev_unlock(hdev); |
7649 | } | ||
7650 | |||
7651 | link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY); | ||
7652 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | ||
7653 | hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE, | ||
7654 | sizeof(link_sec), &link_sec); | ||
7655 | |||
7656 | if (lmp_bredr_capable(hdev)) { | ||
7657 | if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) | ||
7658 | write_fast_connectable(&req, true); | ||
7659 | else | ||
7660 | write_fast_connectable(&req, false); | ||
7661 | __hci_update_page_scan(&req); | ||
7662 | update_class(&req); | ||
7663 | update_name(&req); | ||
7664 | update_eir(&req); | ||
7665 | } | ||
7666 | |||
7667 | return hci_req_run(&req, powered_complete); | ||
7668 | } | 6454 | } |
7669 | 6455 | ||
7670 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | 6456 | void __mgmt_power_off(struct hci_dev *hdev) |
7671 | { | 6457 | { |
7672 | struct cmd_lookup match = { NULL, hdev }; | 6458 | struct cmd_lookup match = { NULL, hdev }; |
7673 | u8 status, zero_cod[] = { 0, 0, 0 }; | 6459 | u8 status, zero_cod[] = { 0, 0, 0 }; |
7674 | int err; | ||
7675 | |||
7676 | if (!hci_dev_test_flag(hdev, HCI_MGMT)) | ||
7677 | return 0; | ||
7678 | |||
7679 | if (powered) { | ||
7680 | if (powered_update_hci(hdev) == 0) | ||
7681 | return 0; | ||
7682 | |||
7683 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, | ||
7684 | &match); | ||
7685 | goto new_settings; | ||
7686 | } | ||
7687 | 6460 | ||
7688 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 6461 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
7689 | 6462 | ||
@@ -7705,13 +6478,10 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
7705 | mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | 6478 | mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, |
7706 | zero_cod, sizeof(zero_cod), NULL); | 6479 | zero_cod, sizeof(zero_cod), NULL); |
7707 | 6480 | ||
7708 | new_settings: | 6481 | new_settings(hdev, match.sk); |
7709 | err = new_settings(hdev, match.sk); | ||
7710 | 6482 | ||
7711 | if (match.sk) | 6483 | if (match.sk) |
7712 | sock_put(match.sk); | 6484 | sock_put(match.sk); |
7713 | |||
7714 | return err; | ||
7715 | } | 6485 | } |
7716 | 6486 | ||
7717 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err) | 6487 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err) |
@@ -7733,43 +6503,6 @@ void mgmt_set_powered_failed(struct hci_dev *hdev, int err) | |||
7733 | mgmt_pending_remove(cmd); | 6503 | mgmt_pending_remove(cmd); |
7734 | } | 6504 | } |
7735 | 6505 | ||
7736 | void mgmt_discoverable_timeout(struct hci_dev *hdev) | ||
7737 | { | ||
7738 | struct hci_request req; | ||
7739 | |||
7740 | hci_dev_lock(hdev); | ||
7741 | |||
7742 | /* When discoverable timeout triggers, then just make sure | ||
7743 | * the limited discoverable flag is cleared. Even in the case | ||
7744 | * of a timeout triggered from general discoverable, it is | ||
7745 | * safe to unconditionally clear the flag. | ||
7746 | */ | ||
7747 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | ||
7748 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); | ||
7749 | |||
7750 | hci_req_init(&req, hdev); | ||
7751 | if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { | ||
7752 | u8 scan = SCAN_PAGE; | ||
7753 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, | ||
7754 | sizeof(scan), &scan); | ||
7755 | } | ||
7756 | update_class(&req); | ||
7757 | |||
7758 | /* Advertising instances don't use the global discoverable setting, so | ||
7759 | * only update AD if advertising was enabled using Set Advertising. | ||
7760 | */ | ||
7761 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
7762 | update_adv_data(&req); | ||
7763 | |||
7764 | hci_req_run(&req, NULL); | ||
7765 | |||
7766 | hdev->discov_timeout = 0; | ||
7767 | |||
7768 | new_settings(hdev, NULL); | ||
7769 | |||
7770 | hci_dev_unlock(hdev); | ||
7771 | } | ||
7772 | |||
7773 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 6506 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
7774 | bool persistent) | 6507 | bool persistent) |
7775 | { | 6508 | { |
@@ -8312,7 +7045,7 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
8312 | if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) | 7045 | if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) |
8313 | hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE, | 7046 | hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE, |
8314 | sizeof(enable), &enable); | 7047 | sizeof(enable), &enable); |
8315 | update_eir(&req); | 7048 | __hci_req_update_eir(&req); |
8316 | } else { | 7049 | } else { |
8317 | clear_eir(&req); | 7050 | clear_eir(&req); |
8318 | } | 7051 | } |
@@ -8452,7 +7185,7 @@ static void restart_le_scan(struct hci_dev *hdev) | |||
8452 | hdev->discovery.scan_duration)) | 7185 | hdev->discovery.scan_duration)) |
8453 | return; | 7186 | return; |
8454 | 7187 | ||
8455 | queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart, | 7188 | queue_delayed_work(hdev->req_workqueue, &hdev->le_scan_restart, |
8456 | DISCOV_LE_RESTART_DELAY); | 7189 | DISCOV_LE_RESTART_DELAY); |
8457 | } | 7190 | } |
8458 | 7191 | ||
@@ -8527,6 +7260,18 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
8527 | return; | 7260 | return; |
8528 | } | 7261 | } |
8529 | 7262 | ||
7263 | if (hdev->discovery.limited) { | ||
7264 | /* Check for limited discoverable bit */ | ||
7265 | if (dev_class) { | ||
7266 | if (!(dev_class[1] & 0x20)) | ||
7267 | return; | ||
7268 | } else { | ||
7269 | u8 *flags = eir_get_data(eir, eir_len, EIR_FLAGS, NULL); | ||
7270 | if (!flags || !(flags[0] & LE_AD_LIMITED)) | ||
7271 | return; | ||
7272 | } | ||
7273 | } | ||
7274 | |||
8530 | /* Make sure that the buffer is big enough. The 5 extra bytes | 7275 | /* Make sure that the buffer is big enough. The 5 extra bytes |
8531 | * are for the potential CoD field. | 7276 | * are for the potential CoD field. |
8532 | */ | 7277 | */ |
@@ -8556,7 +7301,8 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
8556 | /* Copy EIR or advertising data into event */ | 7301 | /* Copy EIR or advertising data into event */ |
8557 | memcpy(ev->eir, eir, eir_len); | 7302 | memcpy(ev->eir, eir, eir_len); |
8558 | 7303 | ||
8559 | if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV)) | 7304 | if (dev_class && !eir_get_data(ev->eir, eir_len, EIR_CLASS_OF_DEV, |
7305 | NULL)) | ||
8560 | eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV, | 7306 | eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV, |
8561 | dev_class, 3); | 7307 | dev_class, 3); |
8562 | 7308 | ||
@@ -8606,35 +7352,6 @@ void mgmt_discovering(struct hci_dev *hdev, u8 discovering) | |||
8606 | mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); | 7352 | mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); |
8607 | } | 7353 | } |
8608 | 7354 | ||
8609 | static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) | ||
8610 | { | ||
8611 | BT_DBG("%s status %u", hdev->name, status); | ||
8612 | } | ||
8613 | |||
8614 | void mgmt_reenable_advertising(struct hci_dev *hdev) | ||
8615 | { | ||
8616 | struct hci_request req; | ||
8617 | u8 instance; | ||
8618 | |||
8619 | if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) && | ||
8620 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
8621 | return; | ||
8622 | |||
8623 | instance = get_current_adv_instance(hdev); | ||
8624 | |||
8625 | hci_req_init(&req, hdev); | ||
8626 | |||
8627 | if (instance) { | ||
8628 | schedule_adv_instance(&req, instance, true); | ||
8629 | } else { | ||
8630 | update_adv_data(&req); | ||
8631 | update_scan_rsp_data(&req); | ||
8632 | enable_advertising(&req); | ||
8633 | } | ||
8634 | |||
8635 | hci_req_run(&req, adv_enable_complete); | ||
8636 | } | ||
8637 | |||
8638 | static struct hci_mgmt_chan chan = { | 7355 | static struct hci_mgmt_chan chan = { |
8639 | .channel = HCI_CHANNEL_CONTROL, | 7356 | .channel = HCI_CHANNEL_CONTROL, |
8640 | .handler_count = ARRAY_SIZE(mgmt_handlers), | 7357 | .handler_count = ARRAY_SIZE(mgmt_handlers), |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 29709fbfd1f5..f7eb02f09b54 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -692,11 +692,9 @@ static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s) | |||
692 | 692 | ||
693 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) | 693 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) |
694 | { | 694 | { |
695 | struct rfcomm_session *s; | 695 | struct rfcomm_session *s, *n; |
696 | struct list_head *p, *n; | ||
697 | struct l2cap_chan *chan; | 696 | struct l2cap_chan *chan; |
698 | list_for_each_safe(p, n, &session_list) { | 697 | list_for_each_entry_safe(s, n, &session_list, list) { |
699 | s = list_entry(p, struct rfcomm_session, list); | ||
700 | chan = l2cap_pi(s->sock->sk)->chan; | 698 | chan = l2cap_pi(s->sock->sk)->chan; |
701 | 699 | ||
702 | if ((!bacmp(src, BDADDR_ANY) || !bacmp(&chan->src, src)) && | 700 | if ((!bacmp(src, BDADDR_ANY) || !bacmp(&chan->src, src)) && |
@@ -709,16 +707,14 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) | |||
709 | static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s, | 707 | static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s, |
710 | int err) | 708 | int err) |
711 | { | 709 | { |
712 | struct rfcomm_dlc *d; | 710 | struct rfcomm_dlc *d, *n; |
713 | struct list_head *p, *n; | ||
714 | 711 | ||
715 | s->state = BT_CLOSED; | 712 | s->state = BT_CLOSED; |
716 | 713 | ||
717 | BT_DBG("session %p state %ld err %d", s, s->state, err); | 714 | BT_DBG("session %p state %ld err %d", s, s->state, err); |
718 | 715 | ||
719 | /* Close all dlcs */ | 716 | /* Close all dlcs */ |
720 | list_for_each_safe(p, n, &s->dlcs) { | 717 | list_for_each_entry_safe(d, n, &s->dlcs, list) { |
721 | d = list_entry(p, struct rfcomm_dlc, list); | ||
722 | d->state = BT_CLOSED; | 718 | d->state = BT_CLOSED; |
723 | __rfcomm_dlc_close(d, err); | 719 | __rfcomm_dlc_close(d, err); |
724 | } | 720 | } |
@@ -1771,13 +1767,11 @@ static struct rfcomm_session *rfcomm_recv_frame(struct rfcomm_session *s, | |||
1771 | 1767 | ||
1772 | static void rfcomm_process_connect(struct rfcomm_session *s) | 1768 | static void rfcomm_process_connect(struct rfcomm_session *s) |
1773 | { | 1769 | { |
1774 | struct rfcomm_dlc *d; | 1770 | struct rfcomm_dlc *d, *n; |
1775 | struct list_head *p, *n; | ||
1776 | 1771 | ||
1777 | BT_DBG("session %p state %ld", s, s->state); | 1772 | BT_DBG("session %p state %ld", s, s->state); |
1778 | 1773 | ||
1779 | list_for_each_safe(p, n, &s->dlcs) { | 1774 | list_for_each_entry_safe(d, n, &s->dlcs, list) { |
1780 | d = list_entry(p, struct rfcomm_dlc, list); | ||
1781 | if (d->state == BT_CONFIG) { | 1775 | if (d->state == BT_CONFIG) { |
1782 | d->mtu = s->mtu; | 1776 | d->mtu = s->mtu; |
1783 | if (rfcomm_check_security(d)) { | 1777 | if (rfcomm_check_security(d)) { |
@@ -1843,14 +1837,11 @@ static int rfcomm_process_tx(struct rfcomm_dlc *d) | |||
1843 | 1837 | ||
1844 | static void rfcomm_process_dlcs(struct rfcomm_session *s) | 1838 | static void rfcomm_process_dlcs(struct rfcomm_session *s) |
1845 | { | 1839 | { |
1846 | struct rfcomm_dlc *d; | 1840 | struct rfcomm_dlc *d, *n; |
1847 | struct list_head *p, *n; | ||
1848 | 1841 | ||
1849 | BT_DBG("session %p state %ld", s, s->state); | 1842 | BT_DBG("session %p state %ld", s, s->state); |
1850 | 1843 | ||
1851 | list_for_each_safe(p, n, &s->dlcs) { | 1844 | list_for_each_entry_safe(d, n, &s->dlcs, list) { |
1852 | d = list_entry(p, struct rfcomm_dlc, list); | ||
1853 | |||
1854 | if (test_bit(RFCOMM_TIMED_OUT, &d->flags)) { | 1845 | if (test_bit(RFCOMM_TIMED_OUT, &d->flags)) { |
1855 | __rfcomm_dlc_close(d, ETIMEDOUT); | 1846 | __rfcomm_dlc_close(d, ETIMEDOUT); |
1856 | continue; | 1847 | continue; |
@@ -1985,14 +1976,11 @@ static struct rfcomm_session *rfcomm_check_connection(struct rfcomm_session *s) | |||
1985 | 1976 | ||
1986 | static void rfcomm_process_sessions(void) | 1977 | static void rfcomm_process_sessions(void) |
1987 | { | 1978 | { |
1988 | struct list_head *p, *n; | 1979 | struct rfcomm_session *s, *n; |
1989 | 1980 | ||
1990 | rfcomm_lock(); | 1981 | rfcomm_lock(); |
1991 | 1982 | ||
1992 | list_for_each_safe(p, n, &session_list) { | 1983 | list_for_each_entry_safe(s, n, &session_list, list) { |
1993 | struct rfcomm_session *s; | ||
1994 | s = list_entry(p, struct rfcomm_session, list); | ||
1995 | |||
1996 | if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) { | 1984 | if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) { |
1997 | s->state = BT_DISCONN; | 1985 | s->state = BT_DISCONN; |
1998 | rfcomm_send_disc(s, 0); | 1986 | rfcomm_send_disc(s, 0); |
@@ -2075,15 +2063,12 @@ failed: | |||
2075 | 2063 | ||
2076 | static void rfcomm_kill_listener(void) | 2064 | static void rfcomm_kill_listener(void) |
2077 | { | 2065 | { |
2078 | struct rfcomm_session *s; | 2066 | struct rfcomm_session *s, *n; |
2079 | struct list_head *p, *n; | ||
2080 | 2067 | ||
2081 | BT_DBG(""); | 2068 | BT_DBG(""); |
2082 | 2069 | ||
2083 | list_for_each_safe(p, n, &session_list) { | 2070 | list_for_each_entry_safe(s, n, &session_list, list) |
2084 | s = list_entry(p, struct rfcomm_session, list); | ||
2085 | rfcomm_session_del(s); | 2071 | rfcomm_session_del(s); |
2086 | } | ||
2087 | } | 2072 | } |
2088 | 2073 | ||
2089 | static int rfcomm_run(void *unused) | 2074 | static int rfcomm_run(void *unused) |
@@ -2113,8 +2098,7 @@ static int rfcomm_run(void *unused) | |||
2113 | static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | 2098 | static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) |
2114 | { | 2099 | { |
2115 | struct rfcomm_session *s; | 2100 | struct rfcomm_session *s; |
2116 | struct rfcomm_dlc *d; | 2101 | struct rfcomm_dlc *d, *n; |
2117 | struct list_head *p, *n; | ||
2118 | 2102 | ||
2119 | BT_DBG("conn %p status 0x%02x encrypt 0x%02x", conn, status, encrypt); | 2103 | BT_DBG("conn %p status 0x%02x encrypt 0x%02x", conn, status, encrypt); |
2120 | 2104 | ||
@@ -2122,9 +2106,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2122 | if (!s) | 2106 | if (!s) |
2123 | return; | 2107 | return; |
2124 | 2108 | ||
2125 | list_for_each_safe(p, n, &s->dlcs) { | 2109 | list_for_each_entry_safe(d, n, &s->dlcs, list) { |
2126 | d = list_entry(p, struct rfcomm_dlc, list); | ||
2127 | |||
2128 | if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) { | 2110 | if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) { |
2129 | rfcomm_dlc_clear_timer(d); | 2111 | rfcomm_dlc_clear_timer(d); |
2130 | if (status || encrypt == 0x00) { | 2112 | if (status || encrypt == 0x00) { |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index fe129663bd3f..f52bcbf2e58c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -526,6 +526,9 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, | |||
526 | if (!addr || addr->sa_family != AF_BLUETOOTH) | 526 | if (!addr || addr->sa_family != AF_BLUETOOTH) |
527 | return -EINVAL; | 527 | return -EINVAL; |
528 | 528 | ||
529 | if (addr_len < sizeof(struct sockaddr_sco)) | ||
530 | return -EINVAL; | ||
531 | |||
529 | lock_sock(sk); | 532 | lock_sock(sk); |
530 | 533 | ||
531 | if (sk->sk_state != BT_OPEN) { | 534 | if (sk->sk_state != BT_OPEN) { |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index c91353841e40..ffed8a1d4f27 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -3027,8 +3027,13 @@ static void smp_ready_cb(struct l2cap_chan *chan) | |||
3027 | 3027 | ||
3028 | BT_DBG("chan %p", chan); | 3028 | BT_DBG("chan %p", chan); |
3029 | 3029 | ||
3030 | /* No need to call l2cap_chan_hold() here since we already own | ||
3031 | * the reference taken in smp_new_conn_cb(). This is just the | ||
3032 | * first time that we tie it to a specific pointer. The code in | ||
3033 | * l2cap_core.c ensures that there's no risk this function wont | ||
3034 | * get called if smp_new_conn_cb was previously called. | ||
3035 | */ | ||
3030 | conn->smp = chan; | 3036 | conn->smp = chan; |
3031 | l2cap_chan_hold(chan); | ||
3032 | 3037 | ||
3033 | if (hcon->type == ACL_LINK && test_bit(HCI_CONN_ENCRYPT, &hcon->flags)) | 3038 | if (hcon->type == ACL_LINK && test_bit(HCI_CONN_ENCRYPT, &hcon->flags)) |
3034 | bredr_pairing(chan); | 3039 | bredr_pairing(chan); |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index a642bb829d09..82e3e9705017 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -135,6 +135,7 @@ static void fdb_del_external_learn(struct net_bridge_fdb_entry *f) | |||
135 | { | 135 | { |
136 | struct switchdev_obj_port_fdb fdb = { | 136 | struct switchdev_obj_port_fdb fdb = { |
137 | .obj = { | 137 | .obj = { |
138 | .orig_dev = f->dst->dev, | ||
138 | .id = SWITCHDEV_OBJ_ID_PORT_FDB, | 139 | .id = SWITCHDEV_OBJ_ID_PORT_FDB, |
139 | .flags = SWITCHDEV_F_DEFER, | 140 | .flags = SWITCHDEV_F_DEFER, |
140 | }, | 141 | }, |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index ec02f5869a78..c367b3e1b5ac 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -493,7 +493,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
493 | 493 | ||
494 | dev->priv_flags |= IFF_BRIDGE_PORT; | 494 | dev->priv_flags |= IFF_BRIDGE_PORT; |
495 | 495 | ||
496 | err = netdev_master_upper_dev_link(dev, br->dev); | 496 | err = netdev_master_upper_dev_link(dev, br->dev, NULL, NULL); |
497 | if (err) | 497 | if (err) |
498 | goto err5; | 498 | goto err5; |
499 | 499 | ||
@@ -511,8 +511,11 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
511 | if (br_fdb_insert(br, p, dev->dev_addr, 0)) | 511 | if (br_fdb_insert(br, p, dev->dev_addr, 0)) |
512 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); | 512 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); |
513 | 513 | ||
514 | if (nbp_vlan_init(p)) | 514 | err = nbp_vlan_init(p); |
515 | if (err) { | ||
515 | netdev_err(dev, "failed to initialize vlan filtering on this port\n"); | 516 | netdev_err(dev, "failed to initialize vlan filtering on this port\n"); |
517 | goto err6; | ||
518 | } | ||
516 | 519 | ||
517 | spin_lock_bh(&br->lock); | 520 | spin_lock_bh(&br->lock); |
518 | changed_addr = br_stp_recalculate_bridge_id(br); | 521 | changed_addr = br_stp_recalculate_bridge_id(br); |
@@ -533,6 +536,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
533 | 536 | ||
534 | return 0; | 537 | return 0; |
535 | 538 | ||
539 | err6: | ||
540 | list_del_rcu(&p->list); | ||
541 | br_fdb_delete_by_port(br, p, 0, 1); | ||
542 | nbp_update_port_count(br); | ||
543 | netdev_upper_dev_unlink(dev, br->dev); | ||
544 | |||
536 | err5: | 545 | err5: |
537 | dev->priv_flags &= ~IFF_BRIDGE_PORT; | 546 | dev->priv_flags &= ~IFF_BRIDGE_PORT; |
538 | netdev_rx_handler_unregister(dev); | 547 | netdev_rx_handler_unregister(dev); |
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index cd8deea2d074..30e105f57f0d 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/if_ether.h> | 7 | #include <linux/if_ether.h> |
8 | #include <net/ip.h> | 8 | #include <net/ip.h> |
9 | #include <net/netlink.h> | 9 | #include <net/netlink.h> |
10 | #include <net/switchdev.h> | ||
10 | #if IS_ENABLED(CONFIG_IPV6) | 11 | #if IS_ENABLED(CONFIG_IPV6) |
11 | #include <net/ipv6.h> | 12 | #include <net/ipv6.h> |
12 | #include <net/addrconf.h> | 13 | #include <net/addrconf.h> |
@@ -210,10 +211,32 @@ static inline size_t rtnl_mdb_nlmsg_size(void) | |||
210 | static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry, | 211 | static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry, |
211 | int type) | 212 | int type) |
212 | { | 213 | { |
214 | struct switchdev_obj_port_mdb mdb = { | ||
215 | .obj = { | ||
216 | .id = SWITCHDEV_OBJ_ID_PORT_MDB, | ||
217 | .flags = SWITCHDEV_F_DEFER, | ||
218 | }, | ||
219 | .vid = entry->vid, | ||
220 | }; | ||
221 | struct net_device *port_dev; | ||
213 | struct net *net = dev_net(dev); | 222 | struct net *net = dev_net(dev); |
214 | struct sk_buff *skb; | 223 | struct sk_buff *skb; |
215 | int err = -ENOBUFS; | 224 | int err = -ENOBUFS; |
216 | 225 | ||
226 | port_dev = __dev_get_by_index(net, entry->ifindex); | ||
227 | if (entry->addr.proto == htons(ETH_P_IP)) | ||
228 | ip_eth_mc_map(entry->addr.u.ip4, mdb.addr); | ||
229 | #if IS_ENABLED(CONFIG_IPV6) | ||
230 | else | ||
231 | ipv6_eth_mc_map(&entry->addr.u.ip6, mdb.addr); | ||
232 | #endif | ||
233 | |||
234 | mdb.obj.orig_dev = port_dev; | ||
235 | if (port_dev && type == RTM_NEWMDB) | ||
236 | switchdev_port_obj_add(port_dev, &mdb.obj); | ||
237 | else if (port_dev && type == RTM_DELMDB) | ||
238 | switchdev_port_obj_del(port_dev, &mdb.obj); | ||
239 | |||
217 | skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC); | 240 | skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC); |
218 | if (!skb) | 241 | if (!skb) |
219 | goto errout; | 242 | goto errout; |
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 5f3f64553179..b3cca126b103 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c | |||
@@ -40,6 +40,7 @@ void br_log_state(const struct net_bridge_port *p) | |||
40 | void br_set_state(struct net_bridge_port *p, unsigned int state) | 40 | void br_set_state(struct net_bridge_port *p, unsigned int state) |
41 | { | 41 | { |
42 | struct switchdev_attr attr = { | 42 | struct switchdev_attr attr = { |
43 | .orig_dev = p->dev, | ||
43 | .id = SWITCHDEV_ATTR_ID_PORT_STP_STATE, | 44 | .id = SWITCHDEV_ATTR_ID_PORT_STP_STATE, |
44 | .flags = SWITCHDEV_F_DEFER, | 45 | .flags = SWITCHDEV_F_DEFER, |
45 | .u.stp_state = state, | 46 | .u.stp_state = state, |
@@ -570,6 +571,7 @@ int br_set_max_age(struct net_bridge *br, unsigned long val) | |||
570 | int br_set_ageing_time(struct net_bridge *br, u32 ageing_time) | 571 | int br_set_ageing_time(struct net_bridge *br, u32 ageing_time) |
571 | { | 572 | { |
572 | struct switchdev_attr attr = { | 573 | struct switchdev_attr attr = { |
574 | .orig_dev = br->dev, | ||
573 | .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, | 575 | .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, |
574 | .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, | 576 | .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, |
575 | .u.ageing_time = ageing_time, | 577 | .u.ageing_time = ageing_time, |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 5396ff08af32..a31ac6ad76a2 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -37,9 +37,10 @@ static inline port_id br_make_port_id(__u8 priority, __u16 port_no) | |||
37 | void br_init_port(struct net_bridge_port *p) | 37 | void br_init_port(struct net_bridge_port *p) |
38 | { | 38 | { |
39 | struct switchdev_attr attr = { | 39 | struct switchdev_attr attr = { |
40 | .orig_dev = p->dev, | ||
40 | .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, | 41 | .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, |
41 | .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP | SWITCHDEV_F_DEFER, | 42 | .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP | SWITCHDEV_F_DEFER, |
42 | .u.ageing_time = p->br->ageing_time, | 43 | .u.ageing_time = jiffies_to_clock_t(p->br->ageing_time), |
43 | }; | 44 | }; |
44 | int err; | 45 | int err; |
45 | 46 | ||
@@ -142,7 +143,10 @@ static void br_stp_start(struct net_bridge *br) | |||
142 | char *envp[] = { NULL }; | 143 | char *envp[] = { NULL }; |
143 | struct net_bridge_port *p; | 144 | struct net_bridge_port *p; |
144 | 145 | ||
145 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | 146 | if (net_eq(dev_net(br->dev), &init_net)) |
147 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | ||
148 | else | ||
149 | r = -ENOENT; | ||
146 | 150 | ||
147 | spin_lock_bh(&br->lock); | 151 | spin_lock_bh(&br->lock); |
148 | 152 | ||
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 8365bd53c421..6b8091407ca3 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include "br_private.h" | 23 | #include "br_private.h" |
24 | 24 | ||
25 | #define to_dev(obj) container_of(obj, struct device, kobj) | ||
26 | #define to_bridge(cd) ((struct net_bridge *)netdev_priv(to_net_dev(cd))) | 25 | #define to_bridge(cd) ((struct net_bridge *)netdev_priv(to_net_dev(cd))) |
27 | 26 | ||
28 | /* | 27 | /* |
@@ -814,7 +813,7 @@ static ssize_t brforward_read(struct file *filp, struct kobject *kobj, | |||
814 | struct bin_attribute *bin_attr, | 813 | struct bin_attribute *bin_attr, |
815 | char *buf, loff_t off, size_t count) | 814 | char *buf, loff_t off, size_t count) |
816 | { | 815 | { |
817 | struct device *dev = to_dev(kobj); | 816 | struct device *dev = kobj_to_dev(kobj); |
818 | struct net_bridge *br = to_bridge(dev); | 817 | struct net_bridge *br = to_bridge(dev); |
819 | int n; | 818 | int n; |
820 | 819 | ||
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 1394da63614a..85e43af4af7a 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
@@ -73,6 +73,7 @@ static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, | |||
73 | u16 vid, u16 flags) | 73 | u16 vid, u16 flags) |
74 | { | 74 | { |
75 | struct switchdev_obj_port_vlan v = { | 75 | struct switchdev_obj_port_vlan v = { |
76 | .obj.orig_dev = dev, | ||
76 | .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, | 77 | .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, |
77 | .flags = flags, | 78 | .flags = flags, |
78 | .vid_begin = vid, | 79 | .vid_begin = vid, |
@@ -120,6 +121,7 @@ static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br, | |||
120 | u16 vid) | 121 | u16 vid) |
121 | { | 122 | { |
122 | struct switchdev_obj_port_vlan v = { | 123 | struct switchdev_obj_port_vlan v = { |
124 | .obj.orig_dev = dev, | ||
123 | .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, | 125 | .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, |
124 | .vid_begin = vid, | 126 | .vid_begin = vid, |
125 | .vid_end = vid, | 127 | .vid_end = vid, |
@@ -624,9 +626,21 @@ void br_recalculate_fwd_mask(struct net_bridge *br) | |||
624 | 626 | ||
625 | int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) | 627 | int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) |
626 | { | 628 | { |
629 | struct switchdev_attr attr = { | ||
630 | .orig_dev = br->dev, | ||
631 | .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, | ||
632 | .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, | ||
633 | .u.vlan_filtering = val, | ||
634 | }; | ||
635 | int err; | ||
636 | |||
627 | if (br->vlan_enabled == val) | 637 | if (br->vlan_enabled == val) |
628 | return 0; | 638 | return 0; |
629 | 639 | ||
640 | err = switchdev_port_attr_set(br->dev, &attr); | ||
641 | if (err && err != -EOPNOTSUPP) | ||
642 | return err; | ||
643 | |||
630 | br->vlan_enabled = val; | 644 | br->vlan_enabled = val; |
631 | br_manage_promisc(br); | 645 | br_manage_promisc(br); |
632 | recalculate_group_addr(br); | 646 | recalculate_group_addr(br); |
@@ -637,13 +651,15 @@ int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) | |||
637 | 651 | ||
638 | int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) | 652 | int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) |
639 | { | 653 | { |
654 | int err; | ||
655 | |||
640 | if (!rtnl_trylock()) | 656 | if (!rtnl_trylock()) |
641 | return restart_syscall(); | 657 | return restart_syscall(); |
642 | 658 | ||
643 | __br_vlan_filter_toggle(br, val); | 659 | err = __br_vlan_filter_toggle(br, val); |
644 | rtnl_unlock(); | 660 | rtnl_unlock(); |
645 | 661 | ||
646 | return 0; | 662 | return err; |
647 | } | 663 | } |
648 | 664 | ||
649 | int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) | 665 | int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) |
@@ -891,6 +907,12 @@ err_rhtbl: | |||
891 | 907 | ||
892 | int nbp_vlan_init(struct net_bridge_port *p) | 908 | int nbp_vlan_init(struct net_bridge_port *p) |
893 | { | 909 | { |
910 | struct switchdev_attr attr = { | ||
911 | .orig_dev = p->br->dev, | ||
912 | .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, | ||
913 | .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, | ||
914 | .u.vlan_filtering = p->br->vlan_enabled, | ||
915 | }; | ||
894 | struct net_bridge_vlan_group *vg; | 916 | struct net_bridge_vlan_group *vg; |
895 | int ret = -ENOMEM; | 917 | int ret = -ENOMEM; |
896 | 918 | ||
@@ -898,6 +920,10 @@ int nbp_vlan_init(struct net_bridge_port *p) | |||
898 | if (!vg) | 920 | if (!vg) |
899 | goto out; | 921 | goto out; |
900 | 922 | ||
923 | ret = switchdev_port_attr_set(p->dev, &attr); | ||
924 | if (ret && ret != -EOPNOTSUPP) | ||
925 | goto err_vlan_enabled; | ||
926 | |||
901 | ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); | 927 | ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); |
902 | if (ret) | 928 | if (ret) |
903 | goto err_rhtbl; | 929 | goto err_rhtbl; |
@@ -917,6 +943,7 @@ err_vlan_add: | |||
917 | RCU_INIT_POINTER(p->vlgrp, NULL); | 943 | RCU_INIT_POINTER(p->vlgrp, NULL); |
918 | synchronize_rcu(); | 944 | synchronize_rcu(); |
919 | rhashtable_destroy(&vg->vlan_hash); | 945 | rhashtable_destroy(&vg->vlan_hash); |
946 | err_vlan_enabled: | ||
920 | err_rhtbl: | 947 | err_rhtbl: |
921 | kfree(vg); | 948 | kfree(vg); |
922 | 949 | ||
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c index 17fd5f2cb4b8..98de6e7fd86d 100644 --- a/net/bridge/netfilter/ebt_ip6.c +++ b/net/bridge/netfilter/ebt_ip6.c | |||
@@ -65,8 +65,8 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
65 | return false; | 65 | return false; |
66 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) | 66 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) |
67 | return false; | 67 | return false; |
68 | if (!(info->bitmask & ( EBT_IP6_DPORT | | 68 | if (!(info->bitmask & (EBT_IP6_DPORT | |
69 | EBT_IP6_SPORT | EBT_IP6_ICMP6))) | 69 | EBT_IP6_SPORT | EBT_IP6_ICMP6))) |
70 | return true; | 70 | return true; |
71 | 71 | ||
72 | /* min icmpv6 headersize is 4, so sizeof(_pkthdr) is ok. */ | 72 | /* min icmpv6 headersize is 4, so sizeof(_pkthdr) is ok. */ |
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 0ad639a96142..152300d164ac 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
@@ -36,14 +36,12 @@ static int ebt_log_tg_check(const struct xt_tgchk_param *par) | |||
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | 38 | ||
39 | struct tcpudphdr | 39 | struct tcpudphdr { |
40 | { | ||
41 | __be16 src; | 40 | __be16 src; |
42 | __be16 dst; | 41 | __be16 dst; |
43 | }; | 42 | }; |
44 | 43 | ||
45 | struct arppayload | 44 | struct arppayload { |
46 | { | ||
47 | unsigned char mac_src[ETH_ALEN]; | 45 | unsigned char mac_src[ETH_ALEN]; |
48 | unsigned char ip_src[4]; | 46 | unsigned char ip_src[4]; |
49 | unsigned char mac_dst[ETH_ALEN]; | 47 | unsigned char mac_dst[ETH_ALEN]; |
@@ -152,7 +150,8 @@ ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
152 | ntohs(ah->ar_op)); | 150 | ntohs(ah->ar_op)); |
153 | 151 | ||
154 | /* If it's for Ethernet and the lengths are OK, | 152 | /* If it's for Ethernet and the lengths are OK, |
155 | * then log the ARP payload */ | 153 | * then log the ARP payload |
154 | */ | ||
156 | if (ah->ar_hrd == htons(1) && | 155 | if (ah->ar_hrd == htons(1) && |
157 | ah->ar_hln == ETH_ALEN && | 156 | ah->ar_hln == ETH_ALEN && |
158 | ah->ar_pln == sizeof(__be32)) { | 157 | ah->ar_pln == sizeof(__be32)) { |
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c index 0c40570069ba..6b731e12ecfa 100644 --- a/net/bridge/netfilter/ebt_stp.c +++ b/net/bridge/netfilter/ebt_stp.c | |||
@@ -41,7 +41,7 @@ struct stp_config_pdu { | |||
41 | #define NR32(p) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) | 41 | #define NR32(p) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) |
42 | 42 | ||
43 | static bool ebt_filter_config(const struct ebt_stp_info *info, | 43 | static bool ebt_filter_config(const struct ebt_stp_info *info, |
44 | const struct stp_config_pdu *stpc) | 44 | const struct stp_config_pdu *stpc) |
45 | { | 45 | { |
46 | const struct ebt_stp_config_info *c; | 46 | const struct ebt_stp_config_info *c; |
47 | uint16_t v16; | 47 | uint16_t v16; |
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c index 618568888128..98c221dbf059 100644 --- a/net/bridge/netfilter/ebt_vlan.c +++ b/net/bridge/netfilter/ebt_vlan.c | |||
@@ -66,7 +66,8 @@ ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
66 | * - Canonical Format Indicator (CFI). The Canonical Format Indicator | 66 | * - Canonical Format Indicator (CFI). The Canonical Format Indicator |
67 | * (CFI) is a single bit flag value. Currently ignored. | 67 | * (CFI) is a single bit flag value. Currently ignored. |
68 | * - VLAN Identifier (VID). The VID is encoded as | 68 | * - VLAN Identifier (VID). The VID is encoded as |
69 | * an unsigned binary number. */ | 69 | * an unsigned binary number. |
70 | */ | ||
70 | id = TCI & VLAN_VID_MASK; | 71 | id = TCI & VLAN_VID_MASK; |
71 | prio = (TCI >> 13) & 0x7; | 72 | prio = (TCI >> 13) & 0x7; |
72 | 73 | ||
@@ -98,7 +99,8 @@ static int ebt_vlan_mt_check(const struct xt_mtchk_param *par) | |||
98 | } | 99 | } |
99 | 100 | ||
100 | /* Check for bitmask range | 101 | /* Check for bitmask range |
101 | * True if even one bit is out of mask */ | 102 | * True if even one bit is out of mask |
103 | */ | ||
102 | if (info->bitmask & ~EBT_VLAN_MASK) { | 104 | if (info->bitmask & ~EBT_VLAN_MASK) { |
103 | pr_debug("bitmask %2X is out of mask (%2X)\n", | 105 | pr_debug("bitmask %2X is out of mask (%2X)\n", |
104 | info->bitmask, EBT_VLAN_MASK); | 106 | info->bitmask, EBT_VLAN_MASK); |
@@ -117,7 +119,8 @@ static int ebt_vlan_mt_check(const struct xt_mtchk_param *par) | |||
117 | * 0 - The null VLAN ID. | 119 | * 0 - The null VLAN ID. |
118 | * 1 - The default Port VID (PVID) | 120 | * 1 - The default Port VID (PVID) |
119 | * 0x0FFF - Reserved for implementation use. | 121 | * 0x0FFF - Reserved for implementation use. |
120 | * if_vlan.h: VLAN_N_VID 4096. */ | 122 | * if_vlan.h: VLAN_N_VID 4096. |
123 | */ | ||
121 | if (GET_BITMASK(EBT_VLAN_ID)) { | 124 | if (GET_BITMASK(EBT_VLAN_ID)) { |
122 | if (!!info->id) { /* if id!=0 => check vid range */ | 125 | if (!!info->id) { /* if id!=0 => check vid range */ |
123 | if (info->id > VLAN_N_VID) { | 126 | if (info->id > VLAN_N_VID) { |
@@ -128,7 +131,8 @@ static int ebt_vlan_mt_check(const struct xt_mtchk_param *par) | |||
128 | /* Note: This is valid VLAN-tagged frame point. | 131 | /* Note: This is valid VLAN-tagged frame point. |
129 | * Any value of user_priority are acceptable, | 132 | * Any value of user_priority are acceptable, |
130 | * but should be ignored according to 802.1Q Std. | 133 | * but should be ignored according to 802.1Q Std. |
131 | * So we just drop the prio flag. */ | 134 | * So we just drop the prio flag. |
135 | */ | ||
132 | info->bitmask &= ~EBT_VLAN_PRIO; | 136 | info->bitmask &= ~EBT_VLAN_PRIO; |
133 | } | 137 | } |
134 | /* Else, id=0 (null VLAN ID) => user_priority range (any?) */ | 138 | /* Else, id=0 (null VLAN ID) => user_priority range (any?) */ |
@@ -143,7 +147,8 @@ static int ebt_vlan_mt_check(const struct xt_mtchk_param *par) | |||
143 | } | 147 | } |
144 | /* Check for encapsulated proto range - it is possible to be | 148 | /* Check for encapsulated proto range - it is possible to be |
145 | * any value for u_short range. | 149 | * any value for u_short range. |
146 | * if_ether.h: ETH_ZLEN 60 - Min. octets in frame sans FCS */ | 150 | * if_ether.h: ETH_ZLEN 60 - Min. octets in frame sans FCS |
151 | */ | ||
147 | if (GET_BITMASK(EBT_VLAN_ENCAP)) { | 152 | if (GET_BITMASK(EBT_VLAN_ENCAP)) { |
148 | if ((unsigned short) ntohs(info->encap) < ETH_ZLEN) { | 153 | if ((unsigned short) ntohs(info->encap) < ETH_ZLEN) { |
149 | pr_debug("encap frame length %d is less than " | 154 | pr_debug("encap frame length %d is less than " |
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 32eccd101f26..593a1bdc079e 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | 13 | ||
14 | #define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \ | 14 | #define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \ |
15 | (1 << NF_BR_LOCAL_OUT)) | 15 | (1 << NF_BR_LOCAL_OUT)) |
16 | 16 | ||
17 | static struct ebt_entries initial_chains[] = { | 17 | static struct ebt_entries initial_chains[] = { |
18 | { | 18 | { |
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index ec55358f00c8..eb33919821ee 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | 13 | ||
14 | #define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \ | 14 | #define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \ |
15 | (1 << NF_BR_POST_ROUTING)) | 15 | (1 << NF_BR_POST_ROUTING)) |
16 | 16 | ||
17 | static struct ebt_entries initial_chains[] = { | 17 | static struct ebt_entries initial_chains[] = { |
18 | { | 18 | { |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index f46ca417bf2d..67b2e27999aa 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -35,8 +35,7 @@ | |||
35 | "report to author: "format, ## args) | 35 | "report to author: "format, ## args) |
36 | /* #define BUGPRINT(format, args...) */ | 36 | /* #define BUGPRINT(format, args...) */ |
37 | 37 | ||
38 | /* | 38 | /* Each cpu has its own set of counters, so there is no need for write_lock in |
39 | * Each cpu has its own set of counters, so there is no need for write_lock in | ||
40 | * the softirq | 39 | * the softirq |
41 | * For reading or updating the counters, the user context needs to | 40 | * For reading or updating the counters, the user context needs to |
42 | * get a write_lock | 41 | * get a write_lock |
@@ -46,7 +45,7 @@ | |||
46 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | 45 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) |
47 | #define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter))) | 46 | #define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter))) |
48 | #define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \ | 47 | #define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \ |
49 | COUNTER_OFFSET(n) * cpu)) | 48 | COUNTER_OFFSET(n) * cpu)) |
50 | 49 | ||
51 | 50 | ||
52 | 51 | ||
@@ -126,7 +125,7 @@ ebt_dev_check(const char *entry, const struct net_device *device) | |||
126 | /* process standard matches */ | 125 | /* process standard matches */ |
127 | static inline int | 126 | static inline int |
128 | ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, | 127 | ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, |
129 | const struct net_device *in, const struct net_device *out) | 128 | const struct net_device *in, const struct net_device *out) |
130 | { | 129 | { |
131 | const struct ethhdr *h = eth_hdr(skb); | 130 | const struct ethhdr *h = eth_hdr(skb); |
132 | const struct net_bridge_port *p; | 131 | const struct net_bridge_port *p; |
@@ -162,7 +161,7 @@ ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, | |||
162 | for (i = 0; i < 6; i++) | 161 | for (i = 0; i < 6; i++) |
163 | verdict |= (h->h_source[i] ^ e->sourcemac[i]) & | 162 | verdict |= (h->h_source[i] ^ e->sourcemac[i]) & |
164 | e->sourcemsk[i]; | 163 | e->sourcemsk[i]; |
165 | if (FWINV2(verdict != 0, EBT_ISOURCE) ) | 164 | if (FWINV2(verdict != 0, EBT_ISOURCE)) |
166 | return 1; | 165 | return 1; |
167 | } | 166 | } |
168 | if (e->bitmask & EBT_DESTMAC) { | 167 | if (e->bitmask & EBT_DESTMAC) { |
@@ -170,7 +169,7 @@ ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, | |||
170 | for (i = 0; i < 6; i++) | 169 | for (i = 0; i < 6; i++) |
171 | verdict |= (h->h_dest[i] ^ e->destmac[i]) & | 170 | verdict |= (h->h_dest[i] ^ e->destmac[i]) & |
172 | e->destmsk[i]; | 171 | e->destmsk[i]; |
173 | if (FWINV2(verdict != 0, EBT_IDEST) ) | 172 | if (FWINV2(verdict != 0, EBT_IDEST)) |
174 | return 1; | 173 | return 1; |
175 | } | 174 | } |
176 | return 0; | 175 | return 0; |
@@ -237,7 +236,8 @@ unsigned int ebt_do_table(struct sk_buff *skb, | |||
237 | (*(counter_base + i)).bcnt += skb->len; | 236 | (*(counter_base + i)).bcnt += skb->len; |
238 | 237 | ||
239 | /* these should only watch: not modify, nor tell us | 238 | /* these should only watch: not modify, nor tell us |
240 | what to do with the packet */ | 239 | * what to do with the packet |
240 | */ | ||
241 | EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &acpar); | 241 | EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &acpar); |
242 | 242 | ||
243 | t = (struct ebt_entry_target *) | 243 | t = (struct ebt_entry_target *) |
@@ -323,7 +323,7 @@ letscontinue: | |||
323 | /* If it succeeds, returns element and locks mutex */ | 323 | /* If it succeeds, returns element and locks mutex */ |
324 | static inline void * | 324 | static inline void * |
325 | find_inlist_lock_noload(struct list_head *head, const char *name, int *error, | 325 | find_inlist_lock_noload(struct list_head *head, const char *name, int *error, |
326 | struct mutex *mutex) | 326 | struct mutex *mutex) |
327 | { | 327 | { |
328 | struct { | 328 | struct { |
329 | struct list_head list; | 329 | struct list_head list; |
@@ -342,7 +342,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error, | |||
342 | 342 | ||
343 | static void * | 343 | static void * |
344 | find_inlist_lock(struct list_head *head, const char *name, const char *prefix, | 344 | find_inlist_lock(struct list_head *head, const char *name, const char *prefix, |
345 | int *error, struct mutex *mutex) | 345 | int *error, struct mutex *mutex) |
346 | { | 346 | { |
347 | return try_then_request_module( | 347 | return try_then_request_module( |
348 | find_inlist_lock_noload(head, name, error, mutex), | 348 | find_inlist_lock_noload(head, name, error, mutex), |
@@ -451,7 +451,8 @@ static int ebt_verify_pointers(const struct ebt_replace *repl, | |||
451 | if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { | 451 | if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) { |
452 | if (e->bitmask != 0) { | 452 | if (e->bitmask != 0) { |
453 | /* we make userspace set this right, | 453 | /* we make userspace set this right, |
454 | so there is no misunderstanding */ | 454 | * so there is no misunderstanding |
455 | */ | ||
455 | BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " | 456 | BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " |
456 | "in distinguisher\n"); | 457 | "in distinguisher\n"); |
457 | return -EINVAL; | 458 | return -EINVAL; |
@@ -487,15 +488,14 @@ static int ebt_verify_pointers(const struct ebt_replace *repl, | |||
487 | return 0; | 488 | return 0; |
488 | } | 489 | } |
489 | 490 | ||
490 | /* | 491 | /* this one is very careful, as it is the first function |
491 | * this one is very careful, as it is the first function | ||
492 | * to parse the userspace data | 492 | * to parse the userspace data |
493 | */ | 493 | */ |
494 | static inline int | 494 | static inline int |
495 | ebt_check_entry_size_and_hooks(const struct ebt_entry *e, | 495 | ebt_check_entry_size_and_hooks(const struct ebt_entry *e, |
496 | const struct ebt_table_info *newinfo, | 496 | const struct ebt_table_info *newinfo, |
497 | unsigned int *n, unsigned int *cnt, | 497 | unsigned int *n, unsigned int *cnt, |
498 | unsigned int *totalcnt, unsigned int *udc_cnt) | 498 | unsigned int *totalcnt, unsigned int *udc_cnt) |
499 | { | 499 | { |
500 | int i; | 500 | int i; |
501 | 501 | ||
@@ -504,10 +504,12 @@ ebt_check_entry_size_and_hooks(const struct ebt_entry *e, | |||
504 | break; | 504 | break; |
505 | } | 505 | } |
506 | /* beginning of a new chain | 506 | /* beginning of a new chain |
507 | if i == NF_BR_NUMHOOKS it must be a user defined chain */ | 507 | * if i == NF_BR_NUMHOOKS it must be a user defined chain |
508 | */ | ||
508 | if (i != NF_BR_NUMHOOKS || !e->bitmask) { | 509 | if (i != NF_BR_NUMHOOKS || !e->bitmask) { |
509 | /* this checks if the previous chain has as many entries | 510 | /* this checks if the previous chain has as many entries |
510 | as it said it has */ | 511 | * as it said it has |
512 | */ | ||
511 | if (*n != *cnt) { | 513 | if (*n != *cnt) { |
512 | BUGPRINT("nentries does not equal the nr of entries " | 514 | BUGPRINT("nentries does not equal the nr of entries " |
513 | "in the chain\n"); | 515 | "in the chain\n"); |
@@ -549,20 +551,18 @@ ebt_check_entry_size_and_hooks(const struct ebt_entry *e, | |||
549 | return 0; | 551 | return 0; |
550 | } | 552 | } |
551 | 553 | ||
552 | struct ebt_cl_stack | 554 | struct ebt_cl_stack { |
553 | { | ||
554 | struct ebt_chainstack cs; | 555 | struct ebt_chainstack cs; |
555 | int from; | 556 | int from; |
556 | unsigned int hookmask; | 557 | unsigned int hookmask; |
557 | }; | 558 | }; |
558 | 559 | ||
559 | /* | 560 | /* We need these positions to check that the jumps to a different part of the |
560 | * we need these positions to check that the jumps to a different part of the | ||
561 | * entries is a jump to the beginning of a new chain. | 561 | * entries is a jump to the beginning of a new chain. |
562 | */ | 562 | */ |
563 | static inline int | 563 | static inline int |
564 | ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, | 564 | ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, |
565 | unsigned int *n, struct ebt_cl_stack *udc) | 565 | unsigned int *n, struct ebt_cl_stack *udc) |
566 | { | 566 | { |
567 | int i; | 567 | int i; |
568 | 568 | ||
@@ -649,9 +649,9 @@ ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt) | |||
649 | 649 | ||
650 | static inline int | 650 | static inline int |
651 | ebt_check_entry(struct ebt_entry *e, struct net *net, | 651 | ebt_check_entry(struct ebt_entry *e, struct net *net, |
652 | const struct ebt_table_info *newinfo, | 652 | const struct ebt_table_info *newinfo, |
653 | const char *name, unsigned int *cnt, | 653 | const char *name, unsigned int *cnt, |
654 | struct ebt_cl_stack *cl_s, unsigned int udc_cnt) | 654 | struct ebt_cl_stack *cl_s, unsigned int udc_cnt) |
655 | { | 655 | { |
656 | struct ebt_entry_target *t; | 656 | struct ebt_entry_target *t; |
657 | struct xt_target *target; | 657 | struct xt_target *target; |
@@ -673,7 +673,7 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, | |||
673 | BUGPRINT("Unknown flag for inv bitmask\n"); | 673 | BUGPRINT("Unknown flag for inv bitmask\n"); |
674 | return -EINVAL; | 674 | return -EINVAL; |
675 | } | 675 | } |
676 | if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) { | 676 | if ((e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3)) { |
677 | BUGPRINT("NOPROTO & 802_3 not allowed\n"); | 677 | BUGPRINT("NOPROTO & 802_3 not allowed\n"); |
678 | return -EINVAL; | 678 | return -EINVAL; |
679 | } | 679 | } |
@@ -687,7 +687,8 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, | |||
687 | break; | 687 | break; |
688 | } | 688 | } |
689 | /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on | 689 | /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on |
690 | a base chain */ | 690 | * a base chain |
691 | */ | ||
691 | if (i < NF_BR_NUMHOOKS) | 692 | if (i < NF_BR_NUMHOOKS) |
692 | hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS); | 693 | hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS); |
693 | else { | 694 | else { |
@@ -758,13 +759,12 @@ cleanup_matches: | |||
758 | return ret; | 759 | return ret; |
759 | } | 760 | } |
760 | 761 | ||
761 | /* | 762 | /* checks for loops and sets the hook mask for udc |
762 | * checks for loops and sets the hook mask for udc | ||
763 | * the hook mask for udc tells us from which base chains the udc can be | 763 | * the hook mask for udc tells us from which base chains the udc can be |
764 | * accessed. This mask is a parameter to the check() functions of the extensions | 764 | * accessed. This mask is a parameter to the check() functions of the extensions |
765 | */ | 765 | */ |
766 | static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s, | 766 | static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s, |
767 | unsigned int udc_cnt, unsigned int hooknr, char *base) | 767 | unsigned int udc_cnt, unsigned int hooknr, char *base) |
768 | { | 768 | { |
769 | int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict; | 769 | int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict; |
770 | const struct ebt_entry *e = (struct ebt_entry *)chain->data; | 770 | const struct ebt_entry *e = (struct ebt_entry *)chain->data; |
@@ -853,7 +853,8 @@ static int translate_table(struct net *net, const char *name, | |||
853 | return -EINVAL; | 853 | return -EINVAL; |
854 | } | 854 | } |
855 | /* make sure chains are ordered after each other in same order | 855 | /* make sure chains are ordered after each other in same order |
856 | as their corresponding hooks */ | 856 | * as their corresponding hooks |
857 | */ | ||
857 | for (j = i + 1; j < NF_BR_NUMHOOKS; j++) { | 858 | for (j = i + 1; j < NF_BR_NUMHOOKS; j++) { |
858 | if (!newinfo->hook_entry[j]) | 859 | if (!newinfo->hook_entry[j]) |
859 | continue; | 860 | continue; |
@@ -868,7 +869,8 @@ static int translate_table(struct net *net, const char *name, | |||
868 | i = 0; /* holds the expected nr. of entries for the chain */ | 869 | i = 0; /* holds the expected nr. of entries for the chain */ |
869 | j = 0; /* holds the up to now counted entries for the chain */ | 870 | j = 0; /* holds the up to now counted entries for the chain */ |
870 | k = 0; /* holds the total nr. of entries, should equal | 871 | k = 0; /* holds the total nr. of entries, should equal |
871 | newinfo->nentries afterwards */ | 872 | * newinfo->nentries afterwards |
873 | */ | ||
872 | udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */ | 874 | udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */ |
873 | ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, | 875 | ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, |
874 | ebt_check_entry_size_and_hooks, newinfo, | 876 | ebt_check_entry_size_and_hooks, newinfo, |
@@ -888,10 +890,12 @@ static int translate_table(struct net *net, const char *name, | |||
888 | } | 890 | } |
889 | 891 | ||
890 | /* get the location of the udc, put them in an array | 892 | /* get the location of the udc, put them in an array |
891 | while we're at it, allocate the chainstack */ | 893 | * while we're at it, allocate the chainstack |
894 | */ | ||
892 | if (udc_cnt) { | 895 | if (udc_cnt) { |
893 | /* this will get free'd in do_replace()/ebt_register_table() | 896 | /* this will get free'd in do_replace()/ebt_register_table() |
894 | if an error occurs */ | 897 | * if an error occurs |
898 | */ | ||
895 | newinfo->chainstack = | 899 | newinfo->chainstack = |
896 | vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack))); | 900 | vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack))); |
897 | if (!newinfo->chainstack) | 901 | if (!newinfo->chainstack) |
@@ -932,14 +936,15 @@ static int translate_table(struct net *net, const char *name, | |||
932 | } | 936 | } |
933 | 937 | ||
934 | /* we now know the following (along with E=mc²): | 938 | /* we now know the following (along with E=mc²): |
935 | - the nr of entries in each chain is right | 939 | * - the nr of entries in each chain is right |
936 | - the size of the allocated space is right | 940 | * - the size of the allocated space is right |
937 | - all valid hooks have a corresponding chain | 941 | * - all valid hooks have a corresponding chain |
938 | - there are no loops | 942 | * - there are no loops |
939 | - wrong data can still be on the level of a single entry | 943 | * - wrong data can still be on the level of a single entry |
940 | - could be there are jumps to places that are not the | 944 | * - could be there are jumps to places that are not the |
941 | beginning of a chain. This can only occur in chains that | 945 | * beginning of a chain. This can only occur in chains that |
942 | are not accessible from any base chains, so we don't care. */ | 946 | * are not accessible from any base chains, so we don't care. |
947 | */ | ||
943 | 948 | ||
944 | /* used to know what we need to clean up if something goes wrong */ | 949 | /* used to know what we need to clean up if something goes wrong */ |
945 | i = 0; | 950 | i = 0; |
@@ -955,7 +960,7 @@ static int translate_table(struct net *net, const char *name, | |||
955 | 960 | ||
956 | /* called under write_lock */ | 961 | /* called under write_lock */ |
957 | static void get_counters(const struct ebt_counter *oldcounters, | 962 | static void get_counters(const struct ebt_counter *oldcounters, |
958 | struct ebt_counter *counters, unsigned int nentries) | 963 | struct ebt_counter *counters, unsigned int nentries) |
959 | { | 964 | { |
960 | int i, cpu; | 965 | int i, cpu; |
961 | struct ebt_counter *counter_base; | 966 | struct ebt_counter *counter_base; |
@@ -986,7 +991,8 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl, | |||
986 | struct ebt_table *t; | 991 | struct ebt_table *t; |
987 | 992 | ||
988 | /* the user wants counters back | 993 | /* the user wants counters back |
989 | the check on the size is done later, when we have the lock */ | 994 | * the check on the size is done later, when we have the lock |
995 | */ | ||
990 | if (repl->num_counters) { | 996 | if (repl->num_counters) { |
991 | unsigned long size = repl->num_counters * sizeof(*counterstmp); | 997 | unsigned long size = repl->num_counters * sizeof(*counterstmp); |
992 | counterstmp = vmalloc(size); | 998 | counterstmp = vmalloc(size); |
@@ -1038,9 +1044,10 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl, | |||
1038 | write_unlock_bh(&t->lock); | 1044 | write_unlock_bh(&t->lock); |
1039 | mutex_unlock(&ebt_mutex); | 1045 | mutex_unlock(&ebt_mutex); |
1040 | /* so, a user can change the chains while having messed up her counter | 1046 | /* so, a user can change the chains while having messed up her counter |
1041 | allocation. Only reason why this is done is because this way the lock | 1047 | * allocation. Only reason why this is done is because this way the lock |
1042 | is held only once, while this doesn't bring the kernel into a | 1048 | * is held only once, while this doesn't bring the kernel into a |
1043 | dangerous state. */ | 1049 | * dangerous state. |
1050 | */ | ||
1044 | if (repl->num_counters && | 1051 | if (repl->num_counters && |
1045 | copy_to_user(repl->counters, counterstmp, | 1052 | copy_to_user(repl->counters, counterstmp, |
1046 | repl->num_counters * sizeof(struct ebt_counter))) { | 1053 | repl->num_counters * sizeof(struct ebt_counter))) { |
@@ -1342,13 +1349,14 @@ static int update_counters(struct net *net, const void __user *user, | |||
1342 | } | 1349 | } |
1343 | 1350 | ||
1344 | static inline int ebt_make_matchname(const struct ebt_entry_match *m, | 1351 | static inline int ebt_make_matchname(const struct ebt_entry_match *m, |
1345 | const char *base, char __user *ubase) | 1352 | const char *base, char __user *ubase) |
1346 | { | 1353 | { |
1347 | char __user *hlp = ubase + ((char *)m - base); | 1354 | char __user *hlp = ubase + ((char *)m - base); |
1348 | char name[EBT_FUNCTION_MAXNAMELEN] = {}; | 1355 | char name[EBT_FUNCTION_MAXNAMELEN] = {}; |
1349 | 1356 | ||
1350 | /* ebtables expects 32 bytes long names but xt_match names are 29 bytes | 1357 | /* ebtables expects 32 bytes long names but xt_match names are 29 bytes |
1351 | long. Copy 29 bytes and fill remaining bytes with zeroes. */ | 1358 | * long. Copy 29 bytes and fill remaining bytes with zeroes. |
1359 | */ | ||
1352 | strlcpy(name, m->u.match->name, sizeof(name)); | 1360 | strlcpy(name, m->u.match->name, sizeof(name)); |
1353 | if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) | 1361 | if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) |
1354 | return -EFAULT; | 1362 | return -EFAULT; |
@@ -1356,19 +1364,19 @@ static inline int ebt_make_matchname(const struct ebt_entry_match *m, | |||
1356 | } | 1364 | } |
1357 | 1365 | ||
1358 | static inline int ebt_make_watchername(const struct ebt_entry_watcher *w, | 1366 | static inline int ebt_make_watchername(const struct ebt_entry_watcher *w, |
1359 | const char *base, char __user *ubase) | 1367 | const char *base, char __user *ubase) |
1360 | { | 1368 | { |
1361 | char __user *hlp = ubase + ((char *)w - base); | 1369 | char __user *hlp = ubase + ((char *)w - base); |
1362 | char name[EBT_FUNCTION_MAXNAMELEN] = {}; | 1370 | char name[EBT_FUNCTION_MAXNAMELEN] = {}; |
1363 | 1371 | ||
1364 | strlcpy(name, w->u.watcher->name, sizeof(name)); | 1372 | strlcpy(name, w->u.watcher->name, sizeof(name)); |
1365 | if (copy_to_user(hlp , name, EBT_FUNCTION_MAXNAMELEN)) | 1373 | if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) |
1366 | return -EFAULT; | 1374 | return -EFAULT; |
1367 | return 0; | 1375 | return 0; |
1368 | } | 1376 | } |
1369 | 1377 | ||
1370 | static inline int | 1378 | static inline int ebt_make_names(struct ebt_entry *e, const char *base, |
1371 | ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase) | 1379 | char __user *ubase) |
1372 | { | 1380 | { |
1373 | int ret; | 1381 | int ret; |
1374 | char __user *hlp; | 1382 | char __user *hlp; |
@@ -1394,9 +1402,9 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase) | |||
1394 | } | 1402 | } |
1395 | 1403 | ||
1396 | static int copy_counters_to_user(struct ebt_table *t, | 1404 | static int copy_counters_to_user(struct ebt_table *t, |
1397 | const struct ebt_counter *oldcounters, | 1405 | const struct ebt_counter *oldcounters, |
1398 | void __user *user, unsigned int num_counters, | 1406 | void __user *user, unsigned int num_counters, |
1399 | unsigned int nentries) | 1407 | unsigned int nentries) |
1400 | { | 1408 | { |
1401 | struct ebt_counter *counterstmp; | 1409 | struct ebt_counter *counterstmp; |
1402 | int ret = 0; | 1410 | int ret = 0; |
@@ -1427,7 +1435,7 @@ static int copy_counters_to_user(struct ebt_table *t, | |||
1427 | 1435 | ||
1428 | /* called with ebt_mutex locked */ | 1436 | /* called with ebt_mutex locked */ |
1429 | static int copy_everything_to_user(struct ebt_table *t, void __user *user, | 1437 | static int copy_everything_to_user(struct ebt_table *t, void __user *user, |
1430 | const int *len, int cmd) | 1438 | const int *len, int cmd) |
1431 | { | 1439 | { |
1432 | struct ebt_replace tmp; | 1440 | struct ebt_replace tmp; |
1433 | const struct ebt_counter *oldcounters; | 1441 | const struct ebt_counter *oldcounters; |
@@ -1595,8 +1603,7 @@ static int ebt_compat_entry_padsize(void) | |||
1595 | static int ebt_compat_match_offset(const struct xt_match *match, | 1603 | static int ebt_compat_match_offset(const struct xt_match *match, |
1596 | unsigned int userlen) | 1604 | unsigned int userlen) |
1597 | { | 1605 | { |
1598 | /* | 1606 | /* ebt_among needs special handling. The kernel .matchsize is |
1599 | * ebt_among needs special handling. The kernel .matchsize is | ||
1600 | * set to -1 at registration time; at runtime an EBT_ALIGN()ed | 1607 | * set to -1 at registration time; at runtime an EBT_ALIGN()ed |
1601 | * value is expected. | 1608 | * value is expected. |
1602 | * Example: userspace sends 4500, ebt_among.c wants 4504. | 1609 | * Example: userspace sends 4500, ebt_among.c wants 4504. |
@@ -1966,8 +1973,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
1966 | return off + match_size; | 1973 | return off + match_size; |
1967 | } | 1974 | } |
1968 | 1975 | ||
1969 | /* | 1976 | /* return size of all matches, watchers or target, including necessary |
1970 | * return size of all matches, watchers or target, including necessary | ||
1971 | * alignment and padding. | 1977 | * alignment and padding. |
1972 | */ | 1978 | */ |
1973 | static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, | 1979 | static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, |
@@ -2070,8 +2076,7 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | |||
2070 | if (ret < 0) | 2076 | if (ret < 0) |
2071 | return ret; | 2077 | return ret; |
2072 | buf_start = (char *) entry; | 2078 | buf_start = (char *) entry; |
2073 | /* | 2079 | /* 0: matches offset, always follows ebt_entry. |
2074 | * 0: matches offset, always follows ebt_entry. | ||
2075 | * 1: watchers offset, from ebt_entry structure | 2080 | * 1: watchers offset, from ebt_entry structure |
2076 | * 2: target offset, from ebt_entry structure | 2081 | * 2: target offset, from ebt_entry structure |
2077 | * 3: next ebt_entry offset, from ebt_entry structure | 2082 | * 3: next ebt_entry offset, from ebt_entry structure |
@@ -2115,8 +2120,7 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | |||
2115 | return 0; | 2120 | return 0; |
2116 | } | 2121 | } |
2117 | 2122 | ||
2118 | /* | 2123 | /* repl->entries_size is the size of the ebt_entry blob in userspace. |
2119 | * repl->entries_size is the size of the ebt_entry blob in userspace. | ||
2120 | * It might need more memory when copied to a 64 bit kernel in case | 2124 | * It might need more memory when copied to a 64 bit kernel in case |
2121 | * userspace is 32-bit. So, first task: find out how much memory is needed. | 2125 | * userspace is 32-bit. So, first task: find out how much memory is needed. |
2122 | * | 2126 | * |
@@ -2305,7 +2309,7 @@ static int compat_do_ebt_set_ctl(struct sock *sk, | |||
2305 | break; | 2309 | break; |
2306 | default: | 2310 | default: |
2307 | ret = -EINVAL; | 2311 | ret = -EINVAL; |
2308 | } | 2312 | } |
2309 | return ret; | 2313 | return ret; |
2310 | } | 2314 | } |
2311 | 2315 | ||
@@ -2360,8 +2364,7 @@ static int compat_do_ebt_get_ctl(struct sock *sk, int cmd, | |||
2360 | break; | 2364 | break; |
2361 | case EBT_SO_GET_ENTRIES: | 2365 | case EBT_SO_GET_ENTRIES: |
2362 | case EBT_SO_GET_INIT_ENTRIES: | 2366 | case EBT_SO_GET_INIT_ENTRIES: |
2363 | /* | 2367 | /* try real handler first in case of userland-side padding. |
2364 | * try real handler first in case of userland-side padding. | ||
2365 | * in case we are dealing with an 'ordinary' 32 bit binary | 2368 | * in case we are dealing with an 'ordinary' 32 bit binary |
2366 | * without 64bit compatibility padding, this will fail right | 2369 | * without 64bit compatibility padding, this will fail right |
2367 | * after copy_from_user when the *len argument is validated. | 2370 | * after copy_from_user when the *len argument is validated. |
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index 62f6b1b19589..7fcdd7261d88 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c | |||
@@ -141,7 +141,7 @@ err: | |||
141 | 141 | ||
142 | static void nf_tables_bridge_exit_net(struct net *net) | 142 | static void nf_tables_bridge_exit_net(struct net *net) |
143 | { | 143 | { |
144 | nft_unregister_afinfo(net->nft.bridge); | 144 | nft_unregister_afinfo(net, net->nft.bridge); |
145 | kfree(net->nft.bridge); | 145 | kfree(net->nft.bridge); |
146 | } | 146 | } |
147 | 147 | ||
diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c index a21269b83f16..4b901d9f2e7c 100644 --- a/net/bridge/netfilter/nft_meta_bridge.c +++ b/net/bridge/netfilter/nft_meta_bridge.c | |||
@@ -84,6 +84,7 @@ static const struct nft_expr_ops nft_meta_bridge_set_ops = { | |||
84 | .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), | 84 | .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), |
85 | .eval = nft_meta_set_eval, | 85 | .eval = nft_meta_set_eval, |
86 | .init = nft_meta_set_init, | 86 | .init = nft_meta_set_init, |
87 | .destroy = nft_meta_set_destroy, | ||
87 | .dump = nft_meta_set_dump, | 88 | .dump = nft_meta_set_dump, |
88 | }; | 89 | }; |
89 | 90 | ||
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index cc858919108e..aa209b1066c9 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
@@ -323,7 +323,7 @@ static long caif_stream_data_wait(struct sock *sk, long timeo) | |||
323 | !timeo) | 323 | !timeo) |
324 | break; | 324 | break; |
325 | 325 | ||
326 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 326 | sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
327 | release_sock(sk); | 327 | release_sock(sk); |
328 | timeo = schedule_timeout(timeo); | 328 | timeo = schedule_timeout(timeo); |
329 | lock_sock(sk); | 329 | lock_sock(sk); |
@@ -331,7 +331,7 @@ static long caif_stream_data_wait(struct sock *sk, long timeo) | |||
331 | if (sock_flag(sk, SOCK_DEAD)) | 331 | if (sock_flag(sk, SOCK_DEAD)) |
332 | break; | 332 | break; |
333 | 333 | ||
334 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 334 | sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
335 | } | 335 | } |
336 | 336 | ||
337 | finish_wait(sk_sleep(sk), &wait); | 337 | finish_wait(sk_sleep(sk), &wait); |
diff --git a/net/core/Makefile b/net/core/Makefile index 086b01fbe1bd..0b835de04de3 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
@@ -9,7 +9,7 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o | |||
9 | 9 | ||
10 | obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ | 10 | obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ |
11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ | 11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ |
12 | sock_diag.o dev_ioctl.o tso.o | 12 | sock_diag.o dev_ioctl.o tso.o sock_reuseport.o |
13 | 13 | ||
14 | obj-$(CONFIG_XFRM) += flow.o | 14 | obj-$(CONFIG_XFRM) += flow.o |
15 | obj-y += net-sysfs.o | 15 | obj-y += net-sysfs.o |
diff --git a/net/core/datagram.c b/net/core/datagram.c index 617088aee21d..fa9dc6450b08 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -83,8 +83,8 @@ static int receiver_wake_function(wait_queue_t *wait, unsigned int mode, int syn | |||
83 | /* | 83 | /* |
84 | * Wait for the last received packet to be different from skb | 84 | * Wait for the last received packet to be different from skb |
85 | */ | 85 | */ |
86 | static int wait_for_more_packets(struct sock *sk, int *err, long *timeo_p, | 86 | int __skb_wait_for_more_packets(struct sock *sk, int *err, long *timeo_p, |
87 | const struct sk_buff *skb) | 87 | const struct sk_buff *skb) |
88 | { | 88 | { |
89 | int error; | 89 | int error; |
90 | DEFINE_WAIT_FUNC(wait, receiver_wake_function); | 90 | DEFINE_WAIT_FUNC(wait, receiver_wake_function); |
@@ -130,6 +130,7 @@ out_noerr: | |||
130 | error = 1; | 130 | error = 1; |
131 | goto out; | 131 | goto out; |
132 | } | 132 | } |
133 | EXPORT_SYMBOL(__skb_wait_for_more_packets); | ||
133 | 134 | ||
134 | static struct sk_buff *skb_set_peeked(struct sk_buff *skb) | 135 | static struct sk_buff *skb_set_peeked(struct sk_buff *skb) |
135 | { | 136 | { |
@@ -161,13 +162,15 @@ done: | |||
161 | } | 162 | } |
162 | 163 | ||
163 | /** | 164 | /** |
164 | * __skb_recv_datagram - Receive a datagram skbuff | 165 | * __skb_try_recv_datagram - Receive a datagram skbuff |
165 | * @sk: socket | 166 | * @sk: socket |
166 | * @flags: MSG_ flags | 167 | * @flags: MSG_ flags |
167 | * @peeked: returns non-zero if this packet has been seen before | 168 | * @peeked: returns non-zero if this packet has been seen before |
168 | * @off: an offset in bytes to peek skb from. Returns an offset | 169 | * @off: an offset in bytes to peek skb from. Returns an offset |
169 | * within an skb where data actually starts | 170 | * within an skb where data actually starts |
170 | * @err: error code returned | 171 | * @err: error code returned |
172 | * @last: set to last peeked message to inform the wait function | ||
173 | * what to look for when peeking | ||
171 | * | 174 | * |
172 | * Get a datagram skbuff, understands the peeking, nonblocking wakeups | 175 | * Get a datagram skbuff, understands the peeking, nonblocking wakeups |
173 | * and possible races. This replaces identical code in packet, raw and | 176 | * and possible races. This replaces identical code in packet, raw and |
@@ -175,9 +178,11 @@ done: | |||
175 | * the long standing peek and read race for datagram sockets. If you | 178 | * the long standing peek and read race for datagram sockets. If you |
176 | * alter this routine remember it must be re-entrant. | 179 | * alter this routine remember it must be re-entrant. |
177 | * | 180 | * |
178 | * This function will lock the socket if a skb is returned, so the caller | 181 | * This function will lock the socket if a skb is returned, so |
179 | * needs to unlock the socket in that case (usually by calling | 182 | * the caller needs to unlock the socket in that case (usually by |
180 | * skb_free_datagram) | 183 | * calling skb_free_datagram). Returns NULL with *err set to |
184 | * -EAGAIN if no data was available or to some other value if an | ||
185 | * error was detected. | ||
181 | * | 186 | * |
182 | * * It does not lock socket since today. This function is | 187 | * * It does not lock socket since today. This function is |
183 | * * free of race conditions. This measure should/can improve | 188 | * * free of race conditions. This measure should/can improve |
@@ -191,13 +196,13 @@ done: | |||
191 | * quite explicitly by POSIX 1003.1g, don't change them without having | 196 | * quite explicitly by POSIX 1003.1g, don't change them without having |
192 | * the standard around please. | 197 | * the standard around please. |
193 | */ | 198 | */ |
194 | struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | 199 | struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags, |
195 | int *peeked, int *off, int *err) | 200 | int *peeked, int *off, int *err, |
201 | struct sk_buff **last) | ||
196 | { | 202 | { |
197 | struct sk_buff_head *queue = &sk->sk_receive_queue; | 203 | struct sk_buff_head *queue = &sk->sk_receive_queue; |
198 | struct sk_buff *skb, *last; | 204 | struct sk_buff *skb; |
199 | unsigned long cpu_flags; | 205 | unsigned long cpu_flags; |
200 | long timeo; | ||
201 | /* | 206 | /* |
202 | * Caller is allowed not to check sk->sk_err before skb_recv_datagram() | 207 | * Caller is allowed not to check sk->sk_err before skb_recv_datagram() |
203 | */ | 208 | */ |
@@ -206,8 +211,6 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | |||
206 | if (error) | 211 | if (error) |
207 | goto no_packet; | 212 | goto no_packet; |
208 | 213 | ||
209 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | ||
210 | |||
211 | do { | 214 | do { |
212 | /* Again only user level code calls this function, so nothing | 215 | /* Again only user level code calls this function, so nothing |
213 | * interrupt level will suddenly eat the receive_queue. | 216 | * interrupt level will suddenly eat the receive_queue. |
@@ -217,10 +220,10 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | |||
217 | */ | 220 | */ |
218 | int _off = *off; | 221 | int _off = *off; |
219 | 222 | ||
220 | last = (struct sk_buff *)queue; | 223 | *last = (struct sk_buff *)queue; |
221 | spin_lock_irqsave(&queue->lock, cpu_flags); | 224 | spin_lock_irqsave(&queue->lock, cpu_flags); |
222 | skb_queue_walk(queue, skb) { | 225 | skb_queue_walk(queue, skb) { |
223 | last = skb; | 226 | *last = skb; |
224 | *peeked = skb->peeked; | 227 | *peeked = skb->peeked; |
225 | if (flags & MSG_PEEK) { | 228 | if (flags & MSG_PEEK) { |
226 | if (_off >= skb->len && (skb->len || _off || | 229 | if (_off >= skb->len && (skb->len || _off || |
@@ -231,8 +234,11 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | |||
231 | 234 | ||
232 | skb = skb_set_peeked(skb); | 235 | skb = skb_set_peeked(skb); |
233 | error = PTR_ERR(skb); | 236 | error = PTR_ERR(skb); |
234 | if (IS_ERR(skb)) | 237 | if (IS_ERR(skb)) { |
235 | goto unlock_err; | 238 | spin_unlock_irqrestore(&queue->lock, |
239 | cpu_flags); | ||
240 | goto no_packet; | ||
241 | } | ||
236 | 242 | ||
237 | atomic_inc(&skb->users); | 243 | atomic_inc(&skb->users); |
238 | } else | 244 | } else |
@@ -242,25 +248,38 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, | |||
242 | *off = _off; | 248 | *off = _off; |
243 | return skb; | 249 | return skb; |
244 | } | 250 | } |
251 | |||
245 | spin_unlock_irqrestore(&queue->lock, cpu_flags); | 252 | spin_unlock_irqrestore(&queue->lock, cpu_flags); |
253 | } while (sk_can_busy_loop(sk) && | ||
254 | sk_busy_loop(sk, flags & MSG_DONTWAIT)); | ||
246 | 255 | ||
247 | if (sk_can_busy_loop(sk) && | 256 | error = -EAGAIN; |
248 | sk_busy_loop(sk, flags & MSG_DONTWAIT)) | ||
249 | continue; | ||
250 | 257 | ||
251 | /* User doesn't want to wait */ | 258 | no_packet: |
252 | error = -EAGAIN; | 259 | *err = error; |
253 | if (!timeo) | 260 | return NULL; |
254 | goto no_packet; | 261 | } |
262 | EXPORT_SYMBOL(__skb_try_recv_datagram); | ||
255 | 263 | ||
256 | } while (!wait_for_more_packets(sk, err, &timeo, last)); | 264 | struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, |
265 | int *peeked, int *off, int *err) | ||
266 | { | ||
267 | struct sk_buff *skb, *last; | ||
268 | long timeo; | ||
257 | 269 | ||
258 | return NULL; | 270 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
271 | |||
272 | do { | ||
273 | skb = __skb_try_recv_datagram(sk, flags, peeked, off, err, | ||
274 | &last); | ||
275 | if (skb) | ||
276 | return skb; | ||
277 | |||
278 | if (*err != -EAGAIN) | ||
279 | break; | ||
280 | } while (timeo && | ||
281 | !__skb_wait_for_more_packets(sk, err, &timeo, last)); | ||
259 | 282 | ||
260 | unlock_err: | ||
261 | spin_unlock_irqrestore(&queue->lock, cpu_flags); | ||
262 | no_packet: | ||
263 | *err = error; | ||
264 | return NULL; | 283 | return NULL; |
265 | } | 284 | } |
266 | EXPORT_SYMBOL(__skb_recv_datagram); | 285 | EXPORT_SYMBOL(__skb_recv_datagram); |
@@ -785,7 +804,7 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, | |||
785 | if (sock_writeable(sk)) | 804 | if (sock_writeable(sk)) |
786 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | 805 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; |
787 | else | 806 | else |
788 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 807 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
789 | 808 | ||
790 | return mask; | 809 | return mask; |
791 | } | 810 | } |
diff --git a/net/core/dev.c b/net/core/dev.c index ae00b894e675..0ca95d5d7af0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -96,6 +96,7 @@ | |||
96 | #include <linux/skbuff.h> | 96 | #include <linux/skbuff.h> |
97 | #include <net/net_namespace.h> | 97 | #include <net/net_namespace.h> |
98 | #include <net/sock.h> | 98 | #include <net/sock.h> |
99 | #include <net/busy_poll.h> | ||
99 | #include <linux/rtnetlink.h> | 100 | #include <linux/rtnetlink.h> |
100 | #include <linux/stat.h> | 101 | #include <linux/stat.h> |
101 | #include <net/dst.h> | 102 | #include <net/dst.h> |
@@ -137,6 +138,7 @@ | |||
137 | #include <linux/errqueue.h> | 138 | #include <linux/errqueue.h> |
138 | #include <linux/hrtimer.h> | 139 | #include <linux/hrtimer.h> |
139 | #include <linux/netfilter_ingress.h> | 140 | #include <linux/netfilter_ingress.h> |
141 | #include <linux/sctp.h> | ||
140 | 142 | ||
141 | #include "net-sysfs.h" | 143 | #include "net-sysfs.h" |
142 | 144 | ||
@@ -182,8 +184,8 @@ EXPORT_SYMBOL(dev_base_lock); | |||
182 | /* protects napi_hash addition/deletion and napi_gen_id */ | 184 | /* protects napi_hash addition/deletion and napi_gen_id */ |
183 | static DEFINE_SPINLOCK(napi_hash_lock); | 185 | static DEFINE_SPINLOCK(napi_hash_lock); |
184 | 186 | ||
185 | static unsigned int napi_gen_id; | 187 | static unsigned int napi_gen_id = NR_CPUS; |
186 | static DEFINE_HASHTABLE(napi_hash, 8); | 188 | static DEFINE_READ_MOSTLY_HASHTABLE(napi_hash, 8); |
187 | 189 | ||
188 | static seqcount_t devnet_rename_seq; | 190 | static seqcount_t devnet_rename_seq; |
189 | 191 | ||
@@ -1674,6 +1676,22 @@ void net_dec_ingress_queue(void) | |||
1674 | EXPORT_SYMBOL_GPL(net_dec_ingress_queue); | 1676 | EXPORT_SYMBOL_GPL(net_dec_ingress_queue); |
1675 | #endif | 1677 | #endif |
1676 | 1678 | ||
1679 | #ifdef CONFIG_NET_EGRESS | ||
1680 | static struct static_key egress_needed __read_mostly; | ||
1681 | |||
1682 | void net_inc_egress_queue(void) | ||
1683 | { | ||
1684 | static_key_slow_inc(&egress_needed); | ||
1685 | } | ||
1686 | EXPORT_SYMBOL_GPL(net_inc_egress_queue); | ||
1687 | |||
1688 | void net_dec_egress_queue(void) | ||
1689 | { | ||
1690 | static_key_slow_dec(&egress_needed); | ||
1691 | } | ||
1692 | EXPORT_SYMBOL_GPL(net_dec_egress_queue); | ||
1693 | #endif | ||
1694 | |||
1677 | static struct static_key netstamp_needed __read_mostly; | 1695 | static struct static_key netstamp_needed __read_mostly; |
1678 | #ifdef HAVE_JUMP_LABEL | 1696 | #ifdef HAVE_JUMP_LABEL |
1679 | /* We are not allowed to call static_key_slow_dec() from irq context | 1697 | /* We are not allowed to call static_key_slow_dec() from irq context |
@@ -2470,6 +2488,141 @@ out: | |||
2470 | } | 2488 | } |
2471 | EXPORT_SYMBOL(skb_checksum_help); | 2489 | EXPORT_SYMBOL(skb_checksum_help); |
2472 | 2490 | ||
2491 | /* skb_csum_offload_check - Driver helper function to determine if a device | ||
2492 | * with limited checksum offload capabilities is able to offload the checksum | ||
2493 | * for a given packet. | ||
2494 | * | ||
2495 | * Arguments: | ||
2496 | * skb - sk_buff for the packet in question | ||
2497 | * spec - contains the description of what device can offload | ||
2498 | * csum_encapped - returns true if the checksum being offloaded is | ||
2499 | * encpasulated. That is it is checksum for the transport header | ||
2500 | * in the inner headers. | ||
2501 | * checksum_help - when set indicates that helper function should | ||
2502 | * call skb_checksum_help if offload checks fail | ||
2503 | * | ||
2504 | * Returns: | ||
2505 | * true: Packet has passed the checksum checks and should be offloadable to | ||
2506 | * the device (a driver may still need to check for additional | ||
2507 | * restrictions of its device) | ||
2508 | * false: Checksum is not offloadable. If checksum_help was set then | ||
2509 | * skb_checksum_help was called to resolve checksum for non-GSO | ||
2510 | * packets and when IP protocol is not SCTP | ||
2511 | */ | ||
2512 | bool __skb_csum_offload_chk(struct sk_buff *skb, | ||
2513 | const struct skb_csum_offl_spec *spec, | ||
2514 | bool *csum_encapped, | ||
2515 | bool csum_help) | ||
2516 | { | ||
2517 | struct iphdr *iph; | ||
2518 | struct ipv6hdr *ipv6; | ||
2519 | void *nhdr; | ||
2520 | int protocol; | ||
2521 | u8 ip_proto; | ||
2522 | |||
2523 | if (skb->protocol == htons(ETH_P_8021Q) || | ||
2524 | skb->protocol == htons(ETH_P_8021AD)) { | ||
2525 | if (!spec->vlan_okay) | ||
2526 | goto need_help; | ||
2527 | } | ||
2528 | |||
2529 | /* We check whether the checksum refers to a transport layer checksum in | ||
2530 | * the outermost header or an encapsulated transport layer checksum that | ||
2531 | * corresponds to the inner headers of the skb. If the checksum is for | ||
2532 | * something else in the packet we need help. | ||
2533 | */ | ||
2534 | if (skb_checksum_start_offset(skb) == skb_transport_offset(skb)) { | ||
2535 | /* Non-encapsulated checksum */ | ||
2536 | protocol = eproto_to_ipproto(vlan_get_protocol(skb)); | ||
2537 | nhdr = skb_network_header(skb); | ||
2538 | *csum_encapped = false; | ||
2539 | if (spec->no_not_encapped) | ||
2540 | goto need_help; | ||
2541 | } else if (skb->encapsulation && spec->encap_okay && | ||
2542 | skb_checksum_start_offset(skb) == | ||
2543 | skb_inner_transport_offset(skb)) { | ||
2544 | /* Encapsulated checksum */ | ||
2545 | *csum_encapped = true; | ||
2546 | switch (skb->inner_protocol_type) { | ||
2547 | case ENCAP_TYPE_ETHER: | ||
2548 | protocol = eproto_to_ipproto(skb->inner_protocol); | ||
2549 | break; | ||
2550 | case ENCAP_TYPE_IPPROTO: | ||
2551 | protocol = skb->inner_protocol; | ||
2552 | break; | ||
2553 | } | ||
2554 | nhdr = skb_inner_network_header(skb); | ||
2555 | } else { | ||
2556 | goto need_help; | ||
2557 | } | ||
2558 | |||
2559 | switch (protocol) { | ||
2560 | case IPPROTO_IP: | ||
2561 | if (!spec->ipv4_okay) | ||
2562 | goto need_help; | ||
2563 | iph = nhdr; | ||
2564 | ip_proto = iph->protocol; | ||
2565 | if (iph->ihl != 5 && !spec->ip_options_okay) | ||
2566 | goto need_help; | ||
2567 | break; | ||
2568 | case IPPROTO_IPV6: | ||
2569 | if (!spec->ipv6_okay) | ||
2570 | goto need_help; | ||
2571 | if (spec->no_encapped_ipv6 && *csum_encapped) | ||
2572 | goto need_help; | ||
2573 | ipv6 = nhdr; | ||
2574 | nhdr += sizeof(*ipv6); | ||
2575 | ip_proto = ipv6->nexthdr; | ||
2576 | break; | ||
2577 | default: | ||
2578 | goto need_help; | ||
2579 | } | ||
2580 | |||
2581 | ip_proto_again: | ||
2582 | switch (ip_proto) { | ||
2583 | case IPPROTO_TCP: | ||
2584 | if (!spec->tcp_okay || | ||
2585 | skb->csum_offset != offsetof(struct tcphdr, check)) | ||
2586 | goto need_help; | ||
2587 | break; | ||
2588 | case IPPROTO_UDP: | ||
2589 | if (!spec->udp_okay || | ||
2590 | skb->csum_offset != offsetof(struct udphdr, check)) | ||
2591 | goto need_help; | ||
2592 | break; | ||
2593 | case IPPROTO_SCTP: | ||
2594 | if (!spec->sctp_okay || | ||
2595 | skb->csum_offset != offsetof(struct sctphdr, checksum)) | ||
2596 | goto cant_help; | ||
2597 | break; | ||
2598 | case NEXTHDR_HOP: | ||
2599 | case NEXTHDR_ROUTING: | ||
2600 | case NEXTHDR_DEST: { | ||
2601 | u8 *opthdr = nhdr; | ||
2602 | |||
2603 | if (protocol != IPPROTO_IPV6 || !spec->ext_hdrs_okay) | ||
2604 | goto need_help; | ||
2605 | |||
2606 | ip_proto = opthdr[0]; | ||
2607 | nhdr += (opthdr[1] + 1) << 3; | ||
2608 | |||
2609 | goto ip_proto_again; | ||
2610 | } | ||
2611 | default: | ||
2612 | goto need_help; | ||
2613 | } | ||
2614 | |||
2615 | /* Passed the tests for offloading checksum */ | ||
2616 | return true; | ||
2617 | |||
2618 | need_help: | ||
2619 | if (csum_help && !skb_shinfo(skb)->gso_size) | ||
2620 | skb_checksum_help(skb); | ||
2621 | cant_help: | ||
2622 | return false; | ||
2623 | } | ||
2624 | EXPORT_SYMBOL(__skb_csum_offload_chk); | ||
2625 | |||
2473 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | 2626 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) |
2474 | { | 2627 | { |
2475 | __be16 type = skb->protocol; | 2628 | __be16 type = skb->protocol; |
@@ -2644,7 +2797,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, | |||
2644 | 2797 | ||
2645 | if (skb->ip_summed != CHECKSUM_NONE && | 2798 | if (skb->ip_summed != CHECKSUM_NONE && |
2646 | !can_checksum_protocol(features, type)) { | 2799 | !can_checksum_protocol(features, type)) { |
2647 | features &= ~NETIF_F_ALL_CSUM; | 2800 | features &= ~NETIF_F_CSUM_MASK; |
2648 | } else if (illegal_highdma(skb->dev, skb)) { | 2801 | } else if (illegal_highdma(skb->dev, skb)) { |
2649 | features &= ~NETIF_F_SG; | 2802 | features &= ~NETIF_F_SG; |
2650 | } | 2803 | } |
@@ -2791,7 +2944,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device | |||
2791 | else | 2944 | else |
2792 | skb_set_transport_header(skb, | 2945 | skb_set_transport_header(skb, |
2793 | skb_checksum_start_offset(skb)); | 2946 | skb_checksum_start_offset(skb)); |
2794 | if (!(features & NETIF_F_ALL_CSUM) && | 2947 | if (!(features & NETIF_F_CSUM_MASK) && |
2795 | skb_checksum_help(skb)) | 2948 | skb_checksum_help(skb)) |
2796 | goto out_kfree_skb; | 2949 | goto out_kfree_skb; |
2797 | } | 2950 | } |
@@ -2870,7 +3023,6 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, | |||
2870 | bool contended; | 3023 | bool contended; |
2871 | int rc; | 3024 | int rc; |
2872 | 3025 | ||
2873 | qdisc_pkt_len_init(skb); | ||
2874 | qdisc_calculate_pkt_len(skb, q); | 3026 | qdisc_calculate_pkt_len(skb, q); |
2875 | /* | 3027 | /* |
2876 | * Heuristic to force contended enqueues to serialize on a | 3028 | * Heuristic to force contended enqueues to serialize on a |
@@ -2928,7 +3080,8 @@ static void skb_update_prio(struct sk_buff *skb) | |||
2928 | struct netprio_map *map = rcu_dereference_bh(skb->dev->priomap); | 3080 | struct netprio_map *map = rcu_dereference_bh(skb->dev->priomap); |
2929 | 3081 | ||
2930 | if (!skb->priority && skb->sk && map) { | 3082 | if (!skb->priority && skb->sk && map) { |
2931 | unsigned int prioidx = skb->sk->sk_cgrp_prioidx; | 3083 | unsigned int prioidx = |
3084 | sock_cgroup_prioidx(&skb->sk->sk_cgrp_data); | ||
2932 | 3085 | ||
2933 | if (prioidx < map->priomap_len) | 3086 | if (prioidx < map->priomap_len) |
2934 | skb->priority = map->priomap[prioidx]; | 3087 | skb->priority = map->priomap[prioidx]; |
@@ -2962,6 +3115,49 @@ int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
2962 | } | 3115 | } |
2963 | EXPORT_SYMBOL(dev_loopback_xmit); | 3116 | EXPORT_SYMBOL(dev_loopback_xmit); |
2964 | 3117 | ||
3118 | #ifdef CONFIG_NET_EGRESS | ||
3119 | static struct sk_buff * | ||
3120 | sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev) | ||
3121 | { | ||
3122 | struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list); | ||
3123 | struct tcf_result cl_res; | ||
3124 | |||
3125 | if (!cl) | ||
3126 | return skb; | ||
3127 | |||
3128 | /* skb->tc_verd and qdisc_skb_cb(skb)->pkt_len were already set | ||
3129 | * earlier by the caller. | ||
3130 | */ | ||
3131 | qdisc_bstats_cpu_update(cl->q, skb); | ||
3132 | |||
3133 | switch (tc_classify(skb, cl, &cl_res, false)) { | ||
3134 | case TC_ACT_OK: | ||
3135 | case TC_ACT_RECLASSIFY: | ||
3136 | skb->tc_index = TC_H_MIN(cl_res.classid); | ||
3137 | break; | ||
3138 | case TC_ACT_SHOT: | ||
3139 | qdisc_qstats_cpu_drop(cl->q); | ||
3140 | *ret = NET_XMIT_DROP; | ||
3141 | goto drop; | ||
3142 | case TC_ACT_STOLEN: | ||
3143 | case TC_ACT_QUEUED: | ||
3144 | *ret = NET_XMIT_SUCCESS; | ||
3145 | drop: | ||
3146 | kfree_skb(skb); | ||
3147 | return NULL; | ||
3148 | case TC_ACT_REDIRECT: | ||
3149 | /* No need to push/pop skb's mac_header here on egress! */ | ||
3150 | skb_do_redirect(skb); | ||
3151 | *ret = NET_XMIT_SUCCESS; | ||
3152 | return NULL; | ||
3153 | default: | ||
3154 | break; | ||
3155 | } | ||
3156 | |||
3157 | return skb; | ||
3158 | } | ||
3159 | #endif /* CONFIG_NET_EGRESS */ | ||
3160 | |||
2965 | static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) | 3161 | static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) |
2966 | { | 3162 | { |
2967 | #ifdef CONFIG_XPS | 3163 | #ifdef CONFIG_XPS |
@@ -3021,7 +3217,9 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev, | |||
3021 | int queue_index = 0; | 3217 | int queue_index = 0; |
3022 | 3218 | ||
3023 | #ifdef CONFIG_XPS | 3219 | #ifdef CONFIG_XPS |
3024 | if (skb->sender_cpu == 0) | 3220 | u32 sender_cpu = skb->sender_cpu - 1; |
3221 | |||
3222 | if (sender_cpu >= (u32)NR_CPUS) | ||
3025 | skb->sender_cpu = raw_smp_processor_id() + 1; | 3223 | skb->sender_cpu = raw_smp_processor_id() + 1; |
3026 | #endif | 3224 | #endif |
3027 | 3225 | ||
@@ -3086,6 +3284,17 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) | |||
3086 | 3284 | ||
3087 | skb_update_prio(skb); | 3285 | skb_update_prio(skb); |
3088 | 3286 | ||
3287 | qdisc_pkt_len_init(skb); | ||
3288 | #ifdef CONFIG_NET_CLS_ACT | ||
3289 | skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS); | ||
3290 | # ifdef CONFIG_NET_EGRESS | ||
3291 | if (static_key_false(&egress_needed)) { | ||
3292 | skb = sch_handle_egress(skb, &rc, dev); | ||
3293 | if (!skb) | ||
3294 | goto out; | ||
3295 | } | ||
3296 | # endif | ||
3297 | #endif | ||
3089 | /* If device/qdisc don't need skb->dst, release it right now while | 3298 | /* If device/qdisc don't need skb->dst, release it right now while |
3090 | * its hot in this cpu cache. | 3299 | * its hot in this cpu cache. |
3091 | */ | 3300 | */ |
@@ -3107,9 +3316,6 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) | |||
3107 | txq = netdev_pick_tx(dev, skb, accel_priv); | 3316 | txq = netdev_pick_tx(dev, skb, accel_priv); |
3108 | q = rcu_dereference_bh(txq->qdisc); | 3317 | q = rcu_dereference_bh(txq->qdisc); |
3109 | 3318 | ||
3110 | #ifdef CONFIG_NET_CLS_ACT | ||
3111 | skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS); | ||
3112 | #endif | ||
3113 | trace_net_dev_queue(skb); | 3319 | trace_net_dev_queue(skb); |
3114 | if (q->enqueue) { | 3320 | if (q->enqueue) { |
3115 | rc = __dev_xmit_skb(skb, q, dev, txq); | 3321 | rc = __dev_xmit_skb(skb, q, dev, txq); |
@@ -3666,9 +3872,9 @@ int (*br_fdb_test_addr_hook)(struct net_device *dev, | |||
3666 | EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook); | 3872 | EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook); |
3667 | #endif | 3873 | #endif |
3668 | 3874 | ||
3669 | static inline struct sk_buff *handle_ing(struct sk_buff *skb, | 3875 | static inline struct sk_buff * |
3670 | struct packet_type **pt_prev, | 3876 | sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret, |
3671 | int *ret, struct net_device *orig_dev) | 3877 | struct net_device *orig_dev) |
3672 | { | 3878 | { |
3673 | #ifdef CONFIG_NET_CLS_ACT | 3879 | #ifdef CONFIG_NET_CLS_ACT |
3674 | struct tcf_proto *cl = rcu_dereference_bh(skb->dev->ingress_cl_list); | 3880 | struct tcf_proto *cl = rcu_dereference_bh(skb->dev->ingress_cl_list); |
@@ -3862,7 +4068,7 @@ another_round: | |||
3862 | skip_taps: | 4068 | skip_taps: |
3863 | #ifdef CONFIG_NET_INGRESS | 4069 | #ifdef CONFIG_NET_INGRESS |
3864 | if (static_key_false(&ingress_needed)) { | 4070 | if (static_key_false(&ingress_needed)) { |
3865 | skb = handle_ing(skb, &pt_prev, &ret, orig_dev); | 4071 | skb = sch_handle_ingress(skb, &pt_prev, &ret, orig_dev); |
3866 | if (!skb) | 4072 | if (!skb) |
3867 | goto out; | 4073 | goto out; |
3868 | 4074 | ||
@@ -4353,6 +4559,7 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb) | |||
4353 | 4559 | ||
4354 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | 4560 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) |
4355 | { | 4561 | { |
4562 | skb_mark_napi_id(skb, napi); | ||
4356 | trace_napi_gro_receive_entry(skb); | 4563 | trace_napi_gro_receive_entry(skb); |
4357 | 4564 | ||
4358 | skb_gro_reset_offset(skb); | 4565 | skb_gro_reset_offset(skb); |
@@ -4386,7 +4593,10 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi) | |||
4386 | 4593 | ||
4387 | if (!skb) { | 4594 | if (!skb) { |
4388 | skb = napi_alloc_skb(napi, GRO_MAX_HEAD); | 4595 | skb = napi_alloc_skb(napi, GRO_MAX_HEAD); |
4389 | napi->skb = skb; | 4596 | if (skb) { |
4597 | napi->skb = skb; | ||
4598 | skb_mark_napi_id(skb, napi); | ||
4599 | } | ||
4390 | } | 4600 | } |
4391 | return skb; | 4601 | return skb; |
4392 | } | 4602 | } |
@@ -4661,7 +4871,7 @@ void napi_complete_done(struct napi_struct *n, int work_done) | |||
4661 | EXPORT_SYMBOL(napi_complete_done); | 4871 | EXPORT_SYMBOL(napi_complete_done); |
4662 | 4872 | ||
4663 | /* must be called under rcu_read_lock(), as we dont take a reference */ | 4873 | /* must be called under rcu_read_lock(), as we dont take a reference */ |
4664 | struct napi_struct *napi_by_id(unsigned int napi_id) | 4874 | static struct napi_struct *napi_by_id(unsigned int napi_id) |
4665 | { | 4875 | { |
4666 | unsigned int hash = napi_id % HASH_SIZE(napi_hash); | 4876 | unsigned int hash = napi_id % HASH_SIZE(napi_hash); |
4667 | struct napi_struct *napi; | 4877 | struct napi_struct *napi; |
@@ -4672,43 +4882,101 @@ struct napi_struct *napi_by_id(unsigned int napi_id) | |||
4672 | 4882 | ||
4673 | return NULL; | 4883 | return NULL; |
4674 | } | 4884 | } |
4675 | EXPORT_SYMBOL_GPL(napi_by_id); | ||
4676 | 4885 | ||
4677 | void napi_hash_add(struct napi_struct *napi) | 4886 | #if defined(CONFIG_NET_RX_BUSY_POLL) |
4887 | #define BUSY_POLL_BUDGET 8 | ||
4888 | bool sk_busy_loop(struct sock *sk, int nonblock) | ||
4678 | { | 4889 | { |
4679 | if (!test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) { | 4890 | unsigned long end_time = !nonblock ? sk_busy_loop_end_time(sk) : 0; |
4891 | int (*busy_poll)(struct napi_struct *dev); | ||
4892 | struct napi_struct *napi; | ||
4893 | int rc = false; | ||
4680 | 4894 | ||
4681 | spin_lock(&napi_hash_lock); | 4895 | rcu_read_lock(); |
4682 | 4896 | ||
4683 | /* 0 is not a valid id, we also skip an id that is taken | 4897 | napi = napi_by_id(sk->sk_napi_id); |
4684 | * we expect both events to be extremely rare | 4898 | if (!napi) |
4685 | */ | 4899 | goto out; |
4686 | napi->napi_id = 0; | 4900 | |
4687 | while (!napi->napi_id) { | 4901 | /* Note: ndo_busy_poll method is optional in linux-4.5 */ |
4688 | napi->napi_id = ++napi_gen_id; | 4902 | busy_poll = napi->dev->netdev_ops->ndo_busy_poll; |
4689 | if (napi_by_id(napi->napi_id)) | 4903 | |
4690 | napi->napi_id = 0; | 4904 | do { |
4905 | rc = 0; | ||
4906 | local_bh_disable(); | ||
4907 | if (busy_poll) { | ||
4908 | rc = busy_poll(napi); | ||
4909 | } else if (napi_schedule_prep(napi)) { | ||
4910 | void *have = netpoll_poll_lock(napi); | ||
4911 | |||
4912 | if (test_bit(NAPI_STATE_SCHED, &napi->state)) { | ||
4913 | rc = napi->poll(napi, BUSY_POLL_BUDGET); | ||
4914 | trace_napi_poll(napi); | ||
4915 | if (rc == BUSY_POLL_BUDGET) { | ||
4916 | napi_complete_done(napi, rc); | ||
4917 | napi_schedule(napi); | ||
4918 | } | ||
4919 | } | ||
4920 | netpoll_poll_unlock(have); | ||
4691 | } | 4921 | } |
4922 | if (rc > 0) | ||
4923 | NET_ADD_STATS_BH(sock_net(sk), | ||
4924 | LINUX_MIB_BUSYPOLLRXPACKETS, rc); | ||
4925 | local_bh_enable(); | ||
4692 | 4926 | ||
4693 | hlist_add_head_rcu(&napi->napi_hash_node, | 4927 | if (rc == LL_FLUSH_FAILED) |
4694 | &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]); | 4928 | break; /* permanent failure */ |
4695 | 4929 | ||
4696 | spin_unlock(&napi_hash_lock); | 4930 | cpu_relax(); |
4697 | } | 4931 | } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && |
4932 | !need_resched() && !busy_loop_timeout(end_time)); | ||
4933 | |||
4934 | rc = !skb_queue_empty(&sk->sk_receive_queue); | ||
4935 | out: | ||
4936 | rcu_read_unlock(); | ||
4937 | return rc; | ||
4938 | } | ||
4939 | EXPORT_SYMBOL(sk_busy_loop); | ||
4940 | |||
4941 | #endif /* CONFIG_NET_RX_BUSY_POLL */ | ||
4942 | |||
4943 | void napi_hash_add(struct napi_struct *napi) | ||
4944 | { | ||
4945 | if (test_bit(NAPI_STATE_NO_BUSY_POLL, &napi->state) || | ||
4946 | test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) | ||
4947 | return; | ||
4948 | |||
4949 | spin_lock(&napi_hash_lock); | ||
4950 | |||
4951 | /* 0..NR_CPUS+1 range is reserved for sender_cpu use */ | ||
4952 | do { | ||
4953 | if (unlikely(++napi_gen_id < NR_CPUS + 1)) | ||
4954 | napi_gen_id = NR_CPUS + 1; | ||
4955 | } while (napi_by_id(napi_gen_id)); | ||
4956 | napi->napi_id = napi_gen_id; | ||
4957 | |||
4958 | hlist_add_head_rcu(&napi->napi_hash_node, | ||
4959 | &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]); | ||
4960 | |||
4961 | spin_unlock(&napi_hash_lock); | ||
4698 | } | 4962 | } |
4699 | EXPORT_SYMBOL_GPL(napi_hash_add); | 4963 | EXPORT_SYMBOL_GPL(napi_hash_add); |
4700 | 4964 | ||
4701 | /* Warning : caller is responsible to make sure rcu grace period | 4965 | /* Warning : caller is responsible to make sure rcu grace period |
4702 | * is respected before freeing memory containing @napi | 4966 | * is respected before freeing memory containing @napi |
4703 | */ | 4967 | */ |
4704 | void napi_hash_del(struct napi_struct *napi) | 4968 | bool napi_hash_del(struct napi_struct *napi) |
4705 | { | 4969 | { |
4970 | bool rcu_sync_needed = false; | ||
4971 | |||
4706 | spin_lock(&napi_hash_lock); | 4972 | spin_lock(&napi_hash_lock); |
4707 | 4973 | ||
4708 | if (test_and_clear_bit(NAPI_STATE_HASHED, &napi->state)) | 4974 | if (test_and_clear_bit(NAPI_STATE_HASHED, &napi->state)) { |
4975 | rcu_sync_needed = true; | ||
4709 | hlist_del_rcu(&napi->napi_hash_node); | 4976 | hlist_del_rcu(&napi->napi_hash_node); |
4710 | 4977 | } | |
4711 | spin_unlock(&napi_hash_lock); | 4978 | spin_unlock(&napi_hash_lock); |
4979 | return rcu_sync_needed; | ||
4712 | } | 4980 | } |
4713 | EXPORT_SYMBOL_GPL(napi_hash_del); | 4981 | EXPORT_SYMBOL_GPL(napi_hash_del); |
4714 | 4982 | ||
@@ -4744,6 +5012,7 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi, | |||
4744 | napi->poll_owner = -1; | 5012 | napi->poll_owner = -1; |
4745 | #endif | 5013 | #endif |
4746 | set_bit(NAPI_STATE_SCHED, &napi->state); | 5014 | set_bit(NAPI_STATE_SCHED, &napi->state); |
5015 | napi_hash_add(napi); | ||
4747 | } | 5016 | } |
4748 | EXPORT_SYMBOL(netif_napi_add); | 5017 | EXPORT_SYMBOL(netif_napi_add); |
4749 | 5018 | ||
@@ -4763,8 +5032,12 @@ void napi_disable(struct napi_struct *n) | |||
4763 | } | 5032 | } |
4764 | EXPORT_SYMBOL(napi_disable); | 5033 | EXPORT_SYMBOL(napi_disable); |
4765 | 5034 | ||
5035 | /* Must be called in process context */ | ||
4766 | void netif_napi_del(struct napi_struct *napi) | 5036 | void netif_napi_del(struct napi_struct *napi) |
4767 | { | 5037 | { |
5038 | might_sleep(); | ||
5039 | if (napi_hash_del(napi)) | ||
5040 | synchronize_net(); | ||
4768 | list_del_init(&napi->dev_list); | 5041 | list_del_init(&napi->dev_list); |
4769 | napi_free_frags(napi); | 5042 | napi_free_frags(napi); |
4770 | 5043 | ||
@@ -5351,7 +5624,7 @@ static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, | |||
5351 | 5624 | ||
5352 | static int __netdev_upper_dev_link(struct net_device *dev, | 5625 | static int __netdev_upper_dev_link(struct net_device *dev, |
5353 | struct net_device *upper_dev, bool master, | 5626 | struct net_device *upper_dev, bool master, |
5354 | void *private) | 5627 | void *upper_priv, void *upper_info) |
5355 | { | 5628 | { |
5356 | struct netdev_notifier_changeupper_info changeupper_info; | 5629 | struct netdev_notifier_changeupper_info changeupper_info; |
5357 | struct netdev_adjacent *i, *j, *to_i, *to_j; | 5630 | struct netdev_adjacent *i, *j, *to_i, *to_j; |
@@ -5375,6 +5648,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
5375 | changeupper_info.upper_dev = upper_dev; | 5648 | changeupper_info.upper_dev = upper_dev; |
5376 | changeupper_info.master = master; | 5649 | changeupper_info.master = master; |
5377 | changeupper_info.linking = true; | 5650 | changeupper_info.linking = true; |
5651 | changeupper_info.upper_info = upper_info; | ||
5378 | 5652 | ||
5379 | ret = call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev, | 5653 | ret = call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev, |
5380 | &changeupper_info.info); | 5654 | &changeupper_info.info); |
@@ -5382,7 +5656,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
5382 | if (ret) | 5656 | if (ret) |
5383 | return ret; | 5657 | return ret; |
5384 | 5658 | ||
5385 | ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private, | 5659 | ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, upper_priv, |
5386 | master); | 5660 | master); |
5387 | if (ret) | 5661 | if (ret) |
5388 | return ret; | 5662 | return ret; |
@@ -5420,8 +5694,12 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
5420 | goto rollback_lower_mesh; | 5694 | goto rollback_lower_mesh; |
5421 | } | 5695 | } |
5422 | 5696 | ||
5423 | call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, | 5697 | ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, |
5424 | &changeupper_info.info); | 5698 | &changeupper_info.info); |
5699 | ret = notifier_to_errno(ret); | ||
5700 | if (ret) | ||
5701 | goto rollback_lower_mesh; | ||
5702 | |||
5425 | return 0; | 5703 | return 0; |
5426 | 5704 | ||
5427 | rollback_lower_mesh: | 5705 | rollback_lower_mesh: |
@@ -5475,7 +5753,7 @@ rollback_mesh: | |||
5475 | int netdev_upper_dev_link(struct net_device *dev, | 5753 | int netdev_upper_dev_link(struct net_device *dev, |
5476 | struct net_device *upper_dev) | 5754 | struct net_device *upper_dev) |
5477 | { | 5755 | { |
5478 | return __netdev_upper_dev_link(dev, upper_dev, false, NULL); | 5756 | return __netdev_upper_dev_link(dev, upper_dev, false, NULL, NULL); |
5479 | } | 5757 | } |
5480 | EXPORT_SYMBOL(netdev_upper_dev_link); | 5758 | EXPORT_SYMBOL(netdev_upper_dev_link); |
5481 | 5759 | ||
@@ -5483,6 +5761,8 @@ EXPORT_SYMBOL(netdev_upper_dev_link); | |||
5483 | * netdev_master_upper_dev_link - Add a master link to the upper device | 5761 | * netdev_master_upper_dev_link - Add a master link to the upper device |
5484 | * @dev: device | 5762 | * @dev: device |
5485 | * @upper_dev: new upper device | 5763 | * @upper_dev: new upper device |
5764 | * @upper_priv: upper device private | ||
5765 | * @upper_info: upper info to be passed down via notifier | ||
5486 | * | 5766 | * |
5487 | * Adds a link to device which is upper to this one. In this case, only | 5767 | * Adds a link to device which is upper to this one. In this case, only |
5488 | * one master upper device can be linked, although other non-master devices | 5768 | * one master upper device can be linked, although other non-master devices |
@@ -5491,20 +5771,14 @@ EXPORT_SYMBOL(netdev_upper_dev_link); | |||
5491 | * counts are adjusted and the function returns zero. | 5771 | * counts are adjusted and the function returns zero. |
5492 | */ | 5772 | */ |
5493 | int netdev_master_upper_dev_link(struct net_device *dev, | 5773 | int netdev_master_upper_dev_link(struct net_device *dev, |
5494 | struct net_device *upper_dev) | 5774 | struct net_device *upper_dev, |
5775 | void *upper_priv, void *upper_info) | ||
5495 | { | 5776 | { |
5496 | return __netdev_upper_dev_link(dev, upper_dev, true, NULL); | 5777 | return __netdev_upper_dev_link(dev, upper_dev, true, |
5778 | upper_priv, upper_info); | ||
5497 | } | 5779 | } |
5498 | EXPORT_SYMBOL(netdev_master_upper_dev_link); | 5780 | EXPORT_SYMBOL(netdev_master_upper_dev_link); |
5499 | 5781 | ||
5500 | int netdev_master_upper_dev_link_private(struct net_device *dev, | ||
5501 | struct net_device *upper_dev, | ||
5502 | void *private) | ||
5503 | { | ||
5504 | return __netdev_upper_dev_link(dev, upper_dev, true, private); | ||
5505 | } | ||
5506 | EXPORT_SYMBOL(netdev_master_upper_dev_link_private); | ||
5507 | |||
5508 | /** | 5782 | /** |
5509 | * netdev_upper_dev_unlink - Removes a link to upper device | 5783 | * netdev_upper_dev_unlink - Removes a link to upper device |
5510 | * @dev: device | 5784 | * @dev: device |
@@ -5663,7 +5937,7 @@ EXPORT_SYMBOL(netdev_lower_dev_get_private); | |||
5663 | 5937 | ||
5664 | 5938 | ||
5665 | int dev_get_nest_level(struct net_device *dev, | 5939 | int dev_get_nest_level(struct net_device *dev, |
5666 | bool (*type_check)(struct net_device *dev)) | 5940 | bool (*type_check)(const struct net_device *dev)) |
5667 | { | 5941 | { |
5668 | struct net_device *lower = NULL; | 5942 | struct net_device *lower = NULL; |
5669 | struct list_head *iter; | 5943 | struct list_head *iter; |
@@ -5685,6 +5959,26 @@ int dev_get_nest_level(struct net_device *dev, | |||
5685 | } | 5959 | } |
5686 | EXPORT_SYMBOL(dev_get_nest_level); | 5960 | EXPORT_SYMBOL(dev_get_nest_level); |
5687 | 5961 | ||
5962 | /** | ||
5963 | * netdev_lower_change - Dispatch event about lower device state change | ||
5964 | * @lower_dev: device | ||
5965 | * @lower_state_info: state to dispatch | ||
5966 | * | ||
5967 | * Send NETDEV_CHANGELOWERSTATE to netdev notifiers with info. | ||
5968 | * The caller must hold the RTNL lock. | ||
5969 | */ | ||
5970 | void netdev_lower_state_changed(struct net_device *lower_dev, | ||
5971 | void *lower_state_info) | ||
5972 | { | ||
5973 | struct netdev_notifier_changelowerstate_info changelowerstate_info; | ||
5974 | |||
5975 | ASSERT_RTNL(); | ||
5976 | changelowerstate_info.lower_state_info = lower_state_info; | ||
5977 | call_netdevice_notifiers_info(NETDEV_CHANGELOWERSTATE, lower_dev, | ||
5978 | &changelowerstate_info.info); | ||
5979 | } | ||
5980 | EXPORT_SYMBOL(netdev_lower_state_changed); | ||
5981 | |||
5688 | static void dev_change_rx_flags(struct net_device *dev, int flags) | 5982 | static void dev_change_rx_flags(struct net_device *dev, int flags) |
5689 | { | 5983 | { |
5690 | const struct net_device_ops *ops = dev->netdev_ops; | 5984 | const struct net_device_ops *ops = dev->netdev_ops; |
@@ -6375,9 +6669,9 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, | |||
6375 | /* UFO needs SG and checksumming */ | 6669 | /* UFO needs SG and checksumming */ |
6376 | if (features & NETIF_F_UFO) { | 6670 | if (features & NETIF_F_UFO) { |
6377 | /* maybe split UFO into V4 and V6? */ | 6671 | /* maybe split UFO into V4 and V6? */ |
6378 | if (!((features & NETIF_F_GEN_CSUM) || | 6672 | if (!(features & NETIF_F_HW_CSUM) && |
6379 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)) | 6673 | ((features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) != |
6380 | == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | 6674 | (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))) { |
6381 | netdev_dbg(dev, | 6675 | netdev_dbg(dev, |
6382 | "Dropping NETIF_F_UFO since no checksum offload features.\n"); | 6676 | "Dropping NETIF_F_UFO since no checksum offload features.\n"); |
6383 | features &= ~NETIF_F_UFO; | 6677 | features &= ~NETIF_F_UFO; |
@@ -7164,11 +7458,13 @@ EXPORT_SYMBOL(alloc_netdev_mqs); | |||
7164 | * This function does the last stage of destroying an allocated device | 7458 | * This function does the last stage of destroying an allocated device |
7165 | * interface. The reference to the device object is released. | 7459 | * interface. The reference to the device object is released. |
7166 | * If this is the last reference then it will be freed. | 7460 | * If this is the last reference then it will be freed. |
7461 | * Must be called in process context. | ||
7167 | */ | 7462 | */ |
7168 | void free_netdev(struct net_device *dev) | 7463 | void free_netdev(struct net_device *dev) |
7169 | { | 7464 | { |
7170 | struct napi_struct *p, *n; | 7465 | struct napi_struct *p, *n; |
7171 | 7466 | ||
7467 | might_sleep(); | ||
7172 | netif_free_tx_queues(dev); | 7468 | netif_free_tx_queues(dev); |
7173 | #ifdef CONFIG_SYSFS | 7469 | #ifdef CONFIG_SYSFS |
7174 | kvfree(dev->_rx); | 7470 | kvfree(dev->_rx); |
@@ -7477,16 +7773,16 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
7477 | netdev_features_t netdev_increment_features(netdev_features_t all, | 7773 | netdev_features_t netdev_increment_features(netdev_features_t all, |
7478 | netdev_features_t one, netdev_features_t mask) | 7774 | netdev_features_t one, netdev_features_t mask) |
7479 | { | 7775 | { |
7480 | if (mask & NETIF_F_GEN_CSUM) | 7776 | if (mask & NETIF_F_HW_CSUM) |
7481 | mask |= NETIF_F_ALL_CSUM; | 7777 | mask |= NETIF_F_CSUM_MASK; |
7482 | mask |= NETIF_F_VLAN_CHALLENGED; | 7778 | mask |= NETIF_F_VLAN_CHALLENGED; |
7483 | 7779 | ||
7484 | all |= one & (NETIF_F_ONE_FOR_ALL|NETIF_F_ALL_CSUM) & mask; | 7780 | all |= one & (NETIF_F_ONE_FOR_ALL | NETIF_F_CSUM_MASK) & mask; |
7485 | all &= one | ~NETIF_F_ALL_FOR_ALL; | 7781 | all &= one | ~NETIF_F_ALL_FOR_ALL; |
7486 | 7782 | ||
7487 | /* If one device supports hw checksumming, set for all. */ | 7783 | /* If one device supports hw checksumming, set for all. */ |
7488 | if (all & NETIF_F_GEN_CSUM) | 7784 | if (all & NETIF_F_HW_CSUM) |
7489 | all &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM); | 7785 | all &= ~(NETIF_F_CSUM_MASK & ~NETIF_F_HW_CSUM); |
7490 | 7786 | ||
7491 | return all; | 7787 | return all; |
7492 | } | 7788 | } |
diff --git a/net/core/dst.c b/net/core/dst.c index e6dc77252fe9..a1656e3b8d72 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -301,12 +301,13 @@ void dst_release(struct dst_entry *dst) | |||
301 | { | 301 | { |
302 | if (dst) { | 302 | if (dst) { |
303 | int newrefcnt; | 303 | int newrefcnt; |
304 | unsigned short nocache = dst->flags & DST_NOCACHE; | ||
304 | 305 | ||
305 | newrefcnt = atomic_dec_return(&dst->__refcnt); | 306 | newrefcnt = atomic_dec_return(&dst->__refcnt); |
306 | if (unlikely(newrefcnt < 0)) | 307 | if (unlikely(newrefcnt < 0)) |
307 | net_warn_ratelimited("%s: dst:%p refcnt:%d\n", | 308 | net_warn_ratelimited("%s: dst:%p refcnt:%d\n", |
308 | __func__, dst, newrefcnt); | 309 | __func__, dst, newrefcnt); |
309 | if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE)) | 310 | if (!newrefcnt && unlikely(nocache)) |
310 | call_rcu(&dst->rcu_head, dst_destroy_rcu); | 311 | call_rcu(&dst->rcu_head, dst_destroy_rcu); |
311 | } | 312 | } |
312 | } | 313 | } |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 29edf74846fc..daf04709dd3c 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -87,7 +87,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] | |||
87 | [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation", | 87 | [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation", |
88 | 88 | ||
89 | [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", | 89 | [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", |
90 | [NETIF_F_SCTP_CSUM_BIT] = "tx-checksum-sctp", | 90 | [NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp", |
91 | [NETIF_F_FCOE_MTU_BIT] = "fcoe-mtu", | 91 | [NETIF_F_FCOE_MTU_BIT] = "fcoe-mtu", |
92 | [NETIF_F_NTUPLE_BIT] = "rx-ntuple-filter", | 92 | [NETIF_F_NTUPLE_BIT] = "rx-ntuple-filter", |
93 | [NETIF_F_RXHASH_BIT] = "rx-hashing", | 93 | [NETIF_F_RXHASH_BIT] = "rx-hashing", |
@@ -191,6 +191,23 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) | |||
191 | return ret; | 191 | return ret; |
192 | } | 192 | } |
193 | 193 | ||
194 | static int phy_get_sset_count(struct phy_device *phydev) | ||
195 | { | ||
196 | int ret; | ||
197 | |||
198 | if (phydev->drv->get_sset_count && | ||
199 | phydev->drv->get_strings && | ||
200 | phydev->drv->get_stats) { | ||
201 | mutex_lock(&phydev->lock); | ||
202 | ret = phydev->drv->get_sset_count(phydev); | ||
203 | mutex_unlock(&phydev->lock); | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | return -EOPNOTSUPP; | ||
209 | } | ||
210 | |||
194 | static int __ethtool_get_sset_count(struct net_device *dev, int sset) | 211 | static int __ethtool_get_sset_count(struct net_device *dev, int sset) |
195 | { | 212 | { |
196 | const struct ethtool_ops *ops = dev->ethtool_ops; | 213 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -204,6 +221,13 @@ static int __ethtool_get_sset_count(struct net_device *dev, int sset) | |||
204 | if (sset == ETH_SS_TUNABLES) | 221 | if (sset == ETH_SS_TUNABLES) |
205 | return ARRAY_SIZE(tunable_strings); | 222 | return ARRAY_SIZE(tunable_strings); |
206 | 223 | ||
224 | if (sset == ETH_SS_PHY_STATS) { | ||
225 | if (dev->phydev) | ||
226 | return phy_get_sset_count(dev->phydev); | ||
227 | else | ||
228 | return -EOPNOTSUPP; | ||
229 | } | ||
230 | |||
207 | if (ops->get_sset_count && ops->get_strings) | 231 | if (ops->get_sset_count && ops->get_strings) |
208 | return ops->get_sset_count(dev, sset); | 232 | return ops->get_sset_count(dev, sset); |
209 | else | 233 | else |
@@ -223,7 +247,17 @@ static void __ethtool_get_strings(struct net_device *dev, | |||
223 | sizeof(rss_hash_func_strings)); | 247 | sizeof(rss_hash_func_strings)); |
224 | else if (stringset == ETH_SS_TUNABLES) | 248 | else if (stringset == ETH_SS_TUNABLES) |
225 | memcpy(data, tunable_strings, sizeof(tunable_strings)); | 249 | memcpy(data, tunable_strings, sizeof(tunable_strings)); |
226 | else | 250 | else if (stringset == ETH_SS_PHY_STATS) { |
251 | struct phy_device *phydev = dev->phydev; | ||
252 | |||
253 | if (phydev) { | ||
254 | mutex_lock(&phydev->lock); | ||
255 | phydev->drv->get_strings(phydev, data); | ||
256 | mutex_unlock(&phydev->lock); | ||
257 | } else { | ||
258 | return; | ||
259 | } | ||
260 | } else | ||
227 | /* ops->get_strings is valid because checked earlier */ | 261 | /* ops->get_strings is valid because checked earlier */ |
228 | ops->get_strings(dev, stringset, data); | 262 | ops->get_strings(dev, stringset, data); |
229 | } | 263 | } |
@@ -235,7 +269,7 @@ static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd) | |||
235 | switch (eth_cmd) { | 269 | switch (eth_cmd) { |
236 | case ETHTOOL_GTXCSUM: | 270 | case ETHTOOL_GTXCSUM: |
237 | case ETHTOOL_STXCSUM: | 271 | case ETHTOOL_STXCSUM: |
238 | return NETIF_F_ALL_CSUM | NETIF_F_SCTP_CSUM; | 272 | return NETIF_F_CSUM_MASK | NETIF_F_SCTP_CRC; |
239 | case ETHTOOL_GRXCSUM: | 273 | case ETHTOOL_GRXCSUM: |
240 | case ETHTOOL_SRXCSUM: | 274 | case ETHTOOL_SRXCSUM: |
241 | return NETIF_F_RXCSUM; | 275 | return NETIF_F_RXCSUM; |
@@ -1401,6 +1435,47 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) | |||
1401 | return ret; | 1435 | return ret; |
1402 | } | 1436 | } |
1403 | 1437 | ||
1438 | static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) | ||
1439 | { | ||
1440 | struct ethtool_stats stats; | ||
1441 | struct phy_device *phydev = dev->phydev; | ||
1442 | u64 *data; | ||
1443 | int ret, n_stats; | ||
1444 | |||
1445 | if (!phydev) | ||
1446 | return -EOPNOTSUPP; | ||
1447 | |||
1448 | n_stats = phy_get_sset_count(phydev); | ||
1449 | |||
1450 | if (n_stats < 0) | ||
1451 | return n_stats; | ||
1452 | WARN_ON(n_stats == 0); | ||
1453 | |||
1454 | if (copy_from_user(&stats, useraddr, sizeof(stats))) | ||
1455 | return -EFAULT; | ||
1456 | |||
1457 | stats.n_stats = n_stats; | ||
1458 | data = kmalloc_array(n_stats, sizeof(u64), GFP_USER); | ||
1459 | if (!data) | ||
1460 | return -ENOMEM; | ||
1461 | |||
1462 | mutex_lock(&phydev->lock); | ||
1463 | phydev->drv->get_stats(phydev, &stats, data); | ||
1464 | mutex_unlock(&phydev->lock); | ||
1465 | |||
1466 | ret = -EFAULT; | ||
1467 | if (copy_to_user(useraddr, &stats, sizeof(stats))) | ||
1468 | goto out; | ||
1469 | useraddr += sizeof(stats); | ||
1470 | if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) | ||
1471 | goto out; | ||
1472 | ret = 0; | ||
1473 | |||
1474 | out: | ||
1475 | kfree(data); | ||
1476 | return ret; | ||
1477 | } | ||
1478 | |||
1404 | static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr) | 1479 | static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr) |
1405 | { | 1480 | { |
1406 | struct ethtool_perm_addr epaddr; | 1481 | struct ethtool_perm_addr epaddr; |
@@ -1779,6 +1854,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1779 | case ETHTOOL_GSSET_INFO: | 1854 | case ETHTOOL_GSSET_INFO: |
1780 | case ETHTOOL_GSTRINGS: | 1855 | case ETHTOOL_GSTRINGS: |
1781 | case ETHTOOL_GSTATS: | 1856 | case ETHTOOL_GSTATS: |
1857 | case ETHTOOL_GPHYSTATS: | ||
1782 | case ETHTOOL_GTSO: | 1858 | case ETHTOOL_GTSO: |
1783 | case ETHTOOL_GPERMADDR: | 1859 | case ETHTOOL_GPERMADDR: |
1784 | case ETHTOOL_GUFO: | 1860 | case ETHTOOL_GUFO: |
@@ -1991,6 +2067,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1991 | case ETHTOOL_STUNABLE: | 2067 | case ETHTOOL_STUNABLE: |
1992 | rc = ethtool_set_tunable(dev, useraddr); | 2068 | rc = ethtool_set_tunable(dev, useraddr); |
1993 | break; | 2069 | break; |
2070 | case ETHTOOL_GPHYSTATS: | ||
2071 | rc = ethtool_get_phy_stats(dev, useraddr); | ||
2072 | break; | ||
1994 | default: | 2073 | default: |
1995 | rc = -EOPNOTSUPP; | 2074 | rc = -EOPNOTSUPP; |
1996 | } | 2075 | } |
diff --git a/net/core/filter.c b/net/core/filter.c index 672eefbfbe99..94d26201080d 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <net/cls_cgroup.h> | 50 | #include <net/cls_cgroup.h> |
51 | #include <net/dst_metadata.h> | 51 | #include <net/dst_metadata.h> |
52 | #include <net/dst.h> | 52 | #include <net/dst.h> |
53 | #include <net/sock_reuseport.h> | ||
53 | 54 | ||
54 | /** | 55 | /** |
55 | * sk_filter - run a packet through a socket filter | 56 | * sk_filter - run a packet through a socket filter |
@@ -348,12 +349,6 @@ static bool convert_bpf_extensions(struct sock_filter *fp, | |||
348 | * jump offsets, 2nd pass remapping: | 349 | * jump offsets, 2nd pass remapping: |
349 | * new_prog = kmalloc(sizeof(struct bpf_insn) * new_len); | 350 | * new_prog = kmalloc(sizeof(struct bpf_insn) * new_len); |
350 | * bpf_convert_filter(old_prog, old_len, new_prog, &new_len); | 351 | * bpf_convert_filter(old_prog, old_len, new_prog, &new_len); |
351 | * | ||
352 | * User BPF's register A is mapped to our BPF register 6, user BPF | ||
353 | * register X is mapped to BPF register 7; frame pointer is always | ||
354 | * register 10; Context 'void *ctx' is stored in register 1, that is, | ||
355 | * for socket filters: ctx == 'struct sk_buff *', for seccomp: | ||
356 | * ctx == 'struct seccomp_data *'. | ||
357 | */ | 352 | */ |
358 | static int bpf_convert_filter(struct sock_filter *prog, int len, | 353 | static int bpf_convert_filter(struct sock_filter *prog, int len, |
359 | struct bpf_insn *new_prog, int *new_len) | 354 | struct bpf_insn *new_prog, int *new_len) |
@@ -381,9 +376,22 @@ do_pass: | |||
381 | new_insn = new_prog; | 376 | new_insn = new_prog; |
382 | fp = prog; | 377 | fp = prog; |
383 | 378 | ||
384 | if (new_insn) | 379 | /* Classic BPF related prologue emission. */ |
385 | *new_insn = BPF_MOV64_REG(BPF_REG_CTX, BPF_REG_ARG1); | 380 | if (new_insn) { |
386 | new_insn++; | 381 | /* Classic BPF expects A and X to be reset first. These need |
382 | * to be guaranteed to be the first two instructions. | ||
383 | */ | ||
384 | *new_insn++ = BPF_ALU64_REG(BPF_XOR, BPF_REG_A, BPF_REG_A); | ||
385 | *new_insn++ = BPF_ALU64_REG(BPF_XOR, BPF_REG_X, BPF_REG_X); | ||
386 | |||
387 | /* All programs must keep CTX in callee saved BPF_REG_CTX. | ||
388 | * In eBPF case it's done by the compiler, here we need to | ||
389 | * do this ourself. Initial CTX is present in BPF_REG_ARG1. | ||
390 | */ | ||
391 | *new_insn++ = BPF_MOV64_REG(BPF_REG_CTX, BPF_REG_ARG1); | ||
392 | } else { | ||
393 | new_insn += 3; | ||
394 | } | ||
387 | 395 | ||
388 | for (i = 0; i < len; fp++, i++) { | 396 | for (i = 0; i < len; fp++, i++) { |
389 | struct bpf_insn tmp_insns[6] = { }; | 397 | struct bpf_insn tmp_insns[6] = { }; |
@@ -777,6 +785,11 @@ static int bpf_check_classic(const struct sock_filter *filter, | |||
777 | if (ftest->k == 0) | 785 | if (ftest->k == 0) |
778 | return -EINVAL; | 786 | return -EINVAL; |
779 | break; | 787 | break; |
788 | case BPF_ALU | BPF_LSH | BPF_K: | ||
789 | case BPF_ALU | BPF_RSH | BPF_K: | ||
790 | if (ftest->k >= 32) | ||
791 | return -EINVAL; | ||
792 | break; | ||
780 | case BPF_LD | BPF_MEM: | 793 | case BPF_LD | BPF_MEM: |
781 | case BPF_LDX | BPF_MEM: | 794 | case BPF_LDX | BPF_MEM: |
782 | case BPF_ST: | 795 | case BPF_ST: |
@@ -1160,17 +1173,32 @@ static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk) | |||
1160 | return 0; | 1173 | return 0; |
1161 | } | 1174 | } |
1162 | 1175 | ||
1163 | /** | 1176 | static int __reuseport_attach_prog(struct bpf_prog *prog, struct sock *sk) |
1164 | * sk_attach_filter - attach a socket filter | 1177 | { |
1165 | * @fprog: the filter program | 1178 | struct bpf_prog *old_prog; |
1166 | * @sk: the socket to use | 1179 | int err; |
1167 | * | 1180 | |
1168 | * Attach the user's filter code. We first run some sanity checks on | 1181 | if (bpf_prog_size(prog->len) > sysctl_optmem_max) |
1169 | * it to make sure it does not explode on us later. If an error | 1182 | return -ENOMEM; |
1170 | * occurs or there is insufficient memory for the filter a negative | 1183 | |
1171 | * errno code is returned. On success the return is zero. | 1184 | if (sk_unhashed(sk)) { |
1172 | */ | 1185 | err = reuseport_alloc(sk); |
1173 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | 1186 | if (err) |
1187 | return err; | ||
1188 | } else if (!rcu_access_pointer(sk->sk_reuseport_cb)) { | ||
1189 | /* The socket wasn't bound with SO_REUSEPORT */ | ||
1190 | return -EINVAL; | ||
1191 | } | ||
1192 | |||
1193 | old_prog = reuseport_attach_prog(sk, prog); | ||
1194 | if (old_prog) | ||
1195 | bpf_prog_destroy(old_prog); | ||
1196 | |||
1197 | return 0; | ||
1198 | } | ||
1199 | |||
1200 | static | ||
1201 | struct bpf_prog *__get_filter(struct sock_fprog *fprog, struct sock *sk) | ||
1174 | { | 1202 | { |
1175 | unsigned int fsize = bpf_classic_proglen(fprog); | 1203 | unsigned int fsize = bpf_classic_proglen(fprog); |
1176 | unsigned int bpf_fsize = bpf_prog_size(fprog->len); | 1204 | unsigned int bpf_fsize = bpf_prog_size(fprog->len); |
@@ -1178,19 +1206,19 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
1178 | int err; | 1206 | int err; |
1179 | 1207 | ||
1180 | if (sock_flag(sk, SOCK_FILTER_LOCKED)) | 1208 | if (sock_flag(sk, SOCK_FILTER_LOCKED)) |
1181 | return -EPERM; | 1209 | return ERR_PTR(-EPERM); |
1182 | 1210 | ||
1183 | /* Make sure new filter is there and in the right amounts. */ | 1211 | /* Make sure new filter is there and in the right amounts. */ |
1184 | if (fprog->filter == NULL) | 1212 | if (fprog->filter == NULL) |
1185 | return -EINVAL; | 1213 | return ERR_PTR(-EINVAL); |
1186 | 1214 | ||
1187 | prog = bpf_prog_alloc(bpf_fsize, 0); | 1215 | prog = bpf_prog_alloc(bpf_fsize, 0); |
1188 | if (!prog) | 1216 | if (!prog) |
1189 | return -ENOMEM; | 1217 | return ERR_PTR(-ENOMEM); |
1190 | 1218 | ||
1191 | if (copy_from_user(prog->insns, fprog->filter, fsize)) { | 1219 | if (copy_from_user(prog->insns, fprog->filter, fsize)) { |
1192 | __bpf_prog_free(prog); | 1220 | __bpf_prog_free(prog); |
1193 | return -EFAULT; | 1221 | return ERR_PTR(-EFAULT); |
1194 | } | 1222 | } |
1195 | 1223 | ||
1196 | prog->len = fprog->len; | 1224 | prog->len = fprog->len; |
@@ -1198,13 +1226,30 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
1198 | err = bpf_prog_store_orig_filter(prog, fprog); | 1226 | err = bpf_prog_store_orig_filter(prog, fprog); |
1199 | if (err) { | 1227 | if (err) { |
1200 | __bpf_prog_free(prog); | 1228 | __bpf_prog_free(prog); |
1201 | return -ENOMEM; | 1229 | return ERR_PTR(-ENOMEM); |
1202 | } | 1230 | } |
1203 | 1231 | ||
1204 | /* bpf_prepare_filter() already takes care of freeing | 1232 | /* bpf_prepare_filter() already takes care of freeing |
1205 | * memory in case something goes wrong. | 1233 | * memory in case something goes wrong. |
1206 | */ | 1234 | */ |
1207 | prog = bpf_prepare_filter(prog, NULL); | 1235 | return bpf_prepare_filter(prog, NULL); |
1236 | } | ||
1237 | |||
1238 | /** | ||
1239 | * sk_attach_filter - attach a socket filter | ||
1240 | * @fprog: the filter program | ||
1241 | * @sk: the socket to use | ||
1242 | * | ||
1243 | * Attach the user's filter code. We first run some sanity checks on | ||
1244 | * it to make sure it does not explode on us later. If an error | ||
1245 | * occurs or there is insufficient memory for the filter a negative | ||
1246 | * errno code is returned. On success the return is zero. | ||
1247 | */ | ||
1248 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | ||
1249 | { | ||
1250 | struct bpf_prog *prog = __get_filter(fprog, sk); | ||
1251 | int err; | ||
1252 | |||
1208 | if (IS_ERR(prog)) | 1253 | if (IS_ERR(prog)) |
1209 | return PTR_ERR(prog); | 1254 | return PTR_ERR(prog); |
1210 | 1255 | ||
@@ -1218,23 +1263,50 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
1218 | } | 1263 | } |
1219 | EXPORT_SYMBOL_GPL(sk_attach_filter); | 1264 | EXPORT_SYMBOL_GPL(sk_attach_filter); |
1220 | 1265 | ||
1221 | int sk_attach_bpf(u32 ufd, struct sock *sk) | 1266 | int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk) |
1222 | { | 1267 | { |
1223 | struct bpf_prog *prog; | 1268 | struct bpf_prog *prog = __get_filter(fprog, sk); |
1224 | int err; | 1269 | int err; |
1225 | 1270 | ||
1271 | if (IS_ERR(prog)) | ||
1272 | return PTR_ERR(prog); | ||
1273 | |||
1274 | err = __reuseport_attach_prog(prog, sk); | ||
1275 | if (err < 0) { | ||
1276 | __bpf_prog_release(prog); | ||
1277 | return err; | ||
1278 | } | ||
1279 | |||
1280 | return 0; | ||
1281 | } | ||
1282 | |||
1283 | static struct bpf_prog *__get_bpf(u32 ufd, struct sock *sk) | ||
1284 | { | ||
1285 | struct bpf_prog *prog; | ||
1286 | |||
1226 | if (sock_flag(sk, SOCK_FILTER_LOCKED)) | 1287 | if (sock_flag(sk, SOCK_FILTER_LOCKED)) |
1227 | return -EPERM; | 1288 | return ERR_PTR(-EPERM); |
1228 | 1289 | ||
1229 | prog = bpf_prog_get(ufd); | 1290 | prog = bpf_prog_get(ufd); |
1230 | if (IS_ERR(prog)) | 1291 | if (IS_ERR(prog)) |
1231 | return PTR_ERR(prog); | 1292 | return prog; |
1232 | 1293 | ||
1233 | if (prog->type != BPF_PROG_TYPE_SOCKET_FILTER) { | 1294 | if (prog->type != BPF_PROG_TYPE_SOCKET_FILTER) { |
1234 | bpf_prog_put(prog); | 1295 | bpf_prog_put(prog); |
1235 | return -EINVAL; | 1296 | return ERR_PTR(-EINVAL); |
1236 | } | 1297 | } |
1237 | 1298 | ||
1299 | return prog; | ||
1300 | } | ||
1301 | |||
1302 | int sk_attach_bpf(u32 ufd, struct sock *sk) | ||
1303 | { | ||
1304 | struct bpf_prog *prog = __get_bpf(ufd, sk); | ||
1305 | int err; | ||
1306 | |||
1307 | if (IS_ERR(prog)) | ||
1308 | return PTR_ERR(prog); | ||
1309 | |||
1238 | err = __sk_attach_prog(prog, sk); | 1310 | err = __sk_attach_prog(prog, sk); |
1239 | if (err < 0) { | 1311 | if (err < 0) { |
1240 | bpf_prog_put(prog); | 1312 | bpf_prog_put(prog); |
@@ -1244,7 +1316,24 @@ int sk_attach_bpf(u32 ufd, struct sock *sk) | |||
1244 | return 0; | 1316 | return 0; |
1245 | } | 1317 | } |
1246 | 1318 | ||
1247 | #define BPF_RECOMPUTE_CSUM(flags) ((flags) & 1) | 1319 | int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk) |
1320 | { | ||
1321 | struct bpf_prog *prog = __get_bpf(ufd, sk); | ||
1322 | int err; | ||
1323 | |||
1324 | if (IS_ERR(prog)) | ||
1325 | return PTR_ERR(prog); | ||
1326 | |||
1327 | err = __reuseport_attach_prog(prog, sk); | ||
1328 | if (err < 0) { | ||
1329 | bpf_prog_put(prog); | ||
1330 | return err; | ||
1331 | } | ||
1332 | |||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | #define BPF_LDST_LEN 16U | ||
1248 | 1337 | ||
1249 | static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) | 1338 | static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) |
1250 | { | 1339 | { |
@@ -1252,9 +1341,12 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) | |||
1252 | int offset = (int) r2; | 1341 | int offset = (int) r2; |
1253 | void *from = (void *) (long) r3; | 1342 | void *from = (void *) (long) r3; |
1254 | unsigned int len = (unsigned int) r4; | 1343 | unsigned int len = (unsigned int) r4; |
1255 | char buf[16]; | 1344 | char buf[BPF_LDST_LEN]; |
1256 | void *ptr; | 1345 | void *ptr; |
1257 | 1346 | ||
1347 | if (unlikely(flags & ~(BPF_F_RECOMPUTE_CSUM))) | ||
1348 | return -EINVAL; | ||
1349 | |||
1258 | /* bpf verifier guarantees that: | 1350 | /* bpf verifier guarantees that: |
1259 | * 'from' pointer points to bpf program stack | 1351 | * 'from' pointer points to bpf program stack |
1260 | * 'len' bytes of it were initialized | 1352 | * 'len' bytes of it were initialized |
@@ -1274,7 +1366,7 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) | |||
1274 | if (unlikely(!ptr)) | 1366 | if (unlikely(!ptr)) |
1275 | return -EFAULT; | 1367 | return -EFAULT; |
1276 | 1368 | ||
1277 | if (BPF_RECOMPUTE_CSUM(flags)) | 1369 | if (flags & BPF_F_RECOMPUTE_CSUM) |
1278 | skb_postpull_rcsum(skb, ptr, len); | 1370 | skb_postpull_rcsum(skb, ptr, len); |
1279 | 1371 | ||
1280 | memcpy(ptr, from, len); | 1372 | memcpy(ptr, from, len); |
@@ -1283,8 +1375,9 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags) | |||
1283 | /* skb_store_bits cannot return -EFAULT here */ | 1375 | /* skb_store_bits cannot return -EFAULT here */ |
1284 | skb_store_bits(skb, offset, ptr, len); | 1376 | skb_store_bits(skb, offset, ptr, len); |
1285 | 1377 | ||
1286 | if (BPF_RECOMPUTE_CSUM(flags) && skb->ip_summed == CHECKSUM_COMPLETE) | 1378 | if (flags & BPF_F_RECOMPUTE_CSUM) |
1287 | skb->csum = csum_add(skb->csum, csum_partial(ptr, len, 0)); | 1379 | skb_postpush_rcsum(skb, ptr, len); |
1380 | |||
1288 | return 0; | 1381 | return 0; |
1289 | } | 1382 | } |
1290 | 1383 | ||
@@ -1299,8 +1392,35 @@ const struct bpf_func_proto bpf_skb_store_bytes_proto = { | |||
1299 | .arg5_type = ARG_ANYTHING, | 1392 | .arg5_type = ARG_ANYTHING, |
1300 | }; | 1393 | }; |
1301 | 1394 | ||
1302 | #define BPF_HEADER_FIELD_SIZE(flags) ((flags) & 0x0f) | 1395 | static u64 bpf_skb_load_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) |
1303 | #define BPF_IS_PSEUDO_HEADER(flags) ((flags) & 0x10) | 1396 | { |
1397 | const struct sk_buff *skb = (const struct sk_buff *)(unsigned long) r1; | ||
1398 | int offset = (int) r2; | ||
1399 | void *to = (void *)(unsigned long) r3; | ||
1400 | unsigned int len = (unsigned int) r4; | ||
1401 | void *ptr; | ||
1402 | |||
1403 | if (unlikely((u32) offset > 0xffff || len > BPF_LDST_LEN)) | ||
1404 | return -EFAULT; | ||
1405 | |||
1406 | ptr = skb_header_pointer(skb, offset, len, to); | ||
1407 | if (unlikely(!ptr)) | ||
1408 | return -EFAULT; | ||
1409 | if (ptr != to) | ||
1410 | memcpy(to, ptr, len); | ||
1411 | |||
1412 | return 0; | ||
1413 | } | ||
1414 | |||
1415 | const struct bpf_func_proto bpf_skb_load_bytes_proto = { | ||
1416 | .func = bpf_skb_load_bytes, | ||
1417 | .gpl_only = false, | ||
1418 | .ret_type = RET_INTEGER, | ||
1419 | .arg1_type = ARG_PTR_TO_CTX, | ||
1420 | .arg2_type = ARG_ANYTHING, | ||
1421 | .arg3_type = ARG_PTR_TO_STACK, | ||
1422 | .arg4_type = ARG_CONST_STACK_SIZE, | ||
1423 | }; | ||
1304 | 1424 | ||
1305 | static u64 bpf_l3_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) | 1425 | static u64 bpf_l3_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) |
1306 | { | 1426 | { |
@@ -1308,6 +1428,8 @@ static u64 bpf_l3_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) | |||
1308 | int offset = (int) r2; | 1428 | int offset = (int) r2; |
1309 | __sum16 sum, *ptr; | 1429 | __sum16 sum, *ptr; |
1310 | 1430 | ||
1431 | if (unlikely(flags & ~(BPF_F_HDR_FIELD_MASK))) | ||
1432 | return -EINVAL; | ||
1311 | if (unlikely((u32) offset > 0xffff)) | 1433 | if (unlikely((u32) offset > 0xffff)) |
1312 | return -EFAULT; | 1434 | return -EFAULT; |
1313 | 1435 | ||
@@ -1319,7 +1441,7 @@ static u64 bpf_l3_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) | |||
1319 | if (unlikely(!ptr)) | 1441 | if (unlikely(!ptr)) |
1320 | return -EFAULT; | 1442 | return -EFAULT; |
1321 | 1443 | ||
1322 | switch (BPF_HEADER_FIELD_SIZE(flags)) { | 1444 | switch (flags & BPF_F_HDR_FIELD_MASK) { |
1323 | case 2: | 1445 | case 2: |
1324 | csum_replace2(ptr, from, to); | 1446 | csum_replace2(ptr, from, to); |
1325 | break; | 1447 | break; |
@@ -1351,10 +1473,12 @@ const struct bpf_func_proto bpf_l3_csum_replace_proto = { | |||
1351 | static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) | 1473 | static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) |
1352 | { | 1474 | { |
1353 | struct sk_buff *skb = (struct sk_buff *) (long) r1; | 1475 | struct sk_buff *skb = (struct sk_buff *) (long) r1; |
1354 | bool is_pseudo = !!BPF_IS_PSEUDO_HEADER(flags); | 1476 | bool is_pseudo = flags & BPF_F_PSEUDO_HDR; |
1355 | int offset = (int) r2; | 1477 | int offset = (int) r2; |
1356 | __sum16 sum, *ptr; | 1478 | __sum16 sum, *ptr; |
1357 | 1479 | ||
1480 | if (unlikely(flags & ~(BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK))) | ||
1481 | return -EINVAL; | ||
1358 | if (unlikely((u32) offset > 0xffff)) | 1482 | if (unlikely((u32) offset > 0xffff)) |
1359 | return -EFAULT; | 1483 | return -EFAULT; |
1360 | 1484 | ||
@@ -1366,7 +1490,7 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags) | |||
1366 | if (unlikely(!ptr)) | 1490 | if (unlikely(!ptr)) |
1367 | return -EFAULT; | 1491 | return -EFAULT; |
1368 | 1492 | ||
1369 | switch (BPF_HEADER_FIELD_SIZE(flags)) { | 1493 | switch (flags & BPF_F_HDR_FIELD_MASK) { |
1370 | case 2: | 1494 | case 2: |
1371 | inet_proto_csum_replace2(ptr, skb, from, to, is_pseudo); | 1495 | inet_proto_csum_replace2(ptr, skb, from, to, is_pseudo); |
1372 | break; | 1496 | break; |
@@ -1395,13 +1519,14 @@ const struct bpf_func_proto bpf_l4_csum_replace_proto = { | |||
1395 | .arg5_type = ARG_ANYTHING, | 1519 | .arg5_type = ARG_ANYTHING, |
1396 | }; | 1520 | }; |
1397 | 1521 | ||
1398 | #define BPF_IS_REDIRECT_INGRESS(flags) ((flags) & 1) | ||
1399 | |||
1400 | static u64 bpf_clone_redirect(u64 r1, u64 ifindex, u64 flags, u64 r4, u64 r5) | 1522 | static u64 bpf_clone_redirect(u64 r1, u64 ifindex, u64 flags, u64 r4, u64 r5) |
1401 | { | 1523 | { |
1402 | struct sk_buff *skb = (struct sk_buff *) (long) r1, *skb2; | 1524 | struct sk_buff *skb = (struct sk_buff *) (long) r1, *skb2; |
1403 | struct net_device *dev; | 1525 | struct net_device *dev; |
1404 | 1526 | ||
1527 | if (unlikely(flags & ~(BPF_F_INGRESS))) | ||
1528 | return -EINVAL; | ||
1529 | |||
1405 | dev = dev_get_by_index_rcu(dev_net(skb->dev), ifindex); | 1530 | dev = dev_get_by_index_rcu(dev_net(skb->dev), ifindex); |
1406 | if (unlikely(!dev)) | 1531 | if (unlikely(!dev)) |
1407 | return -EINVAL; | 1532 | return -EINVAL; |
@@ -1410,8 +1535,12 @@ static u64 bpf_clone_redirect(u64 r1, u64 ifindex, u64 flags, u64 r4, u64 r5) | |||
1410 | if (unlikely(!skb2)) | 1535 | if (unlikely(!skb2)) |
1411 | return -ENOMEM; | 1536 | return -ENOMEM; |
1412 | 1537 | ||
1413 | if (BPF_IS_REDIRECT_INGRESS(flags)) | 1538 | if (flags & BPF_F_INGRESS) { |
1539 | if (skb_at_tc_ingress(skb2)) | ||
1540 | skb_postpush_rcsum(skb2, skb_mac_header(skb2), | ||
1541 | skb2->mac_len); | ||
1414 | return dev_forward_skb(dev, skb2); | 1542 | return dev_forward_skb(dev, skb2); |
1543 | } | ||
1415 | 1544 | ||
1416 | skb2->dev = dev; | 1545 | skb2->dev = dev; |
1417 | skb_sender_cpu_clear(skb2); | 1546 | skb_sender_cpu_clear(skb2); |
@@ -1433,12 +1562,17 @@ struct redirect_info { | |||
1433 | }; | 1562 | }; |
1434 | 1563 | ||
1435 | static DEFINE_PER_CPU(struct redirect_info, redirect_info); | 1564 | static DEFINE_PER_CPU(struct redirect_info, redirect_info); |
1565 | |||
1436 | static u64 bpf_redirect(u64 ifindex, u64 flags, u64 r3, u64 r4, u64 r5) | 1566 | static u64 bpf_redirect(u64 ifindex, u64 flags, u64 r3, u64 r4, u64 r5) |
1437 | { | 1567 | { |
1438 | struct redirect_info *ri = this_cpu_ptr(&redirect_info); | 1568 | struct redirect_info *ri = this_cpu_ptr(&redirect_info); |
1439 | 1569 | ||
1570 | if (unlikely(flags & ~(BPF_F_INGRESS))) | ||
1571 | return TC_ACT_SHOT; | ||
1572 | |||
1440 | ri->ifindex = ifindex; | 1573 | ri->ifindex = ifindex; |
1441 | ri->flags = flags; | 1574 | ri->flags = flags; |
1575 | |||
1442 | return TC_ACT_REDIRECT; | 1576 | return TC_ACT_REDIRECT; |
1443 | } | 1577 | } |
1444 | 1578 | ||
@@ -1454,8 +1588,12 @@ int skb_do_redirect(struct sk_buff *skb) | |||
1454 | return -EINVAL; | 1588 | return -EINVAL; |
1455 | } | 1589 | } |
1456 | 1590 | ||
1457 | if (BPF_IS_REDIRECT_INGRESS(ri->flags)) | 1591 | if (ri->flags & BPF_F_INGRESS) { |
1592 | if (skb_at_tc_ingress(skb)) | ||
1593 | skb_postpush_rcsum(skb, skb_mac_header(skb), | ||
1594 | skb->mac_len); | ||
1458 | return dev_forward_skb(dev, skb); | 1595 | return dev_forward_skb(dev, skb); |
1596 | } | ||
1459 | 1597 | ||
1460 | skb->dev = dev; | 1598 | skb->dev = dev; |
1461 | skb_sender_cpu_clear(skb); | 1599 | skb_sender_cpu_clear(skb); |
@@ -1547,19 +1685,49 @@ bool bpf_helper_changes_skb_data(void *func) | |||
1547 | return false; | 1685 | return false; |
1548 | } | 1686 | } |
1549 | 1687 | ||
1688 | static unsigned short bpf_tunnel_key_af(u64 flags) | ||
1689 | { | ||
1690 | return flags & BPF_F_TUNINFO_IPV6 ? AF_INET6 : AF_INET; | ||
1691 | } | ||
1692 | |||
1550 | static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) | 1693 | static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) |
1551 | { | 1694 | { |
1552 | struct sk_buff *skb = (struct sk_buff *) (long) r1; | 1695 | struct sk_buff *skb = (struct sk_buff *) (long) r1; |
1553 | struct bpf_tunnel_key *to = (struct bpf_tunnel_key *) (long) r2; | 1696 | struct bpf_tunnel_key *to = (struct bpf_tunnel_key *) (long) r2; |
1554 | struct ip_tunnel_info *info = skb_tunnel_info(skb); | 1697 | const struct ip_tunnel_info *info = skb_tunnel_info(skb); |
1698 | u8 compat[sizeof(struct bpf_tunnel_key)]; | ||
1555 | 1699 | ||
1556 | if (unlikely(size != sizeof(struct bpf_tunnel_key) || flags || !info)) | 1700 | if (unlikely(!info || (flags & ~(BPF_F_TUNINFO_IPV6)))) |
1557 | return -EINVAL; | ||
1558 | if (ip_tunnel_info_af(info) != AF_INET) | ||
1559 | return -EINVAL; | 1701 | return -EINVAL; |
1702 | if (ip_tunnel_info_af(info) != bpf_tunnel_key_af(flags)) | ||
1703 | return -EPROTO; | ||
1704 | if (unlikely(size != sizeof(struct bpf_tunnel_key))) { | ||
1705 | switch (size) { | ||
1706 | case offsetof(struct bpf_tunnel_key, remote_ipv6[1]): | ||
1707 | /* Fixup deprecated structure layouts here, so we have | ||
1708 | * a common path later on. | ||
1709 | */ | ||
1710 | if (ip_tunnel_info_af(info) != AF_INET) | ||
1711 | return -EINVAL; | ||
1712 | to = (struct bpf_tunnel_key *)compat; | ||
1713 | break; | ||
1714 | default: | ||
1715 | return -EINVAL; | ||
1716 | } | ||
1717 | } | ||
1560 | 1718 | ||
1561 | to->tunnel_id = be64_to_cpu(info->key.tun_id); | 1719 | to->tunnel_id = be64_to_cpu(info->key.tun_id); |
1562 | to->remote_ipv4 = be32_to_cpu(info->key.u.ipv4.src); | 1720 | to->tunnel_tos = info->key.tos; |
1721 | to->tunnel_ttl = info->key.ttl; | ||
1722 | |||
1723 | if (flags & BPF_F_TUNINFO_IPV6) | ||
1724 | memcpy(to->remote_ipv6, &info->key.u.ipv6.src, | ||
1725 | sizeof(to->remote_ipv6)); | ||
1726 | else | ||
1727 | to->remote_ipv4 = be32_to_cpu(info->key.u.ipv4.src); | ||
1728 | |||
1729 | if (unlikely(size != sizeof(struct bpf_tunnel_key))) | ||
1730 | memcpy((void *)(long) r2, to, size); | ||
1563 | 1731 | ||
1564 | return 0; | 1732 | return 0; |
1565 | } | 1733 | } |
@@ -1581,10 +1749,25 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) | |||
1581 | struct sk_buff *skb = (struct sk_buff *) (long) r1; | 1749 | struct sk_buff *skb = (struct sk_buff *) (long) r1; |
1582 | struct bpf_tunnel_key *from = (struct bpf_tunnel_key *) (long) r2; | 1750 | struct bpf_tunnel_key *from = (struct bpf_tunnel_key *) (long) r2; |
1583 | struct metadata_dst *md = this_cpu_ptr(md_dst); | 1751 | struct metadata_dst *md = this_cpu_ptr(md_dst); |
1752 | u8 compat[sizeof(struct bpf_tunnel_key)]; | ||
1584 | struct ip_tunnel_info *info; | 1753 | struct ip_tunnel_info *info; |
1585 | 1754 | ||
1586 | if (unlikely(size != sizeof(struct bpf_tunnel_key) || flags)) | 1755 | if (unlikely(flags & ~(BPF_F_TUNINFO_IPV6))) |
1587 | return -EINVAL; | 1756 | return -EINVAL; |
1757 | if (unlikely(size != sizeof(struct bpf_tunnel_key))) { | ||
1758 | switch (size) { | ||
1759 | case offsetof(struct bpf_tunnel_key, remote_ipv6[1]): | ||
1760 | /* Fixup deprecated structure layouts here, so we have | ||
1761 | * a common path later on. | ||
1762 | */ | ||
1763 | memcpy(compat, from, size); | ||
1764 | memset(compat + size, 0, sizeof(compat) - size); | ||
1765 | from = (struct bpf_tunnel_key *)compat; | ||
1766 | break; | ||
1767 | default: | ||
1768 | return -EINVAL; | ||
1769 | } | ||
1770 | } | ||
1588 | 1771 | ||
1589 | skb_dst_drop(skb); | 1772 | skb_dst_drop(skb); |
1590 | dst_hold((struct dst_entry *) md); | 1773 | dst_hold((struct dst_entry *) md); |
@@ -1592,9 +1775,19 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) | |||
1592 | 1775 | ||
1593 | info = &md->u.tun_info; | 1776 | info = &md->u.tun_info; |
1594 | info->mode = IP_TUNNEL_INFO_TX; | 1777 | info->mode = IP_TUNNEL_INFO_TX; |
1778 | |||
1595 | info->key.tun_flags = TUNNEL_KEY; | 1779 | info->key.tun_flags = TUNNEL_KEY; |
1596 | info->key.tun_id = cpu_to_be64(from->tunnel_id); | 1780 | info->key.tun_id = cpu_to_be64(from->tunnel_id); |
1597 | info->key.u.ipv4.dst = cpu_to_be32(from->remote_ipv4); | 1781 | info->key.tos = from->tunnel_tos; |
1782 | info->key.ttl = from->tunnel_ttl; | ||
1783 | |||
1784 | if (flags & BPF_F_TUNINFO_IPV6) { | ||
1785 | info->mode |= IP_TUNNEL_INFO_IPV6; | ||
1786 | memcpy(&info->key.u.ipv6.dst, from->remote_ipv6, | ||
1787 | sizeof(from->remote_ipv6)); | ||
1788 | } else { | ||
1789 | info->key.u.ipv4.dst = cpu_to_be32(from->remote_ipv4); | ||
1790 | } | ||
1598 | 1791 | ||
1599 | return 0; | 1792 | return 0; |
1600 | } | 1793 | } |
@@ -1654,6 +1847,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id) | |||
1654 | switch (func_id) { | 1847 | switch (func_id) { |
1655 | case BPF_FUNC_skb_store_bytes: | 1848 | case BPF_FUNC_skb_store_bytes: |
1656 | return &bpf_skb_store_bytes_proto; | 1849 | return &bpf_skb_store_bytes_proto; |
1850 | case BPF_FUNC_skb_load_bytes: | ||
1851 | return &bpf_skb_load_bytes_proto; | ||
1657 | case BPF_FUNC_l3_csum_replace: | 1852 | case BPF_FUNC_l3_csum_replace: |
1658 | return &bpf_l3_csum_replace_proto; | 1853 | return &bpf_l3_csum_replace_proto; |
1659 | case BPF_FUNC_l4_csum_replace: | 1854 | case BPF_FUNC_l4_csum_replace: |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index e6af42da28d9..f18ae91b652e 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -2215,7 +2215,7 @@ static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn, | |||
2215 | ndm->ndm_pad2 = 0; | 2215 | ndm->ndm_pad2 = 0; |
2216 | ndm->ndm_flags = pn->flags | NTF_PROXY; | 2216 | ndm->ndm_flags = pn->flags | NTF_PROXY; |
2217 | ndm->ndm_type = RTN_UNICAST; | 2217 | ndm->ndm_type = RTN_UNICAST; |
2218 | ndm->ndm_ifindex = pn->dev->ifindex; | 2218 | ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0; |
2219 | ndm->ndm_state = NUD_NONE; | 2219 | ndm->ndm_state = NUD_NONE; |
2220 | 2220 | ||
2221 | if (nla_put(skb, NDA_DST, tbl->key_len, pn->key)) | 2221 | if (nla_put(skb, NDA_DST, tbl->key_len, pn->key)) |
@@ -2333,7 +2333,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
2333 | if (h > s_h) | 2333 | if (h > s_h) |
2334 | s_idx = 0; | 2334 | s_idx = 0; |
2335 | for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) { | 2335 | for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) { |
2336 | if (dev_net(n->dev) != net) | 2336 | if (pneigh_net(n) != net) |
2337 | continue; | 2337 | continue; |
2338 | if (idx < s_idx) | 2338 | if (idx < s_idx) |
2339 | goto next; | 2339 | goto next; |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index f88a62ab019d..b6c8a6629b39 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -471,6 +471,7 @@ static ssize_t phys_switch_id_show(struct device *dev, | |||
471 | 471 | ||
472 | if (dev_isalive(netdev)) { | 472 | if (dev_isalive(netdev)) { |
473 | struct switchdev_attr attr = { | 473 | struct switchdev_attr attr = { |
474 | .orig_dev = netdev, | ||
474 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, | 475 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, |
475 | .flags = SWITCHDEV_F_NO_RECURSE, | 476 | .flags = SWITCHDEV_F_NO_RECURSE, |
476 | }; | 477 | }; |
@@ -1452,8 +1453,8 @@ static void netdev_release(struct device *d) | |||
1452 | 1453 | ||
1453 | static const void *net_namespace(struct device *d) | 1454 | static const void *net_namespace(struct device *d) |
1454 | { | 1455 | { |
1455 | struct net_device *dev; | 1456 | struct net_device *dev = to_net_dev(d); |
1456 | dev = container_of(d, struct net_device, dev); | 1457 | |
1457 | return dev_net(dev); | 1458 | return dev_net(dev); |
1458 | } | 1459 | } |
1459 | 1460 | ||
diff --git a/net/core/net-traces.c b/net/core/net-traces.c index adef015b2f41..92da5e4ceb4f 100644 --- a/net/core/net-traces.c +++ b/net/core/net-traces.c | |||
@@ -32,6 +32,10 @@ | |||
32 | #include <trace/events/sock.h> | 32 | #include <trace/events/sock.h> |
33 | #include <trace/events/udp.h> | 33 | #include <trace/events/udp.h> |
34 | #include <trace/events/fib.h> | 34 | #include <trace/events/fib.h> |
35 | #if IS_ENABLED(CONFIG_IPV6) | ||
36 | #include <trace/events/fib6.h> | ||
37 | EXPORT_TRACEPOINT_SYMBOL_GPL(fib6_table_lookup); | ||
38 | #endif | ||
35 | 39 | ||
36 | EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb); | 40 | EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb); |
37 | 41 | ||
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c index 6441f47b1a8f..0260c84ed83c 100644 --- a/net/core/netclassid_cgroup.c +++ b/net/core/netclassid_cgroup.c | |||
@@ -56,29 +56,41 @@ static void cgrp_css_free(struct cgroup_subsys_state *css) | |||
56 | kfree(css_cls_state(css)); | 56 | kfree(css_cls_state(css)); |
57 | } | 57 | } |
58 | 58 | ||
59 | static int update_classid(const void *v, struct file *file, unsigned n) | 59 | static int update_classid_sock(const void *v, struct file *file, unsigned n) |
60 | { | 60 | { |
61 | int err; | 61 | int err; |
62 | struct socket *sock = sock_from_file(file, &err); | 62 | struct socket *sock = sock_from_file(file, &err); |
63 | 63 | ||
64 | if (sock) | 64 | if (sock) { |
65 | sock->sk->sk_classid = (u32)(unsigned long)v; | 65 | spin_lock(&cgroup_sk_update_lock); |
66 | 66 | sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, | |
67 | (unsigned long)v); | ||
68 | spin_unlock(&cgroup_sk_update_lock); | ||
69 | } | ||
67 | return 0; | 70 | return 0; |
68 | } | 71 | } |
69 | 72 | ||
70 | static void cgrp_attach(struct cgroup_subsys_state *css, | 73 | static void update_classid(struct cgroup_subsys_state *css, void *v) |
71 | struct cgroup_taskset *tset) | ||
72 | { | 74 | { |
73 | struct cgroup_cls_state *cs = css_cls_state(css); | 75 | struct css_task_iter it; |
74 | void *v = (void *)(unsigned long)cs->classid; | ||
75 | struct task_struct *p; | 76 | struct task_struct *p; |
76 | 77 | ||
77 | cgroup_taskset_for_each(p, tset) { | 78 | css_task_iter_start(css, &it); |
79 | while ((p = css_task_iter_next(&it))) { | ||
78 | task_lock(p); | 80 | task_lock(p); |
79 | iterate_fd(p->files, 0, update_classid, v); | 81 | iterate_fd(p->files, 0, update_classid_sock, v); |
80 | task_unlock(p); | 82 | task_unlock(p); |
81 | } | 83 | } |
84 | css_task_iter_end(&it); | ||
85 | } | ||
86 | |||
87 | static void cgrp_attach(struct cgroup_taskset *tset) | ||
88 | { | ||
89 | struct cgroup_subsys_state *css; | ||
90 | |||
91 | cgroup_taskset_first(tset, &css); | ||
92 | update_classid(css, | ||
93 | (void *)(unsigned long)css_cls_state(css)->classid); | ||
82 | } | 94 | } |
83 | 95 | ||
84 | static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft) | 96 | static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft) |
@@ -89,8 +101,13 @@ static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft) | |||
89 | static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft, | 101 | static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft, |
90 | u64 value) | 102 | u64 value) |
91 | { | 103 | { |
92 | css_cls_state(css)->classid = (u32) value; | 104 | struct cgroup_cls_state *cs = css_cls_state(css); |
105 | |||
106 | cgroup_sk_alloc_disable(); | ||
107 | |||
108 | cs->classid = (u32)value; | ||
93 | 109 | ||
110 | update_classid(css, (void *)(unsigned long)cs->classid); | ||
94 | return 0; | 111 | return 0; |
95 | } | 112 | } |
96 | 113 | ||
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index cbd0a199bf52..f1efbc39ef6b 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c | |||
@@ -27,6 +27,12 @@ | |||
27 | 27 | ||
28 | #include <linux/fdtable.h> | 28 | #include <linux/fdtable.h> |
29 | 29 | ||
30 | /* | ||
31 | * netprio allocates per-net_device priomap array which is indexed by | ||
32 | * css->id. Limiting css ID to 16bits doesn't lose anything. | ||
33 | */ | ||
34 | #define NETPRIO_ID_MAX USHRT_MAX | ||
35 | |||
30 | #define PRIOMAP_MIN_SZ 128 | 36 | #define PRIOMAP_MIN_SZ 128 |
31 | 37 | ||
32 | /* | 38 | /* |
@@ -144,6 +150,9 @@ static int cgrp_css_online(struct cgroup_subsys_state *css) | |||
144 | struct net_device *dev; | 150 | struct net_device *dev; |
145 | int ret = 0; | 151 | int ret = 0; |
146 | 152 | ||
153 | if (css->id > NETPRIO_ID_MAX) | ||
154 | return -ENOSPC; | ||
155 | |||
147 | if (!parent_css) | 156 | if (!parent_css) |
148 | return 0; | 157 | return 0; |
149 | 158 | ||
@@ -200,6 +209,8 @@ static ssize_t write_priomap(struct kernfs_open_file *of, | |||
200 | if (!dev) | 209 | if (!dev) |
201 | return -ENODEV; | 210 | return -ENODEV; |
202 | 211 | ||
212 | cgroup_sk_alloc_disable(); | ||
213 | |||
203 | rtnl_lock(); | 214 | rtnl_lock(); |
204 | 215 | ||
205 | ret = netprio_set_prio(of_css(of), dev, prio); | 216 | ret = netprio_set_prio(of_css(of), dev, prio); |
@@ -213,18 +224,23 @@ static int update_netprio(const void *v, struct file *file, unsigned n) | |||
213 | { | 224 | { |
214 | int err; | 225 | int err; |
215 | struct socket *sock = sock_from_file(file, &err); | 226 | struct socket *sock = sock_from_file(file, &err); |
216 | if (sock) | 227 | if (sock) { |
217 | sock->sk->sk_cgrp_prioidx = (u32)(unsigned long)v; | 228 | spin_lock(&cgroup_sk_update_lock); |
229 | sock_cgroup_set_prioidx(&sock->sk->sk_cgrp_data, | ||
230 | (unsigned long)v); | ||
231 | spin_unlock(&cgroup_sk_update_lock); | ||
232 | } | ||
218 | return 0; | 233 | return 0; |
219 | } | 234 | } |
220 | 235 | ||
221 | static void net_prio_attach(struct cgroup_subsys_state *css, | 236 | static void net_prio_attach(struct cgroup_taskset *tset) |
222 | struct cgroup_taskset *tset) | ||
223 | { | 237 | { |
224 | struct task_struct *p; | 238 | struct task_struct *p; |
225 | void *v = (void *)(unsigned long)css->cgroup->id; | 239 | struct cgroup_subsys_state *css; |
240 | |||
241 | cgroup_taskset_for_each(p, css, tset) { | ||
242 | void *v = (void *)(unsigned long)css->cgroup->id; | ||
226 | 243 | ||
227 | cgroup_taskset_for_each(p, tset) { | ||
228 | task_lock(p); | 244 | task_lock(p); |
229 | iterate_fd(p->files, 0, update_netprio, v); | 245 | iterate_fd(p->files, 0, update_netprio, v); |
230 | task_unlock(p); | 246 | task_unlock(p); |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index de8d5cc5eb24..1474cfd2dc1c 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -2787,7 +2787,9 @@ static struct sk_buff *pktgen_alloc_skb(struct net_device *dev, | |||
2787 | } else { | 2787 | } else { |
2788 | skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT); | 2788 | skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT); |
2789 | } | 2789 | } |
2790 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 2790 | |
2791 | if (likely(skb)) | ||
2792 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | ||
2791 | 2793 | ||
2792 | return skb; | 2794 | return skb; |
2793 | } | 2795 | } |
@@ -2898,7 +2900,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2898 | 2900 | ||
2899 | if (!(pkt_dev->flags & F_UDPCSUM)) { | 2901 | if (!(pkt_dev->flags & F_UDPCSUM)) { |
2900 | skb->ip_summed = CHECKSUM_NONE; | 2902 | skb->ip_summed = CHECKSUM_NONE; |
2901 | } else if (odev->features & NETIF_F_V4_CSUM) { | 2903 | } else if (odev->features & (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM)) { |
2902 | skb->ip_summed = CHECKSUM_PARTIAL; | 2904 | skb->ip_summed = CHECKSUM_PARTIAL; |
2903 | skb->csum = 0; | 2905 | skb->csum = 0; |
2904 | udp4_hwcsum(skb, iph->saddr, iph->daddr); | 2906 | udp4_hwcsum(skb, iph->saddr, iph->daddr); |
@@ -3032,7 +3034,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
3032 | 3034 | ||
3033 | if (!(pkt_dev->flags & F_UDPCSUM)) { | 3035 | if (!(pkt_dev->flags & F_UDPCSUM)) { |
3034 | skb->ip_summed = CHECKSUM_NONE; | 3036 | skb->ip_summed = CHECKSUM_NONE; |
3035 | } else if (odev->features & NETIF_F_V6_CSUM) { | 3037 | } else if (odev->features & (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM)) { |
3036 | skb->ip_summed = CHECKSUM_PARTIAL; | 3038 | skb->ip_summed = CHECKSUM_PARTIAL; |
3037 | skb->csum_start = skb_transport_header(skb) - skb->head; | 3039 | skb->csum_start = skb_transport_header(skb) - skb->head; |
3038 | skb->csum_offset = offsetof(struct udphdr, check); | 3040 | skb->csum_offset = offsetof(struct udphdr, check); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 34ba7a08876d..d735e854f916 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1027,6 +1027,7 @@ static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev) | |||
1027 | { | 1027 | { |
1028 | int err; | 1028 | int err; |
1029 | struct switchdev_attr attr = { | 1029 | struct switchdev_attr attr = { |
1030 | .orig_dev = dev, | ||
1030 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, | 1031 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, |
1031 | .flags = SWITCHDEV_F_NO_RECURSE, | 1032 | .flags = SWITCHDEV_F_NO_RECURSE, |
1032 | }; | 1033 | }; |
@@ -2563,7 +2564,7 @@ static int nlmsg_populate_fdb_fill(struct sk_buff *skb, | |||
2563 | struct net_device *dev, | 2564 | struct net_device *dev, |
2564 | u8 *addr, u16 vid, u32 pid, u32 seq, | 2565 | u8 *addr, u16 vid, u32 pid, u32 seq, |
2565 | int type, unsigned int flags, | 2566 | int type, unsigned int flags, |
2566 | int nlflags) | 2567 | int nlflags, u16 ndm_state) |
2567 | { | 2568 | { |
2568 | struct nlmsghdr *nlh; | 2569 | struct nlmsghdr *nlh; |
2569 | struct ndmsg *ndm; | 2570 | struct ndmsg *ndm; |
@@ -2579,7 +2580,7 @@ static int nlmsg_populate_fdb_fill(struct sk_buff *skb, | |||
2579 | ndm->ndm_flags = flags; | 2580 | ndm->ndm_flags = flags; |
2580 | ndm->ndm_type = 0; | 2581 | ndm->ndm_type = 0; |
2581 | ndm->ndm_ifindex = dev->ifindex; | 2582 | ndm->ndm_ifindex = dev->ifindex; |
2582 | ndm->ndm_state = NUD_PERMANENT; | 2583 | ndm->ndm_state = ndm_state; |
2583 | 2584 | ||
2584 | if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) | 2585 | if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) |
2585 | goto nla_put_failure; | 2586 | goto nla_put_failure; |
@@ -2600,7 +2601,8 @@ static inline size_t rtnl_fdb_nlmsg_size(void) | |||
2600 | return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN); | 2601 | return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN); |
2601 | } | 2602 | } |
2602 | 2603 | ||
2603 | static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type) | 2604 | static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type, |
2605 | u16 ndm_state) | ||
2604 | { | 2606 | { |
2605 | struct net *net = dev_net(dev); | 2607 | struct net *net = dev_net(dev); |
2606 | struct sk_buff *skb; | 2608 | struct sk_buff *skb; |
@@ -2611,7 +2613,7 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type) | |||
2611 | goto errout; | 2613 | goto errout; |
2612 | 2614 | ||
2613 | err = nlmsg_populate_fdb_fill(skb, dev, addr, vid, | 2615 | err = nlmsg_populate_fdb_fill(skb, dev, addr, vid, |
2614 | 0, 0, type, NTF_SELF, 0); | 2616 | 0, 0, type, NTF_SELF, 0, ndm_state); |
2615 | if (err < 0) { | 2617 | if (err < 0) { |
2616 | kfree_skb(skb); | 2618 | kfree_skb(skb); |
2617 | goto errout; | 2619 | goto errout; |
@@ -2746,7 +2748,8 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2746 | nlh->nlmsg_flags); | 2748 | nlh->nlmsg_flags); |
2747 | 2749 | ||
2748 | if (!err) { | 2750 | if (!err) { |
2749 | rtnl_fdb_notify(dev, addr, vid, RTM_NEWNEIGH); | 2751 | rtnl_fdb_notify(dev, addr, vid, RTM_NEWNEIGH, |
2752 | ndm->ndm_state); | ||
2750 | ndm->ndm_flags &= ~NTF_SELF; | 2753 | ndm->ndm_flags &= ~NTF_SELF; |
2751 | } | 2754 | } |
2752 | } | 2755 | } |
@@ -2847,7 +2850,8 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2847 | err = ndo_dflt_fdb_del(ndm, tb, dev, addr, vid); | 2850 | err = ndo_dflt_fdb_del(ndm, tb, dev, addr, vid); |
2848 | 2851 | ||
2849 | if (!err) { | 2852 | if (!err) { |
2850 | rtnl_fdb_notify(dev, addr, vid, RTM_DELNEIGH); | 2853 | rtnl_fdb_notify(dev, addr, vid, RTM_DELNEIGH, |
2854 | ndm->ndm_state); | ||
2851 | ndm->ndm_flags &= ~NTF_SELF; | 2855 | ndm->ndm_flags &= ~NTF_SELF; |
2852 | } | 2856 | } |
2853 | } | 2857 | } |
@@ -2875,7 +2879,7 @@ static int nlmsg_populate_fdb(struct sk_buff *skb, | |||
2875 | err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, 0, | 2879 | err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, 0, |
2876 | portid, seq, | 2880 | portid, seq, |
2877 | RTM_NEWNEIGH, NTF_SELF, | 2881 | RTM_NEWNEIGH, NTF_SELF, |
2878 | NLM_F_MULTI); | 2882 | NLM_F_MULTI, NUD_PERMANENT); |
2879 | if (err < 0) | 2883 | if (err < 0) |
2880 | return err; | 2884 | return err; |
2881 | skip: | 2885 | skip: |
@@ -3347,7 +3351,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3347 | { | 3351 | { |
3348 | struct net *net = sock_net(skb->sk); | 3352 | struct net *net = sock_net(skb->sk); |
3349 | rtnl_doit_func doit; | 3353 | rtnl_doit_func doit; |
3350 | int sz_idx, kind; | 3354 | int kind; |
3351 | int family; | 3355 | int family; |
3352 | int type; | 3356 | int type; |
3353 | int err; | 3357 | int err; |
@@ -3363,7 +3367,6 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3363 | return 0; | 3367 | return 0; |
3364 | 3368 | ||
3365 | family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family; | 3369 | family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family; |
3366 | sz_idx = type>>2; | ||
3367 | kind = type&3; | 3370 | kind = type&3; |
3368 | 3371 | ||
3369 | if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN)) | 3372 | if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN)) |
diff --git a/net/core/scm.c b/net/core/scm.c index 3b6899b7d810..14596fb37172 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -289,8 +289,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) | |||
289 | /* Bump the usage count and install the file. */ | 289 | /* Bump the usage count and install the file. */ |
290 | sock = sock_from_file(fp[i], &err); | 290 | sock = sock_from_file(fp[i], &err); |
291 | if (sock) { | 291 | if (sock) { |
292 | sock_update_netprioidx(sock->sk); | 292 | sock_update_netprioidx(&sock->sk->sk_cgrp_data); |
293 | sock_update_classid(sock->sk); | 293 | sock_update_classid(&sock->sk->sk_cgrp_data); |
294 | } | 294 | } |
295 | fd_install(new_fd, get_file(fp[i])); | 295 | fd_install(new_fd, get_file(fp[i])); |
296 | } | 296 | } |
@@ -305,6 +305,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) | |||
305 | err = put_user(cmlen, &cm->cmsg_len); | 305 | err = put_user(cmlen, &cm->cmsg_len); |
306 | if (!err) { | 306 | if (!err) { |
307 | cmlen = CMSG_SPACE(i*sizeof(int)); | 307 | cmlen = CMSG_SPACE(i*sizeof(int)); |
308 | if (msg->msg_controllen < cmlen) | ||
309 | cmlen = msg->msg_controllen; | ||
308 | msg->msg_control += cmlen; | 310 | msg->msg_control += cmlen; |
309 | msg->msg_controllen -= cmlen; | 311 | msg->msg_controllen -= cmlen; |
310 | } | 312 | } |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 152b9c70e252..b2df375ec9c2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -3643,7 +3643,8 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb, | |||
3643 | serr->ee.ee_info = tstype; | 3643 | serr->ee.ee_info = tstype; |
3644 | if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { | 3644 | if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { |
3645 | serr->ee.ee_data = skb_shinfo(skb)->tskey; | 3645 | serr->ee.ee_data = skb_shinfo(skb)->tskey; |
3646 | if (sk->sk_protocol == IPPROTO_TCP) | 3646 | if (sk->sk_protocol == IPPROTO_TCP && |
3647 | sk->sk_type == SOCK_STREAM) | ||
3647 | serr->ee.ee_data -= sk->sk_tskey; | 3648 | serr->ee.ee_data -= sk->sk_tskey; |
3648 | } | 3649 | } |
3649 | 3650 | ||
@@ -4268,7 +4269,7 @@ static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) | |||
4268 | return NULL; | 4269 | return NULL; |
4269 | } | 4270 | } |
4270 | 4271 | ||
4271 | memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len, | 4272 | memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len - VLAN_HLEN, |
4272 | 2 * ETH_ALEN); | 4273 | 2 * ETH_ALEN); |
4273 | skb->mac_header += VLAN_HLEN; | 4274 | skb->mac_header += VLAN_HLEN; |
4274 | return skb; | 4275 | return skb; |
diff --git a/net/core/sock.c b/net/core/sock.c index 1e4dd54bfb5a..51270238e269 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -134,6 +134,7 @@ | |||
134 | #include <linux/sock_diag.h> | 134 | #include <linux/sock_diag.h> |
135 | 135 | ||
136 | #include <linux/filter.h> | 136 | #include <linux/filter.h> |
137 | #include <net/sock_reuseport.h> | ||
137 | 138 | ||
138 | #include <trace/events/sock.h> | 139 | #include <trace/events/sock.h> |
139 | 140 | ||
@@ -433,8 +434,6 @@ static bool sock_needs_netstamp(const struct sock *sk) | |||
433 | } | 434 | } |
434 | } | 435 | } |
435 | 436 | ||
436 | #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) | ||
437 | |||
438 | static void sock_disable_timestamp(struct sock *sk, unsigned long flags) | 437 | static void sock_disable_timestamp(struct sock *sk, unsigned long flags) |
439 | { | 438 | { |
440 | if (sk->sk_flags & flags) { | 439 | if (sk->sk_flags & flags) { |
@@ -874,7 +873,8 @@ set_rcvbuf: | |||
874 | 873 | ||
875 | if (val & SOF_TIMESTAMPING_OPT_ID && | 874 | if (val & SOF_TIMESTAMPING_OPT_ID && |
876 | !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { | 875 | !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { |
877 | if (sk->sk_protocol == IPPROTO_TCP) { | 876 | if (sk->sk_protocol == IPPROTO_TCP && |
877 | sk->sk_type == SOCK_STREAM) { | ||
878 | if (sk->sk_state != TCP_ESTABLISHED) { | 878 | if (sk->sk_state != TCP_ESTABLISHED) { |
879 | ret = -EINVAL; | 879 | ret = -EINVAL; |
880 | break; | 880 | break; |
@@ -933,6 +933,32 @@ set_rcvbuf: | |||
933 | } | 933 | } |
934 | break; | 934 | break; |
935 | 935 | ||
936 | case SO_ATTACH_REUSEPORT_CBPF: | ||
937 | ret = -EINVAL; | ||
938 | if (optlen == sizeof(struct sock_fprog)) { | ||
939 | struct sock_fprog fprog; | ||
940 | |||
941 | ret = -EFAULT; | ||
942 | if (copy_from_user(&fprog, optval, sizeof(fprog))) | ||
943 | break; | ||
944 | |||
945 | ret = sk_reuseport_attach_filter(&fprog, sk); | ||
946 | } | ||
947 | break; | ||
948 | |||
949 | case SO_ATTACH_REUSEPORT_EBPF: | ||
950 | ret = -EINVAL; | ||
951 | if (optlen == sizeof(u32)) { | ||
952 | u32 ufd; | ||
953 | |||
954 | ret = -EFAULT; | ||
955 | if (copy_from_user(&ufd, optval, sizeof(ufd))) | ||
956 | break; | ||
957 | |||
958 | ret = sk_reuseport_attach_bpf(ufd, sk); | ||
959 | } | ||
960 | break; | ||
961 | |||
936 | case SO_DETACH_FILTER: | 962 | case SO_DETACH_FILTER: |
937 | ret = sk_detach_filter(sk); | 963 | ret = sk_detach_filter(sk); |
938 | break; | 964 | break; |
@@ -1363,6 +1389,7 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, | |||
1363 | if (!try_module_get(prot->owner)) | 1389 | if (!try_module_get(prot->owner)) |
1364 | goto out_free_sec; | 1390 | goto out_free_sec; |
1365 | sk_tx_queue_clear(sk); | 1391 | sk_tx_queue_clear(sk); |
1392 | cgroup_sk_alloc(&sk->sk_cgrp_data); | ||
1366 | } | 1393 | } |
1367 | 1394 | ||
1368 | return sk; | 1395 | return sk; |
@@ -1385,6 +1412,7 @@ static void sk_prot_free(struct proto *prot, struct sock *sk) | |||
1385 | owner = prot->owner; | 1412 | owner = prot->owner; |
1386 | slab = prot->slab; | 1413 | slab = prot->slab; |
1387 | 1414 | ||
1415 | cgroup_sk_free(&sk->sk_cgrp_data); | ||
1388 | security_sk_free(sk); | 1416 | security_sk_free(sk); |
1389 | if (slab != NULL) | 1417 | if (slab != NULL) |
1390 | kmem_cache_free(slab, sk); | 1418 | kmem_cache_free(slab, sk); |
@@ -1393,17 +1421,6 @@ static void sk_prot_free(struct proto *prot, struct sock *sk) | |||
1393 | module_put(owner); | 1421 | module_put(owner); |
1394 | } | 1422 | } |
1395 | 1423 | ||
1396 | #if IS_ENABLED(CONFIG_CGROUP_NET_PRIO) | ||
1397 | void sock_update_netprioidx(struct sock *sk) | ||
1398 | { | ||
1399 | if (in_interrupt()) | ||
1400 | return; | ||
1401 | |||
1402 | sk->sk_cgrp_prioidx = task_netprioidx(current); | ||
1403 | } | ||
1404 | EXPORT_SYMBOL_GPL(sock_update_netprioidx); | ||
1405 | #endif | ||
1406 | |||
1407 | /** | 1424 | /** |
1408 | * sk_alloc - All socket objects are allocated here | 1425 | * sk_alloc - All socket objects are allocated here |
1409 | * @net: the applicable net namespace | 1426 | * @net: the applicable net namespace |
@@ -1432,8 +1449,8 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, | |||
1432 | sock_net_set(sk, net); | 1449 | sock_net_set(sk, net); |
1433 | atomic_set(&sk->sk_wmem_alloc, 1); | 1450 | atomic_set(&sk->sk_wmem_alloc, 1); |
1434 | 1451 | ||
1435 | sock_update_classid(sk); | 1452 | sock_update_classid(&sk->sk_cgrp_data); |
1436 | sock_update_netprioidx(sk); | 1453 | sock_update_netprioidx(&sk->sk_cgrp_data); |
1437 | } | 1454 | } |
1438 | 1455 | ||
1439 | return sk; | 1456 | return sk; |
@@ -1453,6 +1470,8 @@ void sk_destruct(struct sock *sk) | |||
1453 | sk_filter_uncharge(sk, filter); | 1470 | sk_filter_uncharge(sk, filter); |
1454 | RCU_INIT_POINTER(sk->sk_filter, NULL); | 1471 | RCU_INIT_POINTER(sk->sk_filter, NULL); |
1455 | } | 1472 | } |
1473 | if (rcu_access_pointer(sk->sk_reuseport_cb)) | ||
1474 | reuseport_detach_sock(sk); | ||
1456 | 1475 | ||
1457 | sock_disable_timestamp(sk, SK_FLAGS_TIMESTAMP); | 1476 | sock_disable_timestamp(sk, SK_FLAGS_TIMESTAMP); |
1458 | 1477 | ||
@@ -1530,7 +1549,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | |||
1530 | skb_queue_head_init(&newsk->sk_receive_queue); | 1549 | skb_queue_head_init(&newsk->sk_receive_queue); |
1531 | skb_queue_head_init(&newsk->sk_write_queue); | 1550 | skb_queue_head_init(&newsk->sk_write_queue); |
1532 | 1551 | ||
1533 | spin_lock_init(&newsk->sk_dst_lock); | ||
1534 | rwlock_init(&newsk->sk_callback_lock); | 1552 | rwlock_init(&newsk->sk_callback_lock); |
1535 | lockdep_set_class_and_name(&newsk->sk_callback_lock, | 1553 | lockdep_set_class_and_name(&newsk->sk_callback_lock, |
1536 | af_callback_keys + newsk->sk_family, | 1554 | af_callback_keys + newsk->sk_family, |
@@ -1553,7 +1571,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | |||
1553 | */ | 1571 | */ |
1554 | is_charged = sk_filter_charge(newsk, filter); | 1572 | is_charged = sk_filter_charge(newsk, filter); |
1555 | 1573 | ||
1556 | if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk))) { | 1574 | if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) { |
1557 | /* It is still raw copy of parent, so invalidate | 1575 | /* It is still raw copy of parent, so invalidate |
1558 | * destructor and make plain sk_free() */ | 1576 | * destructor and make plain sk_free() */ |
1559 | newsk->sk_destruct = NULL; | 1577 | newsk->sk_destruct = NULL; |
@@ -1607,7 +1625,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) | |||
1607 | { | 1625 | { |
1608 | u32 max_segs = 1; | 1626 | u32 max_segs = 1; |
1609 | 1627 | ||
1610 | __sk_dst_set(sk, dst); | 1628 | sk_dst_set(sk, dst); |
1611 | sk->sk_route_caps = dst->dev->features; | 1629 | sk->sk_route_caps = dst->dev->features; |
1612 | if (sk->sk_route_caps & NETIF_F_GSO) | 1630 | if (sk->sk_route_caps & NETIF_F_GSO) |
1613 | sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; | 1631 | sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; |
@@ -1815,7 +1833,7 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo) | |||
1815 | { | 1833 | { |
1816 | DEFINE_WAIT(wait); | 1834 | DEFINE_WAIT(wait); |
1817 | 1835 | ||
1818 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 1836 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
1819 | for (;;) { | 1837 | for (;;) { |
1820 | if (!timeo) | 1838 | if (!timeo) |
1821 | break; | 1839 | break; |
@@ -1861,7 +1879,7 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | |||
1861 | if (sk_wmem_alloc_get(sk) < sk->sk_sndbuf) | 1879 | if (sk_wmem_alloc_get(sk) < sk->sk_sndbuf) |
1862 | break; | 1880 | break; |
1863 | 1881 | ||
1864 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 1882 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
1865 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | 1883 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
1866 | err = -EAGAIN; | 1884 | err = -EAGAIN; |
1867 | if (!timeo) | 1885 | if (!timeo) |
@@ -2048,9 +2066,9 @@ int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb) | |||
2048 | DEFINE_WAIT(wait); | 2066 | DEFINE_WAIT(wait); |
2049 | 2067 | ||
2050 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 2068 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
2051 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2069 | sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
2052 | rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb); | 2070 | rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb); |
2053 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2071 | sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
2054 | finish_wait(sk_sleep(sk), &wait); | 2072 | finish_wait(sk_sleep(sk), &wait); |
2055 | return rc; | 2073 | return rc; |
2056 | } | 2074 | } |
@@ -2283,7 +2301,7 @@ static void sock_def_wakeup(struct sock *sk) | |||
2283 | 2301 | ||
2284 | rcu_read_lock(); | 2302 | rcu_read_lock(); |
2285 | wq = rcu_dereference(sk->sk_wq); | 2303 | wq = rcu_dereference(sk->sk_wq); |
2286 | if (wq_has_sleeper(wq)) | 2304 | if (skwq_has_sleeper(wq)) |
2287 | wake_up_interruptible_all(&wq->wait); | 2305 | wake_up_interruptible_all(&wq->wait); |
2288 | rcu_read_unlock(); | 2306 | rcu_read_unlock(); |
2289 | } | 2307 | } |
@@ -2294,7 +2312,7 @@ static void sock_def_error_report(struct sock *sk) | |||
2294 | 2312 | ||
2295 | rcu_read_lock(); | 2313 | rcu_read_lock(); |
2296 | wq = rcu_dereference(sk->sk_wq); | 2314 | wq = rcu_dereference(sk->sk_wq); |
2297 | if (wq_has_sleeper(wq)) | 2315 | if (skwq_has_sleeper(wq)) |
2298 | wake_up_interruptible_poll(&wq->wait, POLLERR); | 2316 | wake_up_interruptible_poll(&wq->wait, POLLERR); |
2299 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); | 2317 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); |
2300 | rcu_read_unlock(); | 2318 | rcu_read_unlock(); |
@@ -2306,7 +2324,7 @@ static void sock_def_readable(struct sock *sk) | |||
2306 | 2324 | ||
2307 | rcu_read_lock(); | 2325 | rcu_read_lock(); |
2308 | wq = rcu_dereference(sk->sk_wq); | 2326 | wq = rcu_dereference(sk->sk_wq); |
2309 | if (wq_has_sleeper(wq)) | 2327 | if (skwq_has_sleeper(wq)) |
2310 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI | | 2328 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI | |
2311 | POLLRDNORM | POLLRDBAND); | 2329 | POLLRDNORM | POLLRDBAND); |
2312 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 2330 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
@@ -2324,7 +2342,7 @@ static void sock_def_write_space(struct sock *sk) | |||
2324 | */ | 2342 | */ |
2325 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { | 2343 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { |
2326 | wq = rcu_dereference(sk->sk_wq); | 2344 | wq = rcu_dereference(sk->sk_wq); |
2327 | if (wq_has_sleeper(wq)) | 2345 | if (skwq_has_sleeper(wq)) |
2328 | wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | | 2346 | wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | |
2329 | POLLWRNORM | POLLWRBAND); | 2347 | POLLWRNORM | POLLWRBAND); |
2330 | 2348 | ||
@@ -2388,7 +2406,6 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
2388 | } else | 2406 | } else |
2389 | sk->sk_wq = NULL; | 2407 | sk->sk_wq = NULL; |
2390 | 2408 | ||
2391 | spin_lock_init(&sk->sk_dst_lock); | ||
2392 | rwlock_init(&sk->sk_callback_lock); | 2409 | rwlock_init(&sk->sk_callback_lock); |
2393 | lockdep_set_class_and_name(&sk->sk_callback_lock, | 2410 | lockdep_set_class_and_name(&sk->sk_callback_lock, |
2394 | af_callback_keys + sk->sk_family, | 2411 | af_callback_keys + sk->sk_family, |
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 0c1d58d43f67..a996ce8c8fb2 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c | |||
@@ -214,7 +214,7 @@ void sock_diag_unregister(const struct sock_diag_handler *hnld) | |||
214 | } | 214 | } |
215 | EXPORT_SYMBOL_GPL(sock_diag_unregister); | 215 | EXPORT_SYMBOL_GPL(sock_diag_unregister); |
216 | 216 | ||
217 | static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 217 | static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh) |
218 | { | 218 | { |
219 | int err; | 219 | int err; |
220 | struct sock_diag_req *req = nlmsg_data(nlh); | 220 | struct sock_diag_req *req = nlmsg_data(nlh); |
@@ -234,8 +234,12 @@ static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
234 | hndl = sock_diag_handlers[req->sdiag_family]; | 234 | hndl = sock_diag_handlers[req->sdiag_family]; |
235 | if (hndl == NULL) | 235 | if (hndl == NULL) |
236 | err = -ENOENT; | 236 | err = -ENOENT; |
237 | else | 237 | else if (nlh->nlmsg_type == SOCK_DIAG_BY_FAMILY) |
238 | err = hndl->dump(skb, nlh); | 238 | err = hndl->dump(skb, nlh); |
239 | else if (nlh->nlmsg_type == SOCK_DESTROY && hndl->destroy) | ||
240 | err = hndl->destroy(skb, nlh); | ||
241 | else | ||
242 | err = -EOPNOTSUPP; | ||
239 | mutex_unlock(&sock_diag_table_mutex); | 243 | mutex_unlock(&sock_diag_table_mutex); |
240 | 244 | ||
241 | return err; | 245 | return err; |
@@ -261,7 +265,8 @@ static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
261 | 265 | ||
262 | return ret; | 266 | return ret; |
263 | case SOCK_DIAG_BY_FAMILY: | 267 | case SOCK_DIAG_BY_FAMILY: |
264 | return __sock_diag_rcv_msg(skb, nlh); | 268 | case SOCK_DESTROY: |
269 | return __sock_diag_cmd(skb, nlh); | ||
265 | default: | 270 | default: |
266 | return -EINVAL; | 271 | return -EINVAL; |
267 | } | 272 | } |
@@ -295,6 +300,18 @@ static int sock_diag_bind(struct net *net, int group) | |||
295 | return 0; | 300 | return 0; |
296 | } | 301 | } |
297 | 302 | ||
303 | int sock_diag_destroy(struct sock *sk, int err) | ||
304 | { | ||
305 | if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) | ||
306 | return -EPERM; | ||
307 | |||
308 | if (!sk->sk_prot->diag_destroy) | ||
309 | return -EOPNOTSUPP; | ||
310 | |||
311 | return sk->sk_prot->diag_destroy(sk, err); | ||
312 | } | ||
313 | EXPORT_SYMBOL_GPL(sock_diag_destroy); | ||
314 | |||
298 | static int __net_init diag_net_init(struct net *net) | 315 | static int __net_init diag_net_init(struct net *net) |
299 | { | 316 | { |
300 | struct netlink_kernel_cfg cfg = { | 317 | struct netlink_kernel_cfg cfg = { |
diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c new file mode 100644 index 000000000000..1df98c557440 --- /dev/null +++ b/net/core/sock_reuseport.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * To speed up listener socket lookup, create an array to store all sockets | ||
3 | * listening on the same port. This allows a decision to be made after finding | ||
4 | * the first socket. An optional BPF program can also be configured for | ||
5 | * selecting the socket index from the array of available sockets. | ||
6 | */ | ||
7 | |||
8 | #include <net/sock_reuseport.h> | ||
9 | #include <linux/bpf.h> | ||
10 | #include <linux/rcupdate.h> | ||
11 | |||
12 | #define INIT_SOCKS 128 | ||
13 | |||
14 | static DEFINE_SPINLOCK(reuseport_lock); | ||
15 | |||
16 | static struct sock_reuseport *__reuseport_alloc(u16 max_socks) | ||
17 | { | ||
18 | size_t size = sizeof(struct sock_reuseport) + | ||
19 | sizeof(struct sock *) * max_socks; | ||
20 | struct sock_reuseport *reuse = kzalloc(size, GFP_ATOMIC); | ||
21 | |||
22 | if (!reuse) | ||
23 | return NULL; | ||
24 | |||
25 | reuse->max_socks = max_socks; | ||
26 | |||
27 | RCU_INIT_POINTER(reuse->prog, NULL); | ||
28 | return reuse; | ||
29 | } | ||
30 | |||
31 | int reuseport_alloc(struct sock *sk) | ||
32 | { | ||
33 | struct sock_reuseport *reuse; | ||
34 | |||
35 | /* bh lock used since this function call may precede hlist lock in | ||
36 | * soft irq of receive path or setsockopt from process context | ||
37 | */ | ||
38 | spin_lock_bh(&reuseport_lock); | ||
39 | WARN_ONCE(rcu_dereference_protected(sk->sk_reuseport_cb, | ||
40 | lockdep_is_held(&reuseport_lock)), | ||
41 | "multiple allocations for the same socket"); | ||
42 | reuse = __reuseport_alloc(INIT_SOCKS); | ||
43 | if (!reuse) { | ||
44 | spin_unlock_bh(&reuseport_lock); | ||
45 | return -ENOMEM; | ||
46 | } | ||
47 | |||
48 | reuse->socks[0] = sk; | ||
49 | reuse->num_socks = 1; | ||
50 | rcu_assign_pointer(sk->sk_reuseport_cb, reuse); | ||
51 | |||
52 | spin_unlock_bh(&reuseport_lock); | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | EXPORT_SYMBOL(reuseport_alloc); | ||
57 | |||
58 | static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse) | ||
59 | { | ||
60 | struct sock_reuseport *more_reuse; | ||
61 | u32 more_socks_size, i; | ||
62 | |||
63 | more_socks_size = reuse->max_socks * 2U; | ||
64 | if (more_socks_size > U16_MAX) | ||
65 | return NULL; | ||
66 | |||
67 | more_reuse = __reuseport_alloc(more_socks_size); | ||
68 | if (!more_reuse) | ||
69 | return NULL; | ||
70 | |||
71 | more_reuse->max_socks = more_socks_size; | ||
72 | more_reuse->num_socks = reuse->num_socks; | ||
73 | more_reuse->prog = reuse->prog; | ||
74 | |||
75 | memcpy(more_reuse->socks, reuse->socks, | ||
76 | reuse->num_socks * sizeof(struct sock *)); | ||
77 | |||
78 | for (i = 0; i < reuse->num_socks; ++i) | ||
79 | rcu_assign_pointer(reuse->socks[i]->sk_reuseport_cb, | ||
80 | more_reuse); | ||
81 | |||
82 | /* Note: we use kfree_rcu here instead of reuseport_free_rcu so | ||
83 | * that reuse and more_reuse can temporarily share a reference | ||
84 | * to prog. | ||
85 | */ | ||
86 | kfree_rcu(reuse, rcu); | ||
87 | return more_reuse; | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * reuseport_add_sock - Add a socket to the reuseport group of another. | ||
92 | * @sk: New socket to add to the group. | ||
93 | * @sk2: Socket belonging to the existing reuseport group. | ||
94 | * May return ENOMEM and not add socket to group under memory pressure. | ||
95 | */ | ||
96 | int reuseport_add_sock(struct sock *sk, const struct sock *sk2) | ||
97 | { | ||
98 | struct sock_reuseport *reuse; | ||
99 | |||
100 | spin_lock_bh(&reuseport_lock); | ||
101 | reuse = rcu_dereference_protected(sk2->sk_reuseport_cb, | ||
102 | lockdep_is_held(&reuseport_lock)), | ||
103 | WARN_ONCE(rcu_dereference_protected(sk->sk_reuseport_cb, | ||
104 | lockdep_is_held(&reuseport_lock)), | ||
105 | "socket already in reuseport group"); | ||
106 | |||
107 | if (reuse->num_socks == reuse->max_socks) { | ||
108 | reuse = reuseport_grow(reuse); | ||
109 | if (!reuse) { | ||
110 | spin_unlock_bh(&reuseport_lock); | ||
111 | return -ENOMEM; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | reuse->socks[reuse->num_socks] = sk; | ||
116 | /* paired with smp_rmb() in reuseport_select_sock() */ | ||
117 | smp_wmb(); | ||
118 | reuse->num_socks++; | ||
119 | rcu_assign_pointer(sk->sk_reuseport_cb, reuse); | ||
120 | |||
121 | spin_unlock_bh(&reuseport_lock); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | EXPORT_SYMBOL(reuseport_add_sock); | ||
126 | |||
127 | static void reuseport_free_rcu(struct rcu_head *head) | ||
128 | { | ||
129 | struct sock_reuseport *reuse; | ||
130 | |||
131 | reuse = container_of(head, struct sock_reuseport, rcu); | ||
132 | if (reuse->prog) | ||
133 | bpf_prog_destroy(reuse->prog); | ||
134 | kfree(reuse); | ||
135 | } | ||
136 | |||
137 | void reuseport_detach_sock(struct sock *sk) | ||
138 | { | ||
139 | struct sock_reuseport *reuse; | ||
140 | int i; | ||
141 | |||
142 | spin_lock_bh(&reuseport_lock); | ||
143 | reuse = rcu_dereference_protected(sk->sk_reuseport_cb, | ||
144 | lockdep_is_held(&reuseport_lock)); | ||
145 | rcu_assign_pointer(sk->sk_reuseport_cb, NULL); | ||
146 | |||
147 | for (i = 0; i < reuse->num_socks; i++) { | ||
148 | if (reuse->socks[i] == sk) { | ||
149 | reuse->socks[i] = reuse->socks[reuse->num_socks - 1]; | ||
150 | reuse->num_socks--; | ||
151 | if (reuse->num_socks == 0) | ||
152 | call_rcu(&reuse->rcu, reuseport_free_rcu); | ||
153 | break; | ||
154 | } | ||
155 | } | ||
156 | spin_unlock_bh(&reuseport_lock); | ||
157 | } | ||
158 | EXPORT_SYMBOL(reuseport_detach_sock); | ||
159 | |||
160 | static struct sock *run_bpf(struct sock_reuseport *reuse, u16 socks, | ||
161 | struct bpf_prog *prog, struct sk_buff *skb, | ||
162 | int hdr_len) | ||
163 | { | ||
164 | struct sk_buff *nskb = NULL; | ||
165 | u32 index; | ||
166 | |||
167 | if (skb_shared(skb)) { | ||
168 | nskb = skb_clone(skb, GFP_ATOMIC); | ||
169 | if (!nskb) | ||
170 | return NULL; | ||
171 | skb = nskb; | ||
172 | } | ||
173 | |||
174 | /* temporarily advance data past protocol header */ | ||
175 | if (!pskb_pull(skb, hdr_len)) { | ||
176 | kfree_skb(nskb); | ||
177 | return NULL; | ||
178 | } | ||
179 | index = bpf_prog_run_save_cb(prog, skb); | ||
180 | __skb_push(skb, hdr_len); | ||
181 | |||
182 | consume_skb(nskb); | ||
183 | |||
184 | if (index >= socks) | ||
185 | return NULL; | ||
186 | |||
187 | return reuse->socks[index]; | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * reuseport_select_sock - Select a socket from an SO_REUSEPORT group. | ||
192 | * @sk: First socket in the group. | ||
193 | * @hash: When no BPF filter is available, use this hash to select. | ||
194 | * @skb: skb to run through BPF filter. | ||
195 | * @hdr_len: BPF filter expects skb data pointer at payload data. If | ||
196 | * the skb does not yet point at the payload, this parameter represents | ||
197 | * how far the pointer needs to advance to reach the payload. | ||
198 | * Returns a socket that should receive the packet (or NULL on error). | ||
199 | */ | ||
200 | struct sock *reuseport_select_sock(struct sock *sk, | ||
201 | u32 hash, | ||
202 | struct sk_buff *skb, | ||
203 | int hdr_len) | ||
204 | { | ||
205 | struct sock_reuseport *reuse; | ||
206 | struct bpf_prog *prog; | ||
207 | struct sock *sk2 = NULL; | ||
208 | u16 socks; | ||
209 | |||
210 | rcu_read_lock(); | ||
211 | reuse = rcu_dereference(sk->sk_reuseport_cb); | ||
212 | |||
213 | /* if memory allocation failed or add call is not yet complete */ | ||
214 | if (!reuse) | ||
215 | goto out; | ||
216 | |||
217 | prog = rcu_dereference(reuse->prog); | ||
218 | socks = READ_ONCE(reuse->num_socks); | ||
219 | if (likely(socks)) { | ||
220 | /* paired with smp_wmb() in reuseport_add_sock() */ | ||
221 | smp_rmb(); | ||
222 | |||
223 | if (prog && skb) | ||
224 | sk2 = run_bpf(reuse, socks, prog, skb, hdr_len); | ||
225 | else | ||
226 | sk2 = reuse->socks[reciprocal_scale(hash, socks)]; | ||
227 | } | ||
228 | |||
229 | out: | ||
230 | rcu_read_unlock(); | ||
231 | return sk2; | ||
232 | } | ||
233 | EXPORT_SYMBOL(reuseport_select_sock); | ||
234 | |||
235 | struct bpf_prog * | ||
236 | reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog) | ||
237 | { | ||
238 | struct sock_reuseport *reuse; | ||
239 | struct bpf_prog *old_prog; | ||
240 | |||
241 | spin_lock_bh(&reuseport_lock); | ||
242 | reuse = rcu_dereference_protected(sk->sk_reuseport_cb, | ||
243 | lockdep_is_held(&reuseport_lock)); | ||
244 | old_prog = rcu_dereference_protected(reuse->prog, | ||
245 | lockdep_is_held(&reuseport_lock)); | ||
246 | rcu_assign_pointer(reuse->prog, prog); | ||
247 | spin_unlock_bh(&reuseport_lock); | ||
248 | |||
249 | return old_prog; | ||
250 | } | ||
251 | EXPORT_SYMBOL(reuseport_attach_prog); | ||
diff --git a/net/core/stream.c b/net/core/stream.c index d70f77a0c889..159516a11b7e 100644 --- a/net/core/stream.c +++ b/net/core/stream.c | |||
@@ -35,11 +35,11 @@ void sk_stream_write_space(struct sock *sk) | |||
35 | 35 | ||
36 | rcu_read_lock(); | 36 | rcu_read_lock(); |
37 | wq = rcu_dereference(sk->sk_wq); | 37 | wq = rcu_dereference(sk->sk_wq); |
38 | if (wq_has_sleeper(wq)) | 38 | if (skwq_has_sleeper(wq)) |
39 | wake_up_interruptible_poll(&wq->wait, POLLOUT | | 39 | wake_up_interruptible_poll(&wq->wait, POLLOUT | |
40 | POLLWRNORM | POLLWRBAND); | 40 | POLLWRNORM | POLLWRBAND); |
41 | if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) | 41 | if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) |
42 | sock_wake_async(sock, SOCK_WAKE_SPACE, POLL_OUT); | 42 | sock_wake_async(wq, SOCK_WAKE_SPACE, POLL_OUT); |
43 | rcu_read_unlock(); | 43 | rcu_read_unlock(); |
44 | } | 44 | } |
45 | } | 45 | } |
@@ -126,7 +126,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) | |||
126 | current_timeo = vm_wait = (prandom_u32() % (HZ / 5)) + 2; | 126 | current_timeo = vm_wait = (prandom_u32() % (HZ / 5)) + 2; |
127 | 127 | ||
128 | while (1) { | 128 | while (1) { |
129 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 129 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
130 | 130 | ||
131 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 131 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
132 | 132 | ||
@@ -139,7 +139,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) | |||
139 | } | 139 | } |
140 | if (signal_pending(current)) | 140 | if (signal_pending(current)) |
141 | goto do_interrupted; | 141 | goto do_interrupted; |
142 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 142 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
143 | if (sk_stream_memory_free(sk) && !vm_wait) | 143 | if (sk_stream_memory_free(sk) && !vm_wait) |
144 | break; | 144 | break; |
145 | 145 | ||
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index db5fc2440a23..9c6d0508e63a 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -202,7 +202,9 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req | |||
202 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); | 202 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); |
203 | 203 | ||
204 | 204 | ||
205 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 205 | rcu_read_lock(); |
206 | final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); | ||
207 | rcu_read_unlock(); | ||
206 | 208 | ||
207 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p); | 209 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p); |
208 | if (IS_ERR(dst)) { | 210 | if (IS_ERR(dst)) { |
@@ -219,7 +221,10 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req | |||
219 | &ireq->ir_v6_loc_addr, | 221 | &ireq->ir_v6_loc_addr, |
220 | &ireq->ir_v6_rmt_addr); | 222 | &ireq->ir_v6_rmt_addr); |
221 | fl6.daddr = ireq->ir_v6_rmt_addr; | 223 | fl6.daddr = ireq->ir_v6_rmt_addr; |
222 | err = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); | 224 | rcu_read_lock(); |
225 | err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), | ||
226 | np->tclass); | ||
227 | rcu_read_unlock(); | ||
223 | err = net_xmit_eval(err); | 228 | err = net_xmit_eval(err); |
224 | } | 229 | } |
225 | 230 | ||
@@ -387,6 +392,7 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, | |||
387 | struct inet_request_sock *ireq = inet_rsk(req); | 392 | struct inet_request_sock *ireq = inet_rsk(req); |
388 | struct ipv6_pinfo *newnp; | 393 | struct ipv6_pinfo *newnp; |
389 | const struct ipv6_pinfo *np = inet6_sk(sk); | 394 | const struct ipv6_pinfo *np = inet6_sk(sk); |
395 | struct ipv6_txoptions *opt; | ||
390 | struct inet_sock *newinet; | 396 | struct inet_sock *newinet; |
391 | struct dccp6_sock *newdp6; | 397 | struct dccp6_sock *newdp6; |
392 | struct sock *newsk; | 398 | struct sock *newsk; |
@@ -453,7 +459,7 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, | |||
453 | * comment in that function for the gory details. -acme | 459 | * comment in that function for the gory details. -acme |
454 | */ | 460 | */ |
455 | 461 | ||
456 | __ip6_dst_store(newsk, dst, NULL, NULL); | 462 | ip6_dst_store(newsk, dst, NULL, NULL); |
457 | newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM | | 463 | newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM | |
458 | NETIF_F_TSO); | 464 | NETIF_F_TSO); |
459 | newdp6 = (struct dccp6_sock *)newsk; | 465 | newdp6 = (struct dccp6_sock *)newsk; |
@@ -488,13 +494,15 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, | |||
488 | * Yes, keeping reference count would be much more clever, but we make | 494 | * Yes, keeping reference count would be much more clever, but we make |
489 | * one more one thing there: reattach optmem to newsk. | 495 | * one more one thing there: reattach optmem to newsk. |
490 | */ | 496 | */ |
491 | if (np->opt != NULL) | 497 | opt = rcu_dereference(np->opt); |
492 | newnp->opt = ipv6_dup_options(newsk, np->opt); | 498 | if (opt) { |
493 | 499 | opt = ipv6_dup_options(newsk, opt); | |
500 | RCU_INIT_POINTER(newnp->opt, opt); | ||
501 | } | ||
494 | inet_csk(newsk)->icsk_ext_hdr_len = 0; | 502 | inet_csk(newsk)->icsk_ext_hdr_len = 0; |
495 | if (newnp->opt != NULL) | 503 | if (opt) |
496 | inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + | 504 | inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + |
497 | newnp->opt->opt_flen); | 505 | opt->opt_flen; |
498 | 506 | ||
499 | dccp_sync_mss(newsk, dst_mtu(dst)); | 507 | dccp_sync_mss(newsk, dst_mtu(dst)); |
500 | 508 | ||
@@ -757,6 +765,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
757 | struct ipv6_pinfo *np = inet6_sk(sk); | 765 | struct ipv6_pinfo *np = inet6_sk(sk); |
758 | struct dccp_sock *dp = dccp_sk(sk); | 766 | struct dccp_sock *dp = dccp_sk(sk); |
759 | struct in6_addr *saddr = NULL, *final_p, final; | 767 | struct in6_addr *saddr = NULL, *final_p, final; |
768 | struct ipv6_txoptions *opt; | ||
760 | struct flowi6 fl6; | 769 | struct flowi6 fl6; |
761 | struct dst_entry *dst; | 770 | struct dst_entry *dst; |
762 | int addr_type; | 771 | int addr_type; |
@@ -856,7 +865,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
856 | fl6.fl6_sport = inet->inet_sport; | 865 | fl6.fl6_sport = inet->inet_sport; |
857 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 866 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
858 | 867 | ||
859 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 868 | opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); |
869 | final_p = fl6_update_dst(&fl6, opt, &final); | ||
860 | 870 | ||
861 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p); | 871 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p); |
862 | if (IS_ERR(dst)) { | 872 | if (IS_ERR(dst)) { |
@@ -873,12 +883,11 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
873 | np->saddr = *saddr; | 883 | np->saddr = *saddr; |
874 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; | 884 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
875 | 885 | ||
876 | __ip6_dst_store(sk, dst, NULL, NULL); | 886 | ip6_dst_store(sk, dst, NULL, NULL); |
877 | 887 | ||
878 | icsk->icsk_ext_hdr_len = 0; | 888 | icsk->icsk_ext_hdr_len = 0; |
879 | if (np->opt != NULL) | 889 | if (opt) |
880 | icsk->icsk_ext_hdr_len = (np->opt->opt_flen + | 890 | icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; |
881 | np->opt->opt_nflen); | ||
882 | 891 | ||
883 | inet->inet_dport = usin->sin6_port; | 892 | inet->inet_dport = usin->sin6_port; |
884 | 893 | ||
diff --git a/net/dccp/output.c b/net/dccp/output.c index 4ce912e691d0..b66c84db0766 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -201,7 +201,7 @@ void dccp_write_space(struct sock *sk) | |||
201 | 201 | ||
202 | rcu_read_lock(); | 202 | rcu_read_lock(); |
203 | wq = rcu_dereference(sk->sk_wq); | 203 | wq = rcu_dereference(sk->sk_wq); |
204 | if (wq_has_sleeper(wq)) | 204 | if (skwq_has_sleeper(wq)) |
205 | wake_up_interruptible(&wq->wait); | 205 | wake_up_interruptible(&wq->wait); |
206 | /* Should agree with poll, otherwise some programs break */ | 206 | /* Should agree with poll, otherwise some programs break */ |
207 | if (sock_writeable(sk)) | 207 | if (sock_writeable(sk)) |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index b5cf13a28009..41e65804ddf5 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -339,8 +339,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock, | |||
339 | if (sk_stream_is_writeable(sk)) { | 339 | if (sk_stream_is_writeable(sk)) { |
340 | mask |= POLLOUT | POLLWRNORM; | 340 | mask |= POLLOUT | POLLWRNORM; |
341 | } else { /* send SIGIO later */ | 341 | } else { /* send SIGIO later */ |
342 | set_bit(SOCK_ASYNC_NOSPACE, | 342 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
343 | &sk->sk_socket->flags); | ||
344 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | 343 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
345 | 344 | ||
346 | /* Race breaker. If space is freed after | 345 | /* Race breaker. If space is freed after |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 675cf94e04f8..13d6b1a6e0fc 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -678,6 +678,9 @@ static int dn_create(struct net *net, struct socket *sock, int protocol, | |||
678 | { | 678 | { |
679 | struct sock *sk; | 679 | struct sock *sk; |
680 | 680 | ||
681 | if (protocol < 0 || protocol > SK_PROTOCOL_MAX) | ||
682 | return -EINVAL; | ||
683 | |||
681 | if (!net_eq(net, &init_net)) | 684 | if (!net_eq(net, &init_net)) |
682 | return -EAFNOSUPPORT; | 685 | return -EAFNOSUPPORT; |
683 | 686 | ||
@@ -1747,9 +1750,9 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | |||
1747 | } | 1750 | } |
1748 | 1751 | ||
1749 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 1752 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1750 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1753 | sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
1751 | sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target)); | 1754 | sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target)); |
1752 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1755 | sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
1753 | finish_wait(sk_sleep(sk), &wait); | 1756 | finish_wait(sk_sleep(sk), &wait); |
1754 | } | 1757 | } |
1755 | 1758 | ||
@@ -2004,10 +2007,10 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) | |||
2004 | } | 2007 | } |
2005 | 2008 | ||
2006 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 2009 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
2007 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2010 | sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
2008 | sk_wait_event(sk, &timeo, | 2011 | sk_wait_event(sk, &timeo, |
2009 | !dn_queue_too_long(scp, queue, flags)); | 2012 | !dn_queue_too_long(scp, queue, flags)); |
2010 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2013 | sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
2011 | finish_wait(sk_sleep(sk), &wait); | 2014 | finish_wait(sk_sleep(sk), &wait); |
2012 | continue; | 2015 | continue; |
2013 | } | 2016 | } |
diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c index 4677b6fa6dda..ecc28cff08ab 100644 --- a/net/dns_resolver/dns_query.c +++ b/net/dns_resolver/dns_query.c | |||
@@ -67,7 +67,7 @@ | |||
67 | * Returns the size of the result on success, -ve error code otherwise. | 67 | * Returns the size of the result on success, -ve error code otherwise. |
68 | */ | 68 | */ |
69 | int dns_query(const char *type, const char *name, size_t namelen, | 69 | int dns_query(const char *type, const char *name, size_t namelen, |
70 | const char *options, char **_result, time_t *_expiry) | 70 | const char *options, char **_result, time64_t *_expiry) |
71 | { | 71 | { |
72 | struct key *rkey; | 72 | struct key *rkey; |
73 | const struct user_key_payload *upayload; | 73 | const struct user_key_payload *upayload; |
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 1eba07feb34a..fa4daba8db55 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
@@ -21,8 +21,10 @@ | |||
21 | #include <linux/of_mdio.h> | 21 | #include <linux/of_mdio.h> |
22 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
23 | #include <linux/of_net.h> | 23 | #include <linux/of_net.h> |
24 | #include <linux/of_gpio.h> | ||
24 | #include <linux/sysfs.h> | 25 | #include <linux/sysfs.h> |
25 | #include <linux/phy_fixed.h> | 26 | #include <linux/phy_fixed.h> |
27 | #include <linux/gpio/consumer.h> | ||
26 | #include "dsa_priv.h" | 28 | #include "dsa_priv.h" |
27 | 29 | ||
28 | char dsa_driver_version[] = "0.1"; | 30 | char dsa_driver_version[] = "0.1"; |
@@ -437,7 +439,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds) | |||
437 | if (of_phy_is_fixed_link(port_dn)) { | 439 | if (of_phy_is_fixed_link(port_dn)) { |
438 | phydev = of_phy_find_device(port_dn); | 440 | phydev = of_phy_find_device(port_dn); |
439 | if (phydev) { | 441 | if (phydev) { |
440 | int addr = phydev->addr; | 442 | int addr = phydev->mdio.addr; |
441 | 443 | ||
442 | phy_device_free(phydev); | 444 | phy_device_free(phydev); |
443 | of_node_put(port_dn); | 445 | of_node_put(port_dn); |
@@ -454,8 +456,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds) | |||
454 | if (!ds->ports[port]) | 456 | if (!ds->ports[port]) |
455 | continue; | 457 | continue; |
456 | 458 | ||
457 | unregister_netdev(ds->ports[port]); | 459 | dsa_slave_destroy(ds->ports[port]); |
458 | free_netdev(ds->ports[port]); | ||
459 | } | 460 | } |
460 | 461 | ||
461 | mdiobus_unregister(ds->slave_mii_bus); | 462 | mdiobus_unregister(ds->slave_mii_bus); |
@@ -506,33 +507,6 @@ static int dsa_switch_resume(struct dsa_switch *ds) | |||
506 | } | 507 | } |
507 | #endif | 508 | #endif |
508 | 509 | ||
509 | |||
510 | /* link polling *************************************************************/ | ||
511 | static void dsa_link_poll_work(struct work_struct *ugly) | ||
512 | { | ||
513 | struct dsa_switch_tree *dst; | ||
514 | int i; | ||
515 | |||
516 | dst = container_of(ugly, struct dsa_switch_tree, link_poll_work); | ||
517 | |||
518 | for (i = 0; i < dst->pd->nr_chips; i++) { | ||
519 | struct dsa_switch *ds = dst->ds[i]; | ||
520 | |||
521 | if (ds != NULL && ds->drv->poll_link != NULL) | ||
522 | ds->drv->poll_link(ds); | ||
523 | } | ||
524 | |||
525 | mod_timer(&dst->link_poll_timer, round_jiffies(jiffies + HZ)); | ||
526 | } | ||
527 | |||
528 | static void dsa_link_poll_timer(unsigned long _dst) | ||
529 | { | ||
530 | struct dsa_switch_tree *dst = (void *)_dst; | ||
531 | |||
532 | schedule_work(&dst->link_poll_work); | ||
533 | } | ||
534 | |||
535 | |||
536 | /* platform driver init and cleanup *****************************************/ | 510 | /* platform driver init and cleanup *****************************************/ |
537 | static int dev_is_class(struct device *dev, void *class) | 511 | static int dev_is_class(struct device *dev, void *class) |
538 | { | 512 | { |
@@ -688,6 +662,9 @@ static int dsa_of_probe(struct device *dev) | |||
688 | const char *port_name; | 662 | const char *port_name; |
689 | int chip_index, port_index; | 663 | int chip_index, port_index; |
690 | const unsigned int *sw_addr, *port_reg; | 664 | const unsigned int *sw_addr, *port_reg; |
665 | int gpio; | ||
666 | enum of_gpio_flags of_flags; | ||
667 | unsigned long flags; | ||
691 | u32 eeprom_len; | 668 | u32 eeprom_len; |
692 | int ret; | 669 | int ret; |
693 | 670 | ||
@@ -766,6 +743,19 @@ static int dsa_of_probe(struct device *dev) | |||
766 | put_device(cd->host_dev); | 743 | put_device(cd->host_dev); |
767 | cd->host_dev = &mdio_bus_switch->dev; | 744 | cd->host_dev = &mdio_bus_switch->dev; |
768 | } | 745 | } |
746 | gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, | ||
747 | &of_flags); | ||
748 | if (gpio_is_valid(gpio)) { | ||
749 | flags = (of_flags == OF_GPIO_ACTIVE_LOW ? | ||
750 | GPIOF_ACTIVE_LOW : 0); | ||
751 | ret = devm_gpio_request_one(dev, gpio, flags, | ||
752 | "switch_reset"); | ||
753 | if (ret) | ||
754 | goto out_free_chip; | ||
755 | |||
756 | cd->reset = gpio_to_desc(gpio); | ||
757 | gpiod_direction_output(cd->reset, 0); | ||
758 | } | ||
769 | 759 | ||
770 | for_each_available_child_of_node(child, port) { | 760 | for_each_available_child_of_node(child, port) { |
771 | port_reg = of_get_property(port, "reg", NULL); | 761 | port_reg = of_get_property(port, "reg", NULL); |
@@ -859,8 +849,6 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev, | |||
859 | } | 849 | } |
860 | 850 | ||
861 | dst->ds[i] = ds; | 851 | dst->ds[i] = ds; |
862 | if (ds->drv->poll_link != NULL) | ||
863 | dst->link_poll_needed = 1; | ||
864 | 852 | ||
865 | ++configured; | 853 | ++configured; |
866 | } | 854 | } |
@@ -879,15 +867,6 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev, | |||
879 | wmb(); | 867 | wmb(); |
880 | dev->dsa_ptr = (void *)dst; | 868 | dev->dsa_ptr = (void *)dst; |
881 | 869 | ||
882 | if (dst->link_poll_needed) { | ||
883 | INIT_WORK(&dst->link_poll_work, dsa_link_poll_work); | ||
884 | init_timer(&dst->link_poll_timer); | ||
885 | dst->link_poll_timer.data = (unsigned long)dst; | ||
886 | dst->link_poll_timer.function = dsa_link_poll_timer; | ||
887 | dst->link_poll_timer.expires = round_jiffies(jiffies + HZ); | ||
888 | add_timer(&dst->link_poll_timer); | ||
889 | } | ||
890 | |||
891 | return 0; | 870 | return 0; |
892 | } | 871 | } |
893 | 872 | ||
@@ -939,8 +918,10 @@ static int dsa_probe(struct platform_device *pdev) | |||
939 | platform_set_drvdata(pdev, dst); | 918 | platform_set_drvdata(pdev, dst); |
940 | 919 | ||
941 | ret = dsa_setup_dst(dst, dev, &pdev->dev, pd); | 920 | ret = dsa_setup_dst(dst, dev, &pdev->dev, pd); |
942 | if (ret) | 921 | if (ret) { |
922 | dev_put(dev); | ||
943 | goto out; | 923 | goto out; |
924 | } | ||
944 | 925 | ||
945 | return 0; | 926 | return 0; |
946 | 927 | ||
@@ -954,17 +935,14 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst) | |||
954 | { | 935 | { |
955 | int i; | 936 | int i; |
956 | 937 | ||
957 | if (dst->link_poll_needed) | ||
958 | del_timer_sync(&dst->link_poll_timer); | ||
959 | |||
960 | flush_work(&dst->link_poll_work); | ||
961 | |||
962 | for (i = 0; i < dst->pd->nr_chips; i++) { | 938 | for (i = 0; i < dst->pd->nr_chips; i++) { |
963 | struct dsa_switch *ds = dst->ds[i]; | 939 | struct dsa_switch *ds = dst->ds[i]; |
964 | 940 | ||
965 | if (ds) | 941 | if (ds) |
966 | dsa_switch_destroy(ds); | 942 | dsa_switch_destroy(ds); |
967 | } | 943 | } |
944 | |||
945 | dev_put(dst->master_netdev); | ||
968 | } | 946 | } |
969 | 947 | ||
970 | static int dsa_remove(struct platform_device *pdev) | 948 | static int dsa_remove(struct platform_device *pdev) |
@@ -1010,6 +988,14 @@ static int dsa_suspend(struct device *d) | |||
1010 | struct dsa_switch_tree *dst = platform_get_drvdata(pdev); | 988 | struct dsa_switch_tree *dst = platform_get_drvdata(pdev); |
1011 | int i, ret = 0; | 989 | int i, ret = 0; |
1012 | 990 | ||
991 | dst->master_netdev->dsa_ptr = NULL; | ||
992 | |||
993 | /* If we used a tagging format that doesn't have an ethertype | ||
994 | * field, make sure that all packets from this point get sent | ||
995 | * without the tag and go through the regular receive path. | ||
996 | */ | ||
997 | wmb(); | ||
998 | |||
1013 | for (i = 0; i < dst->pd->nr_chips; i++) { | 999 | for (i = 0; i < dst->pd->nr_chips; i++) { |
1014 | struct dsa_switch *ds = dst->ds[i]; | 1000 | struct dsa_switch *ds = dst->ds[i]; |
1015 | 1001 | ||
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 311796c809af..1d1a54687e4a 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h | |||
@@ -61,6 +61,7 @@ extern const struct dsa_device_ops notag_netdev_ops; | |||
61 | void dsa_slave_mii_bus_init(struct dsa_switch *ds); | 61 | void dsa_slave_mii_bus_init(struct dsa_switch *ds); |
62 | int dsa_slave_create(struct dsa_switch *ds, struct device *parent, | 62 | int dsa_slave_create(struct dsa_switch *ds, struct device *parent, |
63 | int port, char *name); | 63 | int port, char *name); |
64 | void dsa_slave_destroy(struct net_device *slave_dev); | ||
64 | int dsa_slave_suspend(struct net_device *slave_dev); | 65 | int dsa_slave_suspend(struct net_device *slave_dev); |
65 | int dsa_slave_resume(struct net_device *slave_dev); | 66 | int dsa_slave_resume(struct net_device *slave_dev); |
66 | int dsa_slave_netdevice_event(struct notifier_block *unused, | 67 | int dsa_slave_netdevice_event(struct notifier_block *unused, |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 7bc787b095c8..40b9ca72aae3 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/phy_fixed.h> | 15 | #include <linux/phy_fixed.h> |
16 | #include <linux/of_net.h> | 16 | #include <linux/of_net.h> |
17 | #include <linux/of_mdio.h> | 17 | #include <linux/of_mdio.h> |
18 | #include <linux/mdio.h> | ||
18 | #include <net/rtnetlink.h> | 19 | #include <net/rtnetlink.h> |
19 | #include <net/switchdev.h> | 20 | #include <net/switchdev.h> |
20 | #include <linux/if_bridge.h> | 21 | #include <linux/if_bridge.h> |
@@ -997,7 +998,7 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p, | |||
997 | { | 998 | { |
998 | struct dsa_switch *ds = p->parent; | 999 | struct dsa_switch *ds = p->parent; |
999 | 1000 | ||
1000 | p->phy = ds->slave_mii_bus->phy_map[addr]; | 1001 | p->phy = mdiobus_get_phy(ds->slave_mii_bus, addr); |
1001 | if (!p->phy) { | 1002 | if (!p->phy) { |
1002 | netdev_err(slave_dev, "no phy at %d\n", addr); | 1003 | netdev_err(slave_dev, "no phy at %d\n", addr); |
1003 | return -ENODEV; | 1004 | return -ENODEV; |
@@ -1080,11 +1081,10 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, | |||
1080 | netdev_err(slave_dev, "failed to connect to port %d: %d\n", p->port, ret); | 1081 | netdev_err(slave_dev, "failed to connect to port %d: %d\n", p->port, ret); |
1081 | return ret; | 1082 | return ret; |
1082 | } | 1083 | } |
1083 | } else { | ||
1084 | netdev_info(slave_dev, "attached PHY at address %d [%s]\n", | ||
1085 | p->phy->addr, p->phy->drv->name); | ||
1086 | } | 1084 | } |
1087 | 1085 | ||
1086 | phy_attached_info(p->phy); | ||
1087 | |||
1088 | return 0; | 1088 | return 0; |
1089 | } | 1089 | } |
1090 | 1090 | ||
@@ -1189,13 +1189,6 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, | |||
1189 | p->old_link = -1; | 1189 | p->old_link = -1; |
1190 | p->old_duplex = -1; | 1190 | p->old_duplex = -1; |
1191 | 1191 | ||
1192 | ret = dsa_slave_phy_setup(p, slave_dev); | ||
1193 | if (ret) { | ||
1194 | netdev_err(master, "error %d setting up slave phy\n", ret); | ||
1195 | free_netdev(slave_dev); | ||
1196 | return ret; | ||
1197 | } | ||
1198 | |||
1199 | ds->ports[port] = slave_dev; | 1192 | ds->ports[port] = slave_dev; |
1200 | ret = register_netdev(slave_dev); | 1193 | ret = register_netdev(slave_dev); |
1201 | if (ret) { | 1194 | if (ret) { |
@@ -1209,9 +1202,27 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, | |||
1209 | 1202 | ||
1210 | netif_carrier_off(slave_dev); | 1203 | netif_carrier_off(slave_dev); |
1211 | 1204 | ||
1205 | ret = dsa_slave_phy_setup(p, slave_dev); | ||
1206 | if (ret) { | ||
1207 | netdev_err(master, "error %d setting up slave phy\n", ret); | ||
1208 | free_netdev(slave_dev); | ||
1209 | return ret; | ||
1210 | } | ||
1211 | |||
1212 | return 0; | 1212 | return 0; |
1213 | } | 1213 | } |
1214 | 1214 | ||
1215 | void dsa_slave_destroy(struct net_device *slave_dev) | ||
1216 | { | ||
1217 | struct dsa_slave_priv *p = netdev_priv(slave_dev); | ||
1218 | |||
1219 | netif_carrier_off(slave_dev); | ||
1220 | if (p->phy) | ||
1221 | phy_disconnect(p->phy); | ||
1222 | unregister_netdev(slave_dev); | ||
1223 | free_netdev(slave_dev); | ||
1224 | } | ||
1225 | |||
1215 | static bool dsa_slave_dev_check(struct net_device *dev) | 1226 | static bool dsa_slave_dev_check(struct net_device *dev) |
1216 | { | 1227 | { |
1217 | return dev->netdev_ops == &dsa_slave_netdev_ops; | 1228 | return dev->netdev_ops == &dsa_slave_netdev_ops; |
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 9e63f252a89e..103871784e50 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -52,6 +52,8 @@ | |||
52 | #include <linux/errno.h> | 52 | #include <linux/errno.h> |
53 | #include <linux/init.h> | 53 | #include <linux/init.h> |
54 | #include <linux/if_ether.h> | 54 | #include <linux/if_ether.h> |
55 | #include <linux/of_net.h> | ||
56 | #include <linux/pci.h> | ||
55 | #include <net/dst.h> | 57 | #include <net/dst.h> |
56 | #include <net/arp.h> | 58 | #include <net/arp.h> |
57 | #include <net/sock.h> | 59 | #include <net/sock.h> |
@@ -485,3 +487,32 @@ static int __init eth_offload_init(void) | |||
485 | } | 487 | } |
486 | 488 | ||
487 | fs_initcall(eth_offload_init); | 489 | fs_initcall(eth_offload_init); |
490 | |||
491 | unsigned char * __weak arch_get_platform_mac_address(void) | ||
492 | { | ||
493 | return NULL; | ||
494 | } | ||
495 | |||
496 | int eth_platform_get_mac_address(struct device *dev, u8 *mac_addr) | ||
497 | { | ||
498 | const unsigned char *addr; | ||
499 | struct device_node *dp; | ||
500 | |||
501 | if (dev_is_pci(dev)) | ||
502 | dp = pci_device_to_OF_node(to_pci_dev(dev)); | ||
503 | else | ||
504 | dp = dev->of_node; | ||
505 | |||
506 | addr = NULL; | ||
507 | if (dp) | ||
508 | addr = of_get_mac_address(dp); | ||
509 | if (!addr) | ||
510 | addr = arch_get_platform_mac_address(); | ||
511 | |||
512 | if (!addr) | ||
513 | return -ENODEV; | ||
514 | |||
515 | ether_addr_copy(mac_addr, addr); | ||
516 | return 0; | ||
517 | } | ||
518 | EXPORT_SYMBOL(eth_platform_get_mac_address); | ||
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 35a9788bb3ae..c7d1adca30d8 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c | |||
@@ -312,7 +312,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master, u8 type) | |||
312 | return; | 312 | return; |
313 | 313 | ||
314 | out: | 314 | out: |
315 | WARN_ON_ONCE("HSR: Could not send supervision frame\n"); | 315 | WARN_ONCE(1, "HSR: Could not send supervision frame\n"); |
316 | kfree_skb(skb); | 316 | kfree_skb(skb); |
317 | } | 317 | } |
318 | 318 | ||
diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 20c49c724ba0..737c87a2a41e 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c | |||
@@ -161,9 +161,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev, | |||
161 | wdev->needed_headroom; | 161 | wdev->needed_headroom; |
162 | ldev->needed_tailroom = wdev->needed_tailroom; | 162 | ldev->needed_tailroom = wdev->needed_tailroom; |
163 | 163 | ||
164 | lowpan_netdev_setup(ldev, LOWPAN_LLTYPE_IEEE802154); | 164 | ret = lowpan_register_netdevice(ldev, LOWPAN_LLTYPE_IEEE802154); |
165 | |||
166 | ret = register_netdevice(ldev); | ||
167 | if (ret < 0) { | 165 | if (ret < 0) { |
168 | dev_put(wdev); | 166 | dev_put(wdev); |
169 | return ret; | 167 | return ret; |
@@ -180,7 +178,7 @@ static void lowpan_dellink(struct net_device *ldev, struct list_head *head) | |||
180 | ASSERT_RTNL(); | 178 | ASSERT_RTNL(); |
181 | 179 | ||
182 | wdev->ieee802154_ptr->lowpan_dev = NULL; | 180 | wdev->ieee802154_ptr->lowpan_dev = NULL; |
183 | unregister_netdevice(ldev); | 181 | lowpan_unregister_netdevice(ldev); |
184 | dev_put(wdev); | 182 | dev_put(wdev); |
185 | } | 183 | } |
186 | 184 | ||
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c index 6b437e8760d3..30d875dff6b5 100644 --- a/net/ieee802154/6lowpan/reassembly.c +++ b/net/ieee802154/6lowpan/reassembly.c | |||
@@ -624,7 +624,6 @@ int __init lowpan_net_frag_init(void) | |||
624 | lowpan_frags.hashfn = lowpan_hashfn; | 624 | lowpan_frags.hashfn = lowpan_hashfn; |
625 | lowpan_frags.constructor = lowpan_frag_init; | 625 | lowpan_frags.constructor = lowpan_frag_init; |
626 | lowpan_frags.destructor = NULL; | 626 | lowpan_frags.destructor = NULL; |
627 | lowpan_frags.skb_free = NULL; | ||
628 | lowpan_frags.qsize = sizeof(struct frag_queue); | 627 | lowpan_frags.qsize = sizeof(struct frag_queue); |
629 | lowpan_frags.match = lowpan_frag_match; | 628 | lowpan_frags.match = lowpan_frag_match; |
630 | lowpan_frags.frag_expire = lowpan_frag_expire; | 629 | lowpan_frags.frag_expire = lowpan_frag_expire; |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 416dfa004cfb..c22920525e5d 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -436,6 +436,19 @@ config INET_UDP_DIAG | |||
436 | Support for UDP socket monitoring interface used by the ss tool. | 436 | Support for UDP socket monitoring interface used by the ss tool. |
437 | If unsure, say Y. | 437 | If unsure, say Y. |
438 | 438 | ||
439 | config INET_DIAG_DESTROY | ||
440 | bool "INET: allow privileged process to administratively close sockets" | ||
441 | depends on INET_DIAG | ||
442 | default n | ||
443 | ---help--- | ||
444 | Provides a SOCK_DESTROY operation that allows privileged processes | ||
445 | (e.g., a connection manager or a network administration tool such as | ||
446 | ss) to close sockets opened by other processes. Closing a socket in | ||
447 | this way interrupts any blocking read/write/connect operations on | ||
448 | the socket and causes future socket calls to behave as if the socket | ||
449 | had been disconnected. | ||
450 | If unsure, say N. | ||
451 | |||
439 | menuconfig TCP_CONG_ADVANCED | 452 | menuconfig TCP_CONG_ADVANCED |
440 | bool "TCP: advanced congestion control" | 453 | bool "TCP: advanced congestion control" |
441 | ---help--- | 454 | ---help--- |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 11c4ca13ec3b..5c5db6636704 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -257,6 +257,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol, | |||
257 | int try_loading_module = 0; | 257 | int try_loading_module = 0; |
258 | int err; | 258 | int err; |
259 | 259 | ||
260 | if (protocol < 0 || protocol >= IPPROTO_MAX) | ||
261 | return -EINVAL; | ||
262 | |||
260 | sock->state = SS_UNCONNECTED; | 263 | sock->state = SS_UNCONNECTED; |
261 | 264 | ||
262 | /* Look for the requested type/protocol pair. */ | 265 | /* Look for the requested type/protocol pair. */ |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index cc8f3e506cde..473447593060 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -1155,6 +1155,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
1155 | static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1155 | static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1156 | { | 1156 | { |
1157 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 1157 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
1158 | struct netdev_notifier_changeupper_info *info; | ||
1158 | struct in_device *in_dev; | 1159 | struct in_device *in_dev; |
1159 | struct net *net = dev_net(dev); | 1160 | struct net *net = dev_net(dev); |
1160 | unsigned int flags; | 1161 | unsigned int flags; |
@@ -1193,6 +1194,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
1193 | case NETDEV_CHANGEMTU: | 1194 | case NETDEV_CHANGEMTU: |
1194 | rt_cache_flush(net); | 1195 | rt_cache_flush(net); |
1195 | break; | 1196 | break; |
1197 | case NETDEV_CHANGEUPPER: | ||
1198 | info = ptr; | ||
1199 | /* flush all routes if dev is linked to or unlinked from | ||
1200 | * an L3 master device (e.g., VRF) | ||
1201 | */ | ||
1202 | if (info->upper_dev && netif_is_l3_master(info->upper_dev)) | ||
1203 | fib_disable_ip(dev, NETDEV_DOWN, true); | ||
1204 | break; | ||
1196 | } | 1205 | } |
1197 | return NOTIFY_DONE; | 1206 | return NOTIFY_DONE; |
1198 | } | 1207 | } |
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index e0fcbbbcfe54..976f0dcf6991 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c | |||
@@ -24,6 +24,7 @@ struct fou { | |||
24 | u16 type; | 24 | u16 type; |
25 | struct udp_offload udp_offloads; | 25 | struct udp_offload udp_offloads; |
26 | struct list_head list; | 26 | struct list_head list; |
27 | struct rcu_head rcu; | ||
27 | }; | 28 | }; |
28 | 29 | ||
29 | #define FOU_F_REMCSUM_NOPARTIAL BIT(0) | 30 | #define FOU_F_REMCSUM_NOPARTIAL BIT(0) |
@@ -417,7 +418,7 @@ static void fou_release(struct fou *fou) | |||
417 | list_del(&fou->list); | 418 | list_del(&fou->list); |
418 | udp_tunnel_sock_release(sock); | 419 | udp_tunnel_sock_release(sock); |
419 | 420 | ||
420 | kfree(fou); | 421 | kfree_rcu(fou, rcu); |
421 | } | 422 | } |
422 | 423 | ||
423 | static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg) | 424 | static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg) |
@@ -497,7 +498,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, | |||
497 | sk->sk_allocation = GFP_ATOMIC; | 498 | sk->sk_allocation = GFP_ATOMIC; |
498 | 499 | ||
499 | if (cfg->udp_config.family == AF_INET) { | 500 | if (cfg->udp_config.family == AF_INET) { |
500 | err = udp_add_offload(&fou->udp_offloads); | 501 | err = udp_add_offload(net, &fou->udp_offloads); |
501 | if (err) | 502 | if (err) |
502 | goto error; | 503 | goto error; |
503 | } | 504 | } |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 6baf36e11808..05e4cba14162 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -2126,7 +2126,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) | |||
2126 | ASSERT_RTNL(); | 2126 | ASSERT_RTNL(); |
2127 | 2127 | ||
2128 | in_dev = ip_mc_find_dev(net, imr); | 2128 | in_dev = ip_mc_find_dev(net, imr); |
2129 | if (!in_dev) { | 2129 | if (!imr->imr_ifindex && !imr->imr_address.s_addr && !in_dev) { |
2130 | ret = -ENODEV; | 2130 | ret = -ENODEV; |
2131 | goto out; | 2131 | goto out; |
2132 | } | 2132 | } |
@@ -2147,7 +2147,8 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) | |||
2147 | 2147 | ||
2148 | *imlp = iml->next_rcu; | 2148 | *imlp = iml->next_rcu; |
2149 | 2149 | ||
2150 | ip_mc_dec_group(in_dev, group); | 2150 | if (in_dev) |
2151 | ip_mc_dec_group(in_dev, group); | ||
2151 | 2152 | ||
2152 | /* decrease mem now to avoid the memleak warning */ | 2153 | /* decrease mem now to avoid the memleak warning */ |
2153 | atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); | 2154 | atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index ab9f8a66615d..8bb8e7ad8548 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -350,17 +350,12 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, | |||
350 | nlmsg_flags, unlh); | 350 | nlmsg_flags, unlh); |
351 | } | 351 | } |
352 | 352 | ||
353 | int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, | 353 | struct sock *inet_diag_find_one_icsk(struct net *net, |
354 | struct sk_buff *in_skb, | 354 | struct inet_hashinfo *hashinfo, |
355 | const struct nlmsghdr *nlh, | 355 | const struct inet_diag_req_v2 *req) |
356 | const struct inet_diag_req_v2 *req) | ||
357 | { | 356 | { |
358 | struct net *net = sock_net(in_skb->sk); | ||
359 | struct sk_buff *rep; | ||
360 | struct sock *sk; | 357 | struct sock *sk; |
361 | int err; | ||
362 | 358 | ||
363 | err = -EINVAL; | ||
364 | if (req->sdiag_family == AF_INET) | 359 | if (req->sdiag_family == AF_INET) |
365 | sk = inet_lookup(net, hashinfo, req->id.idiag_dst[0], | 360 | sk = inet_lookup(net, hashinfo, req->id.idiag_dst[0], |
366 | req->id.idiag_dport, req->id.idiag_src[0], | 361 | req->id.idiag_dport, req->id.idiag_src[0], |
@@ -375,15 +370,33 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, | |||
375 | req->id.idiag_if); | 370 | req->id.idiag_if); |
376 | #endif | 371 | #endif |
377 | else | 372 | else |
378 | goto out_nosk; | 373 | return ERR_PTR(-EINVAL); |
379 | 374 | ||
380 | err = -ENOENT; | ||
381 | if (!sk) | 375 | if (!sk) |
382 | goto out_nosk; | 376 | return ERR_PTR(-ENOENT); |
383 | 377 | ||
384 | err = sock_diag_check_cookie(sk, req->id.idiag_cookie); | 378 | if (sock_diag_check_cookie(sk, req->id.idiag_cookie)) { |
385 | if (err) | 379 | sock_gen_put(sk); |
386 | goto out; | 380 | return ERR_PTR(-ENOENT); |
381 | } | ||
382 | |||
383 | return sk; | ||
384 | } | ||
385 | EXPORT_SYMBOL_GPL(inet_diag_find_one_icsk); | ||
386 | |||
387 | int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, | ||
388 | struct sk_buff *in_skb, | ||
389 | const struct nlmsghdr *nlh, | ||
390 | const struct inet_diag_req_v2 *req) | ||
391 | { | ||
392 | struct net *net = sock_net(in_skb->sk); | ||
393 | struct sk_buff *rep; | ||
394 | struct sock *sk; | ||
395 | int err; | ||
396 | |||
397 | sk = inet_diag_find_one_icsk(net, hashinfo, req); | ||
398 | if (IS_ERR(sk)) | ||
399 | return PTR_ERR(sk); | ||
387 | 400 | ||
388 | rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL); | 401 | rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL); |
389 | if (!rep) { | 402 | if (!rep) { |
@@ -409,12 +422,11 @@ out: | |||
409 | if (sk) | 422 | if (sk) |
410 | sock_gen_put(sk); | 423 | sock_gen_put(sk); |
411 | 424 | ||
412 | out_nosk: | ||
413 | return err; | 425 | return err; |
414 | } | 426 | } |
415 | EXPORT_SYMBOL_GPL(inet_diag_dump_one_icsk); | 427 | EXPORT_SYMBOL_GPL(inet_diag_dump_one_icsk); |
416 | 428 | ||
417 | static int inet_diag_get_exact(struct sk_buff *in_skb, | 429 | static int inet_diag_cmd_exact(int cmd, struct sk_buff *in_skb, |
418 | const struct nlmsghdr *nlh, | 430 | const struct nlmsghdr *nlh, |
419 | const struct inet_diag_req_v2 *req) | 431 | const struct inet_diag_req_v2 *req) |
420 | { | 432 | { |
@@ -424,8 +436,12 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, | |||
424 | handler = inet_diag_lock_handler(req->sdiag_protocol); | 436 | handler = inet_diag_lock_handler(req->sdiag_protocol); |
425 | if (IS_ERR(handler)) | 437 | if (IS_ERR(handler)) |
426 | err = PTR_ERR(handler); | 438 | err = PTR_ERR(handler); |
427 | else | 439 | else if (cmd == SOCK_DIAG_BY_FAMILY) |
428 | err = handler->dump_one(in_skb, nlh, req); | 440 | err = handler->dump_one(in_skb, nlh, req); |
441 | else if (cmd == SOCK_DESTROY && handler->destroy) | ||
442 | err = handler->destroy(in_skb, req); | ||
443 | else | ||
444 | err = -EOPNOTSUPP; | ||
429 | inet_diag_unlock_handler(handler); | 445 | inet_diag_unlock_handler(handler); |
430 | 446 | ||
431 | return err; | 447 | return err; |
@@ -938,7 +954,7 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb, | |||
938 | req.idiag_states = rc->idiag_states; | 954 | req.idiag_states = rc->idiag_states; |
939 | req.id = rc->id; | 955 | req.id = rc->id; |
940 | 956 | ||
941 | return inet_diag_get_exact(in_skb, nlh, &req); | 957 | return inet_diag_cmd_exact(SOCK_DIAG_BY_FAMILY, in_skb, nlh, &req); |
942 | } | 958 | } |
943 | 959 | ||
944 | static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) | 960 | static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) |
@@ -972,7 +988,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
972 | return inet_diag_get_exact_compat(skb, nlh); | 988 | return inet_diag_get_exact_compat(skb, nlh); |
973 | } | 989 | } |
974 | 990 | ||
975 | static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | 991 | static int inet_diag_handler_cmd(struct sk_buff *skb, struct nlmsghdr *h) |
976 | { | 992 | { |
977 | int hdrlen = sizeof(struct inet_diag_req_v2); | 993 | int hdrlen = sizeof(struct inet_diag_req_v2); |
978 | struct net *net = sock_net(skb->sk); | 994 | struct net *net = sock_net(skb->sk); |
@@ -980,7 +996,8 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | |||
980 | if (nlmsg_len(h) < hdrlen) | 996 | if (nlmsg_len(h) < hdrlen) |
981 | return -EINVAL; | 997 | return -EINVAL; |
982 | 998 | ||
983 | if (h->nlmsg_flags & NLM_F_DUMP) { | 999 | if (h->nlmsg_type == SOCK_DIAG_BY_FAMILY && |
1000 | h->nlmsg_flags & NLM_F_DUMP) { | ||
984 | if (nlmsg_attrlen(h, hdrlen)) { | 1001 | if (nlmsg_attrlen(h, hdrlen)) { |
985 | struct nlattr *attr; | 1002 | struct nlattr *attr; |
986 | 1003 | ||
@@ -999,7 +1016,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | |||
999 | } | 1016 | } |
1000 | } | 1017 | } |
1001 | 1018 | ||
1002 | return inet_diag_get_exact(skb, h, nlmsg_data(h)); | 1019 | return inet_diag_cmd_exact(h->nlmsg_type, skb, h, nlmsg_data(h)); |
1003 | } | 1020 | } |
1004 | 1021 | ||
1005 | static | 1022 | static |
@@ -1050,14 +1067,16 @@ int inet_diag_handler_get_info(struct sk_buff *skb, struct sock *sk) | |||
1050 | 1067 | ||
1051 | static const struct sock_diag_handler inet_diag_handler = { | 1068 | static const struct sock_diag_handler inet_diag_handler = { |
1052 | .family = AF_INET, | 1069 | .family = AF_INET, |
1053 | .dump = inet_diag_handler_dump, | 1070 | .dump = inet_diag_handler_cmd, |
1054 | .get_info = inet_diag_handler_get_info, | 1071 | .get_info = inet_diag_handler_get_info, |
1072 | .destroy = inet_diag_handler_cmd, | ||
1055 | }; | 1073 | }; |
1056 | 1074 | ||
1057 | static const struct sock_diag_handler inet6_diag_handler = { | 1075 | static const struct sock_diag_handler inet6_diag_handler = { |
1058 | .family = AF_INET6, | 1076 | .family = AF_INET6, |
1059 | .dump = inet_diag_handler_dump, | 1077 | .dump = inet_diag_handler_cmd, |
1060 | .get_info = inet_diag_handler_get_info, | 1078 | .get_info = inet_diag_handler_get_info, |
1079 | .destroy = inet_diag_handler_cmd, | ||
1061 | }; | 1080 | }; |
1062 | 1081 | ||
1063 | int inet_diag_register(const struct inet_diag_handler *h) | 1082 | int inet_diag_register(const struct inet_diag_handler *h) |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index fe144dae7372..3a88b0c73797 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -285,14 +285,6 @@ void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f) | |||
285 | } | 285 | } |
286 | EXPORT_SYMBOL(inet_frag_kill); | 286 | EXPORT_SYMBOL(inet_frag_kill); |
287 | 287 | ||
288 | static inline void frag_kfree_skb(struct netns_frags *nf, struct inet_frags *f, | ||
289 | struct sk_buff *skb) | ||
290 | { | ||
291 | if (f->skb_free) | ||
292 | f->skb_free(skb); | ||
293 | kfree_skb(skb); | ||
294 | } | ||
295 | |||
296 | void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f) | 288 | void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f) |
297 | { | 289 | { |
298 | struct sk_buff *fp; | 290 | struct sk_buff *fp; |
@@ -309,7 +301,7 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f) | |||
309 | struct sk_buff *xp = fp->next; | 301 | struct sk_buff *xp = fp->next; |
310 | 302 | ||
311 | sum_truesize += fp->truesize; | 303 | sum_truesize += fp->truesize; |
312 | frag_kfree_skb(nf, f, fp); | 304 | kfree_skb(fp); |
313 | fp = xp; | 305 | fp = xp; |
314 | } | 306 | } |
315 | sum = sum_truesize + f->qsize; | 307 | sum = sum_truesize + f->qsize; |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 1fe55ae81781..3f00810b7288 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -891,7 +891,6 @@ void __init ipfrag_init(void) | |||
891 | ip4_frags.hashfn = ip4_hashfn; | 891 | ip4_frags.hashfn = ip4_hashfn; |
892 | ip4_frags.constructor = ip4_frag_init; | 892 | ip4_frags.constructor = ip4_frag_init; |
893 | ip4_frags.destructor = ip4_frag_free; | 893 | ip4_frags.destructor = ip4_frag_free; |
894 | ip4_frags.skb_free = NULL; | ||
895 | ip4_frags.qsize = sizeof(struct ipq); | 894 | ip4_frags.qsize = sizeof(struct ipq); |
896 | ip4_frags.match = ip4_frag_match; | 895 | ip4_frags.match = ip4_frag_match; |
897 | ip4_frags.frag_expire = ip_expire; | 896 | ip4_frags.frag_expire = ip_expire; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 614521437e30..7c51c4e1661f 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/tcp.h> | 24 | #include <linux/tcp.h> |
25 | #include <linux/udp.h> | 25 | #include <linux/udp.h> |
26 | #include <linux/if_arp.h> | 26 | #include <linux/if_arp.h> |
27 | #include <linux/mroute.h> | ||
28 | #include <linux/if_vlan.h> | 27 | #include <linux/if_vlan.h> |
29 | #include <linux/init.h> | 28 | #include <linux/init.h> |
30 | #include <linux/in6.h> | 29 | #include <linux/in6.h> |
@@ -562,10 +561,9 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) | |||
562 | tunnel_id_to_key(tun_info->key.tun_id), 0); | 561 | tunnel_id_to_key(tun_info->key.tun_id), 0); |
563 | 562 | ||
564 | df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; | 563 | df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; |
565 | err = iptunnel_xmit(skb->sk, rt, skb, fl.saddr, | 564 | |
566 | key->u.ipv4.dst, IPPROTO_GRE, | 565 | iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, |
567 | key->tos, key->ttl, df, false); | 566 | key->tos, key->ttl, df, false); |
568 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); | ||
569 | return; | 567 | return; |
570 | 568 | ||
571 | err_free_rt: | 569 | err_free_rt: |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4233cbe47052..512a44778cf2 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -76,7 +76,6 @@ | |||
76 | #include <linux/igmp.h> | 76 | #include <linux/igmp.h> |
77 | #include <linux/netfilter_ipv4.h> | 77 | #include <linux/netfilter_ipv4.h> |
78 | #include <linux/netfilter_bridge.h> | 78 | #include <linux/netfilter_bridge.h> |
79 | #include <linux/mroute.h> | ||
80 | #include <linux/netlink.h> | 79 | #include <linux/netlink.h> |
81 | #include <linux/tcp.h> | 80 | #include <linux/tcp.h> |
82 | 81 | ||
@@ -912,7 +911,7 @@ static int __ip_append_data(struct sock *sk, | |||
912 | */ | 911 | */ |
913 | if (transhdrlen && | 912 | if (transhdrlen && |
914 | length + fragheaderlen <= mtu && | 913 | length + fragheaderlen <= mtu && |
915 | rt->dst.dev->features & NETIF_F_V4_CSUM && | 914 | rt->dst.dev->features & (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM) && |
916 | !(flags & MSG_MORE) && | 915 | !(flags & MSG_MORE) && |
917 | !exthdrlen) | 916 | !exthdrlen) |
918 | csummode = CHECKSUM_PARTIAL; | 917 | csummode = CHECKSUM_PARTIAL; |
@@ -921,7 +920,7 @@ static int __ip_append_data(struct sock *sk, | |||
921 | if (((length > mtu) || (skb && skb_is_gso(skb))) && | 920 | if (((length > mtu) || (skb && skb_is_gso(skb))) && |
922 | (sk->sk_protocol == IPPROTO_UDP) && | 921 | (sk->sk_protocol == IPPROTO_UDP) && |
923 | (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && | 922 | (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && |
924 | (sk->sk_type == SOCK_DGRAM)) { | 923 | (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) { |
925 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, | 924 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, |
926 | hh_len, fragheaderlen, transhdrlen, | 925 | hh_len, fragheaderlen, transhdrlen, |
927 | maxfraglen, flags); | 926 | maxfraglen, flags); |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index cbb51f3fac06..c7bd72e9b544 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/tcp.h> | 30 | #include <linux/tcp.h> |
31 | #include <linux/udp.h> | 31 | #include <linux/udp.h> |
32 | #include <linux/if_arp.h> | 32 | #include <linux/if_arp.h> |
33 | #include <linux/mroute.h> | ||
34 | #include <linux/init.h> | 33 | #include <linux/init.h> |
35 | #include <linux/in6.h> | 34 | #include <linux/in6.h> |
36 | #include <linux/inetdevice.h> | 35 | #include <linux/inetdevice.h> |
@@ -657,7 +656,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
657 | struct rtable *rt; /* Route to the other host */ | 656 | struct rtable *rt; /* Route to the other host */ |
658 | unsigned int max_headroom; /* The extra header space needed */ | 657 | unsigned int max_headroom; /* The extra header space needed */ |
659 | __be32 dst; | 658 | __be32 dst; |
660 | int err; | ||
661 | bool connected; | 659 | bool connected; |
662 | 660 | ||
663 | inner_iph = (const struct iphdr *)skb_inner_network_header(skb); | 661 | inner_iph = (const struct iphdr *)skb_inner_network_header(skb); |
@@ -795,10 +793,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
795 | return; | 793 | return; |
796 | } | 794 | } |
797 | 795 | ||
798 | err = iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, | 796 | iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl, |
799 | tos, ttl, df, !net_eq(tunnel->net, dev_net(dev))); | 797 | df, !net_eq(tunnel->net, dev_net(dev))); |
800 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); | ||
801 | |||
802 | return; | 798 | return; |
803 | 799 | ||
804 | #if IS_ENABLED(CONFIG_IPV6) | 800 | #if IS_ENABLED(CONFIG_IPV6) |
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 6cb9009c3d96..859d415c0b2d 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
25 | #include <linux/in.h> | 25 | #include <linux/in.h> |
26 | #include <linux/if_arp.h> | 26 | #include <linux/if_arp.h> |
27 | #include <linux/mroute.h> | ||
28 | #include <linux/init.h> | 27 | #include <linux/init.h> |
29 | #include <linux/in6.h> | 28 | #include <linux/in6.h> |
30 | #include <linux/inetdevice.h> | 29 | #include <linux/inetdevice.h> |
@@ -48,12 +47,13 @@ | |||
48 | #include <net/rtnetlink.h> | 47 | #include <net/rtnetlink.h> |
49 | #include <net/dst_metadata.h> | 48 | #include <net/dst_metadata.h> |
50 | 49 | ||
51 | int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, | 50 | void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, |
52 | __be32 src, __be32 dst, __u8 proto, | 51 | __be32 src, __be32 dst, __u8 proto, |
53 | __u8 tos, __u8 ttl, __be16 df, bool xnet) | 52 | __u8 tos, __u8 ttl, __be16 df, bool xnet) |
54 | { | 53 | { |
55 | int pkt_len = skb->len - skb_inner_network_offset(skb); | 54 | int pkt_len = skb->len - skb_inner_network_offset(skb); |
56 | struct net *net = dev_net(rt->dst.dev); | 55 | struct net *net = dev_net(rt->dst.dev); |
56 | struct net_device *dev = skb->dev; | ||
57 | struct iphdr *iph; | 57 | struct iphdr *iph; |
58 | int err; | 58 | int err; |
59 | 59 | ||
@@ -82,7 +82,7 @@ int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, | |||
82 | err = ip_local_out(net, sk, skb); | 82 | err = ip_local_out(net, sk, skb); |
83 | if (unlikely(net_xmit_eval(err))) | 83 | if (unlikely(net_xmit_eval(err))) |
84 | pkt_len = 0; | 84 | pkt_len = 0; |
85 | return pkt_len; | 85 | iptunnel_xmit_stats(dev, pkt_len); |
86 | } | 86 | } |
87 | EXPORT_SYMBOL_GPL(iptunnel_xmit); | 87 | EXPORT_SYMBOL_GPL(iptunnel_xmit); |
88 | 88 | ||
@@ -251,7 +251,7 @@ static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr, | |||
251 | tun_info = lwt_tun_info(new_state); | 251 | tun_info = lwt_tun_info(new_state); |
252 | 252 | ||
253 | if (tb[LWTUNNEL_IP_ID]) | 253 | if (tb[LWTUNNEL_IP_ID]) |
254 | tun_info->key.tun_id = nla_get_u64(tb[LWTUNNEL_IP_ID]); | 254 | tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP_ID]); |
255 | 255 | ||
256 | if (tb[LWTUNNEL_IP_DST]) | 256 | if (tb[LWTUNNEL_IP_DST]) |
257 | tun_info->key.u.ipv4.dst = nla_get_be32(tb[LWTUNNEL_IP_DST]); | 257 | tun_info->key.u.ipv4.dst = nla_get_be32(tb[LWTUNNEL_IP_DST]); |
@@ -266,7 +266,7 @@ static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr, | |||
266 | tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP_TOS]); | 266 | tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP_TOS]); |
267 | 267 | ||
268 | if (tb[LWTUNNEL_IP_FLAGS]) | 268 | if (tb[LWTUNNEL_IP_FLAGS]) |
269 | tun_info->key.tun_flags = nla_get_u16(tb[LWTUNNEL_IP_FLAGS]); | 269 | tun_info->key.tun_flags = nla_get_be16(tb[LWTUNNEL_IP_FLAGS]); |
270 | 270 | ||
271 | tun_info->mode = IP_TUNNEL_INFO_TX; | 271 | tun_info->mode = IP_TUNNEL_INFO_TX; |
272 | tun_info->options_len = 0; | 272 | tun_info->options_len = 0; |
@@ -281,12 +281,12 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb, | |||
281 | { | 281 | { |
282 | struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate); | 282 | struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate); |
283 | 283 | ||
284 | if (nla_put_u64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id) || | 284 | if (nla_put_be64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id) || |
285 | nla_put_be32(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) || | 285 | nla_put_be32(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) || |
286 | nla_put_be32(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) || | 286 | nla_put_be32(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) || |
287 | nla_put_u8(skb, LWTUNNEL_IP_TOS, tun_info->key.tos) || | 287 | nla_put_u8(skb, LWTUNNEL_IP_TOS, tun_info->key.tos) || |
288 | nla_put_u8(skb, LWTUNNEL_IP_TTL, tun_info->key.ttl) || | 288 | nla_put_u8(skb, LWTUNNEL_IP_TTL, tun_info->key.ttl) || |
289 | nla_put_u16(skb, LWTUNNEL_IP_FLAGS, tun_info->key.tun_flags)) | 289 | nla_put_be16(skb, LWTUNNEL_IP_FLAGS, tun_info->key.tun_flags)) |
290 | return -ENOMEM; | 290 | return -ENOMEM; |
291 | 291 | ||
292 | return 0; | 292 | return 0; |
@@ -346,7 +346,7 @@ static int ip6_tun_build_state(struct net_device *dev, struct nlattr *attr, | |||
346 | tun_info = lwt_tun_info(new_state); | 346 | tun_info = lwt_tun_info(new_state); |
347 | 347 | ||
348 | if (tb[LWTUNNEL_IP6_ID]) | 348 | if (tb[LWTUNNEL_IP6_ID]) |
349 | tun_info->key.tun_id = nla_get_u64(tb[LWTUNNEL_IP6_ID]); | 349 | tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP6_ID]); |
350 | 350 | ||
351 | if (tb[LWTUNNEL_IP6_DST]) | 351 | if (tb[LWTUNNEL_IP6_DST]) |
352 | tun_info->key.u.ipv6.dst = nla_get_in6_addr(tb[LWTUNNEL_IP6_DST]); | 352 | tun_info->key.u.ipv6.dst = nla_get_in6_addr(tb[LWTUNNEL_IP6_DST]); |
@@ -361,7 +361,7 @@ static int ip6_tun_build_state(struct net_device *dev, struct nlattr *attr, | |||
361 | tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP6_TC]); | 361 | tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP6_TC]); |
362 | 362 | ||
363 | if (tb[LWTUNNEL_IP6_FLAGS]) | 363 | if (tb[LWTUNNEL_IP6_FLAGS]) |
364 | tun_info->key.tun_flags = nla_get_u16(tb[LWTUNNEL_IP6_FLAGS]); | 364 | tun_info->key.tun_flags = nla_get_be16(tb[LWTUNNEL_IP6_FLAGS]); |
365 | 365 | ||
366 | tun_info->mode = IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6; | 366 | tun_info->mode = IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6; |
367 | tun_info->options_len = 0; | 367 | tun_info->options_len = 0; |
@@ -376,12 +376,12 @@ static int ip6_tun_fill_encap_info(struct sk_buff *skb, | |||
376 | { | 376 | { |
377 | struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate); | 377 | struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate); |
378 | 378 | ||
379 | if (nla_put_u64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id) || | 379 | if (nla_put_be64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id) || |
380 | nla_put_in6_addr(skb, LWTUNNEL_IP6_DST, &tun_info->key.u.ipv6.dst) || | 380 | nla_put_in6_addr(skb, LWTUNNEL_IP6_DST, &tun_info->key.u.ipv6.dst) || |
381 | nla_put_in6_addr(skb, LWTUNNEL_IP6_SRC, &tun_info->key.u.ipv6.src) || | 381 | nla_put_in6_addr(skb, LWTUNNEL_IP6_SRC, &tun_info->key.u.ipv6.src) || |
382 | nla_put_u8(skb, LWTUNNEL_IP6_HOPLIMIT, tun_info->key.tos) || | 382 | nla_put_u8(skb, LWTUNNEL_IP6_HOPLIMIT, tun_info->key.tos) || |
383 | nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.ttl) || | 383 | nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.ttl) || |
384 | nla_put_u16(skb, LWTUNNEL_IP6_FLAGS, tun_info->key.tun_flags)) | 384 | nla_put_be16(skb, LWTUNNEL_IP6_FLAGS, tun_info->key.tun_flags)) |
385 | return -ENOMEM; | 385 | return -ENOMEM; |
386 | 386 | ||
387 | return 0; | 387 | return 0; |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 4d8f0b698777..5cf10b777b7e 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/tcp.h> | 30 | #include <linux/tcp.h> |
31 | #include <linux/udp.h> | 31 | #include <linux/udp.h> |
32 | #include <linux/if_arp.h> | 32 | #include <linux/if_arp.h> |
33 | #include <linux/mroute.h> | ||
34 | #include <linux/init.h> | 33 | #include <linux/init.h> |
35 | #include <linux/netfilter_ipv4.h> | 34 | #include <linux/netfilter_ipv4.h> |
36 | #include <linux/if_ether.h> | 35 | #include <linux/if_ether.h> |
@@ -200,7 +199,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, | |||
200 | err = dst_output(tunnel->net, skb->sk, skb); | 199 | err = dst_output(tunnel->net, skb->sk, skb); |
201 | if (net_xmit_eval(err) == 0) | 200 | if (net_xmit_eval(err) == 0) |
202 | err = skb->len; | 201 | err = skb->len; |
203 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); | 202 | iptunnel_xmit_stats(dev, err); |
204 | return NETDEV_TX_OK; | 203 | return NETDEV_TX_OK; |
205 | 204 | ||
206 | tx_error_icmp: | 205 | tx_error_icmp: |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 0bc7412d9e14..67f7c9de0b16 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -65,15 +65,6 @@ | |||
65 | #include <net/checksum.h> | 65 | #include <net/checksum.h> |
66 | #include <asm/processor.h> | 66 | #include <asm/processor.h> |
67 | 67 | ||
68 | /* Define this to allow debugging output */ | ||
69 | #undef IPCONFIG_DEBUG | ||
70 | |||
71 | #ifdef IPCONFIG_DEBUG | ||
72 | #define DBG(x) printk x | ||
73 | #else | ||
74 | #define DBG(x) do { } while(0) | ||
75 | #endif | ||
76 | |||
77 | #if defined(CONFIG_IP_PNP_DHCP) | 68 | #if defined(CONFIG_IP_PNP_DHCP) |
78 | #define IPCONFIG_DHCP | 69 | #define IPCONFIG_DHCP |
79 | #endif | 70 | #endif |
@@ -227,7 +218,7 @@ static int __init ic_open_devs(void) | |||
227 | if (dev->mtu >= 364) | 218 | if (dev->mtu >= 364) |
228 | able |= IC_BOOTP; | 219 | able |= IC_BOOTP; |
229 | else | 220 | else |
230 | pr_warn("DHCP/BOOTP: Ignoring device %s, MTU %d too small", | 221 | pr_warn("DHCP/BOOTP: Ignoring device %s, MTU %d too small\n", |
231 | dev->name, dev->mtu); | 222 | dev->name, dev->mtu); |
232 | if (!(dev->flags & IFF_NOARP)) | 223 | if (!(dev->flags & IFF_NOARP)) |
233 | able |= IC_RARP; | 224 | able |= IC_RARP; |
@@ -254,8 +245,8 @@ static int __init ic_open_devs(void) | |||
254 | else | 245 | else |
255 | d->xid = 0; | 246 | d->xid = 0; |
256 | ic_proto_have_if |= able; | 247 | ic_proto_have_if |= able; |
257 | DBG(("IP-Config: %s UP (able=%d, xid=%08x)\n", | 248 | pr_debug("IP-Config: %s UP (able=%d, xid=%08x)\n", |
258 | dev->name, able, d->xid)); | 249 | dev->name, able, d->xid); |
259 | } | 250 | } |
260 | } | 251 | } |
261 | 252 | ||
@@ -311,7 +302,7 @@ static void __init ic_close_devs(void) | |||
311 | next = d->next; | 302 | next = d->next; |
312 | dev = d->dev; | 303 | dev = d->dev; |
313 | if (dev != ic_dev && !netdev_uses_dsa(dev)) { | 304 | if (dev != ic_dev && !netdev_uses_dsa(dev)) { |
314 | DBG(("IP-Config: Downing %s\n", dev->name)); | 305 | pr_debug("IP-Config: Downing %s\n", dev->name); |
315 | dev_change_flags(dev, d->flags); | 306 | dev_change_flags(dev, d->flags); |
316 | } | 307 | } |
317 | kfree(d); | 308 | kfree(d); |
@@ -464,7 +455,8 @@ static int __init ic_defaults(void) | |||
464 | &ic_myaddr); | 455 | &ic_myaddr); |
465 | return -1; | 456 | return -1; |
466 | } | 457 | } |
467 | printk("IP-Config: Guessing netmask %pI4\n", &ic_netmask); | 458 | pr_notice("IP-Config: Guessing netmask %pI4\n", |
459 | &ic_netmask); | ||
468 | } | 460 | } |
469 | 461 | ||
470 | return 0; | 462 | return 0; |
@@ -675,9 +667,7 @@ ic_dhcp_init_options(u8 *options) | |||
675 | u8 *e = options; | 667 | u8 *e = options; |
676 | int len; | 668 | int len; |
677 | 669 | ||
678 | #ifdef IPCONFIG_DEBUG | 670 | pr_debug("DHCP: Sending message type %d\n", mt); |
679 | printk("DHCP: Sending message type %d\n", mt); | ||
680 | #endif | ||
681 | 671 | ||
682 | memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ | 672 | memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ |
683 | e += 4; | 673 | e += 4; |
@@ -847,7 +837,8 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d | |||
847 | else if (dev->type == ARPHRD_FDDI) | 837 | else if (dev->type == ARPHRD_FDDI) |
848 | b->htype = ARPHRD_ETHER; | 838 | b->htype = ARPHRD_ETHER; |
849 | else { | 839 | else { |
850 | printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name); | 840 | pr_warn("Unknown ARP type 0x%04x for device %s\n", dev->type, |
841 | dev->name); | ||
851 | b->htype = dev->type; /* can cause undefined behavior */ | 842 | b->htype = dev->type; /* can cause undefined behavior */ |
852 | } | 843 | } |
853 | 844 | ||
@@ -904,14 +895,12 @@ static void __init ic_do_bootp_ext(u8 *ext) | |||
904 | int i; | 895 | int i; |
905 | __be16 mtu; | 896 | __be16 mtu; |
906 | 897 | ||
907 | #ifdef IPCONFIG_DEBUG | ||
908 | u8 *c; | 898 | u8 *c; |
909 | 899 | ||
910 | printk("DHCP/BOOTP: Got extension %d:",*ext); | 900 | pr_debug("DHCP/BOOTP: Got extension %d:", *ext); |
911 | for (c=ext+2; c<ext+2+ext[1]; c++) | 901 | for (c=ext+2; c<ext+2+ext[1]; c++) |
912 | printk(" %02x", *c); | 902 | pr_debug(" %02x", *c); |
913 | printk("\n"); | 903 | pr_debug("\n"); |
914 | #endif | ||
915 | 904 | ||
916 | switch (*ext++) { | 905 | switch (*ext++) { |
917 | case 1: /* Subnet mask */ | 906 | case 1: /* Subnet mask */ |
@@ -1080,9 +1069,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str | |||
1080 | } | 1069 | } |
1081 | } | 1070 | } |
1082 | 1071 | ||
1083 | #ifdef IPCONFIG_DEBUG | 1072 | pr_debug("DHCP: Got message type %d\n", mt); |
1084 | printk("DHCP: Got message type %d\n", mt); | ||
1085 | #endif | ||
1086 | 1073 | ||
1087 | switch (mt) { | 1074 | switch (mt) { |
1088 | case DHCPOFFER: | 1075 | case DHCPOFFER: |
@@ -1095,10 +1082,8 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str | |||
1095 | /* Let's accept that offer. */ | 1082 | /* Let's accept that offer. */ |
1096 | ic_myaddr = b->your_ip; | 1083 | ic_myaddr = b->your_ip; |
1097 | ic_servaddr = server_id; | 1084 | ic_servaddr = server_id; |
1098 | #ifdef IPCONFIG_DEBUG | 1085 | pr_debug("DHCP: Offered address %pI4 by server %pI4\n", |
1099 | printk("DHCP: Offered address %pI4 by server %pI4\n", | 1086 | &ic_myaddr, &b->iph.saddr); |
1100 | &ic_myaddr, &b->iph.saddr); | ||
1101 | #endif | ||
1102 | /* The DHCP indicated server address takes | 1087 | /* The DHCP indicated server address takes |
1103 | * precedence over the bootp header one if | 1088 | * precedence over the bootp header one if |
1104 | * they are different. | 1089 | * they are different. |
@@ -1295,11 +1280,10 @@ static int __init ic_dynamic(void) | |||
1295 | return -1; | 1280 | return -1; |
1296 | } | 1281 | } |
1297 | 1282 | ||
1298 | printk("IP-Config: Got %s answer from %pI4, ", | 1283 | pr_info("IP-Config: Got %s answer from %pI4, my address is %pI4\n", |
1299 | ((ic_got_reply & IC_RARP) ? "RARP" | 1284 | ((ic_got_reply & IC_RARP) ? "RARP" |
1300 | : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"), | 1285 | : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"), |
1301 | &ic_addrservaddr); | 1286 | &ic_addrservaddr, &ic_myaddr); |
1302 | pr_cont("my address is %pI4\n", &ic_myaddr); | ||
1303 | 1287 | ||
1304 | return 0; | 1288 | return 0; |
1305 | } | 1289 | } |
@@ -1426,7 +1410,7 @@ static int __init ip_auto_config(void) | |||
1426 | if (!ic_enable) | 1410 | if (!ic_enable) |
1427 | return 0; | 1411 | return 0; |
1428 | 1412 | ||
1429 | DBG(("IP-Config: Entered.\n")); | 1413 | pr_debug("IP-Config: Entered.\n"); |
1430 | #ifdef IPCONFIG_DYNAMIC | 1414 | #ifdef IPCONFIG_DYNAMIC |
1431 | try_try_again: | 1415 | try_try_again: |
1432 | #endif | 1416 | #endif |
@@ -1542,7 +1526,7 @@ static int __init ip_auto_config(void) | |||
1542 | pr_cont(", mtu=%d", ic_dev_mtu); | 1526 | pr_cont(", mtu=%d", ic_dev_mtu); |
1543 | for (i = 0; i < CONF_NAMESERVERS_MAX; i++) | 1527 | for (i = 0; i < CONF_NAMESERVERS_MAX; i++) |
1544 | if (ic_nameservers[i] != NONE) { | 1528 | if (ic_nameservers[i] != NONE) { |
1545 | pr_info(" nameserver%u=%pI4", | 1529 | pr_cont(" nameserver%u=%pI4", |
1546 | i, &ic_nameservers[i]); | 1530 | i, &ic_nameservers[i]); |
1547 | break; | 1531 | break; |
1548 | } | 1532 | } |
@@ -1585,7 +1569,7 @@ static int __init ic_proto_name(char *name) | |||
1585 | return 1; | 1569 | return 1; |
1586 | *v = 0; | 1570 | *v = 0; |
1587 | if (kstrtou8(client_id, 0, dhcp_client_identifier)) | 1571 | if (kstrtou8(client_id, 0, dhcp_client_identifier)) |
1588 | DBG("DHCP: Invalid client identifier type\n"); | 1572 | pr_debug("DHCP: Invalid client identifier type\n"); |
1589 | strncpy(dhcp_client_identifier + 1, v + 1, 251); | 1573 | strncpy(dhcp_client_identifier + 1, v + 1, 251); |
1590 | *v = ','; | 1574 | *v = ','; |
1591 | } | 1575 | } |
@@ -1644,7 +1628,7 @@ static int __init ip_auto_config_setup(char *addrs) | |||
1644 | if ((cp = strchr(ip, ':'))) | 1628 | if ((cp = strchr(ip, ':'))) |
1645 | *cp++ = '\0'; | 1629 | *cp++ = '\0'; |
1646 | if (strlen(ip) > 0) { | 1630 | if (strlen(ip) > 0) { |
1647 | DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip)); | 1631 | pr_debug("IP-Config: Parameter #%d: `%s'\n", num, ip); |
1648 | switch (num) { | 1632 | switch (num) { |
1649 | case 0: | 1633 | case 0: |
1650 | if ((ic_myaddr = in_aton(ip)) == ANY) | 1634 | if ((ic_myaddr = in_aton(ip)) == ANY) |
@@ -1716,7 +1700,7 @@ static int __init vendor_class_identifier_setup(char *addrs) | |||
1716 | if (strlcpy(vendor_class_identifier, addrs, | 1700 | if (strlcpy(vendor_class_identifier, addrs, |
1717 | sizeof(vendor_class_identifier)) | 1701 | sizeof(vendor_class_identifier)) |
1718 | >= sizeof(vendor_class_identifier)) | 1702 | >= sizeof(vendor_class_identifier)) |
1719 | pr_warn("DHCP: vendorclass too long, truncated to \"%s\"", | 1703 | pr_warn("DHCP: vendorclass too long, truncated to \"%s\"\n", |
1720 | vendor_class_identifier); | 1704 | vendor_class_identifier); |
1721 | return 1; | 1705 | return 1; |
1722 | } | 1706 | } |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index f34c31defafe..4044da61e747 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -103,7 +103,6 @@ | |||
103 | #include <linux/tcp.h> | 103 | #include <linux/tcp.h> |
104 | #include <linux/udp.h> | 104 | #include <linux/udp.h> |
105 | #include <linux/if_arp.h> | 105 | #include <linux/if_arp.h> |
106 | #include <linux/mroute.h> | ||
107 | #include <linux/init.h> | 106 | #include <linux/init.h> |
108 | #include <linux/netfilter_ipv4.h> | 107 | #include <linux/netfilter_ipv4.h> |
109 | #include <linux/if_ether.h> | 108 | #include <linux/if_ether.h> |
@@ -253,9 +252,6 @@ ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
253 | 252 | ||
254 | p.i_key = p.o_key = 0; | 253 | p.i_key = p.o_key = 0; |
255 | p.i_flags = p.o_flags = 0; | 254 | p.i_flags = p.o_flags = 0; |
256 | if (p.iph.ttl) | ||
257 | p.iph.frag_off |= htons(IP_DF); | ||
258 | |||
259 | err = ip_tunnel_ioctl(dev, &p, cmd); | 255 | err = ip_tunnel_ioctl(dev, &p, cmd); |
260 | if (err) | 256 | if (err) |
261 | return err; | 257 | return err; |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 92dd4b74d513..395e2814a46d 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -66,28 +66,7 @@ | |||
66 | #include <net/netlink.h> | 66 | #include <net/netlink.h> |
67 | #include <net/fib_rules.h> | 67 | #include <net/fib_rules.h> |
68 | #include <linux/netconf.h> | 68 | #include <linux/netconf.h> |
69 | 69 | #include <net/nexthop.h> | |
70 | #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) | ||
71 | #define CONFIG_IP_PIMSM 1 | ||
72 | #endif | ||
73 | |||
74 | struct mr_table { | ||
75 | struct list_head list; | ||
76 | possible_net_t net; | ||
77 | u32 id; | ||
78 | struct sock __rcu *mroute_sk; | ||
79 | struct timer_list ipmr_expire_timer; | ||
80 | struct list_head mfc_unres_queue; | ||
81 | struct list_head mfc_cache_array[MFC_LINES]; | ||
82 | struct vif_device vif_table[MAXVIFS]; | ||
83 | int maxvif; | ||
84 | atomic_t cache_resolve_queue_len; | ||
85 | bool mroute_do_assert; | ||
86 | bool mroute_do_pim; | ||
87 | #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) | ||
88 | int mroute_reg_vif_num; | ||
89 | #endif | ||
90 | }; | ||
91 | 70 | ||
92 | struct ipmr_rule { | 71 | struct ipmr_rule { |
93 | struct fib_rule common; | 72 | struct fib_rule common; |
@@ -103,11 +82,7 @@ struct ipmr_result { | |||
103 | 82 | ||
104 | static DEFINE_RWLOCK(mrt_lock); | 83 | static DEFINE_RWLOCK(mrt_lock); |
105 | 84 | ||
106 | /* | 85 | /* Multicast router control variables */ |
107 | * Multicast router control variables | ||
108 | */ | ||
109 | |||
110 | #define VIF_EXISTS(_mrt, _idx) ((_mrt)->vif_table[_idx].dev != NULL) | ||
111 | 86 | ||
112 | /* Special spinlock for queue of unresolved entries */ | 87 | /* Special spinlock for queue of unresolved entries */ |
113 | static DEFINE_SPINLOCK(mfc_unres_lock); | 88 | static DEFINE_SPINLOCK(mfc_unres_lock); |
@@ -134,7 +109,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, | |||
134 | struct mfc_cache *c, struct rtmsg *rtm); | 109 | struct mfc_cache *c, struct rtmsg *rtm); |
135 | static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc, | 110 | static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc, |
136 | int cmd); | 111 | int cmd); |
137 | static void mroute_clean_tables(struct mr_table *mrt); | 112 | static void mroute_clean_tables(struct mr_table *mrt, bool all); |
138 | static void ipmr_expire_process(unsigned long arg); | 113 | static void ipmr_expire_process(unsigned long arg); |
139 | 114 | ||
140 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES | 115 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES |
@@ -252,8 +227,8 @@ static int __net_init ipmr_rules_init(struct net *net) | |||
252 | INIT_LIST_HEAD(&net->ipv4.mr_tables); | 227 | INIT_LIST_HEAD(&net->ipv4.mr_tables); |
253 | 228 | ||
254 | mrt = ipmr_new_table(net, RT_TABLE_DEFAULT); | 229 | mrt = ipmr_new_table(net, RT_TABLE_DEFAULT); |
255 | if (!mrt) { | 230 | if (IS_ERR(mrt)) { |
256 | err = -ENOMEM; | 231 | err = PTR_ERR(mrt); |
257 | goto err1; | 232 | goto err1; |
258 | } | 233 | } |
259 | 234 | ||
@@ -301,8 +276,13 @@ static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, | |||
301 | 276 | ||
302 | static int __net_init ipmr_rules_init(struct net *net) | 277 | static int __net_init ipmr_rules_init(struct net *net) |
303 | { | 278 | { |
304 | net->ipv4.mrt = ipmr_new_table(net, RT_TABLE_DEFAULT); | 279 | struct mr_table *mrt; |
305 | return net->ipv4.mrt ? 0 : -ENOMEM; | 280 | |
281 | mrt = ipmr_new_table(net, RT_TABLE_DEFAULT); | ||
282 | if (IS_ERR(mrt)) | ||
283 | return PTR_ERR(mrt); | ||
284 | net->ipv4.mrt = mrt; | ||
285 | return 0; | ||
306 | } | 286 | } |
307 | 287 | ||
308 | static void __net_exit ipmr_rules_exit(struct net *net) | 288 | static void __net_exit ipmr_rules_exit(struct net *net) |
@@ -319,13 +299,17 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) | |||
319 | struct mr_table *mrt; | 299 | struct mr_table *mrt; |
320 | unsigned int i; | 300 | unsigned int i; |
321 | 301 | ||
302 | /* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */ | ||
303 | if (id != RT_TABLE_DEFAULT && id >= 1000000000) | ||
304 | return ERR_PTR(-EINVAL); | ||
305 | |||
322 | mrt = ipmr_get_table(net, id); | 306 | mrt = ipmr_get_table(net, id); |
323 | if (mrt) | 307 | if (mrt) |
324 | return mrt; | 308 | return mrt; |
325 | 309 | ||
326 | mrt = kzalloc(sizeof(*mrt), GFP_KERNEL); | 310 | mrt = kzalloc(sizeof(*mrt), GFP_KERNEL); |
327 | if (!mrt) | 311 | if (!mrt) |
328 | return NULL; | 312 | return ERR_PTR(-ENOMEM); |
329 | write_pnet(&mrt->net, net); | 313 | write_pnet(&mrt->net, net); |
330 | mrt->id = id; | 314 | mrt->id = id; |
331 | 315 | ||
@@ -338,9 +322,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) | |||
338 | setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process, | 322 | setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process, |
339 | (unsigned long)mrt); | 323 | (unsigned long)mrt); |
340 | 324 | ||
341 | #ifdef CONFIG_IP_PIMSM | ||
342 | mrt->mroute_reg_vif_num = -1; | 325 | mrt->mroute_reg_vif_num = -1; |
343 | #endif | ||
344 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES | 326 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES |
345 | list_add_tail_rcu(&mrt->list, &net->ipv4.mr_tables); | 327 | list_add_tail_rcu(&mrt->list, &net->ipv4.mr_tables); |
346 | #endif | 328 | #endif |
@@ -350,7 +332,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) | |||
350 | static void ipmr_free_table(struct mr_table *mrt) | 332 | static void ipmr_free_table(struct mr_table *mrt) |
351 | { | 333 | { |
352 | del_timer_sync(&mrt->ipmr_expire_timer); | 334 | del_timer_sync(&mrt->ipmr_expire_timer); |
353 | mroute_clean_tables(mrt); | 335 | mroute_clean_tables(mrt, true); |
354 | kfree(mrt); | 336 | kfree(mrt); |
355 | } | 337 | } |
356 | 338 | ||
@@ -387,8 +369,24 @@ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) | |||
387 | } | 369 | } |
388 | } | 370 | } |
389 | 371 | ||
390 | static | 372 | /* Initialize ipmr pimreg/tunnel in_device */ |
391 | struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v) | 373 | static bool ipmr_init_vif_indev(const struct net_device *dev) |
374 | { | ||
375 | struct in_device *in_dev; | ||
376 | |||
377 | ASSERT_RTNL(); | ||
378 | |||
379 | in_dev = __in_dev_get_rtnl(dev); | ||
380 | if (!in_dev) | ||
381 | return false; | ||
382 | ipv4_devconf_setall(in_dev); | ||
383 | neigh_parms_data_state_setall(in_dev->arp_parms); | ||
384 | IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0; | ||
385 | |||
386 | return true; | ||
387 | } | ||
388 | |||
389 | static struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v) | ||
392 | { | 390 | { |
393 | struct net_device *dev; | 391 | struct net_device *dev; |
394 | 392 | ||
@@ -399,7 +397,6 @@ struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v) | |||
399 | int err; | 397 | int err; |
400 | struct ifreq ifr; | 398 | struct ifreq ifr; |
401 | struct ip_tunnel_parm p; | 399 | struct ip_tunnel_parm p; |
402 | struct in_device *in_dev; | ||
403 | 400 | ||
404 | memset(&p, 0, sizeof(p)); | 401 | memset(&p, 0, sizeof(p)); |
405 | p.iph.daddr = v->vifc_rmt_addr.s_addr; | 402 | p.iph.daddr = v->vifc_rmt_addr.s_addr; |
@@ -424,15 +421,8 @@ struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v) | |||
424 | if (err == 0 && | 421 | if (err == 0 && |
425 | (dev = __dev_get_by_name(net, p.name)) != NULL) { | 422 | (dev = __dev_get_by_name(net, p.name)) != NULL) { |
426 | dev->flags |= IFF_MULTICAST; | 423 | dev->flags |= IFF_MULTICAST; |
427 | 424 | if (!ipmr_init_vif_indev(dev)) | |
428 | in_dev = __in_dev_get_rtnl(dev); | ||
429 | if (!in_dev) | ||
430 | goto failure; | 425 | goto failure; |
431 | |||
432 | ipv4_devconf_setall(in_dev); | ||
433 | neigh_parms_data_state_setall(in_dev->arp_parms); | ||
434 | IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0; | ||
435 | |||
436 | if (dev_open(dev)) | 426 | if (dev_open(dev)) |
437 | goto failure; | 427 | goto failure; |
438 | dev_hold(dev); | 428 | dev_hold(dev); |
@@ -441,16 +431,11 @@ struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v) | |||
441 | return dev; | 431 | return dev; |
442 | 432 | ||
443 | failure: | 433 | failure: |
444 | /* allow the register to be completed before unregistering. */ | ||
445 | rtnl_unlock(); | ||
446 | rtnl_lock(); | ||
447 | |||
448 | unregister_netdevice(dev); | 434 | unregister_netdevice(dev); |
449 | return NULL; | 435 | return NULL; |
450 | } | 436 | } |
451 | 437 | ||
452 | #ifdef CONFIG_IP_PIMSM | 438 | #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) |
453 | |||
454 | static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | 439 | static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) |
455 | { | 440 | { |
456 | struct net *net = dev_net(dev); | 441 | struct net *net = dev_net(dev); |
@@ -500,7 +485,6 @@ static void reg_vif_setup(struct net_device *dev) | |||
500 | static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) | 485 | static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) |
501 | { | 486 | { |
502 | struct net_device *dev; | 487 | struct net_device *dev; |
503 | struct in_device *in_dev; | ||
504 | char name[IFNAMSIZ]; | 488 | char name[IFNAMSIZ]; |
505 | 489 | ||
506 | if (mrt->id == RT_TABLE_DEFAULT) | 490 | if (mrt->id == RT_TABLE_DEFAULT) |
@@ -520,18 +504,8 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) | |||
520 | return NULL; | 504 | return NULL; |
521 | } | 505 | } |
522 | 506 | ||
523 | rcu_read_lock(); | 507 | if (!ipmr_init_vif_indev(dev)) |
524 | in_dev = __in_dev_get_rcu(dev); | ||
525 | if (!in_dev) { | ||
526 | rcu_read_unlock(); | ||
527 | goto failure; | 508 | goto failure; |
528 | } | ||
529 | |||
530 | ipv4_devconf_setall(in_dev); | ||
531 | neigh_parms_data_state_setall(in_dev->arp_parms); | ||
532 | IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0; | ||
533 | rcu_read_unlock(); | ||
534 | |||
535 | if (dev_open(dev)) | 509 | if (dev_open(dev)) |
536 | goto failure; | 510 | goto failure; |
537 | 511 | ||
@@ -540,20 +514,59 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) | |||
540 | return dev; | 514 | return dev; |
541 | 515 | ||
542 | failure: | 516 | failure: |
543 | /* allow the register to be completed before unregistering. */ | ||
544 | rtnl_unlock(); | ||
545 | rtnl_lock(); | ||
546 | |||
547 | unregister_netdevice(dev); | 517 | unregister_netdevice(dev); |
548 | return NULL; | 518 | return NULL; |
549 | } | 519 | } |
520 | |||
521 | /* called with rcu_read_lock() */ | ||
522 | static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb, | ||
523 | unsigned int pimlen) | ||
524 | { | ||
525 | struct net_device *reg_dev = NULL; | ||
526 | struct iphdr *encap; | ||
527 | |||
528 | encap = (struct iphdr *)(skb_transport_header(skb) + pimlen); | ||
529 | /* Check that: | ||
530 | * a. packet is really sent to a multicast group | ||
531 | * b. packet is not a NULL-REGISTER | ||
532 | * c. packet is not truncated | ||
533 | */ | ||
534 | if (!ipv4_is_multicast(encap->daddr) || | ||
535 | encap->tot_len == 0 || | ||
536 | ntohs(encap->tot_len) + pimlen > skb->len) | ||
537 | return 1; | ||
538 | |||
539 | read_lock(&mrt_lock); | ||
540 | if (mrt->mroute_reg_vif_num >= 0) | ||
541 | reg_dev = mrt->vif_table[mrt->mroute_reg_vif_num].dev; | ||
542 | read_unlock(&mrt_lock); | ||
543 | |||
544 | if (!reg_dev) | ||
545 | return 1; | ||
546 | |||
547 | skb->mac_header = skb->network_header; | ||
548 | skb_pull(skb, (u8 *)encap - skb->data); | ||
549 | skb_reset_network_header(skb); | ||
550 | skb->protocol = htons(ETH_P_IP); | ||
551 | skb->ip_summed = CHECKSUM_NONE; | ||
552 | |||
553 | skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev)); | ||
554 | |||
555 | netif_rx(skb); | ||
556 | |||
557 | return NET_RX_SUCCESS; | ||
558 | } | ||
559 | #else | ||
560 | static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) | ||
561 | { | ||
562 | return NULL; | ||
563 | } | ||
550 | #endif | 564 | #endif |
551 | 565 | ||
552 | /** | 566 | /** |
553 | * vif_delete - Delete a VIF entry | 567 | * vif_delete - Delete a VIF entry |
554 | * @notify: Set to 1, if the caller is a notifier_call | 568 | * @notify: Set to 1, if the caller is a notifier_call |
555 | */ | 569 | */ |
556 | |||
557 | static int vif_delete(struct mr_table *mrt, int vifi, int notify, | 570 | static int vif_delete(struct mr_table *mrt, int vifi, int notify, |
558 | struct list_head *head) | 571 | struct list_head *head) |
559 | { | 572 | { |
@@ -575,10 +588,8 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify, | |||
575 | return -EADDRNOTAVAIL; | 588 | return -EADDRNOTAVAIL; |
576 | } | 589 | } |
577 | 590 | ||
578 | #ifdef CONFIG_IP_PIMSM | ||
579 | if (vifi == mrt->mroute_reg_vif_num) | 591 | if (vifi == mrt->mroute_reg_vif_num) |
580 | mrt->mroute_reg_vif_num = -1; | 592 | mrt->mroute_reg_vif_num = -1; |
581 | #endif | ||
582 | 593 | ||
583 | if (vifi + 1 == mrt->maxvif) { | 594 | if (vifi + 1 == mrt->maxvif) { |
584 | int tmp; | 595 | int tmp; |
@@ -625,7 +636,6 @@ static inline void ipmr_cache_free(struct mfc_cache *c) | |||
625 | /* Destroy an unresolved cache entry, killing queued skbs | 636 | /* Destroy an unresolved cache entry, killing queued skbs |
626 | * and reporting error to netlink readers. | 637 | * and reporting error to netlink readers. |
627 | */ | 638 | */ |
628 | |||
629 | static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c) | 639 | static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c) |
630 | { | 640 | { |
631 | struct net *net = read_pnet(&mrt->net); | 641 | struct net *net = read_pnet(&mrt->net); |
@@ -653,9 +663,7 @@ static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c) | |||
653 | ipmr_cache_free(c); | 663 | ipmr_cache_free(c); |
654 | } | 664 | } |
655 | 665 | ||
656 | |||
657 | /* Timer process for the unresolved queue. */ | 666 | /* Timer process for the unresolved queue. */ |
658 | |||
659 | static void ipmr_expire_process(unsigned long arg) | 667 | static void ipmr_expire_process(unsigned long arg) |
660 | { | 668 | { |
661 | struct mr_table *mrt = (struct mr_table *)arg; | 669 | struct mr_table *mrt = (struct mr_table *)arg; |
@@ -695,7 +703,6 @@ out: | |||
695 | } | 703 | } |
696 | 704 | ||
697 | /* Fill oifs list. It is called under write locked mrt_lock. */ | 705 | /* Fill oifs list. It is called under write locked mrt_lock. */ |
698 | |||
699 | static void ipmr_update_thresholds(struct mr_table *mrt, struct mfc_cache *cache, | 706 | static void ipmr_update_thresholds(struct mr_table *mrt, struct mfc_cache *cache, |
700 | unsigned char *ttls) | 707 | unsigned char *ttls) |
701 | { | 708 | { |
@@ -731,10 +738,10 @@ static int vif_add(struct net *net, struct mr_table *mrt, | |||
731 | return -EADDRINUSE; | 738 | return -EADDRINUSE; |
732 | 739 | ||
733 | switch (vifc->vifc_flags) { | 740 | switch (vifc->vifc_flags) { |
734 | #ifdef CONFIG_IP_PIMSM | ||
735 | case VIFF_REGISTER: | 741 | case VIFF_REGISTER: |
736 | /* | 742 | if (!ipmr_pimsm_enabled()) |
737 | * Special Purpose VIF in PIM | 743 | return -EINVAL; |
744 | /* Special Purpose VIF in PIM | ||
738 | * All the packets will be sent to the daemon | 745 | * All the packets will be sent to the daemon |
739 | */ | 746 | */ |
740 | if (mrt->mroute_reg_vif_num >= 0) | 747 | if (mrt->mroute_reg_vif_num >= 0) |
@@ -749,7 +756,6 @@ static int vif_add(struct net *net, struct mr_table *mrt, | |||
749 | return err; | 756 | return err; |
750 | } | 757 | } |
751 | break; | 758 | break; |
752 | #endif | ||
753 | case VIFF_TUNNEL: | 759 | case VIFF_TUNNEL: |
754 | dev = ipmr_new_tunnel(net, vifc); | 760 | dev = ipmr_new_tunnel(net, vifc); |
755 | if (!dev) | 761 | if (!dev) |
@@ -761,7 +767,6 @@ static int vif_add(struct net *net, struct mr_table *mrt, | |||
761 | return err; | 767 | return err; |
762 | } | 768 | } |
763 | break; | 769 | break; |
764 | |||
765 | case VIFF_USE_IFINDEX: | 770 | case VIFF_USE_IFINDEX: |
766 | case 0: | 771 | case 0: |
767 | if (vifc->vifc_flags == VIFF_USE_IFINDEX) { | 772 | if (vifc->vifc_flags == VIFF_USE_IFINDEX) { |
@@ -815,10 +820,8 @@ static int vif_add(struct net *net, struct mr_table *mrt, | |||
815 | /* And finish update writing critical data */ | 820 | /* And finish update writing critical data */ |
816 | write_lock_bh(&mrt_lock); | 821 | write_lock_bh(&mrt_lock); |
817 | v->dev = dev; | 822 | v->dev = dev; |
818 | #ifdef CONFIG_IP_PIMSM | ||
819 | if (v->flags & VIFF_REGISTER) | 823 | if (v->flags & VIFF_REGISTER) |
820 | mrt->mroute_reg_vif_num = vifi; | 824 | mrt->mroute_reg_vif_num = vifi; |
821 | #endif | ||
822 | if (vifi+1 > mrt->maxvif) | 825 | if (vifi+1 > mrt->maxvif) |
823 | mrt->maxvif = vifi+1; | 826 | mrt->maxvif = vifi+1; |
824 | write_unlock_bh(&mrt_lock); | 827 | write_unlock_bh(&mrt_lock); |
@@ -883,9 +886,7 @@ skip: | |||
883 | return ipmr_cache_find_any_parent(mrt, vifi); | 886 | return ipmr_cache_find_any_parent(mrt, vifi); |
884 | } | 887 | } |
885 | 888 | ||
886 | /* | 889 | /* Allocate a multicast cache entry */ |
887 | * Allocate a multicast cache entry | ||
888 | */ | ||
889 | static struct mfc_cache *ipmr_cache_alloc(void) | 890 | static struct mfc_cache *ipmr_cache_alloc(void) |
890 | { | 891 | { |
891 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); | 892 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); |
@@ -906,10 +907,7 @@ static struct mfc_cache *ipmr_cache_alloc_unres(void) | |||
906 | return c; | 907 | return c; |
907 | } | 908 | } |
908 | 909 | ||
909 | /* | 910 | /* A cache entry has gone into a resolved state from queued */ |
910 | * A cache entry has gone into a resolved state from queued | ||
911 | */ | ||
912 | |||
913 | static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, | 911 | static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, |
914 | struct mfc_cache *uc, struct mfc_cache *c) | 912 | struct mfc_cache *uc, struct mfc_cache *c) |
915 | { | 913 | { |
@@ -917,7 +915,6 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, | |||
917 | struct nlmsgerr *e; | 915 | struct nlmsgerr *e; |
918 | 916 | ||
919 | /* Play the pending entries through our router */ | 917 | /* Play the pending entries through our router */ |
920 | |||
921 | while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { | 918 | while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { |
922 | if (ip_hdr(skb)->version == 0) { | 919 | if (ip_hdr(skb)->version == 0) { |
923 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); | 920 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); |
@@ -941,34 +938,29 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, | |||
941 | } | 938 | } |
942 | } | 939 | } |
943 | 940 | ||
944 | /* | 941 | /* Bounce a cache query up to mrouted. We could use netlink for this but mrouted |
945 | * Bounce a cache query up to mrouted. We could use netlink for this but mrouted | 942 | * expects the following bizarre scheme. |
946 | * expects the following bizarre scheme. | ||
947 | * | 943 | * |
948 | * Called under mrt_lock. | 944 | * Called under mrt_lock. |
949 | */ | 945 | */ |
950 | |||
951 | static int ipmr_cache_report(struct mr_table *mrt, | 946 | static int ipmr_cache_report(struct mr_table *mrt, |
952 | struct sk_buff *pkt, vifi_t vifi, int assert) | 947 | struct sk_buff *pkt, vifi_t vifi, int assert) |
953 | { | 948 | { |
954 | struct sk_buff *skb; | ||
955 | const int ihl = ip_hdrlen(pkt); | 949 | const int ihl = ip_hdrlen(pkt); |
950 | struct sock *mroute_sk; | ||
956 | struct igmphdr *igmp; | 951 | struct igmphdr *igmp; |
957 | struct igmpmsg *msg; | 952 | struct igmpmsg *msg; |
958 | struct sock *mroute_sk; | 953 | struct sk_buff *skb; |
959 | int ret; | 954 | int ret; |
960 | 955 | ||
961 | #ifdef CONFIG_IP_PIMSM | ||
962 | if (assert == IGMPMSG_WHOLEPKT) | 956 | if (assert == IGMPMSG_WHOLEPKT) |
963 | skb = skb_realloc_headroom(pkt, sizeof(struct iphdr)); | 957 | skb = skb_realloc_headroom(pkt, sizeof(struct iphdr)); |
964 | else | 958 | else |
965 | #endif | ||
966 | skb = alloc_skb(128, GFP_ATOMIC); | 959 | skb = alloc_skb(128, GFP_ATOMIC); |
967 | 960 | ||
968 | if (!skb) | 961 | if (!skb) |
969 | return -ENOBUFS; | 962 | return -ENOBUFS; |
970 | 963 | ||
971 | #ifdef CONFIG_IP_PIMSM | ||
972 | if (assert == IGMPMSG_WHOLEPKT) { | 964 | if (assert == IGMPMSG_WHOLEPKT) { |
973 | /* Ugly, but we have no choice with this interface. | 965 | /* Ugly, but we have no choice with this interface. |
974 | * Duplicate old header, fix ihl, length etc. | 966 | * Duplicate old header, fix ihl, length etc. |
@@ -986,28 +978,23 @@ static int ipmr_cache_report(struct mr_table *mrt, | |||
986 | ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; | 978 | ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; |
987 | ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + | 979 | ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + |
988 | sizeof(struct iphdr)); | 980 | sizeof(struct iphdr)); |
989 | } else | 981 | } else { |
990 | #endif | 982 | /* Copy the IP header */ |
991 | { | 983 | skb_set_network_header(skb, skb->len); |
992 | 984 | skb_put(skb, ihl); | |
993 | /* Copy the IP header */ | 985 | skb_copy_to_linear_data(skb, pkt->data, ihl); |
994 | 986 | /* Flag to the kernel this is a route add */ | |
995 | skb_set_network_header(skb, skb->len); | 987 | ip_hdr(skb)->protocol = 0; |
996 | skb_put(skb, ihl); | 988 | msg = (struct igmpmsg *)skb_network_header(skb); |
997 | skb_copy_to_linear_data(skb, pkt->data, ihl); | 989 | msg->im_vif = vifi; |
998 | ip_hdr(skb)->protocol = 0; /* Flag to the kernel this is a route add */ | 990 | skb_dst_set(skb, dst_clone(skb_dst(pkt))); |
999 | msg = (struct igmpmsg *)skb_network_header(skb); | 991 | /* Add our header */ |
1000 | msg->im_vif = vifi; | 992 | igmp = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr)); |
1001 | skb_dst_set(skb, dst_clone(skb_dst(pkt))); | 993 | igmp->type = assert; |
1002 | 994 | msg->im_msgtype = assert; | |
1003 | /* Add our header */ | 995 | igmp->code = 0; |
1004 | 996 | ip_hdr(skb)->tot_len = htons(skb->len); /* Fix the length */ | |
1005 | igmp = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr)); | 997 | skb->transport_header = skb->network_header; |
1006 | igmp->type = | ||
1007 | msg->im_msgtype = assert; | ||
1008 | igmp->code = 0; | ||
1009 | ip_hdr(skb)->tot_len = htons(skb->len); /* Fix the length */ | ||
1010 | skb->transport_header = skb->network_header; | ||
1011 | } | 998 | } |
1012 | 999 | ||
1013 | rcu_read_lock(); | 1000 | rcu_read_lock(); |
@@ -1019,7 +1006,6 @@ static int ipmr_cache_report(struct mr_table *mrt, | |||
1019 | } | 1006 | } |
1020 | 1007 | ||
1021 | /* Deliver to mrouted */ | 1008 | /* Deliver to mrouted */ |
1022 | |||
1023 | ret = sock_queue_rcv_skb(mroute_sk, skb); | 1009 | ret = sock_queue_rcv_skb(mroute_sk, skb); |
1024 | rcu_read_unlock(); | 1010 | rcu_read_unlock(); |
1025 | if (ret < 0) { | 1011 | if (ret < 0) { |
@@ -1030,12 +1016,9 @@ static int ipmr_cache_report(struct mr_table *mrt, | |||
1030 | return ret; | 1016 | return ret; |
1031 | } | 1017 | } |
1032 | 1018 | ||
1033 | /* | 1019 | /* Queue a packet for resolution. It gets locked cache entry! */ |
1034 | * Queue a packet for resolution. It gets locked cache entry! | 1020 | static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, |
1035 | */ | 1021 | struct sk_buff *skb) |
1036 | |||
1037 | static int | ||
1038 | ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb) | ||
1039 | { | 1022 | { |
1040 | bool found = false; | 1023 | bool found = false; |
1041 | int err; | 1024 | int err; |
@@ -1053,7 +1036,6 @@ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb) | |||
1053 | 1036 | ||
1054 | if (!found) { | 1037 | if (!found) { |
1055 | /* Create a new entry if allowable */ | 1038 | /* Create a new entry if allowable */ |
1056 | |||
1057 | if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 || | 1039 | if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 || |
1058 | (c = ipmr_cache_alloc_unres()) == NULL) { | 1040 | (c = ipmr_cache_alloc_unres()) == NULL) { |
1059 | spin_unlock_bh(&mfc_unres_lock); | 1041 | spin_unlock_bh(&mfc_unres_lock); |
@@ -1063,13 +1045,11 @@ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb) | |||
1063 | } | 1045 | } |
1064 | 1046 | ||
1065 | /* Fill in the new cache entry */ | 1047 | /* Fill in the new cache entry */ |
1066 | |||
1067 | c->mfc_parent = -1; | 1048 | c->mfc_parent = -1; |
1068 | c->mfc_origin = iph->saddr; | 1049 | c->mfc_origin = iph->saddr; |
1069 | c->mfc_mcastgrp = iph->daddr; | 1050 | c->mfc_mcastgrp = iph->daddr; |
1070 | 1051 | ||
1071 | /* Reflect first query at mrouted. */ | 1052 | /* Reflect first query at mrouted. */ |
1072 | |||
1073 | err = ipmr_cache_report(mrt, skb, vifi, IGMPMSG_NOCACHE); | 1053 | err = ipmr_cache_report(mrt, skb, vifi, IGMPMSG_NOCACHE); |
1074 | if (err < 0) { | 1054 | if (err < 0) { |
1075 | /* If the report failed throw the cache entry | 1055 | /* If the report failed throw the cache entry |
@@ -1091,7 +1071,6 @@ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb) | |||
1091 | } | 1071 | } |
1092 | 1072 | ||
1093 | /* See if we can append the packet */ | 1073 | /* See if we can append the packet */ |
1094 | |||
1095 | if (c->mfc_un.unres.unresolved.qlen > 3) { | 1074 | if (c->mfc_un.unres.unresolved.qlen > 3) { |
1096 | kfree_skb(skb); | 1075 | kfree_skb(skb); |
1097 | err = -ENOBUFS; | 1076 | err = -ENOBUFS; |
@@ -1104,9 +1083,7 @@ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb) | |||
1104 | return err; | 1083 | return err; |
1105 | } | 1084 | } |
1106 | 1085 | ||
1107 | /* | 1086 | /* MFC cache manipulation by user space mroute daemon */ |
1108 | * MFC cache manipulation by user space mroute daemon | ||
1109 | */ | ||
1110 | 1087 | ||
1111 | static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc, int parent) | 1088 | static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc, int parent) |
1112 | { | 1089 | { |
@@ -1177,9 +1154,8 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, | |||
1177 | 1154 | ||
1178 | list_add_rcu(&c->list, &mrt->mfc_cache_array[line]); | 1155 | list_add_rcu(&c->list, &mrt->mfc_cache_array[line]); |
1179 | 1156 | ||
1180 | /* | 1157 | /* Check to see if we resolved a queued list. If so we |
1181 | * Check to see if we resolved a queued list. If so we | 1158 | * need to send on the frames and tidy up. |
1182 | * need to send on the frames and tidy up. | ||
1183 | */ | 1159 | */ |
1184 | found = false; | 1160 | found = false; |
1185 | spin_lock_bh(&mfc_unres_lock); | 1161 | spin_lock_bh(&mfc_unres_lock); |
@@ -1204,29 +1180,25 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, | |||
1204 | return 0; | 1180 | return 0; |
1205 | } | 1181 | } |
1206 | 1182 | ||
1207 | /* | 1183 | /* Close the multicast socket, and clear the vif tables etc */ |
1208 | * Close the multicast socket, and clear the vif tables etc | 1184 | static void mroute_clean_tables(struct mr_table *mrt, bool all) |
1209 | */ | ||
1210 | |||
1211 | static void mroute_clean_tables(struct mr_table *mrt) | ||
1212 | { | 1185 | { |
1213 | int i; | 1186 | int i; |
1214 | LIST_HEAD(list); | 1187 | LIST_HEAD(list); |
1215 | struct mfc_cache *c, *next; | 1188 | struct mfc_cache *c, *next; |
1216 | 1189 | ||
1217 | /* Shut down all active vif entries */ | 1190 | /* Shut down all active vif entries */ |
1218 | |||
1219 | for (i = 0; i < mrt->maxvif; i++) { | 1191 | for (i = 0; i < mrt->maxvif; i++) { |
1220 | if (!(mrt->vif_table[i].flags & VIFF_STATIC)) | 1192 | if (!all && (mrt->vif_table[i].flags & VIFF_STATIC)) |
1221 | vif_delete(mrt, i, 0, &list); | 1193 | continue; |
1194 | vif_delete(mrt, i, 0, &list); | ||
1222 | } | 1195 | } |
1223 | unregister_netdevice_many(&list); | 1196 | unregister_netdevice_many(&list); |
1224 | 1197 | ||
1225 | /* Wipe the cache */ | 1198 | /* Wipe the cache */ |
1226 | |||
1227 | for (i = 0; i < MFC_LINES; i++) { | 1199 | for (i = 0; i < MFC_LINES; i++) { |
1228 | list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[i], list) { | 1200 | list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[i], list) { |
1229 | if (c->mfc_flags & MFC_STATIC) | 1201 | if (!all && (c->mfc_flags & MFC_STATIC)) |
1230 | continue; | 1202 | continue; |
1231 | list_del_rcu(&c->list); | 1203 | list_del_rcu(&c->list); |
1232 | mroute_netlink_event(mrt, c, RTM_DELROUTE); | 1204 | mroute_netlink_event(mrt, c, RTM_DELROUTE); |
@@ -1261,50 +1233,58 @@ static void mrtsock_destruct(struct sock *sk) | |||
1261 | NETCONFA_IFINDEX_ALL, | 1233 | NETCONFA_IFINDEX_ALL, |
1262 | net->ipv4.devconf_all); | 1234 | net->ipv4.devconf_all); |
1263 | RCU_INIT_POINTER(mrt->mroute_sk, NULL); | 1235 | RCU_INIT_POINTER(mrt->mroute_sk, NULL); |
1264 | mroute_clean_tables(mrt); | 1236 | mroute_clean_tables(mrt, false); |
1265 | } | 1237 | } |
1266 | } | 1238 | } |
1267 | rtnl_unlock(); | 1239 | rtnl_unlock(); |
1268 | } | 1240 | } |
1269 | 1241 | ||
1270 | /* | 1242 | /* Socket options and virtual interface manipulation. The whole |
1271 | * Socket options and virtual interface manipulation. The whole | 1243 | * virtual interface system is a complete heap, but unfortunately |
1272 | * virtual interface system is a complete heap, but unfortunately | 1244 | * that's how BSD mrouted happens to think. Maybe one day with a proper |
1273 | * that's how BSD mrouted happens to think. Maybe one day with a proper | 1245 | * MOSPF/PIM router set up we can clean this up. |
1274 | * MOSPF/PIM router set up we can clean this up. | ||
1275 | */ | 1246 | */ |
1276 | 1247 | ||
1277 | int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen) | 1248 | int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, |
1249 | unsigned int optlen) | ||
1278 | { | 1250 | { |
1279 | int ret, parent = 0; | ||
1280 | struct vifctl vif; | ||
1281 | struct mfcctl mfc; | ||
1282 | struct net *net = sock_net(sk); | 1251 | struct net *net = sock_net(sk); |
1252 | int val, ret = 0, parent = 0; | ||
1283 | struct mr_table *mrt; | 1253 | struct mr_table *mrt; |
1254 | struct vifctl vif; | ||
1255 | struct mfcctl mfc; | ||
1256 | u32 uval; | ||
1284 | 1257 | ||
1258 | /* There's one exception to the lock - MRT_DONE which needs to unlock */ | ||
1259 | rtnl_lock(); | ||
1285 | if (sk->sk_type != SOCK_RAW || | 1260 | if (sk->sk_type != SOCK_RAW || |
1286 | inet_sk(sk)->inet_num != IPPROTO_IGMP) | 1261 | inet_sk(sk)->inet_num != IPPROTO_IGMP) { |
1287 | return -EOPNOTSUPP; | 1262 | ret = -EOPNOTSUPP; |
1263 | goto out_unlock; | ||
1264 | } | ||
1288 | 1265 | ||
1289 | mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); | 1266 | mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); |
1290 | if (!mrt) | 1267 | if (!mrt) { |
1291 | return -ENOENT; | 1268 | ret = -ENOENT; |
1292 | 1269 | goto out_unlock; | |
1270 | } | ||
1293 | if (optname != MRT_INIT) { | 1271 | if (optname != MRT_INIT) { |
1294 | if (sk != rcu_access_pointer(mrt->mroute_sk) && | 1272 | if (sk != rcu_access_pointer(mrt->mroute_sk) && |
1295 | !ns_capable(net->user_ns, CAP_NET_ADMIN)) | 1273 | !ns_capable(net->user_ns, CAP_NET_ADMIN)) { |
1296 | return -EACCES; | 1274 | ret = -EACCES; |
1275 | goto out_unlock; | ||
1276 | } | ||
1297 | } | 1277 | } |
1298 | 1278 | ||
1299 | switch (optname) { | 1279 | switch (optname) { |
1300 | case MRT_INIT: | 1280 | case MRT_INIT: |
1301 | if (optlen != sizeof(int)) | 1281 | if (optlen != sizeof(int)) { |
1302 | return -EINVAL; | 1282 | ret = -EINVAL; |
1303 | 1283 | break; | |
1304 | rtnl_lock(); | 1284 | } |
1305 | if (rtnl_dereference(mrt->mroute_sk)) { | 1285 | if (rtnl_dereference(mrt->mroute_sk)) { |
1306 | rtnl_unlock(); | 1286 | ret = -EADDRINUSE; |
1307 | return -EADDRINUSE; | 1287 | break; |
1308 | } | 1288 | } |
1309 | 1289 | ||
1310 | ret = ip_ra_control(sk, 1, mrtsock_destruct); | 1290 | ret = ip_ra_control(sk, 1, mrtsock_destruct); |
@@ -1315,129 +1295,133 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
1315 | NETCONFA_IFINDEX_ALL, | 1295 | NETCONFA_IFINDEX_ALL, |
1316 | net->ipv4.devconf_all); | 1296 | net->ipv4.devconf_all); |
1317 | } | 1297 | } |
1318 | rtnl_unlock(); | 1298 | break; |
1319 | return ret; | ||
1320 | case MRT_DONE: | 1299 | case MRT_DONE: |
1321 | if (sk != rcu_access_pointer(mrt->mroute_sk)) | 1300 | if (sk != rcu_access_pointer(mrt->mroute_sk)) { |
1322 | return -EACCES; | 1301 | ret = -EACCES; |
1323 | return ip_ra_control(sk, 0, NULL); | 1302 | } else { |
1303 | /* We need to unlock here because mrtsock_destruct takes | ||
1304 | * care of rtnl itself and we can't change that due to | ||
1305 | * the IP_ROUTER_ALERT setsockopt which runs without it. | ||
1306 | */ | ||
1307 | rtnl_unlock(); | ||
1308 | ret = ip_ra_control(sk, 0, NULL); | ||
1309 | goto out; | ||
1310 | } | ||
1311 | break; | ||
1324 | case MRT_ADD_VIF: | 1312 | case MRT_ADD_VIF: |
1325 | case MRT_DEL_VIF: | 1313 | case MRT_DEL_VIF: |
1326 | if (optlen != sizeof(vif)) | 1314 | if (optlen != sizeof(vif)) { |
1327 | return -EINVAL; | 1315 | ret = -EINVAL; |
1328 | if (copy_from_user(&vif, optval, sizeof(vif))) | 1316 | break; |
1329 | return -EFAULT; | 1317 | } |
1330 | if (vif.vifc_vifi >= MAXVIFS) | 1318 | if (copy_from_user(&vif, optval, sizeof(vif))) { |
1331 | return -ENFILE; | 1319 | ret = -EFAULT; |
1332 | rtnl_lock(); | 1320 | break; |
1321 | } | ||
1322 | if (vif.vifc_vifi >= MAXVIFS) { | ||
1323 | ret = -ENFILE; | ||
1324 | break; | ||
1325 | } | ||
1333 | if (optname == MRT_ADD_VIF) { | 1326 | if (optname == MRT_ADD_VIF) { |
1334 | ret = vif_add(net, mrt, &vif, | 1327 | ret = vif_add(net, mrt, &vif, |
1335 | sk == rtnl_dereference(mrt->mroute_sk)); | 1328 | sk == rtnl_dereference(mrt->mroute_sk)); |
1336 | } else { | 1329 | } else { |
1337 | ret = vif_delete(mrt, vif.vifc_vifi, 0, NULL); | 1330 | ret = vif_delete(mrt, vif.vifc_vifi, 0, NULL); |
1338 | } | 1331 | } |
1339 | rtnl_unlock(); | 1332 | break; |
1340 | return ret; | 1333 | /* Manipulate the forwarding caches. These live |
1341 | 1334 | * in a sort of kernel/user symbiosis. | |
1342 | /* | 1335 | */ |
1343 | * Manipulate the forwarding caches. These live | ||
1344 | * in a sort of kernel/user symbiosis. | ||
1345 | */ | ||
1346 | case MRT_ADD_MFC: | 1336 | case MRT_ADD_MFC: |
1347 | case MRT_DEL_MFC: | 1337 | case MRT_DEL_MFC: |
1348 | parent = -1; | 1338 | parent = -1; |
1349 | case MRT_ADD_MFC_PROXY: | 1339 | case MRT_ADD_MFC_PROXY: |
1350 | case MRT_DEL_MFC_PROXY: | 1340 | case MRT_DEL_MFC_PROXY: |
1351 | if (optlen != sizeof(mfc)) | 1341 | if (optlen != sizeof(mfc)) { |
1352 | return -EINVAL; | 1342 | ret = -EINVAL; |
1353 | if (copy_from_user(&mfc, optval, sizeof(mfc))) | 1343 | break; |
1354 | return -EFAULT; | 1344 | } |
1345 | if (copy_from_user(&mfc, optval, sizeof(mfc))) { | ||
1346 | ret = -EFAULT; | ||
1347 | break; | ||
1348 | } | ||
1355 | if (parent == 0) | 1349 | if (parent == 0) |
1356 | parent = mfc.mfcc_parent; | 1350 | parent = mfc.mfcc_parent; |
1357 | rtnl_lock(); | ||
1358 | if (optname == MRT_DEL_MFC || optname == MRT_DEL_MFC_PROXY) | 1351 | if (optname == MRT_DEL_MFC || optname == MRT_DEL_MFC_PROXY) |
1359 | ret = ipmr_mfc_delete(mrt, &mfc, parent); | 1352 | ret = ipmr_mfc_delete(mrt, &mfc, parent); |
1360 | else | 1353 | else |
1361 | ret = ipmr_mfc_add(net, mrt, &mfc, | 1354 | ret = ipmr_mfc_add(net, mrt, &mfc, |
1362 | sk == rtnl_dereference(mrt->mroute_sk), | 1355 | sk == rtnl_dereference(mrt->mroute_sk), |
1363 | parent); | 1356 | parent); |
1364 | rtnl_unlock(); | 1357 | break; |
1365 | return ret; | 1358 | /* Control PIM assert. */ |
1366 | /* | ||
1367 | * Control PIM assert. | ||
1368 | */ | ||
1369 | case MRT_ASSERT: | 1359 | case MRT_ASSERT: |
1370 | { | 1360 | if (optlen != sizeof(val)) { |
1371 | int v; | 1361 | ret = -EINVAL; |
1372 | if (optlen != sizeof(v)) | 1362 | break; |
1373 | return -EINVAL; | 1363 | } |
1374 | if (get_user(v, (int __user *)optval)) | 1364 | if (get_user(val, (int __user *)optval)) { |
1375 | return -EFAULT; | 1365 | ret = -EFAULT; |
1376 | mrt->mroute_do_assert = v; | 1366 | break; |
1377 | return 0; | 1367 | } |
1378 | } | 1368 | mrt->mroute_do_assert = val; |
1379 | #ifdef CONFIG_IP_PIMSM | 1369 | break; |
1380 | case MRT_PIM: | 1370 | case MRT_PIM: |
1381 | { | 1371 | if (!ipmr_pimsm_enabled()) { |
1382 | int v; | 1372 | ret = -ENOPROTOOPT; |
1383 | 1373 | break; | |
1384 | if (optlen != sizeof(v)) | 1374 | } |
1385 | return -EINVAL; | 1375 | if (optlen != sizeof(val)) { |
1386 | if (get_user(v, (int __user *)optval)) | 1376 | ret = -EINVAL; |
1387 | return -EFAULT; | 1377 | break; |
1388 | v = !!v; | 1378 | } |
1379 | if (get_user(val, (int __user *)optval)) { | ||
1380 | ret = -EFAULT; | ||
1381 | break; | ||
1382 | } | ||
1389 | 1383 | ||
1390 | rtnl_lock(); | 1384 | val = !!val; |
1391 | ret = 0; | 1385 | if (val != mrt->mroute_do_pim) { |
1392 | if (v != mrt->mroute_do_pim) { | 1386 | mrt->mroute_do_pim = val; |
1393 | mrt->mroute_do_pim = v; | 1387 | mrt->mroute_do_assert = val; |
1394 | mrt->mroute_do_assert = v; | ||
1395 | } | 1388 | } |
1396 | rtnl_unlock(); | 1389 | break; |
1397 | return ret; | ||
1398 | } | ||
1399 | #endif | ||
1400 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES | ||
1401 | case MRT_TABLE: | 1390 | case MRT_TABLE: |
1402 | { | 1391 | if (!IS_BUILTIN(CONFIG_IP_MROUTE_MULTIPLE_TABLES)) { |
1403 | u32 v; | 1392 | ret = -ENOPROTOOPT; |
1404 | 1393 | break; | |
1405 | if (optlen != sizeof(u32)) | 1394 | } |
1406 | return -EINVAL; | 1395 | if (optlen != sizeof(uval)) { |
1407 | if (get_user(v, (u32 __user *)optval)) | 1396 | ret = -EINVAL; |
1408 | return -EFAULT; | 1397 | break; |
1409 | 1398 | } | |
1410 | /* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */ | 1399 | if (get_user(uval, (u32 __user *)optval)) { |
1411 | if (v != RT_TABLE_DEFAULT && v >= 1000000000) | 1400 | ret = -EFAULT; |
1412 | return -EINVAL; | 1401 | break; |
1402 | } | ||
1413 | 1403 | ||
1414 | rtnl_lock(); | ||
1415 | ret = 0; | ||
1416 | if (sk == rtnl_dereference(mrt->mroute_sk)) { | 1404 | if (sk == rtnl_dereference(mrt->mroute_sk)) { |
1417 | ret = -EBUSY; | 1405 | ret = -EBUSY; |
1418 | } else { | 1406 | } else { |
1419 | if (!ipmr_new_table(net, v)) | 1407 | mrt = ipmr_new_table(net, uval); |
1420 | ret = -ENOMEM; | 1408 | if (IS_ERR(mrt)) |
1409 | ret = PTR_ERR(mrt); | ||
1421 | else | 1410 | else |
1422 | raw_sk(sk)->ipmr_table = v; | 1411 | raw_sk(sk)->ipmr_table = uval; |
1423 | } | 1412 | } |
1424 | rtnl_unlock(); | 1413 | break; |
1425 | return ret; | 1414 | /* Spurious command, or MRT_VERSION which you cannot set. */ |
1426 | } | ||
1427 | #endif | ||
1428 | /* | ||
1429 | * Spurious command, or MRT_VERSION which you cannot | ||
1430 | * set. | ||
1431 | */ | ||
1432 | default: | 1415 | default: |
1433 | return -ENOPROTOOPT; | 1416 | ret = -ENOPROTOOPT; |
1434 | } | 1417 | } |
1418 | out_unlock: | ||
1419 | rtnl_unlock(); | ||
1420 | out: | ||
1421 | return ret; | ||
1435 | } | 1422 | } |
1436 | 1423 | ||
1437 | /* | 1424 | /* Getsock opt support for the multicast routing system. */ |
1438 | * Getsock opt support for the multicast routing system. | ||
1439 | */ | ||
1440 | |||
1441 | int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int __user *optlen) | 1425 | int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int __user *optlen) |
1442 | { | 1426 | { |
1443 | int olr; | 1427 | int olr; |
@@ -1453,39 +1437,35 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int | |||
1453 | if (!mrt) | 1437 | if (!mrt) |
1454 | return -ENOENT; | 1438 | return -ENOENT; |
1455 | 1439 | ||
1456 | if (optname != MRT_VERSION && | 1440 | switch (optname) { |
1457 | #ifdef CONFIG_IP_PIMSM | 1441 | case MRT_VERSION: |
1458 | optname != MRT_PIM && | 1442 | val = 0x0305; |
1459 | #endif | 1443 | break; |
1460 | optname != MRT_ASSERT) | 1444 | case MRT_PIM: |
1445 | if (!ipmr_pimsm_enabled()) | ||
1446 | return -ENOPROTOOPT; | ||
1447 | val = mrt->mroute_do_pim; | ||
1448 | break; | ||
1449 | case MRT_ASSERT: | ||
1450 | val = mrt->mroute_do_assert; | ||
1451 | break; | ||
1452 | default: | ||
1461 | return -ENOPROTOOPT; | 1453 | return -ENOPROTOOPT; |
1454 | } | ||
1462 | 1455 | ||
1463 | if (get_user(olr, optlen)) | 1456 | if (get_user(olr, optlen)) |
1464 | return -EFAULT; | 1457 | return -EFAULT; |
1465 | |||
1466 | olr = min_t(unsigned int, olr, sizeof(int)); | 1458 | olr = min_t(unsigned int, olr, sizeof(int)); |
1467 | if (olr < 0) | 1459 | if (olr < 0) |
1468 | return -EINVAL; | 1460 | return -EINVAL; |
1469 | |||
1470 | if (put_user(olr, optlen)) | 1461 | if (put_user(olr, optlen)) |
1471 | return -EFAULT; | 1462 | return -EFAULT; |
1472 | if (optname == MRT_VERSION) | ||
1473 | val = 0x0305; | ||
1474 | #ifdef CONFIG_IP_PIMSM | ||
1475 | else if (optname == MRT_PIM) | ||
1476 | val = mrt->mroute_do_pim; | ||
1477 | #endif | ||
1478 | else | ||
1479 | val = mrt->mroute_do_assert; | ||
1480 | if (copy_to_user(optval, &val, olr)) | 1463 | if (copy_to_user(optval, &val, olr)) |
1481 | return -EFAULT; | 1464 | return -EFAULT; |
1482 | return 0; | 1465 | return 0; |
1483 | } | 1466 | } |
1484 | 1467 | ||
1485 | /* | 1468 | /* The IP multicast ioctl support routines. */ |
1486 | * The IP multicast ioctl support routines. | ||
1487 | */ | ||
1488 | |||
1489 | int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) | 1469 | int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) |
1490 | { | 1470 | { |
1491 | struct sioc_sg_req sr; | 1471 | struct sioc_sg_req sr; |
@@ -1618,7 +1598,6 @@ int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) | |||
1618 | } | 1598 | } |
1619 | #endif | 1599 | #endif |
1620 | 1600 | ||
1621 | |||
1622 | static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr) | 1601 | static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr) |
1623 | { | 1602 | { |
1624 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 1603 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
@@ -1640,17 +1619,14 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v | |||
1640 | return NOTIFY_DONE; | 1619 | return NOTIFY_DONE; |
1641 | } | 1620 | } |
1642 | 1621 | ||
1643 | |||
1644 | static struct notifier_block ip_mr_notifier = { | 1622 | static struct notifier_block ip_mr_notifier = { |
1645 | .notifier_call = ipmr_device_event, | 1623 | .notifier_call = ipmr_device_event, |
1646 | }; | 1624 | }; |
1647 | 1625 | ||
1648 | /* | 1626 | /* Encapsulate a packet by attaching a valid IPIP header to it. |
1649 | * Encapsulate a packet by attaching a valid IPIP header to it. | 1627 | * This avoids tunnel drivers and other mess and gives us the speed so |
1650 | * This avoids tunnel drivers and other mess and gives us the speed so | 1628 | * important for multicast video. |
1651 | * important for multicast video. | ||
1652 | */ | 1629 | */ |
1653 | |||
1654 | static void ip_encap(struct net *net, struct sk_buff *skb, | 1630 | static void ip_encap(struct net *net, struct sk_buff *skb, |
1655 | __be32 saddr, __be32 daddr) | 1631 | __be32 saddr, __be32 daddr) |
1656 | { | 1632 | { |
@@ -1692,9 +1668,7 @@ static inline int ipmr_forward_finish(struct net *net, struct sock *sk, | |||
1692 | return dst_output(net, sk, skb); | 1668 | return dst_output(net, sk, skb); |
1693 | } | 1669 | } |
1694 | 1670 | ||
1695 | /* | 1671 | /* Processing handlers for ipmr_forward */ |
1696 | * Processing handlers for ipmr_forward | ||
1697 | */ | ||
1698 | 1672 | ||
1699 | static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | 1673 | static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, |
1700 | struct sk_buff *skb, struct mfc_cache *c, int vifi) | 1674 | struct sk_buff *skb, struct mfc_cache *c, int vifi) |
@@ -1709,7 +1683,6 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1709 | if (!vif->dev) | 1683 | if (!vif->dev) |
1710 | goto out_free; | 1684 | goto out_free; |
1711 | 1685 | ||
1712 | #ifdef CONFIG_IP_PIMSM | ||
1713 | if (vif->flags & VIFF_REGISTER) { | 1686 | if (vif->flags & VIFF_REGISTER) { |
1714 | vif->pkt_out++; | 1687 | vif->pkt_out++; |
1715 | vif->bytes_out += skb->len; | 1688 | vif->bytes_out += skb->len; |
@@ -1718,7 +1691,6 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1718 | ipmr_cache_report(mrt, skb, vifi, IGMPMSG_WHOLEPKT); | 1691 | ipmr_cache_report(mrt, skb, vifi, IGMPMSG_WHOLEPKT); |
1719 | goto out_free; | 1692 | goto out_free; |
1720 | } | 1693 | } |
1721 | #endif | ||
1722 | 1694 | ||
1723 | if (vif->flags & VIFF_TUNNEL) { | 1695 | if (vif->flags & VIFF_TUNNEL) { |
1724 | rt = ip_route_output_ports(net, &fl4, NULL, | 1696 | rt = ip_route_output_ports(net, &fl4, NULL, |
@@ -1745,7 +1717,6 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1745 | * allow to send ICMP, so that packets will disappear | 1717 | * allow to send ICMP, so that packets will disappear |
1746 | * to blackhole. | 1718 | * to blackhole. |
1747 | */ | 1719 | */ |
1748 | |||
1749 | IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); | 1720 | IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); |
1750 | ip_rt_put(rt); | 1721 | ip_rt_put(rt); |
1751 | goto out_free; | 1722 | goto out_free; |
@@ -1777,8 +1748,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1777 | 1748 | ||
1778 | IPCB(skb)->flags |= IPSKB_FORWARDED; | 1749 | IPCB(skb)->flags |= IPSKB_FORWARDED; |
1779 | 1750 | ||
1780 | /* | 1751 | /* RFC1584 teaches, that DVMRP/PIM router must deliver packets locally |
1781 | * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally | ||
1782 | * not only before forwarding, but after forwarding on all output | 1752 | * not only before forwarding, but after forwarding on all output |
1783 | * interfaces. It is clear, if mrouter runs a multicasting | 1753 | * interfaces. It is clear, if mrouter runs a multicasting |
1784 | * program, it should receive packets not depending to what interface | 1754 | * program, it should receive packets not depending to what interface |
@@ -1809,7 +1779,6 @@ static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev) | |||
1809 | } | 1779 | } |
1810 | 1780 | ||
1811 | /* "local" means that we should preserve one skb (for local delivery) */ | 1781 | /* "local" means that we should preserve one skb (for local delivery) */ |
1812 | |||
1813 | static void ip_mr_forward(struct net *net, struct mr_table *mrt, | 1782 | static void ip_mr_forward(struct net *net, struct mr_table *mrt, |
1814 | struct sk_buff *skb, struct mfc_cache *cache, | 1783 | struct sk_buff *skb, struct mfc_cache *cache, |
1815 | int local) | 1784 | int local) |
@@ -1834,9 +1803,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, | |||
1834 | goto forward; | 1803 | goto forward; |
1835 | } | 1804 | } |
1836 | 1805 | ||
1837 | /* | 1806 | /* Wrong interface: drop packet and (maybe) send PIM assert. */ |
1838 | * Wrong interface: drop packet and (maybe) send PIM assert. | ||
1839 | */ | ||
1840 | if (mrt->vif_table[vif].dev != skb->dev) { | 1807 | if (mrt->vif_table[vif].dev != skb->dev) { |
1841 | if (rt_is_output_route(skb_rtable(skb))) { | 1808 | if (rt_is_output_route(skb_rtable(skb))) { |
1842 | /* It is our own packet, looped back. | 1809 | /* It is our own packet, looped back. |
@@ -1875,9 +1842,7 @@ forward: | |||
1875 | mrt->vif_table[vif].pkt_in++; | 1842 | mrt->vif_table[vif].pkt_in++; |
1876 | mrt->vif_table[vif].bytes_in += skb->len; | 1843 | mrt->vif_table[vif].bytes_in += skb->len; |
1877 | 1844 | ||
1878 | /* | 1845 | /* Forward the frame */ |
1879 | * Forward the frame | ||
1880 | */ | ||
1881 | if (cache->mfc_origin == htonl(INADDR_ANY) && | 1846 | if (cache->mfc_origin == htonl(INADDR_ANY) && |
1882 | cache->mfc_mcastgrp == htonl(INADDR_ANY)) { | 1847 | cache->mfc_mcastgrp == htonl(INADDR_ANY)) { |
1883 | if (true_vifi >= 0 && | 1848 | if (true_vifi >= 0 && |
@@ -1951,11 +1916,9 @@ static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb) | |||
1951 | return mrt; | 1916 | return mrt; |
1952 | } | 1917 | } |
1953 | 1918 | ||
1954 | /* | 1919 | /* Multicast packets for forwarding arrive here |
1955 | * Multicast packets for forwarding arrive here | 1920 | * Called with rcu_read_lock(); |
1956 | * Called with rcu_read_lock(); | ||
1957 | */ | 1921 | */ |
1958 | |||
1959 | int ip_mr_input(struct sk_buff *skb) | 1922 | int ip_mr_input(struct sk_buff *skb) |
1960 | { | 1923 | { |
1961 | struct mfc_cache *cache; | 1924 | struct mfc_cache *cache; |
@@ -2006,9 +1969,7 @@ int ip_mr_input(struct sk_buff *skb) | |||
2006 | vif); | 1969 | vif); |
2007 | } | 1970 | } |
2008 | 1971 | ||
2009 | /* | 1972 | /* No usable cache entry */ |
2010 | * No usable cache entry | ||
2011 | */ | ||
2012 | if (!cache) { | 1973 | if (!cache) { |
2013 | int vif; | 1974 | int vif; |
2014 | 1975 | ||
@@ -2049,53 +2010,8 @@ dont_forward: | |||
2049 | return 0; | 2010 | return 0; |
2050 | } | 2011 | } |
2051 | 2012 | ||
2052 | #ifdef CONFIG_IP_PIMSM | ||
2053 | /* called with rcu_read_lock() */ | ||
2054 | static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb, | ||
2055 | unsigned int pimlen) | ||
2056 | { | ||
2057 | struct net_device *reg_dev = NULL; | ||
2058 | struct iphdr *encap; | ||
2059 | |||
2060 | encap = (struct iphdr *)(skb_transport_header(skb) + pimlen); | ||
2061 | /* | ||
2062 | * Check that: | ||
2063 | * a. packet is really sent to a multicast group | ||
2064 | * b. packet is not a NULL-REGISTER | ||
2065 | * c. packet is not truncated | ||
2066 | */ | ||
2067 | if (!ipv4_is_multicast(encap->daddr) || | ||
2068 | encap->tot_len == 0 || | ||
2069 | ntohs(encap->tot_len) + pimlen > skb->len) | ||
2070 | return 1; | ||
2071 | |||
2072 | read_lock(&mrt_lock); | ||
2073 | if (mrt->mroute_reg_vif_num >= 0) | ||
2074 | reg_dev = mrt->vif_table[mrt->mroute_reg_vif_num].dev; | ||
2075 | read_unlock(&mrt_lock); | ||
2076 | |||
2077 | if (!reg_dev) | ||
2078 | return 1; | ||
2079 | |||
2080 | skb->mac_header = skb->network_header; | ||
2081 | skb_pull(skb, (u8 *)encap - skb->data); | ||
2082 | skb_reset_network_header(skb); | ||
2083 | skb->protocol = htons(ETH_P_IP); | ||
2084 | skb->ip_summed = CHECKSUM_NONE; | ||
2085 | |||
2086 | skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev)); | ||
2087 | |||
2088 | netif_rx(skb); | ||
2089 | |||
2090 | return NET_RX_SUCCESS; | ||
2091 | } | ||
2092 | #endif | ||
2093 | |||
2094 | #ifdef CONFIG_IP_PIMSM_V1 | 2013 | #ifdef CONFIG_IP_PIMSM_V1 |
2095 | /* | 2014 | /* Handle IGMP messages of PIMv1 */ |
2096 | * Handle IGMP messages of PIMv1 | ||
2097 | */ | ||
2098 | |||
2099 | int pim_rcv_v1(struct sk_buff *skb) | 2015 | int pim_rcv_v1(struct sk_buff *skb) |
2100 | { | 2016 | { |
2101 | struct igmphdr *pim; | 2017 | struct igmphdr *pim; |
@@ -2256,8 +2172,6 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb, | |||
2256 | } | 2172 | } |
2257 | 2173 | ||
2258 | read_lock(&mrt_lock); | 2174 | read_lock(&mrt_lock); |
2259 | if (!nowait && (rtm->rtm_flags & RTM_F_NOTIFY)) | ||
2260 | cache->mfc_flags |= MFC_NOTIFY; | ||
2261 | err = __ipmr_fill_mroute(mrt, skb, cache, rtm); | 2175 | err = __ipmr_fill_mroute(mrt, skb, cache, rtm); |
2262 | read_unlock(&mrt_lock); | 2176 | read_unlock(&mrt_lock); |
2263 | rcu_read_unlock(); | 2177 | rcu_read_unlock(); |
@@ -2419,10 +2333,133 @@ done: | |||
2419 | return skb->len; | 2333 | return skb->len; |
2420 | } | 2334 | } |
2421 | 2335 | ||
2336 | static const struct nla_policy rtm_ipmr_policy[RTA_MAX + 1] = { | ||
2337 | [RTA_SRC] = { .type = NLA_U32 }, | ||
2338 | [RTA_DST] = { .type = NLA_U32 }, | ||
2339 | [RTA_IIF] = { .type = NLA_U32 }, | ||
2340 | [RTA_TABLE] = { .type = NLA_U32 }, | ||
2341 | [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, | ||
2342 | }; | ||
2343 | |||
2344 | static bool ipmr_rtm_validate_proto(unsigned char rtm_protocol) | ||
2345 | { | ||
2346 | switch (rtm_protocol) { | ||
2347 | case RTPROT_STATIC: | ||
2348 | case RTPROT_MROUTED: | ||
2349 | return true; | ||
2350 | } | ||
2351 | return false; | ||
2352 | } | ||
2353 | |||
2354 | static int ipmr_nla_get_ttls(const struct nlattr *nla, struct mfcctl *mfcc) | ||
2355 | { | ||
2356 | struct rtnexthop *rtnh = nla_data(nla); | ||
2357 | int remaining = nla_len(nla), vifi = 0; | ||
2358 | |||
2359 | while (rtnh_ok(rtnh, remaining)) { | ||
2360 | mfcc->mfcc_ttls[vifi] = rtnh->rtnh_hops; | ||
2361 | if (++vifi == MAXVIFS) | ||
2362 | break; | ||
2363 | rtnh = rtnh_next(rtnh, &remaining); | ||
2364 | } | ||
2365 | |||
2366 | return remaining > 0 ? -EINVAL : vifi; | ||
2367 | } | ||
2368 | |||
2369 | /* returns < 0 on error, 0 for ADD_MFC and 1 for ADD_MFC_PROXY */ | ||
2370 | static int rtm_to_ipmr_mfcc(struct net *net, struct nlmsghdr *nlh, | ||
2371 | struct mfcctl *mfcc, int *mrtsock, | ||
2372 | struct mr_table **mrtret) | ||
2373 | { | ||
2374 | struct net_device *dev = NULL; | ||
2375 | u32 tblid = RT_TABLE_DEFAULT; | ||
2376 | struct mr_table *mrt; | ||
2377 | struct nlattr *attr; | ||
2378 | struct rtmsg *rtm; | ||
2379 | int ret, rem; | ||
2380 | |||
2381 | ret = nlmsg_validate(nlh, sizeof(*rtm), RTA_MAX, rtm_ipmr_policy); | ||
2382 | if (ret < 0) | ||
2383 | goto out; | ||
2384 | rtm = nlmsg_data(nlh); | ||
2385 | |||
2386 | ret = -EINVAL; | ||
2387 | if (rtm->rtm_family != RTNL_FAMILY_IPMR || rtm->rtm_dst_len != 32 || | ||
2388 | rtm->rtm_type != RTN_MULTICAST || | ||
2389 | rtm->rtm_scope != RT_SCOPE_UNIVERSE || | ||
2390 | !ipmr_rtm_validate_proto(rtm->rtm_protocol)) | ||
2391 | goto out; | ||
2392 | |||
2393 | memset(mfcc, 0, sizeof(*mfcc)); | ||
2394 | mfcc->mfcc_parent = -1; | ||
2395 | ret = 0; | ||
2396 | nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), rem) { | ||
2397 | switch (nla_type(attr)) { | ||
2398 | case RTA_SRC: | ||
2399 | mfcc->mfcc_origin.s_addr = nla_get_be32(attr); | ||
2400 | break; | ||
2401 | case RTA_DST: | ||
2402 | mfcc->mfcc_mcastgrp.s_addr = nla_get_be32(attr); | ||
2403 | break; | ||
2404 | case RTA_IIF: | ||
2405 | dev = __dev_get_by_index(net, nla_get_u32(attr)); | ||
2406 | if (!dev) { | ||
2407 | ret = -ENODEV; | ||
2408 | goto out; | ||
2409 | } | ||
2410 | break; | ||
2411 | case RTA_MULTIPATH: | ||
2412 | if (ipmr_nla_get_ttls(attr, mfcc) < 0) { | ||
2413 | ret = -EINVAL; | ||
2414 | goto out; | ||
2415 | } | ||
2416 | break; | ||
2417 | case RTA_PREFSRC: | ||
2418 | ret = 1; | ||
2419 | break; | ||
2420 | case RTA_TABLE: | ||
2421 | tblid = nla_get_u32(attr); | ||
2422 | break; | ||
2423 | } | ||
2424 | } | ||
2425 | mrt = ipmr_get_table(net, tblid); | ||
2426 | if (!mrt) { | ||
2427 | ret = -ENOENT; | ||
2428 | goto out; | ||
2429 | } | ||
2430 | *mrtret = mrt; | ||
2431 | *mrtsock = rtm->rtm_protocol == RTPROT_MROUTED ? 1 : 0; | ||
2432 | if (dev) | ||
2433 | mfcc->mfcc_parent = ipmr_find_vif(mrt, dev); | ||
2434 | |||
2435 | out: | ||
2436 | return ret; | ||
2437 | } | ||
2438 | |||
2439 | /* takes care of both newroute and delroute */ | ||
2440 | static int ipmr_rtm_route(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
2441 | { | ||
2442 | struct net *net = sock_net(skb->sk); | ||
2443 | int ret, mrtsock, parent; | ||
2444 | struct mr_table *tbl; | ||
2445 | struct mfcctl mfcc; | ||
2446 | |||
2447 | mrtsock = 0; | ||
2448 | tbl = NULL; | ||
2449 | ret = rtm_to_ipmr_mfcc(net, nlh, &mfcc, &mrtsock, &tbl); | ||
2450 | if (ret < 0) | ||
2451 | return ret; | ||
2452 | |||
2453 | parent = ret ? mfcc.mfcc_parent : -1; | ||
2454 | if (nlh->nlmsg_type == RTM_NEWROUTE) | ||
2455 | return ipmr_mfc_add(net, tbl, &mfcc, mrtsock, parent); | ||
2456 | else | ||
2457 | return ipmr_mfc_delete(tbl, &mfcc, parent); | ||
2458 | } | ||
2459 | |||
2422 | #ifdef CONFIG_PROC_FS | 2460 | #ifdef CONFIG_PROC_FS |
2423 | /* | 2461 | /* The /proc interfaces to multicast routing : |
2424 | * The /proc interfaces to multicast routing : | 2462 | * /proc/net/ip_mr_cache & /proc/net/ip_mr_vif |
2425 | * /proc/net/ip_mr_cache & /proc/net/ip_mr_vif | ||
2426 | */ | 2463 | */ |
2427 | struct ipmr_vif_iter { | 2464 | struct ipmr_vif_iter { |
2428 | struct seq_net_private p; | 2465 | struct seq_net_private p; |
@@ -2706,10 +2743,7 @@ static const struct net_protocol pim_protocol = { | |||
2706 | }; | 2743 | }; |
2707 | #endif | 2744 | #endif |
2708 | 2745 | ||
2709 | 2746 | /* Setup for IP multicast routing */ | |
2710 | /* | ||
2711 | * Setup for IP multicast routing | ||
2712 | */ | ||
2713 | static int __net_init ipmr_net_init(struct net *net) | 2747 | static int __net_init ipmr_net_init(struct net *net) |
2714 | { | 2748 | { |
2715 | int err; | 2749 | int err; |
@@ -2759,8 +2793,6 @@ int __init ip_mr_init(void) | |||
2759 | sizeof(struct mfc_cache), | 2793 | sizeof(struct mfc_cache), |
2760 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, | 2794 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, |
2761 | NULL); | 2795 | NULL); |
2762 | if (!mrt_cachep) | ||
2763 | return -ENOMEM; | ||
2764 | 2796 | ||
2765 | err = register_pernet_subsys(&ipmr_net_ops); | 2797 | err = register_pernet_subsys(&ipmr_net_ops); |
2766 | if (err) | 2798 | if (err) |
@@ -2778,6 +2810,10 @@ int __init ip_mr_init(void) | |||
2778 | #endif | 2810 | #endif |
2779 | rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, | 2811 | rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, |
2780 | NULL, ipmr_rtm_dumproute, NULL); | 2812 | NULL, ipmr_rtm_dumproute, NULL); |
2813 | rtnl_register(RTNL_FAMILY_IPMR, RTM_NEWROUTE, | ||
2814 | ipmr_rtm_route, NULL, NULL); | ||
2815 | rtnl_register(RTNL_FAMILY_IPMR, RTM_DELROUTE, | ||
2816 | ipmr_rtm_route, NULL, NULL); | ||
2781 | return 0; | 2817 | return 0; |
2782 | 2818 | ||
2783 | #ifdef CONFIG_IP_PIMSM_V2 | 2819 | #ifdef CONFIG_IP_PIMSM_V2 |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index a35584176535..c187c60e3e0c 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -60,6 +60,7 @@ config NFT_REJECT_IPV4 | |||
60 | 60 | ||
61 | config NFT_DUP_IPV4 | 61 | config NFT_DUP_IPV4 |
62 | tristate "IPv4 nf_tables packet duplication support" | 62 | tristate "IPv4 nf_tables packet duplication support" |
63 | depends on !NF_CONNTRACK || NF_CONNTRACK | ||
63 | select NF_DUP_IPV4 | 64 | select NF_DUP_IPV4 |
64 | help | 65 | help |
65 | This module enables IPv4 packet duplication support for nf_tables. | 66 | This module enables IPv4 packet duplication support for nf_tables. |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 11dccba474b7..b488cac9c5ca 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -38,13 +38,13 @@ MODULE_DESCRIPTION("arptables core"); | |||
38 | /*#define DEBUG_ARP_TABLES_USER*/ | 38 | /*#define DEBUG_ARP_TABLES_USER*/ |
39 | 39 | ||
40 | #ifdef DEBUG_ARP_TABLES | 40 | #ifdef DEBUG_ARP_TABLES |
41 | #define dprintf(format, args...) printk(format , ## args) | 41 | #define dprintf(format, args...) pr_debug(format, ## args) |
42 | #else | 42 | #else |
43 | #define dprintf(format, args...) | 43 | #define dprintf(format, args...) |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #ifdef DEBUG_ARP_TABLES_USER | 46 | #ifdef DEBUG_ARP_TABLES_USER |
47 | #define duprintf(format, args...) printk(format , ## args) | 47 | #define duprintf(format, args...) pr_debug(format, ## args) |
48 | #else | 48 | #else |
49 | #define duprintf(format, args...) | 49 | #define duprintf(format, args...) |
50 | #endif | 50 | #endif |
@@ -1905,7 +1905,7 @@ static int __init arp_tables_init(void) | |||
1905 | if (ret < 0) | 1905 | if (ret < 0) |
1906 | goto err4; | 1906 | goto err4; |
1907 | 1907 | ||
1908 | printk(KERN_INFO "arp_tables: (C) 2002 David S. Miller\n"); | 1908 | pr_info("arp_tables: (C) 2002 David S. Miller\n"); |
1909 | return 0; | 1909 | return 0; |
1910 | 1910 | ||
1911 | err4: | 1911 | err4: |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 461ca926fd39..e3c46e8e2762 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -451,7 +451,7 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) | |||
451 | 451 | ||
452 | ret = nf_register_sockopt(&so_getorigdst); | 452 | ret = nf_register_sockopt(&so_getorigdst); |
453 | if (ret < 0) { | 453 | if (ret < 0) { |
454 | printk(KERN_ERR "Unable to register netfilter socket option\n"); | 454 | pr_err("Unable to register netfilter socket option\n"); |
455 | return ret; | 455 | return ret; |
456 | } | 456 | } |
457 | 457 | ||
diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index 5075b7ecd26d..61c7cc22ea68 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | |||
@@ -132,7 +132,8 @@ static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, | |||
132 | 132 | ||
133 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 133 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
134 | if (!(rt->rt_flags & RTCF_LOCAL) && | 134 | if (!(rt->rt_flags & RTCF_LOCAL) && |
135 | (!skb->dev || skb->dev->features & NETIF_F_V4_CSUM)) { | 135 | (!skb->dev || skb->dev->features & |
136 | (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM))) { | ||
136 | skb->ip_summed = CHECKSUM_PARTIAL; | 137 | skb->ip_summed = CHECKSUM_PARTIAL; |
137 | skb->csum_start = skb_headroom(skb) + | 138 | skb->csum_start = skb_headroom(skb) + |
138 | skb_network_offset(skb) + | 139 | skb_network_offset(skb) + |
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index ddb894ac1458..c9b52c361da2 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c | |||
@@ -1048,7 +1048,7 @@ static int snmp_parse_mangle(unsigned char *msg, | |||
1048 | if (!asn1_uint_decode (&ctx, end, &vers)) | 1048 | if (!asn1_uint_decode (&ctx, end, &vers)) |
1049 | return 0; | 1049 | return 0; |
1050 | if (debug > 1) | 1050 | if (debug > 1) |
1051 | printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1); | 1051 | pr_debug("bsalg: snmp version: %u\n", vers + 1); |
1052 | if (vers > 1) | 1052 | if (vers > 1) |
1053 | return 1; | 1053 | return 1; |
1054 | 1054 | ||
@@ -1064,10 +1064,10 @@ static int snmp_parse_mangle(unsigned char *msg, | |||
1064 | if (debug > 1) { | 1064 | if (debug > 1) { |
1065 | unsigned int i; | 1065 | unsigned int i; |
1066 | 1066 | ||
1067 | printk(KERN_DEBUG "bsalg: community: "); | 1067 | pr_debug("bsalg: community: "); |
1068 | for (i = 0; i < comm.len; i++) | 1068 | for (i = 0; i < comm.len; i++) |
1069 | printk("%c", comm.data[i]); | 1069 | pr_cont("%c", comm.data[i]); |
1070 | printk("\n"); | 1070 | pr_cont("\n"); |
1071 | } | 1071 | } |
1072 | kfree(comm.data); | 1072 | kfree(comm.data); |
1073 | 1073 | ||
@@ -1091,9 +1091,9 @@ static int snmp_parse_mangle(unsigned char *msg, | |||
1091 | }; | 1091 | }; |
1092 | 1092 | ||
1093 | if (pdutype > SNMP_PDU_TRAP2) | 1093 | if (pdutype > SNMP_PDU_TRAP2) |
1094 | printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype); | 1094 | pr_debug("bsalg: bad pdu type %u\n", pdutype); |
1095 | else | 1095 | else |
1096 | printk(KERN_DEBUG "bsalg: pdu: %s\n", pdus[pdutype]); | 1096 | pr_debug("bsalg: pdu: %s\n", pdus[pdutype]); |
1097 | } | 1097 | } |
1098 | if (pdutype != SNMP_PDU_RESPONSE && | 1098 | if (pdutype != SNMP_PDU_RESPONSE && |
1099 | pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2) | 1099 | pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2) |
@@ -1119,7 +1119,7 @@ static int snmp_parse_mangle(unsigned char *msg, | |||
1119 | return 0; | 1119 | return 0; |
1120 | 1120 | ||
1121 | if (debug > 1) | 1121 | if (debug > 1) |
1122 | printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u " | 1122 | pr_debug("bsalg: request: id=0x%lx error_status=%u " |
1123 | "error_index=%u\n", req.id, req.error_status, | 1123 | "error_index=%u\n", req.id, req.error_status, |
1124 | req.error_index); | 1124 | req.error_index); |
1125 | } | 1125 | } |
@@ -1145,13 +1145,13 @@ static int snmp_parse_mangle(unsigned char *msg, | |||
1145 | } | 1145 | } |
1146 | 1146 | ||
1147 | if (debug > 1) { | 1147 | if (debug > 1) { |
1148 | printk(KERN_DEBUG "bsalg: object: "); | 1148 | pr_debug("bsalg: object: "); |
1149 | for (i = 0; i < obj->id_len; i++) { | 1149 | for (i = 0; i < obj->id_len; i++) { |
1150 | if (i > 0) | 1150 | if (i > 0) |
1151 | printk("."); | 1151 | pr_cont("."); |
1152 | printk("%lu", obj->id[i]); | 1152 | pr_cont("%lu", obj->id[i]); |
1153 | } | 1153 | } |
1154 | printk(": type=%u\n", obj->type); | 1154 | pr_cont(": type=%u\n", obj->type); |
1155 | 1155 | ||
1156 | } | 1156 | } |
1157 | 1157 | ||
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index c747b2d9eb77..b6ea57ec5e14 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <net/netfilter/ipv4/nf_reject.h> | 14 | #include <net/netfilter/ipv4/nf_reject.h> |
15 | #include <linux/netfilter_ipv4.h> | 15 | #include <linux/netfilter_ipv4.h> |
16 | #include <linux/netfilter_bridge.h> | 16 | #include <linux/netfilter_bridge.h> |
17 | #include <net/netfilter/ipv4/nf_reject.h> | ||
18 | 17 | ||
19 | const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, | 18 | const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, |
20 | struct tcphdr *_oth, int hook) | 19 | struct tcphdr *_oth, int hook) |
diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c index 9d09d4f59545..cd84d4295a20 100644 --- a/net/ipv4/netfilter/nf_tables_arp.c +++ b/net/ipv4/netfilter/nf_tables_arp.c | |||
@@ -57,7 +57,7 @@ err: | |||
57 | 57 | ||
58 | static void nf_tables_arp_exit_net(struct net *net) | 58 | static void nf_tables_arp_exit_net(struct net *net) |
59 | { | 59 | { |
60 | nft_unregister_afinfo(net->nft.arp); | 60 | nft_unregister_afinfo(net, net->nft.arp); |
61 | kfree(net->nft.arp); | 61 | kfree(net->nft.arp); |
62 | } | 62 | } |
63 | 63 | ||
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c index ca9dc3c46c4f..e44ba3b12fbb 100644 --- a/net/ipv4/netfilter/nf_tables_ipv4.c +++ b/net/ipv4/netfilter/nf_tables_ipv4.c | |||
@@ -78,7 +78,7 @@ err: | |||
78 | 78 | ||
79 | static void nf_tables_ipv4_exit_net(struct net *net) | 79 | static void nf_tables_ipv4_exit_net(struct net *net) |
80 | { | 80 | { |
81 | nft_unregister_afinfo(net->nft.ipv4); | 81 | nft_unregister_afinfo(net, net->nft.ipv4); |
82 | kfree(net->nft.ipv4); | 82 | kfree(net->nft.ipv4); |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index e89094ab5ddb..c117b21b937d 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -1063,6 +1063,7 @@ static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos) | |||
1063 | } | 1063 | } |
1064 | 1064 | ||
1065 | void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family) | 1065 | void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family) |
1066 | __acquires(ping_table.lock) | ||
1066 | { | 1067 | { |
1067 | struct ping_iter_state *state = seq->private; | 1068 | struct ping_iter_state *state = seq->private; |
1068 | state->bucket = 0; | 1069 | state->bucket = 0; |
@@ -1094,6 +1095,7 @@ void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1094 | EXPORT_SYMBOL_GPL(ping_seq_next); | 1095 | EXPORT_SYMBOL_GPL(ping_seq_next); |
1095 | 1096 | ||
1096 | void ping_seq_stop(struct seq_file *seq, void *v) | 1097 | void ping_seq_stop(struct seq_file *seq, void *v) |
1098 | __releases(ping_table.lock) | ||
1097 | { | 1099 | { |
1098 | read_unlock_bh(&ping_table.lock); | 1100 | read_unlock_bh(&ping_table.lock); |
1099 | } | 1101 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 63e5be0abd86..bc35f1842512 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -601,8 +601,11 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
601 | (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), | 601 | (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), |
602 | daddr, saddr, 0, 0); | 602 | daddr, saddr, 0, 0); |
603 | 603 | ||
604 | if (!saddr && ipc.oif) | 604 | if (!saddr && ipc.oif) { |
605 | l3mdev_get_saddr(net, ipc.oif, &fl4); | 605 | err = l3mdev_get_saddr(net, ipc.oif, &fl4); |
606 | if (err < 0) | ||
607 | goto done; | ||
608 | } | ||
606 | 609 | ||
607 | if (!inet->hdrincl) { | 610 | if (!inet->hdrincl) { |
608 | rfv.msg = msg; | 611 | rfv.msg = msg; |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 4cbe9f0a4281..643a86c49020 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -351,7 +351,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
351 | treq->snt_synack.v64 = 0; | 351 | treq->snt_synack.v64 = 0; |
352 | treq->tfo_listener = false; | 352 | treq->tfo_listener = false; |
353 | 353 | ||
354 | ireq->ir_iif = sk->sk_bound_dev_if; | 354 | ireq->ir_iif = inet_request_bound_dev_if(sk, skb); |
355 | 355 | ||
356 | /* We throwed the options of the initial SYN away, so we hope | 356 | /* We throwed the options of the initial SYN away, so we hope |
357 | * the ACK carries the same options again (see RFC1122 4.2.3.8) | 357 | * the ACK carries the same options again (see RFC1122 4.2.3.8) |
@@ -371,7 +371,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) | |||
371 | * hasn't changed since we received the original syn, but I see | 371 | * hasn't changed since we received the original syn, but I see |
372 | * no easy way to do this. | 372 | * no easy way to do this. |
373 | */ | 373 | */ |
374 | flowi4_init_output(&fl4, sk->sk_bound_dev_if, ireq->ir_mark, | 374 | flowi4_init_output(&fl4, ireq->ir_iif, ireq->ir_mark, |
375 | RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP, | 375 | RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP, |
376 | inet_sk_flowi_flags(sk), | 376 | inet_sk_flowi_flags(sk), |
377 | opt->srr ? opt->faddr : ireq->ir_rmt_addr, | 377 | opt->srr ? opt->faddr : ireq->ir_rmt_addr, |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index a0bd7a55193e..46ce410703b1 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -337,27 +337,6 @@ static struct ctl_table ipv4_table[] = { | |||
337 | .proc_handler = proc_dointvec | 337 | .proc_handler = proc_dointvec |
338 | }, | 338 | }, |
339 | { | 339 | { |
340 | .procname = "tcp_keepalive_time", | ||
341 | .data = &sysctl_tcp_keepalive_time, | ||
342 | .maxlen = sizeof(int), | ||
343 | .mode = 0644, | ||
344 | .proc_handler = proc_dointvec_jiffies, | ||
345 | }, | ||
346 | { | ||
347 | .procname = "tcp_keepalive_probes", | ||
348 | .data = &sysctl_tcp_keepalive_probes, | ||
349 | .maxlen = sizeof(int), | ||
350 | .mode = 0644, | ||
351 | .proc_handler = proc_dointvec | ||
352 | }, | ||
353 | { | ||
354 | .procname = "tcp_keepalive_intvl", | ||
355 | .data = &sysctl_tcp_keepalive_intvl, | ||
356 | .maxlen = sizeof(int), | ||
357 | .mode = 0644, | ||
358 | .proc_handler = proc_dointvec_jiffies, | ||
359 | }, | ||
360 | { | ||
361 | .procname = "tcp_retries1", | 340 | .procname = "tcp_retries1", |
362 | .data = &sysctl_tcp_retries1, | 341 | .data = &sysctl_tcp_retries1, |
363 | .maxlen = sizeof(int), | 342 | .maxlen = sizeof(int), |
@@ -915,6 +894,17 @@ static struct ctl_table ipv4_net_table[] = { | |||
915 | .mode = 0644, | 894 | .mode = 0644, |
916 | .proc_handler = proc_dointvec, | 895 | .proc_handler = proc_dointvec, |
917 | }, | 896 | }, |
897 | #ifdef CONFIG_NET_L3_MASTER_DEV | ||
898 | { | ||
899 | .procname = "tcp_l3mdev_accept", | ||
900 | .data = &init_net.ipv4.sysctl_tcp_l3mdev_accept, | ||
901 | .maxlen = sizeof(int), | ||
902 | .mode = 0644, | ||
903 | .proc_handler = proc_dointvec_minmax, | ||
904 | .extra1 = &zero, | ||
905 | .extra2 = &one, | ||
906 | }, | ||
907 | #endif | ||
918 | { | 908 | { |
919 | .procname = "tcp_mtu_probing", | 909 | .procname = "tcp_mtu_probing", |
920 | .data = &init_net.ipv4.sysctl_tcp_mtu_probing, | 910 | .data = &init_net.ipv4.sysctl_tcp_mtu_probing, |
@@ -950,6 +940,27 @@ static struct ctl_table ipv4_net_table[] = { | |||
950 | .mode = 0644, | 940 | .mode = 0644, |
951 | .proc_handler = proc_dointvec | 941 | .proc_handler = proc_dointvec |
952 | }, | 942 | }, |
943 | { | ||
944 | .procname = "tcp_keepalive_time", | ||
945 | .data = &init_net.ipv4.sysctl_tcp_keepalive_time, | ||
946 | .maxlen = sizeof(int), | ||
947 | .mode = 0644, | ||
948 | .proc_handler = proc_dointvec_jiffies, | ||
949 | }, | ||
950 | { | ||
951 | .procname = "tcp_keepalive_probes", | ||
952 | .data = &init_net.ipv4.sysctl_tcp_keepalive_probes, | ||
953 | .maxlen = sizeof(int), | ||
954 | .mode = 0644, | ||
955 | .proc_handler = proc_dointvec | ||
956 | }, | ||
957 | { | ||
958 | .procname = "tcp_keepalive_intvl", | ||
959 | .data = &init_net.ipv4.sysctl_tcp_keepalive_intvl, | ||
960 | .maxlen = sizeof(int), | ||
961 | .mode = 0644, | ||
962 | .proc_handler = proc_dointvec_jiffies, | ||
963 | }, | ||
953 | { } | 964 | { } |
954 | }; | 965 | }; |
955 | 966 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c1728771cf89..7bb1b091efd1 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -517,8 +517,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
517 | if (sk_stream_is_writeable(sk)) { | 517 | if (sk_stream_is_writeable(sk)) { |
518 | mask |= POLLOUT | POLLWRNORM; | 518 | mask |= POLLOUT | POLLWRNORM; |
519 | } else { /* send SIGIO later */ | 519 | } else { /* send SIGIO later */ |
520 | set_bit(SOCK_ASYNC_NOSPACE, | 520 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
521 | &sk->sk_socket->flags); | ||
522 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | 521 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
523 | 522 | ||
524 | /* Race breaker. If space is freed after | 523 | /* Race breaker. If space is freed after |
@@ -906,7 +905,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, | |||
906 | goto out_err; | 905 | goto out_err; |
907 | } | 906 | } |
908 | 907 | ||
909 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 908 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
910 | 909 | ||
911 | mss_now = tcp_send_mss(sk, &size_goal, flags); | 910 | mss_now = tcp_send_mss(sk, &size_goal, flags); |
912 | copied = 0; | 911 | copied = 0; |
@@ -1019,7 +1018,7 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset, | |||
1019 | ssize_t res; | 1018 | ssize_t res; |
1020 | 1019 | ||
1021 | if (!(sk->sk_route_caps & NETIF_F_SG) || | 1020 | if (!(sk->sk_route_caps & NETIF_F_SG) || |
1022 | !(sk->sk_route_caps & NETIF_F_ALL_CSUM)) | 1021 | !sk_check_csum_caps(sk)) |
1023 | return sock_no_sendpage(sk->sk_socket, page, offset, size, | 1022 | return sock_no_sendpage(sk->sk_socket, page, offset, size, |
1024 | flags); | 1023 | flags); |
1025 | 1024 | ||
@@ -1134,7 +1133,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) | |||
1134 | } | 1133 | } |
1135 | 1134 | ||
1136 | /* This should be in poll */ | 1135 | /* This should be in poll */ |
1137 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 1136 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
1138 | 1137 | ||
1139 | mss_now = tcp_send_mss(sk, &size_goal, flags); | 1138 | mss_now = tcp_send_mss(sk, &size_goal, flags); |
1140 | 1139 | ||
@@ -1176,7 +1175,7 @@ new_segment: | |||
1176 | /* | 1175 | /* |
1177 | * Check whether we can use HW checksum. | 1176 | * Check whether we can use HW checksum. |
1178 | */ | 1177 | */ |
1179 | if (sk->sk_route_caps & NETIF_F_ALL_CSUM) | 1178 | if (sk_check_csum_caps(sk)) |
1180 | skb->ip_summed = CHECKSUM_PARTIAL; | 1179 | skb->ip_summed = CHECKSUM_PARTIAL; |
1181 | 1180 | ||
1182 | skb_entail(sk, skb); | 1181 | skb_entail(sk, skb); |
@@ -3081,6 +3080,52 @@ void tcp_done(struct sock *sk) | |||
3081 | } | 3080 | } |
3082 | EXPORT_SYMBOL_GPL(tcp_done); | 3081 | EXPORT_SYMBOL_GPL(tcp_done); |
3083 | 3082 | ||
3083 | int tcp_abort(struct sock *sk, int err) | ||
3084 | { | ||
3085 | if (!sk_fullsock(sk)) { | ||
3086 | if (sk->sk_state == TCP_NEW_SYN_RECV) { | ||
3087 | struct request_sock *req = inet_reqsk(sk); | ||
3088 | |||
3089 | local_bh_disable(); | ||
3090 | inet_csk_reqsk_queue_drop_and_put(req->rsk_listener, | ||
3091 | req); | ||
3092 | local_bh_enable(); | ||
3093 | return 0; | ||
3094 | } | ||
3095 | sock_gen_put(sk); | ||
3096 | return -EOPNOTSUPP; | ||
3097 | } | ||
3098 | |||
3099 | /* Don't race with userspace socket closes such as tcp_close. */ | ||
3100 | lock_sock(sk); | ||
3101 | |||
3102 | if (sk->sk_state == TCP_LISTEN) { | ||
3103 | tcp_set_state(sk, TCP_CLOSE); | ||
3104 | inet_csk_listen_stop(sk); | ||
3105 | } | ||
3106 | |||
3107 | /* Don't race with BH socket closes such as inet_csk_listen_stop. */ | ||
3108 | local_bh_disable(); | ||
3109 | bh_lock_sock(sk); | ||
3110 | |||
3111 | if (!sock_flag(sk, SOCK_DEAD)) { | ||
3112 | sk->sk_err = err; | ||
3113 | /* This barrier is coupled with smp_rmb() in tcp_poll() */ | ||
3114 | smp_wmb(); | ||
3115 | sk->sk_error_report(sk); | ||
3116 | if (tcp_need_reset(sk->sk_state)) | ||
3117 | tcp_send_active_reset(sk, GFP_ATOMIC); | ||
3118 | tcp_done(sk); | ||
3119 | } | ||
3120 | |||
3121 | bh_unlock_sock(sk); | ||
3122 | local_bh_enable(); | ||
3123 | release_sock(sk); | ||
3124 | sock_put(sk); | ||
3125 | return 0; | ||
3126 | } | ||
3127 | EXPORT_SYMBOL_GPL(tcp_abort); | ||
3128 | |||
3084 | extern struct tcp_congestion_ops tcp_reno; | 3129 | extern struct tcp_congestion_ops tcp_reno; |
3085 | 3130 | ||
3086 | static __initdata unsigned long thash_entries; | 3131 | static __initdata unsigned long thash_entries; |
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index b31604086edd..4d610934fb39 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c | |||
@@ -10,6 +10,8 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/net.h> | ||
14 | #include <linux/sock_diag.h> | ||
13 | #include <linux/inet_diag.h> | 15 | #include <linux/inet_diag.h> |
14 | 16 | ||
15 | #include <linux/tcp.h> | 17 | #include <linux/tcp.h> |
@@ -46,12 +48,29 @@ static int tcp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, | |||
46 | return inet_diag_dump_one_icsk(&tcp_hashinfo, in_skb, nlh, req); | 48 | return inet_diag_dump_one_icsk(&tcp_hashinfo, in_skb, nlh, req); |
47 | } | 49 | } |
48 | 50 | ||
51 | #ifdef CONFIG_INET_DIAG_DESTROY | ||
52 | static int tcp_diag_destroy(struct sk_buff *in_skb, | ||
53 | const struct inet_diag_req_v2 *req) | ||
54 | { | ||
55 | struct net *net = sock_net(in_skb->sk); | ||
56 | struct sock *sk = inet_diag_find_one_icsk(net, &tcp_hashinfo, req); | ||
57 | |||
58 | if (IS_ERR(sk)) | ||
59 | return PTR_ERR(sk); | ||
60 | |||
61 | return sock_diag_destroy(sk, ECONNABORTED); | ||
62 | } | ||
63 | #endif | ||
64 | |||
49 | static const struct inet_diag_handler tcp_diag_handler = { | 65 | static const struct inet_diag_handler tcp_diag_handler = { |
50 | .dump = tcp_diag_dump, | 66 | .dump = tcp_diag_dump, |
51 | .dump_one = tcp_diag_dump_one, | 67 | .dump_one = tcp_diag_dump_one, |
52 | .idiag_get_info = tcp_diag_get_info, | 68 | .idiag_get_info = tcp_diag_get_info, |
53 | .idiag_type = IPPROTO_TCP, | 69 | .idiag_type = IPPROTO_TCP, |
54 | .idiag_info_size = sizeof(struct tcp_info), | 70 | .idiag_info_size = sizeof(struct tcp_info), |
71 | #ifdef CONFIG_INET_DIAG_DESTROY | ||
72 | .destroy = tcp_diag_destroy, | ||
73 | #endif | ||
55 | }; | 74 | }; |
56 | 75 | ||
57 | static int __init tcp_diag_init(void) | 76 | static int __init tcp_diag_init(void) |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fdd88c3803a6..0003d409fec5 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2478,6 +2478,9 @@ static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, | |||
2478 | int newly_acked_sacked = prior_unsacked - | 2478 | int newly_acked_sacked = prior_unsacked - |
2479 | (tp->packets_out - tp->sacked_out); | 2479 | (tp->packets_out - tp->sacked_out); |
2480 | 2480 | ||
2481 | if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) | ||
2482 | return; | ||
2483 | |||
2481 | tp->prr_delivered += newly_acked_sacked; | 2484 | tp->prr_delivered += newly_acked_sacked; |
2482 | if (delta < 0) { | 2485 | if (delta < 0) { |
2483 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + | 2486 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + |
@@ -4481,19 +4484,34 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int | |||
4481 | int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | 4484 | int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) |
4482 | { | 4485 | { |
4483 | struct sk_buff *skb; | 4486 | struct sk_buff *skb; |
4487 | int err = -ENOMEM; | ||
4488 | int data_len = 0; | ||
4484 | bool fragstolen; | 4489 | bool fragstolen; |
4485 | 4490 | ||
4486 | if (size == 0) | 4491 | if (size == 0) |
4487 | return 0; | 4492 | return 0; |
4488 | 4493 | ||
4489 | skb = alloc_skb(size, sk->sk_allocation); | 4494 | if (size > PAGE_SIZE) { |
4495 | int npages = min_t(size_t, size >> PAGE_SHIFT, MAX_SKB_FRAGS); | ||
4496 | |||
4497 | data_len = npages << PAGE_SHIFT; | ||
4498 | size = data_len + (size & ~PAGE_MASK); | ||
4499 | } | ||
4500 | skb = alloc_skb_with_frags(size - data_len, data_len, | ||
4501 | PAGE_ALLOC_COSTLY_ORDER, | ||
4502 | &err, sk->sk_allocation); | ||
4490 | if (!skb) | 4503 | if (!skb) |
4491 | goto err; | 4504 | goto err; |
4492 | 4505 | ||
4506 | skb_put(skb, size - data_len); | ||
4507 | skb->data_len = data_len; | ||
4508 | skb->len = size; | ||
4509 | |||
4493 | if (tcp_try_rmem_schedule(sk, skb, skb->truesize)) | 4510 | if (tcp_try_rmem_schedule(sk, skb, skb->truesize)) |
4494 | goto err_free; | 4511 | goto err_free; |
4495 | 4512 | ||
4496 | if (memcpy_from_msg(skb_put(skb, size), msg, size)) | 4513 | err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size); |
4514 | if (err) | ||
4497 | goto err_free; | 4515 | goto err_free; |
4498 | 4516 | ||
4499 | TCP_SKB_CB(skb)->seq = tcp_sk(sk)->rcv_nxt; | 4517 | TCP_SKB_CB(skb)->seq = tcp_sk(sk)->rcv_nxt; |
@@ -4509,7 +4527,8 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | |||
4509 | err_free: | 4527 | err_free: |
4510 | kfree_skb(skb); | 4528 | kfree_skb(skb); |
4511 | err: | 4529 | err: |
4512 | return -ENOMEM; | 4530 | return err; |
4531 | |||
4513 | } | 4532 | } |
4514 | 4533 | ||
4515 | static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) | 4534 | static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) |
@@ -5667,6 +5686,7 @@ discard: | |||
5667 | } | 5686 | } |
5668 | 5687 | ||
5669 | tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; | 5688 | tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; |
5689 | tp->copied_seq = tp->rcv_nxt; | ||
5670 | tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; | 5690 | tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; |
5671 | 5691 | ||
5672 | /* RFC1323: The window in SYN & SYN/ACK segments is | 5692 | /* RFC1323: The window in SYN & SYN/ACK segments is |
@@ -6187,7 +6207,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, | |||
6187 | tcp_openreq_init(req, &tmp_opt, skb, sk); | 6207 | tcp_openreq_init(req, &tmp_opt, skb, sk); |
6188 | 6208 | ||
6189 | /* Note: tcp_v6_init_req() might override ir_iif for link locals */ | 6209 | /* Note: tcp_v6_init_req() might override ir_iif for link locals */ |
6190 | inet_rsk(req)->ir_iif = sk->sk_bound_dev_if; | 6210 | inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb); |
6191 | 6211 | ||
6192 | af_ops->init_req(req, sk, skb); | 6212 | af_ops->init_req(req, sk, skb); |
6193 | 6213 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ba09016d1bfd..65947c1f4733 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -587,7 +587,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
587 | } rep; | 587 | } rep; |
588 | struct ip_reply_arg arg; | 588 | struct ip_reply_arg arg; |
589 | #ifdef CONFIG_TCP_MD5SIG | 589 | #ifdef CONFIG_TCP_MD5SIG |
590 | struct tcp_md5sig_key *key; | 590 | struct tcp_md5sig_key *key = NULL; |
591 | const __u8 *hash_location = NULL; | 591 | const __u8 *hash_location = NULL; |
592 | unsigned char newhash[16]; | 592 | unsigned char newhash[16]; |
593 | int genhash; | 593 | int genhash; |
@@ -627,7 +627,10 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
627 | net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev); | 627 | net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev); |
628 | #ifdef CONFIG_TCP_MD5SIG | 628 | #ifdef CONFIG_TCP_MD5SIG |
629 | hash_location = tcp_parse_md5sig_option(th); | 629 | hash_location = tcp_parse_md5sig_option(th); |
630 | if (!sk && hash_location) { | 630 | if (sk && sk_fullsock(sk)) { |
631 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *) | ||
632 | &ip_hdr(skb)->saddr, AF_INET); | ||
633 | } else if (hash_location) { | ||
631 | /* | 634 | /* |
632 | * active side is lost. Try to find listening socket through | 635 | * active side is lost. Try to find listening socket through |
633 | * source port, and then find md5 key through listening socket. | 636 | * source port, and then find md5 key through listening socket. |
@@ -651,10 +654,6 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
651 | genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, skb); | 654 | genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, skb); |
652 | if (genhash || memcmp(hash_location, newhash, 16) != 0) | 655 | if (genhash || memcmp(hash_location, newhash, 16) != 0) |
653 | goto release_sk1; | 656 | goto release_sk1; |
654 | } else { | ||
655 | key = sk ? tcp_md5_do_lookup(sk, (union tcp_md5_addr *) | ||
656 | &ip_hdr(skb)->saddr, | ||
657 | AF_INET) : NULL; | ||
658 | } | 657 | } |
659 | 658 | ||
660 | if (key) { | 659 | if (key) { |
@@ -675,7 +674,8 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
675 | ip_hdr(skb)->saddr, /* XXX */ | 674 | ip_hdr(skb)->saddr, /* XXX */ |
676 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 675 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
677 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 676 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
678 | arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; | 677 | arg.flags = (sk && inet_sk_transparent(sk)) ? IP_REPLY_ARG_NOSRCCHECK : 0; |
678 | |||
679 | /* When socket is gone, all binding information is lost. | 679 | /* When socket is gone, all binding information is lost. |
680 | * routing might fail in this case. No choice here, if we choose to force | 680 | * routing might fail in this case. No choice here, if we choose to force |
681 | * input interface, we will misroute in case of asymmetric route. | 681 | * input interface, we will misroute in case of asymmetric route. |
@@ -683,6 +683,9 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
683 | if (sk) | 683 | if (sk) |
684 | arg.bound_dev_if = sk->sk_bound_dev_if; | 684 | arg.bound_dev_if = sk->sk_bound_dev_if; |
685 | 685 | ||
686 | BUILD_BUG_ON(offsetof(struct sock, sk_bound_dev_if) != | ||
687 | offsetof(struct inet_timewait_sock, tw_bound_dev_if)); | ||
688 | |||
686 | arg.tos = ip_hdr(skb)->tos; | 689 | arg.tos = ip_hdr(skb)->tos; |
687 | ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), | 690 | ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), |
688 | skb, &TCP_SKB_CB(skb)->header.h4.opt, | 691 | skb, &TCP_SKB_CB(skb)->header.h4.opt, |
@@ -921,7 +924,8 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, | |||
921 | } | 924 | } |
922 | 925 | ||
923 | md5sig = rcu_dereference_protected(tp->md5sig_info, | 926 | md5sig = rcu_dereference_protected(tp->md5sig_info, |
924 | sock_owned_by_user(sk)); | 927 | sock_owned_by_user(sk) || |
928 | lockdep_is_held(&sk->sk_lock.slock)); | ||
925 | if (!md5sig) { | 929 | if (!md5sig) { |
926 | md5sig = kmalloc(sizeof(*md5sig), gfp); | 930 | md5sig = kmalloc(sizeof(*md5sig), gfp); |
927 | if (!md5sig) | 931 | if (!md5sig) |
@@ -1275,6 +1279,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, | |||
1275 | ireq = inet_rsk(req); | 1279 | ireq = inet_rsk(req); |
1276 | sk_daddr_set(newsk, ireq->ir_rmt_addr); | 1280 | sk_daddr_set(newsk, ireq->ir_rmt_addr); |
1277 | sk_rcv_saddr_set(newsk, ireq->ir_loc_addr); | 1281 | sk_rcv_saddr_set(newsk, ireq->ir_loc_addr); |
1282 | newsk->sk_bound_dev_if = ireq->ir_iif; | ||
1278 | newinet->inet_saddr = ireq->ir_loc_addr; | 1283 | newinet->inet_saddr = ireq->ir_loc_addr; |
1279 | inet_opt = ireq->opt; | 1284 | inet_opt = ireq->opt; |
1280 | rcu_assign_pointer(newinet->inet_opt, inet_opt); | 1285 | rcu_assign_pointer(newinet->inet_opt, inet_opt); |
@@ -1492,7 +1497,7 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) | |||
1492 | if (likely(sk->sk_rx_dst)) | 1497 | if (likely(sk->sk_rx_dst)) |
1493 | skb_dst_drop(skb); | 1498 | skb_dst_drop(skb); |
1494 | else | 1499 | else |
1495 | skb_dst_force(skb); | 1500 | skb_dst_force_safe(skb); |
1496 | 1501 | ||
1497 | __skb_queue_tail(&tp->ucopy.prequeue, skb); | 1502 | __skb_queue_tail(&tp->ucopy.prequeue, skb); |
1498 | tp->ucopy.memory += skb->truesize; | 1503 | tp->ucopy.memory += skb->truesize; |
@@ -1704,7 +1709,9 @@ do_time_wait: | |||
1704 | tcp_v4_timewait_ack(sk, skb); | 1709 | tcp_v4_timewait_ack(sk, skb); |
1705 | break; | 1710 | break; |
1706 | case TCP_TW_RST: | 1711 | case TCP_TW_RST: |
1707 | goto no_tcp_socket; | 1712 | tcp_v4_send_reset(sk, skb); |
1713 | inet_twsk_deschedule_put(inet_twsk(sk)); | ||
1714 | goto discard_it; | ||
1708 | case TCP_TW_SUCCESS:; | 1715 | case TCP_TW_SUCCESS:; |
1709 | } | 1716 | } |
1710 | goto discard_it; | 1717 | goto discard_it; |
@@ -1720,8 +1727,7 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | |||
1720 | { | 1727 | { |
1721 | struct dst_entry *dst = skb_dst(skb); | 1728 | struct dst_entry *dst = skb_dst(skb); |
1722 | 1729 | ||
1723 | if (dst) { | 1730 | if (dst && dst_hold_safe(dst)) { |
1724 | dst_hold(dst); | ||
1725 | sk->sk_rx_dst = dst; | 1731 | sk->sk_rx_dst = dst; |
1726 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; | 1732 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; |
1727 | } | 1733 | } |
@@ -2341,6 +2347,7 @@ struct proto tcp_prot = { | |||
2341 | .destroy_cgroup = tcp_destroy_cgroup, | 2347 | .destroy_cgroup = tcp_destroy_cgroup, |
2342 | .proto_cgroup = tcp_proto_cgroup, | 2348 | .proto_cgroup = tcp_proto_cgroup, |
2343 | #endif | 2349 | #endif |
2350 | .diag_destroy = tcp_abort, | ||
2344 | }; | 2351 | }; |
2345 | EXPORT_SYMBOL(tcp_prot); | 2352 | EXPORT_SYMBOL(tcp_prot); |
2346 | 2353 | ||
@@ -2378,6 +2385,10 @@ static int __net_init tcp_sk_init(struct net *net) | |||
2378 | net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD; | 2385 | net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD; |
2379 | net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL; | 2386 | net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL; |
2380 | 2387 | ||
2388 | net->ipv4.sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME; | ||
2389 | net->ipv4.sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES; | ||
2390 | net->ipv4.sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL; | ||
2391 | |||
2381 | return 0; | 2392 | return 0; |
2382 | fail: | 2393 | fail: |
2383 | tcp_sk_exit(net); | 2394 | tcp_sk_exit(net); |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index ac6b1961ffeb..75632a925824 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -131,7 +131,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, | |||
131 | goto kill; | 131 | goto kill; |
132 | 132 | ||
133 | if (th->syn && !before(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt)) | 133 | if (th->syn && !before(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt)) |
134 | goto kill_with_rst; | 134 | return TCP_TW_RST; |
135 | 135 | ||
136 | /* Dup ACK? */ | 136 | /* Dup ACK? */ |
137 | if (!th->ack || | 137 | if (!th->ack || |
@@ -145,11 +145,8 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, | |||
145 | * reset. | 145 | * reset. |
146 | */ | 146 | */ |
147 | if (!th->fin || | 147 | if (!th->fin || |
148 | TCP_SKB_CB(skb)->end_seq != tcptw->tw_rcv_nxt + 1) { | 148 | TCP_SKB_CB(skb)->end_seq != tcptw->tw_rcv_nxt + 1) |
149 | kill_with_rst: | ||
150 | inet_twsk_deschedule_put(tw); | ||
151 | return TCP_TW_RST; | 149 | return TCP_TW_RST; |
152 | } | ||
153 | 150 | ||
154 | /* FIN arrived, enter true time-wait state. */ | 151 | /* FIN arrived, enter true time-wait state. */ |
155 | tw->tw_substate = TCP_TIME_WAIT; | 152 | tw->tw_substate = TCP_TIME_WAIT; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index cb7ca569052c..412a920fe0ec 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2296,7 +2296,7 @@ void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, | |||
2296 | return; | 2296 | return; |
2297 | 2297 | ||
2298 | if (tcp_write_xmit(sk, cur_mss, nonagle, 0, | 2298 | if (tcp_write_xmit(sk, cur_mss, nonagle, 0, |
2299 | sk_gfp_atomic(sk, GFP_ATOMIC))) | 2299 | sk_gfp_mask(sk, GFP_ATOMIC))) |
2300 | tcp_check_probe_timer(sk); | 2300 | tcp_check_probe_timer(sk); |
2301 | } | 2301 | } |
2302 | 2302 | ||
@@ -3150,7 +3150,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) | |||
3150 | { | 3150 | { |
3151 | struct tcp_sock *tp = tcp_sk(sk); | 3151 | struct tcp_sock *tp = tcp_sk(sk); |
3152 | struct tcp_fastopen_request *fo = tp->fastopen_req; | 3152 | struct tcp_fastopen_request *fo = tp->fastopen_req; |
3153 | int syn_loss = 0, space, err = 0, copied; | 3153 | int syn_loss = 0, space, err = 0; |
3154 | unsigned long last_syn_loss = 0; | 3154 | unsigned long last_syn_loss = 0; |
3155 | struct sk_buff *syn_data; | 3155 | struct sk_buff *syn_data; |
3156 | 3156 | ||
@@ -3188,17 +3188,18 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) | |||
3188 | goto fallback; | 3188 | goto fallback; |
3189 | syn_data->ip_summed = CHECKSUM_PARTIAL; | 3189 | syn_data->ip_summed = CHECKSUM_PARTIAL; |
3190 | memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); | 3190 | memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); |
3191 | copied = copy_from_iter(skb_put(syn_data, space), space, | 3191 | if (space) { |
3192 | &fo->data->msg_iter); | 3192 | int copied = copy_from_iter(skb_put(syn_data, space), space, |
3193 | if (unlikely(!copied)) { | 3193 | &fo->data->msg_iter); |
3194 | kfree_skb(syn_data); | 3194 | if (unlikely(!copied)) { |
3195 | goto fallback; | 3195 | kfree_skb(syn_data); |
3196 | } | 3196 | goto fallback; |
3197 | if (copied != space) { | 3197 | } |
3198 | skb_trim(syn_data, copied); | 3198 | if (copied != space) { |
3199 | space = copied; | 3199 | skb_trim(syn_data, copied); |
3200 | space = copied; | ||
3201 | } | ||
3200 | } | 3202 | } |
3201 | |||
3202 | /* No more data pending in inet_wait_for_connect() */ | 3203 | /* No more data pending in inet_wait_for_connect() */ |
3203 | if (space == fo->size) | 3204 | if (space == fo->size) |
3204 | fo->data = NULL; | 3205 | fo->data = NULL; |
@@ -3352,8 +3353,9 @@ void tcp_send_ack(struct sock *sk) | |||
3352 | * tcp_transmit_skb() will set the ownership to this | 3353 | * tcp_transmit_skb() will set the ownership to this |
3353 | * sock. | 3354 | * sock. |
3354 | */ | 3355 | */ |
3355 | buff = alloc_skb(MAX_TCP_HEADER, sk_gfp_atomic(sk, GFP_ATOMIC)); | 3356 | buff = alloc_skb(MAX_TCP_HEADER, |
3356 | if (!buff) { | 3357 | sk_gfp_mask(sk, GFP_ATOMIC | __GFP_NOWARN)); |
3358 | if (unlikely(!buff)) { | ||
3357 | inet_csk_schedule_ack(sk); | 3359 | inet_csk_schedule_ack(sk); |
3358 | inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN; | 3360 | inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN; |
3359 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, | 3361 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, |
@@ -3375,7 +3377,7 @@ void tcp_send_ack(struct sock *sk) | |||
3375 | 3377 | ||
3376 | /* Send it off, this clears delayed acks for us. */ | 3378 | /* Send it off, this clears delayed acks for us. */ |
3377 | skb_mstamp_get(&buff->skb_mstamp); | 3379 | skb_mstamp_get(&buff->skb_mstamp); |
3378 | tcp_transmit_skb(sk, buff, 0, sk_gfp_atomic(sk, GFP_ATOMIC)); | 3380 | tcp_transmit_skb(sk, buff, 0, (__force gfp_t)0); |
3379 | } | 3381 | } |
3380 | EXPORT_SYMBOL_GPL(tcp_send_ack); | 3382 | EXPORT_SYMBOL_GPL(tcp_send_ack); |
3381 | 3383 | ||
@@ -3396,7 +3398,8 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent, int mib) | |||
3396 | struct sk_buff *skb; | 3398 | struct sk_buff *skb; |
3397 | 3399 | ||
3398 | /* We don't queue it, tcp_transmit_skb() sets ownership. */ | 3400 | /* We don't queue it, tcp_transmit_skb() sets ownership. */ |
3399 | skb = alloc_skb(MAX_TCP_HEADER, sk_gfp_atomic(sk, GFP_ATOMIC)); | 3401 | skb = alloc_skb(MAX_TCP_HEADER, |
3402 | sk_gfp_mask(sk, GFP_ATOMIC | __GFP_NOWARN)); | ||
3400 | if (!skb) | 3403 | if (!skb) |
3401 | return -1; | 3404 | return -1; |
3402 | 3405 | ||
@@ -3409,7 +3412,7 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent, int mib) | |||
3409 | tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPHDR_ACK); | 3412 | tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPHDR_ACK); |
3410 | skb_mstamp_get(&skb->skb_mstamp); | 3413 | skb_mstamp_get(&skb->skb_mstamp); |
3411 | NET_INC_STATS(sock_net(sk), mib); | 3414 | NET_INC_STATS(sock_net(sk), mib); |
3412 | return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC); | 3415 | return tcp_transmit_skb(sk, skb, 0, (__force gfp_t)0); |
3413 | } | 3416 | } |
3414 | 3417 | ||
3415 | void tcp_send_window_probe(struct sock *sk) | 3418 | void tcp_send_window_probe(struct sock *sk) |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index c9c716a483e4..a4730a28b220 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -24,9 +24,6 @@ | |||
24 | 24 | ||
25 | int sysctl_tcp_syn_retries __read_mostly = TCP_SYN_RETRIES; | 25 | int sysctl_tcp_syn_retries __read_mostly = TCP_SYN_RETRIES; |
26 | int sysctl_tcp_synack_retries __read_mostly = TCP_SYNACK_RETRIES; | 26 | int sysctl_tcp_synack_retries __read_mostly = TCP_SYNACK_RETRIES; |
27 | int sysctl_tcp_keepalive_time __read_mostly = TCP_KEEPALIVE_TIME; | ||
28 | int sysctl_tcp_keepalive_probes __read_mostly = TCP_KEEPALIVE_PROBES; | ||
29 | int sysctl_tcp_keepalive_intvl __read_mostly = TCP_KEEPALIVE_INTVL; | ||
30 | int sysctl_tcp_retries1 __read_mostly = TCP_RETR1; | 27 | int sysctl_tcp_retries1 __read_mostly = TCP_RETR1; |
31 | int sysctl_tcp_retries2 __read_mostly = TCP_RETR2; | 28 | int sysctl_tcp_retries2 __read_mostly = TCP_RETR2; |
32 | int sysctl_tcp_orphan_retries __read_mostly; | 29 | int sysctl_tcp_orphan_retries __read_mostly; |
@@ -168,7 +165,7 @@ static int tcp_write_timeout(struct sock *sk) | |||
168 | dst_negative_advice(sk); | 165 | dst_negative_advice(sk); |
169 | if (tp->syn_fastopen || tp->syn_data) | 166 | if (tp->syn_fastopen || tp->syn_data) |
170 | tcp_fastopen_cache_set(sk, 0, NULL, true, 0); | 167 | tcp_fastopen_cache_set(sk, 0, NULL, true, 0); |
171 | if (tp->syn_data) | 168 | if (tp->syn_data && icsk->icsk_retransmits == 1) |
172 | NET_INC_STATS_BH(sock_net(sk), | 169 | NET_INC_STATS_BH(sock_net(sk), |
173 | LINUX_MIB_TCPFASTOPENACTIVEFAIL); | 170 | LINUX_MIB_TCPFASTOPENACTIVEFAIL); |
174 | } | 171 | } |
@@ -176,6 +173,18 @@ static int tcp_write_timeout(struct sock *sk) | |||
176 | syn_set = true; | 173 | syn_set = true; |
177 | } else { | 174 | } else { |
178 | if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0, 0)) { | 175 | if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0, 0)) { |
176 | /* Some middle-boxes may black-hole Fast Open _after_ | ||
177 | * the handshake. Therefore we conservatively disable | ||
178 | * Fast Open on this path on recurring timeouts with | ||
179 | * few or zero bytes acked after Fast Open. | ||
180 | */ | ||
181 | if (tp->syn_data_acked && | ||
182 | tp->bytes_acked <= tp->rx_opt.mss_clamp) { | ||
183 | tcp_fastopen_cache_set(sk, 0, NULL, true, 0); | ||
184 | if (icsk->icsk_retransmits == sysctl_tcp_retries1) | ||
185 | NET_INC_STATS_BH(sock_net(sk), | ||
186 | LINUX_MIB_TCPFASTOPENACTIVEFAIL); | ||
187 | } | ||
179 | /* Black hole detection */ | 188 | /* Black hole detection */ |
180 | tcp_mtu_probing(icsk, sk); | 189 | tcp_mtu_probing(icsk, sk); |
181 | 190 | ||
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index 17d35662930d..3e6a472e6b88 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c | |||
@@ -219,7 +219,7 @@ static u32 tcp_yeah_ssthresh(struct sock *sk) | |||
219 | yeah->fast_count = 0; | 219 | yeah->fast_count = 0; |
220 | yeah->reno_count = max(yeah->reno_count>>1, 2U); | 220 | yeah->reno_count = max(yeah->reno_count>>1, 2U); |
221 | 221 | ||
222 | return tp->snd_cwnd - reduction; | 222 | return max_t(int, tp->snd_cwnd - reduction, 2); |
223 | } | 223 | } |
224 | 224 | ||
225 | static struct tcp_congestion_ops tcp_yeah __read_mostly = { | 225 | static struct tcp_congestion_ops tcp_yeah __read_mostly = { |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 24ec14f9825c..dc45b538e237 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -100,7 +100,6 @@ | |||
100 | #include <linux/slab.h> | 100 | #include <linux/slab.h> |
101 | #include <net/tcp_states.h> | 101 | #include <net/tcp_states.h> |
102 | #include <linux/skbuff.h> | 102 | #include <linux/skbuff.h> |
103 | #include <linux/netdevice.h> | ||
104 | #include <linux/proc_fs.h> | 103 | #include <linux/proc_fs.h> |
105 | #include <linux/seq_file.h> | 104 | #include <linux/seq_file.h> |
106 | #include <net/net_namespace.h> | 105 | #include <net/net_namespace.h> |
@@ -114,6 +113,7 @@ | |||
114 | #include <trace/events/skb.h> | 113 | #include <trace/events/skb.h> |
115 | #include <net/busy_poll.h> | 114 | #include <net/busy_poll.h> |
116 | #include "udp_impl.h" | 115 | #include "udp_impl.h" |
116 | #include <net/sock_reuseport.h> | ||
117 | 117 | ||
118 | struct udp_table udp_table __read_mostly; | 118 | struct udp_table udp_table __read_mostly; |
119 | EXPORT_SYMBOL(udp_table); | 119 | EXPORT_SYMBOL(udp_table); |
@@ -138,7 +138,8 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num, | |||
138 | unsigned long *bitmap, | 138 | unsigned long *bitmap, |
139 | struct sock *sk, | 139 | struct sock *sk, |
140 | int (*saddr_comp)(const struct sock *sk1, | 140 | int (*saddr_comp)(const struct sock *sk1, |
141 | const struct sock *sk2), | 141 | const struct sock *sk2, |
142 | bool match_wildcard), | ||
142 | unsigned int log) | 143 | unsigned int log) |
143 | { | 144 | { |
144 | struct sock *sk2; | 145 | struct sock *sk2; |
@@ -153,8 +154,9 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num, | |||
153 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || | 154 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || |
154 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | 155 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && |
155 | (!sk2->sk_reuseport || !sk->sk_reuseport || | 156 | (!sk2->sk_reuseport || !sk->sk_reuseport || |
157 | rcu_access_pointer(sk->sk_reuseport_cb) || | ||
156 | !uid_eq(uid, sock_i_uid(sk2))) && | 158 | !uid_eq(uid, sock_i_uid(sk2))) && |
157 | saddr_comp(sk, sk2)) { | 159 | saddr_comp(sk, sk2, true)) { |
158 | if (!bitmap) | 160 | if (!bitmap) |
159 | return 1; | 161 | return 1; |
160 | __set_bit(udp_sk(sk2)->udp_port_hash >> log, bitmap); | 162 | __set_bit(udp_sk(sk2)->udp_port_hash >> log, bitmap); |
@@ -171,7 +173,8 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num, | |||
171 | struct udp_hslot *hslot2, | 173 | struct udp_hslot *hslot2, |
172 | struct sock *sk, | 174 | struct sock *sk, |
173 | int (*saddr_comp)(const struct sock *sk1, | 175 | int (*saddr_comp)(const struct sock *sk1, |
174 | const struct sock *sk2)) | 176 | const struct sock *sk2, |
177 | bool match_wildcard)) | ||
175 | { | 178 | { |
176 | struct sock *sk2; | 179 | struct sock *sk2; |
177 | struct hlist_nulls_node *node; | 180 | struct hlist_nulls_node *node; |
@@ -187,8 +190,9 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num, | |||
187 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || | 190 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || |
188 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | 191 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && |
189 | (!sk2->sk_reuseport || !sk->sk_reuseport || | 192 | (!sk2->sk_reuseport || !sk->sk_reuseport || |
193 | rcu_access_pointer(sk->sk_reuseport_cb) || | ||
190 | !uid_eq(uid, sock_i_uid(sk2))) && | 194 | !uid_eq(uid, sock_i_uid(sk2))) && |
191 | saddr_comp(sk, sk2)) { | 195 | saddr_comp(sk, sk2, true)) { |
192 | res = 1; | 196 | res = 1; |
193 | break; | 197 | break; |
194 | } | 198 | } |
@@ -197,6 +201,35 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num, | |||
197 | return res; | 201 | return res; |
198 | } | 202 | } |
199 | 203 | ||
204 | static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot, | ||
205 | int (*saddr_same)(const struct sock *sk1, | ||
206 | const struct sock *sk2, | ||
207 | bool match_wildcard)) | ||
208 | { | ||
209 | struct net *net = sock_net(sk); | ||
210 | struct hlist_nulls_node *node; | ||
211 | kuid_t uid = sock_i_uid(sk); | ||
212 | struct sock *sk2; | ||
213 | |||
214 | sk_nulls_for_each(sk2, node, &hslot->head) { | ||
215 | if (net_eq(sock_net(sk2), net) && | ||
216 | sk2 != sk && | ||
217 | sk2->sk_family == sk->sk_family && | ||
218 | ipv6_only_sock(sk2) == ipv6_only_sock(sk) && | ||
219 | (udp_sk(sk2)->udp_port_hash == udp_sk(sk)->udp_port_hash) && | ||
220 | (sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | ||
221 | sk2->sk_reuseport && uid_eq(uid, sock_i_uid(sk2)) && | ||
222 | (*saddr_same)(sk, sk2, false)) { | ||
223 | return reuseport_add_sock(sk, sk2); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | /* Initial allocation may have already happened via setsockopt */ | ||
228 | if (!rcu_access_pointer(sk->sk_reuseport_cb)) | ||
229 | return reuseport_alloc(sk); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
200 | /** | 233 | /** |
201 | * udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 | 234 | * udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 |
202 | * | 235 | * |
@@ -208,7 +241,8 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num, | |||
208 | */ | 241 | */ |
209 | int udp_lib_get_port(struct sock *sk, unsigned short snum, | 242 | int udp_lib_get_port(struct sock *sk, unsigned short snum, |
210 | int (*saddr_comp)(const struct sock *sk1, | 243 | int (*saddr_comp)(const struct sock *sk1, |
211 | const struct sock *sk2), | 244 | const struct sock *sk2, |
245 | bool match_wildcard), | ||
212 | unsigned int hash2_nulladdr) | 246 | unsigned int hash2_nulladdr) |
213 | { | 247 | { |
214 | struct udp_hslot *hslot, *hslot2; | 248 | struct udp_hslot *hslot, *hslot2; |
@@ -291,6 +325,14 @@ found: | |||
291 | udp_sk(sk)->udp_port_hash = snum; | 325 | udp_sk(sk)->udp_port_hash = snum; |
292 | udp_sk(sk)->udp_portaddr_hash ^= snum; | 326 | udp_sk(sk)->udp_portaddr_hash ^= snum; |
293 | if (sk_unhashed(sk)) { | 327 | if (sk_unhashed(sk)) { |
328 | if (sk->sk_reuseport && | ||
329 | udp_reuseport_add_sock(sk, hslot, saddr_comp)) { | ||
330 | inet_sk(sk)->inet_num = 0; | ||
331 | udp_sk(sk)->udp_port_hash = 0; | ||
332 | udp_sk(sk)->udp_portaddr_hash ^= snum; | ||
333 | goto fail_unlock; | ||
334 | } | ||
335 | |||
294 | sk_nulls_add_node_rcu(sk, &hslot->head); | 336 | sk_nulls_add_node_rcu(sk, &hslot->head); |
295 | hslot->count++; | 337 | hslot->count++; |
296 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 338 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
@@ -310,13 +352,22 @@ fail: | |||
310 | } | 352 | } |
311 | EXPORT_SYMBOL(udp_lib_get_port); | 353 | EXPORT_SYMBOL(udp_lib_get_port); |
312 | 354 | ||
313 | static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | 355 | /* match_wildcard == true: 0.0.0.0 equals to any IPv4 addresses |
356 | * match_wildcard == false: addresses must be exactly the same, i.e. | ||
357 | * 0.0.0.0 only equals to 0.0.0.0 | ||
358 | */ | ||
359 | static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2, | ||
360 | bool match_wildcard) | ||
314 | { | 361 | { |
315 | struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); | 362 | struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); |
316 | 363 | ||
317 | return (!ipv6_only_sock(sk2) && | 364 | if (!ipv6_only_sock(sk2)) { |
318 | (!inet1->inet_rcv_saddr || !inet2->inet_rcv_saddr || | 365 | if (inet1->inet_rcv_saddr == inet2->inet_rcv_saddr) |
319 | inet1->inet_rcv_saddr == inet2->inet_rcv_saddr)); | 366 | return 1; |
367 | if (!inet1->inet_rcv_saddr || !inet2->inet_rcv_saddr) | ||
368 | return match_wildcard; | ||
369 | } | ||
370 | return 0; | ||
320 | } | 371 | } |
321 | 372 | ||
322 | static u32 udp4_portaddr_hash(const struct net *net, __be32 saddr, | 373 | static u32 udp4_portaddr_hash(const struct net *net, __be32 saddr, |
@@ -442,7 +493,8 @@ static u32 udp_ehashfn(const struct net *net, const __be32 laddr, | |||
442 | static struct sock *udp4_lib_lookup2(struct net *net, | 493 | static struct sock *udp4_lib_lookup2(struct net *net, |
443 | __be32 saddr, __be16 sport, | 494 | __be32 saddr, __be16 sport, |
444 | __be32 daddr, unsigned int hnum, int dif, | 495 | __be32 daddr, unsigned int hnum, int dif, |
445 | struct udp_hslot *hslot2, unsigned int slot2) | 496 | struct udp_hslot *hslot2, unsigned int slot2, |
497 | struct sk_buff *skb) | ||
446 | { | 498 | { |
447 | struct sock *sk, *result; | 499 | struct sock *sk, *result; |
448 | struct hlist_nulls_node *node; | 500 | struct hlist_nulls_node *node; |
@@ -460,8 +512,15 @@ begin: | |||
460 | badness = score; | 512 | badness = score; |
461 | reuseport = sk->sk_reuseport; | 513 | reuseport = sk->sk_reuseport; |
462 | if (reuseport) { | 514 | if (reuseport) { |
515 | struct sock *sk2; | ||
463 | hash = udp_ehashfn(net, daddr, hnum, | 516 | hash = udp_ehashfn(net, daddr, hnum, |
464 | saddr, sport); | 517 | saddr, sport); |
518 | sk2 = reuseport_select_sock(sk, hash, skb, | ||
519 | sizeof(struct udphdr)); | ||
520 | if (sk2) { | ||
521 | result = sk2; | ||
522 | goto found; | ||
523 | } | ||
465 | matches = 1; | 524 | matches = 1; |
466 | } | 525 | } |
467 | } else if (score == badness && reuseport) { | 526 | } else if (score == badness && reuseport) { |
@@ -479,6 +538,7 @@ begin: | |||
479 | if (get_nulls_value(node) != slot2) | 538 | if (get_nulls_value(node) != slot2) |
480 | goto begin; | 539 | goto begin; |
481 | if (result) { | 540 | if (result) { |
541 | found: | ||
482 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) | 542 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) |
483 | result = NULL; | 543 | result = NULL; |
484 | else if (unlikely(compute_score2(result, net, saddr, sport, | 544 | else if (unlikely(compute_score2(result, net, saddr, sport, |
@@ -495,7 +555,7 @@ begin: | |||
495 | */ | 555 | */ |
496 | struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | 556 | struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, |
497 | __be16 sport, __be32 daddr, __be16 dport, | 557 | __be16 sport, __be32 daddr, __be16 dport, |
498 | int dif, struct udp_table *udptable) | 558 | int dif, struct udp_table *udptable, struct sk_buff *skb) |
499 | { | 559 | { |
500 | struct sock *sk, *result; | 560 | struct sock *sk, *result; |
501 | struct hlist_nulls_node *node; | 561 | struct hlist_nulls_node *node; |
@@ -515,7 +575,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
515 | 575 | ||
516 | result = udp4_lib_lookup2(net, saddr, sport, | 576 | result = udp4_lib_lookup2(net, saddr, sport, |
517 | daddr, hnum, dif, | 577 | daddr, hnum, dif, |
518 | hslot2, slot2); | 578 | hslot2, slot2, skb); |
519 | if (!result) { | 579 | if (!result) { |
520 | hash2 = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum); | 580 | hash2 = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum); |
521 | slot2 = hash2 & udptable->mask; | 581 | slot2 = hash2 & udptable->mask; |
@@ -525,7 +585,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
525 | 585 | ||
526 | result = udp4_lib_lookup2(net, saddr, sport, | 586 | result = udp4_lib_lookup2(net, saddr, sport, |
527 | htonl(INADDR_ANY), hnum, dif, | 587 | htonl(INADDR_ANY), hnum, dif, |
528 | hslot2, slot2); | 588 | hslot2, slot2, skb); |
529 | } | 589 | } |
530 | rcu_read_unlock(); | 590 | rcu_read_unlock(); |
531 | return result; | 591 | return result; |
@@ -541,8 +601,15 @@ begin: | |||
541 | badness = score; | 601 | badness = score; |
542 | reuseport = sk->sk_reuseport; | 602 | reuseport = sk->sk_reuseport; |
543 | if (reuseport) { | 603 | if (reuseport) { |
604 | struct sock *sk2; | ||
544 | hash = udp_ehashfn(net, daddr, hnum, | 605 | hash = udp_ehashfn(net, daddr, hnum, |
545 | saddr, sport); | 606 | saddr, sport); |
607 | sk2 = reuseport_select_sock(sk, hash, skb, | ||
608 | sizeof(struct udphdr)); | ||
609 | if (sk2) { | ||
610 | result = sk2; | ||
611 | goto found; | ||
612 | } | ||
546 | matches = 1; | 613 | matches = 1; |
547 | } | 614 | } |
548 | } else if (score == badness && reuseport) { | 615 | } else if (score == badness && reuseport) { |
@@ -561,6 +628,7 @@ begin: | |||
561 | goto begin; | 628 | goto begin; |
562 | 629 | ||
563 | if (result) { | 630 | if (result) { |
631 | found: | ||
564 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) | 632 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) |
565 | result = NULL; | 633 | result = NULL; |
566 | else if (unlikely(compute_score(result, net, saddr, hnum, sport, | 634 | else if (unlikely(compute_score(result, net, saddr, hnum, sport, |
@@ -582,13 +650,14 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb, | |||
582 | 650 | ||
583 | return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport, | 651 | return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport, |
584 | iph->daddr, dport, inet_iif(skb), | 652 | iph->daddr, dport, inet_iif(skb), |
585 | udptable); | 653 | udptable, skb); |
586 | } | 654 | } |
587 | 655 | ||
588 | struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, | 656 | struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, |
589 | __be32 daddr, __be16 dport, int dif) | 657 | __be32 daddr, __be16 dport, int dif) |
590 | { | 658 | { |
591 | return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table); | 659 | return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, |
660 | &udp_table, NULL); | ||
592 | } | 661 | } |
593 | EXPORT_SYMBOL_GPL(udp4_lib_lookup); | 662 | EXPORT_SYMBOL_GPL(udp4_lib_lookup); |
594 | 663 | ||
@@ -636,7 +705,8 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) | |||
636 | struct net *net = dev_net(skb->dev); | 705 | struct net *net = dev_net(skb->dev); |
637 | 706 | ||
638 | sk = __udp4_lib_lookup(net, iph->daddr, uh->dest, | 707 | sk = __udp4_lib_lookup(net, iph->daddr, uh->dest, |
639 | iph->saddr, uh->source, skb->dev->ifindex, udptable); | 708 | iph->saddr, uh->source, skb->dev->ifindex, udptable, |
709 | NULL); | ||
640 | if (!sk) { | 710 | if (!sk) { |
641 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | 711 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); |
642 | return; /* No socket for error */ | 712 | return; /* No socket for error */ |
@@ -773,7 +843,8 @@ void udp_set_csum(bool nocheck, struct sk_buff *skb, | |||
773 | else if (skb_is_gso(skb)) | 843 | else if (skb_is_gso(skb)) |
774 | uh->check = ~udp_v4_check(len, saddr, daddr, 0); | 844 | uh->check = ~udp_v4_check(len, saddr, daddr, 0); |
775 | else if (skb_dst(skb) && skb_dst(skb)->dev && | 845 | else if (skb_dst(skb) && skb_dst(skb)->dev && |
776 | (skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) { | 846 | (skb_dst(skb)->dev->features & |
847 | (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM))) { | ||
777 | 848 | ||
778 | BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL); | 849 | BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL); |
779 | 850 | ||
@@ -1026,8 +1097,11 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
1026 | flow_flags, | 1097 | flow_flags, |
1027 | faddr, saddr, dport, inet->inet_sport); | 1098 | faddr, saddr, dport, inet->inet_sport); |
1028 | 1099 | ||
1029 | if (!saddr && ipc.oif) | 1100 | if (!saddr && ipc.oif) { |
1030 | l3mdev_get_saddr(net, ipc.oif, fl4); | 1101 | err = l3mdev_get_saddr(net, ipc.oif, fl4); |
1102 | if (err < 0) | ||
1103 | goto out; | ||
1104 | } | ||
1031 | 1105 | ||
1032 | security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); | 1106 | security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); |
1033 | rt = ip_route_output_flow(net, fl4, sk); | 1107 | rt = ip_route_output_flow(net, fl4, sk); |
@@ -1271,6 +1345,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, | |||
1271 | int peeked, off = 0; | 1345 | int peeked, off = 0; |
1272 | int err; | 1346 | int err; |
1273 | int is_udplite = IS_UDPLITE(sk); | 1347 | int is_udplite = IS_UDPLITE(sk); |
1348 | bool checksum_valid = false; | ||
1274 | bool slow; | 1349 | bool slow; |
1275 | 1350 | ||
1276 | if (flags & MSG_ERRQUEUE) | 1351 | if (flags & MSG_ERRQUEUE) |
@@ -1296,11 +1371,12 @@ try_again: | |||
1296 | */ | 1371 | */ |
1297 | 1372 | ||
1298 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { | 1373 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { |
1299 | if (udp_lib_checksum_complete(skb)) | 1374 | checksum_valid = !udp_lib_checksum_complete(skb); |
1375 | if (!checksum_valid) | ||
1300 | goto csum_copy_err; | 1376 | goto csum_copy_err; |
1301 | } | 1377 | } |
1302 | 1378 | ||
1303 | if (skb_csum_unnecessary(skb)) | 1379 | if (checksum_valid || skb_csum_unnecessary(skb)) |
1304 | err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), | 1380 | err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), |
1305 | msg, copied); | 1381 | msg, copied); |
1306 | else { | 1382 | else { |
@@ -1396,6 +1472,8 @@ void udp_lib_unhash(struct sock *sk) | |||
1396 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); | 1472 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); |
1397 | 1473 | ||
1398 | spin_lock_bh(&hslot->lock); | 1474 | spin_lock_bh(&hslot->lock); |
1475 | if (rcu_access_pointer(sk->sk_reuseport_cb)) | ||
1476 | reuseport_detach_sock(sk); | ||
1399 | if (sk_nulls_del_node_init_rcu(sk)) { | 1477 | if (sk_nulls_del_node_init_rcu(sk)) { |
1400 | hslot->count--; | 1478 | hslot->count--; |
1401 | inet_sk(sk)->inet_num = 0; | 1479 | inet_sk(sk)->inet_num = 0; |
@@ -1423,22 +1501,28 @@ void udp_lib_rehash(struct sock *sk, u16 newhash) | |||
1423 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); | 1501 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); |
1424 | nhslot2 = udp_hashslot2(udptable, newhash); | 1502 | nhslot2 = udp_hashslot2(udptable, newhash); |
1425 | udp_sk(sk)->udp_portaddr_hash = newhash; | 1503 | udp_sk(sk)->udp_portaddr_hash = newhash; |
1426 | if (hslot2 != nhslot2) { | 1504 | |
1505 | if (hslot2 != nhslot2 || | ||
1506 | rcu_access_pointer(sk->sk_reuseport_cb)) { | ||
1427 | hslot = udp_hashslot(udptable, sock_net(sk), | 1507 | hslot = udp_hashslot(udptable, sock_net(sk), |
1428 | udp_sk(sk)->udp_port_hash); | 1508 | udp_sk(sk)->udp_port_hash); |
1429 | /* we must lock primary chain too */ | 1509 | /* we must lock primary chain too */ |
1430 | spin_lock_bh(&hslot->lock); | 1510 | spin_lock_bh(&hslot->lock); |
1431 | 1511 | if (rcu_access_pointer(sk->sk_reuseport_cb)) | |
1432 | spin_lock(&hslot2->lock); | 1512 | reuseport_detach_sock(sk); |
1433 | hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); | 1513 | |
1434 | hslot2->count--; | 1514 | if (hslot2 != nhslot2) { |
1435 | spin_unlock(&hslot2->lock); | 1515 | spin_lock(&hslot2->lock); |
1436 | 1516 | hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); | |
1437 | spin_lock(&nhslot2->lock); | 1517 | hslot2->count--; |
1438 | hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, | 1518 | spin_unlock(&hslot2->lock); |
1439 | &nhslot2->head); | 1519 | |
1440 | nhslot2->count++; | 1520 | spin_lock(&nhslot2->lock); |
1441 | spin_unlock(&nhslot2->lock); | 1521 | hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, |
1522 | &nhslot2->head); | ||
1523 | nhslot2->count++; | ||
1524 | spin_unlock(&nhslot2->lock); | ||
1525 | } | ||
1442 | 1526 | ||
1443 | spin_unlock_bh(&hslot->lock); | 1527 | spin_unlock_bh(&hslot->lock); |
1444 | } | 1528 | } |
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 6116604bf6e8..df1966f3b6ec 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
@@ -44,7 +44,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, | |||
44 | sk = __udp4_lib_lookup(net, | 44 | sk = __udp4_lib_lookup(net, |
45 | req->id.idiag_src[0], req->id.idiag_sport, | 45 | req->id.idiag_src[0], req->id.idiag_sport, |
46 | req->id.idiag_dst[0], req->id.idiag_dport, | 46 | req->id.idiag_dst[0], req->id.idiag_dport, |
47 | req->id.idiag_if, tbl); | 47 | req->id.idiag_if, tbl, NULL); |
48 | #if IS_ENABLED(CONFIG_IPV6) | 48 | #if IS_ENABLED(CONFIG_IPV6) |
49 | else if (req->sdiag_family == AF_INET6) | 49 | else if (req->sdiag_family == AF_INET6) |
50 | sk = __udp6_lib_lookup(net, | 50 | sk = __udp6_lib_lookup(net, |
@@ -52,7 +52,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, | |||
52 | req->id.idiag_sport, | 52 | req->id.idiag_sport, |
53 | (struct in6_addr *)req->id.idiag_dst, | 53 | (struct in6_addr *)req->id.idiag_dst, |
54 | req->id.idiag_dport, | 54 | req->id.idiag_dport, |
55 | req->id.idiag_if, tbl); | 55 | req->id.idiag_if, tbl, NULL); |
56 | #endif | 56 | #endif |
57 | else | 57 | else |
58 | goto out_nosk; | 58 | goto out_nosk; |
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index f9386160cbee..4c519c1dc161 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
@@ -21,6 +21,7 @@ static struct udp_offload_priv __rcu *udp_offload_base __read_mostly; | |||
21 | 21 | ||
22 | struct udp_offload_priv { | 22 | struct udp_offload_priv { |
23 | struct udp_offload *offload; | 23 | struct udp_offload *offload; |
24 | possible_net_t net; | ||
24 | struct rcu_head rcu; | 25 | struct rcu_head rcu; |
25 | struct udp_offload_priv __rcu *next; | 26 | struct udp_offload_priv __rcu *next; |
26 | }; | 27 | }; |
@@ -60,8 +61,9 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, | |||
60 | 61 | ||
61 | /* Try to offload checksum if possible */ | 62 | /* Try to offload checksum if possible */ |
62 | offload_csum = !!(need_csum && | 63 | offload_csum = !!(need_csum && |
63 | (skb->dev->features & | 64 | ((skb->dev->features & NETIF_F_HW_CSUM) || |
64 | (is_ipv6 ? NETIF_F_V6_CSUM : NETIF_F_V4_CSUM))); | 65 | (skb->dev->features & (is_ipv6 ? |
66 | NETIF_F_IPV6_CSUM : NETIF_F_IP_CSUM)))); | ||
65 | 67 | ||
66 | /* segment inner packet. */ | 68 | /* segment inner packet. */ |
67 | enc_features = skb->dev->hw_enc_features & features; | 69 | enc_features = skb->dev->hw_enc_features & features; |
@@ -241,13 +243,14 @@ out: | |||
241 | return segs; | 243 | return segs; |
242 | } | 244 | } |
243 | 245 | ||
244 | int udp_add_offload(struct udp_offload *uo) | 246 | int udp_add_offload(struct net *net, struct udp_offload *uo) |
245 | { | 247 | { |
246 | struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_ATOMIC); | 248 | struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_ATOMIC); |
247 | 249 | ||
248 | if (!new_offload) | 250 | if (!new_offload) |
249 | return -ENOMEM; | 251 | return -ENOMEM; |
250 | 252 | ||
253 | write_pnet(&new_offload->net, net); | ||
251 | new_offload->offload = uo; | 254 | new_offload->offload = uo; |
252 | 255 | ||
253 | spin_lock(&udp_offload_lock); | 256 | spin_lock(&udp_offload_lock); |
@@ -311,7 +314,8 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, | |||
311 | rcu_read_lock(); | 314 | rcu_read_lock(); |
312 | uo_priv = rcu_dereference(udp_offload_base); | 315 | uo_priv = rcu_dereference(udp_offload_base); |
313 | for (; uo_priv != NULL; uo_priv = rcu_dereference(uo_priv->next)) { | 316 | for (; uo_priv != NULL; uo_priv = rcu_dereference(uo_priv->next)) { |
314 | if (uo_priv->offload->port == uh->dest && | 317 | if (net_eq(read_pnet(&uo_priv->net), dev_net(skb->dev)) && |
318 | uo_priv->offload->port == uh->dest && | ||
315 | uo_priv->offload->callbacks.gro_receive) | 319 | uo_priv->offload->callbacks.gro_receive) |
316 | goto unflush; | 320 | goto unflush; |
317 | } | 321 | } |
@@ -389,7 +393,8 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff) | |||
389 | 393 | ||
390 | uo_priv = rcu_dereference(udp_offload_base); | 394 | uo_priv = rcu_dereference(udp_offload_base); |
391 | for (; uo_priv != NULL; uo_priv = rcu_dereference(uo_priv->next)) { | 395 | for (; uo_priv != NULL; uo_priv = rcu_dereference(uo_priv->next)) { |
392 | if (uo_priv->offload->port == uh->dest && | 396 | if (net_eq(read_pnet(&uo_priv->net), dev_net(skb->dev)) && |
397 | uo_priv->offload->port == uh->dest && | ||
393 | uo_priv->offload->callbacks.gro_complete) | 398 | uo_priv->offload->callbacks.gro_complete) |
394 | break; | 399 | break; |
395 | } | 400 | } |
diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c index aba428626b52..0ec08814f37d 100644 --- a/net/ipv4/udp_tunnel.c +++ b/net/ipv4/udp_tunnel.c | |||
@@ -74,10 +74,10 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, | |||
74 | } | 74 | } |
75 | EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock); | 75 | EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock); |
76 | 76 | ||
77 | int udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, | 77 | void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, |
78 | __be32 src, __be32 dst, __u8 tos, __u8 ttl, | 78 | __be32 src, __be32 dst, __u8 tos, __u8 ttl, |
79 | __be16 df, __be16 src_port, __be16 dst_port, | 79 | __be16 df, __be16 src_port, __be16 dst_port, |
80 | bool xnet, bool nocheck) | 80 | bool xnet, bool nocheck) |
81 | { | 81 | { |
82 | struct udphdr *uh; | 82 | struct udphdr *uh; |
83 | 83 | ||
@@ -91,8 +91,7 @@ int udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, | |||
91 | 91 | ||
92 | udp_set_csum(nocheck, skb, src, dst, skb->len); | 92 | udp_set_csum(nocheck, skb, src, dst, skb->len); |
93 | 93 | ||
94 | return iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, | 94 | iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, xnet); |
95 | tos, ttl, df, xnet); | ||
96 | } | 95 | } |
97 | EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); | 96 | EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); |
98 | 97 | ||
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 1e0c3c835a63..7b0edb37a115 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -259,7 +259,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
259 | xfrm_dst_ifdown(dst, dev); | 259 | xfrm_dst_ifdown(dst, dev); |
260 | } | 260 | } |
261 | 261 | ||
262 | static struct dst_ops xfrm4_dst_ops = { | 262 | static struct dst_ops xfrm4_dst_ops_template = { |
263 | .family = AF_INET, | 263 | .family = AF_INET, |
264 | .gc = xfrm4_garbage_collect, | 264 | .gc = xfrm4_garbage_collect, |
265 | .update_pmtu = xfrm4_update_pmtu, | 265 | .update_pmtu = xfrm4_update_pmtu, |
@@ -273,7 +273,7 @@ static struct dst_ops xfrm4_dst_ops = { | |||
273 | 273 | ||
274 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { | 274 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { |
275 | .family = AF_INET, | 275 | .family = AF_INET, |
276 | .dst_ops = &xfrm4_dst_ops, | 276 | .dst_ops = &xfrm4_dst_ops_template, |
277 | .dst_lookup = xfrm4_dst_lookup, | 277 | .dst_lookup = xfrm4_dst_lookup, |
278 | .get_saddr = xfrm4_get_saddr, | 278 | .get_saddr = xfrm4_get_saddr, |
279 | .decode_session = _decode_session4, | 279 | .decode_session = _decode_session4, |
@@ -295,7 +295,7 @@ static struct ctl_table xfrm4_policy_table[] = { | |||
295 | { } | 295 | { } |
296 | }; | 296 | }; |
297 | 297 | ||
298 | static int __net_init xfrm4_net_init(struct net *net) | 298 | static int __net_init xfrm4_net_sysctl_init(struct net *net) |
299 | { | 299 | { |
300 | struct ctl_table *table; | 300 | struct ctl_table *table; |
301 | struct ctl_table_header *hdr; | 301 | struct ctl_table_header *hdr; |
@@ -323,7 +323,7 @@ err_alloc: | |||
323 | return -ENOMEM; | 323 | return -ENOMEM; |
324 | } | 324 | } |
325 | 325 | ||
326 | static void __net_exit xfrm4_net_exit(struct net *net) | 326 | static void __net_exit xfrm4_net_sysctl_exit(struct net *net) |
327 | { | 327 | { |
328 | struct ctl_table *table; | 328 | struct ctl_table *table; |
329 | 329 | ||
@@ -335,12 +335,44 @@ static void __net_exit xfrm4_net_exit(struct net *net) | |||
335 | if (!net_eq(net, &init_net)) | 335 | if (!net_eq(net, &init_net)) |
336 | kfree(table); | 336 | kfree(table); |
337 | } | 337 | } |
338 | #else /* CONFIG_SYSCTL */ | ||
339 | static int inline xfrm4_net_sysctl_init(struct net *net) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static void inline xfrm4_net_sysctl_exit(struct net *net) | ||
345 | { | ||
346 | } | ||
347 | #endif | ||
348 | |||
349 | static int __net_init xfrm4_net_init(struct net *net) | ||
350 | { | ||
351 | int ret; | ||
352 | |||
353 | memcpy(&net->xfrm.xfrm4_dst_ops, &xfrm4_dst_ops_template, | ||
354 | sizeof(xfrm4_dst_ops_template)); | ||
355 | ret = dst_entries_init(&net->xfrm.xfrm4_dst_ops); | ||
356 | if (ret) | ||
357 | return ret; | ||
358 | |||
359 | ret = xfrm4_net_sysctl_init(net); | ||
360 | if (ret) | ||
361 | dst_entries_destroy(&net->xfrm.xfrm4_dst_ops); | ||
362 | |||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | static void __net_exit xfrm4_net_exit(struct net *net) | ||
367 | { | ||
368 | xfrm4_net_sysctl_exit(net); | ||
369 | dst_entries_destroy(&net->xfrm.xfrm4_dst_ops); | ||
370 | } | ||
338 | 371 | ||
339 | static struct pernet_operations __net_initdata xfrm4_net_ops = { | 372 | static struct pernet_operations __net_initdata xfrm4_net_ops = { |
340 | .init = xfrm4_net_init, | 373 | .init = xfrm4_net_init, |
341 | .exit = xfrm4_net_exit, | 374 | .exit = xfrm4_net_exit, |
342 | }; | 375 | }; |
343 | #endif | ||
344 | 376 | ||
345 | static void __init xfrm4_policy_init(void) | 377 | static void __init xfrm4_policy_init(void) |
346 | { | 378 | { |
@@ -349,13 +381,9 @@ static void __init xfrm4_policy_init(void) | |||
349 | 381 | ||
350 | void __init xfrm4_init(void) | 382 | void __init xfrm4_init(void) |
351 | { | 383 | { |
352 | dst_entries_init(&xfrm4_dst_ops); | ||
353 | |||
354 | xfrm4_state_init(); | 384 | xfrm4_state_init(); |
355 | xfrm4_policy_init(); | 385 | xfrm4_policy_init(); |
356 | xfrm4_protocol_init(); | 386 | xfrm4_protocol_init(); |
357 | #ifdef CONFIG_SYSCTL | ||
358 | register_pernet_subsys(&xfrm4_net_ops); | 387 | register_pernet_subsys(&xfrm4_net_ops); |
359 | #endif | ||
360 | } | 388 | } |
361 | 389 | ||
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 983bb999738c..bb7dabe2ebbf 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -94,6 +94,7 @@ config IPV6_MIP6 | |||
94 | 94 | ||
95 | config IPV6_ILA | 95 | config IPV6_ILA |
96 | tristate "IPv6: Identifier Locator Addressing (ILA)" | 96 | tristate "IPv6: Identifier Locator Addressing (ILA)" |
97 | depends on NETFILTER | ||
97 | select LWTUNNEL | 98 | select LWTUNNEL |
98 | ---help--- | 99 | ---help--- |
99 | Support for IPv6 Identifier Locator Addressing (ILA). | 100 | Support for IPv6 Identifier Locator Addressing (ILA). |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 2c900c7b7eb1..2fbd90bf8d33 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -34,7 +34,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o | |||
34 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o | 34 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o |
35 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o | 35 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o |
36 | obj-$(CONFIG_IPV6_MIP6) += mip6.o | 36 | obj-$(CONFIG_IPV6_MIP6) += mip6.o |
37 | obj-$(CONFIG_IPV6_ILA) += ila.o | 37 | obj-$(CONFIG_IPV6_ILA) += ila/ |
38 | obj-$(CONFIG_NETFILTER) += netfilter/ | 38 | obj-$(CONFIG_NETFILTER) += netfilter/ |
39 | 39 | ||
40 | obj-$(CONFIG_IPV6_VTI) += ip6_vti.o | 40 | obj-$(CONFIG_IPV6_VTI) += ip6_vti.o |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d84742f003a9..38eeddedfc21 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -70,7 +70,7 @@ | |||
70 | #include <net/sock.h> | 70 | #include <net/sock.h> |
71 | #include <net/snmp.h> | 71 | #include <net/snmp.h> |
72 | 72 | ||
73 | #include <net/af_ieee802154.h> | 73 | #include <net/6lowpan.h> |
74 | #include <net/firewire.h> | 74 | #include <net/firewire.h> |
75 | #include <net/ipv6.h> | 75 | #include <net/ipv6.h> |
76 | #include <net/protocol.h> | 76 | #include <net/protocol.h> |
@@ -350,6 +350,12 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
350 | setup_timer(&ndev->rs_timer, addrconf_rs_timer, | 350 | setup_timer(&ndev->rs_timer, addrconf_rs_timer, |
351 | (unsigned long)ndev); | 351 | (unsigned long)ndev); |
352 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 352 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
353 | |||
354 | if (ndev->cnf.stable_secret.initialized) | ||
355 | ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY; | ||
356 | else | ||
357 | ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64; | ||
358 | |||
353 | ndev->cnf.mtu6 = dev->mtu; | 359 | ndev->cnf.mtu6 = dev->mtu; |
354 | ndev->cnf.sysctl = NULL; | 360 | ndev->cnf.sysctl = NULL; |
355 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); | 361 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); |
@@ -1766,12 +1772,13 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add | |||
1766 | 1772 | ||
1767 | static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | 1773 | static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) |
1768 | { | 1774 | { |
1775 | if (dad_failed) | ||
1776 | ifp->flags |= IFA_F_DADFAILED; | ||
1777 | |||
1769 | if (ifp->flags&IFA_F_PERMANENT) { | 1778 | if (ifp->flags&IFA_F_PERMANENT) { |
1770 | spin_lock_bh(&ifp->lock); | 1779 | spin_lock_bh(&ifp->lock); |
1771 | addrconf_del_dad_work(ifp); | 1780 | addrconf_del_dad_work(ifp); |
1772 | ifp->flags |= IFA_F_TENTATIVE; | 1781 | ifp->flags |= IFA_F_TENTATIVE; |
1773 | if (dad_failed) | ||
1774 | ifp->flags |= IFA_F_DADFAILED; | ||
1775 | spin_unlock_bh(&ifp->lock); | 1782 | spin_unlock_bh(&ifp->lock); |
1776 | if (dad_failed) | 1783 | if (dad_failed) |
1777 | ipv6_ifa_notify(0, ifp); | 1784 | ipv6_ifa_notify(0, ifp); |
@@ -1947,9 +1954,9 @@ static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | |||
1947 | 1954 | ||
1948 | static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev) | 1955 | static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev) |
1949 | { | 1956 | { |
1950 | if (dev->addr_len != IEEE802154_ADDR_LEN) | 1957 | if (dev->addr_len != EUI64_ADDR_LEN) |
1951 | return -1; | 1958 | return -1; |
1952 | memcpy(eui, dev->dev_addr, 8); | 1959 | memcpy(eui, dev->dev_addr, EUI64_ADDR_LEN); |
1953 | eui[0] ^= 2; | 1960 | eui[0] ^= 2; |
1954 | return 0; | 1961 | return 0; |
1955 | } | 1962 | } |
@@ -2041,7 +2048,6 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | |||
2041 | case ARPHRD_IPGRE: | 2048 | case ARPHRD_IPGRE: |
2042 | return addrconf_ifid_gre(eui, dev); | 2049 | return addrconf_ifid_gre(eui, dev); |
2043 | case ARPHRD_6LOWPAN: | 2050 | case ARPHRD_6LOWPAN: |
2044 | case ARPHRD_IEEE802154: | ||
2045 | return addrconf_ifid_eui64(eui, dev); | 2051 | return addrconf_ifid_eui64(eui, dev); |
2046 | case ARPHRD_IEEE1394: | 2052 | case ARPHRD_IEEE1394: |
2047 | return addrconf_ifid_ieee1394(eui, dev); | 2053 | return addrconf_ifid_ieee1394(eui, dev); |
@@ -2314,6 +2320,12 @@ static void manage_tempaddrs(struct inet6_dev *idev, | |||
2314 | } | 2320 | } |
2315 | } | 2321 | } |
2316 | 2322 | ||
2323 | static bool is_addr_mode_generate_stable(struct inet6_dev *idev) | ||
2324 | { | ||
2325 | return idev->addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY || | ||
2326 | idev->addr_gen_mode == IN6_ADDR_GEN_MODE_RANDOM; | ||
2327 | } | ||
2328 | |||
2317 | void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) | 2329 | void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) |
2318 | { | 2330 | { |
2319 | struct prefix_info *pinfo; | 2331 | struct prefix_info *pinfo; |
@@ -2427,8 +2439,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) | |||
2427 | in6_dev->token.s6_addr + 8, 8); | 2439 | in6_dev->token.s6_addr + 8, 8); |
2428 | read_unlock_bh(&in6_dev->lock); | 2440 | read_unlock_bh(&in6_dev->lock); |
2429 | tokenized = true; | 2441 | tokenized = true; |
2430 | } else if (in6_dev->addr_gen_mode == | 2442 | } else if (is_addr_mode_generate_stable(in6_dev) && |
2431 | IN6_ADDR_GEN_MODE_STABLE_PRIVACY && | ||
2432 | !ipv6_generate_stable_address(&addr, 0, | 2443 | !ipv6_generate_stable_address(&addr, 0, |
2433 | in6_dev)) { | 2444 | in6_dev)) { |
2434 | addr_flags |= IFA_F_STABLE_PRIVACY; | 2445 | addr_flags |= IFA_F_STABLE_PRIVACY; |
@@ -2455,7 +2466,7 @@ ok: | |||
2455 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 2466 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
2456 | if (in6_dev->cnf.optimistic_dad && | 2467 | if (in6_dev->cnf.optimistic_dad && |
2457 | !net->ipv6.devconf_all->forwarding && sllao) | 2468 | !net->ipv6.devconf_all->forwarding && sllao) |
2458 | addr_flags = IFA_F_OPTIMISTIC; | 2469 | addr_flags |= IFA_F_OPTIMISTIC; |
2459 | #endif | 2470 | #endif |
2460 | 2471 | ||
2461 | /* Do not allow to create too much of autoconfigured | 2472 | /* Do not allow to create too much of autoconfigured |
@@ -3028,6 +3039,17 @@ retry: | |||
3028 | return 0; | 3039 | return 0; |
3029 | } | 3040 | } |
3030 | 3041 | ||
3042 | static void ipv6_gen_mode_random_init(struct inet6_dev *idev) | ||
3043 | { | ||
3044 | struct ipv6_stable_secret *s = &idev->cnf.stable_secret; | ||
3045 | |||
3046 | if (s->initialized) | ||
3047 | return; | ||
3048 | s = &idev->cnf.stable_secret; | ||
3049 | get_random_bytes(&s->secret, sizeof(s->secret)); | ||
3050 | s->initialized = true; | ||
3051 | } | ||
3052 | |||
3031 | static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) | 3053 | static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) |
3032 | { | 3054 | { |
3033 | struct in6_addr addr; | 3055 | struct in6_addr addr; |
@@ -3038,13 +3060,18 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) | |||
3038 | 3060 | ||
3039 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | 3061 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); |
3040 | 3062 | ||
3041 | if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY) { | 3063 | switch (idev->addr_gen_mode) { |
3064 | case IN6_ADDR_GEN_MODE_RANDOM: | ||
3065 | ipv6_gen_mode_random_init(idev); | ||
3066 | /* fallthrough */ | ||
3067 | case IN6_ADDR_GEN_MODE_STABLE_PRIVACY: | ||
3042 | if (!ipv6_generate_stable_address(&addr, 0, idev)) | 3068 | if (!ipv6_generate_stable_address(&addr, 0, idev)) |
3043 | addrconf_add_linklocal(idev, &addr, | 3069 | addrconf_add_linklocal(idev, &addr, |
3044 | IFA_F_STABLE_PRIVACY); | 3070 | IFA_F_STABLE_PRIVACY); |
3045 | else if (prefix_route) | 3071 | else if (prefix_route) |
3046 | addrconf_prefix_route(&addr, 64, idev->dev, 0, 0); | 3072 | addrconf_prefix_route(&addr, 64, idev->dev, 0, 0); |
3047 | } else if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64) { | 3073 | break; |
3074 | case IN6_ADDR_GEN_MODE_EUI64: | ||
3048 | /* addrconf_add_linklocal also adds a prefix_route and we | 3075 | /* addrconf_add_linklocal also adds a prefix_route and we |
3049 | * only need to care about prefix routes if ipv6_generate_eui64 | 3076 | * only need to care about prefix routes if ipv6_generate_eui64 |
3050 | * couldn't generate one. | 3077 | * couldn't generate one. |
@@ -3053,6 +3080,11 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) | |||
3053 | addrconf_add_linklocal(idev, &addr, 0); | 3080 | addrconf_add_linklocal(idev, &addr, 0); |
3054 | else if (prefix_route) | 3081 | else if (prefix_route) |
3055 | addrconf_prefix_route(&addr, 64, idev->dev, 0, 0); | 3082 | addrconf_prefix_route(&addr, 64, idev->dev, 0, 0); |
3083 | break; | ||
3084 | case IN6_ADDR_GEN_MODE_NONE: | ||
3085 | default: | ||
3086 | /* will not add any link local address */ | ||
3087 | break; | ||
3056 | } | 3088 | } |
3057 | } | 3089 | } |
3058 | 3090 | ||
@@ -3066,10 +3098,10 @@ static void addrconf_dev_config(struct net_device *dev) | |||
3066 | (dev->type != ARPHRD_FDDI) && | 3098 | (dev->type != ARPHRD_FDDI) && |
3067 | (dev->type != ARPHRD_ARCNET) && | 3099 | (dev->type != ARPHRD_ARCNET) && |
3068 | (dev->type != ARPHRD_INFINIBAND) && | 3100 | (dev->type != ARPHRD_INFINIBAND) && |
3069 | (dev->type != ARPHRD_IEEE802154) && | ||
3070 | (dev->type != ARPHRD_IEEE1394) && | 3101 | (dev->type != ARPHRD_IEEE1394) && |
3071 | (dev->type != ARPHRD_TUNNEL6) && | 3102 | (dev->type != ARPHRD_TUNNEL6) && |
3072 | (dev->type != ARPHRD_6LOWPAN)) { | 3103 | (dev->type != ARPHRD_6LOWPAN) && |
3104 | (dev->type != ARPHRD_NONE)) { | ||
3073 | /* Alas, we support only Ethernet autoconfiguration. */ | 3105 | /* Alas, we support only Ethernet autoconfiguration. */ |
3074 | return; | 3106 | return; |
3075 | } | 3107 | } |
@@ -3078,6 +3110,11 @@ static void addrconf_dev_config(struct net_device *dev) | |||
3078 | if (IS_ERR(idev)) | 3110 | if (IS_ERR(idev)) |
3079 | return; | 3111 | return; |
3080 | 3112 | ||
3113 | /* this device type has no EUI support */ | ||
3114 | if (dev->type == ARPHRD_NONE && | ||
3115 | idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64) | ||
3116 | idev->addr_gen_mode = IN6_ADDR_GEN_MODE_RANDOM; | ||
3117 | |||
3081 | addrconf_addr_gen(idev, false); | 3118 | addrconf_addr_gen(idev, false); |
3082 | } | 3119 | } |
3083 | 3120 | ||
@@ -3287,7 +3324,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
3287 | 3324 | ||
3288 | case NETDEV_PRE_TYPE_CHANGE: | 3325 | case NETDEV_PRE_TYPE_CHANGE: |
3289 | case NETDEV_POST_TYPE_CHANGE: | 3326 | case NETDEV_POST_TYPE_CHANGE: |
3290 | addrconf_type_change(dev, event); | 3327 | if (idev) |
3328 | addrconf_type_change(dev, event); | ||
3291 | break; | 3329 | break; |
3292 | } | 3330 | } |
3293 | 3331 | ||
@@ -3642,7 +3680,7 @@ static void addrconf_dad_work(struct work_struct *w) | |||
3642 | 3680 | ||
3643 | /* send a neighbour solicitation for our addr */ | 3681 | /* send a neighbour solicitation for our addr */ |
3644 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 3682 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
3645 | ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any, NULL); | 3683 | ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any); |
3646 | out: | 3684 | out: |
3647 | in6_ifa_put(ifp); | 3685 | in6_ifa_put(ifp); |
3648 | rtnl_unlock(); | 3686 | rtnl_unlock(); |
@@ -4921,7 +4959,8 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla) | |||
4921 | 4959 | ||
4922 | if (mode != IN6_ADDR_GEN_MODE_EUI64 && | 4960 | if (mode != IN6_ADDR_GEN_MODE_EUI64 && |
4923 | mode != IN6_ADDR_GEN_MODE_NONE && | 4961 | mode != IN6_ADDR_GEN_MODE_NONE && |
4924 | mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY) | 4962 | mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY && |
4963 | mode != IN6_ADDR_GEN_MODE_RANDOM) | ||
4925 | return -EINVAL; | 4964 | return -EINVAL; |
4926 | 4965 | ||
4927 | if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY && | 4966 | if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY && |
@@ -5200,6 +5239,20 @@ int addrconf_sysctl_forward(struct ctl_table *ctl, int write, | |||
5200 | } | 5239 | } |
5201 | 5240 | ||
5202 | static | 5241 | static |
5242 | int addrconf_sysctl_hop_limit(struct ctl_table *ctl, int write, | ||
5243 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
5244 | { | ||
5245 | struct ctl_table lctl; | ||
5246 | int min_hl = 1, max_hl = 255; | ||
5247 | |||
5248 | lctl = *ctl; | ||
5249 | lctl.extra1 = &min_hl; | ||
5250 | lctl.extra2 = &max_hl; | ||
5251 | |||
5252 | return proc_dointvec_minmax(&lctl, write, buffer, lenp, ppos); | ||
5253 | } | ||
5254 | |||
5255 | static | ||
5203 | int addrconf_sysctl_mtu(struct ctl_table *ctl, int write, | 5256 | int addrconf_sysctl_mtu(struct ctl_table *ctl, int write, |
5204 | void __user *buffer, size_t *lenp, loff_t *ppos) | 5257 | void __user *buffer, size_t *lenp, loff_t *ppos) |
5205 | { | 5258 | { |
@@ -5363,13 +5416,10 @@ static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write, | |||
5363 | goto out; | 5416 | goto out; |
5364 | } | 5417 | } |
5365 | 5418 | ||
5366 | if (!write) { | 5419 | err = snprintf(str, sizeof(str), "%pI6", &secret->secret); |
5367 | err = snprintf(str, sizeof(str), "%pI6", | 5420 | if (err >= sizeof(str)) { |
5368 | &secret->secret); | 5421 | err = -EIO; |
5369 | if (err >= sizeof(str)) { | 5422 | goto out; |
5370 | err = -EIO; | ||
5371 | goto out; | ||
5372 | } | ||
5373 | } | 5423 | } |
5374 | 5424 | ||
5375 | err = proc_dostring(&lctl, write, buffer, lenp, ppos); | 5425 | err = proc_dostring(&lctl, write, buffer, lenp, ppos); |
@@ -5454,7 +5504,7 @@ static struct addrconf_sysctl_table | |||
5454 | .data = &ipv6_devconf.hop_limit, | 5504 | .data = &ipv6_devconf.hop_limit, |
5455 | .maxlen = sizeof(int), | 5505 | .maxlen = sizeof(int), |
5456 | .mode = 0644, | 5506 | .mode = 0644, |
5457 | .proc_handler = proc_dointvec, | 5507 | .proc_handler = addrconf_sysctl_hop_limit, |
5458 | }, | 5508 | }, |
5459 | { | 5509 | { |
5460 | .procname = "mtu", | 5510 | .procname = "mtu", |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 882124ebb438..a8f6986dcbe5 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -552,7 +552,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr *nlh) | |||
552 | 552 | ||
553 | rcu_read_lock(); | 553 | rcu_read_lock(); |
554 | p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index); | 554 | p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index); |
555 | if (p && ip6addrlbl_hold(p)) | 555 | if (p && !ip6addrlbl_hold(p)) |
556 | p = NULL; | 556 | p = NULL; |
557 | lseq = ip6addrlbl_table.seq; | 557 | lseq = ip6addrlbl_table.seq; |
558 | rcu_read_unlock(); | 558 | rcu_read_unlock(); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 44bb66bde0e2..9f5137cd604e 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -109,6 +109,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, | |||
109 | int try_loading_module = 0; | 109 | int try_loading_module = 0; |
110 | int err; | 110 | int err; |
111 | 111 | ||
112 | if (protocol < 0 || protocol >= IPPROTO_MAX) | ||
113 | return -EINVAL; | ||
114 | |||
112 | /* Look for the requested type/protocol pair. */ | 115 | /* Look for the requested type/protocol pair. */ |
113 | lookup_protocol: | 116 | lookup_protocol: |
114 | err = -ESOCKTNOSUPPORT; | 117 | err = -ESOCKTNOSUPPORT; |
@@ -428,9 +431,11 @@ void inet6_destroy_sock(struct sock *sk) | |||
428 | 431 | ||
429 | /* Free tx options */ | 432 | /* Free tx options */ |
430 | 433 | ||
431 | opt = xchg(&np->opt, NULL); | 434 | opt = xchg((__force struct ipv6_txoptions **)&np->opt, NULL); |
432 | if (opt) | 435 | if (opt) { |
433 | sock_kfree_s(sk, opt, opt->tot_len); | 436 | atomic_sub(opt->tot_len, &sk->sk_omem_alloc); |
437 | txopt_put(opt); | ||
438 | } | ||
434 | } | 439 | } |
435 | EXPORT_SYMBOL_GPL(inet6_destroy_sock); | 440 | EXPORT_SYMBOL_GPL(inet6_destroy_sock); |
436 | 441 | ||
@@ -659,7 +664,10 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
659 | fl6.fl6_sport = inet->inet_sport; | 664 | fl6.fl6_sport = inet->inet_sport; |
660 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 665 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
661 | 666 | ||
662 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 667 | rcu_read_lock(); |
668 | final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), | ||
669 | &final); | ||
670 | rcu_read_unlock(); | ||
663 | 671 | ||
664 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p); | 672 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p); |
665 | if (IS_ERR(dst)) { | 673 | if (IS_ERR(dst)) { |
@@ -668,7 +676,7 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
668 | return PTR_ERR(dst); | 676 | return PTR_ERR(dst); |
669 | } | 677 | } |
670 | 678 | ||
671 | __ip6_dst_store(sk, dst, NULL, NULL); | 679 | ip6_dst_store(sk, dst, NULL, NULL); |
672 | } | 680 | } |
673 | 681 | ||
674 | return 0; | 682 | return 0; |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index d70b0238f468..517c55b01ba8 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -167,8 +167,10 @@ ipv4_connected: | |||
167 | 167 | ||
168 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 168 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
169 | 169 | ||
170 | opt = flowlabel ? flowlabel->opt : np->opt; | 170 | rcu_read_lock(); |
171 | opt = flowlabel ? flowlabel->opt : rcu_dereference(np->opt); | ||
171 | final_p = fl6_update_dst(&fl6, opt, &final); | 172 | final_p = fl6_update_dst(&fl6, opt, &final); |
173 | rcu_read_unlock(); | ||
172 | 174 | ||
173 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p); | 175 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p); |
174 | err = 0; | 176 | err = 0; |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index ce203b0402be..ea7c4d64a00a 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -727,6 +727,7 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt) | |||
727 | *((char **)&opt2->dst1opt) += dif; | 727 | *((char **)&opt2->dst1opt) += dif; |
728 | if (opt2->srcrt) | 728 | if (opt2->srcrt) |
729 | *((char **)&opt2->srcrt) += dif; | 729 | *((char **)&opt2->srcrt) += dif; |
730 | atomic_set(&opt2->refcnt, 1); | ||
730 | } | 731 | } |
731 | return opt2; | 732 | return opt2; |
732 | } | 733 | } |
@@ -790,7 +791,7 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, | |||
790 | return ERR_PTR(-ENOBUFS); | 791 | return ERR_PTR(-ENOBUFS); |
791 | 792 | ||
792 | memset(opt2, 0, tot_len); | 793 | memset(opt2, 0, tot_len); |
793 | 794 | atomic_set(&opt2->refcnt, 1); | |
794 | opt2->tot_len = tot_len; | 795 | opt2->tot_len = tot_len; |
795 | p = (char *)(opt2 + 1); | 796 | p = (char *)(opt2 + 1); |
796 | 797 | ||
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 36c5a98b0472..0a37ddc7af51 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -834,11 +834,6 @@ void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6, | |||
834 | security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); | 834 | security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); |
835 | } | 835 | } |
836 | 836 | ||
837 | /* | ||
838 | * Special lock-class for __icmpv6_sk: | ||
839 | */ | ||
840 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; | ||
841 | |||
842 | static int __net_init icmpv6_sk_init(struct net *net) | 837 | static int __net_init icmpv6_sk_init(struct net *net) |
843 | { | 838 | { |
844 | struct sock *sk; | 839 | struct sock *sk; |
@@ -860,15 +855,6 @@ static int __net_init icmpv6_sk_init(struct net *net) | |||
860 | 855 | ||
861 | net->ipv6.icmp_sk[i] = sk; | 856 | net->ipv6.icmp_sk[i] = sk; |
862 | 857 | ||
863 | /* | ||
864 | * Split off their lock-class, because sk->sk_dst_lock | ||
865 | * gets used from softirqs, which is safe for | ||
866 | * __icmpv6_sk (because those never get directly used | ||
867 | * via userspace syscalls), but unsafe for normal sockets. | ||
868 | */ | ||
869 | lockdep_set_class(&sk->sk_dst_lock, | ||
870 | &icmpv6_socket_sk_dst_lock_key); | ||
871 | |||
872 | /* Enough space for 2 64K ICMP packets, including | 858 | /* Enough space for 2 64K ICMP packets, including |
873 | * sk_buff struct overhead. | 859 | * sk_buff struct overhead. |
874 | */ | 860 | */ |
diff --git a/net/ipv6/ila/Makefile b/net/ipv6/ila/Makefile new file mode 100644 index 000000000000..4b32e5921e5c --- /dev/null +++ b/net/ipv6/ila/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for ILA module | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_IPV6_ILA) += ila.o | ||
6 | |||
7 | ila-objs := ila_common.o ila_lwt.o ila_xlat.o | ||
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h new file mode 100644 index 000000000000..28542cb2b387 --- /dev/null +++ b/net/ipv6/ila/ila.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Tom Herbert <tom@herbertland.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of | ||
7 | * the License, or (at your option) any later version. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #ifndef __ILA_H | ||
12 | #define __ILA_H | ||
13 | |||
14 | #include <linux/errno.h> | ||
15 | #include <linux/ip.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/socket.h> | ||
19 | #include <linux/skbuff.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <net/checksum.h> | ||
22 | #include <net/ip.h> | ||
23 | #include <net/protocol.h> | ||
24 | #include <uapi/linux/ila.h> | ||
25 | |||
26 | struct ila_params { | ||
27 | __be64 locator; | ||
28 | __be64 locator_match; | ||
29 | __wsum csum_diff; | ||
30 | }; | ||
31 | |||
32 | static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to) | ||
33 | { | ||
34 | __be32 diff[] = { | ||
35 | ~from[0], ~from[1], to[0], to[1], | ||
36 | }; | ||
37 | |||
38 | return csum_partial(diff, sizeof(diff), 0); | ||
39 | } | ||
40 | |||
41 | void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p); | ||
42 | |||
43 | int ila_lwt_init(void); | ||
44 | void ila_lwt_fini(void); | ||
45 | int ila_xlat_init(void); | ||
46 | void ila_xlat_fini(void); | ||
47 | |||
48 | #endif /* __ILA_H */ | ||
diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c new file mode 100644 index 000000000000..32dc9aab7297 --- /dev/null +++ b/net/ipv6/ila/ila_common.c | |||
@@ -0,0 +1,103 @@ | |||
1 | #include <linux/errno.h> | ||
2 | #include <linux/ip.h> | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/module.h> | ||
5 | #include <linux/skbuff.h> | ||
6 | #include <linux/socket.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <net/checksum.h> | ||
9 | #include <net/ip.h> | ||
10 | #include <net/ip6_fib.h> | ||
11 | #include <net/lwtunnel.h> | ||
12 | #include <net/protocol.h> | ||
13 | #include <uapi/linux/ila.h> | ||
14 | #include "ila.h" | ||
15 | |||
16 | static __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p) | ||
17 | { | ||
18 | if (*(__be64 *)&ip6h->daddr == p->locator_match) | ||
19 | return p->csum_diff; | ||
20 | else | ||
21 | return compute_csum_diff8((__be32 *)&ip6h->daddr, | ||
22 | (__be32 *)&p->locator); | ||
23 | } | ||
24 | |||
25 | void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) | ||
26 | { | ||
27 | __wsum diff; | ||
28 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
29 | size_t nhoff = sizeof(struct ipv6hdr); | ||
30 | |||
31 | /* First update checksum */ | ||
32 | switch (ip6h->nexthdr) { | ||
33 | case NEXTHDR_TCP: | ||
34 | if (likely(pskb_may_pull(skb, nhoff + sizeof(struct tcphdr)))) { | ||
35 | struct tcphdr *th = (struct tcphdr *) | ||
36 | (skb_network_header(skb) + nhoff); | ||
37 | |||
38 | diff = get_csum_diff(ip6h, p); | ||
39 | inet_proto_csum_replace_by_diff(&th->check, skb, | ||
40 | diff, true); | ||
41 | } | ||
42 | break; | ||
43 | case NEXTHDR_UDP: | ||
44 | if (likely(pskb_may_pull(skb, nhoff + sizeof(struct udphdr)))) { | ||
45 | struct udphdr *uh = (struct udphdr *) | ||
46 | (skb_network_header(skb) + nhoff); | ||
47 | |||
48 | if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { | ||
49 | diff = get_csum_diff(ip6h, p); | ||
50 | inet_proto_csum_replace_by_diff(&uh->check, skb, | ||
51 | diff, true); | ||
52 | if (!uh->check) | ||
53 | uh->check = CSUM_MANGLED_0; | ||
54 | } | ||
55 | } | ||
56 | break; | ||
57 | case NEXTHDR_ICMP: | ||
58 | if (likely(pskb_may_pull(skb, | ||
59 | nhoff + sizeof(struct icmp6hdr)))) { | ||
60 | struct icmp6hdr *ih = (struct icmp6hdr *) | ||
61 | (skb_network_header(skb) + nhoff); | ||
62 | |||
63 | diff = get_csum_diff(ip6h, p); | ||
64 | inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb, | ||
65 | diff, true); | ||
66 | } | ||
67 | break; | ||
68 | } | ||
69 | |||
70 | /* Now change destination address */ | ||
71 | *(__be64 *)&ip6h->daddr = p->locator; | ||
72 | } | ||
73 | |||
74 | static int __init ila_init(void) | ||
75 | { | ||
76 | int ret; | ||
77 | |||
78 | ret = ila_lwt_init(); | ||
79 | |||
80 | if (ret) | ||
81 | goto fail_lwt; | ||
82 | |||
83 | ret = ila_xlat_init(); | ||
84 | if (ret) | ||
85 | goto fail_xlat; | ||
86 | |||
87 | return 0; | ||
88 | fail_xlat: | ||
89 | ila_lwt_fini(); | ||
90 | fail_lwt: | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | static void __exit ila_fini(void) | ||
95 | { | ||
96 | ila_xlat_fini(); | ||
97 | ila_lwt_fini(); | ||
98 | } | ||
99 | |||
100 | module_init(ila_init); | ||
101 | module_exit(ila_fini); | ||
102 | MODULE_AUTHOR("Tom Herbert <tom@herbertland.com>"); | ||
103 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv6/ila.c b/net/ipv6/ila/ila_lwt.c index 1a6852e1ac69..2ae3c4fd8aab 100644 --- a/net/ipv6/ila.c +++ b/net/ipv6/ila/ila_lwt.c | |||
@@ -11,12 +11,7 @@ | |||
11 | #include <net/lwtunnel.h> | 11 | #include <net/lwtunnel.h> |
12 | #include <net/protocol.h> | 12 | #include <net/protocol.h> |
13 | #include <uapi/linux/ila.h> | 13 | #include <uapi/linux/ila.h> |
14 | 14 | #include "ila.h" | |
15 | struct ila_params { | ||
16 | __be64 locator; | ||
17 | __be64 locator_match; | ||
18 | __wsum csum_diff; | ||
19 | }; | ||
20 | 15 | ||
21 | static inline struct ila_params *ila_params_lwtunnel( | 16 | static inline struct ila_params *ila_params_lwtunnel( |
22 | struct lwtunnel_state *lwstate) | 17 | struct lwtunnel_state *lwstate) |
@@ -24,73 +19,6 @@ static inline struct ila_params *ila_params_lwtunnel( | |||
24 | return (struct ila_params *)lwstate->data; | 19 | return (struct ila_params *)lwstate->data; |
25 | } | 20 | } |
26 | 21 | ||
27 | static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to) | ||
28 | { | ||
29 | __be32 diff[] = { | ||
30 | ~from[0], ~from[1], to[0], to[1], | ||
31 | }; | ||
32 | |||
33 | return csum_partial(diff, sizeof(diff), 0); | ||
34 | } | ||
35 | |||
36 | static inline __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p) | ||
37 | { | ||
38 | if (*(__be64 *)&ip6h->daddr == p->locator_match) | ||
39 | return p->csum_diff; | ||
40 | else | ||
41 | return compute_csum_diff8((__be32 *)&ip6h->daddr, | ||
42 | (__be32 *)&p->locator); | ||
43 | } | ||
44 | |||
45 | static void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) | ||
46 | { | ||
47 | __wsum diff; | ||
48 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
49 | size_t nhoff = sizeof(struct ipv6hdr); | ||
50 | |||
51 | /* First update checksum */ | ||
52 | switch (ip6h->nexthdr) { | ||
53 | case NEXTHDR_TCP: | ||
54 | if (likely(pskb_may_pull(skb, nhoff + sizeof(struct tcphdr)))) { | ||
55 | struct tcphdr *th = (struct tcphdr *) | ||
56 | (skb_network_header(skb) + nhoff); | ||
57 | |||
58 | diff = get_csum_diff(ip6h, p); | ||
59 | inet_proto_csum_replace_by_diff(&th->check, skb, | ||
60 | diff, true); | ||
61 | } | ||
62 | break; | ||
63 | case NEXTHDR_UDP: | ||
64 | if (likely(pskb_may_pull(skb, nhoff + sizeof(struct udphdr)))) { | ||
65 | struct udphdr *uh = (struct udphdr *) | ||
66 | (skb_network_header(skb) + nhoff); | ||
67 | |||
68 | if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { | ||
69 | diff = get_csum_diff(ip6h, p); | ||
70 | inet_proto_csum_replace_by_diff(&uh->check, skb, | ||
71 | diff, true); | ||
72 | if (!uh->check) | ||
73 | uh->check = CSUM_MANGLED_0; | ||
74 | } | ||
75 | } | ||
76 | break; | ||
77 | case NEXTHDR_ICMP: | ||
78 | if (likely(pskb_may_pull(skb, | ||
79 | nhoff + sizeof(struct icmp6hdr)))) { | ||
80 | struct icmp6hdr *ih = (struct icmp6hdr *) | ||
81 | (skb_network_header(skb) + nhoff); | ||
82 | |||
83 | diff = get_csum_diff(ip6h, p); | ||
84 | inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb, | ||
85 | diff, true); | ||
86 | } | ||
87 | break; | ||
88 | } | ||
89 | |||
90 | /* Now change destination address */ | ||
91 | *(__be64 *)&ip6h->daddr = p->locator; | ||
92 | } | ||
93 | |||
94 | static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) | 22 | static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
95 | { | 23 | { |
96 | struct dst_entry *dst = skb_dst(skb); | 24 | struct dst_entry *dst = skb_dst(skb); |
@@ -213,17 +141,12 @@ static const struct lwtunnel_encap_ops ila_encap_ops = { | |||
213 | .cmp_encap = ila_encap_cmp, | 141 | .cmp_encap = ila_encap_cmp, |
214 | }; | 142 | }; |
215 | 143 | ||
216 | static int __init ila_init(void) | 144 | int ila_lwt_init(void) |
217 | { | 145 | { |
218 | return lwtunnel_encap_add_ops(&ila_encap_ops, LWTUNNEL_ENCAP_ILA); | 146 | return lwtunnel_encap_add_ops(&ila_encap_ops, LWTUNNEL_ENCAP_ILA); |
219 | } | 147 | } |
220 | 148 | ||
221 | static void __exit ila_fini(void) | 149 | void ila_lwt_fini(void) |
222 | { | 150 | { |
223 | lwtunnel_encap_del_ops(&ila_encap_ops, LWTUNNEL_ENCAP_ILA); | 151 | lwtunnel_encap_del_ops(&ila_encap_ops, LWTUNNEL_ENCAP_ILA); |
224 | } | 152 | } |
225 | |||
226 | module_init(ila_init); | ||
227 | module_exit(ila_fini); | ||
228 | MODULE_AUTHOR("Tom Herbert <tom@herbertland.com>"); | ||
229 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c new file mode 100644 index 000000000000..295ca29a23c3 --- /dev/null +++ b/net/ipv6/ila/ila_xlat.c | |||
@@ -0,0 +1,680 @@ | |||
1 | #include <linux/jhash.h> | ||
2 | #include <linux/netfilter.h> | ||
3 | #include <linux/rcupdate.h> | ||
4 | #include <linux/rhashtable.h> | ||
5 | #include <linux/vmalloc.h> | ||
6 | #include <net/genetlink.h> | ||
7 | #include <net/ila.h> | ||
8 | #include <net/netns/generic.h> | ||
9 | #include <uapi/linux/genetlink.h> | ||
10 | #include "ila.h" | ||
11 | |||
12 | struct ila_xlat_params { | ||
13 | struct ila_params ip; | ||
14 | __be64 identifier; | ||
15 | int ifindex; | ||
16 | unsigned int dir; | ||
17 | }; | ||
18 | |||
19 | struct ila_map { | ||
20 | struct ila_xlat_params p; | ||
21 | struct rhash_head node; | ||
22 | struct ila_map __rcu *next; | ||
23 | struct rcu_head rcu; | ||
24 | }; | ||
25 | |||
26 | static unsigned int ila_net_id; | ||
27 | |||
28 | struct ila_net { | ||
29 | struct rhashtable rhash_table; | ||
30 | spinlock_t *locks; /* Bucket locks for entry manipulation */ | ||
31 | unsigned int locks_mask; | ||
32 | bool hooks_registered; | ||
33 | }; | ||
34 | |||
35 | #define LOCKS_PER_CPU 10 | ||
36 | |||
37 | static int alloc_ila_locks(struct ila_net *ilan) | ||
38 | { | ||
39 | unsigned int i, size; | ||
40 | unsigned int nr_pcpus = num_possible_cpus(); | ||
41 | |||
42 | nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL); | ||
43 | size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU); | ||
44 | |||
45 | if (sizeof(spinlock_t) != 0) { | ||
46 | #ifdef CONFIG_NUMA | ||
47 | if (size * sizeof(spinlock_t) > PAGE_SIZE) | ||
48 | ilan->locks = vmalloc(size * sizeof(spinlock_t)); | ||
49 | else | ||
50 | #endif | ||
51 | ilan->locks = kmalloc_array(size, sizeof(spinlock_t), | ||
52 | GFP_KERNEL); | ||
53 | if (!ilan->locks) | ||
54 | return -ENOMEM; | ||
55 | for (i = 0; i < size; i++) | ||
56 | spin_lock_init(&ilan->locks[i]); | ||
57 | } | ||
58 | ilan->locks_mask = size - 1; | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static u32 hashrnd __read_mostly; | ||
64 | static __always_inline void __ila_hash_secret_init(void) | ||
65 | { | ||
66 | net_get_random_once(&hashrnd, sizeof(hashrnd)); | ||
67 | } | ||
68 | |||
69 | static inline u32 ila_identifier_hash(__be64 identifier) | ||
70 | { | ||
71 | u32 *v = (u32 *)&identifier; | ||
72 | |||
73 | return jhash_2words(v[0], v[1], hashrnd); | ||
74 | } | ||
75 | |||
76 | static inline spinlock_t *ila_get_lock(struct ila_net *ilan, __be64 identifier) | ||
77 | { | ||
78 | return &ilan->locks[ila_identifier_hash(identifier) & ilan->locks_mask]; | ||
79 | } | ||
80 | |||
81 | static inline int ila_cmp_wildcards(struct ila_map *ila, __be64 loc, | ||
82 | int ifindex, unsigned int dir) | ||
83 | { | ||
84 | return (ila->p.ip.locator_match && ila->p.ip.locator_match != loc) || | ||
85 | (ila->p.ifindex && ila->p.ifindex != ifindex) || | ||
86 | !(ila->p.dir & dir); | ||
87 | } | ||
88 | |||
89 | static inline int ila_cmp_params(struct ila_map *ila, struct ila_xlat_params *p) | ||
90 | { | ||
91 | return (ila->p.ip.locator_match != p->ip.locator_match) || | ||
92 | (ila->p.ifindex != p->ifindex) || | ||
93 | (ila->p.dir != p->dir); | ||
94 | } | ||
95 | |||
96 | static int ila_cmpfn(struct rhashtable_compare_arg *arg, | ||
97 | const void *obj) | ||
98 | { | ||
99 | const struct ila_map *ila = obj; | ||
100 | |||
101 | return (ila->p.identifier != *(__be64 *)arg->key); | ||
102 | } | ||
103 | |||
104 | static inline int ila_order(struct ila_map *ila) | ||
105 | { | ||
106 | int score = 0; | ||
107 | |||
108 | if (ila->p.ip.locator_match) | ||
109 | score += 1 << 0; | ||
110 | |||
111 | if (ila->p.ifindex) | ||
112 | score += 1 << 1; | ||
113 | |||
114 | return score; | ||
115 | } | ||
116 | |||
117 | static const struct rhashtable_params rht_params = { | ||
118 | .nelem_hint = 1024, | ||
119 | .head_offset = offsetof(struct ila_map, node), | ||
120 | .key_offset = offsetof(struct ila_map, p.identifier), | ||
121 | .key_len = sizeof(u64), /* identifier */ | ||
122 | .max_size = 1048576, | ||
123 | .min_size = 256, | ||
124 | .automatic_shrinking = true, | ||
125 | .obj_cmpfn = ila_cmpfn, | ||
126 | }; | ||
127 | |||
128 | static struct genl_family ila_nl_family = { | ||
129 | .id = GENL_ID_GENERATE, | ||
130 | .hdrsize = 0, | ||
131 | .name = ILA_GENL_NAME, | ||
132 | .version = ILA_GENL_VERSION, | ||
133 | .maxattr = ILA_ATTR_MAX, | ||
134 | .netnsok = true, | ||
135 | .parallel_ops = true, | ||
136 | }; | ||
137 | |||
138 | static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { | ||
139 | [ILA_ATTR_IDENTIFIER] = { .type = NLA_U64, }, | ||
140 | [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, | ||
141 | [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, }, | ||
142 | [ILA_ATTR_IFINDEX] = { .type = NLA_U32, }, | ||
143 | [ILA_ATTR_DIR] = { .type = NLA_U32, }, | ||
144 | }; | ||
145 | |||
146 | static int parse_nl_config(struct genl_info *info, | ||
147 | struct ila_xlat_params *p) | ||
148 | { | ||
149 | memset(p, 0, sizeof(*p)); | ||
150 | |||
151 | if (info->attrs[ILA_ATTR_IDENTIFIER]) | ||
152 | p->identifier = (__force __be64)nla_get_u64( | ||
153 | info->attrs[ILA_ATTR_IDENTIFIER]); | ||
154 | |||
155 | if (info->attrs[ILA_ATTR_LOCATOR]) | ||
156 | p->ip.locator = (__force __be64)nla_get_u64( | ||
157 | info->attrs[ILA_ATTR_LOCATOR]); | ||
158 | |||
159 | if (info->attrs[ILA_ATTR_LOCATOR_MATCH]) | ||
160 | p->ip.locator_match = (__force __be64)nla_get_u64( | ||
161 | info->attrs[ILA_ATTR_LOCATOR_MATCH]); | ||
162 | |||
163 | if (info->attrs[ILA_ATTR_IFINDEX]) | ||
164 | p->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]); | ||
165 | |||
166 | if (info->attrs[ILA_ATTR_DIR]) | ||
167 | p->dir = nla_get_u32(info->attrs[ILA_ATTR_DIR]); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* Must be called with rcu readlock */ | ||
173 | static inline struct ila_map *ila_lookup_wildcards(__be64 id, __be64 loc, | ||
174 | int ifindex, | ||
175 | unsigned int dir, | ||
176 | struct ila_net *ilan) | ||
177 | { | ||
178 | struct ila_map *ila; | ||
179 | |||
180 | ila = rhashtable_lookup_fast(&ilan->rhash_table, &id, rht_params); | ||
181 | while (ila) { | ||
182 | if (!ila_cmp_wildcards(ila, loc, ifindex, dir)) | ||
183 | return ila; | ||
184 | ila = rcu_access_pointer(ila->next); | ||
185 | } | ||
186 | |||
187 | return NULL; | ||
188 | } | ||
189 | |||
190 | /* Must be called with rcu readlock */ | ||
191 | static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *p, | ||
192 | struct ila_net *ilan) | ||
193 | { | ||
194 | struct ila_map *ila; | ||
195 | |||
196 | ila = rhashtable_lookup_fast(&ilan->rhash_table, &p->identifier, | ||
197 | rht_params); | ||
198 | while (ila) { | ||
199 | if (!ila_cmp_params(ila, p)) | ||
200 | return ila; | ||
201 | ila = rcu_access_pointer(ila->next); | ||
202 | } | ||
203 | |||
204 | return NULL; | ||
205 | } | ||
206 | |||
207 | static inline void ila_release(struct ila_map *ila) | ||
208 | { | ||
209 | kfree_rcu(ila, rcu); | ||
210 | } | ||
211 | |||
212 | static void ila_free_cb(void *ptr, void *arg) | ||
213 | { | ||
214 | struct ila_map *ila = (struct ila_map *)ptr, *next; | ||
215 | |||
216 | /* Assume rcu_readlock held */ | ||
217 | while (ila) { | ||
218 | next = rcu_access_pointer(ila->next); | ||
219 | ila_release(ila); | ||
220 | ila = next; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | static int ila_xlat_addr(struct sk_buff *skb, int dir); | ||
225 | |||
226 | static unsigned int | ||
227 | ila_nf_input(void *priv, | ||
228 | struct sk_buff *skb, | ||
229 | const struct nf_hook_state *state) | ||
230 | { | ||
231 | ila_xlat_addr(skb, ILA_DIR_IN); | ||
232 | return NF_ACCEPT; | ||
233 | } | ||
234 | |||
235 | static struct nf_hook_ops ila_nf_hook_ops[] __read_mostly = { | ||
236 | { | ||
237 | .hook = ila_nf_input, | ||
238 | .pf = NFPROTO_IPV6, | ||
239 | .hooknum = NF_INET_PRE_ROUTING, | ||
240 | .priority = -1, | ||
241 | }, | ||
242 | }; | ||
243 | |||
244 | static int ila_add_mapping(struct net *net, struct ila_xlat_params *p) | ||
245 | { | ||
246 | struct ila_net *ilan = net_generic(net, ila_net_id); | ||
247 | struct ila_map *ila, *head; | ||
248 | spinlock_t *lock = ila_get_lock(ilan, p->identifier); | ||
249 | int err = 0, order; | ||
250 | |||
251 | if (!ilan->hooks_registered) { | ||
252 | /* We defer registering net hooks in the namespace until the | ||
253 | * first mapping is added. | ||
254 | */ | ||
255 | err = nf_register_net_hooks(net, ila_nf_hook_ops, | ||
256 | ARRAY_SIZE(ila_nf_hook_ops)); | ||
257 | if (err) | ||
258 | return err; | ||
259 | |||
260 | ilan->hooks_registered = true; | ||
261 | } | ||
262 | |||
263 | ila = kzalloc(sizeof(*ila), GFP_KERNEL); | ||
264 | if (!ila) | ||
265 | return -ENOMEM; | ||
266 | |||
267 | ila->p = *p; | ||
268 | |||
269 | if (p->ip.locator_match) { | ||
270 | /* Precompute checksum difference for translation since we | ||
271 | * know both the old identifier and the new one. | ||
272 | */ | ||
273 | ila->p.ip.csum_diff = compute_csum_diff8( | ||
274 | (__be32 *)&p->ip.locator_match, | ||
275 | (__be32 *)&p->ip.locator); | ||
276 | } | ||
277 | |||
278 | order = ila_order(ila); | ||
279 | |||
280 | spin_lock(lock); | ||
281 | |||
282 | head = rhashtable_lookup_fast(&ilan->rhash_table, &p->identifier, | ||
283 | rht_params); | ||
284 | if (!head) { | ||
285 | /* New entry for the rhash_table */ | ||
286 | err = rhashtable_lookup_insert_fast(&ilan->rhash_table, | ||
287 | &ila->node, rht_params); | ||
288 | } else { | ||
289 | struct ila_map *tila = head, *prev = NULL; | ||
290 | |||
291 | do { | ||
292 | if (!ila_cmp_params(tila, p)) { | ||
293 | err = -EEXIST; | ||
294 | goto out; | ||
295 | } | ||
296 | |||
297 | if (order > ila_order(tila)) | ||
298 | break; | ||
299 | |||
300 | prev = tila; | ||
301 | tila = rcu_dereference_protected(tila->next, | ||
302 | lockdep_is_held(lock)); | ||
303 | } while (tila); | ||
304 | |||
305 | if (prev) { | ||
306 | /* Insert in sub list of head */ | ||
307 | RCU_INIT_POINTER(ila->next, tila); | ||
308 | rcu_assign_pointer(prev->next, ila); | ||
309 | } else { | ||
310 | /* Make this ila new head */ | ||
311 | RCU_INIT_POINTER(ila->next, head); | ||
312 | err = rhashtable_replace_fast(&ilan->rhash_table, | ||
313 | &head->node, | ||
314 | &ila->node, rht_params); | ||
315 | if (err) | ||
316 | goto out; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | out: | ||
321 | spin_unlock(lock); | ||
322 | |||
323 | if (err) | ||
324 | kfree(ila); | ||
325 | |||
326 | return err; | ||
327 | } | ||
328 | |||
329 | static int ila_del_mapping(struct net *net, struct ila_xlat_params *p) | ||
330 | { | ||
331 | struct ila_net *ilan = net_generic(net, ila_net_id); | ||
332 | struct ila_map *ila, *head, *prev; | ||
333 | spinlock_t *lock = ila_get_lock(ilan, p->identifier); | ||
334 | int err = -ENOENT; | ||
335 | |||
336 | spin_lock(lock); | ||
337 | |||
338 | head = rhashtable_lookup_fast(&ilan->rhash_table, | ||
339 | &p->identifier, rht_params); | ||
340 | ila = head; | ||
341 | |||
342 | prev = NULL; | ||
343 | |||
344 | while (ila) { | ||
345 | if (ila_cmp_params(ila, p)) { | ||
346 | prev = ila; | ||
347 | ila = rcu_dereference_protected(ila->next, | ||
348 | lockdep_is_held(lock)); | ||
349 | continue; | ||
350 | } | ||
351 | |||
352 | err = 0; | ||
353 | |||
354 | if (prev) { | ||
355 | /* Not head, just delete from list */ | ||
356 | rcu_assign_pointer(prev->next, ila->next); | ||
357 | } else { | ||
358 | /* It is the head. If there is something in the | ||
359 | * sublist we need to make a new head. | ||
360 | */ | ||
361 | head = rcu_dereference_protected(ila->next, | ||
362 | lockdep_is_held(lock)); | ||
363 | if (head) { | ||
364 | /* Put first entry in the sublist into the | ||
365 | * table | ||
366 | */ | ||
367 | err = rhashtable_replace_fast( | ||
368 | &ilan->rhash_table, &ila->node, | ||
369 | &head->node, rht_params); | ||
370 | if (err) | ||
371 | goto out; | ||
372 | } else { | ||
373 | /* Entry no longer used */ | ||
374 | err = rhashtable_remove_fast(&ilan->rhash_table, | ||
375 | &ila->node, | ||
376 | rht_params); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | ila_release(ila); | ||
381 | |||
382 | break; | ||
383 | } | ||
384 | |||
385 | out: | ||
386 | spin_unlock(lock); | ||
387 | |||
388 | return err; | ||
389 | } | ||
390 | |||
391 | static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info) | ||
392 | { | ||
393 | struct net *net = genl_info_net(info); | ||
394 | struct ila_xlat_params p; | ||
395 | int err; | ||
396 | |||
397 | err = parse_nl_config(info, &p); | ||
398 | if (err) | ||
399 | return err; | ||
400 | |||
401 | return ila_add_mapping(net, &p); | ||
402 | } | ||
403 | |||
404 | static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) | ||
405 | { | ||
406 | struct net *net = genl_info_net(info); | ||
407 | struct ila_xlat_params p; | ||
408 | int err; | ||
409 | |||
410 | err = parse_nl_config(info, &p); | ||
411 | if (err) | ||
412 | return err; | ||
413 | |||
414 | ila_del_mapping(net, &p); | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg) | ||
420 | { | ||
421 | if (nla_put_u64(msg, ILA_ATTR_IDENTIFIER, | ||
422 | (__force u64)ila->p.identifier) || | ||
423 | nla_put_u64(msg, ILA_ATTR_LOCATOR, | ||
424 | (__force u64)ila->p.ip.locator) || | ||
425 | nla_put_u64(msg, ILA_ATTR_LOCATOR_MATCH, | ||
426 | (__force u64)ila->p.ip.locator_match) || | ||
427 | nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->p.ifindex) || | ||
428 | nla_put_u32(msg, ILA_ATTR_DIR, ila->p.dir)) | ||
429 | return -1; | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int ila_dump_info(struct ila_map *ila, | ||
435 | u32 portid, u32 seq, u32 flags, | ||
436 | struct sk_buff *skb, u8 cmd) | ||
437 | { | ||
438 | void *hdr; | ||
439 | |||
440 | hdr = genlmsg_put(skb, portid, seq, &ila_nl_family, flags, cmd); | ||
441 | if (!hdr) | ||
442 | return -ENOMEM; | ||
443 | |||
444 | if (ila_fill_info(ila, skb) < 0) | ||
445 | goto nla_put_failure; | ||
446 | |||
447 | genlmsg_end(skb, hdr); | ||
448 | return 0; | ||
449 | |||
450 | nla_put_failure: | ||
451 | genlmsg_cancel(skb, hdr); | ||
452 | return -EMSGSIZE; | ||
453 | } | ||
454 | |||
455 | static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info) | ||
456 | { | ||
457 | struct net *net = genl_info_net(info); | ||
458 | struct ila_net *ilan = net_generic(net, ila_net_id); | ||
459 | struct sk_buff *msg; | ||
460 | struct ila_xlat_params p; | ||
461 | struct ila_map *ila; | ||
462 | int ret; | ||
463 | |||
464 | ret = parse_nl_config(info, &p); | ||
465 | if (ret) | ||
466 | return ret; | ||
467 | |||
468 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
469 | if (!msg) | ||
470 | return -ENOMEM; | ||
471 | |||
472 | rcu_read_lock(); | ||
473 | |||
474 | ila = ila_lookup_by_params(&p, ilan); | ||
475 | if (ila) { | ||
476 | ret = ila_dump_info(ila, | ||
477 | info->snd_portid, | ||
478 | info->snd_seq, 0, msg, | ||
479 | info->genlhdr->cmd); | ||
480 | } | ||
481 | |||
482 | rcu_read_unlock(); | ||
483 | |||
484 | if (ret < 0) | ||
485 | goto out_free; | ||
486 | |||
487 | return genlmsg_reply(msg, info); | ||
488 | |||
489 | out_free: | ||
490 | nlmsg_free(msg); | ||
491 | return ret; | ||
492 | } | ||
493 | |||
494 | struct ila_dump_iter { | ||
495 | struct rhashtable_iter rhiter; | ||
496 | }; | ||
497 | |||
498 | static int ila_nl_dump_start(struct netlink_callback *cb) | ||
499 | { | ||
500 | struct net *net = sock_net(cb->skb->sk); | ||
501 | struct ila_net *ilan = net_generic(net, ila_net_id); | ||
502 | struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args; | ||
503 | |||
504 | return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter); | ||
505 | } | ||
506 | |||
507 | static int ila_nl_dump_done(struct netlink_callback *cb) | ||
508 | { | ||
509 | struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args; | ||
510 | |||
511 | rhashtable_walk_exit(&iter->rhiter); | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
517 | { | ||
518 | struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args; | ||
519 | struct rhashtable_iter *rhiter = &iter->rhiter; | ||
520 | struct ila_map *ila; | ||
521 | int ret; | ||
522 | |||
523 | ret = rhashtable_walk_start(rhiter); | ||
524 | if (ret && ret != -EAGAIN) | ||
525 | goto done; | ||
526 | |||
527 | for (;;) { | ||
528 | ila = rhashtable_walk_next(rhiter); | ||
529 | |||
530 | if (IS_ERR(ila)) { | ||
531 | if (PTR_ERR(ila) == -EAGAIN) | ||
532 | continue; | ||
533 | ret = PTR_ERR(ila); | ||
534 | goto done; | ||
535 | } else if (!ila) { | ||
536 | break; | ||
537 | } | ||
538 | |||
539 | while (ila) { | ||
540 | ret = ila_dump_info(ila, NETLINK_CB(cb->skb).portid, | ||
541 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
542 | skb, ILA_CMD_GET); | ||
543 | if (ret) | ||
544 | goto done; | ||
545 | |||
546 | ila = rcu_access_pointer(ila->next); | ||
547 | } | ||
548 | } | ||
549 | |||
550 | ret = skb->len; | ||
551 | |||
552 | done: | ||
553 | rhashtable_walk_stop(rhiter); | ||
554 | return ret; | ||
555 | } | ||
556 | |||
557 | static const struct genl_ops ila_nl_ops[] = { | ||
558 | { | ||
559 | .cmd = ILA_CMD_ADD, | ||
560 | .doit = ila_nl_cmd_add_mapping, | ||
561 | .policy = ila_nl_policy, | ||
562 | .flags = GENL_ADMIN_PERM, | ||
563 | }, | ||
564 | { | ||
565 | .cmd = ILA_CMD_DEL, | ||
566 | .doit = ila_nl_cmd_del_mapping, | ||
567 | .policy = ila_nl_policy, | ||
568 | .flags = GENL_ADMIN_PERM, | ||
569 | }, | ||
570 | { | ||
571 | .cmd = ILA_CMD_GET, | ||
572 | .doit = ila_nl_cmd_get_mapping, | ||
573 | .start = ila_nl_dump_start, | ||
574 | .dumpit = ila_nl_dump, | ||
575 | .done = ila_nl_dump_done, | ||
576 | .policy = ila_nl_policy, | ||
577 | }, | ||
578 | }; | ||
579 | |||
580 | #define ILA_HASH_TABLE_SIZE 1024 | ||
581 | |||
582 | static __net_init int ila_init_net(struct net *net) | ||
583 | { | ||
584 | int err; | ||
585 | struct ila_net *ilan = net_generic(net, ila_net_id); | ||
586 | |||
587 | err = alloc_ila_locks(ilan); | ||
588 | if (err) | ||
589 | return err; | ||
590 | |||
591 | rhashtable_init(&ilan->rhash_table, &rht_params); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static __net_exit void ila_exit_net(struct net *net) | ||
597 | { | ||
598 | struct ila_net *ilan = net_generic(net, ila_net_id); | ||
599 | |||
600 | rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL); | ||
601 | |||
602 | kvfree(ilan->locks); | ||
603 | |||
604 | if (ilan->hooks_registered) | ||
605 | nf_unregister_net_hooks(net, ila_nf_hook_ops, | ||
606 | ARRAY_SIZE(ila_nf_hook_ops)); | ||
607 | } | ||
608 | |||
609 | static struct pernet_operations ila_net_ops = { | ||
610 | .init = ila_init_net, | ||
611 | .exit = ila_exit_net, | ||
612 | .id = &ila_net_id, | ||
613 | .size = sizeof(struct ila_net), | ||
614 | }; | ||
615 | |||
616 | static int ila_xlat_addr(struct sk_buff *skb, int dir) | ||
617 | { | ||
618 | struct ila_map *ila; | ||
619 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
620 | struct net *net = dev_net(skb->dev); | ||
621 | struct ila_net *ilan = net_generic(net, ila_net_id); | ||
622 | __be64 identifier, locator_match; | ||
623 | size_t nhoff; | ||
624 | |||
625 | /* Assumes skb contains a valid IPv6 header that is pulled */ | ||
626 | |||
627 | identifier = *(__be64 *)&ip6h->daddr.in6_u.u6_addr8[8]; | ||
628 | locator_match = *(__be64 *)&ip6h->daddr.in6_u.u6_addr8[0]; | ||
629 | nhoff = sizeof(struct ipv6hdr); | ||
630 | |||
631 | rcu_read_lock(); | ||
632 | |||
633 | ila = ila_lookup_wildcards(identifier, locator_match, | ||
634 | skb->dev->ifindex, dir, ilan); | ||
635 | if (ila) | ||
636 | update_ipv6_locator(skb, &ila->p.ip); | ||
637 | |||
638 | rcu_read_unlock(); | ||
639 | |||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | int ila_xlat_incoming(struct sk_buff *skb) | ||
644 | { | ||
645 | return ila_xlat_addr(skb, ILA_DIR_IN); | ||
646 | } | ||
647 | EXPORT_SYMBOL(ila_xlat_incoming); | ||
648 | |||
649 | int ila_xlat_outgoing(struct sk_buff *skb) | ||
650 | { | ||
651 | return ila_xlat_addr(skb, ILA_DIR_OUT); | ||
652 | } | ||
653 | EXPORT_SYMBOL(ila_xlat_outgoing); | ||
654 | |||
655 | int ila_xlat_init(void) | ||
656 | { | ||
657 | int ret; | ||
658 | |||
659 | ret = register_pernet_device(&ila_net_ops); | ||
660 | if (ret) | ||
661 | goto exit; | ||
662 | |||
663 | ret = genl_register_family_with_ops(&ila_nl_family, | ||
664 | ila_nl_ops); | ||
665 | if (ret < 0) | ||
666 | goto unregister; | ||
667 | |||
668 | return 0; | ||
669 | |||
670 | unregister: | ||
671 | unregister_pernet_device(&ila_net_ops); | ||
672 | exit: | ||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | void ila_xlat_fini(void) | ||
677 | { | ||
678 | genl_unregister_family(&ila_nl_family); | ||
679 | unregister_pernet_device(&ila_net_ops); | ||
680 | } | ||
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 5d1c7cee2cb2..36c3f0155010 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -51,12 +51,12 @@ int inet6_csk_bind_conflict(const struct sock *sk, | |||
51 | (sk2->sk_state != TCP_TIME_WAIT && | 51 | (sk2->sk_state != TCP_TIME_WAIT && |
52 | !uid_eq(uid, | 52 | !uid_eq(uid, |
53 | sock_i_uid((struct sock *)sk2))))) { | 53 | sock_i_uid((struct sock *)sk2))))) { |
54 | if (ipv6_rcv_saddr_equal(sk, sk2)) | 54 | if (ipv6_rcv_saddr_equal(sk, sk2, true)) |
55 | break; | 55 | break; |
56 | } | 56 | } |
57 | if (!relax && reuse && sk2->sk_reuse && | 57 | if (!relax && reuse && sk2->sk_reuse && |
58 | sk2->sk_state != TCP_LISTEN && | 58 | sk2->sk_state != TCP_LISTEN && |
59 | ipv6_rcv_saddr_equal(sk, sk2)) | 59 | ipv6_rcv_saddr_equal(sk, sk2, true)) |
60 | break; | 60 | break; |
61 | } | 61 | } |
62 | } | 62 | } |
@@ -78,7 +78,9 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk, | |||
78 | memset(fl6, 0, sizeof(*fl6)); | 78 | memset(fl6, 0, sizeof(*fl6)); |
79 | fl6->flowi6_proto = proto; | 79 | fl6->flowi6_proto = proto; |
80 | fl6->daddr = ireq->ir_v6_rmt_addr; | 80 | fl6->daddr = ireq->ir_v6_rmt_addr; |
81 | final_p = fl6_update_dst(fl6, np->opt, &final); | 81 | rcu_read_lock(); |
82 | final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); | ||
83 | rcu_read_unlock(); | ||
82 | fl6->saddr = ireq->ir_v6_loc_addr; | 84 | fl6->saddr = ireq->ir_v6_loc_addr; |
83 | fl6->flowi6_oif = ireq->ir_iif; | 85 | fl6->flowi6_oif = ireq->ir_iif; |
84 | fl6->flowi6_mark = ireq->ir_mark; | 86 | fl6->flowi6_mark = ireq->ir_mark; |
@@ -109,14 +111,6 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr) | |||
109 | EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); | 111 | EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); |
110 | 112 | ||
111 | static inline | 113 | static inline |
112 | void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, | ||
113 | const struct in6_addr *daddr, | ||
114 | const struct in6_addr *saddr) | ||
115 | { | ||
116 | __ip6_dst_store(sk, dst, daddr, saddr); | ||
117 | } | ||
118 | |||
119 | static inline | ||
120 | struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | 114 | struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) |
121 | { | 115 | { |
122 | return __sk_dst_check(sk, cookie); | 116 | return __sk_dst_check(sk, cookie); |
@@ -142,14 +136,16 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk, | |||
142 | fl6->fl6_dport = inet->inet_dport; | 136 | fl6->fl6_dport = inet->inet_dport; |
143 | security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); | 137 | security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); |
144 | 138 | ||
145 | final_p = fl6_update_dst(fl6, np->opt, &final); | 139 | rcu_read_lock(); |
140 | final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); | ||
141 | rcu_read_unlock(); | ||
146 | 142 | ||
147 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 143 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
148 | if (!dst) { | 144 | if (!dst) { |
149 | dst = ip6_dst_lookup_flow(sk, fl6, final_p); | 145 | dst = ip6_dst_lookup_flow(sk, fl6, final_p); |
150 | 146 | ||
151 | if (!IS_ERR(dst)) | 147 | if (!IS_ERR(dst)) |
152 | __inet6_csk_dst_store(sk, dst, NULL, NULL); | 148 | ip6_dst_store(sk, dst, NULL, NULL); |
153 | } | 149 | } |
154 | return dst; | 150 | return dst; |
155 | } | 151 | } |
@@ -175,7 +171,8 @@ int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused | |||
175 | /* Restore final destination back after routing done */ | 171 | /* Restore final destination back after routing done */ |
176 | fl6.daddr = sk->sk_v6_daddr; | 172 | fl6.daddr = sk->sk_v6_daddr; |
177 | 173 | ||
178 | res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); | 174 | res = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), |
175 | np->tclass); | ||
179 | rcu_read_unlock(); | 176 | rcu_read_unlock(); |
180 | return res; | 177 | return res; |
181 | } | 178 | } |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 3c7b9310b33f..f37f18b6b40c 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/tcp.h> | 24 | #include <linux/tcp.h> |
25 | #include <linux/udp.h> | 25 | #include <linux/udp.h> |
26 | #include <linux/if_arp.h> | 26 | #include <linux/if_arp.h> |
27 | #include <linux/mroute.h> | ||
28 | #include <linux/init.h> | 27 | #include <linux/init.h> |
29 | #include <linux/in6.h> | 28 | #include <linux/in6.h> |
30 | #include <linux/inetdevice.h> | 29 | #include <linux/inetdevice.h> |
@@ -1571,13 +1570,11 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], | |||
1571 | return -EEXIST; | 1570 | return -EEXIST; |
1572 | } else { | 1571 | } else { |
1573 | t = nt; | 1572 | t = nt; |
1574 | |||
1575 | ip6gre_tunnel_unlink(ign, t); | ||
1576 | ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); | ||
1577 | ip6gre_tunnel_link(ign, t); | ||
1578 | netdev_state_change(dev); | ||
1579 | } | 1573 | } |
1580 | 1574 | ||
1575 | ip6gre_tunnel_unlink(ign, t); | ||
1576 | ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); | ||
1577 | ip6gre_tunnel_link(ign, t); | ||
1581 | return 0; | 1578 | return 0; |
1582 | } | 1579 | } |
1583 | 1580 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index e6a7bd15b9b7..23de98f976d5 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1322,7 +1322,7 @@ emsgsize: | |||
1322 | headersize == sizeof(struct ipv6hdr) && | 1322 | headersize == sizeof(struct ipv6hdr) && |
1323 | length < mtu - headersize && | 1323 | length < mtu - headersize && |
1324 | !(flags & MSG_MORE) && | 1324 | !(flags & MSG_MORE) && |
1325 | rt->dst.dev->features & NETIF_F_V6_CSUM) | 1325 | rt->dst.dev->features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) |
1326 | csummode = CHECKSUM_PARTIAL; | 1326 | csummode = CHECKSUM_PARTIAL; |
1327 | 1327 | ||
1328 | if (sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) { | 1328 | if (sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) { |
@@ -1353,7 +1353,7 @@ emsgsize: | |||
1353 | (skb && skb_is_gso(skb))) && | 1353 | (skb && skb_is_gso(skb))) && |
1354 | (sk->sk_protocol == IPPROTO_UDP) && | 1354 | (sk->sk_protocol == IPPROTO_UDP) && |
1355 | (rt->dst.dev->features & NETIF_F_UFO) && | 1355 | (rt->dst.dev->features & NETIF_F_UFO) && |
1356 | (sk->sk_type == SOCK_DGRAM)) { | 1356 | (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) { |
1357 | err = ip6_ufo_append_data(sk, queue, getfrag, from, length, | 1357 | err = ip6_ufo_append_data(sk, queue, getfrag, from, length, |
1358 | hh_len, fragheaderlen, | 1358 | hh_len, fragheaderlen, |
1359 | transhdrlen, mtu, flags, fl6); | 1359 | transhdrlen, mtu, flags, fl6); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index eabffbb89795..137fca42aaa6 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -177,7 +177,7 @@ void ip6_tnl_dst_reset(struct ip6_tnl *t) | |||
177 | int i; | 177 | int i; |
178 | 178 | ||
179 | for_each_possible_cpu(i) | 179 | for_each_possible_cpu(i) |
180 | ip6_tnl_per_cpu_dst_set(raw_cpu_ptr(t->dst_cache), NULL); | 180 | ip6_tnl_per_cpu_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); |
181 | } | 181 | } |
182 | EXPORT_SYMBOL_GPL(ip6_tnl_dst_reset); | 182 | EXPORT_SYMBOL_GPL(ip6_tnl_dst_reset); |
183 | 183 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index ad19136086dd..a10e77103c88 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -118,7 +118,7 @@ static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc, | |||
118 | int cmd); | 118 | int cmd); |
119 | static int ip6mr_rtm_dumproute(struct sk_buff *skb, | 119 | static int ip6mr_rtm_dumproute(struct sk_buff *skb, |
120 | struct netlink_callback *cb); | 120 | struct netlink_callback *cb); |
121 | static void mroute_clean_tables(struct mr6_table *mrt); | 121 | static void mroute_clean_tables(struct mr6_table *mrt, bool all); |
122 | static void ipmr_expire_process(unsigned long arg); | 122 | static void ipmr_expire_process(unsigned long arg); |
123 | 123 | ||
124 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | 124 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES |
@@ -334,7 +334,7 @@ static struct mr6_table *ip6mr_new_table(struct net *net, u32 id) | |||
334 | static void ip6mr_free_table(struct mr6_table *mrt) | 334 | static void ip6mr_free_table(struct mr6_table *mrt) |
335 | { | 335 | { |
336 | del_timer_sync(&mrt->ipmr_expire_timer); | 336 | del_timer_sync(&mrt->ipmr_expire_timer); |
337 | mroute_clean_tables(mrt); | 337 | mroute_clean_tables(mrt, true); |
338 | kfree(mrt); | 338 | kfree(mrt); |
339 | } | 339 | } |
340 | 340 | ||
@@ -765,10 +765,6 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt) | |||
765 | return dev; | 765 | return dev; |
766 | 766 | ||
767 | failure: | 767 | failure: |
768 | /* allow the register to be completed before unregistering. */ | ||
769 | rtnl_unlock(); | ||
770 | rtnl_lock(); | ||
771 | |||
772 | unregister_netdevice(dev); | 768 | unregister_netdevice(dev); |
773 | return NULL; | 769 | return NULL; |
774 | } | 770 | } |
@@ -1542,7 +1538,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt, | |||
1542 | * Close the multicast socket, and clear the vif tables etc | 1538 | * Close the multicast socket, and clear the vif tables etc |
1543 | */ | 1539 | */ |
1544 | 1540 | ||
1545 | static void mroute_clean_tables(struct mr6_table *mrt) | 1541 | static void mroute_clean_tables(struct mr6_table *mrt, bool all) |
1546 | { | 1542 | { |
1547 | int i; | 1543 | int i; |
1548 | LIST_HEAD(list); | 1544 | LIST_HEAD(list); |
@@ -1552,8 +1548,9 @@ static void mroute_clean_tables(struct mr6_table *mrt) | |||
1552 | * Shut down all active vif entries | 1548 | * Shut down all active vif entries |
1553 | */ | 1549 | */ |
1554 | for (i = 0; i < mrt->maxvif; i++) { | 1550 | for (i = 0; i < mrt->maxvif; i++) { |
1555 | if (!(mrt->vif6_table[i].flags & VIFF_STATIC)) | 1551 | if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC)) |
1556 | mif6_delete(mrt, i, &list); | 1552 | continue; |
1553 | mif6_delete(mrt, i, &list); | ||
1557 | } | 1554 | } |
1558 | unregister_netdevice_many(&list); | 1555 | unregister_netdevice_many(&list); |
1559 | 1556 | ||
@@ -1562,7 +1559,7 @@ static void mroute_clean_tables(struct mr6_table *mrt) | |||
1562 | */ | 1559 | */ |
1563 | for (i = 0; i < MFC6_LINES; i++) { | 1560 | for (i = 0; i < MFC6_LINES; i++) { |
1564 | list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) { | 1561 | list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) { |
1565 | if (c->mfc_flags & MFC_STATIC) | 1562 | if (!all && (c->mfc_flags & MFC_STATIC)) |
1566 | continue; | 1563 | continue; |
1567 | write_lock_bh(&mrt_lock); | 1564 | write_lock_bh(&mrt_lock); |
1568 | list_del(&c->list); | 1565 | list_del(&c->list); |
@@ -1625,7 +1622,7 @@ int ip6mr_sk_done(struct sock *sk) | |||
1625 | net->ipv6.devconf_all); | 1622 | net->ipv6.devconf_all); |
1626 | write_unlock_bh(&mrt_lock); | 1623 | write_unlock_bh(&mrt_lock); |
1627 | 1624 | ||
1628 | mroute_clean_tables(mrt); | 1625 | mroute_clean_tables(mrt, false); |
1629 | err = 0; | 1626 | err = 0; |
1630 | break; | 1627 | break; |
1631 | } | 1628 | } |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 63e6956917c9..4449ad1f8114 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -111,7 +111,8 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk, | |||
111 | icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); | 111 | icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); |
112 | } | 112 | } |
113 | } | 113 | } |
114 | opt = xchg(&inet6_sk(sk)->opt, opt); | 114 | opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt, |
115 | opt); | ||
115 | sk_dst_reset(sk); | 116 | sk_dst_reset(sk); |
116 | 117 | ||
117 | return opt; | 118 | return opt; |
@@ -231,9 +232,12 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
231 | sk->sk_socket->ops = &inet_dgram_ops; | 232 | sk->sk_socket->ops = &inet_dgram_ops; |
232 | sk->sk_family = PF_INET; | 233 | sk->sk_family = PF_INET; |
233 | } | 234 | } |
234 | opt = xchg(&np->opt, NULL); | 235 | opt = xchg((__force struct ipv6_txoptions **)&np->opt, |
235 | if (opt) | 236 | NULL); |
236 | sock_kfree_s(sk, opt, opt->tot_len); | 237 | if (opt) { |
238 | atomic_sub(opt->tot_len, &sk->sk_omem_alloc); | ||
239 | txopt_put(opt); | ||
240 | } | ||
237 | pktopt = xchg(&np->pktoptions, NULL); | 241 | pktopt = xchg(&np->pktoptions, NULL); |
238 | kfree_skb(pktopt); | 242 | kfree_skb(pktopt); |
239 | 243 | ||
@@ -403,7 +407,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
403 | if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW)) | 407 | if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW)) |
404 | break; | 408 | break; |
405 | 409 | ||
406 | opt = ipv6_renew_options(sk, np->opt, optname, | 410 | opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); |
411 | opt = ipv6_renew_options(sk, opt, optname, | ||
407 | (struct ipv6_opt_hdr __user *)optval, | 412 | (struct ipv6_opt_hdr __user *)optval, |
408 | optlen); | 413 | optlen); |
409 | if (IS_ERR(opt)) { | 414 | if (IS_ERR(opt)) { |
@@ -432,8 +437,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
432 | retv = 0; | 437 | retv = 0; |
433 | opt = ipv6_update_options(sk, opt); | 438 | opt = ipv6_update_options(sk, opt); |
434 | sticky_done: | 439 | sticky_done: |
435 | if (opt) | 440 | if (opt) { |
436 | sock_kfree_s(sk, opt, opt->tot_len); | 441 | atomic_sub(opt->tot_len, &sk->sk_omem_alloc); |
442 | txopt_put(opt); | ||
443 | } | ||
437 | break; | 444 | break; |
438 | } | 445 | } |
439 | 446 | ||
@@ -486,6 +493,7 @@ sticky_done: | |||
486 | break; | 493 | break; |
487 | 494 | ||
488 | memset(opt, 0, sizeof(*opt)); | 495 | memset(opt, 0, sizeof(*opt)); |
496 | atomic_set(&opt->refcnt, 1); | ||
489 | opt->tot_len = sizeof(*opt) + optlen; | 497 | opt->tot_len = sizeof(*opt) + optlen; |
490 | retv = -EFAULT; | 498 | retv = -EFAULT; |
491 | if (copy_from_user(opt+1, optval, optlen)) | 499 | if (copy_from_user(opt+1, optval, optlen)) |
@@ -502,8 +510,10 @@ update: | |||
502 | retv = 0; | 510 | retv = 0; |
503 | opt = ipv6_update_options(sk, opt); | 511 | opt = ipv6_update_options(sk, opt); |
504 | done: | 512 | done: |
505 | if (opt) | 513 | if (opt) { |
506 | sock_kfree_s(sk, opt, opt->tot_len); | 514 | atomic_sub(opt->tot_len, &sk->sk_omem_alloc); |
515 | txopt_put(opt); | ||
516 | } | ||
507 | break; | 517 | break; |
508 | } | 518 | } |
509 | case IPV6_UNICAST_HOPS: | 519 | case IPV6_UNICAST_HOPS: |
@@ -1110,10 +1120,11 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1110 | case IPV6_RTHDR: | 1120 | case IPV6_RTHDR: |
1111 | case IPV6_DSTOPTS: | 1121 | case IPV6_DSTOPTS: |
1112 | { | 1122 | { |
1123 | struct ipv6_txoptions *opt; | ||
1113 | 1124 | ||
1114 | lock_sock(sk); | 1125 | lock_sock(sk); |
1115 | len = ipv6_getsockopt_sticky(sk, np->opt, | 1126 | opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); |
1116 | optname, optval, len); | 1127 | len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len); |
1117 | release_sock(sk); | 1128 | release_sock(sk); |
1118 | /* check if ipv6_getsockopt_sticky() returns err code */ | 1129 | /* check if ipv6_getsockopt_sticky() returns err code */ |
1119 | if (len < 0) | 1130 | if (len < 0) |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3e0f855e1bea..84afb9a77278 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -556,8 +556,7 @@ static void ndisc_send_unsol_na(struct net_device *dev) | |||
556 | } | 556 | } |
557 | 557 | ||
558 | void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit, | 558 | void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit, |
559 | const struct in6_addr *daddr, const struct in6_addr *saddr, | 559 | const struct in6_addr *daddr, const struct in6_addr *saddr) |
560 | struct sk_buff *oskb) | ||
561 | { | 560 | { |
562 | struct sk_buff *skb; | 561 | struct sk_buff *skb; |
563 | struct in6_addr addr_buf; | 562 | struct in6_addr addr_buf; |
@@ -593,9 +592,6 @@ void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit, | |||
593 | ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR, | 592 | ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR, |
594 | dev->dev_addr); | 593 | dev->dev_addr); |
595 | 594 | ||
596 | if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE) && oskb) | ||
597 | skb_dst_copy(skb, oskb); | ||
598 | |||
599 | ndisc_send_skb(skb, daddr, saddr); | 595 | ndisc_send_skb(skb, daddr, saddr); |
600 | } | 596 | } |
601 | 597 | ||
@@ -682,12 +678,12 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
682 | "%s: trying to ucast probe in NUD_INVALID: %pI6\n", | 678 | "%s: trying to ucast probe in NUD_INVALID: %pI6\n", |
683 | __func__, target); | 679 | __func__, target); |
684 | } | 680 | } |
685 | ndisc_send_ns(dev, target, target, saddr, skb); | 681 | ndisc_send_ns(dev, target, target, saddr); |
686 | } else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) { | 682 | } else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) { |
687 | neigh_app_ns(neigh); | 683 | neigh_app_ns(neigh); |
688 | } else { | 684 | } else { |
689 | addrconf_addr_solict_mult(target, &mcaddr); | 685 | addrconf_addr_solict_mult(target, &mcaddr); |
690 | ndisc_send_ns(dev, target, &mcaddr, saddr, skb); | 686 | ndisc_send_ns(dev, target, &mcaddr, saddr); |
691 | } | 687 | } |
692 | } | 688 | } |
693 | 689 | ||
@@ -1187,7 +1183,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1187 | */ | 1183 | */ |
1188 | if (!in6_dev->cnf.accept_ra_from_local && | 1184 | if (!in6_dev->cnf.accept_ra_from_local && |
1189 | ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, | 1185 | ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, |
1190 | NULL, 0)) { | 1186 | in6_dev->dev, 0)) { |
1191 | ND_PRINTK(2, info, | 1187 | ND_PRINTK(2, info, |
1192 | "RA from local address detected on dev: %s: default router ignored\n", | 1188 | "RA from local address detected on dev: %s: default router ignored\n", |
1193 | skb->dev->name); | 1189 | skb->dev->name); |
@@ -1341,7 +1337,7 @@ skip_linkparms: | |||
1341 | #ifdef CONFIG_IPV6_ROUTE_INFO | 1337 | #ifdef CONFIG_IPV6_ROUTE_INFO |
1342 | if (!in6_dev->cnf.accept_ra_from_local && | 1338 | if (!in6_dev->cnf.accept_ra_from_local && |
1343 | ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, | 1339 | ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, |
1344 | NULL, 0)) { | 1340 | in6_dev->dev, 0)) { |
1345 | ND_PRINTK(2, info, | 1341 | ND_PRINTK(2, info, |
1346 | "RA from local address detected on dev: %s: router info ignored.\n", | 1342 | "RA from local address detected on dev: %s: router info ignored.\n", |
1347 | skb->dev->name); | 1343 | skb->dev->name); |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index f6a024e141e5..e10a04c9cdc7 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -49,6 +49,7 @@ config NFT_REJECT_IPV6 | |||
49 | 49 | ||
50 | config NFT_DUP_IPV6 | 50 | config NFT_DUP_IPV6 |
51 | tristate "IPv6 nf_tables packet duplication support" | 51 | tristate "IPv6 nf_tables packet duplication support" |
52 | depends on !NF_CONNTRACK || NF_CONNTRACK | ||
52 | select NF_DUP_IPV6 | 53 | select NF_DUP_IPV6 |
53 | help | 54 | help |
54 | This module enables IPv6 packet duplication support for nf_tables. | 55 | This module enables IPv6 packet duplication support for nf_tables. |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index d5efeb87350e..e4347aeb2e65 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -56,7 +56,6 @@ struct nf_ct_frag6_skb_cb | |||
56 | { | 56 | { |
57 | struct inet6_skb_parm h; | 57 | struct inet6_skb_parm h; |
58 | int offset; | 58 | int offset; |
59 | struct sk_buff *orig; | ||
60 | }; | 59 | }; |
61 | 60 | ||
62 | #define NFCT_FRAG6_CB(skb) ((struct nf_ct_frag6_skb_cb *)((skb)->cb)) | 61 | #define NFCT_FRAG6_CB(skb) ((struct nf_ct_frag6_skb_cb *)((skb)->cb)) |
@@ -170,12 +169,6 @@ static unsigned int nf_hashfn(const struct inet_frag_queue *q) | |||
170 | return nf_hash_frag(nq->id, &nq->saddr, &nq->daddr); | 169 | return nf_hash_frag(nq->id, &nq->saddr, &nq->daddr); |
171 | } | 170 | } |
172 | 171 | ||
173 | static void nf_skb_free(struct sk_buff *skb) | ||
174 | { | ||
175 | if (NFCT_FRAG6_CB(skb)->orig) | ||
176 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); | ||
177 | } | ||
178 | |||
179 | static void nf_ct_frag6_expire(unsigned long data) | 172 | static void nf_ct_frag6_expire(unsigned long data) |
180 | { | 173 | { |
181 | struct frag_queue *fq; | 174 | struct frag_queue *fq; |
@@ -190,7 +183,7 @@ static void nf_ct_frag6_expire(unsigned long data) | |||
190 | /* Creation primitives. */ | 183 | /* Creation primitives. */ |
191 | static inline struct frag_queue *fq_find(struct net *net, __be32 id, | 184 | static inline struct frag_queue *fq_find(struct net *net, __be32 id, |
192 | u32 user, struct in6_addr *src, | 185 | u32 user, struct in6_addr *src, |
193 | struct in6_addr *dst, u8 ecn) | 186 | struct in6_addr *dst, int iif, u8 ecn) |
194 | { | 187 | { |
195 | struct inet_frag_queue *q; | 188 | struct inet_frag_queue *q; |
196 | struct ip6_create_arg arg; | 189 | struct ip6_create_arg arg; |
@@ -200,6 +193,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id, | |||
200 | arg.user = user; | 193 | arg.user = user; |
201 | arg.src = src; | 194 | arg.src = src; |
202 | arg.dst = dst; | 195 | arg.dst = dst; |
196 | arg.iif = iif; | ||
203 | arg.ecn = ecn; | 197 | arg.ecn = ecn; |
204 | 198 | ||
205 | local_bh_disable(); | 199 | local_bh_disable(); |
@@ -368,17 +362,18 @@ err: | |||
368 | 362 | ||
369 | /* | 363 | /* |
370 | * Check if this packet is complete. | 364 | * Check if this packet is complete. |
371 | * Returns NULL on failure by any reason, and pointer | ||
372 | * to current nexthdr field in reassembled frame. | ||
373 | * | 365 | * |
374 | * It is called with locked fq, and caller must check that | 366 | * It is called with locked fq, and caller must check that |
375 | * queue is eligible for reassembly i.e. it is not COMPLETE, | 367 | * queue is eligible for reassembly i.e. it is not COMPLETE, |
376 | * the last and the first frames arrived and all the bits are here. | 368 | * the last and the first frames arrived and all the bits are here. |
369 | * | ||
370 | * returns true if *prev skb has been transformed into the reassembled | ||
371 | * skb, false otherwise. | ||
377 | */ | 372 | */ |
378 | static struct sk_buff * | 373 | static bool |
379 | nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | 374 | nf_ct_frag6_reasm(struct frag_queue *fq, struct sk_buff *prev, struct net_device *dev) |
380 | { | 375 | { |
381 | struct sk_buff *fp, *op, *head = fq->q.fragments; | 376 | struct sk_buff *fp, *head = fq->q.fragments; |
382 | int payload_len; | 377 | int payload_len; |
383 | u8 ecn; | 378 | u8 ecn; |
384 | 379 | ||
@@ -389,22 +384,21 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | |||
389 | 384 | ||
390 | ecn = ip_frag_ecn_table[fq->ecn]; | 385 | ecn = ip_frag_ecn_table[fq->ecn]; |
391 | if (unlikely(ecn == 0xff)) | 386 | if (unlikely(ecn == 0xff)) |
392 | goto out_fail; | 387 | return false; |
393 | 388 | ||
394 | /* Unfragmented part is taken from the first segment. */ | 389 | /* Unfragmented part is taken from the first segment. */ |
395 | payload_len = ((head->data - skb_network_header(head)) - | 390 | payload_len = ((head->data - skb_network_header(head)) - |
396 | sizeof(struct ipv6hdr) + fq->q.len - | 391 | sizeof(struct ipv6hdr) + fq->q.len - |
397 | sizeof(struct frag_hdr)); | 392 | sizeof(struct frag_hdr)); |
398 | if (payload_len > IPV6_MAXPLEN) { | 393 | if (payload_len > IPV6_MAXPLEN) { |
399 | pr_debug("payload len is too large.\n"); | 394 | net_dbg_ratelimited("nf_ct_frag6_reasm: payload len = %d\n", |
400 | goto out_oversize; | 395 | payload_len); |
396 | return false; | ||
401 | } | 397 | } |
402 | 398 | ||
403 | /* Head of list must not be cloned. */ | 399 | /* Head of list must not be cloned. */ |
404 | if (skb_unclone(head, GFP_ATOMIC)) { | 400 | if (skb_unclone(head, GFP_ATOMIC)) |
405 | pr_debug("skb is cloned but can't expand head"); | 401 | return false; |
406 | goto out_oom; | ||
407 | } | ||
408 | 402 | ||
409 | /* If the first fragment is fragmented itself, we split | 403 | /* If the first fragment is fragmented itself, we split |
410 | * it to two chunks: the first with data and paged part | 404 | * it to two chunks: the first with data and paged part |
@@ -415,7 +409,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | |||
415 | 409 | ||
416 | clone = alloc_skb(0, GFP_ATOMIC); | 410 | clone = alloc_skb(0, GFP_ATOMIC); |
417 | if (clone == NULL) | 411 | if (clone == NULL) |
418 | goto out_oom; | 412 | return false; |
419 | 413 | ||
420 | clone->next = head->next; | 414 | clone->next = head->next; |
421 | head->next = clone; | 415 | head->next = clone; |
@@ -429,10 +423,41 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | |||
429 | clone->csum = 0; | 423 | clone->csum = 0; |
430 | clone->ip_summed = head->ip_summed; | 424 | clone->ip_summed = head->ip_summed; |
431 | 425 | ||
432 | NFCT_FRAG6_CB(clone)->orig = NULL; | ||
433 | add_frag_mem_limit(fq->q.net, clone->truesize); | 426 | add_frag_mem_limit(fq->q.net, clone->truesize); |
434 | } | 427 | } |
435 | 428 | ||
429 | /* morph head into last received skb: prev. | ||
430 | * | ||
431 | * This allows callers of ipv6 conntrack defrag to continue | ||
432 | * to use the last skb(frag) passed into the reasm engine. | ||
433 | * The last skb frag 'silently' turns into the full reassembled skb. | ||
434 | * | ||
435 | * Since prev is also part of q->fragments we have to clone it first. | ||
436 | */ | ||
437 | if (head != prev) { | ||
438 | struct sk_buff *iter; | ||
439 | |||
440 | fp = skb_clone(prev, GFP_ATOMIC); | ||
441 | if (!fp) | ||
442 | return false; | ||
443 | |||
444 | fp->next = prev->next; | ||
445 | |||
446 | iter = head; | ||
447 | while (iter) { | ||
448 | if (iter->next == prev) { | ||
449 | iter->next = fp; | ||
450 | break; | ||
451 | } | ||
452 | iter = iter->next; | ||
453 | } | ||
454 | |||
455 | skb_morph(prev, head); | ||
456 | prev->next = head->next; | ||
457 | consume_skb(head); | ||
458 | head = prev; | ||
459 | } | ||
460 | |||
436 | /* We have to remove fragment header from datagram and to relocate | 461 | /* We have to remove fragment header from datagram and to relocate |
437 | * header in order to calculate ICV correctly. */ | 462 | * header in order to calculate ICV correctly. */ |
438 | skb_network_header(head)[fq->nhoffset] = skb_transport_header(head)[0]; | 463 | skb_network_header(head)[fq->nhoffset] = skb_transport_header(head)[0]; |
@@ -473,31 +498,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | |||
473 | fq->q.fragments = NULL; | 498 | fq->q.fragments = NULL; |
474 | fq->q.fragments_tail = NULL; | 499 | fq->q.fragments_tail = NULL; |
475 | 500 | ||
476 | /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ | 501 | return true; |
477 | fp = skb_shinfo(head)->frag_list; | ||
478 | if (fp && NFCT_FRAG6_CB(fp)->orig == NULL) | ||
479 | /* at above code, head skb is divided into two skbs. */ | ||
480 | fp = fp->next; | ||
481 | |||
482 | op = NFCT_FRAG6_CB(head)->orig; | ||
483 | for (; fp; fp = fp->next) { | ||
484 | struct sk_buff *orig = NFCT_FRAG6_CB(fp)->orig; | ||
485 | |||
486 | op->next = orig; | ||
487 | op = orig; | ||
488 | NFCT_FRAG6_CB(fp)->orig = NULL; | ||
489 | } | ||
490 | |||
491 | return head; | ||
492 | |||
493 | out_oversize: | ||
494 | net_dbg_ratelimited("nf_ct_frag6_reasm: payload len = %d\n", | ||
495 | payload_len); | ||
496 | goto out_fail; | ||
497 | out_oom: | ||
498 | net_dbg_ratelimited("nf_ct_frag6_reasm: no memory for reassembly\n"); | ||
499 | out_fail: | ||
500 | return NULL; | ||
501 | } | 502 | } |
502 | 503 | ||
503 | /* | 504 | /* |
@@ -563,89 +564,61 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) | |||
563 | return 0; | 564 | return 0; |
564 | } | 565 | } |
565 | 566 | ||
566 | struct sk_buff *nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) | 567 | int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) |
567 | { | 568 | { |
568 | struct sk_buff *clone; | ||
569 | struct net_device *dev = skb->dev; | 569 | struct net_device *dev = skb->dev; |
570 | int fhoff, nhoff, ret; | ||
570 | struct frag_hdr *fhdr; | 571 | struct frag_hdr *fhdr; |
571 | struct frag_queue *fq; | 572 | struct frag_queue *fq; |
572 | struct ipv6hdr *hdr; | 573 | struct ipv6hdr *hdr; |
573 | int fhoff, nhoff; | ||
574 | u8 prevhdr; | 574 | u8 prevhdr; |
575 | struct sk_buff *ret_skb = NULL; | ||
576 | 575 | ||
577 | /* Jumbo payload inhibits frag. header */ | 576 | /* Jumbo payload inhibits frag. header */ |
578 | if (ipv6_hdr(skb)->payload_len == 0) { | 577 | if (ipv6_hdr(skb)->payload_len == 0) { |
579 | pr_debug("payload len = 0\n"); | 578 | pr_debug("payload len = 0\n"); |
580 | return skb; | 579 | return -EINVAL; |
581 | } | 580 | } |
582 | 581 | ||
583 | if (find_prev_fhdr(skb, &prevhdr, &nhoff, &fhoff) < 0) | 582 | if (find_prev_fhdr(skb, &prevhdr, &nhoff, &fhoff) < 0) |
584 | return skb; | 583 | return -EINVAL; |
585 | 584 | ||
586 | clone = skb_clone(skb, GFP_ATOMIC); | 585 | if (!pskb_may_pull(skb, fhoff + sizeof(*fhdr))) |
587 | if (clone == NULL) { | 586 | return -ENOMEM; |
588 | pr_debug("Can't clone skb\n"); | ||
589 | return skb; | ||
590 | } | ||
591 | 587 | ||
592 | NFCT_FRAG6_CB(clone)->orig = skb; | 588 | skb_set_transport_header(skb, fhoff); |
593 | 589 | hdr = ipv6_hdr(skb); | |
594 | if (!pskb_may_pull(clone, fhoff + sizeof(*fhdr))) { | 590 | fhdr = (struct frag_hdr *)skb_transport_header(skb); |
595 | pr_debug("message is too short.\n"); | ||
596 | goto ret_orig; | ||
597 | } | ||
598 | |||
599 | skb_set_transport_header(clone, fhoff); | ||
600 | hdr = ipv6_hdr(clone); | ||
601 | fhdr = (struct frag_hdr *)skb_transport_header(clone); | ||
602 | 591 | ||
603 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr, | 592 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr, |
604 | ip6_frag_ecn(hdr)); | 593 | skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr)); |
605 | if (fq == NULL) { | 594 | if (fq == NULL) { |
606 | pr_debug("Can't find and can't create new queue\n"); | 595 | pr_debug("Can't find and can't create new queue\n"); |
607 | goto ret_orig; | 596 | return -ENOMEM; |
608 | } | 597 | } |
609 | 598 | ||
610 | spin_lock_bh(&fq->q.lock); | 599 | spin_lock_bh(&fq->q.lock); |
611 | 600 | ||
612 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { | 601 | if (nf_ct_frag6_queue(fq, skb, fhdr, nhoff) < 0) { |
613 | spin_unlock_bh(&fq->q.lock); | 602 | ret = -EINVAL; |
614 | pr_debug("Can't insert skb to queue\n"); | 603 | goto out_unlock; |
615 | inet_frag_put(&fq->q, &nf_frags); | ||
616 | goto ret_orig; | ||
617 | } | 604 | } |
618 | 605 | ||
606 | /* after queue has assumed skb ownership, only 0 or -EINPROGRESS | ||
607 | * must be returned. | ||
608 | */ | ||
609 | ret = -EINPROGRESS; | ||
619 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 610 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
620 | fq->q.meat == fq->q.len) { | 611 | fq->q.meat == fq->q.len && |
621 | ret_skb = nf_ct_frag6_reasm(fq, dev); | 612 | nf_ct_frag6_reasm(fq, skb, dev)) |
622 | if (ret_skb == NULL) | 613 | ret = 0; |
623 | pr_debug("Can't reassemble fragmented packets\n"); | ||
624 | } | ||
625 | spin_unlock_bh(&fq->q.lock); | ||
626 | 614 | ||
615 | out_unlock: | ||
616 | spin_unlock_bh(&fq->q.lock); | ||
627 | inet_frag_put(&fq->q, &nf_frags); | 617 | inet_frag_put(&fq->q, &nf_frags); |
628 | return ret_skb; | 618 | return ret; |
629 | |||
630 | ret_orig: | ||
631 | kfree_skb(clone); | ||
632 | return skb; | ||
633 | } | 619 | } |
634 | EXPORT_SYMBOL_GPL(nf_ct_frag6_gather); | 620 | EXPORT_SYMBOL_GPL(nf_ct_frag6_gather); |
635 | 621 | ||
636 | void nf_ct_frag6_consume_orig(struct sk_buff *skb) | ||
637 | { | ||
638 | struct sk_buff *s, *s2; | ||
639 | |||
640 | for (s = NFCT_FRAG6_CB(skb)->orig; s;) { | ||
641 | s2 = s->next; | ||
642 | s->next = NULL; | ||
643 | consume_skb(s); | ||
644 | s = s2; | ||
645 | } | ||
646 | } | ||
647 | EXPORT_SYMBOL_GPL(nf_ct_frag6_consume_orig); | ||
648 | |||
649 | static int nf_ct_net_init(struct net *net) | 622 | static int nf_ct_net_init(struct net *net) |
650 | { | 623 | { |
651 | int res; | 624 | int res; |
@@ -680,7 +653,6 @@ int nf_ct_frag6_init(void) | |||
680 | nf_frags.hashfn = nf_hashfn; | 653 | nf_frags.hashfn = nf_hashfn; |
681 | nf_frags.constructor = ip6_frag_init; | 654 | nf_frags.constructor = ip6_frag_init; |
682 | nf_frags.destructor = NULL; | 655 | nf_frags.destructor = NULL; |
683 | nf_frags.skb_free = nf_skb_free; | ||
684 | nf_frags.qsize = sizeof(struct frag_queue); | 656 | nf_frags.qsize = sizeof(struct frag_queue); |
685 | nf_frags.match = ip6_frag_match; | 657 | nf_frags.match = ip6_frag_match; |
686 | nf_frags.frag_expire = nf_ct_frag6_expire; | 658 | nf_frags.frag_expire = nf_ct_frag6_expire; |
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index 4fdbed5ebfb6..f7aab5ab93a5 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | |||
@@ -55,7 +55,7 @@ static unsigned int ipv6_defrag(void *priv, | |||
55 | struct sk_buff *skb, | 55 | struct sk_buff *skb, |
56 | const struct nf_hook_state *state) | 56 | const struct nf_hook_state *state) |
57 | { | 57 | { |
58 | struct sk_buff *reasm; | 58 | int err; |
59 | 59 | ||
60 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 60 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
61 | /* Previously seen (loopback)? */ | 61 | /* Previously seen (loopback)? */ |
@@ -63,23 +63,13 @@ static unsigned int ipv6_defrag(void *priv, | |||
63 | return NF_ACCEPT; | 63 | return NF_ACCEPT; |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | reasm = nf_ct_frag6_gather(state->net, skb, | 66 | err = nf_ct_frag6_gather(state->net, skb, |
67 | nf_ct6_defrag_user(state->hook, skb)); | 67 | nf_ct6_defrag_user(state->hook, skb)); |
68 | /* queued */ | 68 | /* queued */ |
69 | if (reasm == NULL) | 69 | if (err == -EINPROGRESS) |
70 | return NF_STOLEN; | 70 | return NF_STOLEN; |
71 | 71 | ||
72 | /* error occurred or not fragmented */ | 72 | return NF_ACCEPT; |
73 | if (reasm == skb) | ||
74 | return NF_ACCEPT; | ||
75 | |||
76 | nf_ct_frag6_consume_orig(reasm); | ||
77 | |||
78 | NF_HOOK_THRESH(NFPROTO_IPV6, state->hook, state->net, state->sk, reasm, | ||
79 | state->in, state->out, | ||
80 | state->okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1); | ||
81 | |||
82 | return NF_STOLEN; | ||
83 | } | 73 | } |
84 | 74 | ||
85 | static struct nf_hook_ops ipv6_defrag_ops[] = { | 75 | static struct nf_hook_ops ipv6_defrag_ops[] = { |
diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index 238e70c3f7b7..6ce309928841 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | |||
@@ -136,7 +136,8 @@ static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, | |||
136 | 136 | ||
137 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 137 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
138 | if (!(rt->rt6i_flags & RTF_LOCAL) && | 138 | if (!(rt->rt6i_flags & RTF_LOCAL) && |
139 | (!skb->dev || skb->dev->features & NETIF_F_V6_CSUM)) { | 139 | (!skb->dev || skb->dev->features & |
140 | (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))) { | ||
140 | skb->ip_summed = CHECKSUM_PARTIAL; | 141 | skb->ip_summed = CHECKSUM_PARTIAL; |
141 | skb->csum_start = skb_headroom(skb) + | 142 | skb->csum_start = skb_headroom(skb) + |
142 | skb_network_offset(skb) + | 143 | skb_network_offset(skb) + |
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index e0f922b777e3..4709f657b7b6 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <net/netfilter/ipv6/nf_reject.h> | 14 | #include <net/netfilter/ipv6/nf_reject.h> |
15 | #include <linux/netfilter_ipv6.h> | 15 | #include <linux/netfilter_ipv6.h> |
16 | #include <linux/netfilter_bridge.h> | 16 | #include <linux/netfilter_bridge.h> |
17 | #include <net/netfilter/ipv6/nf_reject.h> | ||
18 | 17 | ||
19 | const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, | 18 | const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, |
20 | struct tcphdr *otcph, | 19 | struct tcphdr *otcph, |
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c index 120ea9131be0..30b22f4dff55 100644 --- a/net/ipv6/netfilter/nf_tables_ipv6.c +++ b/net/ipv6/netfilter/nf_tables_ipv6.c | |||
@@ -77,7 +77,7 @@ err: | |||
77 | 77 | ||
78 | static void nf_tables_ipv6_exit_net(struct net *net) | 78 | static void nf_tables_ipv6_exit_net(struct net *net) |
79 | { | 79 | { |
80 | nft_unregister_afinfo(net->nft.ipv6); | 80 | nft_unregister_afinfo(net, net->nft.ipv6); |
81 | kfree(net->nft.ipv6); | 81 | kfree(net->nft.ipv6); |
82 | } | 82 | } |
83 | 83 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index dc65ec198f7c..fa59dd7a427e 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -733,6 +733,7 @@ static int raw6_getfrag(void *from, char *to, int offset, int len, int odd, | |||
733 | 733 | ||
734 | static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | 734 | static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) |
735 | { | 735 | { |
736 | struct ipv6_txoptions *opt_to_free = NULL; | ||
736 | struct ipv6_txoptions opt_space; | 737 | struct ipv6_txoptions opt_space; |
737 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); | 738 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); |
738 | struct in6_addr *daddr, *final_p, final; | 739 | struct in6_addr *daddr, *final_p, final; |
@@ -839,8 +840,10 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
839 | if (!(opt->opt_nflen|opt->opt_flen)) | 840 | if (!(opt->opt_nflen|opt->opt_flen)) |
840 | opt = NULL; | 841 | opt = NULL; |
841 | } | 842 | } |
842 | if (!opt) | 843 | if (!opt) { |
843 | opt = np->opt; | 844 | opt = txopt_get(np); |
845 | opt_to_free = opt; | ||
846 | } | ||
844 | if (flowlabel) | 847 | if (flowlabel) |
845 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 848 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
846 | opt = ipv6_fixup_options(&opt_space, opt); | 849 | opt = ipv6_fixup_options(&opt_space, opt); |
@@ -906,6 +909,7 @@ done: | |||
906 | dst_release(dst); | 909 | dst_release(dst); |
907 | out: | 910 | out: |
908 | fl6_sock_release(flowlabel); | 911 | fl6_sock_release(flowlabel); |
912 | txopt_put(opt_to_free); | ||
909 | return err < 0 ? err : len; | 913 | return err < 0 ? err : len; |
910 | do_confirm: | 914 | do_confirm: |
911 | dst_confirm(dst); | 915 | dst_confirm(dst); |
@@ -968,6 +972,11 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
968 | return -EFAULT; | 972 | return -EFAULT; |
969 | 973 | ||
970 | switch (optname) { | 974 | switch (optname) { |
975 | case IPV6_HDRINCL: | ||
976 | if (sk->sk_type != SOCK_RAW) | ||
977 | return -EINVAL; | ||
978 | inet_sk(sk)->hdrincl = !!val; | ||
979 | return 0; | ||
971 | case IPV6_CHECKSUM: | 980 | case IPV6_CHECKSUM: |
972 | if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 && | 981 | if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 && |
973 | level == IPPROTO_IPV6) { | 982 | level == IPPROTO_IPV6) { |
@@ -1012,7 +1021,8 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
1012 | return -EOPNOTSUPP; | 1021 | return -EOPNOTSUPP; |
1013 | return rawv6_seticmpfilter(sk, level, optname, optval, optlen); | 1022 | return rawv6_seticmpfilter(sk, level, optname, optval, optlen); |
1014 | case SOL_IPV6: | 1023 | case SOL_IPV6: |
1015 | if (optname == IPV6_CHECKSUM) | 1024 | if (optname == IPV6_CHECKSUM || |
1025 | optname == IPV6_HDRINCL) | ||
1016 | break; | 1026 | break; |
1017 | default: | 1027 | default: |
1018 | return ipv6_setsockopt(sk, level, optname, optval, optlen); | 1028 | return ipv6_setsockopt(sk, level, optname, optval, optlen); |
@@ -1033,7 +1043,8 @@ static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
1033 | return -EOPNOTSUPP; | 1043 | return -EOPNOTSUPP; |
1034 | return rawv6_seticmpfilter(sk, level, optname, optval, optlen); | 1044 | return rawv6_seticmpfilter(sk, level, optname, optval, optlen); |
1035 | case SOL_IPV6: | 1045 | case SOL_IPV6: |
1036 | if (optname == IPV6_CHECKSUM) | 1046 | if (optname == IPV6_CHECKSUM || |
1047 | optname == IPV6_HDRINCL) | ||
1037 | break; | 1048 | break; |
1038 | default: | 1049 | default: |
1039 | return compat_ipv6_setsockopt(sk, level, optname, | 1050 | return compat_ipv6_setsockopt(sk, level, optname, |
@@ -1053,6 +1064,9 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1053 | return -EFAULT; | 1064 | return -EFAULT; |
1054 | 1065 | ||
1055 | switch (optname) { | 1066 | switch (optname) { |
1067 | case IPV6_HDRINCL: | ||
1068 | val = inet_sk(sk)->hdrincl; | ||
1069 | break; | ||
1056 | case IPV6_CHECKSUM: | 1070 | case IPV6_CHECKSUM: |
1057 | /* | 1071 | /* |
1058 | * We allow getsockopt() for IPPROTO_IPV6-level | 1072 | * We allow getsockopt() for IPPROTO_IPV6-level |
@@ -1090,7 +1104,8 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1090 | return -EOPNOTSUPP; | 1104 | return -EOPNOTSUPP; |
1091 | return rawv6_geticmpfilter(sk, level, optname, optval, optlen); | 1105 | return rawv6_geticmpfilter(sk, level, optname, optval, optlen); |
1092 | case SOL_IPV6: | 1106 | case SOL_IPV6: |
1093 | if (optname == IPV6_CHECKSUM) | 1107 | if (optname == IPV6_CHECKSUM || |
1108 | optname == IPV6_HDRINCL) | ||
1094 | break; | 1109 | break; |
1095 | default: | 1110 | default: |
1096 | return ipv6_getsockopt(sk, level, optname, optval, optlen); | 1111 | return ipv6_getsockopt(sk, level, optname, optval, optlen); |
@@ -1111,7 +1126,8 @@ static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1111 | return -EOPNOTSUPP; | 1126 | return -EOPNOTSUPP; |
1112 | return rawv6_geticmpfilter(sk, level, optname, optval, optlen); | 1127 | return rawv6_geticmpfilter(sk, level, optname, optval, optlen); |
1113 | case SOL_IPV6: | 1128 | case SOL_IPV6: |
1114 | if (optname == IPV6_CHECKSUM) | 1129 | if (optname == IPV6_CHECKSUM || |
1130 | optname == IPV6_HDRINCL) | ||
1115 | break; | 1131 | break; |
1116 | default: | 1132 | default: |
1117 | return compat_ipv6_getsockopt(sk, level, optname, | 1133 | return compat_ipv6_getsockopt(sk, level, optname, |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 44e21a03cfc3..18f3498a6c80 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -108,7 +108,10 @@ bool ip6_frag_match(const struct inet_frag_queue *q, const void *a) | |||
108 | return fq->id == arg->id && | 108 | return fq->id == arg->id && |
109 | fq->user == arg->user && | 109 | fq->user == arg->user && |
110 | ipv6_addr_equal(&fq->saddr, arg->src) && | 110 | ipv6_addr_equal(&fq->saddr, arg->src) && |
111 | ipv6_addr_equal(&fq->daddr, arg->dst); | 111 | ipv6_addr_equal(&fq->daddr, arg->dst) && |
112 | (arg->iif == fq->iif || | ||
113 | !(ipv6_addr_type(arg->dst) & (IPV6_ADDR_MULTICAST | | ||
114 | IPV6_ADDR_LINKLOCAL))); | ||
112 | } | 115 | } |
113 | EXPORT_SYMBOL(ip6_frag_match); | 116 | EXPORT_SYMBOL(ip6_frag_match); |
114 | 117 | ||
@@ -180,7 +183,7 @@ static void ip6_frag_expire(unsigned long data) | |||
180 | 183 | ||
181 | static struct frag_queue * | 184 | static struct frag_queue * |
182 | fq_find(struct net *net, __be32 id, const struct in6_addr *src, | 185 | fq_find(struct net *net, __be32 id, const struct in6_addr *src, |
183 | const struct in6_addr *dst, u8 ecn) | 186 | const struct in6_addr *dst, int iif, u8 ecn) |
184 | { | 187 | { |
185 | struct inet_frag_queue *q; | 188 | struct inet_frag_queue *q; |
186 | struct ip6_create_arg arg; | 189 | struct ip6_create_arg arg; |
@@ -190,6 +193,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, | |||
190 | arg.user = IP6_DEFRAG_LOCAL_DELIVER; | 193 | arg.user = IP6_DEFRAG_LOCAL_DELIVER; |
191 | arg.src = src; | 194 | arg.src = src; |
192 | arg.dst = dst; | 195 | arg.dst = dst; |
196 | arg.iif = iif; | ||
193 | arg.ecn = ecn; | 197 | arg.ecn = ecn; |
194 | 198 | ||
195 | hash = inet6_hash_frag(id, src, dst); | 199 | hash = inet6_hash_frag(id, src, dst); |
@@ -551,7 +555,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
551 | } | 555 | } |
552 | 556 | ||
553 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, | 557 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, |
554 | ip6_frag_ecn(hdr)); | 558 | skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr)); |
555 | if (fq) { | 559 | if (fq) { |
556 | int ret; | 560 | int ret; |
557 | 561 | ||
@@ -751,7 +755,6 @@ int __init ipv6_frag_init(void) | |||
751 | ip6_frags.hashfn = ip6_hashfn; | 755 | ip6_frags.hashfn = ip6_hashfn; |
752 | ip6_frags.constructor = ip6_frag_init; | 756 | ip6_frags.constructor = ip6_frag_init; |
753 | ip6_frags.destructor = NULL; | 757 | ip6_frags.destructor = NULL; |
754 | ip6_frags.skb_free = NULL; | ||
755 | ip6_frags.qsize = sizeof(struct frag_queue); | 758 | ip6_frags.qsize = sizeof(struct frag_queue); |
756 | ip6_frags.match = ip6_frag_match; | 759 | ip6_frags.match = ip6_frag_match; |
757 | ip6_frags.frag_expire = ip6_frag_expire; | 760 | ip6_frags.frag_expire = ip6_frag_expire; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6f01fe122abd..3c8834bc822d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <net/lwtunnel.h> | 62 | #include <net/lwtunnel.h> |
63 | #include <net/ip_tunnels.h> | 63 | #include <net/ip_tunnels.h> |
64 | #include <net/l3mdev.h> | 64 | #include <net/l3mdev.h> |
65 | #include <trace/events/fib6.h> | ||
65 | 66 | ||
66 | #include <asm/uaccess.h> | 67 | #include <asm/uaccess.h> |
67 | 68 | ||
@@ -523,7 +524,7 @@ static void rt6_probe_deferred(struct work_struct *w) | |||
523 | container_of(w, struct __rt6_probe_work, work); | 524 | container_of(w, struct __rt6_probe_work, work); |
524 | 525 | ||
525 | addrconf_addr_solict_mult(&work->target, &mcaddr); | 526 | addrconf_addr_solict_mult(&work->target, &mcaddr); |
526 | ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL, NULL); | 527 | ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL); |
527 | dev_put(work->dev); | 528 | dev_put(work->dev); |
528 | kfree(work); | 529 | kfree(work); |
529 | } | 530 | } |
@@ -865,6 +866,9 @@ restart: | |||
865 | } | 866 | } |
866 | dst_use(&rt->dst, jiffies); | 867 | dst_use(&rt->dst, jiffies); |
867 | read_unlock_bh(&table->tb6_lock); | 868 | read_unlock_bh(&table->tb6_lock); |
869 | |||
870 | trace_fib6_table_lookup(net, rt, table->tb6_id, fl6); | ||
871 | |||
868 | return rt; | 872 | return rt; |
869 | 873 | ||
870 | } | 874 | } |
@@ -1078,6 +1082,8 @@ redo_rt6_select: | |||
1078 | read_unlock_bh(&table->tb6_lock); | 1082 | read_unlock_bh(&table->tb6_lock); |
1079 | 1083 | ||
1080 | rt6_dst_from_metrics_check(rt); | 1084 | rt6_dst_from_metrics_check(rt); |
1085 | |||
1086 | trace_fib6_table_lookup(net, rt, table->tb6_id, fl6); | ||
1081 | return rt; | 1087 | return rt; |
1082 | } else if (unlikely((fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH) && | 1088 | } else if (unlikely((fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH) && |
1083 | !(rt->rt6i_flags & RTF_GATEWAY))) { | 1089 | !(rt->rt6i_flags & RTF_GATEWAY))) { |
@@ -1101,6 +1107,8 @@ redo_rt6_select: | |||
1101 | uncached_rt = net->ipv6.ip6_null_entry; | 1107 | uncached_rt = net->ipv6.ip6_null_entry; |
1102 | 1108 | ||
1103 | dst_hold(&uncached_rt->dst); | 1109 | dst_hold(&uncached_rt->dst); |
1110 | |||
1111 | trace_fib6_table_lookup(net, uncached_rt, table->tb6_id, fl6); | ||
1104 | return uncached_rt; | 1112 | return uncached_rt; |
1105 | 1113 | ||
1106 | } else { | 1114 | } else { |
@@ -1125,6 +1133,7 @@ redo_rt6_select: | |||
1125 | dst_release(&rt->dst); | 1133 | dst_release(&rt->dst); |
1126 | } | 1134 | } |
1127 | 1135 | ||
1136 | trace_fib6_table_lookup(net, pcpu_rt, table->tb6_id, fl6); | ||
1128 | return pcpu_rt; | 1137 | return pcpu_rt; |
1129 | 1138 | ||
1130 | } | 1139 | } |
@@ -1474,6 +1483,7 @@ out: | |||
1474 | 1483 | ||
1475 | read_unlock_bh(&table->tb6_lock); | 1484 | read_unlock_bh(&table->tb6_lock); |
1476 | 1485 | ||
1486 | trace_fib6_table_lookup(net, rt, table->tb6_id, fl6); | ||
1477 | return rt; | 1487 | return rt; |
1478 | }; | 1488 | }; |
1479 | 1489 | ||
@@ -2699,6 +2709,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { | |||
2699 | [RTA_PREF] = { .type = NLA_U8 }, | 2709 | [RTA_PREF] = { .type = NLA_U8 }, |
2700 | [RTA_ENCAP_TYPE] = { .type = NLA_U16 }, | 2710 | [RTA_ENCAP_TYPE] = { .type = NLA_U16 }, |
2701 | [RTA_ENCAP] = { .type = NLA_NESTED }, | 2711 | [RTA_ENCAP] = { .type = NLA_NESTED }, |
2712 | [RTA_EXPIRES] = { .type = NLA_U32 }, | ||
2702 | }; | 2713 | }; |
2703 | 2714 | ||
2704 | static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, | 2715 | static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, |
@@ -2799,6 +2810,15 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
2799 | if (tb[RTA_ENCAP_TYPE]) | 2810 | if (tb[RTA_ENCAP_TYPE]) |
2800 | cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]); | 2811 | cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]); |
2801 | 2812 | ||
2813 | if (tb[RTA_EXPIRES]) { | ||
2814 | unsigned long timeout = addrconf_timeout_fixup(nla_get_u32(tb[RTA_EXPIRES]), HZ); | ||
2815 | |||
2816 | if (addrconf_finite_timeout(timeout)) { | ||
2817 | cfg->fc_expires = jiffies_to_clock_t(timeout * HZ); | ||
2818 | cfg->fc_flags |= RTF_EXPIRES; | ||
2819 | } | ||
2820 | } | ||
2821 | |||
2802 | err = 0; | 2822 | err = 0; |
2803 | errout: | 2823 | errout: |
2804 | return err; | 2824 | return err; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index dcccae86190f..e794ef66a401 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -820,7 +820,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
820 | const struct in6_addr *addr6; | 820 | const struct in6_addr *addr6; |
821 | int addr_type; | 821 | int addr_type; |
822 | u8 ttl; | 822 | u8 ttl; |
823 | int err; | ||
824 | u8 protocol = IPPROTO_IPV6; | 823 | u8 protocol = IPPROTO_IPV6; |
825 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); | 824 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); |
826 | 825 | ||
@@ -983,10 +982,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
983 | 982 | ||
984 | skb_set_inner_ipproto(skb, IPPROTO_IPV6); | 983 | skb_set_inner_ipproto(skb, IPPROTO_IPV6); |
985 | 984 | ||
986 | err = iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, | 985 | iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl, |
987 | protocol, tos, ttl, df, | 986 | df, !net_eq(tunnel->net, dev_net(dev))); |
988 | !net_eq(tunnel->net, dev_net(dev))); | ||
989 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); | ||
990 | return NETDEV_TX_OK; | 987 | return NETDEV_TX_OK; |
991 | 988 | ||
992 | tx_error_icmp: | 989 | tx_error_icmp: |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index bb8f2fa1c7fb..2906ef20795e 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -193,7 +193,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
193 | ireq->pktopts = skb; | 193 | ireq->pktopts = skb; |
194 | } | 194 | } |
195 | 195 | ||
196 | ireq->ir_iif = sk->sk_bound_dev_if; | 196 | ireq->ir_iif = inet_request_bound_dev_if(sk, skb); |
197 | /* So that link locals have meaning */ | 197 | /* So that link locals have meaning */ |
198 | if (!sk->sk_bound_dev_if && | 198 | if (!sk->sk_bound_dev_if && |
199 | ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL) | 199 | ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL) |
@@ -222,9 +222,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
222 | memset(&fl6, 0, sizeof(fl6)); | 222 | memset(&fl6, 0, sizeof(fl6)); |
223 | fl6.flowi6_proto = IPPROTO_TCP; | 223 | fl6.flowi6_proto = IPPROTO_TCP; |
224 | fl6.daddr = ireq->ir_v6_rmt_addr; | 224 | fl6.daddr = ireq->ir_v6_rmt_addr; |
225 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 225 | final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); |
226 | fl6.saddr = ireq->ir_v6_loc_addr; | 226 | fl6.saddr = ireq->ir_v6_loc_addr; |
227 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 227 | fl6.flowi6_oif = ireq->ir_iif; |
228 | fl6.flowi6_mark = ireq->ir_mark; | 228 | fl6.flowi6_mark = ireq->ir_mark; |
229 | fl6.fl6_dport = ireq->ir_rmt_port; | 229 | fl6.fl6_dport = ireq->ir_rmt_port; |
230 | fl6.fl6_sport = inet_sk(sk)->inet_sport; | 230 | fl6.fl6_sport = inet_sk(sk)->inet_sport; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c5429a636f1a..db9f1c318afc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -93,10 +93,9 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | |||
93 | { | 93 | { |
94 | struct dst_entry *dst = skb_dst(skb); | 94 | struct dst_entry *dst = skb_dst(skb); |
95 | 95 | ||
96 | if (dst) { | 96 | if (dst && dst_hold_safe(dst)) { |
97 | const struct rt6_info *rt = (const struct rt6_info *)dst; | 97 | const struct rt6_info *rt = (const struct rt6_info *)dst; |
98 | 98 | ||
99 | dst_hold(dst); | ||
100 | sk->sk_rx_dst = dst; | 99 | sk->sk_rx_dst = dst; |
101 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; | 100 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; |
102 | inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); | 101 | inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); |
@@ -120,6 +119,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
120 | struct ipv6_pinfo *np = inet6_sk(sk); | 119 | struct ipv6_pinfo *np = inet6_sk(sk); |
121 | struct tcp_sock *tp = tcp_sk(sk); | 120 | struct tcp_sock *tp = tcp_sk(sk); |
122 | struct in6_addr *saddr = NULL, *final_p, final; | 121 | struct in6_addr *saddr = NULL, *final_p, final; |
122 | struct ipv6_txoptions *opt; | ||
123 | struct flowi6 fl6; | 123 | struct flowi6 fl6; |
124 | struct dst_entry *dst; | 124 | struct dst_entry *dst; |
125 | int addr_type; | 125 | int addr_type; |
@@ -235,7 +235,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
235 | fl6.fl6_dport = usin->sin6_port; | 235 | fl6.fl6_dport = usin->sin6_port; |
236 | fl6.fl6_sport = inet->inet_sport; | 236 | fl6.fl6_sport = inet->inet_sport; |
237 | 237 | ||
238 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 238 | opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); |
239 | final_p = fl6_update_dst(&fl6, opt, &final); | ||
239 | 240 | ||
240 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 241 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
241 | 242 | ||
@@ -255,7 +256,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
255 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; | 256 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
256 | 257 | ||
257 | sk->sk_gso_type = SKB_GSO_TCPV6; | 258 | sk->sk_gso_type = SKB_GSO_TCPV6; |
258 | __ip6_dst_store(sk, dst, NULL, NULL); | 259 | ip6_dst_store(sk, dst, NULL, NULL); |
259 | 260 | ||
260 | if (tcp_death_row.sysctl_tw_recycle && | 261 | if (tcp_death_row.sysctl_tw_recycle && |
261 | !tp->rx_opt.ts_recent_stamp && | 262 | !tp->rx_opt.ts_recent_stamp && |
@@ -263,9 +264,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
263 | tcp_fetch_timewait_stamp(sk, dst); | 264 | tcp_fetch_timewait_stamp(sk, dst); |
264 | 265 | ||
265 | icsk->icsk_ext_hdr_len = 0; | 266 | icsk->icsk_ext_hdr_len = 0; |
266 | if (np->opt) | 267 | if (opt) |
267 | icsk->icsk_ext_hdr_len = (np->opt->opt_flen + | 268 | icsk->icsk_ext_hdr_len = opt->opt_flen + |
268 | np->opt->opt_nflen); | 269 | opt->opt_nflen; |
269 | 270 | ||
270 | tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | 271 | tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); |
271 | 272 | ||
@@ -461,7 +462,10 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst, | |||
461 | if (np->repflow && ireq->pktopts) | 462 | if (np->repflow && ireq->pktopts) |
462 | fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); | 463 | fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); |
463 | 464 | ||
464 | err = ip6_xmit(sk, skb, fl6, np->opt, np->tclass); | 465 | rcu_read_lock(); |
466 | err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), | ||
467 | np->tclass); | ||
468 | rcu_read_unlock(); | ||
465 | err = net_xmit_eval(err); | 469 | err = net_xmit_eval(err); |
466 | } | 470 | } |
467 | 471 | ||
@@ -852,7 +856,9 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
852 | 856 | ||
853 | #ifdef CONFIG_TCP_MD5SIG | 857 | #ifdef CONFIG_TCP_MD5SIG |
854 | hash_location = tcp_parse_md5sig_option(th); | 858 | hash_location = tcp_parse_md5sig_option(th); |
855 | if (!sk && hash_location) { | 859 | if (sk && sk_fullsock(sk)) { |
860 | key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr); | ||
861 | } else if (hash_location) { | ||
856 | /* | 862 | /* |
857 | * active side is lost. Try to find listening socket through | 863 | * active side is lost. Try to find listening socket through |
858 | * source port, and then find md5 key through listening socket. | 864 | * source port, and then find md5 key through listening socket. |
@@ -875,8 +881,6 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) | |||
875 | genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb); | 881 | genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb); |
876 | if (genhash || memcmp(hash_location, newhash, 16) != 0) | 882 | if (genhash || memcmp(hash_location, newhash, 16) != 0) |
877 | goto release_sk1; | 883 | goto release_sk1; |
878 | } else { | ||
879 | key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL; | ||
880 | } | 884 | } |
881 | #endif | 885 | #endif |
882 | 886 | ||
@@ -972,6 +976,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
972 | struct inet_request_sock *ireq; | 976 | struct inet_request_sock *ireq; |
973 | struct ipv6_pinfo *newnp; | 977 | struct ipv6_pinfo *newnp; |
974 | const struct ipv6_pinfo *np = inet6_sk(sk); | 978 | const struct ipv6_pinfo *np = inet6_sk(sk); |
979 | struct ipv6_txoptions *opt; | ||
975 | struct tcp6_sock *newtcp6sk; | 980 | struct tcp6_sock *newtcp6sk; |
976 | struct inet_sock *newinet; | 981 | struct inet_sock *newinet; |
977 | struct tcp_sock *newtp; | 982 | struct tcp_sock *newtp; |
@@ -1056,7 +1061,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
1056 | */ | 1061 | */ |
1057 | 1062 | ||
1058 | newsk->sk_gso_type = SKB_GSO_TCPV6; | 1063 | newsk->sk_gso_type = SKB_GSO_TCPV6; |
1059 | __ip6_dst_store(newsk, dst, NULL, NULL); | 1064 | ip6_dst_store(newsk, dst, NULL, NULL); |
1060 | inet6_sk_rx_dst_set(newsk, skb); | 1065 | inet6_sk_rx_dst_set(newsk, skb); |
1061 | 1066 | ||
1062 | newtcp6sk = (struct tcp6_sock *)newsk; | 1067 | newtcp6sk = (struct tcp6_sock *)newsk; |
@@ -1098,13 +1103,15 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
1098 | but we make one more one thing there: reattach optmem | 1103 | but we make one more one thing there: reattach optmem |
1099 | to newsk. | 1104 | to newsk. |
1100 | */ | 1105 | */ |
1101 | if (np->opt) | 1106 | opt = rcu_dereference(np->opt); |
1102 | newnp->opt = ipv6_dup_options(newsk, np->opt); | 1107 | if (opt) { |
1103 | 1108 | opt = ipv6_dup_options(newsk, opt); | |
1109 | RCU_INIT_POINTER(newnp->opt, opt); | ||
1110 | } | ||
1104 | inet_csk(newsk)->icsk_ext_hdr_len = 0; | 1111 | inet_csk(newsk)->icsk_ext_hdr_len = 0; |
1105 | if (newnp->opt) | 1112 | if (opt) |
1106 | inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + | 1113 | inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + |
1107 | newnp->opt->opt_flen); | 1114 | opt->opt_flen; |
1108 | 1115 | ||
1109 | tcp_ca_openreq_child(newsk, dst); | 1116 | tcp_ca_openreq_child(newsk, dst); |
1110 | 1117 | ||
@@ -1130,7 +1137,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
1130 | */ | 1137 | */ |
1131 | tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr, | 1138 | tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr, |
1132 | AF_INET6, key->key, key->keylen, | 1139 | AF_INET6, key->key, key->keylen, |
1133 | sk_gfp_atomic(sk, GFP_ATOMIC)); | 1140 | sk_gfp_mask(sk, GFP_ATOMIC)); |
1134 | } | 1141 | } |
1135 | #endif | 1142 | #endif |
1136 | 1143 | ||
@@ -1146,7 +1153,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
1146 | /* Clone pktoptions received with SYN, if we own the req */ | 1153 | /* Clone pktoptions received with SYN, if we own the req */ |
1147 | if (ireq->pktopts) { | 1154 | if (ireq->pktopts) { |
1148 | newnp->pktoptions = skb_clone(ireq->pktopts, | 1155 | newnp->pktoptions = skb_clone(ireq->pktopts, |
1149 | sk_gfp_atomic(sk, GFP_ATOMIC)); | 1156 | sk_gfp_mask(sk, GFP_ATOMIC)); |
1150 | consume_skb(ireq->pktopts); | 1157 | consume_skb(ireq->pktopts); |
1151 | ireq->pktopts = NULL; | 1158 | ireq->pktopts = NULL; |
1152 | if (newnp->pktoptions) | 1159 | if (newnp->pktoptions) |
@@ -1212,7 +1219,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1212 | --ANK (980728) | 1219 | --ANK (980728) |
1213 | */ | 1220 | */ |
1214 | if (np->rxopt.all) | 1221 | if (np->rxopt.all) |
1215 | opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC)); | 1222 | opt_skb = skb_clone(skb, sk_gfp_mask(sk, GFP_ATOMIC)); |
1216 | 1223 | ||
1217 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1224 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1218 | struct dst_entry *dst = sk->sk_rx_dst; | 1225 | struct dst_entry *dst = sk->sk_rx_dst; |
@@ -1511,7 +1518,9 @@ do_time_wait: | |||
1511 | break; | 1518 | break; |
1512 | case TCP_TW_RST: | 1519 | case TCP_TW_RST: |
1513 | tcp_v6_restore_cb(skb); | 1520 | tcp_v6_restore_cb(skb); |
1514 | goto no_tcp_socket; | 1521 | tcp_v6_send_reset(sk, skb); |
1522 | inet_twsk_deschedule_put(inet_twsk(sk)); | ||
1523 | goto discard_it; | ||
1515 | case TCP_TW_SUCCESS: | 1524 | case TCP_TW_SUCCESS: |
1516 | ; | 1525 | ; |
1517 | } | 1526 | } |
@@ -1884,6 +1893,7 @@ struct proto tcpv6_prot = { | |||
1884 | .proto_cgroup = tcp_proto_cgroup, | 1893 | .proto_cgroup = tcp_proto_cgroup, |
1885 | #endif | 1894 | #endif |
1886 | .clear_sk = tcp_v6_clear_sk, | 1895 | .clear_sk = tcp_v6_clear_sk, |
1896 | .diag_destroy = tcp_abort, | ||
1887 | }; | 1897 | }; |
1888 | 1898 | ||
1889 | static const struct inet6_protocol tcpv6_protocol = { | 1899 | static const struct inet6_protocol tcpv6_protocol = { |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 01bcb49619ee..5d2c2afffe7b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <net/xfrm.h> | 47 | #include <net/xfrm.h> |
48 | #include <net/inet6_hashtables.h> | 48 | #include <net/inet6_hashtables.h> |
49 | #include <net/busy_poll.h> | 49 | #include <net/busy_poll.h> |
50 | #include <net/sock_reuseport.h> | ||
50 | 51 | ||
51 | #include <linux/proc_fs.h> | 52 | #include <linux/proc_fs.h> |
52 | #include <linux/seq_file.h> | 53 | #include <linux/seq_file.h> |
@@ -76,7 +77,14 @@ static u32 udp6_ehashfn(const struct net *net, | |||
76 | udp_ipv6_hash_secret + net_hash_mix(net)); | 77 | udp_ipv6_hash_secret + net_hash_mix(net)); |
77 | } | 78 | } |
78 | 79 | ||
79 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | 80 | /* match_wildcard == true: IPV6_ADDR_ANY equals to any IPv6 addresses if IPv6 |
81 | * only, and any IPv4 addresses if not IPv6 only | ||
82 | * match_wildcard == false: addresses must be exactly the same, i.e. | ||
83 | * IPV6_ADDR_ANY only equals to IPV6_ADDR_ANY, | ||
84 | * and 0.0.0.0 equals to 0.0.0.0 only | ||
85 | */ | ||
86 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2, | ||
87 | bool match_wildcard) | ||
80 | { | 88 | { |
81 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | 89 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); |
82 | int sk2_ipv6only = inet_v6_ipv6only(sk2); | 90 | int sk2_ipv6only = inet_v6_ipv6only(sk2); |
@@ -84,16 +92,24 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
84 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; | 92 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; |
85 | 93 | ||
86 | /* if both are mapped, treat as IPv4 */ | 94 | /* if both are mapped, treat as IPv4 */ |
87 | if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) | 95 | if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) { |
88 | return (!sk2_ipv6only && | 96 | if (!sk2_ipv6only) { |
89 | (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr || | 97 | if (sk->sk_rcv_saddr == sk2->sk_rcv_saddr) |
90 | sk->sk_rcv_saddr == sk2->sk_rcv_saddr)); | 98 | return 1; |
99 | if (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr) | ||
100 | return match_wildcard; | ||
101 | } | ||
102 | return 0; | ||
103 | } | ||
91 | 104 | ||
92 | if (addr_type2 == IPV6_ADDR_ANY && | 105 | if (addr_type == IPV6_ADDR_ANY && addr_type2 == IPV6_ADDR_ANY) |
106 | return 1; | ||
107 | |||
108 | if (addr_type2 == IPV6_ADDR_ANY && match_wildcard && | ||
93 | !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) | 109 | !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) |
94 | return 1; | 110 | return 1; |
95 | 111 | ||
96 | if (addr_type == IPV6_ADDR_ANY && | 112 | if (addr_type == IPV6_ADDR_ANY && match_wildcard && |
97 | !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED)) | 113 | !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED)) |
98 | return 1; | 114 | return 1; |
99 | 115 | ||
@@ -235,7 +251,8 @@ static inline int compute_score2(struct sock *sk, struct net *net, | |||
235 | static struct sock *udp6_lib_lookup2(struct net *net, | 251 | static struct sock *udp6_lib_lookup2(struct net *net, |
236 | const struct in6_addr *saddr, __be16 sport, | 252 | const struct in6_addr *saddr, __be16 sport, |
237 | const struct in6_addr *daddr, unsigned int hnum, int dif, | 253 | const struct in6_addr *daddr, unsigned int hnum, int dif, |
238 | struct udp_hslot *hslot2, unsigned int slot2) | 254 | struct udp_hslot *hslot2, unsigned int slot2, |
255 | struct sk_buff *skb) | ||
239 | { | 256 | { |
240 | struct sock *sk, *result; | 257 | struct sock *sk, *result; |
241 | struct hlist_nulls_node *node; | 258 | struct hlist_nulls_node *node; |
@@ -253,8 +270,15 @@ begin: | |||
253 | badness = score; | 270 | badness = score; |
254 | reuseport = sk->sk_reuseport; | 271 | reuseport = sk->sk_reuseport; |
255 | if (reuseport) { | 272 | if (reuseport) { |
273 | struct sock *sk2; | ||
256 | hash = udp6_ehashfn(net, daddr, hnum, | 274 | hash = udp6_ehashfn(net, daddr, hnum, |
257 | saddr, sport); | 275 | saddr, sport); |
276 | sk2 = reuseport_select_sock(sk, hash, skb, | ||
277 | sizeof(struct udphdr)); | ||
278 | if (sk2) { | ||
279 | result = sk2; | ||
280 | goto found; | ||
281 | } | ||
258 | matches = 1; | 282 | matches = 1; |
259 | } | 283 | } |
260 | } else if (score == badness && reuseport) { | 284 | } else if (score == badness && reuseport) { |
@@ -273,6 +297,7 @@ begin: | |||
273 | goto begin; | 297 | goto begin; |
274 | 298 | ||
275 | if (result) { | 299 | if (result) { |
300 | found: | ||
276 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) | 301 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) |
277 | result = NULL; | 302 | result = NULL; |
278 | else if (unlikely(compute_score2(result, net, saddr, sport, | 303 | else if (unlikely(compute_score2(result, net, saddr, sport, |
@@ -287,7 +312,8 @@ begin: | |||
287 | struct sock *__udp6_lib_lookup(struct net *net, | 312 | struct sock *__udp6_lib_lookup(struct net *net, |
288 | const struct in6_addr *saddr, __be16 sport, | 313 | const struct in6_addr *saddr, __be16 sport, |
289 | const struct in6_addr *daddr, __be16 dport, | 314 | const struct in6_addr *daddr, __be16 dport, |
290 | int dif, struct udp_table *udptable) | 315 | int dif, struct udp_table *udptable, |
316 | struct sk_buff *skb) | ||
291 | { | 317 | { |
292 | struct sock *sk, *result; | 318 | struct sock *sk, *result; |
293 | struct hlist_nulls_node *node; | 319 | struct hlist_nulls_node *node; |
@@ -307,7 +333,7 @@ struct sock *__udp6_lib_lookup(struct net *net, | |||
307 | 333 | ||
308 | result = udp6_lib_lookup2(net, saddr, sport, | 334 | result = udp6_lib_lookup2(net, saddr, sport, |
309 | daddr, hnum, dif, | 335 | daddr, hnum, dif, |
310 | hslot2, slot2); | 336 | hslot2, slot2, skb); |
311 | if (!result) { | 337 | if (!result) { |
312 | hash2 = udp6_portaddr_hash(net, &in6addr_any, hnum); | 338 | hash2 = udp6_portaddr_hash(net, &in6addr_any, hnum); |
313 | slot2 = hash2 & udptable->mask; | 339 | slot2 = hash2 & udptable->mask; |
@@ -317,7 +343,7 @@ struct sock *__udp6_lib_lookup(struct net *net, | |||
317 | 343 | ||
318 | result = udp6_lib_lookup2(net, saddr, sport, | 344 | result = udp6_lib_lookup2(net, saddr, sport, |
319 | &in6addr_any, hnum, dif, | 345 | &in6addr_any, hnum, dif, |
320 | hslot2, slot2); | 346 | hslot2, slot2, skb); |
321 | } | 347 | } |
322 | rcu_read_unlock(); | 348 | rcu_read_unlock(); |
323 | return result; | 349 | return result; |
@@ -332,8 +358,15 @@ begin: | |||
332 | badness = score; | 358 | badness = score; |
333 | reuseport = sk->sk_reuseport; | 359 | reuseport = sk->sk_reuseport; |
334 | if (reuseport) { | 360 | if (reuseport) { |
361 | struct sock *sk2; | ||
335 | hash = udp6_ehashfn(net, daddr, hnum, | 362 | hash = udp6_ehashfn(net, daddr, hnum, |
336 | saddr, sport); | 363 | saddr, sport); |
364 | sk2 = reuseport_select_sock(sk, hash, skb, | ||
365 | sizeof(struct udphdr)); | ||
366 | if (sk2) { | ||
367 | result = sk2; | ||
368 | goto found; | ||
369 | } | ||
337 | matches = 1; | 370 | matches = 1; |
338 | } | 371 | } |
339 | } else if (score == badness && reuseport) { | 372 | } else if (score == badness && reuseport) { |
@@ -352,6 +385,7 @@ begin: | |||
352 | goto begin; | 385 | goto begin; |
353 | 386 | ||
354 | if (result) { | 387 | if (result) { |
388 | found: | ||
355 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) | 389 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) |
356 | result = NULL; | 390 | result = NULL; |
357 | else if (unlikely(compute_score(result, net, hnum, saddr, sport, | 391 | else if (unlikely(compute_score(result, net, hnum, saddr, sport, |
@@ -377,13 +411,13 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, | |||
377 | return sk; | 411 | return sk; |
378 | return __udp6_lib_lookup(dev_net(skb_dst(skb)->dev), &iph->saddr, sport, | 412 | return __udp6_lib_lookup(dev_net(skb_dst(skb)->dev), &iph->saddr, sport, |
379 | &iph->daddr, dport, inet6_iif(skb), | 413 | &iph->daddr, dport, inet6_iif(skb), |
380 | udptable); | 414 | udptable, skb); |
381 | } | 415 | } |
382 | 416 | ||
383 | struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, | 417 | struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, |
384 | const struct in6_addr *daddr, __be16 dport, int dif) | 418 | const struct in6_addr *daddr, __be16 dport, int dif) |
385 | { | 419 | { |
386 | return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table); | 420 | return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table, NULL); |
387 | } | 421 | } |
388 | EXPORT_SYMBOL_GPL(udp6_lib_lookup); | 422 | EXPORT_SYMBOL_GPL(udp6_lib_lookup); |
389 | 423 | ||
@@ -402,6 +436,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, | |||
402 | int peeked, off = 0; | 436 | int peeked, off = 0; |
403 | int err; | 437 | int err; |
404 | int is_udplite = IS_UDPLITE(sk); | 438 | int is_udplite = IS_UDPLITE(sk); |
439 | bool checksum_valid = false; | ||
405 | int is_udp4; | 440 | int is_udp4; |
406 | bool slow; | 441 | bool slow; |
407 | 442 | ||
@@ -433,11 +468,12 @@ try_again: | |||
433 | */ | 468 | */ |
434 | 469 | ||
435 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { | 470 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { |
436 | if (udp_lib_checksum_complete(skb)) | 471 | checksum_valid = !udp_lib_checksum_complete(skb); |
472 | if (!checksum_valid) | ||
437 | goto csum_copy_err; | 473 | goto csum_copy_err; |
438 | } | 474 | } |
439 | 475 | ||
440 | if (skb_csum_unnecessary(skb)) | 476 | if (checksum_valid || skb_csum_unnecessary(skb)) |
441 | err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), | 477 | err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), |
442 | msg, copied); | 478 | msg, copied); |
443 | else { | 479 | else { |
@@ -547,8 +583,8 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
547 | int err; | 583 | int err; |
548 | struct net *net = dev_net(skb->dev); | 584 | struct net *net = dev_net(skb->dev); |
549 | 585 | ||
550 | sk = __udp6_lib_lookup(net, daddr, uh->dest, | 586 | sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source, |
551 | saddr, uh->source, inet6_iif(skb), udptable); | 587 | inet6_iif(skb), udptable, skb); |
552 | if (!sk) { | 588 | if (!sk) { |
553 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), | 589 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), |
554 | ICMP6_MIB_INERRORS); | 590 | ICMP6_MIB_INERRORS); |
@@ -1110,6 +1146,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
1110 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); | 1146 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); |
1111 | struct in6_addr *daddr, *final_p, final; | 1147 | struct in6_addr *daddr, *final_p, final; |
1112 | struct ipv6_txoptions *opt = NULL; | 1148 | struct ipv6_txoptions *opt = NULL; |
1149 | struct ipv6_txoptions *opt_to_free = NULL; | ||
1113 | struct ip6_flowlabel *flowlabel = NULL; | 1150 | struct ip6_flowlabel *flowlabel = NULL; |
1114 | struct flowi6 fl6; | 1151 | struct flowi6 fl6; |
1115 | struct dst_entry *dst; | 1152 | struct dst_entry *dst; |
@@ -1263,8 +1300,10 @@ do_udp_sendmsg: | |||
1263 | opt = NULL; | 1300 | opt = NULL; |
1264 | connected = 0; | 1301 | connected = 0; |
1265 | } | 1302 | } |
1266 | if (!opt) | 1303 | if (!opt) { |
1267 | opt = np->opt; | 1304 | opt = txopt_get(np); |
1305 | opt_to_free = opt; | ||
1306 | } | ||
1268 | if (flowlabel) | 1307 | if (flowlabel) |
1269 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 1308 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
1270 | opt = ipv6_fixup_options(&opt_space, opt); | 1309 | opt = ipv6_fixup_options(&opt_space, opt); |
@@ -1373,6 +1412,7 @@ release_dst: | |||
1373 | out: | 1412 | out: |
1374 | dst_release(dst); | 1413 | dst_release(dst); |
1375 | fl6_sock_release(flowlabel); | 1414 | fl6_sock_release(flowlabel); |
1415 | txopt_put(opt_to_free); | ||
1376 | if (!err) | 1416 | if (!err) |
1377 | return len; | 1417 | return len; |
1378 | /* | 1418 | /* |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 5643423fe67a..c074771a10f7 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -279,7 +279,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
279 | xfrm_dst_ifdown(dst, dev); | 279 | xfrm_dst_ifdown(dst, dev); |
280 | } | 280 | } |
281 | 281 | ||
282 | static struct dst_ops xfrm6_dst_ops = { | 282 | static struct dst_ops xfrm6_dst_ops_template = { |
283 | .family = AF_INET6, | 283 | .family = AF_INET6, |
284 | .gc = xfrm6_garbage_collect, | 284 | .gc = xfrm6_garbage_collect, |
285 | .update_pmtu = xfrm6_update_pmtu, | 285 | .update_pmtu = xfrm6_update_pmtu, |
@@ -293,7 +293,7 @@ static struct dst_ops xfrm6_dst_ops = { | |||
293 | 293 | ||
294 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | 294 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { |
295 | .family = AF_INET6, | 295 | .family = AF_INET6, |
296 | .dst_ops = &xfrm6_dst_ops, | 296 | .dst_ops = &xfrm6_dst_ops_template, |
297 | .dst_lookup = xfrm6_dst_lookup, | 297 | .dst_lookup = xfrm6_dst_lookup, |
298 | .get_saddr = xfrm6_get_saddr, | 298 | .get_saddr = xfrm6_get_saddr, |
299 | .decode_session = _decode_session6, | 299 | .decode_session = _decode_session6, |
@@ -325,7 +325,7 @@ static struct ctl_table xfrm6_policy_table[] = { | |||
325 | { } | 325 | { } |
326 | }; | 326 | }; |
327 | 327 | ||
328 | static int __net_init xfrm6_net_init(struct net *net) | 328 | static int __net_init xfrm6_net_sysctl_init(struct net *net) |
329 | { | 329 | { |
330 | struct ctl_table *table; | 330 | struct ctl_table *table; |
331 | struct ctl_table_header *hdr; | 331 | struct ctl_table_header *hdr; |
@@ -353,7 +353,7 @@ err_alloc: | |||
353 | return -ENOMEM; | 353 | return -ENOMEM; |
354 | } | 354 | } |
355 | 355 | ||
356 | static void __net_exit xfrm6_net_exit(struct net *net) | 356 | static void __net_exit xfrm6_net_sysctl_exit(struct net *net) |
357 | { | 357 | { |
358 | struct ctl_table *table; | 358 | struct ctl_table *table; |
359 | 359 | ||
@@ -365,24 +365,52 @@ static void __net_exit xfrm6_net_exit(struct net *net) | |||
365 | if (!net_eq(net, &init_net)) | 365 | if (!net_eq(net, &init_net)) |
366 | kfree(table); | 366 | kfree(table); |
367 | } | 367 | } |
368 | #else /* CONFIG_SYSCTL */ | ||
369 | static int inline xfrm6_net_sysctl_init(struct net *net) | ||
370 | { | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static void inline xfrm6_net_sysctl_exit(struct net *net) | ||
375 | { | ||
376 | } | ||
377 | #endif | ||
378 | |||
379 | static int __net_init xfrm6_net_init(struct net *net) | ||
380 | { | ||
381 | int ret; | ||
382 | |||
383 | memcpy(&net->xfrm.xfrm6_dst_ops, &xfrm6_dst_ops_template, | ||
384 | sizeof(xfrm6_dst_ops_template)); | ||
385 | ret = dst_entries_init(&net->xfrm.xfrm6_dst_ops); | ||
386 | if (ret) | ||
387 | return ret; | ||
388 | |||
389 | ret = xfrm6_net_sysctl_init(net); | ||
390 | if (ret) | ||
391 | dst_entries_destroy(&net->xfrm.xfrm6_dst_ops); | ||
392 | |||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | static void __net_exit xfrm6_net_exit(struct net *net) | ||
397 | { | ||
398 | xfrm6_net_sysctl_exit(net); | ||
399 | dst_entries_destroy(&net->xfrm.xfrm6_dst_ops); | ||
400 | } | ||
368 | 401 | ||
369 | static struct pernet_operations xfrm6_net_ops = { | 402 | static struct pernet_operations xfrm6_net_ops = { |
370 | .init = xfrm6_net_init, | 403 | .init = xfrm6_net_init, |
371 | .exit = xfrm6_net_exit, | 404 | .exit = xfrm6_net_exit, |
372 | }; | 405 | }; |
373 | #endif | ||
374 | 406 | ||
375 | int __init xfrm6_init(void) | 407 | int __init xfrm6_init(void) |
376 | { | 408 | { |
377 | int ret; | 409 | int ret; |
378 | 410 | ||
379 | dst_entries_init(&xfrm6_dst_ops); | ||
380 | |||
381 | ret = xfrm6_policy_init(); | 411 | ret = xfrm6_policy_init(); |
382 | if (ret) { | 412 | if (ret) |
383 | dst_entries_destroy(&xfrm6_dst_ops); | ||
384 | goto out; | 413 | goto out; |
385 | } | ||
386 | ret = xfrm6_state_init(); | 414 | ret = xfrm6_state_init(); |
387 | if (ret) | 415 | if (ret) |
388 | goto out_policy; | 416 | goto out_policy; |
@@ -391,9 +419,7 @@ int __init xfrm6_init(void) | |||
391 | if (ret) | 419 | if (ret) |
392 | goto out_state; | 420 | goto out_state; |
393 | 421 | ||
394 | #ifdef CONFIG_SYSCTL | ||
395 | register_pernet_subsys(&xfrm6_net_ops); | 422 | register_pernet_subsys(&xfrm6_net_ops); |
396 | #endif | ||
397 | out: | 423 | out: |
398 | return ret; | 424 | return ret; |
399 | out_state: | 425 | out_state: |
@@ -405,11 +431,8 @@ out_policy: | |||
405 | 431 | ||
406 | void xfrm6_fini(void) | 432 | void xfrm6_fini(void) |
407 | { | 433 | { |
408 | #ifdef CONFIG_SYSCTL | ||
409 | unregister_pernet_subsys(&xfrm6_net_ops); | 434 | unregister_pernet_subsys(&xfrm6_net_ops); |
410 | #endif | ||
411 | xfrm6_protocol_fini(); | 435 | xfrm6_protocol_fini(); |
412 | xfrm6_policy_fini(); | 436 | xfrm6_policy_fini(); |
413 | xfrm6_state_fini(); | 437 | xfrm6_state_fini(); |
414 | dst_entries_destroy(&xfrm6_dst_ops); | ||
415 | } | 438 | } |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index e6aa48b5395c..923abd6b3064 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -1086,6 +1086,9 @@ static int irda_create(struct net *net, struct socket *sock, int protocol, | |||
1086 | struct sock *sk; | 1086 | struct sock *sk; |
1087 | struct irda_sock *self; | 1087 | struct irda_sock *self; |
1088 | 1088 | ||
1089 | if (protocol < 0 || protocol > SK_PROTOCOL_MAX) | ||
1090 | return -EINVAL; | ||
1091 | |||
1089 | if (net != &init_net) | 1092 | if (net != &init_net) |
1090 | return -EAFNOSUPPORT; | 1093 | return -EAFNOSUPPORT; |
1091 | 1094 | ||
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index fcb2752419c6..ef50a94d3eb7 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -303,7 +303,7 @@ static void iucv_sock_wake_msglim(struct sock *sk) | |||
303 | 303 | ||
304 | rcu_read_lock(); | 304 | rcu_read_lock(); |
305 | wq = rcu_dereference(sk->sk_wq); | 305 | wq = rcu_dereference(sk->sk_wq); |
306 | if (wq_has_sleeper(wq)) | 306 | if (skwq_has_sleeper(wq)) |
307 | wake_up_interruptible_all(&wq->wait); | 307 | wake_up_interruptible_all(&wq->wait); |
308 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 308 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
309 | rcu_read_unlock(); | 309 | rcu_read_unlock(); |
@@ -1031,7 +1031,7 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1031 | struct sock *sk = sock->sk; | 1031 | struct sock *sk = sock->sk; |
1032 | struct iucv_sock *iucv = iucv_sk(sk); | 1032 | struct iucv_sock *iucv = iucv_sk(sk); |
1033 | struct sk_buff *skb; | 1033 | struct sk_buff *skb; |
1034 | struct iucv_message txmsg; | 1034 | struct iucv_message txmsg = {0}; |
1035 | struct cmsghdr *cmsg; | 1035 | struct cmsghdr *cmsg; |
1036 | int cmsg_done; | 1036 | int cmsg_done; |
1037 | long timeo; | 1037 | long timeo; |
@@ -1483,7 +1483,7 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, | |||
1483 | if (sock_writeable(sk) && iucv_below_msglim(sk)) | 1483 | if (sock_writeable(sk) && iucv_below_msglim(sk)) |
1484 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | 1484 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; |
1485 | else | 1485 | else |
1486 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 1486 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
1487 | 1487 | ||
1488 | return mask; | 1488 | return mask; |
1489 | } | 1489 | } |
@@ -2084,11 +2084,7 @@ static int afiucv_hs_callback_rx(struct sock *sk, struct sk_buff *skb) | |||
2084 | return NET_RX_SUCCESS; | 2084 | return NET_RX_SUCCESS; |
2085 | } | 2085 | } |
2086 | 2086 | ||
2087 | /* write stuff from iucv_msg to skb cb */ | 2087 | /* write stuff from iucv_msg to skb cb */ |
2088 | if (skb->len < sizeof(struct af_iucv_trans_hdr)) { | ||
2089 | kfree_skb(skb); | ||
2090 | return NET_RX_SUCCESS; | ||
2091 | } | ||
2092 | skb_pull(skb, sizeof(struct af_iucv_trans_hdr)); | 2088 | skb_pull(skb, sizeof(struct af_iucv_trans_hdr)); |
2093 | skb_reset_transport_header(skb); | 2089 | skb_reset_transport_header(skb); |
2094 | skb_reset_network_header(skb); | 2090 | skb_reset_network_header(skb); |
@@ -2119,6 +2115,20 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, | |||
2119 | char nullstring[8]; | 2115 | char nullstring[8]; |
2120 | int err = 0; | 2116 | int err = 0; |
2121 | 2117 | ||
2118 | if (skb->len < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) { | ||
2119 | WARN_ONCE(1, "AF_IUCV too short skb, len=%d, min=%d", | ||
2120 | (int)skb->len, | ||
2121 | (int)(ETH_HLEN + sizeof(struct af_iucv_trans_hdr))); | ||
2122 | kfree_skb(skb); | ||
2123 | return NET_RX_SUCCESS; | ||
2124 | } | ||
2125 | if (skb_headlen(skb) < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) | ||
2126 | if (skb_linearize(skb)) { | ||
2127 | WARN_ONCE(1, "AF_IUCV skb_linearize failed, len=%d", | ||
2128 | (int)skb->len); | ||
2129 | kfree_skb(skb); | ||
2130 | return NET_RX_SUCCESS; | ||
2131 | } | ||
2122 | skb_pull(skb, ETH_HLEN); | 2132 | skb_pull(skb, ETH_HLEN); |
2123 | trans_hdr = (struct af_iucv_trans_hdr *)skb->data; | 2133 | trans_hdr = (struct af_iucv_trans_hdr *)skb->data; |
2124 | EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName)); | 2134 | EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName)); |
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index aca38d8aed8e..a2c8747d2936 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c | |||
@@ -486,6 +486,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
486 | DECLARE_SOCKADDR(struct sockaddr_l2tpip6 *, lsa, msg->msg_name); | 486 | DECLARE_SOCKADDR(struct sockaddr_l2tpip6 *, lsa, msg->msg_name); |
487 | struct in6_addr *daddr, *final_p, final; | 487 | struct in6_addr *daddr, *final_p, final; |
488 | struct ipv6_pinfo *np = inet6_sk(sk); | 488 | struct ipv6_pinfo *np = inet6_sk(sk); |
489 | struct ipv6_txoptions *opt_to_free = NULL; | ||
489 | struct ipv6_txoptions *opt = NULL; | 490 | struct ipv6_txoptions *opt = NULL; |
490 | struct ip6_flowlabel *flowlabel = NULL; | 491 | struct ip6_flowlabel *flowlabel = NULL; |
491 | struct dst_entry *dst = NULL; | 492 | struct dst_entry *dst = NULL; |
@@ -575,8 +576,10 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
575 | opt = NULL; | 576 | opt = NULL; |
576 | } | 577 | } |
577 | 578 | ||
578 | if (opt == NULL) | 579 | if (!opt) { |
579 | opt = np->opt; | 580 | opt = txopt_get(np); |
581 | opt_to_free = opt; | ||
582 | } | ||
580 | if (flowlabel) | 583 | if (flowlabel) |
581 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 584 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
582 | opt = ipv6_fixup_options(&opt_space, opt); | 585 | opt = ipv6_fixup_options(&opt_space, opt); |
@@ -631,6 +634,7 @@ done: | |||
631 | dst_release(dst); | 634 | dst_release(dst); |
632 | out: | 635 | out: |
633 | fl6_sock_release(flowlabel); | 636 | fl6_sock_release(flowlabel); |
637 | txopt_put(opt_to_free); | ||
634 | 638 | ||
635 | return err < 0 ? err : len; | 639 | return err < 0 ? err : len; |
636 | 640 | ||
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 1ad18c55064c..652c250b9a3b 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
@@ -230,26 +230,11 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int | |||
230 | 230 | ||
231 | if (sk->sk_state & PPPOX_BOUND) { | 231 | if (sk->sk_state & PPPOX_BOUND) { |
232 | struct pppox_sock *po; | 232 | struct pppox_sock *po; |
233 | |||
233 | l2tp_dbg(session, PPPOL2TP_MSG_DATA, | 234 | l2tp_dbg(session, PPPOL2TP_MSG_DATA, |
234 | "%s: recv %d byte data frame, passing to ppp\n", | 235 | "%s: recv %d byte data frame, passing to ppp\n", |
235 | session->name, data_len); | 236 | session->name, data_len); |
236 | 237 | ||
237 | /* We need to forget all info related to the L2TP packet | ||
238 | * gathered in the skb as we are going to reuse the same | ||
239 | * skb for the inner packet. | ||
240 | * Namely we need to: | ||
241 | * - reset xfrm (IPSec) information as it applies to | ||
242 | * the outer L2TP packet and not to the inner one | ||
243 | * - release the dst to force a route lookup on the inner | ||
244 | * IP packet since skb->dst currently points to the dst | ||
245 | * of the UDP tunnel | ||
246 | * - reset netfilter information as it doesn't apply | ||
247 | * to the inner packet either | ||
248 | */ | ||
249 | secpath_reset(skb); | ||
250 | skb_dst_drop(skb); | ||
251 | nf_reset(skb); | ||
252 | |||
253 | po = pppox_sk(sk); | 238 | po = pppox_sk(sk); |
254 | ppp_input(&po->chan, skb); | 239 | ppp_input(&po->chan, skb); |
255 | } else { | 240 | } else { |
@@ -1862,5 +1847,5 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | |||
1862 | MODULE_DESCRIPTION("PPP over L2TP over UDP"); | 1847 | MODULE_DESCRIPTION("PPP over L2TP over UDP"); |
1863 | MODULE_LICENSE("GPL"); | 1848 | MODULE_LICENSE("GPL"); |
1864 | MODULE_VERSION(PPPOL2TP_DRV_VERSION); | 1849 | MODULE_VERSION(PPPOL2TP_DRV_VERSION); |
1865 | MODULE_ALIAS("pppox-proto-" __stringify(PX_PROTO_OL2TP)); | 1850 | MODULE_ALIAS_NET_PF_PROTO(PF_PPPOX, PX_PROTO_OL2TP); |
1866 | MODULE_ALIAS_L2TP_PWTYPE(11); | 1851 | MODULE_ALIAS_L2TP_PWTYPE(11); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index a758eb84e8f0..ff757181b0a8 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -500,7 +500,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
500 | /* send AddBA request */ | 500 | /* send AddBA request */ |
501 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | 501 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
502 | tid_tx->dialog_token, start_seq_num, | 502 | tid_tx->dialog_token, start_seq_num, |
503 | local->hw.max_tx_aggregation_subframes, | 503 | IEEE80211_MAX_AMPDU_BUF, |
504 | tid_tx->timeout); | 504 | tid_tx->timeout); |
505 | } | 505 | } |
506 | 506 | ||
@@ -926,6 +926,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
926 | amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; | 926 | amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; |
927 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 927 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
928 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | 928 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; |
929 | buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes); | ||
929 | 930 | ||
930 | mutex_lock(&sta->ampdu_mlme.mtx); | 931 | mutex_lock(&sta->ampdu_mlme.mtx); |
931 | 932 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c2bd1b6a6922..166a29fe6c35 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1169,8 +1169,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1169 | * rc isn't initialized here yet, so ignore it | 1169 | * rc isn't initialized here yet, so ignore it |
1170 | */ | 1170 | */ |
1171 | __ieee80211_vht_handle_opmode(sdata, sta, | 1171 | __ieee80211_vht_handle_opmode(sdata, sta, |
1172 | params->opmode_notif, | 1172 | params->opmode_notif, band); |
1173 | band, false); | ||
1174 | } | 1173 | } |
1175 | 1174 | ||
1176 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1175 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
@@ -1216,16 +1215,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1216 | if (!sta) | 1215 | if (!sta) |
1217 | return -ENOMEM; | 1216 | return -ENOMEM; |
1218 | 1217 | ||
1219 | /* | ||
1220 | * defaults -- if userspace wants something else we'll | ||
1221 | * change it accordingly in sta_apply_parameters() | ||
1222 | */ | ||
1223 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && | ||
1224 | !(params->sta_flags_set & (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1225 | BIT(NL80211_STA_FLAG_ASSOCIATED)))) { | ||
1226 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | ||
1227 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | ||
1228 | } | ||
1229 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 1218 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) |
1230 | sta->sta.tdls = true; | 1219 | sta->sta.tdls = true; |
1231 | 1220 | ||
@@ -1994,6 +1983,11 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1994 | return ieee80211_request_scan(sdata, req); | 1983 | return ieee80211_request_scan(sdata, req); |
1995 | } | 1984 | } |
1996 | 1985 | ||
1986 | static void ieee80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev) | ||
1987 | { | ||
1988 | ieee80211_scan_cancel(wiphy_priv(wiphy)); | ||
1989 | } | ||
1990 | |||
1997 | static int | 1991 | static int |
1998 | ieee80211_sched_scan_start(struct wiphy *wiphy, | 1992 | ieee80211_sched_scan_start(struct wiphy *wiphy, |
1999 | struct net_device *dev, | 1993 | struct net_device *dev, |
@@ -2509,294 +2503,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
2509 | return 0; | 2503 | return 0; |
2510 | } | 2504 | } |
2511 | 2505 | ||
2512 | static bool ieee80211_coalesce_started_roc(struct ieee80211_local *local, | ||
2513 | struct ieee80211_roc_work *new_roc, | ||
2514 | struct ieee80211_roc_work *cur_roc) | ||
2515 | { | ||
2516 | unsigned long now = jiffies; | ||
2517 | unsigned long remaining = cur_roc->hw_start_time + | ||
2518 | msecs_to_jiffies(cur_roc->duration) - | ||
2519 | now; | ||
2520 | |||
2521 | if (WARN_ON(!cur_roc->started || !cur_roc->hw_begun)) | ||
2522 | return false; | ||
2523 | |||
2524 | /* if it doesn't fit entirely, schedule a new one */ | ||
2525 | if (new_roc->duration > jiffies_to_msecs(remaining)) | ||
2526 | return false; | ||
2527 | |||
2528 | ieee80211_handle_roc_started(new_roc); | ||
2529 | |||
2530 | /* add to dependents so we send the expired event properly */ | ||
2531 | list_add_tail(&new_roc->list, &cur_roc->dependents); | ||
2532 | return true; | ||
2533 | } | ||
2534 | |||
2535 | static u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local) | ||
2536 | { | ||
2537 | lockdep_assert_held(&local->mtx); | ||
2538 | |||
2539 | local->roc_cookie_counter++; | ||
2540 | |||
2541 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
2542 | if (WARN_ON(local->roc_cookie_counter == 0)) | ||
2543 | local->roc_cookie_counter++; | ||
2544 | |||
2545 | return local->roc_cookie_counter; | ||
2546 | } | ||
2547 | |||
2548 | static int ieee80211_start_roc_work(struct ieee80211_local *local, | ||
2549 | struct ieee80211_sub_if_data *sdata, | ||
2550 | struct ieee80211_channel *channel, | ||
2551 | unsigned int duration, u64 *cookie, | ||
2552 | struct sk_buff *txskb, | ||
2553 | enum ieee80211_roc_type type) | ||
2554 | { | ||
2555 | struct ieee80211_roc_work *roc, *tmp; | ||
2556 | bool queued = false; | ||
2557 | int ret; | ||
2558 | |||
2559 | lockdep_assert_held(&local->mtx); | ||
2560 | |||
2561 | if (local->use_chanctx && !local->ops->remain_on_channel) | ||
2562 | return -EOPNOTSUPP; | ||
2563 | |||
2564 | roc = kzalloc(sizeof(*roc), GFP_KERNEL); | ||
2565 | if (!roc) | ||
2566 | return -ENOMEM; | ||
2567 | |||
2568 | /* | ||
2569 | * If the duration is zero, then the driver | ||
2570 | * wouldn't actually do anything. Set it to | ||
2571 | * 10 for now. | ||
2572 | * | ||
2573 | * TODO: cancel the off-channel operation | ||
2574 | * when we get the SKB's TX status and | ||
2575 | * the wait time was zero before. | ||
2576 | */ | ||
2577 | if (!duration) | ||
2578 | duration = 10; | ||
2579 | |||
2580 | roc->chan = channel; | ||
2581 | roc->duration = duration; | ||
2582 | roc->req_duration = duration; | ||
2583 | roc->frame = txskb; | ||
2584 | roc->type = type; | ||
2585 | roc->sdata = sdata; | ||
2586 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); | ||
2587 | INIT_LIST_HEAD(&roc->dependents); | ||
2588 | |||
2589 | /* | ||
2590 | * cookie is either the roc cookie (for normal roc) | ||
2591 | * or the SKB (for mgmt TX) | ||
2592 | */ | ||
2593 | if (!txskb) { | ||
2594 | roc->cookie = ieee80211_mgmt_tx_cookie(local); | ||
2595 | *cookie = roc->cookie; | ||
2596 | } else { | ||
2597 | roc->mgmt_tx_cookie = *cookie; | ||
2598 | } | ||
2599 | |||
2600 | /* if there's one pending or we're scanning, queue this one */ | ||
2601 | if (!list_empty(&local->roc_list) || | ||
2602 | local->scanning || ieee80211_is_radar_required(local)) | ||
2603 | goto out_check_combine; | ||
2604 | |||
2605 | /* if not HW assist, just queue & schedule work */ | ||
2606 | if (!local->ops->remain_on_channel) { | ||
2607 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); | ||
2608 | goto out_queue; | ||
2609 | } | ||
2610 | |||
2611 | /* otherwise actually kick it off here (for error handling) */ | ||
2612 | |||
2613 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); | ||
2614 | if (ret) { | ||
2615 | kfree(roc); | ||
2616 | return ret; | ||
2617 | } | ||
2618 | |||
2619 | roc->started = true; | ||
2620 | goto out_queue; | ||
2621 | |||
2622 | out_check_combine: | ||
2623 | list_for_each_entry(tmp, &local->roc_list, list) { | ||
2624 | if (tmp->chan != channel || tmp->sdata != sdata) | ||
2625 | continue; | ||
2626 | |||
2627 | /* | ||
2628 | * Extend this ROC if possible: | ||
2629 | * | ||
2630 | * If it hasn't started yet, just increase the duration | ||
2631 | * and add the new one to the list of dependents. | ||
2632 | * If the type of the new ROC has higher priority, modify the | ||
2633 | * type of the previous one to match that of the new one. | ||
2634 | */ | ||
2635 | if (!tmp->started) { | ||
2636 | list_add_tail(&roc->list, &tmp->dependents); | ||
2637 | tmp->duration = max(tmp->duration, roc->duration); | ||
2638 | tmp->type = max(tmp->type, roc->type); | ||
2639 | queued = true; | ||
2640 | break; | ||
2641 | } | ||
2642 | |||
2643 | /* If it has already started, it's more difficult ... */ | ||
2644 | if (local->ops->remain_on_channel) { | ||
2645 | /* | ||
2646 | * In the offloaded ROC case, if it hasn't begun, add | ||
2647 | * this new one to the dependent list to be handled | ||
2648 | * when the master one begins. If it has begun, | ||
2649 | * check if it fits entirely within the existing one, | ||
2650 | * in which case it will just be dependent as well. | ||
2651 | * Otherwise, schedule it by itself. | ||
2652 | */ | ||
2653 | if (!tmp->hw_begun) { | ||
2654 | list_add_tail(&roc->list, &tmp->dependents); | ||
2655 | queued = true; | ||
2656 | break; | ||
2657 | } | ||
2658 | |||
2659 | if (ieee80211_coalesce_started_roc(local, roc, tmp)) | ||
2660 | queued = true; | ||
2661 | } else if (del_timer_sync(&tmp->work.timer)) { | ||
2662 | unsigned long new_end; | ||
2663 | |||
2664 | /* | ||
2665 | * In the software ROC case, cancel the timer, if | ||
2666 | * that fails then the finish work is already | ||
2667 | * queued/pending and thus we queue the new ROC | ||
2668 | * normally, if that succeeds then we can extend | ||
2669 | * the timer duration and TX the frame (if any.) | ||
2670 | */ | ||
2671 | |||
2672 | list_add_tail(&roc->list, &tmp->dependents); | ||
2673 | queued = true; | ||
2674 | |||
2675 | new_end = jiffies + msecs_to_jiffies(roc->duration); | ||
2676 | |||
2677 | /* ok, it was started & we canceled timer */ | ||
2678 | if (time_after(new_end, tmp->work.timer.expires)) | ||
2679 | mod_timer(&tmp->work.timer, new_end); | ||
2680 | else | ||
2681 | add_timer(&tmp->work.timer); | ||
2682 | |||
2683 | ieee80211_handle_roc_started(roc); | ||
2684 | } | ||
2685 | break; | ||
2686 | } | ||
2687 | |||
2688 | out_queue: | ||
2689 | if (!queued) | ||
2690 | list_add_tail(&roc->list, &local->roc_list); | ||
2691 | |||
2692 | return 0; | ||
2693 | } | ||
2694 | |||
2695 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | ||
2696 | struct wireless_dev *wdev, | ||
2697 | struct ieee80211_channel *chan, | ||
2698 | unsigned int duration, | ||
2699 | u64 *cookie) | ||
2700 | { | ||
2701 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
2702 | struct ieee80211_local *local = sdata->local; | ||
2703 | int ret; | ||
2704 | |||
2705 | mutex_lock(&local->mtx); | ||
2706 | ret = ieee80211_start_roc_work(local, sdata, chan, | ||
2707 | duration, cookie, NULL, | ||
2708 | IEEE80211_ROC_TYPE_NORMAL); | ||
2709 | mutex_unlock(&local->mtx); | ||
2710 | |||
2711 | return ret; | ||
2712 | } | ||
2713 | |||
2714 | static int ieee80211_cancel_roc(struct ieee80211_local *local, | ||
2715 | u64 cookie, bool mgmt_tx) | ||
2716 | { | ||
2717 | struct ieee80211_roc_work *roc, *tmp, *found = NULL; | ||
2718 | int ret; | ||
2719 | |||
2720 | mutex_lock(&local->mtx); | ||
2721 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | ||
2722 | struct ieee80211_roc_work *dep, *tmp2; | ||
2723 | |||
2724 | list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) { | ||
2725 | if (!mgmt_tx && dep->cookie != cookie) | ||
2726 | continue; | ||
2727 | else if (mgmt_tx && dep->mgmt_tx_cookie != cookie) | ||
2728 | continue; | ||
2729 | /* found dependent item -- just remove it */ | ||
2730 | list_del(&dep->list); | ||
2731 | mutex_unlock(&local->mtx); | ||
2732 | |||
2733 | ieee80211_roc_notify_destroy(dep, true); | ||
2734 | return 0; | ||
2735 | } | ||
2736 | |||
2737 | if (!mgmt_tx && roc->cookie != cookie) | ||
2738 | continue; | ||
2739 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) | ||
2740 | continue; | ||
2741 | |||
2742 | found = roc; | ||
2743 | break; | ||
2744 | } | ||
2745 | |||
2746 | if (!found) { | ||
2747 | mutex_unlock(&local->mtx); | ||
2748 | return -ENOENT; | ||
2749 | } | ||
2750 | |||
2751 | /* | ||
2752 | * We found the item to cancel, so do that. Note that it | ||
2753 | * may have dependents, which we also cancel (and send | ||
2754 | * the expired signal for.) Not doing so would be quite | ||
2755 | * tricky here, but we may need to fix it later. | ||
2756 | */ | ||
2757 | |||
2758 | if (local->ops->remain_on_channel) { | ||
2759 | if (found->started) { | ||
2760 | ret = drv_cancel_remain_on_channel(local); | ||
2761 | if (WARN_ON_ONCE(ret)) { | ||
2762 | mutex_unlock(&local->mtx); | ||
2763 | return ret; | ||
2764 | } | ||
2765 | } | ||
2766 | |||
2767 | list_del(&found->list); | ||
2768 | |||
2769 | if (found->started) | ||
2770 | ieee80211_start_next_roc(local); | ||
2771 | mutex_unlock(&local->mtx); | ||
2772 | |||
2773 | ieee80211_roc_notify_destroy(found, true); | ||
2774 | } else { | ||
2775 | /* work may be pending so use it all the time */ | ||
2776 | found->abort = true; | ||
2777 | ieee80211_queue_delayed_work(&local->hw, &found->work, 0); | ||
2778 | |||
2779 | mutex_unlock(&local->mtx); | ||
2780 | |||
2781 | /* work will clean up etc */ | ||
2782 | flush_delayed_work(&found->work); | ||
2783 | WARN_ON(!found->to_be_freed); | ||
2784 | kfree(found); | ||
2785 | } | ||
2786 | |||
2787 | return 0; | ||
2788 | } | ||
2789 | |||
2790 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | ||
2791 | struct wireless_dev *wdev, | ||
2792 | u64 cookie) | ||
2793 | { | ||
2794 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
2795 | struct ieee80211_local *local = sdata->local; | ||
2796 | |||
2797 | return ieee80211_cancel_roc(local, cookie, false); | ||
2798 | } | ||
2799 | |||
2800 | static int ieee80211_start_radar_detection(struct wiphy *wiphy, | 2506 | static int ieee80211_start_radar_detection(struct wiphy *wiphy, |
2801 | struct net_device *dev, | 2507 | struct net_device *dev, |
2802 | struct cfg80211_chan_def *chandef, | 2508 | struct cfg80211_chan_def *chandef, |
@@ -3267,9 +2973,21 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3267 | return err; | 2973 | return err; |
3268 | } | 2974 | } |
3269 | 2975 | ||
3270 | static struct sk_buff *ieee80211_make_ack_skb(struct ieee80211_local *local, | 2976 | u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local) |
3271 | struct sk_buff *skb, u64 *cookie, | 2977 | { |
3272 | gfp_t gfp) | 2978 | lockdep_assert_held(&local->mtx); |
2979 | |||
2980 | local->roc_cookie_counter++; | ||
2981 | |||
2982 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
2983 | if (WARN_ON(local->roc_cookie_counter == 0)) | ||
2984 | local->roc_cookie_counter++; | ||
2985 | |||
2986 | return local->roc_cookie_counter; | ||
2987 | } | ||
2988 | |||
2989 | int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb, | ||
2990 | u64 *cookie, gfp_t gfp) | ||
3273 | { | 2991 | { |
3274 | unsigned long spin_flags; | 2992 | unsigned long spin_flags; |
3275 | struct sk_buff *ack_skb; | 2993 | struct sk_buff *ack_skb; |
@@ -3277,7 +2995,7 @@ static struct sk_buff *ieee80211_make_ack_skb(struct ieee80211_local *local, | |||
3277 | 2995 | ||
3278 | ack_skb = skb_copy(skb, gfp); | 2996 | ack_skb = skb_copy(skb, gfp); |
3279 | if (!ack_skb) | 2997 | if (!ack_skb) |
3280 | return ERR_PTR(-ENOMEM); | 2998 | return -ENOMEM; |
3281 | 2999 | ||
3282 | spin_lock_irqsave(&local->ack_status_lock, spin_flags); | 3000 | spin_lock_irqsave(&local->ack_status_lock, spin_flags); |
3283 | id = idr_alloc(&local->ack_status_frames, ack_skb, | 3001 | id = idr_alloc(&local->ack_status_frames, ack_skb, |
@@ -3286,7 +3004,7 @@ static struct sk_buff *ieee80211_make_ack_skb(struct ieee80211_local *local, | |||
3286 | 3004 | ||
3287 | if (id < 0) { | 3005 | if (id < 0) { |
3288 | kfree_skb(ack_skb); | 3006 | kfree_skb(ack_skb); |
3289 | return ERR_PTR(-ENOMEM); | 3007 | return -ENOMEM; |
3290 | } | 3008 | } |
3291 | 3009 | ||
3292 | IEEE80211_SKB_CB(skb)->ack_frame_id = id; | 3010 | IEEE80211_SKB_CB(skb)->ack_frame_id = id; |
@@ -3294,200 +3012,7 @@ static struct sk_buff *ieee80211_make_ack_skb(struct ieee80211_local *local, | |||
3294 | *cookie = ieee80211_mgmt_tx_cookie(local); | 3012 | *cookie = ieee80211_mgmt_tx_cookie(local); |
3295 | IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie; | 3013 | IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie; |
3296 | 3014 | ||
3297 | return ack_skb; | 3015 | return 0; |
3298 | } | ||
3299 | |||
3300 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
3301 | struct cfg80211_mgmt_tx_params *params, | ||
3302 | u64 *cookie) | ||
3303 | { | ||
3304 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
3305 | struct ieee80211_local *local = sdata->local; | ||
3306 | struct sk_buff *skb, *ack_skb; | ||
3307 | struct sta_info *sta; | ||
3308 | const struct ieee80211_mgmt *mgmt = (void *)params->buf; | ||
3309 | bool need_offchan = false; | ||
3310 | u32 flags; | ||
3311 | int ret; | ||
3312 | u8 *data; | ||
3313 | |||
3314 | if (params->dont_wait_for_ack) | ||
3315 | flags = IEEE80211_TX_CTL_NO_ACK; | ||
3316 | else | ||
3317 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | ||
3318 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
3319 | |||
3320 | if (params->no_cck) | ||
3321 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | ||
3322 | |||
3323 | switch (sdata->vif.type) { | ||
3324 | case NL80211_IFTYPE_ADHOC: | ||
3325 | if (!sdata->vif.bss_conf.ibss_joined) | ||
3326 | need_offchan = true; | ||
3327 | /* fall through */ | ||
3328 | #ifdef CONFIG_MAC80211_MESH | ||
3329 | case NL80211_IFTYPE_MESH_POINT: | ||
3330 | if (ieee80211_vif_is_mesh(&sdata->vif) && | ||
3331 | !sdata->u.mesh.mesh_id_len) | ||
3332 | need_offchan = true; | ||
3333 | /* fall through */ | ||
3334 | #endif | ||
3335 | case NL80211_IFTYPE_AP: | ||
3336 | case NL80211_IFTYPE_AP_VLAN: | ||
3337 | case NL80211_IFTYPE_P2P_GO: | ||
3338 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
3339 | !ieee80211_vif_is_mesh(&sdata->vif) && | ||
3340 | !rcu_access_pointer(sdata->bss->beacon)) | ||
3341 | need_offchan = true; | ||
3342 | if (!ieee80211_is_action(mgmt->frame_control) || | ||
3343 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC || | ||
3344 | mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED || | ||
3345 | mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) | ||
3346 | break; | ||
3347 | rcu_read_lock(); | ||
3348 | sta = sta_info_get(sdata, mgmt->da); | ||
3349 | rcu_read_unlock(); | ||
3350 | if (!sta) | ||
3351 | return -ENOLINK; | ||
3352 | break; | ||
3353 | case NL80211_IFTYPE_STATION: | ||
3354 | case NL80211_IFTYPE_P2P_CLIENT: | ||
3355 | sdata_lock(sdata); | ||
3356 | if (!sdata->u.mgd.associated || | ||
3357 | (params->offchan && params->wait && | ||
3358 | local->ops->remain_on_channel && | ||
3359 | memcmp(sdata->u.mgd.associated->bssid, | ||
3360 | mgmt->bssid, ETH_ALEN))) | ||
3361 | need_offchan = true; | ||
3362 | sdata_unlock(sdata); | ||
3363 | break; | ||
3364 | case NL80211_IFTYPE_P2P_DEVICE: | ||
3365 | need_offchan = true; | ||
3366 | break; | ||
3367 | default: | ||
3368 | return -EOPNOTSUPP; | ||
3369 | } | ||
3370 | |||
3371 | /* configurations requiring offchan cannot work if no channel has been | ||
3372 | * specified | ||
3373 | */ | ||
3374 | if (need_offchan && !params->chan) | ||
3375 | return -EINVAL; | ||
3376 | |||
3377 | mutex_lock(&local->mtx); | ||
3378 | |||
3379 | /* Check if the operating channel is the requested channel */ | ||
3380 | if (!need_offchan) { | ||
3381 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3382 | |||
3383 | rcu_read_lock(); | ||
3384 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3385 | |||
3386 | if (chanctx_conf) { | ||
3387 | need_offchan = params->chan && | ||
3388 | (params->chan != | ||
3389 | chanctx_conf->def.chan); | ||
3390 | } else if (!params->chan) { | ||
3391 | ret = -EINVAL; | ||
3392 | rcu_read_unlock(); | ||
3393 | goto out_unlock; | ||
3394 | } else { | ||
3395 | need_offchan = true; | ||
3396 | } | ||
3397 | rcu_read_unlock(); | ||
3398 | } | ||
3399 | |||
3400 | if (need_offchan && !params->offchan) { | ||
3401 | ret = -EBUSY; | ||
3402 | goto out_unlock; | ||
3403 | } | ||
3404 | |||
3405 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + params->len); | ||
3406 | if (!skb) { | ||
3407 | ret = -ENOMEM; | ||
3408 | goto out_unlock; | ||
3409 | } | ||
3410 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
3411 | |||
3412 | data = skb_put(skb, params->len); | ||
3413 | memcpy(data, params->buf, params->len); | ||
3414 | |||
3415 | /* Update CSA counters */ | ||
3416 | if (sdata->vif.csa_active && | ||
3417 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
3418 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT || | ||
3419 | sdata->vif.type == NL80211_IFTYPE_ADHOC) && | ||
3420 | params->n_csa_offsets) { | ||
3421 | int i; | ||
3422 | struct beacon_data *beacon = NULL; | ||
3423 | |||
3424 | rcu_read_lock(); | ||
3425 | |||
3426 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
3427 | beacon = rcu_dereference(sdata->u.ap.beacon); | ||
3428 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
3429 | beacon = rcu_dereference(sdata->u.ibss.presp); | ||
3430 | else if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
3431 | beacon = rcu_dereference(sdata->u.mesh.beacon); | ||
3432 | |||
3433 | if (beacon) | ||
3434 | for (i = 0; i < params->n_csa_offsets; i++) | ||
3435 | data[params->csa_offsets[i]] = | ||
3436 | beacon->csa_current_counter; | ||
3437 | |||
3438 | rcu_read_unlock(); | ||
3439 | } | ||
3440 | |||
3441 | IEEE80211_SKB_CB(skb)->flags = flags; | ||
3442 | |||
3443 | skb->dev = sdata->dev; | ||
3444 | |||
3445 | if (!params->dont_wait_for_ack) { | ||
3446 | /* make a copy to preserve the frame contents | ||
3447 | * in case of encryption. | ||
3448 | */ | ||
3449 | ack_skb = ieee80211_make_ack_skb(local, skb, cookie, | ||
3450 | GFP_KERNEL); | ||
3451 | if (IS_ERR(ack_skb)) { | ||
3452 | ret = PTR_ERR(ack_skb); | ||
3453 | kfree_skb(skb); | ||
3454 | goto out_unlock; | ||
3455 | } | ||
3456 | } else { | ||
3457 | /* for cookie below */ | ||
3458 | ack_skb = skb; | ||
3459 | } | ||
3460 | |||
3461 | if (!need_offchan) { | ||
3462 | ieee80211_tx_skb(sdata, skb); | ||
3463 | ret = 0; | ||
3464 | goto out_unlock; | ||
3465 | } | ||
3466 | |||
3467 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN | | ||
3468 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | ||
3469 | if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) | ||
3470 | IEEE80211_SKB_CB(skb)->hw_queue = | ||
3471 | local->hw.offchannel_tx_hw_queue; | ||
3472 | |||
3473 | /* This will handle all kinds of coalescing and immediate TX */ | ||
3474 | ret = ieee80211_start_roc_work(local, sdata, params->chan, | ||
3475 | params->wait, cookie, skb, | ||
3476 | IEEE80211_ROC_TYPE_MGMT_TX); | ||
3477 | if (ret) | ||
3478 | kfree_skb(skb); | ||
3479 | out_unlock: | ||
3480 | mutex_unlock(&local->mtx); | ||
3481 | return ret; | ||
3482 | } | ||
3483 | |||
3484 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | ||
3485 | struct wireless_dev *wdev, | ||
3486 | u64 cookie) | ||
3487 | { | ||
3488 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
3489 | |||
3490 | return ieee80211_cancel_roc(local, cookie, true); | ||
3491 | } | 3016 | } |
3492 | 3017 | ||
3493 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | 3018 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, |
@@ -3565,7 +3090,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3565 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3090 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3566 | struct ieee80211_local *local = sdata->local; | 3091 | struct ieee80211_local *local = sdata->local; |
3567 | struct ieee80211_qos_hdr *nullfunc; | 3092 | struct ieee80211_qos_hdr *nullfunc; |
3568 | struct sk_buff *skb, *ack_skb; | 3093 | struct sk_buff *skb; |
3569 | int size = sizeof(*nullfunc); | 3094 | int size = sizeof(*nullfunc); |
3570 | __le16 fc; | 3095 | __le16 fc; |
3571 | bool qos; | 3096 | bool qos; |
@@ -3633,10 +3158,9 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3633 | if (qos) | 3158 | if (qos) |
3634 | nullfunc->qos_ctrl = cpu_to_le16(7); | 3159 | nullfunc->qos_ctrl = cpu_to_le16(7); |
3635 | 3160 | ||
3636 | ack_skb = ieee80211_make_ack_skb(local, skb, cookie, GFP_ATOMIC); | 3161 | ret = ieee80211_attach_ack_skb(local, skb, cookie, GFP_ATOMIC); |
3637 | if (IS_ERR(ack_skb)) { | 3162 | if (ret) { |
3638 | kfree_skb(skb); | 3163 | kfree_skb(skb); |
3639 | ret = PTR_ERR(ack_skb); | ||
3640 | goto unlock; | 3164 | goto unlock; |
3641 | } | 3165 | } |
3642 | 3166 | ||
@@ -3838,6 +3362,7 @@ const struct cfg80211_ops mac80211_config_ops = { | |||
3838 | .suspend = ieee80211_suspend, | 3362 | .suspend = ieee80211_suspend, |
3839 | .resume = ieee80211_resume, | 3363 | .resume = ieee80211_resume, |
3840 | .scan = ieee80211_scan, | 3364 | .scan = ieee80211_scan, |
3365 | .abort_scan = ieee80211_abort_scan, | ||
3841 | .sched_scan_start = ieee80211_sched_scan_start, | 3366 | .sched_scan_start = ieee80211_sched_scan_start, |
3842 | .sched_scan_stop = ieee80211_sched_scan_stop, | 3367 | .sched_scan_stop = ieee80211_sched_scan_stop, |
3843 | .auth = ieee80211_auth, | 3368 | .auth = ieee80211_auth, |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 4d2aaebd4f97..abbdff03ce92 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -125,6 +125,7 @@ static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = { | |||
125 | FLAG(TDLS_WIDER_BW), | 125 | FLAG(TDLS_WIDER_BW), |
126 | FLAG(SUPPORTS_AMSDU_IN_AMPDU), | 126 | FLAG(SUPPORTS_AMSDU_IN_AMPDU), |
127 | FLAG(BEACON_TX_STATUS), | 127 | FLAG(BEACON_TX_STATUS), |
128 | FLAG(NEEDS_UNIQUE_STA_ADDR), | ||
128 | 129 | ||
129 | /* keep last for the build bug below */ | 130 | /* keep last for the build bug below */ |
130 | (void *)0x1 | 131 | (void *)0x1 |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 337bb5d78003..f7fc0e00497f 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -428,6 +428,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
428 | chandef.width = sdata->u.ibss.chandef.width; | 428 | chandef.width = sdata->u.ibss.chandef.width; |
429 | break; | 429 | break; |
430 | case NL80211_CHAN_WIDTH_80: | 430 | case NL80211_CHAN_WIDTH_80: |
431 | case NL80211_CHAN_WIDTH_80P80: | ||
431 | case NL80211_CHAN_WIDTH_160: | 432 | case NL80211_CHAN_WIDTH_160: |
432 | chandef = sdata->u.ibss.chandef; | 433 | chandef = sdata->u.ibss.chandef; |
433 | chandef.chan = cbss->channel; | 434 | chandef.chan = cbss->channel; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d832bd59236b..b84f6aa32c08 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -325,19 +325,15 @@ struct mesh_preq_queue { | |||
325 | 325 | ||
326 | struct ieee80211_roc_work { | 326 | struct ieee80211_roc_work { |
327 | struct list_head list; | 327 | struct list_head list; |
328 | struct list_head dependents; | ||
329 | |||
330 | struct delayed_work work; | ||
331 | 328 | ||
332 | struct ieee80211_sub_if_data *sdata; | 329 | struct ieee80211_sub_if_data *sdata; |
333 | 330 | ||
334 | struct ieee80211_channel *chan; | 331 | struct ieee80211_channel *chan; |
335 | 332 | ||
336 | bool started, abort, hw_begun, notified; | 333 | bool started, abort, hw_begun, notified; |
337 | bool to_be_freed; | ||
338 | bool on_channel; | 334 | bool on_channel; |
339 | 335 | ||
340 | unsigned long hw_start_time; | 336 | unsigned long start_time; |
341 | 337 | ||
342 | u32 duration, req_duration; | 338 | u32 duration, req_duration; |
343 | struct sk_buff *frame; | 339 | struct sk_buff *frame; |
@@ -1335,6 +1331,7 @@ struct ieee80211_local { | |||
1335 | /* | 1331 | /* |
1336 | * Remain-on-channel support | 1332 | * Remain-on-channel support |
1337 | */ | 1333 | */ |
1334 | struct delayed_work roc_work; | ||
1338 | struct list_head roc_list; | 1335 | struct list_head roc_list; |
1339 | struct work_struct hw_roc_start, hw_roc_done; | 1336 | struct work_struct hw_roc_start, hw_roc_done; |
1340 | unsigned long hw_roc_start_time; | 1337 | unsigned long hw_roc_start_time; |
@@ -1483,6 +1480,10 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
1483 | void ieee80211_configure_filter(struct ieee80211_local *local); | 1480 | void ieee80211_configure_filter(struct ieee80211_local *local); |
1484 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); | 1481 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
1485 | 1482 | ||
1483 | u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local); | ||
1484 | int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb, | ||
1485 | u64 *cookie, gfp_t gfp); | ||
1486 | |||
1486 | /* STA code */ | 1487 | /* STA code */ |
1487 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); | 1488 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
1488 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 1489 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
@@ -1577,16 +1578,22 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_local *local); | |||
1577 | void ieee80211_sched_scan_end(struct ieee80211_local *local); | 1578 | void ieee80211_sched_scan_end(struct ieee80211_local *local); |
1578 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); | 1579 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); |
1579 | 1580 | ||
1580 | /* off-channel helpers */ | 1581 | /* off-channel/mgmt-tx */ |
1581 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); | 1582 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); |
1582 | void ieee80211_offchannel_return(struct ieee80211_local *local); | 1583 | void ieee80211_offchannel_return(struct ieee80211_local *local); |
1583 | void ieee80211_roc_setup(struct ieee80211_local *local); | 1584 | void ieee80211_roc_setup(struct ieee80211_local *local); |
1584 | void ieee80211_start_next_roc(struct ieee80211_local *local); | 1585 | void ieee80211_start_next_roc(struct ieee80211_local *local); |
1585 | void ieee80211_roc_purge(struct ieee80211_local *local, | 1586 | void ieee80211_roc_purge(struct ieee80211_local *local, |
1586 | struct ieee80211_sub_if_data *sdata); | 1587 | struct ieee80211_sub_if_data *sdata); |
1587 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free); | 1588 | int ieee80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, |
1588 | void ieee80211_sw_roc_work(struct work_struct *work); | 1589 | struct ieee80211_channel *chan, |
1589 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | 1590 | unsigned int duration, u64 *cookie); |
1591 | int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | ||
1592 | struct wireless_dev *wdev, u64 cookie); | ||
1593 | int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
1594 | struct cfg80211_mgmt_tx_params *params, u64 *cookie); | ||
1595 | int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | ||
1596 | struct wireless_dev *wdev, u64 cookie); | ||
1590 | 1597 | ||
1591 | /* channel switch handling */ | 1598 | /* channel switch handling */ |
1592 | void ieee80211_csa_finalize_work(struct work_struct *work); | 1599 | void ieee80211_csa_finalize_work(struct work_struct *work); |
@@ -1709,10 +1716,10 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); | |||
1709 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); | 1716 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); |
1710 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1717 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
1711 | struct sta_info *sta, u8 opmode, | 1718 | struct sta_info *sta, u8 opmode, |
1712 | enum ieee80211_band band, bool nss_only); | 1719 | enum ieee80211_band band); |
1713 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1720 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
1714 | struct sta_info *sta, u8 opmode, | 1721 | struct sta_info *sta, u8 opmode, |
1715 | enum ieee80211_band band, bool nss_only); | 1722 | enum ieee80211_band band); |
1716 | void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, | 1723 | void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, |
1717 | struct ieee80211_sta_vht_cap *vht_cap); | 1724 | struct ieee80211_sta_vht_cap *vht_cap); |
1718 | void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, | 1725 | void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d0dc1bfaeec2..c9e325d2e120 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -76,7 +76,8 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | |||
76 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, | 76 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, |
77 | bool update_bss) | 77 | bool update_bss) |
78 | { | 78 | { |
79 | if (__ieee80211_recalc_txpower(sdata) || update_bss) | 79 | if (__ieee80211_recalc_txpower(sdata) || |
80 | (update_bss && ieee80211_sdata_running(sdata))) | ||
80 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); | 81 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); |
81 | } | 82 | } |
82 | 83 | ||
@@ -1861,6 +1862,7 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | |||
1861 | unregister_netdevice(sdata->dev); | 1862 | unregister_netdevice(sdata->dev); |
1862 | } else { | 1863 | } else { |
1863 | cfg80211_unregister_wdev(&sdata->wdev); | 1864 | cfg80211_unregister_wdev(&sdata->wdev); |
1865 | ieee80211_teardown_sdata(sdata); | ||
1864 | kfree(sdata); | 1866 | kfree(sdata); |
1865 | } | 1867 | } |
1866 | } | 1868 | } |
@@ -1870,7 +1872,6 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata) | |||
1870 | if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state))) | 1872 | if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state))) |
1871 | return; | 1873 | return; |
1872 | ieee80211_do_stop(sdata, true); | 1874 | ieee80211_do_stop(sdata, true); |
1873 | ieee80211_teardown_sdata(sdata); | ||
1874 | } | 1875 | } |
1875 | 1876 | ||
1876 | void ieee80211_remove_interfaces(struct ieee80211_local *local) | 1877 | void ieee80211_remove_interfaces(struct ieee80211_local *local) |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 44388d6a1d8e..5e5bc599da4c 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -4,6 +4,7 @@ | |||
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 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> |
6 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 6 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
7 | * Copyright 2015 Intel Deutschland GmbH | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
@@ -320,7 +321,7 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
320 | return; | 321 | return; |
321 | 322 | ||
322 | if (new) | 323 | if (new) |
323 | list_add_tail(&new->list, &sdata->key_list); | 324 | list_add_tail_rcu(&new->list, &sdata->key_list); |
324 | 325 | ||
325 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); | 326 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); |
326 | 327 | ||
@@ -368,7 +369,7 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
368 | } | 369 | } |
369 | 370 | ||
370 | if (old) | 371 | if (old) |
371 | list_del(&old->list); | 372 | list_del_rcu(&old->list); |
372 | } | 373 | } |
373 | 374 | ||
374 | struct ieee80211_key * | 375 | struct ieee80211_key * |
@@ -592,8 +593,8 @@ static void ieee80211_key_destroy(struct ieee80211_key *key, | |||
592 | return; | 593 | return; |
593 | 594 | ||
594 | /* | 595 | /* |
595 | * Synchronize so the TX path can no longer be using | 596 | * Synchronize so the TX path and rcu key iterators |
596 | * this key before we free/remove it. | 597 | * can no longer be using this key before we free/remove it. |
597 | */ | 598 | */ |
598 | synchronize_net(); | 599 | synchronize_net(); |
599 | 600 | ||
@@ -744,6 +745,53 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, | |||
744 | } | 745 | } |
745 | EXPORT_SYMBOL(ieee80211_iter_keys); | 746 | EXPORT_SYMBOL(ieee80211_iter_keys); |
746 | 747 | ||
748 | static void | ||
749 | _ieee80211_iter_keys_rcu(struct ieee80211_hw *hw, | ||
750 | struct ieee80211_sub_if_data *sdata, | ||
751 | void (*iter)(struct ieee80211_hw *hw, | ||
752 | struct ieee80211_vif *vif, | ||
753 | struct ieee80211_sta *sta, | ||
754 | struct ieee80211_key_conf *key, | ||
755 | void *data), | ||
756 | void *iter_data) | ||
757 | { | ||
758 | struct ieee80211_key *key; | ||
759 | |||
760 | list_for_each_entry_rcu(key, &sdata->key_list, list) { | ||
761 | /* skip keys of station in removal process */ | ||
762 | if (key->sta && key->sta->removed) | ||
763 | continue; | ||
764 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | ||
765 | continue; | ||
766 | |||
767 | iter(hw, &sdata->vif, | ||
768 | key->sta ? &key->sta->sta : NULL, | ||
769 | &key->conf, iter_data); | ||
770 | } | ||
771 | } | ||
772 | |||
773 | void ieee80211_iter_keys_rcu(struct ieee80211_hw *hw, | ||
774 | struct ieee80211_vif *vif, | ||
775 | void (*iter)(struct ieee80211_hw *hw, | ||
776 | struct ieee80211_vif *vif, | ||
777 | struct ieee80211_sta *sta, | ||
778 | struct ieee80211_key_conf *key, | ||
779 | void *data), | ||
780 | void *iter_data) | ||
781 | { | ||
782 | struct ieee80211_local *local = hw_to_local(hw); | ||
783 | struct ieee80211_sub_if_data *sdata; | ||
784 | |||
785 | if (vif) { | ||
786 | sdata = vif_to_sdata(vif); | ||
787 | _ieee80211_iter_keys_rcu(hw, sdata, iter, iter_data); | ||
788 | } else { | ||
789 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
790 | _ieee80211_iter_keys_rcu(hw, sdata, iter, iter_data); | ||
791 | } | ||
792 | } | ||
793 | EXPORT_SYMBOL(ieee80211_iter_keys_rcu); | ||
794 | |||
747 | static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata, | 795 | static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata, |
748 | struct list_head *keys) | 796 | struct list_head *keys) |
749 | { | 797 | { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 858f6b1cb149..6bcf0faa4a89 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1149,6 +1149,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1149 | 1149 | ||
1150 | rtnl_unlock(); | 1150 | rtnl_unlock(); |
1151 | 1151 | ||
1152 | cancel_delayed_work_sync(&local->roc_work); | ||
1152 | cancel_work_sync(&local->restart_work); | 1153 | cancel_work_sync(&local->restart_work); |
1153 | cancel_work_sync(&local->reconfig_filter); | 1154 | cancel_work_sync(&local->reconfig_filter); |
1154 | cancel_work_sync(&local->tdls_chsw_work); | 1155 | cancel_work_sync(&local->tdls_chsw_work); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index b890e225a8f1..dadf8dc6f1cf 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -779,10 +779,8 @@ void mesh_plink_broken(struct sta_info *sta) | |||
779 | static void mesh_path_node_reclaim(struct rcu_head *rp) | 779 | static void mesh_path_node_reclaim(struct rcu_head *rp) |
780 | { | 780 | { |
781 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); | 781 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); |
782 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; | ||
783 | 782 | ||
784 | del_timer_sync(&node->mpath->timer); | 783 | del_timer_sync(&node->mpath->timer); |
785 | atomic_dec(&sdata->u.mesh.mpaths); | ||
786 | kfree(node->mpath); | 784 | kfree(node->mpath); |
787 | kfree(node); | 785 | kfree(node); |
788 | } | 786 | } |
@@ -790,8 +788,9 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) | |||
790 | /* needs to be called with the corresponding hashwlock taken */ | 788 | /* needs to be called with the corresponding hashwlock taken */ |
791 | static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) | 789 | static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) |
792 | { | 790 | { |
793 | struct mesh_path *mpath; | 791 | struct mesh_path *mpath = node->mpath; |
794 | mpath = node->mpath; | 792 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; |
793 | |||
795 | spin_lock(&mpath->state_lock); | 794 | spin_lock(&mpath->state_lock); |
796 | mpath->flags |= MESH_PATH_RESOLVING; | 795 | mpath->flags |= MESH_PATH_RESOLVING; |
797 | if (mpath->is_gate) | 796 | if (mpath->is_gate) |
@@ -799,6 +798,7 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) | |||
799 | hlist_del_rcu(&node->list); | 798 | hlist_del_rcu(&node->list); |
800 | call_rcu(&node->rcu, mesh_path_node_reclaim); | 799 | call_rcu(&node->rcu, mesh_path_node_reclaim); |
801 | spin_unlock(&mpath->state_lock); | 800 | spin_unlock(&mpath->state_lock); |
801 | atomic_dec(&sdata->u.mesh.mpaths); | ||
802 | atomic_dec(&tbl->entries); | 802 | atomic_dec(&tbl->entries); |
803 | } | 803 | } |
804 | 804 | ||
@@ -968,8 +968,8 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) | |||
968 | copy = true; | 968 | copy = true; |
969 | } else { | 969 | } else { |
970 | mpath_dbg(sdata, | 970 | mpath_dbg(sdata, |
971 | "Not forwarding %p (flags %#x)\n", | 971 | "Not forwarding to %pM (flags %#x)\n", |
972 | gate->mpath, gate->mpath->flags); | 972 | gate->mpath->dst, gate->mpath->flags); |
973 | } | 973 | } |
974 | } | 974 | } |
975 | 975 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b140cc6651f4..1c342e2592c4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1379,21 +1379,26 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
1379 | */ | 1379 | */ |
1380 | if (has_80211h_pwr && | 1380 | if (has_80211h_pwr && |
1381 | (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) { | 1381 | (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) { |
1382 | new_ap_level = pwr_level_80211h; | ||
1383 | |||
1384 | if (sdata->ap_power_level == new_ap_level) | ||
1385 | return 0; | ||
1386 | |||
1382 | sdata_dbg(sdata, | 1387 | sdata_dbg(sdata, |
1383 | "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", | 1388 | "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", |
1384 | pwr_level_80211h, chan_pwr, pwr_reduction_80211h, | 1389 | pwr_level_80211h, chan_pwr, pwr_reduction_80211h, |
1385 | sdata->u.mgd.bssid); | 1390 | sdata->u.mgd.bssid); |
1386 | new_ap_level = pwr_level_80211h; | ||
1387 | } else { /* has_cisco_pwr is always true here. */ | 1391 | } else { /* has_cisco_pwr is always true here. */ |
1392 | new_ap_level = pwr_level_cisco; | ||
1393 | |||
1394 | if (sdata->ap_power_level == new_ap_level) | ||
1395 | return 0; | ||
1396 | |||
1388 | sdata_dbg(sdata, | 1397 | sdata_dbg(sdata, |
1389 | "Limiting TX power to %d dBm as advertised by %pM\n", | 1398 | "Limiting TX power to %d dBm as advertised by %pM\n", |
1390 | pwr_level_cisco, sdata->u.mgd.bssid); | 1399 | pwr_level_cisco, sdata->u.mgd.bssid); |
1391 | new_ap_level = pwr_level_cisco; | ||
1392 | } | 1400 | } |
1393 | 1401 | ||
1394 | if (sdata->ap_power_level == new_ap_level) | ||
1395 | return 0; | ||
1396 | |||
1397 | sdata->ap_power_level = new_ap_level; | 1402 | sdata->ap_power_level = new_ap_level; |
1398 | if (__ieee80211_recalc_txpower(sdata)) | 1403 | if (__ieee80211_recalc_txpower(sdata)) |
1399 | return BSS_CHANGED_TXPOWER; | 1404 | return BSS_CHANGED_TXPOWER; |
@@ -1930,7 +1935,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1930 | 1935 | ||
1931 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | 1936 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; |
1932 | 1937 | ||
1933 | if (sdata->vif.p2p) { | 1938 | if (sdata->vif.p2p || |
1939 | sdata->vif.driver_flags & IEEE80211_VIF_GET_NOA_UPDATE) { | ||
1934 | const struct cfg80211_bss_ies *ies; | 1940 | const struct cfg80211_bss_ies *ies; |
1935 | 1941 | ||
1936 | rcu_read_lock(); | 1942 | rcu_read_lock(); |
@@ -3458,7 +3464,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3458 | } | 3464 | } |
3459 | } | 3465 | } |
3460 | 3466 | ||
3461 | if (sdata->vif.p2p) { | 3467 | if (sdata->vif.p2p || |
3468 | sdata->vif.driver_flags & IEEE80211_VIF_GET_NOA_UPDATE) { | ||
3462 | struct ieee80211_p2p_noa_attr noa = {}; | 3469 | struct ieee80211_p2p_noa_attr noa = {}; |
3463 | int ret; | 3470 | int ret; |
3464 | 3471 | ||
@@ -3575,7 +3582,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3575 | 3582 | ||
3576 | if (sta && elems.opmode_notif) | 3583 | if (sta && elems.opmode_notif) |
3577 | ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif, | 3584 | ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif, |
3578 | rx_status->band, true); | 3585 | rx_status->band); |
3579 | mutex_unlock(&local->sta_mtx); | 3586 | mutex_unlock(&local->sta_mtx); |
3580 | 3587 | ||
3581 | changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt, | 3588 | changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt, |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 04401037140e..8b2f4eaac2ba 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -187,11 +187,80 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) | |||
187 | false); | 187 | false); |
188 | } | 188 | } |
189 | 189 | ||
190 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | 190 | static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) |
191 | { | 191 | { |
192 | if (roc->notified) | 192 | /* was never transmitted */ |
193 | if (roc->frame) { | ||
194 | cfg80211_mgmt_tx_status(&roc->sdata->wdev, roc->mgmt_tx_cookie, | ||
195 | roc->frame->data, roc->frame->len, | ||
196 | false, GFP_KERNEL); | ||
197 | ieee80211_free_txskb(&roc->sdata->local->hw, roc->frame); | ||
198 | } | ||
199 | |||
200 | if (!roc->mgmt_tx_cookie) | ||
201 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, | ||
202 | roc->cookie, roc->chan, | ||
203 | GFP_KERNEL); | ||
204 | |||
205 | list_del(&roc->list); | ||
206 | kfree(roc); | ||
207 | } | ||
208 | |||
209 | static unsigned long ieee80211_end_finished_rocs(struct ieee80211_local *local, | ||
210 | unsigned long now) | ||
211 | { | ||
212 | struct ieee80211_roc_work *roc, *tmp; | ||
213 | long remaining_dur_min = LONG_MAX; | ||
214 | |||
215 | lockdep_assert_held(&local->mtx); | ||
216 | |||
217 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | ||
218 | long remaining; | ||
219 | |||
220 | if (!roc->started) | ||
221 | break; | ||
222 | |||
223 | remaining = roc->start_time + | ||
224 | msecs_to_jiffies(roc->duration) - | ||
225 | now; | ||
226 | |||
227 | /* In case of HW ROC, it is possible that the HW finished the | ||
228 | * ROC session before the actual requested time. In such a case | ||
229 | * end the ROC session (disregarding the remaining time). | ||
230 | */ | ||
231 | if (roc->abort || roc->hw_begun || remaining <= 0) | ||
232 | ieee80211_roc_notify_destroy(roc); | ||
233 | else | ||
234 | remaining_dur_min = min(remaining_dur_min, remaining); | ||
235 | } | ||
236 | |||
237 | return remaining_dur_min; | ||
238 | } | ||
239 | |||
240 | static bool ieee80211_recalc_sw_work(struct ieee80211_local *local, | ||
241 | unsigned long now) | ||
242 | { | ||
243 | long dur = ieee80211_end_finished_rocs(local, now); | ||
244 | |||
245 | if (dur == LONG_MAX) | ||
246 | return false; | ||
247 | |||
248 | mod_delayed_work(local->workqueue, &local->roc_work, dur); | ||
249 | return true; | ||
250 | } | ||
251 | |||
252 | static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc, | ||
253 | unsigned long start_time) | ||
254 | { | ||
255 | struct ieee80211_local *local = roc->sdata->local; | ||
256 | |||
257 | if (WARN_ON(roc->notified)) | ||
193 | return; | 258 | return; |
194 | 259 | ||
260 | roc->start_time = start_time; | ||
261 | roc->started = true; | ||
262 | roc->hw_begun = true; | ||
263 | |||
195 | if (roc->mgmt_tx_cookie) { | 264 | if (roc->mgmt_tx_cookie) { |
196 | if (!WARN_ON(!roc->frame)) { | 265 | if (!WARN_ON(!roc->frame)) { |
197 | ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7, | 266 | ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7, |
@@ -205,40 +274,26 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | |||
205 | } | 274 | } |
206 | 275 | ||
207 | roc->notified = true; | 276 | roc->notified = true; |
277 | |||
278 | if (!local->ops->remain_on_channel) | ||
279 | ieee80211_recalc_sw_work(local, start_time); | ||
208 | } | 280 | } |
209 | 281 | ||
210 | static void ieee80211_hw_roc_start(struct work_struct *work) | 282 | static void ieee80211_hw_roc_start(struct work_struct *work) |
211 | { | 283 | { |
212 | struct ieee80211_local *local = | 284 | struct ieee80211_local *local = |
213 | container_of(work, struct ieee80211_local, hw_roc_start); | 285 | container_of(work, struct ieee80211_local, hw_roc_start); |
214 | struct ieee80211_roc_work *roc, *dep, *tmp; | 286 | struct ieee80211_roc_work *roc; |
215 | 287 | ||
216 | mutex_lock(&local->mtx); | 288 | mutex_lock(&local->mtx); |
217 | 289 | ||
218 | if (list_empty(&local->roc_list)) | 290 | list_for_each_entry(roc, &local->roc_list, list) { |
219 | goto out_unlock; | 291 | if (!roc->started) |
220 | 292 | break; | |
221 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, | ||
222 | list); | ||
223 | |||
224 | if (!roc->started) | ||
225 | goto out_unlock; | ||
226 | |||
227 | roc->hw_begun = true; | ||
228 | roc->hw_start_time = local->hw_roc_start_time; | ||
229 | 293 | ||
230 | ieee80211_handle_roc_started(roc); | 294 | ieee80211_handle_roc_started(roc, local->hw_roc_start_time); |
231 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) { | ||
232 | ieee80211_handle_roc_started(dep); | ||
233 | |||
234 | if (dep->duration > roc->duration) { | ||
235 | u32 dur = dep->duration; | ||
236 | dep->duration = dur - roc->duration; | ||
237 | roc->duration = dur; | ||
238 | list_move(&dep->list, &roc->list); | ||
239 | } | ||
240 | } | 295 | } |
241 | out_unlock: | 296 | |
242 | mutex_unlock(&local->mtx); | 297 | mutex_unlock(&local->mtx); |
243 | } | 298 | } |
244 | 299 | ||
@@ -254,34 +309,40 @@ void ieee80211_ready_on_channel(struct ieee80211_hw *hw) | |||
254 | } | 309 | } |
255 | EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); | 310 | EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); |
256 | 311 | ||
257 | void ieee80211_start_next_roc(struct ieee80211_local *local) | 312 | static void _ieee80211_start_next_roc(struct ieee80211_local *local) |
258 | { | 313 | { |
259 | struct ieee80211_roc_work *roc; | 314 | struct ieee80211_roc_work *roc, *tmp; |
315 | enum ieee80211_roc_type type; | ||
316 | u32 min_dur, max_dur; | ||
260 | 317 | ||
261 | lockdep_assert_held(&local->mtx); | 318 | lockdep_assert_held(&local->mtx); |
262 | 319 | ||
263 | if (list_empty(&local->roc_list)) { | 320 | if (WARN_ON(list_empty(&local->roc_list))) |
264 | ieee80211_run_deferred_scan(local); | ||
265 | return; | 321 | return; |
266 | } | ||
267 | 322 | ||
268 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, | 323 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, |
269 | list); | 324 | list); |
270 | 325 | ||
271 | if (WARN_ON_ONCE(roc->started)) | 326 | if (WARN_ON(roc->started)) |
272 | return; | 327 | return; |
273 | 328 | ||
274 | if (local->ops->remain_on_channel) { | 329 | min_dur = roc->duration; |
275 | int ret, duration = roc->duration; | 330 | max_dur = roc->duration; |
276 | 331 | type = roc->type; | |
277 | /* XXX: duplicated, see ieee80211_start_roc_work() */ | ||
278 | if (!duration) | ||
279 | duration = 10; | ||
280 | 332 | ||
281 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, | 333 | list_for_each_entry(tmp, &local->roc_list, list) { |
282 | duration, roc->type); | 334 | if (tmp == roc) |
335 | continue; | ||
336 | if (tmp->sdata != roc->sdata || tmp->chan != roc->chan) | ||
337 | break; | ||
338 | max_dur = max(tmp->duration, max_dur); | ||
339 | min_dur = min(tmp->duration, min_dur); | ||
340 | type = max(tmp->type, type); | ||
341 | } | ||
283 | 342 | ||
284 | roc->started = true; | 343 | if (local->ops->remain_on_channel) { |
344 | int ret = drv_remain_on_channel(local, roc->sdata, roc->chan, | ||
345 | max_dur, type); | ||
285 | 346 | ||
286 | if (ret) { | 347 | if (ret) { |
287 | wiphy_warn(local->hw.wiphy, | 348 | wiphy_warn(local->hw.wiphy, |
@@ -290,74 +351,24 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
290 | * queue the work struct again to avoid recursion | 351 | * queue the work struct again to avoid recursion |
291 | * when multiple failures occur | 352 | * when multiple failures occur |
292 | */ | 353 | */ |
293 | ieee80211_remain_on_channel_expired(&local->hw); | 354 | list_for_each_entry(tmp, &local->roc_list, list) { |
355 | if (tmp->sdata != roc->sdata || | ||
356 | tmp->chan != roc->chan) | ||
357 | break; | ||
358 | tmp->started = true; | ||
359 | tmp->abort = true; | ||
360 | } | ||
361 | ieee80211_queue_work(&local->hw, &local->hw_roc_done); | ||
362 | return; | ||
294 | } | 363 | } |
295 | } else { | ||
296 | /* delay it a bit */ | ||
297 | ieee80211_queue_delayed_work(&local->hw, &roc->work, | ||
298 | round_jiffies_relative(HZ/2)); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free) | ||
303 | { | ||
304 | struct ieee80211_roc_work *dep, *tmp; | ||
305 | |||
306 | if (WARN_ON(roc->to_be_freed)) | ||
307 | return; | ||
308 | |||
309 | /* was never transmitted */ | ||
310 | if (roc->frame) { | ||
311 | cfg80211_mgmt_tx_status(&roc->sdata->wdev, | ||
312 | (unsigned long)roc->frame, | ||
313 | roc->frame->data, roc->frame->len, | ||
314 | false, GFP_KERNEL); | ||
315 | kfree_skb(roc->frame); | ||
316 | } | ||
317 | |||
318 | if (!roc->mgmt_tx_cookie) | ||
319 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, | ||
320 | roc->cookie, roc->chan, | ||
321 | GFP_KERNEL); | ||
322 | |||
323 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) | ||
324 | ieee80211_roc_notify_destroy(dep, true); | ||
325 | |||
326 | if (free) | ||
327 | kfree(roc); | ||
328 | else | ||
329 | roc->to_be_freed = true; | ||
330 | } | ||
331 | |||
332 | void ieee80211_sw_roc_work(struct work_struct *work) | ||
333 | { | ||
334 | struct ieee80211_roc_work *roc = | ||
335 | container_of(work, struct ieee80211_roc_work, work.work); | ||
336 | struct ieee80211_sub_if_data *sdata = roc->sdata; | ||
337 | struct ieee80211_local *local = sdata->local; | ||
338 | bool started, on_channel; | ||
339 | |||
340 | mutex_lock(&local->mtx); | ||
341 | |||
342 | if (roc->to_be_freed) | ||
343 | goto out_unlock; | ||
344 | |||
345 | if (roc->abort) | ||
346 | goto finish; | ||
347 | |||
348 | if (WARN_ON(list_empty(&local->roc_list))) | ||
349 | goto out_unlock; | ||
350 | |||
351 | if (WARN_ON(roc != list_first_entry(&local->roc_list, | ||
352 | struct ieee80211_roc_work, | ||
353 | list))) | ||
354 | goto out_unlock; | ||
355 | |||
356 | if (!roc->started) { | ||
357 | struct ieee80211_roc_work *dep; | ||
358 | |||
359 | WARN_ON(local->use_chanctx); | ||
360 | 364 | ||
365 | /* we'll notify about the start once the HW calls back */ | ||
366 | list_for_each_entry(tmp, &local->roc_list, list) { | ||
367 | if (tmp->sdata != roc->sdata || tmp->chan != roc->chan) | ||
368 | break; | ||
369 | tmp->started = true; | ||
370 | } | ||
371 | } else { | ||
361 | /* If actually operating on the desired channel (with at least | 372 | /* If actually operating on the desired channel (with at least |
362 | * 20 MHz channel width) don't stop all the operations but still | 373 | * 20 MHz channel width) don't stop all the operations but still |
363 | * treat it as though the ROC operation started properly, so | 374 | * treat it as though the ROC operation started properly, so |
@@ -377,27 +388,72 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
377 | ieee80211_hw_config(local, 0); | 388 | ieee80211_hw_config(local, 0); |
378 | } | 389 | } |
379 | 390 | ||
380 | /* tell userspace or send frame */ | 391 | ieee80211_queue_delayed_work(&local->hw, &local->roc_work, |
381 | ieee80211_handle_roc_started(roc); | 392 | msecs_to_jiffies(min_dur)); |
382 | list_for_each_entry(dep, &roc->dependents, list) | ||
383 | ieee80211_handle_roc_started(dep); | ||
384 | 393 | ||
385 | /* if it was pure TX, just finish right away */ | 394 | /* tell userspace or send frame(s) */ |
386 | if (!roc->duration) | 395 | list_for_each_entry(tmp, &local->roc_list, list) { |
387 | goto finish; | 396 | if (tmp->sdata != roc->sdata || tmp->chan != roc->chan) |
397 | break; | ||
388 | 398 | ||
389 | roc->started = true; | 399 | tmp->on_channel = roc->on_channel; |
390 | ieee80211_queue_delayed_work(&local->hw, &roc->work, | 400 | ieee80211_handle_roc_started(tmp, jiffies); |
391 | msecs_to_jiffies(roc->duration)); | 401 | } |
402 | } | ||
403 | } | ||
404 | |||
405 | void ieee80211_start_next_roc(struct ieee80211_local *local) | ||
406 | { | ||
407 | struct ieee80211_roc_work *roc; | ||
408 | |||
409 | lockdep_assert_held(&local->mtx); | ||
410 | |||
411 | if (list_empty(&local->roc_list)) { | ||
412 | ieee80211_run_deferred_scan(local); | ||
413 | return; | ||
414 | } | ||
415 | |||
416 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, | ||
417 | list); | ||
418 | |||
419 | if (WARN_ON_ONCE(roc->started)) | ||
420 | return; | ||
421 | |||
422 | if (local->ops->remain_on_channel) { | ||
423 | _ieee80211_start_next_roc(local); | ||
424 | } else { | ||
425 | /* delay it a bit */ | ||
426 | ieee80211_queue_delayed_work(&local->hw, &local->roc_work, | ||
427 | round_jiffies_relative(HZ/2)); | ||
428 | } | ||
429 | } | ||
430 | |||
431 | static void __ieee80211_roc_work(struct ieee80211_local *local) | ||
432 | { | ||
433 | struct ieee80211_roc_work *roc; | ||
434 | bool on_channel; | ||
435 | |||
436 | lockdep_assert_held(&local->mtx); | ||
437 | |||
438 | if (WARN_ON(local->ops->remain_on_channel)) | ||
439 | return; | ||
440 | |||
441 | roc = list_first_entry_or_null(&local->roc_list, | ||
442 | struct ieee80211_roc_work, list); | ||
443 | if (!roc) | ||
444 | return; | ||
445 | |||
446 | if (!roc->started) { | ||
447 | WARN_ON(local->use_chanctx); | ||
448 | _ieee80211_start_next_roc(local); | ||
392 | } else { | 449 | } else { |
393 | /* finish this ROC */ | ||
394 | finish: | ||
395 | list_del(&roc->list); | ||
396 | started = roc->started; | ||
397 | on_channel = roc->on_channel; | 450 | on_channel = roc->on_channel; |
398 | ieee80211_roc_notify_destroy(roc, !roc->abort); | 451 | if (ieee80211_recalc_sw_work(local, jiffies)) |
452 | return; | ||
453 | |||
454 | /* careful - roc pointer became invalid during recalc */ | ||
399 | 455 | ||
400 | if (started && !on_channel) { | 456 | if (!on_channel) { |
401 | ieee80211_flush_queues(local, NULL, false); | 457 | ieee80211_flush_queues(local, NULL, false); |
402 | 458 | ||
403 | local->tmp_channel = NULL; | 459 | local->tmp_channel = NULL; |
@@ -407,14 +463,17 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
407 | } | 463 | } |
408 | 464 | ||
409 | ieee80211_recalc_idle(local); | 465 | ieee80211_recalc_idle(local); |
410 | 466 | ieee80211_start_next_roc(local); | |
411 | if (started) | ||
412 | ieee80211_start_next_roc(local); | ||
413 | else if (list_empty(&local->roc_list)) | ||
414 | ieee80211_run_deferred_scan(local); | ||
415 | } | 467 | } |
468 | } | ||
416 | 469 | ||
417 | out_unlock: | 470 | static void ieee80211_roc_work(struct work_struct *work) |
471 | { | ||
472 | struct ieee80211_local *local = | ||
473 | container_of(work, struct ieee80211_local, roc_work.work); | ||
474 | |||
475 | mutex_lock(&local->mtx); | ||
476 | __ieee80211_roc_work(local); | ||
418 | mutex_unlock(&local->mtx); | 477 | mutex_unlock(&local->mtx); |
419 | } | 478 | } |
420 | 479 | ||
@@ -422,27 +481,14 @@ static void ieee80211_hw_roc_done(struct work_struct *work) | |||
422 | { | 481 | { |
423 | struct ieee80211_local *local = | 482 | struct ieee80211_local *local = |
424 | container_of(work, struct ieee80211_local, hw_roc_done); | 483 | container_of(work, struct ieee80211_local, hw_roc_done); |
425 | struct ieee80211_roc_work *roc; | ||
426 | 484 | ||
427 | mutex_lock(&local->mtx); | 485 | mutex_lock(&local->mtx); |
428 | 486 | ||
429 | if (list_empty(&local->roc_list)) | 487 | ieee80211_end_finished_rocs(local, jiffies); |
430 | goto out_unlock; | ||
431 | |||
432 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, | ||
433 | list); | ||
434 | |||
435 | if (!roc->started) | ||
436 | goto out_unlock; | ||
437 | |||
438 | list_del(&roc->list); | ||
439 | |||
440 | ieee80211_roc_notify_destroy(roc, true); | ||
441 | 488 | ||
442 | /* if there's another roc, start it now */ | 489 | /* if there's another roc, start it now */ |
443 | ieee80211_start_next_roc(local); | 490 | ieee80211_start_next_roc(local); |
444 | 491 | ||
445 | out_unlock: | ||
446 | mutex_unlock(&local->mtx); | 492 | mutex_unlock(&local->mtx); |
447 | } | 493 | } |
448 | 494 | ||
@@ -456,47 +502,500 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw) | |||
456 | } | 502 | } |
457 | EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); | 503 | EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); |
458 | 504 | ||
459 | void ieee80211_roc_setup(struct ieee80211_local *local) | 505 | static bool |
506 | ieee80211_coalesce_hw_started_roc(struct ieee80211_local *local, | ||
507 | struct ieee80211_roc_work *new_roc, | ||
508 | struct ieee80211_roc_work *cur_roc) | ||
460 | { | 509 | { |
461 | INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); | 510 | unsigned long now = jiffies; |
462 | INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); | 511 | unsigned long remaining; |
463 | INIT_LIST_HEAD(&local->roc_list); | 512 | |
513 | if (WARN_ON(!cur_roc->started)) | ||
514 | return false; | ||
515 | |||
516 | /* if it was scheduled in the hardware, but not started yet, | ||
517 | * we can only combine if the older one had a longer duration | ||
518 | */ | ||
519 | if (!cur_roc->hw_begun && new_roc->duration > cur_roc->duration) | ||
520 | return false; | ||
521 | |||
522 | remaining = cur_roc->start_time + | ||
523 | msecs_to_jiffies(cur_roc->duration) - | ||
524 | now; | ||
525 | |||
526 | /* if it doesn't fit entirely, schedule a new one */ | ||
527 | if (new_roc->duration > jiffies_to_msecs(remaining)) | ||
528 | return false; | ||
529 | |||
530 | /* add just after the current one so we combine their finish later */ | ||
531 | list_add(&new_roc->list, &cur_roc->list); | ||
532 | |||
533 | /* if the existing one has already begun then let this one also | ||
534 | * begin, otherwise they'll both be marked properly by the work | ||
535 | * struct that runs once the driver notifies us of the beginning | ||
536 | */ | ||
537 | if (cur_roc->hw_begun) | ||
538 | ieee80211_handle_roc_started(new_roc, now); | ||
539 | |||
540 | return true; | ||
464 | } | 541 | } |
465 | 542 | ||
466 | void ieee80211_roc_purge(struct ieee80211_local *local, | 543 | static int ieee80211_start_roc_work(struct ieee80211_local *local, |
467 | struct ieee80211_sub_if_data *sdata) | 544 | struct ieee80211_sub_if_data *sdata, |
545 | struct ieee80211_channel *channel, | ||
546 | unsigned int duration, u64 *cookie, | ||
547 | struct sk_buff *txskb, | ||
548 | enum ieee80211_roc_type type) | ||
468 | { | 549 | { |
469 | struct ieee80211_roc_work *roc, *tmp; | 550 | struct ieee80211_roc_work *roc, *tmp; |
470 | LIST_HEAD(tmp_list); | 551 | bool queued = false, combine_started = true; |
552 | int ret; | ||
553 | |||
554 | lockdep_assert_held(&local->mtx); | ||
555 | |||
556 | if (local->use_chanctx && !local->ops->remain_on_channel) | ||
557 | return -EOPNOTSUPP; | ||
558 | |||
559 | roc = kzalloc(sizeof(*roc), GFP_KERNEL); | ||
560 | if (!roc) | ||
561 | return -ENOMEM; | ||
562 | |||
563 | /* | ||
564 | * If the duration is zero, then the driver | ||
565 | * wouldn't actually do anything. Set it to | ||
566 | * 10 for now. | ||
567 | * | ||
568 | * TODO: cancel the off-channel operation | ||
569 | * when we get the SKB's TX status and | ||
570 | * the wait time was zero before. | ||
571 | */ | ||
572 | if (!duration) | ||
573 | duration = 10; | ||
574 | |||
575 | roc->chan = channel; | ||
576 | roc->duration = duration; | ||
577 | roc->req_duration = duration; | ||
578 | roc->frame = txskb; | ||
579 | roc->type = type; | ||
580 | roc->sdata = sdata; | ||
581 | |||
582 | /* | ||
583 | * cookie is either the roc cookie (for normal roc) | ||
584 | * or the SKB (for mgmt TX) | ||
585 | */ | ||
586 | if (!txskb) { | ||
587 | roc->cookie = ieee80211_mgmt_tx_cookie(local); | ||
588 | *cookie = roc->cookie; | ||
589 | } else { | ||
590 | roc->mgmt_tx_cookie = *cookie; | ||
591 | } | ||
592 | |||
593 | /* if there's no need to queue, handle it immediately */ | ||
594 | if (list_empty(&local->roc_list) && | ||
595 | !local->scanning && !ieee80211_is_radar_required(local)) { | ||
596 | /* if not HW assist, just queue & schedule work */ | ||
597 | if (!local->ops->remain_on_channel) { | ||
598 | list_add_tail(&roc->list, &local->roc_list); | ||
599 | ieee80211_queue_delayed_work(&local->hw, | ||
600 | &local->roc_work, 0); | ||
601 | } else { | ||
602 | /* otherwise actually kick it off here | ||
603 | * (for error handling) | ||
604 | */ | ||
605 | ret = drv_remain_on_channel(local, sdata, channel, | ||
606 | duration, type); | ||
607 | if (ret) { | ||
608 | kfree(roc); | ||
609 | return ret; | ||
610 | } | ||
611 | roc->started = true; | ||
612 | list_add_tail(&roc->list, &local->roc_list); | ||
613 | } | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | /* otherwise handle queueing */ | ||
619 | |||
620 | list_for_each_entry(tmp, &local->roc_list, list) { | ||
621 | if (tmp->chan != channel || tmp->sdata != sdata) | ||
622 | continue; | ||
623 | |||
624 | /* | ||
625 | * Extend this ROC if possible: If it hasn't started, add | ||
626 | * just after the new one to combine. | ||
627 | */ | ||
628 | if (!tmp->started) { | ||
629 | list_add(&roc->list, &tmp->list); | ||
630 | queued = true; | ||
631 | break; | ||
632 | } | ||
633 | |||
634 | if (!combine_started) | ||
635 | continue; | ||
636 | |||
637 | if (!local->ops->remain_on_channel) { | ||
638 | /* If there's no hardware remain-on-channel, and | ||
639 | * doing so won't push us over the maximum r-o-c | ||
640 | * we allow, then we can just add the new one to | ||
641 | * the list and mark it as having started now. | ||
642 | * If it would push over the limit, don't try to | ||
643 | * combine with other started ones (that haven't | ||
644 | * been running as long) but potentially sort it | ||
645 | * with others that had the same fate. | ||
646 | */ | ||
647 | unsigned long now = jiffies; | ||
648 | u32 elapsed = jiffies_to_msecs(now - tmp->start_time); | ||
649 | struct wiphy *wiphy = local->hw.wiphy; | ||
650 | u32 max_roc = wiphy->max_remain_on_channel_duration; | ||
651 | |||
652 | if (elapsed + roc->duration > max_roc) { | ||
653 | combine_started = false; | ||
654 | continue; | ||
655 | } | ||
656 | |||
657 | list_add(&roc->list, &tmp->list); | ||
658 | queued = true; | ||
659 | roc->on_channel = tmp->on_channel; | ||
660 | ieee80211_handle_roc_started(roc, now); | ||
661 | break; | ||
662 | } | ||
663 | |||
664 | queued = ieee80211_coalesce_hw_started_roc(local, roc, tmp); | ||
665 | if (queued) | ||
666 | break; | ||
667 | /* if it wasn't queued, perhaps it can be combined with | ||
668 | * another that also couldn't get combined previously, | ||
669 | * but no need to check for already started ones, since | ||
670 | * that can't work. | ||
671 | */ | ||
672 | combine_started = false; | ||
673 | } | ||
674 | |||
675 | if (!queued) | ||
676 | list_add_tail(&roc->list, &local->roc_list); | ||
677 | |||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | int ieee80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
682 | struct ieee80211_channel *chan, | ||
683 | unsigned int duration, u64 *cookie) | ||
684 | { | ||
685 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
686 | struct ieee80211_local *local = sdata->local; | ||
687 | int ret; | ||
688 | |||
689 | mutex_lock(&local->mtx); | ||
690 | ret = ieee80211_start_roc_work(local, sdata, chan, | ||
691 | duration, cookie, NULL, | ||
692 | IEEE80211_ROC_TYPE_NORMAL); | ||
693 | mutex_unlock(&local->mtx); | ||
694 | |||
695 | return ret; | ||
696 | } | ||
697 | |||
698 | static int ieee80211_cancel_roc(struct ieee80211_local *local, | ||
699 | u64 cookie, bool mgmt_tx) | ||
700 | { | ||
701 | struct ieee80211_roc_work *roc, *tmp, *found = NULL; | ||
702 | int ret; | ||
703 | |||
704 | if (!cookie) | ||
705 | return -ENOENT; | ||
471 | 706 | ||
472 | mutex_lock(&local->mtx); | 707 | mutex_lock(&local->mtx); |
473 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | 708 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { |
474 | if (sdata && roc->sdata != sdata) | 709 | if (!mgmt_tx && roc->cookie != cookie) |
475 | continue; | 710 | continue; |
711 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) | ||
712 | continue; | ||
713 | |||
714 | found = roc; | ||
715 | break; | ||
716 | } | ||
717 | |||
718 | if (!found) { | ||
719 | mutex_unlock(&local->mtx); | ||
720 | return -ENOENT; | ||
721 | } | ||
722 | |||
723 | if (!found->started) { | ||
724 | ieee80211_roc_notify_destroy(found); | ||
725 | goto out_unlock; | ||
726 | } | ||
476 | 727 | ||
477 | if (roc->started && local->ops->remain_on_channel) { | 728 | if (local->ops->remain_on_channel) { |
478 | /* can race, so ignore return value */ | 729 | ret = drv_cancel_remain_on_channel(local); |
479 | drv_cancel_remain_on_channel(local); | 730 | if (WARN_ON_ONCE(ret)) { |
731 | mutex_unlock(&local->mtx); | ||
732 | return ret; | ||
733 | } | ||
734 | |||
735 | /* TODO: | ||
736 | * if multiple items were combined here then we really shouldn't | ||
737 | * cancel them all - we should wait for as much time as needed | ||
738 | * for the longest remaining one, and only then cancel ... | ||
739 | */ | ||
740 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | ||
741 | if (!roc->started) | ||
742 | break; | ||
743 | if (roc == found) | ||
744 | found = NULL; | ||
745 | ieee80211_roc_notify_destroy(roc); | ||
480 | } | 746 | } |
481 | 747 | ||
482 | list_move_tail(&roc->list, &tmp_list); | 748 | /* that really must not happen - it was started */ |
483 | roc->abort = true; | 749 | WARN_ON(found); |
750 | |||
751 | ieee80211_start_next_roc(local); | ||
752 | } else { | ||
753 | /* go through work struct to return to the operating channel */ | ||
754 | found->abort = true; | ||
755 | mod_delayed_work(local->workqueue, &local->roc_work, 0); | ||
484 | } | 756 | } |
757 | |||
758 | out_unlock: | ||
485 | mutex_unlock(&local->mtx); | 759 | mutex_unlock(&local->mtx); |
486 | 760 | ||
487 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { | 761 | return 0; |
488 | if (local->ops->remain_on_channel) { | 762 | } |
489 | list_del(&roc->list); | 763 | |
490 | ieee80211_roc_notify_destroy(roc, true); | 764 | int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, |
765 | struct wireless_dev *wdev, u64 cookie) | ||
766 | { | ||
767 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
768 | struct ieee80211_local *local = sdata->local; | ||
769 | |||
770 | return ieee80211_cancel_roc(local, cookie, false); | ||
771 | } | ||
772 | |||
773 | int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
774 | struct cfg80211_mgmt_tx_params *params, u64 *cookie) | ||
775 | { | ||
776 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
777 | struct ieee80211_local *local = sdata->local; | ||
778 | struct sk_buff *skb; | ||
779 | struct sta_info *sta; | ||
780 | const struct ieee80211_mgmt *mgmt = (void *)params->buf; | ||
781 | bool need_offchan = false; | ||
782 | u32 flags; | ||
783 | int ret; | ||
784 | u8 *data; | ||
785 | |||
786 | if (params->dont_wait_for_ack) | ||
787 | flags = IEEE80211_TX_CTL_NO_ACK; | ||
788 | else | ||
789 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | ||
790 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
791 | |||
792 | if (params->no_cck) | ||
793 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | ||
794 | |||
795 | switch (sdata->vif.type) { | ||
796 | case NL80211_IFTYPE_ADHOC: | ||
797 | if (!sdata->vif.bss_conf.ibss_joined) | ||
798 | need_offchan = true; | ||
799 | /* fall through */ | ||
800 | #ifdef CONFIG_MAC80211_MESH | ||
801 | case NL80211_IFTYPE_MESH_POINT: | ||
802 | if (ieee80211_vif_is_mesh(&sdata->vif) && | ||
803 | !sdata->u.mesh.mesh_id_len) | ||
804 | need_offchan = true; | ||
805 | /* fall through */ | ||
806 | #endif | ||
807 | case NL80211_IFTYPE_AP: | ||
808 | case NL80211_IFTYPE_AP_VLAN: | ||
809 | case NL80211_IFTYPE_P2P_GO: | ||
810 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
811 | !ieee80211_vif_is_mesh(&sdata->vif) && | ||
812 | !rcu_access_pointer(sdata->bss->beacon)) | ||
813 | need_offchan = true; | ||
814 | if (!ieee80211_is_action(mgmt->frame_control) || | ||
815 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC || | ||
816 | mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED || | ||
817 | mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) | ||
818 | break; | ||
819 | rcu_read_lock(); | ||
820 | sta = sta_info_get(sdata, mgmt->da); | ||
821 | rcu_read_unlock(); | ||
822 | if (!sta) | ||
823 | return -ENOLINK; | ||
824 | break; | ||
825 | case NL80211_IFTYPE_STATION: | ||
826 | case NL80211_IFTYPE_P2P_CLIENT: | ||
827 | sdata_lock(sdata); | ||
828 | if (!sdata->u.mgd.associated || | ||
829 | (params->offchan && params->wait && | ||
830 | local->ops->remain_on_channel && | ||
831 | memcmp(sdata->u.mgd.associated->bssid, | ||
832 | mgmt->bssid, ETH_ALEN))) | ||
833 | need_offchan = true; | ||
834 | sdata_unlock(sdata); | ||
835 | break; | ||
836 | case NL80211_IFTYPE_P2P_DEVICE: | ||
837 | need_offchan = true; | ||
838 | break; | ||
839 | default: | ||
840 | return -EOPNOTSUPP; | ||
841 | } | ||
842 | |||
843 | /* configurations requiring offchan cannot work if no channel has been | ||
844 | * specified | ||
845 | */ | ||
846 | if (need_offchan && !params->chan) | ||
847 | return -EINVAL; | ||
848 | |||
849 | mutex_lock(&local->mtx); | ||
850 | |||
851 | /* Check if the operating channel is the requested channel */ | ||
852 | if (!need_offchan) { | ||
853 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
854 | |||
855 | rcu_read_lock(); | ||
856 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
857 | |||
858 | if (chanctx_conf) { | ||
859 | need_offchan = params->chan && | ||
860 | (params->chan != | ||
861 | chanctx_conf->def.chan); | ||
862 | } else if (!params->chan) { | ||
863 | ret = -EINVAL; | ||
864 | rcu_read_unlock(); | ||
865 | goto out_unlock; | ||
491 | } else { | 866 | } else { |
492 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); | 867 | need_offchan = true; |
868 | } | ||
869 | rcu_read_unlock(); | ||
870 | } | ||
871 | |||
872 | if (need_offchan && !params->offchan) { | ||
873 | ret = -EBUSY; | ||
874 | goto out_unlock; | ||
875 | } | ||
876 | |||
877 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + params->len); | ||
878 | if (!skb) { | ||
879 | ret = -ENOMEM; | ||
880 | goto out_unlock; | ||
881 | } | ||
882 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
883 | |||
884 | data = skb_put(skb, params->len); | ||
885 | memcpy(data, params->buf, params->len); | ||
886 | |||
887 | /* Update CSA counters */ | ||
888 | if (sdata->vif.csa_active && | ||
889 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
890 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT || | ||
891 | sdata->vif.type == NL80211_IFTYPE_ADHOC) && | ||
892 | params->n_csa_offsets) { | ||
893 | int i; | ||
894 | struct beacon_data *beacon = NULL; | ||
895 | |||
896 | rcu_read_lock(); | ||
897 | |||
898 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
899 | beacon = rcu_dereference(sdata->u.ap.beacon); | ||
900 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
901 | beacon = rcu_dereference(sdata->u.ibss.presp); | ||
902 | else if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
903 | beacon = rcu_dereference(sdata->u.mesh.beacon); | ||
904 | |||
905 | if (beacon) | ||
906 | for (i = 0; i < params->n_csa_offsets; i++) | ||
907 | data[params->csa_offsets[i]] = | ||
908 | beacon->csa_current_counter; | ||
909 | |||
910 | rcu_read_unlock(); | ||
911 | } | ||
493 | 912 | ||
494 | /* work will clean up etc */ | 913 | IEEE80211_SKB_CB(skb)->flags = flags; |
495 | flush_delayed_work(&roc->work); | 914 | |
496 | WARN_ON(!roc->to_be_freed); | 915 | skb->dev = sdata->dev; |
497 | kfree(roc); | 916 | |
917 | if (!params->dont_wait_for_ack) { | ||
918 | /* make a copy to preserve the frame contents | ||
919 | * in case of encryption. | ||
920 | */ | ||
921 | ret = ieee80211_attach_ack_skb(local, skb, cookie, GFP_KERNEL); | ||
922 | if (ret) { | ||
923 | kfree_skb(skb); | ||
924 | goto out_unlock; | ||
498 | } | 925 | } |
926 | } else { | ||
927 | /* Assign a dummy non-zero cookie, it's not sent to | ||
928 | * userspace in this case but we rely on its value | ||
929 | * internally in the need_offchan case to distinguish | ||
930 | * mgmt-tx from remain-on-channel. | ||
931 | */ | ||
932 | *cookie = 0xffffffff; | ||
499 | } | 933 | } |
500 | 934 | ||
501 | WARN_ON_ONCE(!list_empty(&tmp_list)); | 935 | if (!need_offchan) { |
936 | ieee80211_tx_skb(sdata, skb); | ||
937 | ret = 0; | ||
938 | goto out_unlock; | ||
939 | } | ||
940 | |||
941 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN | | ||
942 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | ||
943 | if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) | ||
944 | IEEE80211_SKB_CB(skb)->hw_queue = | ||
945 | local->hw.offchannel_tx_hw_queue; | ||
946 | |||
947 | /* This will handle all kinds of coalescing and immediate TX */ | ||
948 | ret = ieee80211_start_roc_work(local, sdata, params->chan, | ||
949 | params->wait, cookie, skb, | ||
950 | IEEE80211_ROC_TYPE_MGMT_TX); | ||
951 | if (ret) | ||
952 | ieee80211_free_txskb(&local->hw, skb); | ||
953 | out_unlock: | ||
954 | mutex_unlock(&local->mtx); | ||
955 | return ret; | ||
956 | } | ||
957 | |||
958 | int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | ||
959 | struct wireless_dev *wdev, u64 cookie) | ||
960 | { | ||
961 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
962 | |||
963 | return ieee80211_cancel_roc(local, cookie, true); | ||
964 | } | ||
965 | |||
966 | void ieee80211_roc_setup(struct ieee80211_local *local) | ||
967 | { | ||
968 | INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); | ||
969 | INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); | ||
970 | INIT_DELAYED_WORK(&local->roc_work, ieee80211_roc_work); | ||
971 | INIT_LIST_HEAD(&local->roc_list); | ||
972 | } | ||
973 | |||
974 | void ieee80211_roc_purge(struct ieee80211_local *local, | ||
975 | struct ieee80211_sub_if_data *sdata) | ||
976 | { | ||
977 | struct ieee80211_roc_work *roc, *tmp; | ||
978 | bool work_to_do = false; | ||
979 | |||
980 | mutex_lock(&local->mtx); | ||
981 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | ||
982 | if (sdata && roc->sdata != sdata) | ||
983 | continue; | ||
984 | |||
985 | if (roc->started) { | ||
986 | if (local->ops->remain_on_channel) { | ||
987 | /* can race, so ignore return value */ | ||
988 | drv_cancel_remain_on_channel(local); | ||
989 | ieee80211_roc_notify_destroy(roc); | ||
990 | } else { | ||
991 | roc->abort = true; | ||
992 | work_to_do = true; | ||
993 | } | ||
994 | } else { | ||
995 | ieee80211_roc_notify_destroy(roc); | ||
996 | } | ||
997 | } | ||
998 | if (work_to_do) | ||
999 | __ieee80211_roc_work(local); | ||
1000 | mutex_unlock(&local->mtx); | ||
502 | } | 1001 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8bae5de0dc44..bc081850ac0e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -661,8 +661,7 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
661 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) | 661 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) |
662 | { | 662 | { |
663 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 663 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
664 | WARN_ONCE((unsigned long)rx->skb->data & 1, | 664 | WARN_ON_ONCE((unsigned long)rx->skb->data & 1); |
665 | "unaligned packet at 0x%p\n", rx->skb->data); | ||
666 | #endif | 665 | #endif |
667 | } | 666 | } |
668 | 667 | ||
@@ -2736,8 +2735,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2736 | opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; | 2735 | opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; |
2737 | 2736 | ||
2738 | ieee80211_vht_handle_opmode(rx->sdata, rx->sta, | 2737 | ieee80211_vht_handle_opmode(rx->sdata, rx->sta, |
2739 | opmode, status->band, | 2738 | opmode, status->band); |
2740 | false); | ||
2741 | goto handled; | 2739 | goto handled; |
2742 | } | 2740 | } |
2743 | default: | 2741 | default: |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 4aeca4b0c3cb..a413e52f7691 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -597,8 +597,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
597 | /* We need to ensure power level is at max for scanning. */ | 597 | /* We need to ensure power level is at max for scanning. */ |
598 | ieee80211_hw_config(local, 0); | 598 | ieee80211_hw_config(local, 0); |
599 | 599 | ||
600 | if ((req->channels[0]->flags & | 600 | if ((req->channels[0]->flags & (IEEE80211_CHAN_NO_IR | |
601 | IEEE80211_CHAN_NO_IR) || | 601 | IEEE80211_CHAN_RADAR)) || |
602 | !req->n_ssids) { | 602 | !req->n_ssids) { |
603 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 603 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
604 | } else { | 604 | } else { |
@@ -645,7 +645,7 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) | |||
645 | * TODO: channel switching also consumes quite some time, | 645 | * TODO: channel switching also consumes quite some time, |
646 | * add that delay as well to get a better estimation | 646 | * add that delay as well to get a better estimation |
647 | */ | 647 | */ |
648 | if (chan->flags & IEEE80211_CHAN_NO_IR) | 648 | if (chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) |
649 | return IEEE80211_PASSIVE_CHANNEL_TIME; | 649 | return IEEE80211_PASSIVE_CHANNEL_TIME; |
650 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; | 650 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; |
651 | } | 651 | } |
@@ -777,7 +777,8 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
777 | * | 777 | * |
778 | * In any case, it is not necessary for a passive scan. | 778 | * In any case, it is not necessary for a passive scan. |
779 | */ | 779 | */ |
780 | if (chan->flags & IEEE80211_CHAN_NO_IR || !scan_req->n_ssids) { | 780 | if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) || |
781 | !scan_req->n_ssids) { | ||
781 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 782 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
782 | local->next_scan_state = SCAN_DECISION; | 783 | local->next_scan_state = SCAN_DECISION; |
783 | return; | 784 | return; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f91d1873218c..4402ad5b27d1 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 3 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
4 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 4 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
5 | * Copyright (C) 2015 Intel Deutschland GmbH | ||
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 |
@@ -435,6 +436,19 @@ static int sta_info_insert_check(struct sta_info *sta) | |||
435 | is_multicast_ether_addr(sta->sta.addr))) | 436 | is_multicast_ether_addr(sta->sta.addr))) |
436 | return -EINVAL; | 437 | return -EINVAL; |
437 | 438 | ||
439 | /* Strictly speaking this isn't necessary as we hold the mutex, but | ||
440 | * the rhashtable code can't really deal with that distinction. We | ||
441 | * do require the mutex for correctness though. | ||
442 | */ | ||
443 | rcu_read_lock(); | ||
444 | lockdep_assert_held(&sdata->local->sta_mtx); | ||
445 | if (ieee80211_hw_check(&sdata->local->hw, NEEDS_UNIQUE_STA_ADDR) && | ||
446 | ieee80211_find_sta_by_ifaddr(&sdata->local->hw, sta->addr, NULL)) { | ||
447 | rcu_read_unlock(); | ||
448 | return -ENOTUNIQ; | ||
449 | } | ||
450 | rcu_read_unlock(); | ||
451 | |||
438 | return 0; | 452 | return 0; |
439 | } | 453 | } |
440 | 454 | ||
@@ -554,14 +568,15 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | |||
554 | 568 | ||
555 | might_sleep(); | 569 | might_sleep(); |
556 | 570 | ||
571 | mutex_lock(&local->sta_mtx); | ||
572 | |||
557 | err = sta_info_insert_check(sta); | 573 | err = sta_info_insert_check(sta); |
558 | if (err) { | 574 | if (err) { |
575 | mutex_unlock(&local->sta_mtx); | ||
559 | rcu_read_lock(); | 576 | rcu_read_lock(); |
560 | goto out_free; | 577 | goto out_free; |
561 | } | 578 | } |
562 | 579 | ||
563 | mutex_lock(&local->sta_mtx); | ||
564 | |||
565 | err = sta_info_insert_finish(sta); | 580 | err = sta_info_insert_finish(sta); |
566 | if (err) | 581 | if (err) |
567 | goto out_free; | 582 | goto out_free; |
@@ -868,6 +883,7 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta) | |||
868 | } | 883 | } |
869 | 884 | ||
870 | list_del_rcu(&sta->list); | 885 | list_del_rcu(&sta->list); |
886 | sta->removed = true; | ||
871 | 887 | ||
872 | drv_sta_pre_rcu_remove(local, sta->sdata, sta); | 888 | drv_sta_pre_rcu_remove(local, sta->sdata, sta); |
873 | 889 | ||
@@ -1230,11 +1246,11 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1230 | ieee80211_check_fast_xmit(sta); | 1246 | ieee80211_check_fast_xmit(sta); |
1231 | } | 1247 | } |
1232 | 1248 | ||
1233 | static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | 1249 | static void ieee80211_send_null_response(struct sta_info *sta, int tid, |
1234 | struct sta_info *sta, int tid, | ||
1235 | enum ieee80211_frame_release_type reason, | 1250 | enum ieee80211_frame_release_type reason, |
1236 | bool call_driver) | 1251 | bool call_driver, bool more_data) |
1237 | { | 1252 | { |
1253 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
1238 | struct ieee80211_local *local = sdata->local; | 1254 | struct ieee80211_local *local = sdata->local; |
1239 | struct ieee80211_qos_hdr *nullfunc; | 1255 | struct ieee80211_qos_hdr *nullfunc; |
1240 | struct sk_buff *skb; | 1256 | struct sk_buff *skb; |
@@ -1274,9 +1290,13 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
1274 | if (qos) { | 1290 | if (qos) { |
1275 | nullfunc->qos_ctrl = cpu_to_le16(tid); | 1291 | nullfunc->qos_ctrl = cpu_to_le16(tid); |
1276 | 1292 | ||
1277 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD) | 1293 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD) { |
1278 | nullfunc->qos_ctrl |= | 1294 | nullfunc->qos_ctrl |= |
1279 | cpu_to_le16(IEEE80211_QOS_CTL_EOSP); | 1295 | cpu_to_le16(IEEE80211_QOS_CTL_EOSP); |
1296 | if (more_data) | ||
1297 | nullfunc->frame_control |= | ||
1298 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
1299 | } | ||
1280 | } | 1300 | } |
1281 | 1301 | ||
1282 | info = IEEE80211_SKB_CB(skb); | 1302 | info = IEEE80211_SKB_CB(skb); |
@@ -1323,22 +1343,48 @@ static int find_highest_prio_tid(unsigned long tids) | |||
1323 | return fls(tids) - 1; | 1343 | return fls(tids) - 1; |
1324 | } | 1344 | } |
1325 | 1345 | ||
1346 | /* Indicates if the MORE_DATA bit should be set in the last | ||
1347 | * frame obtained by ieee80211_sta_ps_get_frames. | ||
1348 | * Note that driver_release_tids is relevant only if | ||
1349 | * reason = IEEE80211_FRAME_RELEASE_PSPOLL | ||
1350 | */ | ||
1351 | static bool | ||
1352 | ieee80211_sta_ps_more_data(struct sta_info *sta, u8 ignored_acs, | ||
1353 | enum ieee80211_frame_release_type reason, | ||
1354 | unsigned long driver_release_tids) | ||
1355 | { | ||
1356 | int ac; | ||
1357 | |||
1358 | /* If the driver has data on more than one TID then | ||
1359 | * certainly there's more data if we release just a | ||
1360 | * single frame now (from a single TID). This will | ||
1361 | * only happen for PS-Poll. | ||
1362 | */ | ||
1363 | if (reason == IEEE80211_FRAME_RELEASE_PSPOLL && | ||
1364 | hweight16(driver_release_tids) > 1) | ||
1365 | return true; | ||
1366 | |||
1367 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
1368 | if (ignored_acs & BIT(ac)) | ||
1369 | continue; | ||
1370 | |||
1371 | if (!skb_queue_empty(&sta->tx_filtered[ac]) || | ||
1372 | !skb_queue_empty(&sta->ps_tx_buf[ac])) | ||
1373 | return true; | ||
1374 | } | ||
1375 | |||
1376 | return false; | ||
1377 | } | ||
1378 | |||
1326 | static void | 1379 | static void |
1327 | ieee80211_sta_ps_deliver_response(struct sta_info *sta, | 1380 | ieee80211_sta_ps_get_frames(struct sta_info *sta, int n_frames, u8 ignored_acs, |
1328 | int n_frames, u8 ignored_acs, | 1381 | enum ieee80211_frame_release_type reason, |
1329 | enum ieee80211_frame_release_type reason) | 1382 | struct sk_buff_head *frames, |
1383 | unsigned long *driver_release_tids) | ||
1330 | { | 1384 | { |
1331 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1385 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1332 | struct ieee80211_local *local = sdata->local; | 1386 | struct ieee80211_local *local = sdata->local; |
1333 | bool more_data = false; | ||
1334 | int ac; | 1387 | int ac; |
1335 | unsigned long driver_release_tids = 0; | ||
1336 | struct sk_buff_head frames; | ||
1337 | |||
1338 | /* Service or PS-Poll period starts */ | ||
1339 | set_sta_flag(sta, WLAN_STA_SP); | ||
1340 | |||
1341 | __skb_queue_head_init(&frames); | ||
1342 | 1388 | ||
1343 | /* Get response frame(s) and more data bit for the last one. */ | 1389 | /* Get response frame(s) and more data bit for the last one. */ |
1344 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 1390 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
@@ -1352,26 +1398,13 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1352 | /* if we already have frames from software, then we can't also | 1398 | /* if we already have frames from software, then we can't also |
1353 | * release from hardware queues | 1399 | * release from hardware queues |
1354 | */ | 1400 | */ |
1355 | if (skb_queue_empty(&frames)) { | 1401 | if (skb_queue_empty(frames)) { |
1356 | driver_release_tids |= sta->driver_buffered_tids & tids; | 1402 | *driver_release_tids |= |
1357 | driver_release_tids |= sta->txq_buffered_tids & tids; | 1403 | sta->driver_buffered_tids & tids; |
1404 | *driver_release_tids |= sta->txq_buffered_tids & tids; | ||
1358 | } | 1405 | } |
1359 | 1406 | ||
1360 | if (driver_release_tids) { | 1407 | if (!*driver_release_tids) { |
1361 | /* If the driver has data on more than one TID then | ||
1362 | * certainly there's more data if we release just a | ||
1363 | * single frame now (from a single TID). This will | ||
1364 | * only happen for PS-Poll. | ||
1365 | */ | ||
1366 | if (reason == IEEE80211_FRAME_RELEASE_PSPOLL && | ||
1367 | hweight16(driver_release_tids) > 1) { | ||
1368 | more_data = true; | ||
1369 | driver_release_tids = | ||
1370 | BIT(find_highest_prio_tid( | ||
1371 | driver_release_tids)); | ||
1372 | break; | ||
1373 | } | ||
1374 | } else { | ||
1375 | struct sk_buff *skb; | 1408 | struct sk_buff *skb; |
1376 | 1409 | ||
1377 | while (n_frames > 0) { | 1410 | while (n_frames > 0) { |
@@ -1385,20 +1418,44 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1385 | if (!skb) | 1418 | if (!skb) |
1386 | break; | 1419 | break; |
1387 | n_frames--; | 1420 | n_frames--; |
1388 | __skb_queue_tail(&frames, skb); | 1421 | __skb_queue_tail(frames, skb); |
1389 | } | 1422 | } |
1390 | } | 1423 | } |
1391 | 1424 | ||
1392 | /* If we have more frames buffered on this AC, then set the | 1425 | /* If we have more frames buffered on this AC, then abort the |
1393 | * more-data bit and abort the loop since we can't send more | 1426 | * loop since we can't send more data from other ACs before |
1394 | * data from other ACs before the buffered frames from this. | 1427 | * the buffered frames from this. |
1395 | */ | 1428 | */ |
1396 | if (!skb_queue_empty(&sta->tx_filtered[ac]) || | 1429 | if (!skb_queue_empty(&sta->tx_filtered[ac]) || |
1397 | !skb_queue_empty(&sta->ps_tx_buf[ac])) { | 1430 | !skb_queue_empty(&sta->ps_tx_buf[ac])) |
1398 | more_data = true; | ||
1399 | break; | 1431 | break; |
1400 | } | ||
1401 | } | 1432 | } |
1433 | } | ||
1434 | |||
1435 | static void | ||
1436 | ieee80211_sta_ps_deliver_response(struct sta_info *sta, | ||
1437 | int n_frames, u8 ignored_acs, | ||
1438 | enum ieee80211_frame_release_type reason) | ||
1439 | { | ||
1440 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
1441 | struct ieee80211_local *local = sdata->local; | ||
1442 | unsigned long driver_release_tids = 0; | ||
1443 | struct sk_buff_head frames; | ||
1444 | bool more_data; | ||
1445 | |||
1446 | /* Service or PS-Poll period starts */ | ||
1447 | set_sta_flag(sta, WLAN_STA_SP); | ||
1448 | |||
1449 | __skb_queue_head_init(&frames); | ||
1450 | |||
1451 | ieee80211_sta_ps_get_frames(sta, n_frames, ignored_acs, reason, | ||
1452 | &frames, &driver_release_tids); | ||
1453 | |||
1454 | more_data = ieee80211_sta_ps_more_data(sta, ignored_acs, reason, driver_release_tids); | ||
1455 | |||
1456 | if (reason == IEEE80211_FRAME_RELEASE_PSPOLL) | ||
1457 | driver_release_tids = | ||
1458 | BIT(find_highest_prio_tid(driver_release_tids)); | ||
1402 | 1459 | ||
1403 | if (skb_queue_empty(&frames) && !driver_release_tids) { | 1460 | if (skb_queue_empty(&frames) && !driver_release_tids) { |
1404 | int tid; | 1461 | int tid; |
@@ -1421,7 +1478,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1421 | /* This will evaluate to 1, 3, 5 or 7. */ | 1478 | /* This will evaluate to 1, 3, 5 or 7. */ |
1422 | tid = 7 - ((ffs(~ignored_acs) - 1) << 1); | 1479 | tid = 7 - ((ffs(~ignored_acs) - 1) << 1); |
1423 | 1480 | ||
1424 | ieee80211_send_null_response(sdata, sta, tid, reason, true); | 1481 | ieee80211_send_null_response(sta, tid, reason, true, false); |
1425 | } else if (!driver_release_tids) { | 1482 | } else if (!driver_release_tids) { |
1426 | struct sk_buff_head pending; | 1483 | struct sk_buff_head pending; |
1427 | struct sk_buff *skb; | 1484 | struct sk_buff *skb; |
@@ -1521,8 +1578,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1521 | 1578 | ||
1522 | if (need_null) | 1579 | if (need_null) |
1523 | ieee80211_send_null_response( | 1580 | ieee80211_send_null_response( |
1524 | sdata, sta, find_highest_prio_tid(tids), | 1581 | sta, find_highest_prio_tid(tids), |
1525 | reason, false); | 1582 | reason, false, false); |
1526 | 1583 | ||
1527 | sta_info_recalc_tim(sta); | 1584 | sta_info_recalc_tim(sta); |
1528 | } else { | 1585 | } else { |
@@ -1660,6 +1717,22 @@ void ieee80211_sta_eosp(struct ieee80211_sta *pubsta) | |||
1660 | } | 1717 | } |
1661 | EXPORT_SYMBOL(ieee80211_sta_eosp); | 1718 | EXPORT_SYMBOL(ieee80211_sta_eosp); |
1662 | 1719 | ||
1720 | void ieee80211_send_eosp_nullfunc(struct ieee80211_sta *pubsta, int tid) | ||
1721 | { | ||
1722 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | ||
1723 | enum ieee80211_frame_release_type reason; | ||
1724 | bool more_data; | ||
1725 | |||
1726 | trace_api_send_eosp_nullfunc(sta->local, pubsta, tid); | ||
1727 | |||
1728 | reason = IEEE80211_FRAME_RELEASE_UAPSD; | ||
1729 | more_data = ieee80211_sta_ps_more_data(sta, ~sta->sta.uapsd_queues, | ||
1730 | reason, 0); | ||
1731 | |||
1732 | ieee80211_send_null_response(sta, tid, reason, false, more_data); | ||
1733 | } | ||
1734 | EXPORT_SYMBOL(ieee80211_send_eosp_nullfunc); | ||
1735 | |||
1663 | void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | 1736 | void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, |
1664 | u8 tid, bool buffered) | 1737 | u8 tid, bool buffered) |
1665 | { | 1738 | { |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 2cafb21b422f..d6051629ed15 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -367,6 +367,7 @@ DECLARE_EWMA(signal, 1024, 8) | |||
367 | * @mesh: mesh STA information | 367 | * @mesh: mesh STA information |
368 | * @debugfs: debug filesystem info | 368 | * @debugfs: debug filesystem info |
369 | * @dead: set to true when sta is unlinked | 369 | * @dead: set to true when sta is unlinked |
370 | * @removed: set to true when sta is being removed from sta_list | ||
370 | * @uploaded: set to true when sta is uploaded to the driver | 371 | * @uploaded: set to true when sta is uploaded to the driver |
371 | * @sta: station information we share with the driver | 372 | * @sta: station information we share with the driver |
372 | * @sta_state: duplicates information about station state (for debug) | 373 | * @sta_state: duplicates information about station state (for debug) |
@@ -412,6 +413,7 @@ struct sta_info { | |||
412 | u16 listen_interval; | 413 | u16 listen_interval; |
413 | 414 | ||
414 | bool dead; | 415 | bool dead; |
416 | bool removed; | ||
415 | 417 | ||
416 | bool uploaded; | 418 | bool uploaded; |
417 | 419 | ||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 56c6d6cfa5a1..a6b4442776a0 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -2027,6 +2027,31 @@ TRACE_EVENT(api_eosp, | |||
2027 | ) | 2027 | ) |
2028 | ); | 2028 | ); |
2029 | 2029 | ||
2030 | TRACE_EVENT(api_send_eosp_nullfunc, | ||
2031 | TP_PROTO(struct ieee80211_local *local, | ||
2032 | struct ieee80211_sta *sta, | ||
2033 | u8 tid), | ||
2034 | |||
2035 | TP_ARGS(local, sta, tid), | ||
2036 | |||
2037 | TP_STRUCT__entry( | ||
2038 | LOCAL_ENTRY | ||
2039 | STA_ENTRY | ||
2040 | __field(u8, tid) | ||
2041 | ), | ||
2042 | |||
2043 | TP_fast_assign( | ||
2044 | LOCAL_ASSIGN; | ||
2045 | STA_ASSIGN; | ||
2046 | __entry->tid = tid; | ||
2047 | ), | ||
2048 | |||
2049 | TP_printk( | ||
2050 | LOCAL_PR_FMT STA_PR_FMT " tid:%d", | ||
2051 | LOCAL_PR_ARG, STA_PR_ARG, __entry->tid | ||
2052 | ) | ||
2053 | ); | ||
2054 | |||
2030 | TRACE_EVENT(api_sta_set_buffered, | 2055 | TRACE_EVENT(api_sta_set_buffered, |
2031 | TP_PROTO(struct ieee80211_local *local, | 2056 | TP_PROTO(struct ieee80211_local *local, |
2032 | struct ieee80211_sta *sta, | 2057 | struct ieee80211_sta *sta, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index bdc224d5053a..3311ce0f3d6c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1431,7 +1431,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local, | |||
1431 | info->hw_queue = | 1431 | info->hw_queue = |
1432 | vif->hw_queue[skb_get_queue_mapping(skb)]; | 1432 | vif->hw_queue[skb_get_queue_mapping(skb)]; |
1433 | } else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) { | 1433 | } else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) { |
1434 | dev_kfree_skb(skb); | 1434 | ieee80211_purge_tx_queue(&local->hw, skbs); |
1435 | return true; | 1435 | return true; |
1436 | } else | 1436 | } else |
1437 | vif = NULL; | 1437 | vif = NULL; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 74058020b7d6..3943d4bf289c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -288,10 +288,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
288 | if (!test_bit(reason, &local->queue_stop_reasons[queue])) | 288 | if (!test_bit(reason, &local->queue_stop_reasons[queue])) |
289 | return; | 289 | return; |
290 | 290 | ||
291 | if (!refcounted) | 291 | if (!refcounted) { |
292 | local->q_stop_reasons[queue][reason] = 0; | 292 | local->q_stop_reasons[queue][reason] = 0; |
293 | else | 293 | } else { |
294 | local->q_stop_reasons[queue][reason]--; | 294 | local->q_stop_reasons[queue][reason]--; |
295 | if (WARN_ON(local->q_stop_reasons[queue][reason] < 0)) | ||
296 | local->q_stop_reasons[queue][reason] = 0; | ||
297 | } | ||
295 | 298 | ||
296 | if (local->q_stop_reasons[queue][reason] == 0) | 299 | if (local->q_stop_reasons[queue][reason] == 0) |
297 | __clear_bit(reason, &local->queue_stop_reasons[queue]); | 300 | __clear_bit(reason, &local->queue_stop_reasons[queue]); |
@@ -1641,6 +1644,29 @@ void ieee80211_stop_device(struct ieee80211_local *local) | |||
1641 | drv_stop(local); | 1644 | drv_stop(local); |
1642 | } | 1645 | } |
1643 | 1646 | ||
1647 | static void ieee80211_flush_completed_scan(struct ieee80211_local *local, | ||
1648 | bool aborted) | ||
1649 | { | ||
1650 | /* It's possible that we don't handle the scan completion in | ||
1651 | * time during suspend, so if it's still marked as completed | ||
1652 | * here, queue the work and flush it to clean things up. | ||
1653 | * Instead of calling the worker function directly here, we | ||
1654 | * really queue it to avoid potential races with other flows | ||
1655 | * scheduling the same work. | ||
1656 | */ | ||
1657 | if (test_bit(SCAN_COMPLETED, &local->scanning)) { | ||
1658 | /* If coming from reconfiguration failure, abort the scan so | ||
1659 | * we don't attempt to continue a partial HW scan - which is | ||
1660 | * possible otherwise if (e.g.) the 2.4 GHz portion was the | ||
1661 | * completed scan, and a 5 GHz portion is still pending. | ||
1662 | */ | ||
1663 | if (aborted) | ||
1664 | set_bit(SCAN_ABORTED, &local->scanning); | ||
1665 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); | ||
1666 | flush_delayed_work(&local->scan_work); | ||
1667 | } | ||
1668 | } | ||
1669 | |||
1644 | static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) | 1670 | static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) |
1645 | { | 1671 | { |
1646 | struct ieee80211_sub_if_data *sdata; | 1672 | struct ieee80211_sub_if_data *sdata; |
@@ -1660,6 +1686,8 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) | |||
1660 | local->suspended = false; | 1686 | local->suspended = false; |
1661 | local->in_reconfig = false; | 1687 | local->in_reconfig = false; |
1662 | 1688 | ||
1689 | ieee80211_flush_completed_scan(local, true); | ||
1690 | |||
1663 | /* scheduled scan clearly can't be running any more, but tell | 1691 | /* scheduled scan clearly can't be running any more, but tell |
1664 | * cfg80211 and clear local state | 1692 | * cfg80211 and clear local state |
1665 | */ | 1693 | */ |
@@ -1698,6 +1726,27 @@ static void ieee80211_assign_chanctx(struct ieee80211_local *local, | |||
1698 | mutex_unlock(&local->chanctx_mtx); | 1726 | mutex_unlock(&local->chanctx_mtx); |
1699 | } | 1727 | } |
1700 | 1728 | ||
1729 | static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata) | ||
1730 | { | ||
1731 | struct ieee80211_local *local = sdata->local; | ||
1732 | struct sta_info *sta; | ||
1733 | |||
1734 | /* add STAs back */ | ||
1735 | mutex_lock(&local->sta_mtx); | ||
1736 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1737 | enum ieee80211_sta_state state; | ||
1738 | |||
1739 | if (!sta->uploaded || sta->sdata != sdata) | ||
1740 | continue; | ||
1741 | |||
1742 | for (state = IEEE80211_STA_NOTEXIST; | ||
1743 | state < sta->sta_state; state++) | ||
1744 | WARN_ON(drv_sta_state(local, sta->sdata, sta, state, | ||
1745 | state + 1)); | ||
1746 | } | ||
1747 | mutex_unlock(&local->sta_mtx); | ||
1748 | } | ||
1749 | |||
1701 | int ieee80211_reconfig(struct ieee80211_local *local) | 1750 | int ieee80211_reconfig(struct ieee80211_local *local) |
1702 | { | 1751 | { |
1703 | struct ieee80211_hw *hw = &local->hw; | 1752 | struct ieee80211_hw *hw = &local->hw; |
@@ -1833,50 +1882,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1833 | WARN_ON(drv_add_chanctx(local, ctx)); | 1882 | WARN_ON(drv_add_chanctx(local, ctx)); |
1834 | mutex_unlock(&local->chanctx_mtx); | 1883 | mutex_unlock(&local->chanctx_mtx); |
1835 | 1884 | ||
1836 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1837 | if (!ieee80211_sdata_running(sdata)) | ||
1838 | continue; | ||
1839 | ieee80211_assign_chanctx(local, sdata); | ||
1840 | } | ||
1841 | |||
1842 | sdata = rtnl_dereference(local->monitor_sdata); | 1885 | sdata = rtnl_dereference(local->monitor_sdata); |
1843 | if (sdata && ieee80211_sdata_running(sdata)) | 1886 | if (sdata && ieee80211_sdata_running(sdata)) |
1844 | ieee80211_assign_chanctx(local, sdata); | 1887 | ieee80211_assign_chanctx(local, sdata); |
1845 | } | 1888 | } |
1846 | 1889 | ||
1847 | /* add STAs back */ | ||
1848 | mutex_lock(&local->sta_mtx); | ||
1849 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1850 | enum ieee80211_sta_state state; | ||
1851 | |||
1852 | if (!sta->uploaded) | ||
1853 | continue; | ||
1854 | |||
1855 | /* AP-mode stations will be added later */ | ||
1856 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | ||
1857 | continue; | ||
1858 | |||
1859 | for (state = IEEE80211_STA_NOTEXIST; | ||
1860 | state < sta->sta_state; state++) | ||
1861 | WARN_ON(drv_sta_state(local, sta->sdata, sta, state, | ||
1862 | state + 1)); | ||
1863 | } | ||
1864 | mutex_unlock(&local->sta_mtx); | ||
1865 | |||
1866 | /* reconfigure tx conf */ | ||
1867 | if (hw->queues >= IEEE80211_NUM_ACS) { | ||
1868 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1869 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
1870 | sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
1871 | !ieee80211_sdata_running(sdata)) | ||
1872 | continue; | ||
1873 | |||
1874 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | ||
1875 | drv_conf_tx(local, sdata, i, | ||
1876 | &sdata->tx_conf[i]); | ||
1877 | } | ||
1878 | } | ||
1879 | |||
1880 | /* reconfigure hardware */ | 1890 | /* reconfigure hardware */ |
1881 | ieee80211_hw_config(local, ~0); | 1891 | ieee80211_hw_config(local, ~0); |
1882 | 1892 | ||
@@ -1889,6 +1899,22 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1889 | if (!ieee80211_sdata_running(sdata)) | 1899 | if (!ieee80211_sdata_running(sdata)) |
1890 | continue; | 1900 | continue; |
1891 | 1901 | ||
1902 | ieee80211_assign_chanctx(local, sdata); | ||
1903 | |||
1904 | switch (sdata->vif.type) { | ||
1905 | case NL80211_IFTYPE_AP_VLAN: | ||
1906 | case NL80211_IFTYPE_MONITOR: | ||
1907 | break; | ||
1908 | default: | ||
1909 | ieee80211_reconfig_stations(sdata); | ||
1910 | /* fall through */ | ||
1911 | case NL80211_IFTYPE_AP: /* AP stations are handled later */ | ||
1912 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | ||
1913 | drv_conf_tx(local, sdata, i, | ||
1914 | &sdata->tx_conf[i]); | ||
1915 | break; | ||
1916 | } | ||
1917 | |||
1892 | /* common change flags for all interface types */ | 1918 | /* common change flags for all interface types */ |
1893 | changed = BSS_CHANGED_ERP_CTS_PROT | | 1919 | changed = BSS_CHANGED_ERP_CTS_PROT | |
1894 | BSS_CHANGED_ERP_PREAMBLE | | 1920 | BSS_CHANGED_ERP_PREAMBLE | |
@@ -2074,17 +2100,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
2074 | mb(); | 2100 | mb(); |
2075 | local->resuming = false; | 2101 | local->resuming = false; |
2076 | 2102 | ||
2077 | /* It's possible that we don't handle the scan completion in | 2103 | ieee80211_flush_completed_scan(local, false); |
2078 | * time during suspend, so if it's still marked as completed | ||
2079 | * here, queue the work and flush it to clean things up. | ||
2080 | * Instead of calling the worker function directly here, we | ||
2081 | * really queue it to avoid potential races with other flows | ||
2082 | * scheduling the same work. | ||
2083 | */ | ||
2084 | if (test_bit(SCAN_COMPLETED, &local->scanning)) { | ||
2085 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); | ||
2086 | flush_delayed_work(&local->scan_work); | ||
2087 | } | ||
2088 | 2104 | ||
2089 | if (local->open_count && !reconfig_due_to_wowlan) | 2105 | if (local->open_count && !reconfig_due_to_wowlan) |
2090 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); | 2106 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index ff1c798921a6..c38b2f07a919 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -378,7 +378,7 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) | |||
378 | 378 | ||
379 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 379 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
380 | struct sta_info *sta, u8 opmode, | 380 | struct sta_info *sta, u8 opmode, |
381 | enum ieee80211_band band, bool nss_only) | 381 | enum ieee80211_band band) |
382 | { | 382 | { |
383 | struct ieee80211_local *local = sdata->local; | 383 | struct ieee80211_local *local = sdata->local; |
384 | struct ieee80211_supported_band *sband; | 384 | struct ieee80211_supported_band *sband; |
@@ -401,9 +401,6 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
401 | changed |= IEEE80211_RC_NSS_CHANGED; | 401 | changed |= IEEE80211_RC_NSS_CHANGED; |
402 | } | 402 | } |
403 | 403 | ||
404 | if (nss_only) | ||
405 | return changed; | ||
406 | |||
407 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { | 404 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { |
408 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: | 405 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: |
409 | sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20; | 406 | sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20; |
@@ -430,13 +427,12 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
430 | 427 | ||
431 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 428 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
432 | struct sta_info *sta, u8 opmode, | 429 | struct sta_info *sta, u8 opmode, |
433 | enum ieee80211_band band, bool nss_only) | 430 | enum ieee80211_band band) |
434 | { | 431 | { |
435 | struct ieee80211_local *local = sdata->local; | 432 | struct ieee80211_local *local = sdata->local; |
436 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | 433 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
437 | 434 | ||
438 | u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, | 435 | u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band); |
439 | band, nss_only); | ||
440 | 436 | ||
441 | if (changed > 0) | 437 | if (changed > 0) |
442 | rate_control_rate_update(local, sband, sta, changed); | 438 | rate_control_rate_update(local, sband, sta, changed); |
diff --git a/net/mac802154/driver-ops.h b/net/mac802154/driver-ops.h index 0550f3365e33..fd9daf2ecec9 100644 --- a/net/mac802154/driver-ops.h +++ b/net/mac802154/driver-ops.h | |||
@@ -18,9 +18,6 @@ drv_xmit_async(struct ieee802154_local *local, struct sk_buff *skb) | |||
18 | static inline int | 18 | static inline int |
19 | drv_xmit_sync(struct ieee802154_local *local, struct sk_buff *skb) | 19 | drv_xmit_sync(struct ieee802154_local *local, struct sk_buff *skb) |
20 | { | 20 | { |
21 | /* don't allow other operations while sync xmit */ | ||
22 | ASSERT_RTNL(); | ||
23 | |||
24 | might_sleep(); | 21 | might_sleep(); |
25 | 22 | ||
26 | return local->ops->xmit_sync(&local->hw, skb); | 23 | return local->ops->xmit_sync(&local->hw, skb); |
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c index 8606da459ff3..3db16346cab3 100644 --- a/net/mac802154/mac_cmd.c +++ b/net/mac802154/mac_cmd.c | |||
@@ -126,7 +126,7 @@ static void mac802154_get_mac_params(struct net_device *dev, | |||
126 | params->lbt = wpan_dev->lbt; | 126 | params->lbt = wpan_dev->lbt; |
127 | } | 127 | } |
128 | 128 | ||
129 | static struct ieee802154_llsec_ops mac802154_llsec_ops = { | 129 | static const struct ieee802154_llsec_ops mac802154_llsec_ops = { |
130 | .get_params = mac802154_get_params, | 130 | .get_params = mac802154_get_params, |
131 | .set_params = mac802154_set_params, | 131 | .set_params = mac802154_set_params, |
132 | .add_key = mac802154_add_key, | 132 | .add_key = mac802154_add_key, |
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c index 42e96729dae6..446e1300383e 100644 --- a/net/mac802154/rx.c +++ b/net/mac802154/rx.c | |||
@@ -217,8 +217,7 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local, | |||
217 | break; | 217 | break; |
218 | } | 218 | } |
219 | 219 | ||
220 | if (skb) | 220 | kfree_skb(skb); |
221 | kfree_skb(skb); | ||
222 | } | 221 | } |
223 | 222 | ||
224 | static void | 223 | static void |
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c index 3827f359b336..7e253455f9dd 100644 --- a/net/mac802154/tx.c +++ b/net/mac802154/tx.c | |||
@@ -38,12 +38,6 @@ void ieee802154_xmit_worker(struct work_struct *work) | |||
38 | struct net_device *dev = skb->dev; | 38 | struct net_device *dev = skb->dev; |
39 | int res; | 39 | int res; |
40 | 40 | ||
41 | rtnl_lock(); | ||
42 | |||
43 | /* check if ifdown occurred while schedule */ | ||
44 | if (!netif_running(dev)) | ||
45 | goto err_tx; | ||
46 | |||
47 | res = drv_xmit_sync(local, skb); | 41 | res = drv_xmit_sync(local, skb); |
48 | if (res) | 42 | if (res) |
49 | goto err_tx; | 43 | goto err_tx; |
@@ -53,14 +47,11 @@ void ieee802154_xmit_worker(struct work_struct *work) | |||
53 | dev->stats.tx_packets++; | 47 | dev->stats.tx_packets++; |
54 | dev->stats.tx_bytes += skb->len; | 48 | dev->stats.tx_bytes += skb->len; |
55 | 49 | ||
56 | rtnl_unlock(); | ||
57 | |||
58 | return; | 50 | return; |
59 | 51 | ||
60 | err_tx: | 52 | err_tx: |
61 | /* Restart the netif queue on each sub_if_data object. */ | 53 | /* Restart the netif queue on each sub_if_data object. */ |
62 | ieee802154_wake_queue(&local->hw); | 54 | ieee802154_wake_queue(&local->hw); |
63 | rtnl_unlock(); | ||
64 | kfree_skb(skb); | 55 | kfree_skb(skb); |
65 | netdev_dbg(dev, "transmission failed\n"); | 56 | netdev_dbg(dev, "transmission failed\n"); |
66 | } | 57 | } |
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index c70d750148b6..b18c5ed42d95 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -27,6 +27,8 @@ | |||
27 | */ | 27 | */ |
28 | #define MAX_MP_SELECT_LABELS 4 | 28 | #define MAX_MP_SELECT_LABELS 4 |
29 | 29 | ||
30 | #define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1) | ||
31 | |||
30 | static int zero = 0; | 32 | static int zero = 0; |
31 | static int label_limit = (1 << 20) - 1; | 33 | static int label_limit = (1 << 20) - 1; |
32 | 34 | ||
@@ -96,22 +98,15 @@ bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) | |||
96 | } | 98 | } |
97 | EXPORT_SYMBOL_GPL(mpls_pkt_too_big); | 99 | EXPORT_SYMBOL_GPL(mpls_pkt_too_big); |
98 | 100 | ||
99 | static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt, | 101 | static u32 mpls_multipath_hash(struct mpls_route *rt, |
100 | struct sk_buff *skb, bool bos) | 102 | struct sk_buff *skb, bool bos) |
101 | { | 103 | { |
102 | struct mpls_entry_decoded dec; | 104 | struct mpls_entry_decoded dec; |
103 | struct mpls_shim_hdr *hdr; | 105 | struct mpls_shim_hdr *hdr; |
104 | bool eli_seen = false; | 106 | bool eli_seen = false; |
105 | int label_index; | 107 | int label_index; |
106 | int nh_index = 0; | ||
107 | u32 hash = 0; | 108 | u32 hash = 0; |
108 | 109 | ||
109 | /* No need to look further into packet if there's only | ||
110 | * one path | ||
111 | */ | ||
112 | if (rt->rt_nhn == 1) | ||
113 | goto out; | ||
114 | |||
115 | for (label_index = 0; label_index < MAX_MP_SELECT_LABELS && !bos; | 110 | for (label_index = 0; label_index < MAX_MP_SELECT_LABELS && !bos; |
116 | label_index++) { | 111 | label_index++) { |
117 | if (!pskb_may_pull(skb, sizeof(*hdr) * label_index)) | 112 | if (!pskb_may_pull(skb, sizeof(*hdr) * label_index)) |
@@ -165,7 +160,38 @@ static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt, | |||
165 | } | 160 | } |
166 | } | 161 | } |
167 | 162 | ||
168 | nh_index = hash % rt->rt_nhn; | 163 | return hash; |
164 | } | ||
165 | |||
166 | static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt, | ||
167 | struct sk_buff *skb, bool bos) | ||
168 | { | ||
169 | int alive = ACCESS_ONCE(rt->rt_nhn_alive); | ||
170 | u32 hash = 0; | ||
171 | int nh_index = 0; | ||
172 | int n = 0; | ||
173 | |||
174 | /* No need to look further into packet if there's only | ||
175 | * one path | ||
176 | */ | ||
177 | if (rt->rt_nhn == 1) | ||
178 | goto out; | ||
179 | |||
180 | if (alive <= 0) | ||
181 | return NULL; | ||
182 | |||
183 | hash = mpls_multipath_hash(rt, skb, bos); | ||
184 | nh_index = hash % alive; | ||
185 | if (alive == rt->rt_nhn) | ||
186 | goto out; | ||
187 | for_nexthops(rt) { | ||
188 | if (nh->nh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) | ||
189 | continue; | ||
190 | if (n == nh_index) | ||
191 | return nh; | ||
192 | n++; | ||
193 | } endfor_nexthops(rt); | ||
194 | |||
169 | out: | 195 | out: |
170 | return &rt->rt_nh[nh_index]; | 196 | return &rt->rt_nh[nh_index]; |
171 | } | 197 | } |
@@ -317,7 +343,13 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, | |||
317 | } | 343 | } |
318 | } | 344 | } |
319 | 345 | ||
320 | err = neigh_xmit(nh->nh_via_table, out_dev, mpls_nh_via(rt, nh), skb); | 346 | /* If via wasn't specified then send out using device address */ |
347 | if (nh->nh_via_table == MPLS_NEIGH_TABLE_UNSPEC) | ||
348 | err = neigh_xmit(NEIGH_LINK_TABLE, out_dev, | ||
349 | out_dev->dev_addr, skb); | ||
350 | else | ||
351 | err = neigh_xmit(nh->nh_via_table, out_dev, | ||
352 | mpls_nh_via(rt, nh), skb); | ||
321 | if (err) | 353 | if (err) |
322 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", | 354 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", |
323 | __func__, err); | 355 | __func__, err); |
@@ -365,6 +397,7 @@ static struct mpls_route *mpls_rt_alloc(int num_nh, u8 max_alen) | |||
365 | GFP_KERNEL); | 397 | GFP_KERNEL); |
366 | if (rt) { | 398 | if (rt) { |
367 | rt->rt_nhn = num_nh; | 399 | rt->rt_nhn = num_nh; |
400 | rt->rt_nhn_alive = num_nh; | ||
368 | rt->rt_max_alen = max_alen_aligned; | 401 | rt->rt_max_alen = max_alen_aligned; |
369 | } | 402 | } |
370 | 403 | ||
@@ -534,8 +567,22 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt, | |||
534 | if (!mpls_dev_get(dev)) | 567 | if (!mpls_dev_get(dev)) |
535 | goto errout; | 568 | goto errout; |
536 | 569 | ||
570 | if ((nh->nh_via_table == NEIGH_LINK_TABLE) && | ||
571 | (dev->addr_len != nh->nh_via_alen)) | ||
572 | goto errout; | ||
573 | |||
537 | RCU_INIT_POINTER(nh->nh_dev, dev); | 574 | RCU_INIT_POINTER(nh->nh_dev, dev); |
538 | 575 | ||
576 | if (!(dev->flags & IFF_UP)) { | ||
577 | nh->nh_flags |= RTNH_F_DEAD; | ||
578 | } else { | ||
579 | unsigned int flags; | ||
580 | |||
581 | flags = dev_get_flags(dev); | ||
582 | if (!(flags & (IFF_RUNNING | IFF_LOWER_UP))) | ||
583 | nh->nh_flags |= RTNH_F_LINKDOWN; | ||
584 | } | ||
585 | |||
539 | return 0; | 586 | return 0; |
540 | 587 | ||
541 | errout: | 588 | errout: |
@@ -570,6 +617,9 @@ static int mpls_nh_build_from_cfg(struct mpls_route_config *cfg, | |||
570 | if (err) | 617 | if (err) |
571 | goto errout; | 618 | goto errout; |
572 | 619 | ||
620 | if (nh->nh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) | ||
621 | rt->rt_nhn_alive--; | ||
622 | |||
573 | return 0; | 623 | return 0; |
574 | 624 | ||
575 | errout: | 625 | errout: |
@@ -577,8 +627,8 @@ errout: | |||
577 | } | 627 | } |
578 | 628 | ||
579 | static int mpls_nh_build(struct net *net, struct mpls_route *rt, | 629 | static int mpls_nh_build(struct net *net, struct mpls_route *rt, |
580 | struct mpls_nh *nh, int oif, | 630 | struct mpls_nh *nh, int oif, struct nlattr *via, |
581 | struct nlattr *via, struct nlattr *newdst) | 631 | struct nlattr *newdst) |
582 | { | 632 | { |
583 | int err = -ENOMEM; | 633 | int err = -ENOMEM; |
584 | 634 | ||
@@ -592,10 +642,14 @@ static int mpls_nh_build(struct net *net, struct mpls_route *rt, | |||
592 | goto errout; | 642 | goto errout; |
593 | } | 643 | } |
594 | 644 | ||
595 | err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table, | 645 | if (via) { |
596 | __mpls_nh_via(rt, nh)); | 646 | err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table, |
597 | if (err) | 647 | __mpls_nh_via(rt, nh)); |
598 | goto errout; | 648 | if (err) |
649 | goto errout; | ||
650 | } else { | ||
651 | nh->nh_via_table = MPLS_NEIGH_TABLE_UNSPEC; | ||
652 | } | ||
599 | 653 | ||
600 | err = mpls_nh_assign_dev(net, rt, nh, oif); | 654 | err = mpls_nh_assign_dev(net, rt, nh, oif); |
601 | if (err) | 655 | if (err) |
@@ -677,15 +731,14 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg, | |||
677 | nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST); | 731 | nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST); |
678 | } | 732 | } |
679 | 733 | ||
680 | if (!nla_via) | ||
681 | goto errout; | ||
682 | |||
683 | err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh, | 734 | err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh, |
684 | rtnh->rtnh_ifindex, nla_via, | 735 | rtnh->rtnh_ifindex, nla_via, nla_newdst); |
685 | nla_newdst); | ||
686 | if (err) | 736 | if (err) |
687 | goto errout; | 737 | goto errout; |
688 | 738 | ||
739 | if (nh->nh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) | ||
740 | rt->rt_nhn_alive--; | ||
741 | |||
689 | rtnh = rtnh_next(rtnh, &remaining); | 742 | rtnh = rtnh_next(rtnh, &remaining); |
690 | nhs++; | 743 | nhs++; |
691 | } endfor_nexthops(rt); | 744 | } endfor_nexthops(rt); |
@@ -875,34 +928,74 @@ free: | |||
875 | return ERR_PTR(err); | 928 | return ERR_PTR(err); |
876 | } | 929 | } |
877 | 930 | ||
878 | static void mpls_ifdown(struct net_device *dev) | 931 | static void mpls_ifdown(struct net_device *dev, int event) |
879 | { | 932 | { |
880 | struct mpls_route __rcu **platform_label; | 933 | struct mpls_route __rcu **platform_label; |
881 | struct net *net = dev_net(dev); | 934 | struct net *net = dev_net(dev); |
882 | struct mpls_dev *mdev; | ||
883 | unsigned index; | 935 | unsigned index; |
884 | 936 | ||
885 | platform_label = rtnl_dereference(net->mpls.platform_label); | 937 | platform_label = rtnl_dereference(net->mpls.platform_label); |
886 | for (index = 0; index < net->mpls.platform_labels; index++) { | 938 | for (index = 0; index < net->mpls.platform_labels; index++) { |
887 | struct mpls_route *rt = rtnl_dereference(platform_label[index]); | 939 | struct mpls_route *rt = rtnl_dereference(platform_label[index]); |
940 | |||
888 | if (!rt) | 941 | if (!rt) |
889 | continue; | 942 | continue; |
890 | for_nexthops(rt) { | 943 | |
944 | change_nexthops(rt) { | ||
891 | if (rtnl_dereference(nh->nh_dev) != dev) | 945 | if (rtnl_dereference(nh->nh_dev) != dev) |
892 | continue; | 946 | continue; |
893 | nh->nh_dev = NULL; | 947 | switch (event) { |
948 | case NETDEV_DOWN: | ||
949 | case NETDEV_UNREGISTER: | ||
950 | nh->nh_flags |= RTNH_F_DEAD; | ||
951 | /* fall through */ | ||
952 | case NETDEV_CHANGE: | ||
953 | nh->nh_flags |= RTNH_F_LINKDOWN; | ||
954 | ACCESS_ONCE(rt->rt_nhn_alive) = rt->rt_nhn_alive - 1; | ||
955 | break; | ||
956 | } | ||
957 | if (event == NETDEV_UNREGISTER) | ||
958 | RCU_INIT_POINTER(nh->nh_dev, NULL); | ||
894 | } endfor_nexthops(rt); | 959 | } endfor_nexthops(rt); |
895 | } | 960 | } |
896 | 961 | ||
897 | mdev = mpls_dev_get(dev); | ||
898 | if (!mdev) | ||
899 | return; | ||
900 | 962 | ||
901 | mpls_dev_sysctl_unregister(mdev); | 963 | return; |
964 | } | ||
965 | |||
966 | static void mpls_ifup(struct net_device *dev, unsigned int nh_flags) | ||
967 | { | ||
968 | struct mpls_route __rcu **platform_label; | ||
969 | struct net *net = dev_net(dev); | ||
970 | unsigned index; | ||
971 | int alive; | ||
972 | |||
973 | platform_label = rtnl_dereference(net->mpls.platform_label); | ||
974 | for (index = 0; index < net->mpls.platform_labels; index++) { | ||
975 | struct mpls_route *rt = rtnl_dereference(platform_label[index]); | ||
976 | |||
977 | if (!rt) | ||
978 | continue; | ||
979 | |||
980 | alive = 0; | ||
981 | change_nexthops(rt) { | ||
982 | struct net_device *nh_dev = | ||
983 | rtnl_dereference(nh->nh_dev); | ||
902 | 984 | ||
903 | RCU_INIT_POINTER(dev->mpls_ptr, NULL); | 985 | if (!(nh->nh_flags & nh_flags)) { |
986 | alive++; | ||
987 | continue; | ||
988 | } | ||
989 | if (nh_dev != dev) | ||
990 | continue; | ||
991 | alive++; | ||
992 | nh->nh_flags &= ~nh_flags; | ||
993 | } endfor_nexthops(rt); | ||
994 | |||
995 | ACCESS_ONCE(rt->rt_nhn_alive) = alive; | ||
996 | } | ||
904 | 997 | ||
905 | kfree_rcu(mdev, rcu); | 998 | return; |
906 | } | 999 | } |
907 | 1000 | ||
908 | static int mpls_dev_notify(struct notifier_block *this, unsigned long event, | 1001 | static int mpls_dev_notify(struct notifier_block *this, unsigned long event, |
@@ -910,9 +1003,9 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, | |||
910 | { | 1003 | { |
911 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 1004 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
912 | struct mpls_dev *mdev; | 1005 | struct mpls_dev *mdev; |
1006 | unsigned int flags; | ||
913 | 1007 | ||
914 | switch(event) { | 1008 | if (event == NETDEV_REGISTER) { |
915 | case NETDEV_REGISTER: | ||
916 | /* For now just support ethernet devices */ | 1009 | /* For now just support ethernet devices */ |
917 | if ((dev->type == ARPHRD_ETHER) || | 1010 | if ((dev->type == ARPHRD_ETHER) || |
918 | (dev->type == ARPHRD_LOOPBACK)) { | 1011 | (dev->type == ARPHRD_LOOPBACK)) { |
@@ -920,10 +1013,39 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, | |||
920 | if (IS_ERR(mdev)) | 1013 | if (IS_ERR(mdev)) |
921 | return notifier_from_errno(PTR_ERR(mdev)); | 1014 | return notifier_from_errno(PTR_ERR(mdev)); |
922 | } | 1015 | } |
923 | break; | 1016 | return NOTIFY_OK; |
1017 | } | ||
1018 | |||
1019 | mdev = mpls_dev_get(dev); | ||
1020 | if (!mdev) | ||
1021 | return NOTIFY_OK; | ||
924 | 1022 | ||
1023 | switch (event) { | ||
1024 | case NETDEV_DOWN: | ||
1025 | mpls_ifdown(dev, event); | ||
1026 | break; | ||
1027 | case NETDEV_UP: | ||
1028 | flags = dev_get_flags(dev); | ||
1029 | if (flags & (IFF_RUNNING | IFF_LOWER_UP)) | ||
1030 | mpls_ifup(dev, RTNH_F_DEAD | RTNH_F_LINKDOWN); | ||
1031 | else | ||
1032 | mpls_ifup(dev, RTNH_F_DEAD); | ||
1033 | break; | ||
1034 | case NETDEV_CHANGE: | ||
1035 | flags = dev_get_flags(dev); | ||
1036 | if (flags & (IFF_RUNNING | IFF_LOWER_UP)) | ||
1037 | mpls_ifup(dev, RTNH_F_DEAD | RTNH_F_LINKDOWN); | ||
1038 | else | ||
1039 | mpls_ifdown(dev, event); | ||
1040 | break; | ||
925 | case NETDEV_UNREGISTER: | 1041 | case NETDEV_UNREGISTER: |
926 | mpls_ifdown(dev); | 1042 | mpls_ifdown(dev, event); |
1043 | mdev = mpls_dev_get(dev); | ||
1044 | if (mdev) { | ||
1045 | mpls_dev_sysctl_unregister(mdev); | ||
1046 | RCU_INIT_POINTER(dev->mpls_ptr, NULL); | ||
1047 | kfree_rcu(mdev, rcu); | ||
1048 | } | ||
927 | break; | 1049 | break; |
928 | case NETDEV_CHANGENAME: | 1050 | case NETDEV_CHANGENAME: |
929 | mdev = mpls_dev_get(dev); | 1051 | mdev = mpls_dev_get(dev); |
@@ -1118,6 +1240,7 @@ static int rtm_to_route_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1118 | 1240 | ||
1119 | cfg->rc_label = LABEL_NOT_SPECIFIED; | 1241 | cfg->rc_label = LABEL_NOT_SPECIFIED; |
1120 | cfg->rc_protocol = rtm->rtm_protocol; | 1242 | cfg->rc_protocol = rtm->rtm_protocol; |
1243 | cfg->rc_via_table = MPLS_NEIGH_TABLE_UNSPEC; | ||
1121 | cfg->rc_nlflags = nlh->nlmsg_flags; | 1244 | cfg->rc_nlflags = nlh->nlmsg_flags; |
1122 | cfg->rc_nlinfo.portid = NETLINK_CB(skb).portid; | 1245 | cfg->rc_nlinfo.portid = NETLINK_CB(skb).portid; |
1123 | cfg->rc_nlinfo.nlh = nlh; | 1246 | cfg->rc_nlinfo.nlh = nlh; |
@@ -1231,15 +1354,22 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, | |||
1231 | nla_put_labels(skb, RTA_NEWDST, nh->nh_labels, | 1354 | nla_put_labels(skb, RTA_NEWDST, nh->nh_labels, |
1232 | nh->nh_label)) | 1355 | nh->nh_label)) |
1233 | goto nla_put_failure; | 1356 | goto nla_put_failure; |
1234 | if (nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh), | 1357 | if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC && |
1358 | nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh), | ||
1235 | nh->nh_via_alen)) | 1359 | nh->nh_via_alen)) |
1236 | goto nla_put_failure; | 1360 | goto nla_put_failure; |
1237 | dev = rtnl_dereference(nh->nh_dev); | 1361 | dev = rtnl_dereference(nh->nh_dev); |
1238 | if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) | 1362 | if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) |
1239 | goto nla_put_failure; | 1363 | goto nla_put_failure; |
1364 | if (nh->nh_flags & RTNH_F_LINKDOWN) | ||
1365 | rtm->rtm_flags |= RTNH_F_LINKDOWN; | ||
1366 | if (nh->nh_flags & RTNH_F_DEAD) | ||
1367 | rtm->rtm_flags |= RTNH_F_DEAD; | ||
1240 | } else { | 1368 | } else { |
1241 | struct rtnexthop *rtnh; | 1369 | struct rtnexthop *rtnh; |
1242 | struct nlattr *mp; | 1370 | struct nlattr *mp; |
1371 | int dead = 0; | ||
1372 | int linkdown = 0; | ||
1243 | 1373 | ||
1244 | mp = nla_nest_start(skb, RTA_MULTIPATH); | 1374 | mp = nla_nest_start(skb, RTA_MULTIPATH); |
1245 | if (!mp) | 1375 | if (!mp) |
@@ -1253,11 +1383,21 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, | |||
1253 | dev = rtnl_dereference(nh->nh_dev); | 1383 | dev = rtnl_dereference(nh->nh_dev); |
1254 | if (dev) | 1384 | if (dev) |
1255 | rtnh->rtnh_ifindex = dev->ifindex; | 1385 | rtnh->rtnh_ifindex = dev->ifindex; |
1386 | if (nh->nh_flags & RTNH_F_LINKDOWN) { | ||
1387 | rtnh->rtnh_flags |= RTNH_F_LINKDOWN; | ||
1388 | linkdown++; | ||
1389 | } | ||
1390 | if (nh->nh_flags & RTNH_F_DEAD) { | ||
1391 | rtnh->rtnh_flags |= RTNH_F_DEAD; | ||
1392 | dead++; | ||
1393 | } | ||
1394 | |||
1256 | if (nh->nh_labels && nla_put_labels(skb, RTA_NEWDST, | 1395 | if (nh->nh_labels && nla_put_labels(skb, RTA_NEWDST, |
1257 | nh->nh_labels, | 1396 | nh->nh_labels, |
1258 | nh->nh_label)) | 1397 | nh->nh_label)) |
1259 | goto nla_put_failure; | 1398 | goto nla_put_failure; |
1260 | if (nla_put_via(skb, nh->nh_via_table, | 1399 | if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC && |
1400 | nla_put_via(skb, nh->nh_via_table, | ||
1261 | mpls_nh_via(rt, nh), | 1401 | mpls_nh_via(rt, nh), |
1262 | nh->nh_via_alen)) | 1402 | nh->nh_via_alen)) |
1263 | goto nla_put_failure; | 1403 | goto nla_put_failure; |
@@ -1266,6 +1406,11 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, | |||
1266 | rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh; | 1406 | rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh; |
1267 | } endfor_nexthops(rt); | 1407 | } endfor_nexthops(rt); |
1268 | 1408 | ||
1409 | if (linkdown == rt->rt_nhn) | ||
1410 | rtm->rtm_flags |= RTNH_F_LINKDOWN; | ||
1411 | if (dead == rt->rt_nhn) | ||
1412 | rtm->rtm_flags |= RTNH_F_DEAD; | ||
1413 | |||
1269 | nla_nest_end(skb, mp); | 1414 | nla_nest_end(skb, mp); |
1270 | } | 1415 | } |
1271 | 1416 | ||
@@ -1319,7 +1464,8 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt) | |||
1319 | 1464 | ||
1320 | if (nh->nh_dev) | 1465 | if (nh->nh_dev) |
1321 | payload += nla_total_size(4); /* RTA_OIF */ | 1466 | payload += nla_total_size(4); /* RTA_OIF */ |
1322 | payload += nla_total_size(2 + nh->nh_via_alen); /* RTA_VIA */ | 1467 | if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC) /* RTA_VIA */ |
1468 | payload += nla_total_size(2 + nh->nh_via_alen); | ||
1323 | if (nh->nh_labels) /* RTA_NEWDST */ | 1469 | if (nh->nh_labels) /* RTA_NEWDST */ |
1324 | payload += nla_total_size(nh->nh_labels * 4); | 1470 | payload += nla_total_size(nh->nh_labels * 4); |
1325 | } else { | 1471 | } else { |
@@ -1328,7 +1474,9 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt) | |||
1328 | 1474 | ||
1329 | for_nexthops(rt) { | 1475 | for_nexthops(rt) { |
1330 | nhsize += nla_total_size(sizeof(struct rtnexthop)); | 1476 | nhsize += nla_total_size(sizeof(struct rtnexthop)); |
1331 | nhsize += nla_total_size(2 + nh->nh_via_alen); | 1477 | /* RTA_VIA */ |
1478 | if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC) | ||
1479 | nhsize += nla_total_size(2 + nh->nh_via_alen); | ||
1332 | if (nh->nh_labels) | 1480 | if (nh->nh_labels) |
1333 | nhsize += nla_total_size(nh->nh_labels * 4); | 1481 | nhsize += nla_total_size(nh->nh_labels * 4); |
1334 | } endfor_nexthops(rt); | 1482 | } endfor_nexthops(rt); |
diff --git a/net/mpls/internal.h b/net/mpls/internal.h index bde52ce88c94..732a5c17e986 100644 --- a/net/mpls/internal.h +++ b/net/mpls/internal.h | |||
@@ -41,6 +41,7 @@ enum mpls_payload_type { | |||
41 | 41 | ||
42 | struct mpls_nh { /* next hop label forwarding entry */ | 42 | struct mpls_nh { /* next hop label forwarding entry */ |
43 | struct net_device __rcu *nh_dev; | 43 | struct net_device __rcu *nh_dev; |
44 | unsigned int nh_flags; | ||
44 | u32 nh_label[MAX_NEW_LABELS]; | 45 | u32 nh_label[MAX_NEW_LABELS]; |
45 | u8 nh_labels; | 46 | u8 nh_labels; |
46 | u8 nh_via_alen; | 47 | u8 nh_via_alen; |
@@ -74,6 +75,7 @@ struct mpls_route { /* next hop label forwarding entry */ | |||
74 | u8 rt_payload_type; | 75 | u8 rt_payload_type; |
75 | u8 rt_max_alen; | 76 | u8 rt_max_alen; |
76 | unsigned int rt_nhn; | 77 | unsigned int rt_nhn; |
78 | unsigned int rt_nhn_alive; | ||
77 | struct mpls_nh rt_nh[0]; | 79 | struct mpls_nh rt_nh[0]; |
78 | }; | 80 | }; |
79 | 81 | ||
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c index 67591aef9cae..fb31aa87de81 100644 --- a/net/mpls/mpls_iptunnel.c +++ b/net/mpls/mpls_iptunnel.c | |||
@@ -37,7 +37,7 @@ static unsigned int mpls_encap_size(struct mpls_iptunnel_encap *en) | |||
37 | return en->labels * sizeof(struct mpls_shim_hdr); | 37 | return en->labels * sizeof(struct mpls_shim_hdr); |
38 | } | 38 | } |
39 | 39 | ||
40 | int mpls_output(struct net *net, struct sock *sk, struct sk_buff *skb) | 40 | static int mpls_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
41 | { | 41 | { |
42 | struct mpls_iptunnel_encap *tun_encap_info; | 42 | struct mpls_iptunnel_encap *tun_encap_info; |
43 | struct mpls_shim_hdr *hdr; | 43 | struct mpls_shim_hdr *hdr; |
@@ -54,10 +54,10 @@ int mpls_output(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
54 | unsigned int ttl; | 54 | unsigned int ttl; |
55 | 55 | ||
56 | /* Obtain the ttl */ | 56 | /* Obtain the ttl */ |
57 | if (skb->protocol == htons(ETH_P_IP)) { | 57 | if (dst->ops->family == AF_INET) { |
58 | ttl = ip_hdr(skb)->ttl; | 58 | ttl = ip_hdr(skb)->ttl; |
59 | rt = (struct rtable *)dst; | 59 | rt = (struct rtable *)dst; |
60 | } else if (skb->protocol == htons(ETH_P_IPV6)) { | 60 | } else if (dst->ops->family == AF_INET6) { |
61 | ttl = ipv6_hdr(skb)->hop_limit; | 61 | ttl = ipv6_hdr(skb)->hop_limit; |
62 | rt6 = (struct rt6_info *)dst; | 62 | rt6 = (struct rt6_info *)dst; |
63 | } else { | 63 | } else { |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 4692782b5280..8c067e6663a1 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -563,6 +563,28 @@ config NFT_COMPAT | |||
563 | x_tables match/target extensions over the nf_tables | 563 | x_tables match/target extensions over the nf_tables |
564 | framework. | 564 | framework. |
565 | 565 | ||
566 | if NF_TABLES_NETDEV | ||
567 | |||
568 | config NF_DUP_NETDEV | ||
569 | tristate "Netfilter packet duplication support" | ||
570 | help | ||
571 | This option enables the generic packet duplication infrastructure | ||
572 | for Netfilter. | ||
573 | |||
574 | config NFT_DUP_NETDEV | ||
575 | tristate "Netfilter nf_tables netdev packet duplication support" | ||
576 | select NF_DUP_NETDEV | ||
577 | help | ||
578 | This option enables packet duplication for the "netdev" family. | ||
579 | |||
580 | config NFT_FWD_NETDEV | ||
581 | tristate "Netfilter nf_tables netdev packet forwarding support" | ||
582 | select NF_DUP_NETDEV | ||
583 | help | ||
584 | This option enables packet forwarding for the "netdev" family. | ||
585 | |||
586 | endif # NF_TABLES_NETDEV | ||
587 | |||
566 | endif # NF_TABLES | 588 | endif # NF_TABLES |
567 | 589 | ||
568 | config NETFILTER_XTABLES | 590 | config NETFILTER_XTABLES |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 7638c36b498c..69134541d65b 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -66,8 +66,11 @@ obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o | |||
66 | # SYNPROXY | 66 | # SYNPROXY |
67 | obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o | 67 | obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o |
68 | 68 | ||
69 | # generic packet duplication from netdev family | ||
70 | obj-$(CONFIG_NF_DUP_NETDEV) += nf_dup_netdev.o | ||
71 | |||
69 | # nf_tables | 72 | # nf_tables |
70 | nf_tables-objs += nf_tables_core.o nf_tables_api.o | 73 | nf_tables-objs += nf_tables_core.o nf_tables_api.o nf_tables_trace.o |
71 | nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o nft_dynset.o | 74 | nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o nft_dynset.o |
72 | nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o | 75 | nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o |
73 | 76 | ||
@@ -90,6 +93,10 @@ obj-$(CONFIG_NFT_LOG) += nft_log.o | |||
90 | obj-$(CONFIG_NFT_MASQ) += nft_masq.o | 93 | obj-$(CONFIG_NFT_MASQ) += nft_masq.o |
91 | obj-$(CONFIG_NFT_REDIR) += nft_redir.o | 94 | obj-$(CONFIG_NFT_REDIR) += nft_redir.o |
92 | 95 | ||
96 | # nf_tables netdev | ||
97 | obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o | ||
98 | obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o | ||
99 | |||
93 | # generic X tables | 100 | # generic X tables |
94 | obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o | 101 | obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o |
95 | 102 | ||
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 54f3d7cb23e6..95db43fc0303 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -825,20 +825,17 @@ find_free_id(struct ip_set_net *inst, const char *name, ip_set_id_t *index, | |||
825 | return 0; | 825 | return 0; |
826 | } | 826 | } |
827 | 827 | ||
828 | static int | 828 | static int ip_set_none(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
829 | ip_set_none(struct sock *ctnl, struct sk_buff *skb, | 829 | const struct nlmsghdr *nlh, |
830 | const struct nlmsghdr *nlh, | 830 | const struct nlattr * const attr[]) |
831 | const struct nlattr * const attr[]) | ||
832 | { | 831 | { |
833 | return -EOPNOTSUPP; | 832 | return -EOPNOTSUPP; |
834 | } | 833 | } |
835 | 834 | ||
836 | static int | 835 | static int ip_set_create(struct net *net, struct sock *ctnl, |
837 | ip_set_create(struct sock *ctnl, struct sk_buff *skb, | 836 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
838 | const struct nlmsghdr *nlh, | 837 | const struct nlattr * const attr[]) |
839 | const struct nlattr * const attr[]) | ||
840 | { | 838 | { |
841 | struct net *net = sock_net(ctnl); | ||
842 | struct ip_set_net *inst = ip_set_pernet(net); | 839 | struct ip_set_net *inst = ip_set_pernet(net); |
843 | struct ip_set *set, *clash = NULL; | 840 | struct ip_set *set, *clash = NULL; |
844 | ip_set_id_t index = IPSET_INVALID_ID; | 841 | ip_set_id_t index = IPSET_INVALID_ID; |
@@ -976,12 +973,11 @@ ip_set_destroy_set(struct ip_set *set) | |||
976 | kfree(set); | 973 | kfree(set); |
977 | } | 974 | } |
978 | 975 | ||
979 | static int | 976 | static int ip_set_destroy(struct net *net, struct sock *ctnl, |
980 | ip_set_destroy(struct sock *ctnl, struct sk_buff *skb, | 977 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
981 | const struct nlmsghdr *nlh, | 978 | const struct nlattr * const attr[]) |
982 | const struct nlattr * const attr[]) | ||
983 | { | 979 | { |
984 | struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | 980 | struct ip_set_net *inst = ip_set_pernet(net); |
985 | struct ip_set *s; | 981 | struct ip_set *s; |
986 | ip_set_id_t i; | 982 | ip_set_id_t i; |
987 | int ret = 0; | 983 | int ret = 0; |
@@ -1052,12 +1048,11 @@ ip_set_flush_set(struct ip_set *set) | |||
1052 | spin_unlock_bh(&set->lock); | 1048 | spin_unlock_bh(&set->lock); |
1053 | } | 1049 | } |
1054 | 1050 | ||
1055 | static int | 1051 | static int ip_set_flush(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
1056 | ip_set_flush(struct sock *ctnl, struct sk_buff *skb, | 1052 | const struct nlmsghdr *nlh, |
1057 | const struct nlmsghdr *nlh, | 1053 | const struct nlattr * const attr[]) |
1058 | const struct nlattr * const attr[]) | ||
1059 | { | 1054 | { |
1060 | struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | 1055 | struct ip_set_net *inst = ip_set_pernet(net); |
1061 | struct ip_set *s; | 1056 | struct ip_set *s; |
1062 | ip_set_id_t i; | 1057 | ip_set_id_t i; |
1063 | 1058 | ||
@@ -1092,12 +1087,11 @@ ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = { | |||
1092 | .len = IPSET_MAXNAMELEN - 1 }, | 1087 | .len = IPSET_MAXNAMELEN - 1 }, |
1093 | }; | 1088 | }; |
1094 | 1089 | ||
1095 | static int | 1090 | static int ip_set_rename(struct net *net, struct sock *ctnl, |
1096 | ip_set_rename(struct sock *ctnl, struct sk_buff *skb, | 1091 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1097 | const struct nlmsghdr *nlh, | 1092 | const struct nlattr * const attr[]) |
1098 | const struct nlattr * const attr[]) | ||
1099 | { | 1093 | { |
1100 | struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | 1094 | struct ip_set_net *inst = ip_set_pernet(net); |
1101 | struct ip_set *set, *s; | 1095 | struct ip_set *set, *s; |
1102 | const char *name2; | 1096 | const char *name2; |
1103 | ip_set_id_t i; | 1097 | ip_set_id_t i; |
@@ -1142,12 +1136,11 @@ out: | |||
1142 | * so the ip_set_list always contains valid pointers to the sets. | 1136 | * so the ip_set_list always contains valid pointers to the sets. |
1143 | */ | 1137 | */ |
1144 | 1138 | ||
1145 | static int | 1139 | static int ip_set_swap(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
1146 | ip_set_swap(struct sock *ctnl, struct sk_buff *skb, | 1140 | const struct nlmsghdr *nlh, |
1147 | const struct nlmsghdr *nlh, | 1141 | const struct nlattr * const attr[]) |
1148 | const struct nlattr * const attr[]) | ||
1149 | { | 1142 | { |
1150 | struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | 1143 | struct ip_set_net *inst = ip_set_pernet(net); |
1151 | struct ip_set *from, *to; | 1144 | struct ip_set *from, *to; |
1152 | ip_set_id_t from_id, to_id; | 1145 | ip_set_id_t from_id, to_id; |
1153 | char from_name[IPSET_MAXNAMELEN]; | 1146 | char from_name[IPSET_MAXNAMELEN]; |
@@ -1413,10 +1406,9 @@ out: | |||
1413 | return ret < 0 ? ret : skb->len; | 1406 | return ret < 0 ? ret : skb->len; |
1414 | } | 1407 | } |
1415 | 1408 | ||
1416 | static int | 1409 | static int ip_set_dump(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
1417 | ip_set_dump(struct sock *ctnl, struct sk_buff *skb, | 1410 | const struct nlmsghdr *nlh, |
1418 | const struct nlmsghdr *nlh, | 1411 | const struct nlattr * const attr[]) |
1419 | const struct nlattr * const attr[]) | ||
1420 | { | 1412 | { |
1421 | if (unlikely(protocol_failed(attr))) | 1413 | if (unlikely(protocol_failed(attr))) |
1422 | return -IPSET_ERR_PROTOCOL; | 1414 | return -IPSET_ERR_PROTOCOL; |
@@ -1500,12 +1492,11 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, | |||
1500 | return ret; | 1492 | return ret; |
1501 | } | 1493 | } |
1502 | 1494 | ||
1503 | static int | 1495 | static int ip_set_uadd(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
1504 | ip_set_uadd(struct sock *ctnl, struct sk_buff *skb, | 1496 | const struct nlmsghdr *nlh, |
1505 | const struct nlmsghdr *nlh, | 1497 | const struct nlattr * const attr[]) |
1506 | const struct nlattr * const attr[]) | ||
1507 | { | 1498 | { |
1508 | struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | 1499 | struct ip_set_net *inst = ip_set_pernet(net); |
1509 | struct ip_set *set; | 1500 | struct ip_set *set; |
1510 | struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; | 1501 | struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; |
1511 | const struct nlattr *nla; | 1502 | const struct nlattr *nla; |
@@ -1555,12 +1546,11 @@ ip_set_uadd(struct sock *ctnl, struct sk_buff *skb, | |||
1555 | return ret; | 1546 | return ret; |
1556 | } | 1547 | } |
1557 | 1548 | ||
1558 | static int | 1549 | static int ip_set_udel(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
1559 | ip_set_udel(struct sock *ctnl, struct sk_buff *skb, | 1550 | const struct nlmsghdr *nlh, |
1560 | const struct nlmsghdr *nlh, | 1551 | const struct nlattr * const attr[]) |
1561 | const struct nlattr * const attr[]) | ||
1562 | { | 1552 | { |
1563 | struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | 1553 | struct ip_set_net *inst = ip_set_pernet(net); |
1564 | struct ip_set *set; | 1554 | struct ip_set *set; |
1565 | struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; | 1555 | struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; |
1566 | const struct nlattr *nla; | 1556 | const struct nlattr *nla; |
@@ -1610,12 +1600,11 @@ ip_set_udel(struct sock *ctnl, struct sk_buff *skb, | |||
1610 | return ret; | 1600 | return ret; |
1611 | } | 1601 | } |
1612 | 1602 | ||
1613 | static int | 1603 | static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
1614 | ip_set_utest(struct sock *ctnl, struct sk_buff *skb, | 1604 | const struct nlmsghdr *nlh, |
1615 | const struct nlmsghdr *nlh, | 1605 | const struct nlattr * const attr[]) |
1616 | const struct nlattr * const attr[]) | ||
1617 | { | 1606 | { |
1618 | struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | 1607 | struct ip_set_net *inst = ip_set_pernet(net); |
1619 | struct ip_set *set; | 1608 | struct ip_set *set; |
1620 | struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; | 1609 | struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {}; |
1621 | int ret = 0; | 1610 | int ret = 0; |
@@ -1646,12 +1635,11 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb, | |||
1646 | 1635 | ||
1647 | /* Get headed data of a set */ | 1636 | /* Get headed data of a set */ |
1648 | 1637 | ||
1649 | static int | 1638 | static int ip_set_header(struct net *net, struct sock *ctnl, |
1650 | ip_set_header(struct sock *ctnl, struct sk_buff *skb, | 1639 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1651 | const struct nlmsghdr *nlh, | 1640 | const struct nlattr * const attr[]) |
1652 | const struct nlattr * const attr[]) | ||
1653 | { | 1641 | { |
1654 | struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl)); | 1642 | struct ip_set_net *inst = ip_set_pernet(net); |
1655 | const struct ip_set *set; | 1643 | const struct ip_set *set; |
1656 | struct sk_buff *skb2; | 1644 | struct sk_buff *skb2; |
1657 | struct nlmsghdr *nlh2; | 1645 | struct nlmsghdr *nlh2; |
@@ -1703,10 +1691,9 @@ static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = { | |||
1703 | [IPSET_ATTR_FAMILY] = { .type = NLA_U8 }, | 1691 | [IPSET_ATTR_FAMILY] = { .type = NLA_U8 }, |
1704 | }; | 1692 | }; |
1705 | 1693 | ||
1706 | static int | 1694 | static int ip_set_type(struct net *net, struct sock *ctnl, struct sk_buff *skb, |
1707 | ip_set_type(struct sock *ctnl, struct sk_buff *skb, | 1695 | const struct nlmsghdr *nlh, |
1708 | const struct nlmsghdr *nlh, | 1696 | const struct nlattr * const attr[]) |
1709 | const struct nlattr * const attr[]) | ||
1710 | { | 1697 | { |
1711 | struct sk_buff *skb2; | 1698 | struct sk_buff *skb2; |
1712 | struct nlmsghdr *nlh2; | 1699 | struct nlmsghdr *nlh2; |
@@ -1762,10 +1749,9 @@ ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = { | |||
1762 | [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, | 1749 | [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, |
1763 | }; | 1750 | }; |
1764 | 1751 | ||
1765 | static int | 1752 | static int ip_set_protocol(struct net *net, struct sock *ctnl, |
1766 | ip_set_protocol(struct sock *ctnl, struct sk_buff *skb, | 1753 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1767 | const struct nlmsghdr *nlh, | 1754 | const struct nlattr * const attr[]) |
1768 | const struct nlattr * const attr[]) | ||
1769 | { | 1755 | { |
1770 | struct sk_buff *skb2; | 1756 | struct sk_buff *skb2; |
1771 | struct nlmsghdr *nlh2; | 1757 | struct nlmsghdr *nlh2; |
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index 010ddeec135f..d952d67f904d 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c | |||
@@ -169,7 +169,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
169 | /* Only update csum if we really have to */ | 169 | /* Only update csum if we really have to */ |
170 | if (sctph->dest != cp->dport || payload_csum || | 170 | if (sctph->dest != cp->dport || payload_csum || |
171 | (skb->ip_summed == CHECKSUM_PARTIAL && | 171 | (skb->ip_summed == CHECKSUM_PARTIAL && |
172 | !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CSUM))) { | 172 | !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CRC))) { |
173 | sctph->dest = cp->dport; | 173 | sctph->dest = cp->dport; |
174 | sctp_nat_csum(skb, sctph, sctphoff); | 174 | sctp_nat_csum(skb, sctph, sctphoff); |
175 | } else if (skb->ip_summed != CHECKSUM_PARTIAL) { | 175 | } else if (skb->ip_summed != CHECKSUM_PARTIAL) { |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index acf5c7b3f378..278927ab0948 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -596,11 +596,18 @@ static int exp_proc_init(struct net *net) | |||
596 | { | 596 | { |
597 | #ifdef CONFIG_NF_CONNTRACK_PROCFS | 597 | #ifdef CONFIG_NF_CONNTRACK_PROCFS |
598 | struct proc_dir_entry *proc; | 598 | struct proc_dir_entry *proc; |
599 | kuid_t root_uid; | ||
600 | kgid_t root_gid; | ||
599 | 601 | ||
600 | proc = proc_create("nf_conntrack_expect", 0440, net->proc_net, | 602 | proc = proc_create("nf_conntrack_expect", 0440, net->proc_net, |
601 | &exp_file_ops); | 603 | &exp_file_ops); |
602 | if (!proc) | 604 | if (!proc) |
603 | return -ENOMEM; | 605 | return -ENOMEM; |
606 | |||
607 | root_uid = make_kuid(net->user_ns, 0); | ||
608 | root_gid = make_kgid(net->user_ns, 0); | ||
609 | if (uid_valid(root_uid) && gid_valid(root_gid)) | ||
610 | proc_set_user(proc, root_uid, root_gid); | ||
604 | #endif /* CONFIG_NF_CONNTRACK_PROCFS */ | 611 | #endif /* CONFIG_NF_CONNTRACK_PROCFS */ |
605 | return 0; | 612 | return 0; |
606 | } | 613 | } |
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index b666959f17c0..883c691ec8d0 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | |||
13 | #include <linux/module.h> | 15 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
15 | #include <linux/netfilter.h> | 17 | #include <linux/netfilter.h> |
@@ -505,11 +507,11 @@ skip_nl_seq: | |||
505 | different IP address. Simply don't record it for | 507 | different IP address. Simply don't record it for |
506 | NAT. */ | 508 | NAT. */ |
507 | if (cmd.l3num == PF_INET) { | 509 | if (cmd.l3num == PF_INET) { |
508 | pr_debug("conntrack_ftp: NOT RECORDING: %pI4 != %pI4\n", | 510 | pr_debug("NOT RECORDING: %pI4 != %pI4\n", |
509 | &cmd.u3.ip, | 511 | &cmd.u3.ip, |
510 | &ct->tuplehash[dir].tuple.src.u3.ip); | 512 | &ct->tuplehash[dir].tuple.src.u3.ip); |
511 | } else { | 513 | } else { |
512 | pr_debug("conntrack_ftp: NOT RECORDING: %pI6 != %pI6\n", | 514 | pr_debug("NOT RECORDING: %pI6 != %pI6\n", |
513 | cmd.u3.ip6, | 515 | cmd.u3.ip6, |
514 | ct->tuplehash[dir].tuple.src.u3.ip6); | 516 | ct->tuplehash[dir].tuple.src.u3.ip6); |
515 | } | 517 | } |
@@ -586,8 +588,7 @@ static void nf_conntrack_ftp_fini(void) | |||
586 | if (ftp[i][j].me == NULL) | 588 | if (ftp[i][j].me == NULL) |
587 | continue; | 589 | continue; |
588 | 590 | ||
589 | pr_debug("nf_ct_ftp: unregistering helper for pf: %d " | 591 | pr_debug("unregistering helper for pf: %d port: %d\n", |
590 | "port: %d\n", | ||
591 | ftp[i][j].tuple.src.l3num, ports[i]); | 592 | ftp[i][j].tuple.src.l3num, ports[i]); |
592 | nf_conntrack_helper_unregister(&ftp[i][j]); | 593 | nf_conntrack_helper_unregister(&ftp[i][j]); |
593 | } | 594 | } |
@@ -625,14 +626,12 @@ static int __init nf_conntrack_ftp_init(void) | |||
625 | else | 626 | else |
626 | sprintf(ftp[i][j].name, "ftp-%d", ports[i]); | 627 | sprintf(ftp[i][j].name, "ftp-%d", ports[i]); |
627 | 628 | ||
628 | pr_debug("nf_ct_ftp: registering helper for pf: %d " | 629 | pr_debug("registering helper for pf: %d port: %d\n", |
629 | "port: %d\n", | ||
630 | ftp[i][j].tuple.src.l3num, ports[i]); | 630 | ftp[i][j].tuple.src.l3num, ports[i]); |
631 | ret = nf_conntrack_helper_register(&ftp[i][j]); | 631 | ret = nf_conntrack_helper_register(&ftp[i][j]); |
632 | if (ret) { | 632 | if (ret) { |
633 | printk(KERN_ERR "nf_ct_ftp: failed to register" | 633 | pr_err("failed to register helper for pf: %d port: %d\n", |
634 | " helper for pf: %d port: %d\n", | 634 | ftp[i][j].tuple.src.l3num, ports[i]); |
635 | ftp[i][j].tuple.src.l3num, ports[i]); | ||
636 | nf_conntrack_ftp_fini(); | 635 | nf_conntrack_ftp_fini(); |
637 | return ret; | 636 | return ret; |
638 | } | 637 | } |
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 0fd2976db7ee..8b6da2719600 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c | |||
@@ -9,6 +9,8 @@ | |||
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 | 11 | ||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | |||
12 | #include <linux/module.h> | 14 | #include <linux/module.h> |
13 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
14 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
@@ -237,7 +239,7 @@ static int __init nf_conntrack_irc_init(void) | |||
237 | int i, ret; | 239 | int i, ret; |
238 | 240 | ||
239 | if (max_dcc_channels < 1) { | 241 | if (max_dcc_channels < 1) { |
240 | printk(KERN_ERR "nf_ct_irc: max_dcc_channels must not be zero\n"); | 242 | pr_err("max_dcc_channels must not be zero\n"); |
241 | return -EINVAL; | 243 | return -EINVAL; |
242 | } | 244 | } |
243 | 245 | ||
@@ -267,8 +269,7 @@ static int __init nf_conntrack_irc_init(void) | |||
267 | 269 | ||
268 | ret = nf_conntrack_helper_register(&irc[i]); | 270 | ret = nf_conntrack_helper_register(&irc[i]); |
269 | if (ret) { | 271 | if (ret) { |
270 | printk(KERN_ERR "nf_ct_irc: failed to register helper " | 272 | pr_err("failed to register helper for pf: %u port: %u\n", |
271 | "for pf: %u port: %u\n", | ||
272 | irc[i].tuple.src.l3num, ports[i]); | 273 | irc[i].tuple.src.l3num, ports[i]); |
273 | nf_conntrack_irc_fini(); | 274 | nf_conntrack_irc_fini(); |
274 | return ret; | 275 | return ret; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 9f5272968abb..dbb1bb3edb45 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -1113,12 +1113,11 @@ static int ctnetlink_flush_conntrack(struct net *net, | |||
1113 | return 0; | 1113 | return 0; |
1114 | } | 1114 | } |
1115 | 1115 | ||
1116 | static int | 1116 | static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl, |
1117 | ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | 1117 | struct sk_buff *skb, |
1118 | const struct nlmsghdr *nlh, | 1118 | const struct nlmsghdr *nlh, |
1119 | const struct nlattr * const cda[]) | 1119 | const struct nlattr * const cda[]) |
1120 | { | 1120 | { |
1121 | struct net *net = sock_net(ctnl); | ||
1122 | struct nf_conntrack_tuple_hash *h; | 1121 | struct nf_conntrack_tuple_hash *h; |
1123 | struct nf_conntrack_tuple tuple; | 1122 | struct nf_conntrack_tuple tuple; |
1124 | struct nf_conn *ct; | 1123 | struct nf_conn *ct; |
@@ -1168,12 +1167,11 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1168 | return 0; | 1167 | return 0; |
1169 | } | 1168 | } |
1170 | 1169 | ||
1171 | static int | 1170 | static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl, |
1172 | ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | 1171 | struct sk_buff *skb, |
1173 | const struct nlmsghdr *nlh, | 1172 | const struct nlmsghdr *nlh, |
1174 | const struct nlattr * const cda[]) | 1173 | const struct nlattr * const cda[]) |
1175 | { | 1174 | { |
1176 | struct net *net = sock_net(ctnl); | ||
1177 | struct nf_conntrack_tuple_hash *h; | 1175 | struct nf_conntrack_tuple_hash *h; |
1178 | struct nf_conntrack_tuple tuple; | 1176 | struct nf_conntrack_tuple tuple; |
1179 | struct nf_conn *ct; | 1177 | struct nf_conn *ct; |
@@ -1330,10 +1328,10 @@ ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb) | |||
1330 | return ctnetlink_dump_list(skb, cb, true); | 1328 | return ctnetlink_dump_list(skb, cb, true); |
1331 | } | 1329 | } |
1332 | 1330 | ||
1333 | static int | 1331 | static int ctnetlink_get_ct_dying(struct net *net, struct sock *ctnl, |
1334 | ctnetlink_get_ct_dying(struct sock *ctnl, struct sk_buff *skb, | 1332 | struct sk_buff *skb, |
1335 | const struct nlmsghdr *nlh, | 1333 | const struct nlmsghdr *nlh, |
1336 | const struct nlattr * const cda[]) | 1334 | const struct nlattr * const cda[]) |
1337 | { | 1335 | { |
1338 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 1336 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
1339 | struct netlink_dump_control c = { | 1337 | struct netlink_dump_control c = { |
@@ -1352,10 +1350,10 @@ ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb) | |||
1352 | return ctnetlink_dump_list(skb, cb, false); | 1350 | return ctnetlink_dump_list(skb, cb, false); |
1353 | } | 1351 | } |
1354 | 1352 | ||
1355 | static int | 1353 | static int ctnetlink_get_ct_unconfirmed(struct net *net, struct sock *ctnl, |
1356 | ctnetlink_get_ct_unconfirmed(struct sock *ctnl, struct sk_buff *skb, | 1354 | struct sk_buff *skb, |
1357 | const struct nlmsghdr *nlh, | 1355 | const struct nlmsghdr *nlh, |
1358 | const struct nlattr * const cda[]) | 1356 | const struct nlattr * const cda[]) |
1359 | { | 1357 | { |
1360 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 1358 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
1361 | struct netlink_dump_control c = { | 1359 | struct netlink_dump_control c = { |
@@ -1865,12 +1863,11 @@ err1: | |||
1865 | return ERR_PTR(err); | 1863 | return ERR_PTR(err); |
1866 | } | 1864 | } |
1867 | 1865 | ||
1868 | static int | 1866 | static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl, |
1869 | ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | 1867 | struct sk_buff *skb, |
1870 | const struct nlmsghdr *nlh, | 1868 | const struct nlmsghdr *nlh, |
1871 | const struct nlattr * const cda[]) | 1869 | const struct nlattr * const cda[]) |
1872 | { | 1870 | { |
1873 | struct net *net = sock_net(ctnl); | ||
1874 | struct nf_conntrack_tuple otuple, rtuple; | 1871 | struct nf_conntrack_tuple otuple, rtuple; |
1875 | struct nf_conntrack_tuple_hash *h = NULL; | 1872 | struct nf_conntrack_tuple_hash *h = NULL; |
1876 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1873 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
@@ -2034,10 +2031,10 @@ ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
2034 | return skb->len; | 2031 | return skb->len; |
2035 | } | 2032 | } |
2036 | 2033 | ||
2037 | static int | 2034 | static int ctnetlink_stat_ct_cpu(struct net *net, struct sock *ctnl, |
2038 | ctnetlink_stat_ct_cpu(struct sock *ctnl, struct sk_buff *skb, | 2035 | struct sk_buff *skb, |
2039 | const struct nlmsghdr *nlh, | 2036 | const struct nlmsghdr *nlh, |
2040 | const struct nlattr * const cda[]) | 2037 | const struct nlattr * const cda[]) |
2041 | { | 2038 | { |
2042 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 2039 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
2043 | struct netlink_dump_control c = { | 2040 | struct netlink_dump_control c = { |
@@ -2080,10 +2077,9 @@ nlmsg_failure: | |||
2080 | return -1; | 2077 | return -1; |
2081 | } | 2078 | } |
2082 | 2079 | ||
2083 | static int | 2080 | static int ctnetlink_stat_ct(struct net *net, struct sock *ctnl, |
2084 | ctnetlink_stat_ct(struct sock *ctnl, struct sk_buff *skb, | 2081 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
2085 | const struct nlmsghdr *nlh, | 2082 | const struct nlattr * const cda[]) |
2086 | const struct nlattr * const cda[]) | ||
2087 | { | 2083 | { |
2088 | struct sk_buff *skb2; | 2084 | struct sk_buff *skb2; |
2089 | int err; | 2085 | int err; |
@@ -2729,12 +2725,12 @@ out: | |||
2729 | return skb->len; | 2725 | return skb->len; |
2730 | } | 2726 | } |
2731 | 2727 | ||
2732 | static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb, | 2728 | static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, |
2729 | struct sk_buff *skb, | ||
2733 | const struct nlmsghdr *nlh, | 2730 | const struct nlmsghdr *nlh, |
2734 | const struct nlattr * const cda[]) | 2731 | const struct nlattr * const cda[]) |
2735 | { | 2732 | { |
2736 | int err; | 2733 | int err; |
2737 | struct net *net = sock_net(ctnl); | ||
2738 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2734 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
2739 | u_int8_t u3 = nfmsg->nfgen_family; | 2735 | u_int8_t u3 = nfmsg->nfgen_family; |
2740 | struct nf_conntrack_tuple tuple; | 2736 | struct nf_conntrack_tuple tuple; |
@@ -2768,12 +2764,10 @@ static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb, | |||
2768 | return err; | 2764 | return err; |
2769 | } | 2765 | } |
2770 | 2766 | ||
2771 | static int | 2767 | static int ctnetlink_get_expect(struct net *net, struct sock *ctnl, |
2772 | ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | 2768 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
2773 | const struct nlmsghdr *nlh, | 2769 | const struct nlattr * const cda[]) |
2774 | const struct nlattr * const cda[]) | ||
2775 | { | 2770 | { |
2776 | struct net *net = sock_net(ctnl); | ||
2777 | struct nf_conntrack_tuple tuple; | 2771 | struct nf_conntrack_tuple tuple; |
2778 | struct nf_conntrack_expect *exp; | 2772 | struct nf_conntrack_expect *exp; |
2779 | struct sk_buff *skb2; | 2773 | struct sk_buff *skb2; |
@@ -2784,7 +2778,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
2784 | 2778 | ||
2785 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 2779 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
2786 | if (cda[CTA_EXPECT_MASTER]) | 2780 | if (cda[CTA_EXPECT_MASTER]) |
2787 | return ctnetlink_dump_exp_ct(ctnl, skb, nlh, cda); | 2781 | return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda); |
2788 | else { | 2782 | else { |
2789 | struct netlink_dump_control c = { | 2783 | struct netlink_dump_control c = { |
2790 | .dump = ctnetlink_exp_dump_table, | 2784 | .dump = ctnetlink_exp_dump_table, |
@@ -2850,12 +2844,10 @@ out: | |||
2850 | return err == -EAGAIN ? -ENOBUFS : err; | 2844 | return err == -EAGAIN ? -ENOBUFS : err; |
2851 | } | 2845 | } |
2852 | 2846 | ||
2853 | static int | 2847 | static int ctnetlink_del_expect(struct net *net, struct sock *ctnl, |
2854 | ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | 2848 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
2855 | const struct nlmsghdr *nlh, | 2849 | const struct nlattr * const cda[]) |
2856 | const struct nlattr * const cda[]) | ||
2857 | { | 2850 | { |
2858 | struct net *net = sock_net(ctnl); | ||
2859 | struct nf_conntrack_expect *exp; | 2851 | struct nf_conntrack_expect *exp; |
2860 | struct nf_conntrack_tuple tuple; | 2852 | struct nf_conntrack_tuple tuple; |
2861 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2853 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
@@ -3136,12 +3128,10 @@ err_ct: | |||
3136 | return err; | 3128 | return err; |
3137 | } | 3129 | } |
3138 | 3130 | ||
3139 | static int | 3131 | static int ctnetlink_new_expect(struct net *net, struct sock *ctnl, |
3140 | ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | 3132 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
3141 | const struct nlmsghdr *nlh, | 3133 | const struct nlattr * const cda[]) |
3142 | const struct nlattr * const cda[]) | ||
3143 | { | 3134 | { |
3144 | struct net *net = sock_net(ctnl); | ||
3145 | struct nf_conntrack_tuple tuple; | 3135 | struct nf_conntrack_tuple tuple; |
3146 | struct nf_conntrack_expect *exp; | 3136 | struct nf_conntrack_expect *exp; |
3147 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 3137 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
@@ -3242,10 +3232,10 @@ ctnetlink_exp_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
3242 | return skb->len; | 3232 | return skb->len; |
3243 | } | 3233 | } |
3244 | 3234 | ||
3245 | static int | 3235 | static int ctnetlink_stat_exp_cpu(struct net *net, struct sock *ctnl, |
3246 | ctnetlink_stat_exp_cpu(struct sock *ctnl, struct sk_buff *skb, | 3236 | struct sk_buff *skb, |
3247 | const struct nlmsghdr *nlh, | 3237 | const struct nlmsghdr *nlh, |
3248 | const struct nlattr * const cda[]) | 3238 | const struct nlattr * const cda[]) |
3249 | { | 3239 | { |
3250 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 3240 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
3251 | struct netlink_dump_control c = { | 3241 | struct netlink_dump_control c = { |
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index 4a2134fd3fcb..7523a575f6d1 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c | |||
@@ -17,6 +17,8 @@ | |||
17 | * published by the Free Software Foundation. | 17 | * published by the Free Software Foundation. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
21 | |||
20 | #include <linux/module.h> | 22 | #include <linux/module.h> |
21 | #include <linux/moduleparam.h> | 23 | #include <linux/moduleparam.h> |
22 | #include <linux/netfilter.h> | 24 | #include <linux/netfilter.h> |
@@ -120,14 +122,14 @@ static int help(struct sk_buff *skb, | |||
120 | ct_sane_info->state = SANE_STATE_NORMAL; | 122 | ct_sane_info->state = SANE_STATE_NORMAL; |
121 | 123 | ||
122 | if (datalen < sizeof(struct sane_reply_net_start)) { | 124 | if (datalen < sizeof(struct sane_reply_net_start)) { |
123 | pr_debug("nf_ct_sane: NET_START reply too short\n"); | 125 | pr_debug("NET_START reply too short\n"); |
124 | goto out; | 126 | goto out; |
125 | } | 127 | } |
126 | 128 | ||
127 | reply = sb_ptr; | 129 | reply = sb_ptr; |
128 | if (reply->status != htonl(SANE_STATUS_SUCCESS)) { | 130 | if (reply->status != htonl(SANE_STATUS_SUCCESS)) { |
129 | /* saned refused the command */ | 131 | /* saned refused the command */ |
130 | pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n", | 132 | pr_debug("unsuccessful SANE_STATUS = %u\n", |
131 | ntohl(reply->status)); | 133 | ntohl(reply->status)); |
132 | goto out; | 134 | goto out; |
133 | } | 135 | } |
@@ -148,7 +150,7 @@ static int help(struct sk_buff *skb, | |||
148 | &tuple->src.u3, &tuple->dst.u3, | 150 | &tuple->src.u3, &tuple->dst.u3, |
149 | IPPROTO_TCP, NULL, &reply->port); | 151 | IPPROTO_TCP, NULL, &reply->port); |
150 | 152 | ||
151 | pr_debug("nf_ct_sane: expect: "); | 153 | pr_debug("expect: "); |
152 | nf_ct_dump_tuple(&exp->tuple); | 154 | nf_ct_dump_tuple(&exp->tuple); |
153 | 155 | ||
154 | /* Can't expect this? Best to drop packet now. */ | 156 | /* Can't expect this? Best to drop packet now. */ |
@@ -178,8 +180,7 @@ static void nf_conntrack_sane_fini(void) | |||
178 | 180 | ||
179 | for (i = 0; i < ports_c; i++) { | 181 | for (i = 0; i < ports_c; i++) { |
180 | for (j = 0; j < 2; j++) { | 182 | for (j = 0; j < 2; j++) { |
181 | pr_debug("nf_ct_sane: unregistering helper for pf: %d " | 183 | pr_debug("unregistering helper for pf: %d port: %d\n", |
182 | "port: %d\n", | ||
183 | sane[i][j].tuple.src.l3num, ports[i]); | 184 | sane[i][j].tuple.src.l3num, ports[i]); |
184 | nf_conntrack_helper_unregister(&sane[i][j]); | 185 | nf_conntrack_helper_unregister(&sane[i][j]); |
185 | } | 186 | } |
@@ -216,14 +217,12 @@ static int __init nf_conntrack_sane_init(void) | |||
216 | else | 217 | else |
217 | sprintf(sane[i][j].name, "sane-%d", ports[i]); | 218 | sprintf(sane[i][j].name, "sane-%d", ports[i]); |
218 | 219 | ||
219 | pr_debug("nf_ct_sane: registering helper for pf: %d " | 220 | pr_debug("registering helper for pf: %d port: %d\n", |
220 | "port: %d\n", | ||
221 | sane[i][j].tuple.src.l3num, ports[i]); | 221 | sane[i][j].tuple.src.l3num, ports[i]); |
222 | ret = nf_conntrack_helper_register(&sane[i][j]); | 222 | ret = nf_conntrack_helper_register(&sane[i][j]); |
223 | if (ret) { | 223 | if (ret) { |
224 | printk(KERN_ERR "nf_ct_sane: failed to " | 224 | pr_err("failed to register helper for pf: %d port: %d\n", |
225 | "register helper for pf: %d port: %d\n", | 225 | sane[i][j].tuple.src.l3num, ports[i]); |
226 | sane[i][j].tuple.src.l3num, ports[i]); | ||
227 | nf_conntrack_sane_fini(); | 226 | nf_conntrack_sane_fini(); |
228 | return ret; | 227 | return ret; |
229 | } | 228 | } |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 885b4aba3695..3e06402739e0 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | |||
13 | #include <linux/module.h> | 15 | #include <linux/module.h> |
14 | #include <linux/ctype.h> | 16 | #include <linux/ctype.h> |
15 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
@@ -1665,8 +1667,7 @@ static int __init nf_conntrack_sip_init(void) | |||
1665 | 1667 | ||
1666 | ret = nf_conntrack_helper_register(&sip[i][j]); | 1668 | ret = nf_conntrack_helper_register(&sip[i][j]); |
1667 | if (ret) { | 1669 | if (ret) { |
1668 | printk(KERN_ERR "nf_ct_sip: failed to register" | 1670 | pr_err("failed to register helper for pf: %u port: %u\n", |
1669 | " helper for pf: %u port: %u\n", | ||
1670 | sip[i][j].tuple.src.l3num, ports[i]); | 1671 | sip[i][j].tuple.src.l3num, ports[i]); |
1671 | nf_conntrack_sip_fini(); | 1672 | nf_conntrack_sip_fini(); |
1672 | return ret; | 1673 | return ret; |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 1fb3cacc04e1..0f1a45bcacb2 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -392,11 +392,18 @@ static const struct file_operations ct_cpu_seq_fops = { | |||
392 | static int nf_conntrack_standalone_init_proc(struct net *net) | 392 | static int nf_conntrack_standalone_init_proc(struct net *net) |
393 | { | 393 | { |
394 | struct proc_dir_entry *pde; | 394 | struct proc_dir_entry *pde; |
395 | kuid_t root_uid; | ||
396 | kgid_t root_gid; | ||
395 | 397 | ||
396 | pde = proc_create("nf_conntrack", 0440, net->proc_net, &ct_file_ops); | 398 | pde = proc_create("nf_conntrack", 0440, net->proc_net, &ct_file_ops); |
397 | if (!pde) | 399 | if (!pde) |
398 | goto out_nf_conntrack; | 400 | goto out_nf_conntrack; |
399 | 401 | ||
402 | root_uid = make_kuid(net->user_ns, 0); | ||
403 | root_gid = make_kgid(net->user_ns, 0); | ||
404 | if (uid_valid(root_uid) && gid_valid(root_gid)) | ||
405 | proc_set_user(pde, root_uid, root_gid); | ||
406 | |||
400 | pde = proc_create("nf_conntrack", S_IRUGO, net->proc_net_stat, | 407 | pde = proc_create("nf_conntrack", S_IRUGO, net->proc_net_stat, |
401 | &ct_cpu_seq_fops); | 408 | &ct_cpu_seq_fops); |
402 | if (!pde) | 409 | if (!pde) |
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index e68ab4fbd71f..36f964066461 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * published by the Free Software Foundation. | 5 | * published by the Free Software Foundation. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
9 | |||
8 | #include <linux/module.h> | 10 | #include <linux/module.h> |
9 | #include <linux/moduleparam.h> | 11 | #include <linux/moduleparam.h> |
10 | #include <linux/in.h> | 12 | #include <linux/in.h> |
@@ -138,9 +140,8 @@ static int __init nf_conntrack_tftp_init(void) | |||
138 | 140 | ||
139 | ret = nf_conntrack_helper_register(&tftp[i][j]); | 141 | ret = nf_conntrack_helper_register(&tftp[i][j]); |
140 | if (ret) { | 142 | if (ret) { |
141 | printk(KERN_ERR "nf_ct_tftp: failed to register" | 143 | pr_err("failed to register helper for pf: %u port: %u\n", |
142 | " helper for pf: %u port: %u\n", | 144 | tftp[i][j].tuple.src.l3num, ports[i]); |
143 | tftp[i][j].tuple.src.l3num, ports[i]); | ||
144 | nf_conntrack_tftp_fini(); | 145 | nf_conntrack_tftp_fini(); |
145 | return ret; | 146 | return ret; |
146 | } | 147 | } |
diff --git a/net/netfilter/nf_conntrack_timeout.c b/net/netfilter/nf_conntrack_timeout.c index 93da609d9d29..26e742006c48 100644 --- a/net/netfilter/nf_conntrack_timeout.c +++ b/net/netfilter/nf_conntrack_timeout.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <net/netfilter/nf_conntrack_timeout.h> | 25 | #include <net/netfilter/nf_conntrack_timeout.h> |
26 | 26 | ||
27 | struct ctnl_timeout * | 27 | struct ctnl_timeout * |
28 | (*nf_ct_timeout_find_get_hook)(const char *name) __read_mostly; | 28 | (*nf_ct_timeout_find_get_hook)(struct net *net, const char *name) __read_mostly; |
29 | EXPORT_SYMBOL_GPL(nf_ct_timeout_find_get_hook); | 29 | EXPORT_SYMBOL_GPL(nf_ct_timeout_find_get_hook); |
30 | 30 | ||
31 | void (*nf_ct_timeout_put_hook)(struct ctnl_timeout *timeout) __read_mostly; | 31 | void (*nf_ct_timeout_put_hook)(struct ctnl_timeout *timeout) __read_mostly; |
diff --git a/net/netfilter/nf_dup_netdev.c b/net/netfilter/nf_dup_netdev.c new file mode 100644 index 000000000000..8414ee1a0319 --- /dev/null +++ b/net/netfilter/nf_dup_netdev.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Pablo Neira Ayuso <pablo@netfilter.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License version 2 as published by | ||
6 | * the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/netlink.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/netfilter/nf_tables.h> | ||
15 | #include <net/netfilter/nf_tables.h> | ||
16 | |||
17 | void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif) | ||
18 | { | ||
19 | struct net_device *dev; | ||
20 | struct sk_buff *skb; | ||
21 | |||
22 | dev = dev_get_by_index_rcu(pkt->net, oif); | ||
23 | if (dev == NULL) | ||
24 | return; | ||
25 | |||
26 | skb = skb_clone(pkt->skb, GFP_ATOMIC); | ||
27 | if (skb == NULL) | ||
28 | return; | ||
29 | |||
30 | if (skb_mac_header_was_set(skb)) | ||
31 | skb_push(skb, skb->mac_len); | ||
32 | |||
33 | skb->dev = dev; | ||
34 | skb_sender_cpu_clear(skb); | ||
35 | dev_queue_xmit(skb); | ||
36 | } | ||
37 | EXPORT_SYMBOL_GPL(nf_dup_netdev_egress); | ||
38 | |||
39 | MODULE_LICENSE("GPL"); | ||
40 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 93cc4737018f..2011977cd79d 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -41,6 +41,8 @@ int nft_register_afinfo(struct net *net, struct nft_af_info *afi) | |||
41 | } | 41 | } |
42 | EXPORT_SYMBOL_GPL(nft_register_afinfo); | 42 | EXPORT_SYMBOL_GPL(nft_register_afinfo); |
43 | 43 | ||
44 | static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi); | ||
45 | |||
44 | /** | 46 | /** |
45 | * nft_unregister_afinfo - unregister nf_tables address family info | 47 | * nft_unregister_afinfo - unregister nf_tables address family info |
46 | * | 48 | * |
@@ -48,9 +50,10 @@ EXPORT_SYMBOL_GPL(nft_register_afinfo); | |||
48 | * | 50 | * |
49 | * Unregister the address family for use with nf_tables. | 51 | * Unregister the address family for use with nf_tables. |
50 | */ | 52 | */ |
51 | void nft_unregister_afinfo(struct nft_af_info *afi) | 53 | void nft_unregister_afinfo(struct net *net, struct nft_af_info *afi) |
52 | { | 54 | { |
53 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 55 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
56 | __nft_release_afinfo(net, afi); | ||
54 | list_del_rcu(&afi->list); | 57 | list_del_rcu(&afi->list); |
55 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | 58 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
56 | } | 59 | } |
@@ -89,6 +92,7 @@ nf_tables_afinfo_lookup(struct net *net, int family, bool autoload) | |||
89 | } | 92 | } |
90 | 93 | ||
91 | static void nft_ctx_init(struct nft_ctx *ctx, | 94 | static void nft_ctx_init(struct nft_ctx *ctx, |
95 | struct net *net, | ||
92 | const struct sk_buff *skb, | 96 | const struct sk_buff *skb, |
93 | const struct nlmsghdr *nlh, | 97 | const struct nlmsghdr *nlh, |
94 | struct nft_af_info *afi, | 98 | struct nft_af_info *afi, |
@@ -96,7 +100,7 @@ static void nft_ctx_init(struct nft_ctx *ctx, | |||
96 | struct nft_chain *chain, | 100 | struct nft_chain *chain, |
97 | const struct nlattr * const *nla) | 101 | const struct nlattr * const *nla) |
98 | { | 102 | { |
99 | ctx->net = sock_net(skb->sk); | 103 | ctx->net = net; |
100 | ctx->afi = afi; | 104 | ctx->afi = afi; |
101 | ctx->table = table; | 105 | ctx->table = table; |
102 | ctx->chain = chain; | 106 | ctx->chain = chain; |
@@ -127,8 +131,8 @@ static void nft_trans_destroy(struct nft_trans *trans) | |||
127 | kfree(trans); | 131 | kfree(trans); |
128 | } | 132 | } |
129 | 133 | ||
130 | int nft_register_basechain(struct nft_base_chain *basechain, | 134 | static int nft_register_basechain(struct nft_base_chain *basechain, |
131 | unsigned int hook_nops) | 135 | unsigned int hook_nops) |
132 | { | 136 | { |
133 | struct net *net = read_pnet(&basechain->pnet); | 137 | struct net *net = read_pnet(&basechain->pnet); |
134 | 138 | ||
@@ -137,10 +141,9 @@ int nft_register_basechain(struct nft_base_chain *basechain, | |||
137 | 141 | ||
138 | return nf_register_net_hooks(net, basechain->ops, hook_nops); | 142 | return nf_register_net_hooks(net, basechain->ops, hook_nops); |
139 | } | 143 | } |
140 | EXPORT_SYMBOL_GPL(nft_register_basechain); | ||
141 | 144 | ||
142 | void nft_unregister_basechain(struct nft_base_chain *basechain, | 145 | static void nft_unregister_basechain(struct nft_base_chain *basechain, |
143 | unsigned int hook_nops) | 146 | unsigned int hook_nops) |
144 | { | 147 | { |
145 | struct net *net = read_pnet(&basechain->pnet); | 148 | struct net *net = read_pnet(&basechain->pnet); |
146 | 149 | ||
@@ -149,7 +152,6 @@ void nft_unregister_basechain(struct nft_base_chain *basechain, | |||
149 | 152 | ||
150 | nf_unregister_net_hooks(net, basechain->ops, hook_nops); | 153 | nf_unregister_net_hooks(net, basechain->ops, hook_nops); |
151 | } | 154 | } |
152 | EXPORT_SYMBOL_GPL(nft_unregister_basechain); | ||
153 | 155 | ||
154 | static int nf_tables_register_hooks(const struct nft_table *table, | 156 | static int nf_tables_register_hooks(const struct nft_table *table, |
155 | struct nft_chain *chain, | 157 | struct nft_chain *chain, |
@@ -541,15 +543,14 @@ done: | |||
541 | return skb->len; | 543 | return skb->len; |
542 | } | 544 | } |
543 | 545 | ||
544 | static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb, | 546 | static int nf_tables_gettable(struct net *net, struct sock *nlsk, |
545 | const struct nlmsghdr *nlh, | 547 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
546 | const struct nlattr * const nla[]) | 548 | const struct nlattr * const nla[]) |
547 | { | 549 | { |
548 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 550 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
549 | const struct nft_af_info *afi; | 551 | const struct nft_af_info *afi; |
550 | const struct nft_table *table; | 552 | const struct nft_table *table; |
551 | struct sk_buff *skb2; | 553 | struct sk_buff *skb2; |
552 | struct net *net = sock_net(skb->sk); | ||
553 | int family = nfmsg->nfgen_family; | 554 | int family = nfmsg->nfgen_family; |
554 | int err; | 555 | int err; |
555 | 556 | ||
@@ -672,15 +673,14 @@ err: | |||
672 | return ret; | 673 | return ret; |
673 | } | 674 | } |
674 | 675 | ||
675 | static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, | 676 | static int nf_tables_newtable(struct net *net, struct sock *nlsk, |
676 | const struct nlmsghdr *nlh, | 677 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
677 | const struct nlattr * const nla[]) | 678 | const struct nlattr * const nla[]) |
678 | { | 679 | { |
679 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 680 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
680 | const struct nlattr *name; | 681 | const struct nlattr *name; |
681 | struct nft_af_info *afi; | 682 | struct nft_af_info *afi; |
682 | struct nft_table *table; | 683 | struct nft_table *table; |
683 | struct net *net = sock_net(skb->sk); | ||
684 | int family = nfmsg->nfgen_family; | 684 | int family = nfmsg->nfgen_family; |
685 | u32 flags = 0; | 685 | u32 flags = 0; |
686 | struct nft_ctx ctx; | 686 | struct nft_ctx ctx; |
@@ -706,7 +706,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, | |||
706 | if (nlh->nlmsg_flags & NLM_F_REPLACE) | 706 | if (nlh->nlmsg_flags & NLM_F_REPLACE) |
707 | return -EOPNOTSUPP; | 707 | return -EOPNOTSUPP; |
708 | 708 | ||
709 | nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); | 709 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); |
710 | return nf_tables_updtable(&ctx); | 710 | return nf_tables_updtable(&ctx); |
711 | } | 711 | } |
712 | 712 | ||
@@ -730,7 +730,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, | |||
730 | INIT_LIST_HEAD(&table->sets); | 730 | INIT_LIST_HEAD(&table->sets); |
731 | table->flags = flags; | 731 | table->flags = flags; |
732 | 732 | ||
733 | nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); | 733 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); |
734 | err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); | 734 | err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); |
735 | if (err < 0) | 735 | if (err < 0) |
736 | goto err3; | 736 | goto err3; |
@@ -810,18 +810,17 @@ out: | |||
810 | return err; | 810 | return err; |
811 | } | 811 | } |
812 | 812 | ||
813 | static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb, | 813 | static int nf_tables_deltable(struct net *net, struct sock *nlsk, |
814 | const struct nlmsghdr *nlh, | 814 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
815 | const struct nlattr * const nla[]) | 815 | const struct nlattr * const nla[]) |
816 | { | 816 | { |
817 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 817 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
818 | struct nft_af_info *afi; | 818 | struct nft_af_info *afi; |
819 | struct nft_table *table; | 819 | struct nft_table *table; |
820 | struct net *net = sock_net(skb->sk); | ||
821 | int family = nfmsg->nfgen_family; | 820 | int family = nfmsg->nfgen_family; |
822 | struct nft_ctx ctx; | 821 | struct nft_ctx ctx; |
823 | 822 | ||
824 | nft_ctx_init(&ctx, skb, nlh, NULL, NULL, NULL, nla); | 823 | nft_ctx_init(&ctx, net, skb, nlh, NULL, NULL, NULL, nla); |
825 | if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) | 824 | if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) |
826 | return nft_flush(&ctx, family); | 825 | return nft_flush(&ctx, family); |
827 | 826 | ||
@@ -832,8 +831,6 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb, | |||
832 | table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]); | 831 | table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]); |
833 | if (IS_ERR(table)) | 832 | if (IS_ERR(table)) |
834 | return PTR_ERR(table); | 833 | return PTR_ERR(table); |
835 | if (table->flags & NFT_TABLE_INACTIVE) | ||
836 | return -ENOENT; | ||
837 | 834 | ||
838 | ctx.afi = afi; | 835 | ctx.afi = afi; |
839 | ctx.table = table; | 836 | ctx.table = table; |
@@ -1099,8 +1096,8 @@ done: | |||
1099 | return skb->len; | 1096 | return skb->len; |
1100 | } | 1097 | } |
1101 | 1098 | ||
1102 | static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb, | 1099 | static int nf_tables_getchain(struct net *net, struct sock *nlsk, |
1103 | const struct nlmsghdr *nlh, | 1100 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1104 | const struct nlattr * const nla[]) | 1101 | const struct nlattr * const nla[]) |
1105 | { | 1102 | { |
1106 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1103 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
@@ -1108,7 +1105,6 @@ static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb, | |||
1108 | const struct nft_table *table; | 1105 | const struct nft_table *table; |
1109 | const struct nft_chain *chain; | 1106 | const struct nft_chain *chain; |
1110 | struct sk_buff *skb2; | 1107 | struct sk_buff *skb2; |
1111 | struct net *net = sock_net(skb->sk); | ||
1112 | int family = nfmsg->nfgen_family; | 1108 | int family = nfmsg->nfgen_family; |
1113 | int err; | 1109 | int err; |
1114 | 1110 | ||
@@ -1221,8 +1217,8 @@ static void nf_tables_chain_destroy(struct nft_chain *chain) | |||
1221 | } | 1217 | } |
1222 | } | 1218 | } |
1223 | 1219 | ||
1224 | static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | 1220 | static int nf_tables_newchain(struct net *net, struct sock *nlsk, |
1225 | const struct nlmsghdr *nlh, | 1221 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1226 | const struct nlattr * const nla[]) | 1222 | const struct nlattr * const nla[]) |
1227 | { | 1223 | { |
1228 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1224 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
@@ -1232,7 +1228,6 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
1232 | struct nft_chain *chain; | 1228 | struct nft_chain *chain; |
1233 | struct nft_base_chain *basechain = NULL; | 1229 | struct nft_base_chain *basechain = NULL; |
1234 | struct nlattr *ha[NFTA_HOOK_MAX + 1]; | 1230 | struct nlattr *ha[NFTA_HOOK_MAX + 1]; |
1235 | struct net *net = sock_net(skb->sk); | ||
1236 | int family = nfmsg->nfgen_family; | 1231 | int family = nfmsg->nfgen_family; |
1237 | struct net_device *dev = NULL; | 1232 | struct net_device *dev = NULL; |
1238 | u8 policy = NF_ACCEPT; | 1233 | u8 policy = NF_ACCEPT; |
@@ -1313,7 +1308,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
1313 | return PTR_ERR(stats); | 1308 | return PTR_ERR(stats); |
1314 | } | 1309 | } |
1315 | 1310 | ||
1316 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); | 1311 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); |
1317 | trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN, | 1312 | trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN, |
1318 | sizeof(struct nft_trans_chain)); | 1313 | sizeof(struct nft_trans_chain)); |
1319 | if (trans == NULL) { | 1314 | if (trans == NULL) { |
@@ -1461,7 +1456,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, | |||
1461 | if (err < 0) | 1456 | if (err < 0) |
1462 | goto err1; | 1457 | goto err1; |
1463 | 1458 | ||
1464 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); | 1459 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); |
1465 | err = nft_trans_chain_add(&ctx, NFT_MSG_NEWCHAIN); | 1460 | err = nft_trans_chain_add(&ctx, NFT_MSG_NEWCHAIN); |
1466 | if (err < 0) | 1461 | if (err < 0) |
1467 | goto err2; | 1462 | goto err2; |
@@ -1476,15 +1471,14 @@ err1: | |||
1476 | return err; | 1471 | return err; |
1477 | } | 1472 | } |
1478 | 1473 | ||
1479 | static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, | 1474 | static int nf_tables_delchain(struct net *net, struct sock *nlsk, |
1480 | const struct nlmsghdr *nlh, | 1475 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1481 | const struct nlattr * const nla[]) | 1476 | const struct nlattr * const nla[]) |
1482 | { | 1477 | { |
1483 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1478 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
1484 | struct nft_af_info *afi; | 1479 | struct nft_af_info *afi; |
1485 | struct nft_table *table; | 1480 | struct nft_table *table; |
1486 | struct nft_chain *chain; | 1481 | struct nft_chain *chain; |
1487 | struct net *net = sock_net(skb->sk); | ||
1488 | int family = nfmsg->nfgen_family; | 1482 | int family = nfmsg->nfgen_family; |
1489 | struct nft_ctx ctx; | 1483 | struct nft_ctx ctx; |
1490 | 1484 | ||
@@ -1495,18 +1489,14 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, | |||
1495 | table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]); | 1489 | table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]); |
1496 | if (IS_ERR(table)) | 1490 | if (IS_ERR(table)) |
1497 | return PTR_ERR(table); | 1491 | return PTR_ERR(table); |
1498 | if (table->flags & NFT_TABLE_INACTIVE) | ||
1499 | return -ENOENT; | ||
1500 | 1492 | ||
1501 | chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]); | 1493 | chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]); |
1502 | if (IS_ERR(chain)) | 1494 | if (IS_ERR(chain)) |
1503 | return PTR_ERR(chain); | 1495 | return PTR_ERR(chain); |
1504 | if (chain->flags & NFT_CHAIN_INACTIVE) | ||
1505 | return -ENOENT; | ||
1506 | if (chain->use > 0) | 1496 | if (chain->use > 0) |
1507 | return -EBUSY; | 1497 | return -EBUSY; |
1508 | 1498 | ||
1509 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); | 1499 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); |
1510 | 1500 | ||
1511 | return nft_delchain(&ctx); | 1501 | return nft_delchain(&ctx); |
1512 | } | 1502 | } |
@@ -1931,8 +1921,8 @@ done: | |||
1931 | return skb->len; | 1921 | return skb->len; |
1932 | } | 1922 | } |
1933 | 1923 | ||
1934 | static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb, | 1924 | static int nf_tables_getrule(struct net *net, struct sock *nlsk, |
1935 | const struct nlmsghdr *nlh, | 1925 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1936 | const struct nlattr * const nla[]) | 1926 | const struct nlattr * const nla[]) |
1937 | { | 1927 | { |
1938 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1928 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
@@ -1941,7 +1931,6 @@ static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb, | |||
1941 | const struct nft_chain *chain; | 1931 | const struct nft_chain *chain; |
1942 | const struct nft_rule *rule; | 1932 | const struct nft_rule *rule; |
1943 | struct sk_buff *skb2; | 1933 | struct sk_buff *skb2; |
1944 | struct net *net = sock_net(skb->sk); | ||
1945 | int family = nfmsg->nfgen_family; | 1934 | int family = nfmsg->nfgen_family; |
1946 | int err; | 1935 | int err; |
1947 | 1936 | ||
@@ -2010,13 +1999,12 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx, | |||
2010 | 1999 | ||
2011 | static struct nft_expr_info *info; | 2000 | static struct nft_expr_info *info; |
2012 | 2001 | ||
2013 | static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, | 2002 | static int nf_tables_newrule(struct net *net, struct sock *nlsk, |
2014 | const struct nlmsghdr *nlh, | 2003 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
2015 | const struct nlattr * const nla[]) | 2004 | const struct nlattr * const nla[]) |
2016 | { | 2005 | { |
2017 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2006 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
2018 | struct nft_af_info *afi; | 2007 | struct nft_af_info *afi; |
2019 | struct net *net = sock_net(skb->sk); | ||
2020 | struct nft_table *table; | 2008 | struct nft_table *table; |
2021 | struct nft_chain *chain; | 2009 | struct nft_chain *chain; |
2022 | struct nft_rule *rule, *old_rule = NULL; | 2010 | struct nft_rule *rule, *old_rule = NULL; |
@@ -2075,7 +2063,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, | |||
2075 | return PTR_ERR(old_rule); | 2063 | return PTR_ERR(old_rule); |
2076 | } | 2064 | } |
2077 | 2065 | ||
2078 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); | 2066 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); |
2079 | 2067 | ||
2080 | n = 0; | 2068 | n = 0; |
2081 | size = 0; | 2069 | size = 0; |
@@ -2176,13 +2164,12 @@ err1: | |||
2176 | return err; | 2164 | return err; |
2177 | } | 2165 | } |
2178 | 2166 | ||
2179 | static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb, | 2167 | static int nf_tables_delrule(struct net *net, struct sock *nlsk, |
2180 | const struct nlmsghdr *nlh, | 2168 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
2181 | const struct nlattr * const nla[]) | 2169 | const struct nlattr * const nla[]) |
2182 | { | 2170 | { |
2183 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2171 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
2184 | struct nft_af_info *afi; | 2172 | struct nft_af_info *afi; |
2185 | struct net *net = sock_net(skb->sk); | ||
2186 | struct nft_table *table; | 2173 | struct nft_table *table; |
2187 | struct nft_chain *chain = NULL; | 2174 | struct nft_chain *chain = NULL; |
2188 | struct nft_rule *rule; | 2175 | struct nft_rule *rule; |
@@ -2196,8 +2183,6 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb, | |||
2196 | table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]); | 2183 | table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]); |
2197 | if (IS_ERR(table)) | 2184 | if (IS_ERR(table)) |
2198 | return PTR_ERR(table); | 2185 | return PTR_ERR(table); |
2199 | if (table->flags & NFT_TABLE_INACTIVE) | ||
2200 | return -ENOENT; | ||
2201 | 2186 | ||
2202 | if (nla[NFTA_RULE_CHAIN]) { | 2187 | if (nla[NFTA_RULE_CHAIN]) { |
2203 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]); | 2188 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]); |
@@ -2205,7 +2190,7 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb, | |||
2205 | return PTR_ERR(chain); | 2190 | return PTR_ERR(chain); |
2206 | } | 2191 | } |
2207 | 2192 | ||
2208 | nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); | 2193 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); |
2209 | 2194 | ||
2210 | if (chain) { | 2195 | if (chain) { |
2211 | if (nla[NFTA_RULE_HANDLE]) { | 2196 | if (nla[NFTA_RULE_HANDLE]) { |
@@ -2338,18 +2323,19 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = { | |||
2338 | [NFTA_SET_ID] = { .type = NLA_U32 }, | 2323 | [NFTA_SET_ID] = { .type = NLA_U32 }, |
2339 | [NFTA_SET_TIMEOUT] = { .type = NLA_U64 }, | 2324 | [NFTA_SET_TIMEOUT] = { .type = NLA_U64 }, |
2340 | [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 }, | 2325 | [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 }, |
2326 | [NFTA_SET_USERDATA] = { .type = NLA_BINARY, | ||
2327 | .len = NFT_USERDATA_MAXLEN }, | ||
2341 | }; | 2328 | }; |
2342 | 2329 | ||
2343 | static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { | 2330 | static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { |
2344 | [NFTA_SET_DESC_SIZE] = { .type = NLA_U32 }, | 2331 | [NFTA_SET_DESC_SIZE] = { .type = NLA_U32 }, |
2345 | }; | 2332 | }; |
2346 | 2333 | ||
2347 | static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, | 2334 | static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net, |
2348 | const struct sk_buff *skb, | 2335 | const struct sk_buff *skb, |
2349 | const struct nlmsghdr *nlh, | 2336 | const struct nlmsghdr *nlh, |
2350 | const struct nlattr * const nla[]) | 2337 | const struct nlattr * const nla[]) |
2351 | { | 2338 | { |
2352 | struct net *net = sock_net(skb->sk); | ||
2353 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2339 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
2354 | struct nft_af_info *afi = NULL; | 2340 | struct nft_af_info *afi = NULL; |
2355 | struct nft_table *table = NULL; | 2341 | struct nft_table *table = NULL; |
@@ -2367,11 +2353,9 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, | |||
2367 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); | 2353 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); |
2368 | if (IS_ERR(table)) | 2354 | if (IS_ERR(table)) |
2369 | return PTR_ERR(table); | 2355 | return PTR_ERR(table); |
2370 | if (table->flags & NFT_TABLE_INACTIVE) | ||
2371 | return -ENOENT; | ||
2372 | } | 2356 | } |
2373 | 2357 | ||
2374 | nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla); | 2358 | nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); |
2375 | return 0; | 2359 | return 0; |
2376 | } | 2360 | } |
2377 | 2361 | ||
@@ -2500,6 +2484,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, | |||
2500 | goto nla_put_failure; | 2484 | goto nla_put_failure; |
2501 | } | 2485 | } |
2502 | 2486 | ||
2487 | if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata)) | ||
2488 | goto nla_put_failure; | ||
2489 | |||
2503 | desc = nla_nest_start(skb, NFTA_SET_DESC); | 2490 | desc = nla_nest_start(skb, NFTA_SET_DESC); |
2504 | if (desc == NULL) | 2491 | if (desc == NULL) |
2505 | goto nla_put_failure; | 2492 | goto nla_put_failure; |
@@ -2619,8 +2606,8 @@ static int nf_tables_dump_sets_done(struct netlink_callback *cb) | |||
2619 | return 0; | 2606 | return 0; |
2620 | } | 2607 | } |
2621 | 2608 | ||
2622 | static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, | 2609 | static int nf_tables_getset(struct net *net, struct sock *nlsk, |
2623 | const struct nlmsghdr *nlh, | 2610 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
2624 | const struct nlattr * const nla[]) | 2611 | const struct nlattr * const nla[]) |
2625 | { | 2612 | { |
2626 | const struct nft_set *set; | 2613 | const struct nft_set *set; |
@@ -2630,7 +2617,7 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, | |||
2630 | int err; | 2617 | int err; |
2631 | 2618 | ||
2632 | /* Verify existence before starting dump */ | 2619 | /* Verify existence before starting dump */ |
2633 | err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla); | 2620 | err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla); |
2634 | if (err < 0) | 2621 | if (err < 0) |
2635 | return err; | 2622 | return err; |
2636 | 2623 | ||
@@ -2693,14 +2680,13 @@ static int nf_tables_set_desc_parse(const struct nft_ctx *ctx, | |||
2693 | return 0; | 2680 | return 0; |
2694 | } | 2681 | } |
2695 | 2682 | ||
2696 | static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | 2683 | static int nf_tables_newset(struct net *net, struct sock *nlsk, |
2697 | const struct nlmsghdr *nlh, | 2684 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
2698 | const struct nlattr * const nla[]) | 2685 | const struct nlattr * const nla[]) |
2699 | { | 2686 | { |
2700 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2687 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
2701 | const struct nft_set_ops *ops; | 2688 | const struct nft_set_ops *ops; |
2702 | struct nft_af_info *afi; | 2689 | struct nft_af_info *afi; |
2703 | struct net *net = sock_net(skb->sk); | ||
2704 | struct nft_table *table; | 2690 | struct nft_table *table; |
2705 | struct nft_set *set; | 2691 | struct nft_set *set; |
2706 | struct nft_ctx ctx; | 2692 | struct nft_ctx ctx; |
@@ -2710,6 +2696,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | |||
2710 | u64 timeout; | 2696 | u64 timeout; |
2711 | u32 ktype, dtype, flags, policy, gc_int; | 2697 | u32 ktype, dtype, flags, policy, gc_int; |
2712 | struct nft_set_desc desc; | 2698 | struct nft_set_desc desc; |
2699 | unsigned char *udata; | ||
2700 | u16 udlen; | ||
2713 | int err; | 2701 | int err; |
2714 | 2702 | ||
2715 | if (nla[NFTA_SET_TABLE] == NULL || | 2703 | if (nla[NFTA_SET_TABLE] == NULL || |
@@ -2798,7 +2786,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | |||
2798 | if (IS_ERR(table)) | 2786 | if (IS_ERR(table)) |
2799 | return PTR_ERR(table); | 2787 | return PTR_ERR(table); |
2800 | 2788 | ||
2801 | nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); | 2789 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); |
2802 | 2790 | ||
2803 | set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME]); | 2791 | set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME]); |
2804 | if (IS_ERR(set)) { | 2792 | if (IS_ERR(set)) { |
@@ -2822,12 +2810,16 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | |||
2822 | if (IS_ERR(ops)) | 2810 | if (IS_ERR(ops)) |
2823 | return PTR_ERR(ops); | 2811 | return PTR_ERR(ops); |
2824 | 2812 | ||
2813 | udlen = 0; | ||
2814 | if (nla[NFTA_SET_USERDATA]) | ||
2815 | udlen = nla_len(nla[NFTA_SET_USERDATA]); | ||
2816 | |||
2825 | size = 0; | 2817 | size = 0; |
2826 | if (ops->privsize != NULL) | 2818 | if (ops->privsize != NULL) |
2827 | size = ops->privsize(nla); | 2819 | size = ops->privsize(nla); |
2828 | 2820 | ||
2829 | err = -ENOMEM; | 2821 | err = -ENOMEM; |
2830 | set = kzalloc(sizeof(*set) + size, GFP_KERNEL); | 2822 | set = kzalloc(sizeof(*set) + size + udlen, GFP_KERNEL); |
2831 | if (set == NULL) | 2823 | if (set == NULL) |
2832 | goto err1; | 2824 | goto err1; |
2833 | 2825 | ||
@@ -2836,6 +2828,12 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | |||
2836 | if (err < 0) | 2828 | if (err < 0) |
2837 | goto err2; | 2829 | goto err2; |
2838 | 2830 | ||
2831 | udata = NULL; | ||
2832 | if (udlen) { | ||
2833 | udata = set->data + size; | ||
2834 | nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen); | ||
2835 | } | ||
2836 | |||
2839 | INIT_LIST_HEAD(&set->bindings); | 2837 | INIT_LIST_HEAD(&set->bindings); |
2840 | write_pnet(&set->pnet, net); | 2838 | write_pnet(&set->pnet, net); |
2841 | set->ops = ops; | 2839 | set->ops = ops; |
@@ -2846,6 +2844,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, | |||
2846 | set->flags = flags; | 2844 | set->flags = flags; |
2847 | set->size = desc.size; | 2845 | set->size = desc.size; |
2848 | set->policy = policy; | 2846 | set->policy = policy; |
2847 | set->udlen = udlen; | ||
2848 | set->udata = udata; | ||
2849 | set->timeout = timeout; | 2849 | set->timeout = timeout; |
2850 | set->gc_int = gc_int; | 2850 | set->gc_int = gc_int; |
2851 | 2851 | ||
@@ -2882,8 +2882,8 @@ static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set | |||
2882 | nft_set_destroy(set); | 2882 | nft_set_destroy(set); |
2883 | } | 2883 | } |
2884 | 2884 | ||
2885 | static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, | 2885 | static int nf_tables_delset(struct net *net, struct sock *nlsk, |
2886 | const struct nlmsghdr *nlh, | 2886 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
2887 | const struct nlattr * const nla[]) | 2887 | const struct nlattr * const nla[]) |
2888 | { | 2888 | { |
2889 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2889 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
@@ -2896,15 +2896,13 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, | |||
2896 | if (nla[NFTA_SET_TABLE] == NULL) | 2896 | if (nla[NFTA_SET_TABLE] == NULL) |
2897 | return -EINVAL; | 2897 | return -EINVAL; |
2898 | 2898 | ||
2899 | err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla); | 2899 | err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla); |
2900 | if (err < 0) | 2900 | if (err < 0) |
2901 | return err; | 2901 | return err; |
2902 | 2902 | ||
2903 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); | 2903 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); |
2904 | if (IS_ERR(set)) | 2904 | if (IS_ERR(set)) |
2905 | return PTR_ERR(set); | 2905 | return PTR_ERR(set); |
2906 | if (set->flags & NFT_SET_INACTIVE) | ||
2907 | return -ENOENT; | ||
2908 | if (!list_empty(&set->bindings)) | 2906 | if (!list_empty(&set->bindings)) |
2909 | return -EBUSY; | 2907 | return -EBUSY; |
2910 | 2908 | ||
@@ -3024,16 +3022,14 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + | |||
3024 | [NFTA_SET_ELEM_LIST_SET_ID] = { .type = NLA_U32 }, | 3022 | [NFTA_SET_ELEM_LIST_SET_ID] = { .type = NLA_U32 }, |
3025 | }; | 3023 | }; |
3026 | 3024 | ||
3027 | static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, | 3025 | static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net, |
3028 | const struct sk_buff *skb, | 3026 | const struct sk_buff *skb, |
3029 | const struct nlmsghdr *nlh, | 3027 | const struct nlmsghdr *nlh, |
3030 | const struct nlattr * const nla[], | 3028 | const struct nlattr * const nla[]) |
3031 | bool trans) | ||
3032 | { | 3029 | { |
3033 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 3030 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
3034 | struct nft_af_info *afi; | 3031 | struct nft_af_info *afi; |
3035 | struct nft_table *table; | 3032 | struct nft_table *table; |
3036 | struct net *net = sock_net(skb->sk); | ||
3037 | 3033 | ||
3038 | afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); | 3034 | afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); |
3039 | if (IS_ERR(afi)) | 3035 | if (IS_ERR(afi)) |
@@ -3042,10 +3038,8 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, | |||
3042 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE]); | 3038 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE]); |
3043 | if (IS_ERR(table)) | 3039 | if (IS_ERR(table)) |
3044 | return PTR_ERR(table); | 3040 | return PTR_ERR(table); |
3045 | if (!trans && (table->flags & NFT_TABLE_INACTIVE)) | ||
3046 | return -ENOENT; | ||
3047 | 3041 | ||
3048 | nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla); | 3042 | nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); |
3049 | return 0; | 3043 | return 0; |
3050 | } | 3044 | } |
3051 | 3045 | ||
@@ -3135,6 +3129,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx, | |||
3135 | 3129 | ||
3136 | static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) | 3130 | static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) |
3137 | { | 3131 | { |
3132 | struct net *net = sock_net(skb->sk); | ||
3138 | const struct nft_set *set; | 3133 | const struct nft_set *set; |
3139 | struct nft_set_dump_args args; | 3134 | struct nft_set_dump_args args; |
3140 | struct nft_ctx ctx; | 3135 | struct nft_ctx ctx; |
@@ -3150,10 +3145,12 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) | |||
3150 | if (err < 0) | 3145 | if (err < 0) |
3151 | return err; | 3146 | return err; |
3152 | 3147 | ||
3153 | err = nft_ctx_init_from_elemattr(&ctx, cb->skb, cb->nlh, (void *)nla, | 3148 | err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh, |
3154 | false); | 3149 | (void *)nla); |
3155 | if (err < 0) | 3150 | if (err < 0) |
3156 | return err; | 3151 | return err; |
3152 | if (ctx.table->flags & NFT_TABLE_INACTIVE) | ||
3153 | return -ENOENT; | ||
3157 | 3154 | ||
3158 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]); | 3155 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]); |
3159 | if (IS_ERR(set)) | 3156 | if (IS_ERR(set)) |
@@ -3208,17 +3205,19 @@ nla_put_failure: | |||
3208 | return -ENOSPC; | 3205 | return -ENOSPC; |
3209 | } | 3206 | } |
3210 | 3207 | ||
3211 | static int nf_tables_getsetelem(struct sock *nlsk, struct sk_buff *skb, | 3208 | static int nf_tables_getsetelem(struct net *net, struct sock *nlsk, |
3212 | const struct nlmsghdr *nlh, | 3209 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
3213 | const struct nlattr * const nla[]) | 3210 | const struct nlattr * const nla[]) |
3214 | { | 3211 | { |
3215 | const struct nft_set *set; | 3212 | const struct nft_set *set; |
3216 | struct nft_ctx ctx; | 3213 | struct nft_ctx ctx; |
3217 | int err; | 3214 | int err; |
3218 | 3215 | ||
3219 | err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false); | 3216 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla); |
3220 | if (err < 0) | 3217 | if (err < 0) |
3221 | return err; | 3218 | return err; |
3219 | if (ctx.table->flags & NFT_TABLE_INACTIVE) | ||
3220 | return -ENOENT; | ||
3222 | 3221 | ||
3223 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]); | 3222 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]); |
3224 | if (IS_ERR(set)) | 3223 | if (IS_ERR(set)) |
@@ -3528,11 +3527,10 @@ err1: | |||
3528 | return err; | 3527 | return err; |
3529 | } | 3528 | } |
3530 | 3529 | ||
3531 | static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb, | 3530 | static int nf_tables_newsetelem(struct net *net, struct sock *nlsk, |
3532 | const struct nlmsghdr *nlh, | 3531 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
3533 | const struct nlattr * const nla[]) | 3532 | const struct nlattr * const nla[]) |
3534 | { | 3533 | { |
3535 | struct net *net = sock_net(skb->sk); | ||
3536 | const struct nlattr *attr; | 3534 | const struct nlattr *attr; |
3537 | struct nft_set *set; | 3535 | struct nft_set *set; |
3538 | struct nft_ctx ctx; | 3536 | struct nft_ctx ctx; |
@@ -3541,7 +3539,7 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb, | |||
3541 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) | 3539 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) |
3542 | return -EINVAL; | 3540 | return -EINVAL; |
3543 | 3541 | ||
3544 | err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, true); | 3542 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla); |
3545 | if (err < 0) | 3543 | if (err < 0) |
3546 | return err; | 3544 | return err; |
3547 | 3545 | ||
@@ -3623,8 +3621,8 @@ err1: | |||
3623 | return err; | 3621 | return err; |
3624 | } | 3622 | } |
3625 | 3623 | ||
3626 | static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb, | 3624 | static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, |
3627 | const struct nlmsghdr *nlh, | 3625 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
3628 | const struct nlattr * const nla[]) | 3626 | const struct nlattr * const nla[]) |
3629 | { | 3627 | { |
3630 | const struct nlattr *attr; | 3628 | const struct nlattr *attr; |
@@ -3635,7 +3633,7 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb, | |||
3635 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) | 3633 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) |
3636 | return -EINVAL; | 3634 | return -EINVAL; |
3637 | 3635 | ||
3638 | err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false); | 3636 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla); |
3639 | if (err < 0) | 3637 | if (err < 0) |
3640 | return err; | 3638 | return err; |
3641 | 3639 | ||
@@ -3739,11 +3737,10 @@ err: | |||
3739 | return err; | 3737 | return err; |
3740 | } | 3738 | } |
3741 | 3739 | ||
3742 | static int nf_tables_getgen(struct sock *nlsk, struct sk_buff *skb, | 3740 | static int nf_tables_getgen(struct net *net, struct sock *nlsk, |
3743 | const struct nlmsghdr *nlh, | 3741 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
3744 | const struct nlattr * const nla[]) | 3742 | const struct nlattr * const nla[]) |
3745 | { | 3743 | { |
3746 | struct net *net = sock_net(skb->sk); | ||
3747 | struct sk_buff *skb2; | 3744 | struct sk_buff *skb2; |
3748 | int err; | 3745 | int err; |
3749 | 3746 | ||
@@ -3887,9 +3884,8 @@ static void nf_tables_commit_release(struct nft_trans *trans) | |||
3887 | kfree(trans); | 3884 | kfree(trans); |
3888 | } | 3885 | } |
3889 | 3886 | ||
3890 | static int nf_tables_commit(struct sk_buff *skb) | 3887 | static int nf_tables_commit(struct net *net, struct sk_buff *skb) |
3891 | { | 3888 | { |
3892 | struct net *net = sock_net(skb->sk); | ||
3893 | struct nft_trans *trans, *next; | 3889 | struct nft_trans *trans, *next; |
3894 | struct nft_trans_elem *te; | 3890 | struct nft_trans_elem *te; |
3895 | 3891 | ||
@@ -4024,13 +4020,13 @@ static void nf_tables_abort_release(struct nft_trans *trans) | |||
4024 | kfree(trans); | 4020 | kfree(trans); |
4025 | } | 4021 | } |
4026 | 4022 | ||
4027 | static int nf_tables_abort(struct sk_buff *skb) | 4023 | static int nf_tables_abort(struct net *net, struct sk_buff *skb) |
4028 | { | 4024 | { |
4029 | struct net *net = sock_net(skb->sk); | ||
4030 | struct nft_trans *trans, *next; | 4025 | struct nft_trans *trans, *next; |
4031 | struct nft_trans_elem *te; | 4026 | struct nft_trans_elem *te; |
4032 | 4027 | ||
4033 | list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { | 4028 | list_for_each_entry_safe_reverse(trans, next, &net->nft.commit_list, |
4029 | list) { | ||
4034 | switch (trans->msg_type) { | 4030 | switch (trans->msg_type) { |
4035 | case NFT_MSG_NEWTABLE: | 4031 | case NFT_MSG_NEWTABLE: |
4036 | if (nft_trans_table_update(trans)) { | 4032 | if (nft_trans_table_update(trans)) { |
@@ -4446,22 +4442,22 @@ static void nft_verdict_uninit(const struct nft_data *data) | |||
4446 | } | 4442 | } |
4447 | } | 4443 | } |
4448 | 4444 | ||
4449 | static int nft_verdict_dump(struct sk_buff *skb, const struct nft_data *data) | 4445 | int nft_verdict_dump(struct sk_buff *skb, int type, const struct nft_verdict *v) |
4450 | { | 4446 | { |
4451 | struct nlattr *nest; | 4447 | struct nlattr *nest; |
4452 | 4448 | ||
4453 | nest = nla_nest_start(skb, NFTA_DATA_VERDICT); | 4449 | nest = nla_nest_start(skb, type); |
4454 | if (!nest) | 4450 | if (!nest) |
4455 | goto nla_put_failure; | 4451 | goto nla_put_failure; |
4456 | 4452 | ||
4457 | if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(data->verdict.code))) | 4453 | if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(v->code))) |
4458 | goto nla_put_failure; | 4454 | goto nla_put_failure; |
4459 | 4455 | ||
4460 | switch (data->verdict.code) { | 4456 | switch (v->code) { |
4461 | case NFT_JUMP: | 4457 | case NFT_JUMP: |
4462 | case NFT_GOTO: | 4458 | case NFT_GOTO: |
4463 | if (nla_put_string(skb, NFTA_VERDICT_CHAIN, | 4459 | if (nla_put_string(skb, NFTA_VERDICT_CHAIN, |
4464 | data->verdict.chain->name)) | 4460 | v->chain->name)) |
4465 | goto nla_put_failure; | 4461 | goto nla_put_failure; |
4466 | } | 4462 | } |
4467 | nla_nest_end(skb, nest); | 4463 | nla_nest_end(skb, nest); |
@@ -4572,7 +4568,7 @@ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, | |||
4572 | err = nft_value_dump(skb, data, len); | 4568 | err = nft_value_dump(skb, data, len); |
4573 | break; | 4569 | break; |
4574 | case NFT_DATA_VERDICT: | 4570 | case NFT_DATA_VERDICT: |
4575 | err = nft_verdict_dump(skb, data); | 4571 | err = nft_verdict_dump(skb, NFTA_DATA_VERDICT, &data->verdict); |
4576 | break; | 4572 | break; |
4577 | default: | 4573 | default: |
4578 | err = -EINVAL; | 4574 | err = -EINVAL; |
@@ -4584,7 +4580,7 @@ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, | |||
4584 | } | 4580 | } |
4585 | EXPORT_SYMBOL_GPL(nft_data_dump); | 4581 | EXPORT_SYMBOL_GPL(nft_data_dump); |
4586 | 4582 | ||
4587 | static int nf_tables_init_net(struct net *net) | 4583 | static int __net_init nf_tables_init_net(struct net *net) |
4588 | { | 4584 | { |
4589 | INIT_LIST_HEAD(&net->nft.af_info); | 4585 | INIT_LIST_HEAD(&net->nft.af_info); |
4590 | INIT_LIST_HEAD(&net->nft.commit_list); | 4586 | INIT_LIST_HEAD(&net->nft.commit_list); |
@@ -4592,6 +4588,67 @@ static int nf_tables_init_net(struct net *net) | |||
4592 | return 0; | 4588 | return 0; |
4593 | } | 4589 | } |
4594 | 4590 | ||
4591 | int __nft_release_basechain(struct nft_ctx *ctx) | ||
4592 | { | ||
4593 | struct nft_rule *rule, *nr; | ||
4594 | |||
4595 | BUG_ON(!(ctx->chain->flags & NFT_BASE_CHAIN)); | ||
4596 | |||
4597 | nf_tables_unregister_hooks(ctx->chain->table, ctx->chain, | ||
4598 | ctx->afi->nops); | ||
4599 | list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { | ||
4600 | list_del(&rule->list); | ||
4601 | ctx->chain->use--; | ||
4602 | nf_tables_rule_destroy(ctx, rule); | ||
4603 | } | ||
4604 | list_del(&ctx->chain->list); | ||
4605 | ctx->table->use--; | ||
4606 | nf_tables_chain_destroy(ctx->chain); | ||
4607 | |||
4608 | return 0; | ||
4609 | } | ||
4610 | EXPORT_SYMBOL_GPL(__nft_release_basechain); | ||
4611 | |||
4612 | /* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */ | ||
4613 | static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) | ||
4614 | { | ||
4615 | struct nft_table *table, *nt; | ||
4616 | struct nft_chain *chain, *nc; | ||
4617 | struct nft_rule *rule, *nr; | ||
4618 | struct nft_set *set, *ns; | ||
4619 | struct nft_ctx ctx = { | ||
4620 | .net = net, | ||
4621 | .afi = afi, | ||
4622 | }; | ||
4623 | |||
4624 | list_for_each_entry_safe(table, nt, &afi->tables, list) { | ||
4625 | list_for_each_entry(chain, &table->chains, list) | ||
4626 | nf_tables_unregister_hooks(table, chain, afi->nops); | ||
4627 | /* No packets are walking on these chains anymore. */ | ||
4628 | ctx.table = table; | ||
4629 | list_for_each_entry(chain, &table->chains, list) { | ||
4630 | ctx.chain = chain; | ||
4631 | list_for_each_entry_safe(rule, nr, &chain->rules, list) { | ||
4632 | list_del(&rule->list); | ||
4633 | chain->use--; | ||
4634 | nf_tables_rule_destroy(&ctx, rule); | ||
4635 | } | ||
4636 | } | ||
4637 | list_for_each_entry_safe(set, ns, &table->sets, list) { | ||
4638 | list_del(&set->list); | ||
4639 | table->use--; | ||
4640 | nft_set_destroy(set); | ||
4641 | } | ||
4642 | list_for_each_entry_safe(chain, nc, &table->chains, list) { | ||
4643 | list_del(&chain->list); | ||
4644 | table->use--; | ||
4645 | nf_tables_chain_destroy(chain); | ||
4646 | } | ||
4647 | list_del(&table->list); | ||
4648 | nf_tables_table_destroy(&ctx); | ||
4649 | } | ||
4650 | } | ||
4651 | |||
4595 | static struct pernet_operations nf_tables_net_ops = { | 4652 | static struct pernet_operations nf_tables_net_ops = { |
4596 | .init = nf_tables_init_net, | 4653 | .init = nf_tables_init_net, |
4597 | }; | 4654 | }; |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index f3695a497408..e9f8dffcc244 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
@@ -16,22 +16,17 @@ | |||
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/netlink.h> | 17 | #include <linux/netlink.h> |
18 | #include <linux/netfilter.h> | 18 | #include <linux/netfilter.h> |
19 | #include <linux/static_key.h> | ||
19 | #include <linux/netfilter/nfnetlink.h> | 20 | #include <linux/netfilter/nfnetlink.h> |
20 | #include <linux/netfilter/nf_tables.h> | 21 | #include <linux/netfilter/nf_tables.h> |
21 | #include <net/netfilter/nf_tables_core.h> | 22 | #include <net/netfilter/nf_tables_core.h> |
22 | #include <net/netfilter/nf_tables.h> | 23 | #include <net/netfilter/nf_tables.h> |
23 | #include <net/netfilter/nf_log.h> | 24 | #include <net/netfilter/nf_log.h> |
24 | 25 | ||
25 | enum nft_trace { | 26 | static const char *const comments[__NFT_TRACETYPE_MAX] = { |
26 | NFT_TRACE_RULE, | 27 | [NFT_TRACETYPE_POLICY] = "policy", |
27 | NFT_TRACE_RETURN, | 28 | [NFT_TRACETYPE_RETURN] = "return", |
28 | NFT_TRACE_POLICY, | 29 | [NFT_TRACETYPE_RULE] = "rule", |
29 | }; | ||
30 | |||
31 | static const char *const comments[] = { | ||
32 | [NFT_TRACE_RULE] = "rule", | ||
33 | [NFT_TRACE_RETURN] = "return", | ||
34 | [NFT_TRACE_POLICY] = "policy", | ||
35 | }; | 30 | }; |
36 | 31 | ||
37 | static struct nf_loginfo trace_loginfo = { | 32 | static struct nf_loginfo trace_loginfo = { |
@@ -44,22 +39,36 @@ static struct nf_loginfo trace_loginfo = { | |||
44 | }, | 39 | }, |
45 | }; | 40 | }; |
46 | 41 | ||
47 | static void __nft_trace_packet(const struct nft_pktinfo *pkt, | 42 | static noinline void __nft_trace_packet(struct nft_traceinfo *info, |
48 | const struct nft_chain *chain, | 43 | const struct nft_chain *chain, |
49 | int rulenum, enum nft_trace type) | 44 | int rulenum, enum nft_trace_types type) |
50 | { | 45 | { |
46 | const struct nft_pktinfo *pkt = info->pkt; | ||
47 | |||
48 | if (!info->trace || !pkt->skb->nf_trace) | ||
49 | return; | ||
50 | |||
51 | info->chain = chain; | ||
52 | info->type = type; | ||
53 | |||
54 | nft_trace_notify(info); | ||
55 | |||
51 | nf_log_trace(pkt->net, pkt->pf, pkt->hook, pkt->skb, pkt->in, | 56 | nf_log_trace(pkt->net, pkt->pf, pkt->hook, pkt->skb, pkt->in, |
52 | pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", | 57 | pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", |
53 | chain->table->name, chain->name, comments[type], | 58 | chain->table->name, chain->name, comments[type], |
54 | rulenum); | 59 | rulenum); |
55 | } | 60 | } |
56 | 61 | ||
57 | static inline void nft_trace_packet(const struct nft_pktinfo *pkt, | 62 | static inline void nft_trace_packet(struct nft_traceinfo *info, |
58 | const struct nft_chain *chain, | 63 | const struct nft_chain *chain, |
59 | int rulenum, enum nft_trace type) | 64 | const struct nft_rule *rule, |
65 | int rulenum, | ||
66 | enum nft_trace_types type) | ||
60 | { | 67 | { |
61 | if (unlikely(pkt->skb->nf_trace)) | 68 | if (static_branch_unlikely(&nft_trace_enabled)) { |
62 | __nft_trace_packet(pkt, chain, rulenum, type); | 69 | info->rule = rule; |
70 | __nft_trace_packet(info, chain, rulenum, type); | ||
71 | } | ||
63 | } | 72 | } |
64 | 73 | ||
65 | static void nft_cmp_fast_eval(const struct nft_expr *expr, | 74 | static void nft_cmp_fast_eval(const struct nft_expr *expr, |
@@ -121,7 +130,11 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) | |||
121 | struct nft_stats *stats; | 130 | struct nft_stats *stats; |
122 | int rulenum; | 131 | int rulenum; |
123 | unsigned int gencursor = nft_genmask_cur(net); | 132 | unsigned int gencursor = nft_genmask_cur(net); |
133 | struct nft_traceinfo info; | ||
124 | 134 | ||
135 | info.trace = false; | ||
136 | if (static_branch_unlikely(&nft_trace_enabled)) | ||
137 | nft_trace_init(&info, pkt, ®s.verdict, basechain); | ||
125 | do_chain: | 138 | do_chain: |
126 | rulenum = 0; | 139 | rulenum = 0; |
127 | rule = list_entry(&chain->rules, struct nft_rule, list); | 140 | rule = list_entry(&chain->rules, struct nft_rule, list); |
@@ -151,7 +164,8 @@ next_rule: | |||
151 | regs.verdict.code = NFT_CONTINUE; | 164 | regs.verdict.code = NFT_CONTINUE; |
152 | continue; | 165 | continue; |
153 | case NFT_CONTINUE: | 166 | case NFT_CONTINUE: |
154 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | 167 | nft_trace_packet(&info, chain, rule, |
168 | rulenum, NFT_TRACETYPE_RULE); | ||
155 | continue; | 169 | continue; |
156 | } | 170 | } |
157 | break; | 171 | break; |
@@ -161,7 +175,8 @@ next_rule: | |||
161 | case NF_ACCEPT: | 175 | case NF_ACCEPT: |
162 | case NF_DROP: | 176 | case NF_DROP: |
163 | case NF_QUEUE: | 177 | case NF_QUEUE: |
164 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | 178 | nft_trace_packet(&info, chain, rule, |
179 | rulenum, NFT_TRACETYPE_RULE); | ||
165 | return regs.verdict.code; | 180 | return regs.verdict.code; |
166 | } | 181 | } |
167 | 182 | ||
@@ -174,7 +189,8 @@ next_rule: | |||
174 | stackptr++; | 189 | stackptr++; |
175 | /* fall through */ | 190 | /* fall through */ |
176 | case NFT_GOTO: | 191 | case NFT_GOTO: |
177 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | 192 | nft_trace_packet(&info, chain, rule, |
193 | rulenum, NFT_TRACETYPE_RULE); | ||
178 | 194 | ||
179 | chain = regs.verdict.chain; | 195 | chain = regs.verdict.chain; |
180 | goto do_chain; | 196 | goto do_chain; |
@@ -182,7 +198,8 @@ next_rule: | |||
182 | rulenum++; | 198 | rulenum++; |
183 | /* fall through */ | 199 | /* fall through */ |
184 | case NFT_RETURN: | 200 | case NFT_RETURN: |
185 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN); | 201 | nft_trace_packet(&info, chain, rule, |
202 | rulenum, NFT_TRACETYPE_RETURN); | ||
186 | break; | 203 | break; |
187 | default: | 204 | default: |
188 | WARN_ON(1); | 205 | WARN_ON(1); |
@@ -196,7 +213,8 @@ next_rule: | |||
196 | goto next_rule; | 213 | goto next_rule; |
197 | } | 214 | } |
198 | 215 | ||
199 | nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY); | 216 | nft_trace_packet(&info, basechain, NULL, -1, |
217 | NFT_TRACETYPE_POLICY); | ||
200 | 218 | ||
201 | rcu_read_lock_bh(); | 219 | rcu_read_lock_bh(); |
202 | stats = this_cpu_ptr(rcu_dereference(nft_base_chain(basechain)->stats)); | 220 | stats = this_cpu_ptr(rcu_dereference(nft_base_chain(basechain)->stats)); |
diff --git a/net/netfilter/nf_tables_inet.c b/net/netfilter/nf_tables_inet.c index 9dd2d216cfc1..6b5f76295d3d 100644 --- a/net/netfilter/nf_tables_inet.c +++ b/net/netfilter/nf_tables_inet.c | |||
@@ -57,7 +57,7 @@ err: | |||
57 | 57 | ||
58 | static void __net_exit nf_tables_inet_exit_net(struct net *net) | 58 | static void __net_exit nf_tables_inet_exit_net(struct net *net) |
59 | { | 59 | { |
60 | nft_unregister_afinfo(net->nft.inet); | 60 | nft_unregister_afinfo(net, net->nft.inet); |
61 | kfree(net->nft.inet); | 61 | kfree(net->nft.inet); |
62 | } | 62 | } |
63 | 63 | ||
diff --git a/net/netfilter/nf_tables_netdev.c b/net/netfilter/nf_tables_netdev.c index 7b9c053ba750..b6605e000801 100644 --- a/net/netfilter/nf_tables_netdev.c +++ b/net/netfilter/nf_tables_netdev.c | |||
@@ -94,7 +94,7 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb, | |||
94 | { | 94 | { |
95 | struct nft_pktinfo pkt; | 95 | struct nft_pktinfo pkt; |
96 | 96 | ||
97 | switch (eth_hdr(skb)->h_proto) { | 97 | switch (skb->protocol) { |
98 | case htons(ETH_P_IP): | 98 | case htons(ETH_P_IP): |
99 | nft_netdev_set_pktinfo_ipv4(&pkt, skb, state); | 99 | nft_netdev_set_pktinfo_ipv4(&pkt, skb, state); |
100 | break; | 100 | break; |
@@ -139,7 +139,7 @@ err: | |||
139 | 139 | ||
140 | static void nf_tables_netdev_exit_net(struct net *net) | 140 | static void nf_tables_netdev_exit_net(struct net *net) |
141 | { | 141 | { |
142 | nft_unregister_afinfo(net->nft.netdev); | 142 | nft_unregister_afinfo(net, net->nft.netdev); |
143 | kfree(net->nft.netdev); | 143 | kfree(net->nft.netdev); |
144 | } | 144 | } |
145 | 145 | ||
@@ -156,35 +156,17 @@ static const struct nf_chain_type nft_filter_chain_netdev = { | |||
156 | .hook_mask = (1 << NF_NETDEV_INGRESS), | 156 | .hook_mask = (1 << NF_NETDEV_INGRESS), |
157 | }; | 157 | }; |
158 | 158 | ||
159 | static void nft_netdev_event(unsigned long event, struct nft_af_info *afi, | 159 | static void nft_netdev_event(unsigned long event, struct net_device *dev, |
160 | struct net_device *dev, struct nft_table *table, | 160 | struct nft_ctx *ctx) |
161 | struct nft_base_chain *basechain) | ||
162 | { | 161 | { |
163 | switch (event) { | 162 | struct nft_base_chain *basechain = nft_base_chain(ctx->chain); |
164 | case NETDEV_REGISTER: | ||
165 | if (strcmp(basechain->dev_name, dev->name) != 0) | ||
166 | return; | ||
167 | 163 | ||
168 | BUG_ON(!(basechain->flags & NFT_BASECHAIN_DISABLED)); | 164 | switch (event) { |
169 | |||
170 | dev_hold(dev); | ||
171 | basechain->ops[0].dev = dev; | ||
172 | basechain->flags &= ~NFT_BASECHAIN_DISABLED; | ||
173 | if (!(table->flags & NFT_TABLE_F_DORMANT)) | ||
174 | nft_register_basechain(basechain, afi->nops); | ||
175 | break; | ||
176 | case NETDEV_UNREGISTER: | 165 | case NETDEV_UNREGISTER: |
177 | if (strcmp(basechain->dev_name, dev->name) != 0) | 166 | if (strcmp(basechain->dev_name, dev->name) != 0) |
178 | return; | 167 | return; |
179 | 168 | ||
180 | BUG_ON(basechain->flags & NFT_BASECHAIN_DISABLED); | 169 | __nft_release_basechain(ctx); |
181 | |||
182 | if (!(table->flags & NFT_TABLE_F_DORMANT)) | ||
183 | nft_unregister_basechain(basechain, afi->nops); | ||
184 | |||
185 | dev_put(basechain->ops[0].dev); | ||
186 | basechain->ops[0].dev = NULL; | ||
187 | basechain->flags |= NFT_BASECHAIN_DISABLED; | ||
188 | break; | 170 | break; |
189 | case NETDEV_CHANGENAME: | 171 | case NETDEV_CHANGENAME: |
190 | if (dev->ifindex != basechain->ops[0].dev->ifindex) | 172 | if (dev->ifindex != basechain->ops[0].dev->ifindex) |
@@ -201,20 +183,29 @@ static int nf_tables_netdev_event(struct notifier_block *this, | |||
201 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 183 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
202 | struct nft_af_info *afi; | 184 | struct nft_af_info *afi; |
203 | struct nft_table *table; | 185 | struct nft_table *table; |
204 | struct nft_chain *chain; | 186 | struct nft_chain *chain, *nr; |
187 | struct nft_ctx ctx = { | ||
188 | .net = dev_net(dev), | ||
189 | }; | ||
190 | |||
191 | if (event != NETDEV_UNREGISTER && | ||
192 | event != NETDEV_CHANGENAME) | ||
193 | return NOTIFY_DONE; | ||
205 | 194 | ||
206 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 195 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
207 | list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { | 196 | list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { |
197 | ctx.afi = afi; | ||
208 | if (afi->family != NFPROTO_NETDEV) | 198 | if (afi->family != NFPROTO_NETDEV) |
209 | continue; | 199 | continue; |
210 | 200 | ||
211 | list_for_each_entry(table, &afi->tables, list) { | 201 | list_for_each_entry(table, &afi->tables, list) { |
212 | list_for_each_entry(chain, &table->chains, list) { | 202 | ctx.table = table; |
203 | list_for_each_entry_safe(chain, nr, &table->chains, list) { | ||
213 | if (!(chain->flags & NFT_BASE_CHAIN)) | 204 | if (!(chain->flags & NFT_BASE_CHAIN)) |
214 | continue; | 205 | continue; |
215 | 206 | ||
216 | nft_netdev_event(event, afi, dev, table, | 207 | ctx.chain = chain; |
217 | nft_base_chain(chain)); | 208 | nft_netdev_event(event, dev, &ctx); |
218 | } | 209 | } |
219 | } | 210 | } |
220 | } | 211 | } |
diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c new file mode 100644 index 000000000000..e9e959f65d91 --- /dev/null +++ b/net/netfilter/nf_tables_trace.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | * (C) 2015 Red Hat GmbH | ||
3 | * Author: Florian Westphal <fw@strlen.de> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/static_key.h> | ||
12 | #include <linux/hash.h> | ||
13 | #include <linux/jhash.h> | ||
14 | #include <linux/if_vlan.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <linux/netlink.h> | ||
18 | #include <linux/netfilter.h> | ||
19 | #include <linux/netfilter/nfnetlink.h> | ||
20 | #include <linux/netfilter/nf_tables.h> | ||
21 | #include <net/netfilter/nf_tables_core.h> | ||
22 | #include <net/netfilter/nf_tables.h> | ||
23 | |||
24 | #define NFT_TRACETYPE_LL_HSIZE 20 | ||
25 | #define NFT_TRACETYPE_NETWORK_HSIZE 40 | ||
26 | #define NFT_TRACETYPE_TRANSPORT_HSIZE 20 | ||
27 | |||
28 | DEFINE_STATIC_KEY_FALSE(nft_trace_enabled); | ||
29 | EXPORT_SYMBOL_GPL(nft_trace_enabled); | ||
30 | |||
31 | static int trace_fill_id(struct sk_buff *nlskb, struct sk_buff *skb) | ||
32 | { | ||
33 | __be32 id; | ||
34 | |||
35 | /* using skb address as ID results in a limited number of | ||
36 | * values (and quick reuse). | ||
37 | * | ||
38 | * So we attempt to use as many skb members that will not | ||
39 | * change while skb is with netfilter. | ||
40 | */ | ||
41 | id = (__be32)jhash_2words(hash32_ptr(skb), skb_get_hash(skb), | ||
42 | skb->skb_iif); | ||
43 | |||
44 | return nla_put_be32(nlskb, NFTA_TRACE_ID, id); | ||
45 | } | ||
46 | |||
47 | static int trace_fill_header(struct sk_buff *nlskb, u16 type, | ||
48 | const struct sk_buff *skb, | ||
49 | int off, unsigned int len) | ||
50 | { | ||
51 | struct nlattr *nla; | ||
52 | |||
53 | if (len == 0) | ||
54 | return 0; | ||
55 | |||
56 | nla = nla_reserve(nlskb, type, len); | ||
57 | if (!nla || skb_copy_bits(skb, off, nla_data(nla), len)) | ||
58 | return -1; | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int nf_trace_fill_ll_header(struct sk_buff *nlskb, | ||
64 | const struct sk_buff *skb) | ||
65 | { | ||
66 | struct vlan_ethhdr veth; | ||
67 | int off; | ||
68 | |||
69 | BUILD_BUG_ON(sizeof(veth) > NFT_TRACETYPE_LL_HSIZE); | ||
70 | |||
71 | off = skb_mac_header(skb) - skb->data; | ||
72 | if (off != -ETH_HLEN) | ||
73 | return -1; | ||
74 | |||
75 | if (skb_copy_bits(skb, off, &veth, ETH_HLEN)) | ||
76 | return -1; | ||
77 | |||
78 | veth.h_vlan_proto = skb->vlan_proto; | ||
79 | veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb)); | ||
80 | veth.h_vlan_encapsulated_proto = skb->protocol; | ||
81 | |||
82 | return nla_put(nlskb, NFTA_TRACE_LL_HEADER, sizeof(veth), &veth); | ||
83 | } | ||
84 | |||
85 | static int nf_trace_fill_dev_info(struct sk_buff *nlskb, | ||
86 | const struct net_device *indev, | ||
87 | const struct net_device *outdev) | ||
88 | { | ||
89 | if (indev) { | ||
90 | if (nla_put_be32(nlskb, NFTA_TRACE_IIF, | ||
91 | htonl(indev->ifindex))) | ||
92 | return -1; | ||
93 | |||
94 | if (nla_put_be16(nlskb, NFTA_TRACE_IIFTYPE, | ||
95 | htons(indev->type))) | ||
96 | return -1; | ||
97 | } | ||
98 | |||
99 | if (outdev) { | ||
100 | if (nla_put_be32(nlskb, NFTA_TRACE_OIF, | ||
101 | htonl(outdev->ifindex))) | ||
102 | return -1; | ||
103 | |||
104 | if (nla_put_be16(nlskb, NFTA_TRACE_OIFTYPE, | ||
105 | htons(outdev->type))) | ||
106 | return -1; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int nf_trace_fill_pkt_info(struct sk_buff *nlskb, | ||
113 | const struct nft_pktinfo *pkt) | ||
114 | { | ||
115 | const struct sk_buff *skb = pkt->skb; | ||
116 | unsigned int len = min_t(unsigned int, | ||
117 | pkt->xt.thoff - skb_network_offset(skb), | ||
118 | NFT_TRACETYPE_NETWORK_HSIZE); | ||
119 | int off = skb_network_offset(skb); | ||
120 | |||
121 | if (trace_fill_header(nlskb, NFTA_TRACE_NETWORK_HEADER, skb, off, len)) | ||
122 | return -1; | ||
123 | |||
124 | len = min_t(unsigned int, skb->len - pkt->xt.thoff, | ||
125 | NFT_TRACETYPE_TRANSPORT_HSIZE); | ||
126 | |||
127 | if (trace_fill_header(nlskb, NFTA_TRACE_TRANSPORT_HEADER, skb, | ||
128 | pkt->xt.thoff, len)) | ||
129 | return -1; | ||
130 | |||
131 | if (!skb_mac_header_was_set(skb)) | ||
132 | return 0; | ||
133 | |||
134 | if (skb_vlan_tag_get(skb)) | ||
135 | return nf_trace_fill_ll_header(nlskb, skb); | ||
136 | |||
137 | off = skb_mac_header(skb) - skb->data; | ||
138 | len = min_t(unsigned int, -off, NFT_TRACETYPE_LL_HSIZE); | ||
139 | return trace_fill_header(nlskb, NFTA_TRACE_LL_HEADER, | ||
140 | skb, off, len); | ||
141 | } | ||
142 | |||
143 | static int nf_trace_fill_rule_info(struct sk_buff *nlskb, | ||
144 | const struct nft_traceinfo *info) | ||
145 | { | ||
146 | if (!info->rule) | ||
147 | return 0; | ||
148 | |||
149 | /* a continue verdict with ->type == RETURN means that this is | ||
150 | * an implicit return (end of chain reached). | ||
151 | * | ||
152 | * Since no rule matched, the ->rule pointer is invalid. | ||
153 | */ | ||
154 | if (info->type == NFT_TRACETYPE_RETURN && | ||
155 | info->verdict->code == NFT_CONTINUE) | ||
156 | return 0; | ||
157 | |||
158 | return nla_put_be64(nlskb, NFTA_TRACE_RULE_HANDLE, | ||
159 | cpu_to_be64(info->rule->handle)); | ||
160 | } | ||
161 | |||
162 | void nft_trace_notify(struct nft_traceinfo *info) | ||
163 | { | ||
164 | const struct nft_pktinfo *pkt = info->pkt; | ||
165 | struct nfgenmsg *nfmsg; | ||
166 | struct nlmsghdr *nlh; | ||
167 | struct sk_buff *skb; | ||
168 | unsigned int size; | ||
169 | int event = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_TRACE; | ||
170 | |||
171 | if (!nfnetlink_has_listeners(pkt->net, NFNLGRP_NFTRACE)) | ||
172 | return; | ||
173 | |||
174 | size = nlmsg_total_size(sizeof(struct nfgenmsg)) + | ||
175 | nla_total_size(NFT_TABLE_MAXNAMELEN) + | ||
176 | nla_total_size(NFT_CHAIN_MAXNAMELEN) + | ||
177 | nla_total_size(sizeof(__be64)) + /* rule handle */ | ||
178 | nla_total_size(sizeof(__be32)) + /* trace type */ | ||
179 | nla_total_size(0) + /* VERDICT, nested */ | ||
180 | nla_total_size(sizeof(u32)) + /* verdict code */ | ||
181 | nla_total_size(NFT_CHAIN_MAXNAMELEN) + /* jump target */ | ||
182 | nla_total_size(sizeof(u32)) + /* id */ | ||
183 | nla_total_size(NFT_TRACETYPE_LL_HSIZE) + | ||
184 | nla_total_size(NFT_TRACETYPE_NETWORK_HSIZE) + | ||
185 | nla_total_size(NFT_TRACETYPE_TRANSPORT_HSIZE) + | ||
186 | nla_total_size(sizeof(u32)) + /* iif */ | ||
187 | nla_total_size(sizeof(__be16)) + /* iiftype */ | ||
188 | nla_total_size(sizeof(u32)) + /* oif */ | ||
189 | nla_total_size(sizeof(__be16)) + /* oiftype */ | ||
190 | nla_total_size(sizeof(u32)) + /* mark */ | ||
191 | nla_total_size(sizeof(u32)) + /* nfproto */ | ||
192 | nla_total_size(sizeof(u32)); /* policy */ | ||
193 | |||
194 | skb = nlmsg_new(size, GFP_ATOMIC); | ||
195 | if (!skb) | ||
196 | return; | ||
197 | |||
198 | nlh = nlmsg_put(skb, 0, 0, event, sizeof(struct nfgenmsg), 0); | ||
199 | if (!nlh) | ||
200 | goto nla_put_failure; | ||
201 | |||
202 | nfmsg = nlmsg_data(nlh); | ||
203 | nfmsg->nfgen_family = info->basechain->type->family; | ||
204 | nfmsg->version = NFNETLINK_V0; | ||
205 | nfmsg->res_id = 0; | ||
206 | |||
207 | if (nla_put_be32(skb, NFTA_TRACE_NFPROTO, htonl(pkt->pf))) | ||
208 | goto nla_put_failure; | ||
209 | |||
210 | if (nla_put_be32(skb, NFTA_TRACE_TYPE, htonl(info->type))) | ||
211 | goto nla_put_failure; | ||
212 | |||
213 | if (trace_fill_id(skb, pkt->skb)) | ||
214 | goto nla_put_failure; | ||
215 | |||
216 | if (info->chain) { | ||
217 | if (nla_put_string(skb, NFTA_TRACE_CHAIN, | ||
218 | info->chain->name)) | ||
219 | goto nla_put_failure; | ||
220 | if (nla_put_string(skb, NFTA_TRACE_TABLE, | ||
221 | info->chain->table->name)) | ||
222 | goto nla_put_failure; | ||
223 | } | ||
224 | |||
225 | if (nf_trace_fill_rule_info(skb, info)) | ||
226 | goto nla_put_failure; | ||
227 | |||
228 | switch (info->type) { | ||
229 | case NFT_TRACETYPE_UNSPEC: | ||
230 | case __NFT_TRACETYPE_MAX: | ||
231 | break; | ||
232 | case NFT_TRACETYPE_RETURN: | ||
233 | case NFT_TRACETYPE_RULE: | ||
234 | if (nft_verdict_dump(skb, NFTA_TRACE_VERDICT, info->verdict)) | ||
235 | goto nla_put_failure; | ||
236 | break; | ||
237 | case NFT_TRACETYPE_POLICY: | ||
238 | if (nla_put_be32(skb, NFTA_TRACE_POLICY, | ||
239 | info->basechain->policy)) | ||
240 | goto nla_put_failure; | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | if (pkt->skb->mark && | ||
245 | nla_put_be32(skb, NFTA_TRACE_MARK, htonl(pkt->skb->mark))) | ||
246 | goto nla_put_failure; | ||
247 | |||
248 | if (!info->packet_dumped) { | ||
249 | if (nf_trace_fill_dev_info(skb, pkt->in, pkt->out)) | ||
250 | goto nla_put_failure; | ||
251 | |||
252 | if (nf_trace_fill_pkt_info(skb, pkt)) | ||
253 | goto nla_put_failure; | ||
254 | info->packet_dumped = true; | ||
255 | } | ||
256 | |||
257 | nlmsg_end(skb, nlh); | ||
258 | nfnetlink_send(skb, pkt->net, 0, NFNLGRP_NFTRACE, 0, GFP_ATOMIC); | ||
259 | return; | ||
260 | |||
261 | nla_put_failure: | ||
262 | WARN_ON_ONCE(1); | ||
263 | kfree_skb(skb); | ||
264 | } | ||
265 | |||
266 | void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, | ||
267 | const struct nft_verdict *verdict, | ||
268 | const struct nft_chain *chain) | ||
269 | { | ||
270 | info->basechain = nft_base_chain(chain); | ||
271 | info->trace = true; | ||
272 | info->packet_dumped = false; | ||
273 | info->pkt = pkt; | ||
274 | info->verdict = verdict; | ||
275 | } | ||
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 46453ab318db..a7ba23353dab 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -33,6 +33,10 @@ MODULE_LICENSE("GPL"); | |||
33 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | 33 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
34 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); | 34 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); |
35 | 35 | ||
36 | #define nfnl_dereference_protected(id) \ | ||
37 | rcu_dereference_protected(table[(id)].subsys, \ | ||
38 | lockdep_nfnl_is_held((id))) | ||
39 | |||
36 | static char __initdata nfversion[] = "0.30"; | 40 | static char __initdata nfversion[] = "0.30"; |
37 | 41 | ||
38 | static struct { | 42 | static struct { |
@@ -49,6 +53,7 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = { | |||
49 | [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP, | 53 | [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP, |
50 | [NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES, | 54 | [NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES, |
51 | [NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT, | 55 | [NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT, |
56 | [NFNLGRP_NFTRACE] = NFNL_SUBSYS_NFTABLES, | ||
52 | }; | 57 | }; |
53 | 58 | ||
54 | void nfnl_lock(__u8 subsys_id) | 59 | void nfnl_lock(__u8 subsys_id) |
@@ -201,19 +206,18 @@ replay: | |||
201 | } | 206 | } |
202 | 207 | ||
203 | if (nc->call_rcu) { | 208 | if (nc->call_rcu) { |
204 | err = nc->call_rcu(net->nfnl, skb, nlh, | 209 | err = nc->call_rcu(net, net->nfnl, skb, nlh, |
205 | (const struct nlattr **)cda); | 210 | (const struct nlattr **)cda); |
206 | rcu_read_unlock(); | 211 | rcu_read_unlock(); |
207 | } else { | 212 | } else { |
208 | rcu_read_unlock(); | 213 | rcu_read_unlock(); |
209 | nfnl_lock(subsys_id); | 214 | nfnl_lock(subsys_id); |
210 | if (rcu_dereference_protected(table[subsys_id].subsys, | 215 | if (nfnl_dereference_protected(subsys_id) != ss || |
211 | lockdep_is_held(&table[subsys_id].mutex)) != ss || | ||
212 | nfnetlink_find_client(type, ss) != nc) | 216 | nfnetlink_find_client(type, ss) != nc) |
213 | err = -EAGAIN; | 217 | err = -EAGAIN; |
214 | else if (nc->call) | 218 | else if (nc->call) |
215 | err = nc->call(net->nfnl, skb, nlh, | 219 | err = nc->call(net, net->nfnl, skb, nlh, |
216 | (const struct nlattr **)cda); | 220 | (const struct nlattr **)cda); |
217 | else | 221 | else |
218 | err = -EINVAL; | 222 | err = -EINVAL; |
219 | nfnl_unlock(subsys_id); | 223 | nfnl_unlock(subsys_id); |
@@ -295,18 +299,14 @@ replay: | |||
295 | if (!skb) | 299 | if (!skb) |
296 | return netlink_ack(oskb, nlh, -ENOMEM); | 300 | return netlink_ack(oskb, nlh, -ENOMEM); |
297 | 301 | ||
298 | skb->sk = oskb->sk; | ||
299 | |||
300 | nfnl_lock(subsys_id); | 302 | nfnl_lock(subsys_id); |
301 | ss = rcu_dereference_protected(table[subsys_id].subsys, | 303 | ss = nfnl_dereference_protected(subsys_id); |
302 | lockdep_is_held(&table[subsys_id].mutex)); | ||
303 | if (!ss) { | 304 | if (!ss) { |
304 | #ifdef CONFIG_MODULES | 305 | #ifdef CONFIG_MODULES |
305 | nfnl_unlock(subsys_id); | 306 | nfnl_unlock(subsys_id); |
306 | request_module("nfnetlink-subsys-%d", subsys_id); | 307 | request_module("nfnetlink-subsys-%d", subsys_id); |
307 | nfnl_lock(subsys_id); | 308 | nfnl_lock(subsys_id); |
308 | ss = rcu_dereference_protected(table[subsys_id].subsys, | 309 | ss = nfnl_dereference_protected(subsys_id); |
309 | lockdep_is_held(&table[subsys_id].mutex)); | ||
310 | if (!ss) | 310 | if (!ss) |
311 | #endif | 311 | #endif |
312 | { | 312 | { |
@@ -381,7 +381,7 @@ replay: | |||
381 | goto ack; | 381 | goto ack; |
382 | 382 | ||
383 | if (nc->call_batch) { | 383 | if (nc->call_batch) { |
384 | err = nc->call_batch(net->nfnl, skb, nlh, | 384 | err = nc->call_batch(net, net->nfnl, skb, nlh, |
385 | (const struct nlattr **)cda); | 385 | (const struct nlattr **)cda); |
386 | } | 386 | } |
387 | 387 | ||
@@ -425,15 +425,15 @@ next: | |||
425 | } | 425 | } |
426 | done: | 426 | done: |
427 | if (status & NFNL_BATCH_REPLAY) { | 427 | if (status & NFNL_BATCH_REPLAY) { |
428 | ss->abort(oskb); | 428 | ss->abort(net, oskb); |
429 | nfnl_err_reset(&err_list); | 429 | nfnl_err_reset(&err_list); |
430 | nfnl_unlock(subsys_id); | 430 | nfnl_unlock(subsys_id); |
431 | kfree_skb(skb); | 431 | kfree_skb(skb); |
432 | goto replay; | 432 | goto replay; |
433 | } else if (status == NFNL_BATCH_DONE) { | 433 | } else if (status == NFNL_BATCH_DONE) { |
434 | ss->commit(oskb); | 434 | ss->commit(net, oskb); |
435 | } else { | 435 | } else { |
436 | ss->abort(oskb); | 436 | ss->abort(net, oskb); |
437 | } | 437 | } |
438 | 438 | ||
439 | nfnl_err_deliver(&err_list, oskb); | 439 | nfnl_err_deliver(&err_list, oskb); |
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index fefbf5f0b28d..5274b04c42a6 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c | |||
@@ -46,12 +46,11 @@ struct nfacct_filter { | |||
46 | #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES) | 46 | #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES) |
47 | #define NFACCT_OVERQUOTA_BIT 2 /* NFACCT_F_OVERQUOTA */ | 47 | #define NFACCT_OVERQUOTA_BIT 2 /* NFACCT_F_OVERQUOTA */ |
48 | 48 | ||
49 | static int | 49 | static int nfnl_acct_new(struct net *net, struct sock *nfnl, |
50 | nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb, | 50 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
51 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | 51 | const struct nlattr * const tb[]) |
52 | { | 52 | { |
53 | struct nf_acct *nfacct, *matching = NULL; | 53 | struct nf_acct *nfacct, *matching = NULL; |
54 | struct net *net = sock_net(nfnl); | ||
55 | char *acct_name; | 54 | char *acct_name; |
56 | unsigned int size = 0; | 55 | unsigned int size = 0; |
57 | u32 flags = 0; | 56 | u32 flags = 0; |
@@ -253,11 +252,10 @@ nfacct_filter_alloc(const struct nlattr * const attr) | |||
253 | return filter; | 252 | return filter; |
254 | } | 253 | } |
255 | 254 | ||
256 | static int | 255 | static int nfnl_acct_get(struct net *net, struct sock *nfnl, |
257 | nfnl_acct_get(struct sock *nfnl, struct sk_buff *skb, | 256 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
258 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | 257 | const struct nlattr * const tb[]) |
259 | { | 258 | { |
260 | struct net *net = sock_net(nfnl); | ||
261 | int ret = -ENOENT; | 259 | int ret = -ENOENT; |
262 | struct nf_acct *cur; | 260 | struct nf_acct *cur; |
263 | char *acct_name; | 261 | char *acct_name; |
@@ -333,11 +331,10 @@ static int nfnl_acct_try_del(struct nf_acct *cur) | |||
333 | return ret; | 331 | return ret; |
334 | } | 332 | } |
335 | 333 | ||
336 | static int | 334 | static int nfnl_acct_del(struct net *net, struct sock *nfnl, |
337 | nfnl_acct_del(struct sock *nfnl, struct sk_buff *skb, | 335 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
338 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | 336 | const struct nlattr * const tb[]) |
339 | { | 337 | { |
340 | struct net *net = sock_net(nfnl); | ||
341 | char *acct_name; | 338 | char *acct_name; |
342 | struct nf_acct *cur; | 339 | struct nf_acct *cur; |
343 | int ret = -ENOENT; | 340 | int ret = -ENOENT; |
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index 54330fb5efaf..e924e95fcc7f 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c | |||
@@ -286,9 +286,9 @@ nfnl_cthelper_update(const struct nlattr * const tb[], | |||
286 | return 0; | 286 | return 0; |
287 | } | 287 | } |
288 | 288 | ||
289 | static int | 289 | static int nfnl_cthelper_new(struct net *net, struct sock *nfnl, |
290 | nfnl_cthelper_new(struct sock *nfnl, struct sk_buff *skb, | 290 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
291 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | 291 | const struct nlattr * const tb[]) |
292 | { | 292 | { |
293 | const char *helper_name; | 293 | const char *helper_name; |
294 | struct nf_conntrack_helper *cur, *helper = NULL; | 294 | struct nf_conntrack_helper *cur, *helper = NULL; |
@@ -498,9 +498,9 @@ out: | |||
498 | return skb->len; | 498 | return skb->len; |
499 | } | 499 | } |
500 | 500 | ||
501 | static int | 501 | static int nfnl_cthelper_get(struct net *net, struct sock *nfnl, |
502 | nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *skb, | 502 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
503 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | 503 | const struct nlattr * const tb[]) |
504 | { | 504 | { |
505 | int ret = -ENOENT, i; | 505 | int ret = -ENOENT, i; |
506 | struct nf_conntrack_helper *cur; | 506 | struct nf_conntrack_helper *cur; |
@@ -570,9 +570,9 @@ nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *skb, | |||
570 | return ret; | 570 | return ret; |
571 | } | 571 | } |
572 | 572 | ||
573 | static int | 573 | static int nfnl_cthelper_del(struct net *net, struct sock *nfnl, |
574 | nfnl_cthelper_del(struct sock *nfnl, struct sk_buff *skb, | 574 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
575 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | 575 | const struct nlattr * const tb[]) |
576 | { | 576 | { |
577 | char *helper_name = NULL; | 577 | char *helper_name = NULL; |
578 | struct nf_conntrack_helper *cur; | 578 | struct nf_conntrack_helper *cur; |
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index c7a2d0e1c462..5d010f27ac01 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c | |||
@@ -38,8 +38,6 @@ MODULE_LICENSE("GPL"); | |||
38 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | 38 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); |
39 | MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning"); | 39 | MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning"); |
40 | 40 | ||
41 | static LIST_HEAD(cttimeout_list); | ||
42 | |||
43 | static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { | 41 | static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { |
44 | [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING, | 42 | [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING, |
45 | .len = CTNL_TIMEOUT_NAME_MAX - 1}, | 43 | .len = CTNL_TIMEOUT_NAME_MAX - 1}, |
@@ -67,16 +65,15 @@ ctnl_timeout_parse_policy(void *timeouts, struct nf_conntrack_l4proto *l4proto, | |||
67 | return ret; | 65 | return ret; |
68 | } | 66 | } |
69 | 67 | ||
70 | static int | 68 | static int cttimeout_new_timeout(struct net *net, struct sock *ctnl, |
71 | cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | 69 | struct sk_buff *skb, |
72 | const struct nlmsghdr *nlh, | 70 | const struct nlmsghdr *nlh, |
73 | const struct nlattr * const cda[]) | 71 | const struct nlattr * const cda[]) |
74 | { | 72 | { |
75 | __u16 l3num; | 73 | __u16 l3num; |
76 | __u8 l4num; | 74 | __u8 l4num; |
77 | struct nf_conntrack_l4proto *l4proto; | 75 | struct nf_conntrack_l4proto *l4proto; |
78 | struct ctnl_timeout *timeout, *matching = NULL; | 76 | struct ctnl_timeout *timeout, *matching = NULL; |
79 | struct net *net = sock_net(skb->sk); | ||
80 | char *name; | 77 | char *name; |
81 | int ret; | 78 | int ret; |
82 | 79 | ||
@@ -90,7 +87,7 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
90 | l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO])); | 87 | l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO])); |
91 | l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); | 88 | l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); |
92 | 89 | ||
93 | list_for_each_entry(timeout, &cttimeout_list, head) { | 90 | list_for_each_entry(timeout, &net->nfct_timeout_list, head) { |
94 | if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) | 91 | if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) |
95 | continue; | 92 | continue; |
96 | 93 | ||
@@ -145,7 +142,7 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
145 | timeout->l3num = l3num; | 142 | timeout->l3num = l3num; |
146 | timeout->l4proto = l4proto; | 143 | timeout->l4proto = l4proto; |
147 | atomic_set(&timeout->refcnt, 1); | 144 | atomic_set(&timeout->refcnt, 1); |
148 | list_add_tail_rcu(&timeout->head, &cttimeout_list); | 145 | list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list); |
149 | 146 | ||
150 | return 0; | 147 | return 0; |
151 | err: | 148 | err: |
@@ -209,6 +206,7 @@ nla_put_failure: | |||
209 | static int | 206 | static int |
210 | ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb) | 207 | ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb) |
211 | { | 208 | { |
209 | struct net *net = sock_net(skb->sk); | ||
212 | struct ctnl_timeout *cur, *last; | 210 | struct ctnl_timeout *cur, *last; |
213 | 211 | ||
214 | if (cb->args[2]) | 212 | if (cb->args[2]) |
@@ -219,7 +217,7 @@ ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
219 | cb->args[1] = 0; | 217 | cb->args[1] = 0; |
220 | 218 | ||
221 | rcu_read_lock(); | 219 | rcu_read_lock(); |
222 | list_for_each_entry_rcu(cur, &cttimeout_list, head) { | 220 | list_for_each_entry_rcu(cur, &net->nfct_timeout_list, head) { |
223 | if (last) { | 221 | if (last) { |
224 | if (cur != last) | 222 | if (cur != last) |
225 | continue; | 223 | continue; |
@@ -240,10 +238,10 @@ ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
240 | return skb->len; | 238 | return skb->len; |
241 | } | 239 | } |
242 | 240 | ||
243 | static int | 241 | static int cttimeout_get_timeout(struct net *net, struct sock *ctnl, |
244 | cttimeout_get_timeout(struct sock *ctnl, struct sk_buff *skb, | 242 | struct sk_buff *skb, |
245 | const struct nlmsghdr *nlh, | 243 | const struct nlmsghdr *nlh, |
246 | const struct nlattr * const cda[]) | 244 | const struct nlattr * const cda[]) |
247 | { | 245 | { |
248 | int ret = -ENOENT; | 246 | int ret = -ENOENT; |
249 | char *name; | 247 | char *name; |
@@ -260,7 +258,7 @@ cttimeout_get_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
260 | return -EINVAL; | 258 | return -EINVAL; |
261 | name = nla_data(cda[CTA_TIMEOUT_NAME]); | 259 | name = nla_data(cda[CTA_TIMEOUT_NAME]); |
262 | 260 | ||
263 | list_for_each_entry(cur, &cttimeout_list, head) { | 261 | list_for_each_entry(cur, &net->nfct_timeout_list, head) { |
264 | struct sk_buff *skb2; | 262 | struct sk_buff *skb2; |
265 | 263 | ||
266 | if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) | 264 | if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) |
@@ -301,17 +299,17 @@ static void untimeout(struct nf_conntrack_tuple_hash *i, | |||
301 | RCU_INIT_POINTER(timeout_ext->timeout, NULL); | 299 | RCU_INIT_POINTER(timeout_ext->timeout, NULL); |
302 | } | 300 | } |
303 | 301 | ||
304 | static void ctnl_untimeout(struct ctnl_timeout *timeout) | 302 | static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout) |
305 | { | 303 | { |
306 | struct nf_conntrack_tuple_hash *h; | 304 | struct nf_conntrack_tuple_hash *h; |
307 | const struct hlist_nulls_node *nn; | 305 | const struct hlist_nulls_node *nn; |
308 | int i; | 306 | int i; |
309 | 307 | ||
310 | local_bh_disable(); | 308 | local_bh_disable(); |
311 | for (i = 0; i < init_net.ct.htable_size; i++) { | 309 | for (i = 0; i < net->ct.htable_size; i++) { |
312 | spin_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); | 310 | spin_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); |
313 | if (i < init_net.ct.htable_size) { | 311 | if (i < net->ct.htable_size) { |
314 | hlist_nulls_for_each_entry(h, nn, &init_net.ct.hash[i], hnnode) | 312 | hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) |
315 | untimeout(h, timeout); | 313 | untimeout(h, timeout); |
316 | } | 314 | } |
317 | spin_unlock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); | 315 | spin_unlock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); |
@@ -320,7 +318,7 @@ static void ctnl_untimeout(struct ctnl_timeout *timeout) | |||
320 | } | 318 | } |
321 | 319 | ||
322 | /* try to delete object, fail if it is still in use. */ | 320 | /* try to delete object, fail if it is still in use. */ |
323 | static int ctnl_timeout_try_del(struct ctnl_timeout *timeout) | 321 | static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout) |
324 | { | 322 | { |
325 | int ret = 0; | 323 | int ret = 0; |
326 | 324 | ||
@@ -329,7 +327,7 @@ static int ctnl_timeout_try_del(struct ctnl_timeout *timeout) | |||
329 | /* We are protected by nfnl mutex. */ | 327 | /* We are protected by nfnl mutex. */ |
330 | list_del_rcu(&timeout->head); | 328 | list_del_rcu(&timeout->head); |
331 | nf_ct_l4proto_put(timeout->l4proto); | 329 | nf_ct_l4proto_put(timeout->l4proto); |
332 | ctnl_untimeout(timeout); | 330 | ctnl_untimeout(net, timeout); |
333 | kfree_rcu(timeout, rcu_head); | 331 | kfree_rcu(timeout, rcu_head); |
334 | } else { | 332 | } else { |
335 | /* still in use, restore reference counter. */ | 333 | /* still in use, restore reference counter. */ |
@@ -339,28 +337,28 @@ static int ctnl_timeout_try_del(struct ctnl_timeout *timeout) | |||
339 | return ret; | 337 | return ret; |
340 | } | 338 | } |
341 | 339 | ||
342 | static int | 340 | static int cttimeout_del_timeout(struct net *net, struct sock *ctnl, |
343 | cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb, | 341 | struct sk_buff *skb, |
344 | const struct nlmsghdr *nlh, | 342 | const struct nlmsghdr *nlh, |
345 | const struct nlattr * const cda[]) | 343 | const struct nlattr * const cda[]) |
346 | { | 344 | { |
347 | char *name; | ||
348 | struct ctnl_timeout *cur; | 345 | struct ctnl_timeout *cur; |
349 | int ret = -ENOENT; | 346 | int ret = -ENOENT; |
347 | char *name; | ||
350 | 348 | ||
351 | if (!cda[CTA_TIMEOUT_NAME]) { | 349 | if (!cda[CTA_TIMEOUT_NAME]) { |
352 | list_for_each_entry(cur, &cttimeout_list, head) | 350 | list_for_each_entry(cur, &net->nfct_timeout_list, head) |
353 | ctnl_timeout_try_del(cur); | 351 | ctnl_timeout_try_del(net, cur); |
354 | 352 | ||
355 | return 0; | 353 | return 0; |
356 | } | 354 | } |
357 | name = nla_data(cda[CTA_TIMEOUT_NAME]); | 355 | name = nla_data(cda[CTA_TIMEOUT_NAME]); |
358 | 356 | ||
359 | list_for_each_entry(cur, &cttimeout_list, head) { | 357 | list_for_each_entry(cur, &net->nfct_timeout_list, head) { |
360 | if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) | 358 | if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) |
361 | continue; | 359 | continue; |
362 | 360 | ||
363 | ret = ctnl_timeout_try_del(cur); | 361 | ret = ctnl_timeout_try_del(net, cur); |
364 | if (ret < 0) | 362 | if (ret < 0) |
365 | return ret; | 363 | return ret; |
366 | 364 | ||
@@ -369,15 +367,14 @@ cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
369 | return ret; | 367 | return ret; |
370 | } | 368 | } |
371 | 369 | ||
372 | static int | 370 | static int cttimeout_default_set(struct net *net, struct sock *ctnl, |
373 | cttimeout_default_set(struct sock *ctnl, struct sk_buff *skb, | 371 | struct sk_buff *skb, |
374 | const struct nlmsghdr *nlh, | 372 | const struct nlmsghdr *nlh, |
375 | const struct nlattr * const cda[]) | 373 | const struct nlattr * const cda[]) |
376 | { | 374 | { |
377 | __u16 l3num; | 375 | __u16 l3num; |
378 | __u8 l4num; | 376 | __u8 l4num; |
379 | struct nf_conntrack_l4proto *l4proto; | 377 | struct nf_conntrack_l4proto *l4proto; |
380 | struct net *net = sock_net(skb->sk); | ||
381 | unsigned int *timeouts; | 378 | unsigned int *timeouts; |
382 | int ret; | 379 | int ret; |
383 | 380 | ||
@@ -459,14 +456,14 @@ nla_put_failure: | |||
459 | return -1; | 456 | return -1; |
460 | } | 457 | } |
461 | 458 | ||
462 | static int cttimeout_default_get(struct sock *ctnl, struct sk_buff *skb, | 459 | static int cttimeout_default_get(struct net *net, struct sock *ctnl, |
460 | struct sk_buff *skb, | ||
463 | const struct nlmsghdr *nlh, | 461 | const struct nlmsghdr *nlh, |
464 | const struct nlattr * const cda[]) | 462 | const struct nlattr * const cda[]) |
465 | { | 463 | { |
466 | __u16 l3num; | 464 | __u16 l3num; |
467 | __u8 l4num; | 465 | __u8 l4num; |
468 | struct nf_conntrack_l4proto *l4proto; | 466 | struct nf_conntrack_l4proto *l4proto; |
469 | struct net *net = sock_net(skb->sk); | ||
470 | struct sk_buff *skb2; | 467 | struct sk_buff *skb2; |
471 | int ret, err; | 468 | int ret, err; |
472 | 469 | ||
@@ -511,12 +508,13 @@ err: | |||
511 | } | 508 | } |
512 | 509 | ||
513 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 510 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
514 | static struct ctnl_timeout *ctnl_timeout_find_get(const char *name) | 511 | static struct ctnl_timeout * |
512 | ctnl_timeout_find_get(struct net *net, const char *name) | ||
515 | { | 513 | { |
516 | struct ctnl_timeout *timeout, *matching = NULL; | 514 | struct ctnl_timeout *timeout, *matching = NULL; |
517 | 515 | ||
518 | rcu_read_lock(); | 516 | rcu_read_lock(); |
519 | list_for_each_entry_rcu(timeout, &cttimeout_list, head) { | 517 | list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) { |
520 | if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) | 518 | if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) |
521 | continue; | 519 | continue; |
522 | 520 | ||
@@ -569,10 +567,39 @@ static const struct nfnetlink_subsystem cttimeout_subsys = { | |||
569 | 567 | ||
570 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT); | 568 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT); |
571 | 569 | ||
570 | static int __net_init cttimeout_net_init(struct net *net) | ||
571 | { | ||
572 | INIT_LIST_HEAD(&net->nfct_timeout_list); | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static void __net_exit cttimeout_net_exit(struct net *net) | ||
578 | { | ||
579 | struct ctnl_timeout *cur, *tmp; | ||
580 | |||
581 | ctnl_untimeout(net, NULL); | ||
582 | |||
583 | list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) { | ||
584 | list_del_rcu(&cur->head); | ||
585 | nf_ct_l4proto_put(cur->l4proto); | ||
586 | kfree_rcu(cur, rcu_head); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | static struct pernet_operations cttimeout_ops = { | ||
591 | .init = cttimeout_net_init, | ||
592 | .exit = cttimeout_net_exit, | ||
593 | }; | ||
594 | |||
572 | static int __init cttimeout_init(void) | 595 | static int __init cttimeout_init(void) |
573 | { | 596 | { |
574 | int ret; | 597 | int ret; |
575 | 598 | ||
599 | ret = register_pernet_subsys(&cttimeout_ops); | ||
600 | if (ret < 0) | ||
601 | return ret; | ||
602 | |||
576 | ret = nfnetlink_subsys_register(&cttimeout_subsys); | 603 | ret = nfnetlink_subsys_register(&cttimeout_subsys); |
577 | if (ret < 0) { | 604 | if (ret < 0) { |
578 | pr_err("cttimeout_init: cannot register cttimeout with " | 605 | pr_err("cttimeout_init: cannot register cttimeout with " |
@@ -586,28 +613,17 @@ static int __init cttimeout_init(void) | |||
586 | return 0; | 613 | return 0; |
587 | 614 | ||
588 | err_out: | 615 | err_out: |
616 | unregister_pernet_subsys(&cttimeout_ops); | ||
589 | return ret; | 617 | return ret; |
590 | } | 618 | } |
591 | 619 | ||
592 | static void __exit cttimeout_exit(void) | 620 | static void __exit cttimeout_exit(void) |
593 | { | 621 | { |
594 | struct ctnl_timeout *cur, *tmp; | ||
595 | |||
596 | pr_info("cttimeout: unregistering from nfnetlink.\n"); | 622 | pr_info("cttimeout: unregistering from nfnetlink.\n"); |
597 | 623 | ||
598 | nfnetlink_subsys_unregister(&cttimeout_subsys); | 624 | nfnetlink_subsys_unregister(&cttimeout_subsys); |
599 | 625 | ||
600 | /* Make sure no conntrack objects refer to custom timeouts anymore. */ | 626 | unregister_pernet_subsys(&cttimeout_ops); |
601 | ctnl_untimeout(NULL); | ||
602 | |||
603 | list_for_each_entry_safe(cur, tmp, &cttimeout_list, head) { | ||
604 | list_del_rcu(&cur->head); | ||
605 | /* We are sure that our objects have no clients at this point, | ||
606 | * it's safe to release them all without checking refcnt. | ||
607 | */ | ||
608 | nf_ct_l4proto_put(cur->l4proto); | ||
609 | kfree_rcu(cur, rcu_head); | ||
610 | } | ||
611 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 627 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
612 | RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); | 628 | RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); |
613 | RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); | 629 | RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 740cce4685ac..8ca932057c13 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -293,24 +293,20 @@ nfulnl_set_nlbufsiz(struct nfulnl_instance *inst, u_int32_t nlbufsiz) | |||
293 | return status; | 293 | return status; |
294 | } | 294 | } |
295 | 295 | ||
296 | static int | 296 | static void |
297 | nfulnl_set_timeout(struct nfulnl_instance *inst, u_int32_t timeout) | 297 | nfulnl_set_timeout(struct nfulnl_instance *inst, u_int32_t timeout) |
298 | { | 298 | { |
299 | spin_lock_bh(&inst->lock); | 299 | spin_lock_bh(&inst->lock); |
300 | inst->flushtimeout = timeout; | 300 | inst->flushtimeout = timeout; |
301 | spin_unlock_bh(&inst->lock); | 301 | spin_unlock_bh(&inst->lock); |
302 | |||
303 | return 0; | ||
304 | } | 302 | } |
305 | 303 | ||
306 | static int | 304 | static void |
307 | nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh) | 305 | nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh) |
308 | { | 306 | { |
309 | spin_lock_bh(&inst->lock); | 307 | spin_lock_bh(&inst->lock); |
310 | inst->qthreshold = qthresh; | 308 | inst->qthreshold = qthresh; |
311 | spin_unlock_bh(&inst->lock); | 309 | spin_unlock_bh(&inst->lock); |
312 | |||
313 | return 0; | ||
314 | } | 310 | } |
315 | 311 | ||
316 | static int | 312 | static int |
@@ -789,10 +785,9 @@ static struct notifier_block nfulnl_rtnl_notifier = { | |||
789 | .notifier_call = nfulnl_rcv_nl_event, | 785 | .notifier_call = nfulnl_rcv_nl_event, |
790 | }; | 786 | }; |
791 | 787 | ||
792 | static int | 788 | static int nfulnl_recv_unsupp(struct net *net, struct sock *ctnl, |
793 | nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, | 789 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
794 | const struct nlmsghdr *nlh, | 790 | const struct nlattr * const nfqa[]) |
795 | const struct nlattr * const nfqa[]) | ||
796 | { | 791 | { |
797 | return -ENOTSUPP; | 792 | return -ENOTSUPP; |
798 | } | 793 | } |
@@ -813,16 +808,14 @@ static const struct nla_policy nfula_cfg_policy[NFULA_CFG_MAX+1] = { | |||
813 | [NFULA_CFG_FLAGS] = { .type = NLA_U16 }, | 808 | [NFULA_CFG_FLAGS] = { .type = NLA_U16 }, |
814 | }; | 809 | }; |
815 | 810 | ||
816 | static int | 811 | static int nfulnl_recv_config(struct net *net, struct sock *ctnl, |
817 | nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | 812 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
818 | const struct nlmsghdr *nlh, | 813 | const struct nlattr * const nfula[]) |
819 | const struct nlattr * const nfula[]) | ||
820 | { | 814 | { |
821 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 815 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
822 | u_int16_t group_num = ntohs(nfmsg->res_id); | 816 | u_int16_t group_num = ntohs(nfmsg->res_id); |
823 | struct nfulnl_instance *inst; | 817 | struct nfulnl_instance *inst; |
824 | struct nfulnl_msg_config_cmd *cmd = NULL; | 818 | struct nfulnl_msg_config_cmd *cmd = NULL; |
825 | struct net *net = sock_net(ctnl); | ||
826 | struct nfnl_log_net *log = nfnl_log_pernet(net); | 819 | struct nfnl_log_net *log = nfnl_log_pernet(net); |
827 | int ret = 0; | 820 | int ret = 0; |
828 | u16 flags = 0; | 821 | u16 flags = 0; |
@@ -895,7 +888,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
895 | goto out_put; | 888 | goto out_put; |
896 | default: | 889 | default: |
897 | ret = -ENOTSUPP; | 890 | ret = -ENOTSUPP; |
898 | break; | 891 | goto out_put; |
899 | } | 892 | } |
900 | } else if (!inst) { | 893 | } else if (!inst) { |
901 | ret = -ENODEV; | 894 | ret = -ENODEV; |
@@ -1064,15 +1057,26 @@ static int __net_init nfnl_log_net_init(struct net *net) | |||
1064 | { | 1057 | { |
1065 | unsigned int i; | 1058 | unsigned int i; |
1066 | struct nfnl_log_net *log = nfnl_log_pernet(net); | 1059 | struct nfnl_log_net *log = nfnl_log_pernet(net); |
1060 | #ifdef CONFIG_PROC_FS | ||
1061 | struct proc_dir_entry *proc; | ||
1062 | kuid_t root_uid; | ||
1063 | kgid_t root_gid; | ||
1064 | #endif | ||
1067 | 1065 | ||
1068 | for (i = 0; i < INSTANCE_BUCKETS; i++) | 1066 | for (i = 0; i < INSTANCE_BUCKETS; i++) |
1069 | INIT_HLIST_HEAD(&log->instance_table[i]); | 1067 | INIT_HLIST_HEAD(&log->instance_table[i]); |
1070 | spin_lock_init(&log->instances_lock); | 1068 | spin_lock_init(&log->instances_lock); |
1071 | 1069 | ||
1072 | #ifdef CONFIG_PROC_FS | 1070 | #ifdef CONFIG_PROC_FS |
1073 | if (!proc_create("nfnetlink_log", 0440, | 1071 | proc = proc_create("nfnetlink_log", 0440, |
1074 | net->nf.proc_netfilter, &nful_file_ops)) | 1072 | net->nf.proc_netfilter, &nful_file_ops); |
1073 | if (!proc) | ||
1075 | return -ENOMEM; | 1074 | return -ENOMEM; |
1075 | |||
1076 | root_uid = make_kuid(net->user_ns, 0); | ||
1077 | root_gid = make_kgid(net->user_ns, 0); | ||
1078 | if (uid_valid(root_uid) && gid_valid(root_gid)) | ||
1079 | proc_set_user(proc, root_uid, root_gid); | ||
1076 | #endif | 1080 | #endif |
1077 | return 0; | 1081 | return 0; |
1078 | } | 1082 | } |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 7d81d280cb4f..1d3936587ace 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -365,8 +365,9 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
365 | break; | 365 | break; |
366 | } | 366 | } |
367 | 367 | ||
368 | nfnl_ct = rcu_dereference(nfnl_ct_hook); | ||
369 | |||
368 | if (queue->flags & NFQA_CFG_F_CONNTRACK) { | 370 | if (queue->flags & NFQA_CFG_F_CONNTRACK) { |
369 | nfnl_ct = rcu_dereference(nfnl_ct_hook); | ||
370 | if (nfnl_ct != NULL) { | 371 | if (nfnl_ct != NULL) { |
371 | ct = nfnl_ct->get_ct(entskb, &ctinfo); | 372 | ct = nfnl_ct->get_ct(entskb, &ctinfo); |
372 | if (ct != NULL) | 373 | if (ct != NULL) |
@@ -956,10 +957,10 @@ static int nfq_id_after(unsigned int id, unsigned int max) | |||
956 | return (int)(id - max) > 0; | 957 | return (int)(id - max) > 0; |
957 | } | 958 | } |
958 | 959 | ||
959 | static int | 960 | static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl, |
960 | nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, | 961 | struct sk_buff *skb, |
961 | const struct nlmsghdr *nlh, | 962 | const struct nlmsghdr *nlh, |
962 | const struct nlattr * const nfqa[]) | 963 | const struct nlattr * const nfqa[]) |
963 | { | 964 | { |
964 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 965 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
965 | struct nf_queue_entry *entry, *tmp; | 966 | struct nf_queue_entry *entry, *tmp; |
@@ -968,8 +969,6 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, | |||
968 | struct nfqnl_instance *queue; | 969 | struct nfqnl_instance *queue; |
969 | LIST_HEAD(batch_list); | 970 | LIST_HEAD(batch_list); |
970 | u16 queue_num = ntohs(nfmsg->res_id); | 971 | u16 queue_num = ntohs(nfmsg->res_id); |
971 | |||
972 | struct net *net = sock_net(ctnl); | ||
973 | struct nfnl_queue_net *q = nfnl_queue_pernet(net); | 972 | struct nfnl_queue_net *q = nfnl_queue_pernet(net); |
974 | 973 | ||
975 | queue = verdict_instance_lookup(q, queue_num, | 974 | queue = verdict_instance_lookup(q, queue_num, |
@@ -1028,14 +1027,13 @@ static struct nf_conn *nfqnl_ct_parse(struct nfnl_ct_hook *nfnl_ct, | |||
1028 | return ct; | 1027 | return ct; |
1029 | } | 1028 | } |
1030 | 1029 | ||
1031 | static int | 1030 | static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl, |
1032 | nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | 1031 | struct sk_buff *skb, |
1033 | const struct nlmsghdr *nlh, | 1032 | const struct nlmsghdr *nlh, |
1034 | const struct nlattr * const nfqa[]) | 1033 | const struct nlattr * const nfqa[]) |
1035 | { | 1034 | { |
1036 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1035 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
1037 | u_int16_t queue_num = ntohs(nfmsg->res_id); | 1036 | u_int16_t queue_num = ntohs(nfmsg->res_id); |
1038 | |||
1039 | struct nfqnl_msg_verdict_hdr *vhdr; | 1037 | struct nfqnl_msg_verdict_hdr *vhdr; |
1040 | struct nfqnl_instance *queue; | 1038 | struct nfqnl_instance *queue; |
1041 | unsigned int verdict; | 1039 | unsigned int verdict; |
@@ -1043,8 +1041,6 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | |||
1043 | enum ip_conntrack_info uninitialized_var(ctinfo); | 1041 | enum ip_conntrack_info uninitialized_var(ctinfo); |
1044 | struct nfnl_ct_hook *nfnl_ct; | 1042 | struct nfnl_ct_hook *nfnl_ct; |
1045 | struct nf_conn *ct = NULL; | 1043 | struct nf_conn *ct = NULL; |
1046 | |||
1047 | struct net *net = sock_net(ctnl); | ||
1048 | struct nfnl_queue_net *q = nfnl_queue_pernet(net); | 1044 | struct nfnl_queue_net *q = nfnl_queue_pernet(net); |
1049 | 1045 | ||
1050 | queue = instance_lookup(q, queue_num); | 1046 | queue = instance_lookup(q, queue_num); |
@@ -1064,9 +1060,10 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | |||
1064 | if (entry == NULL) | 1060 | if (entry == NULL) |
1065 | return -ENOENT; | 1061 | return -ENOENT; |
1066 | 1062 | ||
1063 | /* rcu lock already held from nfnl->call_rcu. */ | ||
1064 | nfnl_ct = rcu_dereference(nfnl_ct_hook); | ||
1065 | |||
1067 | if (nfqa[NFQA_CT]) { | 1066 | if (nfqa[NFQA_CT]) { |
1068 | /* rcu lock already held from nfnl->call_rcu. */ | ||
1069 | nfnl_ct = rcu_dereference(nfnl_ct_hook); | ||
1070 | if (nfnl_ct != NULL) | 1067 | if (nfnl_ct != NULL) |
1071 | ct = nfqnl_ct_parse(nfnl_ct, nlh, nfqa, entry, &ctinfo); | 1068 | ct = nfqnl_ct_parse(nfnl_ct, nlh, nfqa, entry, &ctinfo); |
1072 | } | 1069 | } |
@@ -1090,10 +1087,9 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | |||
1090 | return 0; | 1087 | return 0; |
1091 | } | 1088 | } |
1092 | 1089 | ||
1093 | static int | 1090 | static int nfqnl_recv_unsupp(struct net *net, struct sock *ctnl, |
1094 | nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, | 1091 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1095 | const struct nlmsghdr *nlh, | 1092 | const struct nlattr * const nfqa[]) |
1096 | const struct nlattr * const nfqa[]) | ||
1097 | { | 1093 | { |
1098 | return -ENOTSUPP; | 1094 | return -ENOTSUPP; |
1099 | } | 1095 | } |
@@ -1108,17 +1104,16 @@ static const struct nf_queue_handler nfqh = { | |||
1108 | .nf_hook_drop = &nfqnl_nf_hook_drop, | 1104 | .nf_hook_drop = &nfqnl_nf_hook_drop, |
1109 | }; | 1105 | }; |
1110 | 1106 | ||
1111 | static int | 1107 | static int nfqnl_recv_config(struct net *net, struct sock *ctnl, |
1112 | nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | 1108 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
1113 | const struct nlmsghdr *nlh, | 1109 | const struct nlattr * const nfqa[]) |
1114 | const struct nlattr * const nfqa[]) | ||
1115 | { | 1110 | { |
1116 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1111 | struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
1117 | u_int16_t queue_num = ntohs(nfmsg->res_id); | 1112 | u_int16_t queue_num = ntohs(nfmsg->res_id); |
1118 | struct nfqnl_instance *queue; | 1113 | struct nfqnl_instance *queue; |
1119 | struct nfqnl_msg_config_cmd *cmd = NULL; | 1114 | struct nfqnl_msg_config_cmd *cmd = NULL; |
1120 | struct net *net = sock_net(ctnl); | ||
1121 | struct nfnl_queue_net *q = nfnl_queue_pernet(net); | 1115 | struct nfnl_queue_net *q = nfnl_queue_pernet(net); |
1116 | __u32 flags = 0, mask = 0; | ||
1122 | int ret = 0; | 1117 | int ret = 0; |
1123 | 1118 | ||
1124 | if (nfqa[NFQA_CFG_CMD]) { | 1119 | if (nfqa[NFQA_CFG_CMD]) { |
@@ -1131,6 +1126,40 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
1131 | } | 1126 | } |
1132 | } | 1127 | } |
1133 | 1128 | ||
1129 | /* Check if we support these flags in first place, dependencies should | ||
1130 | * be there too not to break atomicity. | ||
1131 | */ | ||
1132 | if (nfqa[NFQA_CFG_FLAGS]) { | ||
1133 | if (!nfqa[NFQA_CFG_MASK]) { | ||
1134 | /* A mask is needed to specify which flags are being | ||
1135 | * changed. | ||
1136 | */ | ||
1137 | return -EINVAL; | ||
1138 | } | ||
1139 | |||
1140 | flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS])); | ||
1141 | mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK])); | ||
1142 | |||
1143 | if (flags >= NFQA_CFG_F_MAX) | ||
1144 | return -EOPNOTSUPP; | ||
1145 | |||
1146 | #if !IS_ENABLED(CONFIG_NETWORK_SECMARK) | ||
1147 | if (flags & mask & NFQA_CFG_F_SECCTX) | ||
1148 | return -EOPNOTSUPP; | ||
1149 | #endif | ||
1150 | if ((flags & mask & NFQA_CFG_F_CONNTRACK) && | ||
1151 | !rcu_access_pointer(nfnl_ct_hook)) { | ||
1152 | #ifdef CONFIG_MODULES | ||
1153 | nfnl_unlock(NFNL_SUBSYS_QUEUE); | ||
1154 | request_module("ip_conntrack_netlink"); | ||
1155 | nfnl_lock(NFNL_SUBSYS_QUEUE); | ||
1156 | if (rcu_access_pointer(nfnl_ct_hook)) | ||
1157 | return -EAGAIN; | ||
1158 | #endif | ||
1159 | return -EOPNOTSUPP; | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1134 | rcu_read_lock(); | 1163 | rcu_read_lock(); |
1135 | queue = instance_lookup(q, queue_num); | 1164 | queue = instance_lookup(q, queue_num); |
1136 | if (queue && queue->peer_portid != NETLINK_CB(skb).portid) { | 1165 | if (queue && queue->peer_portid != NETLINK_CB(skb).portid) { |
@@ -1158,70 +1187,38 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
1158 | goto err_out_unlock; | 1187 | goto err_out_unlock; |
1159 | } | 1188 | } |
1160 | instance_destroy(q, queue); | 1189 | instance_destroy(q, queue); |
1161 | break; | 1190 | goto err_out_unlock; |
1162 | case NFQNL_CFG_CMD_PF_BIND: | 1191 | case NFQNL_CFG_CMD_PF_BIND: |
1163 | case NFQNL_CFG_CMD_PF_UNBIND: | 1192 | case NFQNL_CFG_CMD_PF_UNBIND: |
1164 | break; | 1193 | break; |
1165 | default: | 1194 | default: |
1166 | ret = -ENOTSUPP; | 1195 | ret = -ENOTSUPP; |
1167 | break; | 1196 | goto err_out_unlock; |
1168 | } | 1197 | } |
1169 | } | 1198 | } |
1170 | 1199 | ||
1200 | if (!queue) { | ||
1201 | ret = -ENODEV; | ||
1202 | goto err_out_unlock; | ||
1203 | } | ||
1204 | |||
1171 | if (nfqa[NFQA_CFG_PARAMS]) { | 1205 | if (nfqa[NFQA_CFG_PARAMS]) { |
1172 | struct nfqnl_msg_config_params *params; | 1206 | struct nfqnl_msg_config_params *params = |
1207 | nla_data(nfqa[NFQA_CFG_PARAMS]); | ||
1173 | 1208 | ||
1174 | if (!queue) { | ||
1175 | ret = -ENODEV; | ||
1176 | goto err_out_unlock; | ||
1177 | } | ||
1178 | params = nla_data(nfqa[NFQA_CFG_PARAMS]); | ||
1179 | nfqnl_set_mode(queue, params->copy_mode, | 1209 | nfqnl_set_mode(queue, params->copy_mode, |
1180 | ntohl(params->copy_range)); | 1210 | ntohl(params->copy_range)); |
1181 | } | 1211 | } |
1182 | 1212 | ||
1183 | if (nfqa[NFQA_CFG_QUEUE_MAXLEN]) { | 1213 | if (nfqa[NFQA_CFG_QUEUE_MAXLEN]) { |
1184 | __be32 *queue_maxlen; | 1214 | __be32 *queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]); |
1185 | 1215 | ||
1186 | if (!queue) { | ||
1187 | ret = -ENODEV; | ||
1188 | goto err_out_unlock; | ||
1189 | } | ||
1190 | queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]); | ||
1191 | spin_lock_bh(&queue->lock); | 1216 | spin_lock_bh(&queue->lock); |
1192 | queue->queue_maxlen = ntohl(*queue_maxlen); | 1217 | queue->queue_maxlen = ntohl(*queue_maxlen); |
1193 | spin_unlock_bh(&queue->lock); | 1218 | spin_unlock_bh(&queue->lock); |
1194 | } | 1219 | } |
1195 | 1220 | ||
1196 | if (nfqa[NFQA_CFG_FLAGS]) { | 1221 | if (nfqa[NFQA_CFG_FLAGS]) { |
1197 | __u32 flags, mask; | ||
1198 | |||
1199 | if (!queue) { | ||
1200 | ret = -ENODEV; | ||
1201 | goto err_out_unlock; | ||
1202 | } | ||
1203 | |||
1204 | if (!nfqa[NFQA_CFG_MASK]) { | ||
1205 | /* A mask is needed to specify which flags are being | ||
1206 | * changed. | ||
1207 | */ | ||
1208 | ret = -EINVAL; | ||
1209 | goto err_out_unlock; | ||
1210 | } | ||
1211 | |||
1212 | flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS])); | ||
1213 | mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK])); | ||
1214 | |||
1215 | if (flags >= NFQA_CFG_F_MAX) { | ||
1216 | ret = -EOPNOTSUPP; | ||
1217 | goto err_out_unlock; | ||
1218 | } | ||
1219 | #if !IS_ENABLED(CONFIG_NETWORK_SECMARK) | ||
1220 | if (flags & mask & NFQA_CFG_F_SECCTX) { | ||
1221 | ret = -EOPNOTSUPP; | ||
1222 | goto err_out_unlock; | ||
1223 | } | ||
1224 | #endif | ||
1225 | spin_lock_bh(&queue->lock); | 1222 | spin_lock_bh(&queue->lock); |
1226 | queue->flags &= ~mask; | 1223 | queue->flags &= ~mask; |
1227 | queue->flags |= flags & mask; | 1224 | queue->flags |= flags & mask; |
@@ -1417,6 +1414,7 @@ static int __init nfnetlink_queue_init(void) | |||
1417 | 1414 | ||
1418 | cleanup_netlink_notifier: | 1415 | cleanup_netlink_notifier: |
1419 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); | 1416 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); |
1417 | unregister_pernet_subsys(&nfnl_queue_net_ops); | ||
1420 | out: | 1418 | out: |
1421 | return status; | 1419 | return status; |
1422 | } | 1420 | } |
diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c index fde5145f2e36..383c17138399 100644 --- a/net/netfilter/nft_byteorder.c +++ b/net/netfilter/nft_byteorder.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | 8 | * Development of this code funded by Astaro AG (http://www.astaro.com/) |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <asm/unaligned.h> | ||
11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
@@ -39,6 +40,27 @@ static void nft_byteorder_eval(const struct nft_expr *expr, | |||
39 | d = (void *)dst; | 40 | d = (void *)dst; |
40 | 41 | ||
41 | switch (priv->size) { | 42 | switch (priv->size) { |
43 | case 8: { | ||
44 | u64 src64; | ||
45 | |||
46 | switch (priv->op) { | ||
47 | case NFT_BYTEORDER_NTOH: | ||
48 | for (i = 0; i < priv->len / 8; i++) { | ||
49 | src64 = get_unaligned_be64(&src[i]); | ||
50 | src64 = be64_to_cpu((__force __be64)src64); | ||
51 | put_unaligned_be64(src64, &dst[i]); | ||
52 | } | ||
53 | break; | ||
54 | case NFT_BYTEORDER_HTON: | ||
55 | for (i = 0; i < priv->len / 8; i++) { | ||
56 | src64 = get_unaligned_be64(&src[i]); | ||
57 | src64 = (__force u64)cpu_to_be64(src64); | ||
58 | put_unaligned_be64(src64, &dst[i]); | ||
59 | } | ||
60 | break; | ||
61 | } | ||
62 | break; | ||
63 | } | ||
42 | case 4: | 64 | case 4: |
43 | switch (priv->op) { | 65 | switch (priv->op) { |
44 | case NFT_BYTEORDER_NTOH: | 66 | case NFT_BYTEORDER_NTOH: |
@@ -101,6 +123,7 @@ static int nft_byteorder_init(const struct nft_ctx *ctx, | |||
101 | switch (priv->size) { | 123 | switch (priv->size) { |
102 | case 2: | 124 | case 2: |
103 | case 4: | 125 | case 4: |
126 | case 8: | ||
104 | break; | 127 | break; |
105 | default: | 128 | default: |
106 | return -EINVAL; | 129 | return -EINVAL; |
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 9c8fab00164b..454841baa4d0 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
@@ -519,9 +519,9 @@ nla_put_failure: | |||
519 | return -1; | 519 | return -1; |
520 | } | 520 | } |
521 | 521 | ||
522 | static int | 522 | static int nfnl_compat_get(struct net *net, struct sock *nfnl, |
523 | nfnl_compat_get(struct sock *nfnl, struct sk_buff *skb, | 523 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
524 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | 524 | const struct nlattr * const tb[]) |
525 | { | 525 | { |
526 | int ret = 0, target; | 526 | int ret = 0, target; |
527 | struct nfgenmsg *nfmsg; | 527 | struct nfgenmsg *nfmsg; |
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 8cbca3432f90..a0eb2161e3ef 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/netfilter/nf_tables.h> | 16 | #include <linux/netfilter/nf_tables.h> |
17 | #include <net/netfilter/nf_tables.h> | 17 | #include <net/netfilter/nf_tables.h> |
18 | #include <net/netfilter/nf_conntrack.h> | 18 | #include <net/netfilter/nf_conntrack.h> |
19 | #include <net/netfilter/nf_conntrack_acct.h> | ||
19 | #include <net/netfilter/nf_conntrack_tuple.h> | 20 | #include <net/netfilter/nf_conntrack_tuple.h> |
20 | #include <net/netfilter/nf_conntrack_helper.h> | 21 | #include <net/netfilter/nf_conntrack_helper.h> |
21 | #include <net/netfilter/nf_conntrack_ecache.h> | 22 | #include <net/netfilter/nf_conntrack_ecache.h> |
@@ -30,6 +31,18 @@ struct nft_ct { | |||
30 | }; | 31 | }; |
31 | }; | 32 | }; |
32 | 33 | ||
34 | static u64 nft_ct_get_eval_counter(const struct nf_conn_counter *c, | ||
35 | enum nft_ct_keys k, | ||
36 | enum ip_conntrack_dir d) | ||
37 | { | ||
38 | if (d < IP_CT_DIR_MAX) | ||
39 | return k == NFT_CT_BYTES ? atomic64_read(&c[d].bytes) : | ||
40 | atomic64_read(&c[d].packets); | ||
41 | |||
42 | return nft_ct_get_eval_counter(c, k, IP_CT_DIR_ORIGINAL) + | ||
43 | nft_ct_get_eval_counter(c, k, IP_CT_DIR_REPLY); | ||
44 | } | ||
45 | |||
33 | static void nft_ct_get_eval(const struct nft_expr *expr, | 46 | static void nft_ct_get_eval(const struct nft_expr *expr, |
34 | struct nft_regs *regs, | 47 | struct nft_regs *regs, |
35 | const struct nft_pktinfo *pkt) | 48 | const struct nft_pktinfo *pkt) |
@@ -114,6 +127,17 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
114 | NF_CT_LABELS_MAX_SIZE - size); | 127 | NF_CT_LABELS_MAX_SIZE - size); |
115 | return; | 128 | return; |
116 | } | 129 | } |
130 | case NFT_CT_BYTES: /* fallthrough */ | ||
131 | case NFT_CT_PKTS: { | ||
132 | const struct nf_conn_acct *acct = nf_conn_acct_find(ct); | ||
133 | u64 count = 0; | ||
134 | |||
135 | if (acct) | ||
136 | count = nft_ct_get_eval_counter(acct->counter, | ||
137 | priv->key, priv->dir); | ||
138 | memcpy(dest, &count, sizeof(count)); | ||
139 | return; | ||
140 | } | ||
117 | #endif | 141 | #endif |
118 | default: | 142 | default: |
119 | break; | 143 | break; |
@@ -291,6 +315,13 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, | |||
291 | return -EINVAL; | 315 | return -EINVAL; |
292 | len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all); | 316 | len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all); |
293 | break; | 317 | break; |
318 | case NFT_CT_BYTES: | ||
319 | case NFT_CT_PKTS: | ||
320 | /* no direction? return sum of original + reply */ | ||
321 | if (tb[NFTA_CT_DIRECTION] == NULL) | ||
322 | priv->dir = IP_CT_DIR_MAX; | ||
323 | len = sizeof(u64); | ||
324 | break; | ||
294 | default: | 325 | default: |
295 | return -EOPNOTSUPP; | 326 | return -EOPNOTSUPP; |
296 | } | 327 | } |
@@ -366,6 +397,7 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
366 | goto nla_put_failure; | 397 | goto nla_put_failure; |
367 | 398 | ||
368 | switch (priv->key) { | 399 | switch (priv->key) { |
400 | case NFT_CT_L3PROTOCOL: | ||
369 | case NFT_CT_PROTOCOL: | 401 | case NFT_CT_PROTOCOL: |
370 | case NFT_CT_SRC: | 402 | case NFT_CT_SRC: |
371 | case NFT_CT_DST: | 403 | case NFT_CT_DST: |
@@ -373,6 +405,13 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
373 | case NFT_CT_PROTO_DST: | 405 | case NFT_CT_PROTO_DST: |
374 | if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) | 406 | if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) |
375 | goto nla_put_failure; | 407 | goto nla_put_failure; |
408 | break; | ||
409 | case NFT_CT_BYTES: | ||
410 | case NFT_CT_PKTS: | ||
411 | if (priv->dir < IP_CT_DIR_MAX && | ||
412 | nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) | ||
413 | goto nla_put_failure; | ||
414 | break; | ||
376 | default: | 415 | default: |
377 | break; | 416 | break; |
378 | } | 417 | } |
diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c new file mode 100644 index 000000000000..2cc1e0ef56e8 --- /dev/null +++ b/net/netfilter/nft_dup_netdev.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Pablo Neira Ayuso <pablo@netfilter.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License version 2 as published by | ||
6 | * the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/netlink.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/netfilter/nf_tables.h> | ||
15 | #include <net/netfilter/nf_tables.h> | ||
16 | #include <net/netfilter/nf_dup_netdev.h> | ||
17 | |||
18 | struct nft_dup_netdev { | ||
19 | enum nft_registers sreg_dev:8; | ||
20 | }; | ||
21 | |||
22 | static void nft_dup_netdev_eval(const struct nft_expr *expr, | ||
23 | struct nft_regs *regs, | ||
24 | const struct nft_pktinfo *pkt) | ||
25 | { | ||
26 | struct nft_dup_netdev *priv = nft_expr_priv(expr); | ||
27 | int oif = regs->data[priv->sreg_dev]; | ||
28 | |||
29 | nf_dup_netdev_egress(pkt, oif); | ||
30 | } | ||
31 | |||
32 | static const struct nla_policy nft_dup_netdev_policy[NFTA_DUP_MAX + 1] = { | ||
33 | [NFTA_DUP_SREG_DEV] = { .type = NLA_U32 }, | ||
34 | }; | ||
35 | |||
36 | static int nft_dup_netdev_init(const struct nft_ctx *ctx, | ||
37 | const struct nft_expr *expr, | ||
38 | const struct nlattr * const tb[]) | ||
39 | { | ||
40 | struct nft_dup_netdev *priv = nft_expr_priv(expr); | ||
41 | |||
42 | if (tb[NFTA_DUP_SREG_DEV] == NULL) | ||
43 | return -EINVAL; | ||
44 | |||
45 | priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]); | ||
46 | return nft_validate_register_load(priv->sreg_dev, sizeof(int)); | ||
47 | } | ||
48 | |||
49 | static const struct nft_expr_ops nft_dup_netdev_ingress_ops; | ||
50 | |||
51 | static int nft_dup_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr) | ||
52 | { | ||
53 | struct nft_dup_netdev *priv = nft_expr_priv(expr); | ||
54 | |||
55 | if (nft_dump_register(skb, NFTA_DUP_SREG_DEV, priv->sreg_dev)) | ||
56 | goto nla_put_failure; | ||
57 | |||
58 | return 0; | ||
59 | |||
60 | nla_put_failure: | ||
61 | return -1; | ||
62 | } | ||
63 | |||
64 | static struct nft_expr_type nft_dup_netdev_type; | ||
65 | static const struct nft_expr_ops nft_dup_netdev_ops = { | ||
66 | .type = &nft_dup_netdev_type, | ||
67 | .size = NFT_EXPR_SIZE(sizeof(struct nft_dup_netdev)), | ||
68 | .eval = nft_dup_netdev_eval, | ||
69 | .init = nft_dup_netdev_init, | ||
70 | .dump = nft_dup_netdev_dump, | ||
71 | }; | ||
72 | |||
73 | static struct nft_expr_type nft_dup_netdev_type __read_mostly = { | ||
74 | .family = NFPROTO_NETDEV, | ||
75 | .name = "dup", | ||
76 | .ops = &nft_dup_netdev_ops, | ||
77 | .policy = nft_dup_netdev_policy, | ||
78 | .maxattr = NFTA_DUP_MAX, | ||
79 | .owner = THIS_MODULE, | ||
80 | }; | ||
81 | |||
82 | static int __init nft_dup_netdev_module_init(void) | ||
83 | { | ||
84 | return nft_register_expr(&nft_dup_netdev_type); | ||
85 | } | ||
86 | |||
87 | static void __exit nft_dup_netdev_module_exit(void) | ||
88 | { | ||
89 | nft_unregister_expr(&nft_dup_netdev_type); | ||
90 | } | ||
91 | |||
92 | module_init(nft_dup_netdev_module_init); | ||
93 | module_exit(nft_dup_netdev_module_exit); | ||
94 | |||
95 | MODULE_LICENSE("GPL"); | ||
96 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
97 | MODULE_ALIAS_NFT_AF_EXPR(5, "dup"); | ||
diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c new file mode 100644 index 000000000000..763ebc3e0b2b --- /dev/null +++ b/net/netfilter/nft_fwd_netdev.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Pablo Neira Ayuso <pablo@netfilter.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License version 2 as published by | ||
6 | * the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/netlink.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/netfilter/nf_tables.h> | ||
15 | #include <net/netfilter/nf_tables.h> | ||
16 | #include <net/netfilter/nf_dup_netdev.h> | ||
17 | |||
18 | struct nft_fwd_netdev { | ||
19 | enum nft_registers sreg_dev:8; | ||
20 | }; | ||
21 | |||
22 | static void nft_fwd_netdev_eval(const struct nft_expr *expr, | ||
23 | struct nft_regs *regs, | ||
24 | const struct nft_pktinfo *pkt) | ||
25 | { | ||
26 | struct nft_fwd_netdev *priv = nft_expr_priv(expr); | ||
27 | int oif = regs->data[priv->sreg_dev]; | ||
28 | |||
29 | nf_dup_netdev_egress(pkt, oif); | ||
30 | regs->verdict.code = NF_DROP; | ||
31 | } | ||
32 | |||
33 | static const struct nla_policy nft_fwd_netdev_policy[NFTA_FWD_MAX + 1] = { | ||
34 | [NFTA_FWD_SREG_DEV] = { .type = NLA_U32 }, | ||
35 | }; | ||
36 | |||
37 | static int nft_fwd_netdev_init(const struct nft_ctx *ctx, | ||
38 | const struct nft_expr *expr, | ||
39 | const struct nlattr * const tb[]) | ||
40 | { | ||
41 | struct nft_fwd_netdev *priv = nft_expr_priv(expr); | ||
42 | |||
43 | if (tb[NFTA_FWD_SREG_DEV] == NULL) | ||
44 | return -EINVAL; | ||
45 | |||
46 | priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]); | ||
47 | return nft_validate_register_load(priv->sreg_dev, sizeof(int)); | ||
48 | } | ||
49 | |||
50 | static const struct nft_expr_ops nft_fwd_netdev_ingress_ops; | ||
51 | |||
52 | static int nft_fwd_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr) | ||
53 | { | ||
54 | struct nft_fwd_netdev *priv = nft_expr_priv(expr); | ||
55 | |||
56 | if (nft_dump_register(skb, NFTA_FWD_SREG_DEV, priv->sreg_dev)) | ||
57 | goto nla_put_failure; | ||
58 | |||
59 | return 0; | ||
60 | |||
61 | nla_put_failure: | ||
62 | return -1; | ||
63 | } | ||
64 | |||
65 | static struct nft_expr_type nft_fwd_netdev_type; | ||
66 | static const struct nft_expr_ops nft_fwd_netdev_ops = { | ||
67 | .type = &nft_fwd_netdev_type, | ||
68 | .size = NFT_EXPR_SIZE(sizeof(struct nft_fwd_netdev)), | ||
69 | .eval = nft_fwd_netdev_eval, | ||
70 | .init = nft_fwd_netdev_init, | ||
71 | .dump = nft_fwd_netdev_dump, | ||
72 | }; | ||
73 | |||
74 | static struct nft_expr_type nft_fwd_netdev_type __read_mostly = { | ||
75 | .family = NFPROTO_NETDEV, | ||
76 | .name = "fwd", | ||
77 | .ops = &nft_fwd_netdev_ops, | ||
78 | .policy = nft_fwd_netdev_policy, | ||
79 | .maxattr = NFTA_FWD_MAX, | ||
80 | .owner = THIS_MODULE, | ||
81 | }; | ||
82 | |||
83 | static int __init nft_fwd_netdev_module_init(void) | ||
84 | { | ||
85 | return nft_register_expr(&nft_fwd_netdev_type); | ||
86 | } | ||
87 | |||
88 | static void __exit nft_fwd_netdev_module_exit(void) | ||
89 | { | ||
90 | nft_unregister_expr(&nft_fwd_netdev_type); | ||
91 | } | ||
92 | |||
93 | module_init(nft_fwd_netdev_module_init); | ||
94 | module_exit(nft_fwd_netdev_module_exit); | ||
95 | |||
96 | MODULE_LICENSE("GPL"); | ||
97 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
98 | MODULE_ALIAS_NFT_AF_EXPR(5, "fwd"); | ||
diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c index 5d67938f8b2f..99d18578afc6 100644 --- a/net/netfilter/nft_limit.c +++ b/net/netfilter/nft_limit.c | |||
@@ -26,6 +26,7 @@ struct nft_limit { | |||
26 | u64 rate; | 26 | u64 rate; |
27 | u64 nsecs; | 27 | u64 nsecs; |
28 | u32 burst; | 28 | u32 burst; |
29 | bool invert; | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost) | 32 | static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost) |
@@ -44,11 +45,11 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost) | |||
44 | if (delta >= 0) { | 45 | if (delta >= 0) { |
45 | limit->tokens = delta; | 46 | limit->tokens = delta; |
46 | spin_unlock_bh(&limit_lock); | 47 | spin_unlock_bh(&limit_lock); |
47 | return false; | 48 | return limit->invert; |
48 | } | 49 | } |
49 | limit->tokens = tokens; | 50 | limit->tokens = tokens; |
50 | spin_unlock_bh(&limit_lock); | 51 | spin_unlock_bh(&limit_lock); |
51 | return true; | 52 | return !limit->invert; |
52 | } | 53 | } |
53 | 54 | ||
54 | static int nft_limit_init(struct nft_limit *limit, | 55 | static int nft_limit_init(struct nft_limit *limit, |
@@ -78,6 +79,12 @@ static int nft_limit_init(struct nft_limit *limit, | |||
78 | 79 | ||
79 | limit->rate = rate; | 80 | limit->rate = rate; |
80 | } | 81 | } |
82 | if (tb[NFTA_LIMIT_FLAGS]) { | ||
83 | u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS])); | ||
84 | |||
85 | if (flags & NFT_LIMIT_F_INV) | ||
86 | limit->invert = true; | ||
87 | } | ||
81 | limit->last = ktime_get_ns(); | 88 | limit->last = ktime_get_ns(); |
82 | 89 | ||
83 | return 0; | 90 | return 0; |
@@ -86,13 +93,15 @@ static int nft_limit_init(struct nft_limit *limit, | |||
86 | static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit, | 93 | static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit, |
87 | enum nft_limit_type type) | 94 | enum nft_limit_type type) |
88 | { | 95 | { |
96 | u32 flags = limit->invert ? NFT_LIMIT_F_INV : 0; | ||
89 | u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC); | 97 | u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC); |
90 | u64 rate = limit->rate - limit->burst; | 98 | u64 rate = limit->rate - limit->burst; |
91 | 99 | ||
92 | if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) || | 100 | if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate)) || |
93 | nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) || | 101 | nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs)) || |
94 | nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(limit->burst)) || | 102 | nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(limit->burst)) || |
95 | nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type))) | 103 | nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type)) || |
104 | nla_put_be32(skb, NFTA_LIMIT_FLAGS, htonl(flags))) | ||
96 | goto nla_put_failure; | 105 | goto nla_put_failure; |
97 | return 0; | 106 | return 0; |
98 | 107 | ||
@@ -120,6 +129,7 @@ static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = { | |||
120 | [NFTA_LIMIT_UNIT] = { .type = NLA_U64 }, | 129 | [NFTA_LIMIT_UNIT] = { .type = NLA_U64 }, |
121 | [NFTA_LIMIT_BURST] = { .type = NLA_U32 }, | 130 | [NFTA_LIMIT_BURST] = { .type = NLA_U32 }, |
122 | [NFTA_LIMIT_TYPE] = { .type = NLA_U32 }, | 131 | [NFTA_LIMIT_TYPE] = { .type = NLA_U32 }, |
132 | [NFTA_LIMIT_FLAGS] = { .type = NLA_U32 }, | ||
123 | }; | 133 | }; |
124 | 134 | ||
125 | static int nft_limit_pkts_init(const struct nft_ctx *ctx, | 135 | static int nft_limit_pkts_init(const struct nft_ctx *ctx, |
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index 9dfaf4d55ee0..fe885bf271c5 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
@@ -18,12 +18,16 @@ | |||
18 | #include <linux/ip.h> | 18 | #include <linux/ip.h> |
19 | #include <linux/ipv6.h> | 19 | #include <linux/ipv6.h> |
20 | #include <linux/smp.h> | 20 | #include <linux/smp.h> |
21 | #include <linux/static_key.h> | ||
21 | #include <net/dst.h> | 22 | #include <net/dst.h> |
22 | #include <net/sock.h> | 23 | #include <net/sock.h> |
23 | #include <net/tcp_states.h> /* for TCP_TIME_WAIT */ | 24 | #include <net/tcp_states.h> /* for TCP_TIME_WAIT */ |
24 | #include <net/netfilter/nf_tables.h> | 25 | #include <net/netfilter/nf_tables.h> |
26 | #include <net/netfilter/nf_tables_core.h> | ||
25 | #include <net/netfilter/nft_meta.h> | 27 | #include <net/netfilter/nft_meta.h> |
26 | 28 | ||
29 | #include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */ | ||
30 | |||
27 | void nft_meta_get_eval(const struct nft_expr *expr, | 31 | void nft_meta_get_eval(const struct nft_expr *expr, |
28 | struct nft_regs *regs, | 32 | struct nft_regs *regs, |
29 | const struct nft_pktinfo *pkt) | 33 | const struct nft_pktinfo *pkt) |
@@ -174,7 +178,7 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
174 | sk = skb_to_full_sk(skb); | 178 | sk = skb_to_full_sk(skb); |
175 | if (!sk || !sk_fullsock(sk)) | 179 | if (!sk || !sk_fullsock(sk)) |
176 | goto err; | 180 | goto err; |
177 | *dest = sk->sk_classid; | 181 | *dest = sock_cgroup_classid(&sk->sk_cgrp_data); |
178 | break; | 182 | break; |
179 | #endif | 183 | #endif |
180 | default: | 184 | default: |
@@ -188,6 +192,13 @@ err: | |||
188 | } | 192 | } |
189 | EXPORT_SYMBOL_GPL(nft_meta_get_eval); | 193 | EXPORT_SYMBOL_GPL(nft_meta_get_eval); |
190 | 194 | ||
195 | /* don't change or set _LOOPBACK, _USER, etc. */ | ||
196 | static bool pkt_type_ok(u32 p) | ||
197 | { | ||
198 | return p == PACKET_HOST || p == PACKET_BROADCAST || | ||
199 | p == PACKET_MULTICAST || p == PACKET_OTHERHOST; | ||
200 | } | ||
201 | |||
191 | void nft_meta_set_eval(const struct nft_expr *expr, | 202 | void nft_meta_set_eval(const struct nft_expr *expr, |
192 | struct nft_regs *regs, | 203 | struct nft_regs *regs, |
193 | const struct nft_pktinfo *pkt) | 204 | const struct nft_pktinfo *pkt) |
@@ -203,6 +214,11 @@ void nft_meta_set_eval(const struct nft_expr *expr, | |||
203 | case NFT_META_PRIORITY: | 214 | case NFT_META_PRIORITY: |
204 | skb->priority = value; | 215 | skb->priority = value; |
205 | break; | 216 | break; |
217 | case NFT_META_PKTTYPE: | ||
218 | if (skb->pkt_type != value && | ||
219 | pkt_type_ok(value) && pkt_type_ok(skb->pkt_type)) | ||
220 | skb->pkt_type = value; | ||
221 | break; | ||
206 | case NFT_META_NFTRACE: | 222 | case NFT_META_NFTRACE: |
207 | skb->nf_trace = 1; | 223 | skb->nf_trace = 1; |
208 | break; | 224 | break; |
@@ -271,6 +287,24 @@ int nft_meta_get_init(const struct nft_ctx *ctx, | |||
271 | } | 287 | } |
272 | EXPORT_SYMBOL_GPL(nft_meta_get_init); | 288 | EXPORT_SYMBOL_GPL(nft_meta_get_init); |
273 | 289 | ||
290 | static int nft_meta_set_init_pkttype(const struct nft_ctx *ctx) | ||
291 | { | ||
292 | unsigned int hooks; | ||
293 | |||
294 | switch (ctx->afi->family) { | ||
295 | case NFPROTO_BRIDGE: | ||
296 | hooks = 1 << NF_BR_PRE_ROUTING; | ||
297 | break; | ||
298 | case NFPROTO_NETDEV: | ||
299 | hooks = 1 << NF_NETDEV_INGRESS; | ||
300 | break; | ||
301 | default: | ||
302 | return -EOPNOTSUPP; | ||
303 | } | ||
304 | |||
305 | return nft_chain_validate_hooks(ctx->chain, hooks); | ||
306 | } | ||
307 | |||
274 | int nft_meta_set_init(const struct nft_ctx *ctx, | 308 | int nft_meta_set_init(const struct nft_ctx *ctx, |
275 | const struct nft_expr *expr, | 309 | const struct nft_expr *expr, |
276 | const struct nlattr * const tb[]) | 310 | const struct nlattr * const tb[]) |
@@ -288,6 +322,12 @@ int nft_meta_set_init(const struct nft_ctx *ctx, | |||
288 | case NFT_META_NFTRACE: | 322 | case NFT_META_NFTRACE: |
289 | len = sizeof(u8); | 323 | len = sizeof(u8); |
290 | break; | 324 | break; |
325 | case NFT_META_PKTTYPE: | ||
326 | err = nft_meta_set_init_pkttype(ctx); | ||
327 | if (err) | ||
328 | return err; | ||
329 | len = sizeof(u8); | ||
330 | break; | ||
291 | default: | 331 | default: |
292 | return -EOPNOTSUPP; | 332 | return -EOPNOTSUPP; |
293 | } | 333 | } |
@@ -297,6 +337,9 @@ int nft_meta_set_init(const struct nft_ctx *ctx, | |||
297 | if (err < 0) | 337 | if (err < 0) |
298 | return err; | 338 | return err; |
299 | 339 | ||
340 | if (priv->key == NFT_META_NFTRACE) | ||
341 | static_branch_inc(&nft_trace_enabled); | ||
342 | |||
300 | return 0; | 343 | return 0; |
301 | } | 344 | } |
302 | EXPORT_SYMBOL_GPL(nft_meta_set_init); | 345 | EXPORT_SYMBOL_GPL(nft_meta_set_init); |
@@ -334,6 +377,16 @@ nla_put_failure: | |||
334 | } | 377 | } |
335 | EXPORT_SYMBOL_GPL(nft_meta_set_dump); | 378 | EXPORT_SYMBOL_GPL(nft_meta_set_dump); |
336 | 379 | ||
380 | void nft_meta_set_destroy(const struct nft_ctx *ctx, | ||
381 | const struct nft_expr *expr) | ||
382 | { | ||
383 | const struct nft_meta *priv = nft_expr_priv(expr); | ||
384 | |||
385 | if (priv->key == NFT_META_NFTRACE) | ||
386 | static_branch_dec(&nft_trace_enabled); | ||
387 | } | ||
388 | EXPORT_SYMBOL_GPL(nft_meta_set_destroy); | ||
389 | |||
337 | static struct nft_expr_type nft_meta_type; | 390 | static struct nft_expr_type nft_meta_type; |
338 | static const struct nft_expr_ops nft_meta_get_ops = { | 391 | static const struct nft_expr_ops nft_meta_get_ops = { |
339 | .type = &nft_meta_type, | 392 | .type = &nft_meta_type, |
@@ -348,6 +401,7 @@ static const struct nft_expr_ops nft_meta_set_ops = { | |||
348 | .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), | 401 | .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), |
349 | .eval = nft_meta_set_eval, | 402 | .eval = nft_meta_set_eval, |
350 | .init = nft_meta_set_init, | 403 | .init = nft_meta_set_init, |
404 | .destroy = nft_meta_set_destroy, | ||
351 | .dump = nft_meta_set_dump, | 405 | .dump = nft_meta_set_dump, |
352 | }; | 406 | }; |
353 | 407 | ||
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 09b4b07eb676..12cd4bf16d17 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c | |||
@@ -107,10 +107,13 @@ err: | |||
107 | } | 107 | } |
108 | 108 | ||
109 | static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { | 109 | static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { |
110 | [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, | 110 | [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, |
111 | [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, | 111 | [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, |
112 | [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 }, | 112 | [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, |
113 | [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, | 113 | [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 }, |
114 | [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, | ||
115 | [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, | ||
116 | [NFTA_PAYLOAD_CSUM_OFFSET] = { .type = NLA_U32 }, | ||
114 | }; | 117 | }; |
115 | 118 | ||
116 | static int nft_payload_init(const struct nft_ctx *ctx, | 119 | static int nft_payload_init(const struct nft_ctx *ctx, |
@@ -160,6 +163,118 @@ const struct nft_expr_ops nft_payload_fast_ops = { | |||
160 | .dump = nft_payload_dump, | 163 | .dump = nft_payload_dump, |
161 | }; | 164 | }; |
162 | 165 | ||
166 | static void nft_payload_set_eval(const struct nft_expr *expr, | ||
167 | struct nft_regs *regs, | ||
168 | const struct nft_pktinfo *pkt) | ||
169 | { | ||
170 | const struct nft_payload_set *priv = nft_expr_priv(expr); | ||
171 | struct sk_buff *skb = pkt->skb; | ||
172 | const u32 *src = ®s->data[priv->sreg]; | ||
173 | int offset, csum_offset; | ||
174 | __wsum fsum, tsum; | ||
175 | __sum16 sum; | ||
176 | |||
177 | switch (priv->base) { | ||
178 | case NFT_PAYLOAD_LL_HEADER: | ||
179 | if (!skb_mac_header_was_set(skb)) | ||
180 | goto err; | ||
181 | offset = skb_mac_header(skb) - skb->data; | ||
182 | break; | ||
183 | case NFT_PAYLOAD_NETWORK_HEADER: | ||
184 | offset = skb_network_offset(skb); | ||
185 | break; | ||
186 | case NFT_PAYLOAD_TRANSPORT_HEADER: | ||
187 | offset = pkt->xt.thoff; | ||
188 | break; | ||
189 | default: | ||
190 | BUG(); | ||
191 | } | ||
192 | |||
193 | csum_offset = offset + priv->csum_offset; | ||
194 | offset += priv->offset; | ||
195 | |||
196 | if (priv->csum_type == NFT_PAYLOAD_CSUM_INET && | ||
197 | (priv->base != NFT_PAYLOAD_TRANSPORT_HEADER || | ||
198 | skb->ip_summed != CHECKSUM_PARTIAL)) { | ||
199 | if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) | ||
200 | goto err; | ||
201 | |||
202 | fsum = skb_checksum(skb, offset, priv->len, 0); | ||
203 | tsum = csum_partial(src, priv->len, 0); | ||
204 | sum = csum_fold(csum_add(csum_sub(~csum_unfold(sum), fsum), | ||
205 | tsum)); | ||
206 | if (sum == 0) | ||
207 | sum = CSUM_MANGLED_0; | ||
208 | |||
209 | if (!skb_make_writable(skb, csum_offset + sizeof(sum)) || | ||
210 | skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) | ||
211 | goto err; | ||
212 | } | ||
213 | |||
214 | if (!skb_make_writable(skb, max(offset + priv->len, 0)) || | ||
215 | skb_store_bits(skb, offset, src, priv->len) < 0) | ||
216 | goto err; | ||
217 | |||
218 | return; | ||
219 | err: | ||
220 | regs->verdict.code = NFT_BREAK; | ||
221 | } | ||
222 | |||
223 | static int nft_payload_set_init(const struct nft_ctx *ctx, | ||
224 | const struct nft_expr *expr, | ||
225 | const struct nlattr * const tb[]) | ||
226 | { | ||
227 | struct nft_payload_set *priv = nft_expr_priv(expr); | ||
228 | |||
229 | priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); | ||
230 | priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); | ||
231 | priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); | ||
232 | priv->sreg = nft_parse_register(tb[NFTA_PAYLOAD_SREG]); | ||
233 | |||
234 | if (tb[NFTA_PAYLOAD_CSUM_TYPE]) | ||
235 | priv->csum_type = | ||
236 | ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE])); | ||
237 | if (tb[NFTA_PAYLOAD_CSUM_OFFSET]) | ||
238 | priv->csum_offset = | ||
239 | ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET])); | ||
240 | |||
241 | switch (priv->csum_type) { | ||
242 | case NFT_PAYLOAD_CSUM_NONE: | ||
243 | case NFT_PAYLOAD_CSUM_INET: | ||
244 | break; | ||
245 | default: | ||
246 | return -EOPNOTSUPP; | ||
247 | } | ||
248 | |||
249 | return nft_validate_register_load(priv->sreg, priv->len); | ||
250 | } | ||
251 | |||
252 | static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr) | ||
253 | { | ||
254 | const struct nft_payload_set *priv = nft_expr_priv(expr); | ||
255 | |||
256 | if (nft_dump_register(skb, NFTA_PAYLOAD_SREG, priv->sreg) || | ||
257 | nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || | ||
258 | nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || | ||
259 | nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) || | ||
260 | nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) || | ||
261 | nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET, | ||
262 | htonl(priv->csum_offset))) | ||
263 | goto nla_put_failure; | ||
264 | return 0; | ||
265 | |||
266 | nla_put_failure: | ||
267 | return -1; | ||
268 | } | ||
269 | |||
270 | static const struct nft_expr_ops nft_payload_set_ops = { | ||
271 | .type = &nft_payload_type, | ||
272 | .size = NFT_EXPR_SIZE(sizeof(struct nft_payload_set)), | ||
273 | .eval = nft_payload_set_eval, | ||
274 | .init = nft_payload_set_init, | ||
275 | .dump = nft_payload_set_dump, | ||
276 | }; | ||
277 | |||
163 | static const struct nft_expr_ops * | 278 | static const struct nft_expr_ops * |
164 | nft_payload_select_ops(const struct nft_ctx *ctx, | 279 | nft_payload_select_ops(const struct nft_ctx *ctx, |
165 | const struct nlattr * const tb[]) | 280 | const struct nlattr * const tb[]) |
@@ -167,8 +282,7 @@ nft_payload_select_ops(const struct nft_ctx *ctx, | |||
167 | enum nft_payload_bases base; | 282 | enum nft_payload_bases base; |
168 | unsigned int offset, len; | 283 | unsigned int offset, len; |
169 | 284 | ||
170 | if (tb[NFTA_PAYLOAD_DREG] == NULL || | 285 | if (tb[NFTA_PAYLOAD_BASE] == NULL || |
171 | tb[NFTA_PAYLOAD_BASE] == NULL || | ||
172 | tb[NFTA_PAYLOAD_OFFSET] == NULL || | 286 | tb[NFTA_PAYLOAD_OFFSET] == NULL || |
173 | tb[NFTA_PAYLOAD_LEN] == NULL) | 287 | tb[NFTA_PAYLOAD_LEN] == NULL) |
174 | return ERR_PTR(-EINVAL); | 288 | return ERR_PTR(-EINVAL); |
@@ -183,6 +297,15 @@ nft_payload_select_ops(const struct nft_ctx *ctx, | |||
183 | return ERR_PTR(-EOPNOTSUPP); | 297 | return ERR_PTR(-EOPNOTSUPP); |
184 | } | 298 | } |
185 | 299 | ||
300 | if (tb[NFTA_PAYLOAD_SREG] != NULL) { | ||
301 | if (tb[NFTA_PAYLOAD_DREG] != NULL) | ||
302 | return ERR_PTR(-EINVAL); | ||
303 | return &nft_payload_set_ops; | ||
304 | } | ||
305 | |||
306 | if (tb[NFTA_PAYLOAD_DREG] == NULL) | ||
307 | return ERR_PTR(-EINVAL); | ||
308 | |||
186 | offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); | 309 | offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); |
187 | len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); | 310 | len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); |
188 | 311 | ||
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index d4aaad747ea9..c8a0b7da5ff4 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/audit.h> | 28 | #include <linux/audit.h> |
29 | #include <linux/user_namespace.h> | ||
29 | #include <net/net_namespace.h> | 30 | #include <net/net_namespace.h> |
30 | 31 | ||
31 | #include <linux/netfilter/x_tables.h> | 32 | #include <linux/netfilter/x_tables.h> |
@@ -1226,6 +1227,8 @@ int xt_proto_init(struct net *net, u_int8_t af) | |||
1226 | #ifdef CONFIG_PROC_FS | 1227 | #ifdef CONFIG_PROC_FS |
1227 | char buf[XT_FUNCTION_MAXNAMELEN]; | 1228 | char buf[XT_FUNCTION_MAXNAMELEN]; |
1228 | struct proc_dir_entry *proc; | 1229 | struct proc_dir_entry *proc; |
1230 | kuid_t root_uid; | ||
1231 | kgid_t root_gid; | ||
1229 | #endif | 1232 | #endif |
1230 | 1233 | ||
1231 | if (af >= ARRAY_SIZE(xt_prefix)) | 1234 | if (af >= ARRAY_SIZE(xt_prefix)) |
@@ -1233,12 +1236,17 @@ int xt_proto_init(struct net *net, u_int8_t af) | |||
1233 | 1236 | ||
1234 | 1237 | ||
1235 | #ifdef CONFIG_PROC_FS | 1238 | #ifdef CONFIG_PROC_FS |
1239 | root_uid = make_kuid(net->user_ns, 0); | ||
1240 | root_gid = make_kgid(net->user_ns, 0); | ||
1241 | |||
1236 | strlcpy(buf, xt_prefix[af], sizeof(buf)); | 1242 | strlcpy(buf, xt_prefix[af], sizeof(buf)); |
1237 | strlcat(buf, FORMAT_TABLES, sizeof(buf)); | 1243 | strlcat(buf, FORMAT_TABLES, sizeof(buf)); |
1238 | proc = proc_create_data(buf, 0440, net->proc_net, &xt_table_ops, | 1244 | proc = proc_create_data(buf, 0440, net->proc_net, &xt_table_ops, |
1239 | (void *)(unsigned long)af); | 1245 | (void *)(unsigned long)af); |
1240 | if (!proc) | 1246 | if (!proc) |
1241 | goto out; | 1247 | goto out; |
1248 | if (uid_valid(root_uid) && gid_valid(root_gid)) | ||
1249 | proc_set_user(proc, root_uid, root_gid); | ||
1242 | 1250 | ||
1243 | strlcpy(buf, xt_prefix[af], sizeof(buf)); | 1251 | strlcpy(buf, xt_prefix[af], sizeof(buf)); |
1244 | strlcat(buf, FORMAT_MATCHES, sizeof(buf)); | 1252 | strlcat(buf, FORMAT_MATCHES, sizeof(buf)); |
@@ -1246,6 +1254,8 @@ int xt_proto_init(struct net *net, u_int8_t af) | |||
1246 | (void *)(unsigned long)af); | 1254 | (void *)(unsigned long)af); |
1247 | if (!proc) | 1255 | if (!proc) |
1248 | goto out_remove_tables; | 1256 | goto out_remove_tables; |
1257 | if (uid_valid(root_uid) && gid_valid(root_gid)) | ||
1258 | proc_set_user(proc, root_uid, root_gid); | ||
1249 | 1259 | ||
1250 | strlcpy(buf, xt_prefix[af], sizeof(buf)); | 1260 | strlcpy(buf, xt_prefix[af], sizeof(buf)); |
1251 | strlcat(buf, FORMAT_TARGETS, sizeof(buf)); | 1261 | strlcat(buf, FORMAT_TARGETS, sizeof(buf)); |
@@ -1253,6 +1263,8 @@ int xt_proto_init(struct net *net, u_int8_t af) | |||
1253 | (void *)(unsigned long)af); | 1263 | (void *)(unsigned long)af); |
1254 | if (!proc) | 1264 | if (!proc) |
1255 | goto out_remove_matches; | 1265 | goto out_remove_matches; |
1266 | if (uid_valid(root_uid) && gid_valid(root_gid)) | ||
1267 | proc_set_user(proc, root_uid, root_gid); | ||
1256 | #endif | 1268 | #endif |
1257 | 1269 | ||
1258 | return 0; | 1270 | return 0; |
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index e7ac07e53b59..6669e68d589e 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -143,7 +143,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | |||
143 | goto out; | 143 | goto out; |
144 | } | 144 | } |
145 | 145 | ||
146 | timeout = timeout_find_get(timeout_name); | 146 | timeout = timeout_find_get(par->net, timeout_name); |
147 | if (timeout == NULL) { | 147 | if (timeout == NULL) { |
148 | ret = -ENOENT; | 148 | ret = -ENOENT; |
149 | pr_info("No such timeout policy \"%s\"\n", timeout_name); | 149 | pr_info("No such timeout policy \"%s\"\n", timeout_name); |
diff --git a/net/netfilter/xt_cgroup.c b/net/netfilter/xt_cgroup.c index a1d126f29463..a086a914865f 100644 --- a/net/netfilter/xt_cgroup.c +++ b/net/netfilter/xt_cgroup.c | |||
@@ -24,9 +24,9 @@ MODULE_DESCRIPTION("Xtables: process control group matching"); | |||
24 | MODULE_ALIAS("ipt_cgroup"); | 24 | MODULE_ALIAS("ipt_cgroup"); |
25 | MODULE_ALIAS("ip6t_cgroup"); | 25 | MODULE_ALIAS("ip6t_cgroup"); |
26 | 26 | ||
27 | static int cgroup_mt_check(const struct xt_mtchk_param *par) | 27 | static int cgroup_mt_check_v0(const struct xt_mtchk_param *par) |
28 | { | 28 | { |
29 | struct xt_cgroup_info *info = par->matchinfo; | 29 | struct xt_cgroup_info_v0 *info = par->matchinfo; |
30 | 30 | ||
31 | if (info->invert & ~1) | 31 | if (info->invert & ~1) |
32 | return -EINVAL; | 32 | return -EINVAL; |
@@ -34,38 +34,110 @@ static int cgroup_mt_check(const struct xt_mtchk_param *par) | |||
34 | return 0; | 34 | return 0; |
35 | } | 35 | } |
36 | 36 | ||
37 | static int cgroup_mt_check_v1(const struct xt_mtchk_param *par) | ||
38 | { | ||
39 | struct xt_cgroup_info_v1 *info = par->matchinfo; | ||
40 | struct cgroup *cgrp; | ||
41 | |||
42 | if ((info->invert_path & ~1) || (info->invert_classid & ~1)) | ||
43 | return -EINVAL; | ||
44 | |||
45 | if (!info->has_path && !info->has_classid) { | ||
46 | pr_info("xt_cgroup: no path or classid specified\n"); | ||
47 | return -EINVAL; | ||
48 | } | ||
49 | |||
50 | if (info->has_path && info->has_classid) { | ||
51 | pr_info("xt_cgroup: both path and classid specified\n"); | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | |||
55 | if (info->has_path) { | ||
56 | cgrp = cgroup_get_from_path(info->path); | ||
57 | if (IS_ERR(cgrp)) { | ||
58 | pr_info("xt_cgroup: invalid path, errno=%ld\n", | ||
59 | PTR_ERR(cgrp)); | ||
60 | return -EINVAL; | ||
61 | } | ||
62 | info->priv = cgrp; | ||
63 | } | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
37 | static bool | 68 | static bool |
38 | cgroup_mt(const struct sk_buff *skb, struct xt_action_param *par) | 69 | cgroup_mt_v0(const struct sk_buff *skb, struct xt_action_param *par) |
39 | { | 70 | { |
40 | const struct xt_cgroup_info *info = par->matchinfo; | 71 | const struct xt_cgroup_info_v0 *info = par->matchinfo; |
41 | 72 | ||
42 | if (skb->sk == NULL || !sk_fullsock(skb->sk)) | 73 | if (skb->sk == NULL || !sk_fullsock(skb->sk)) |
43 | return false; | 74 | return false; |
44 | 75 | ||
45 | return (info->id == skb->sk->sk_classid) ^ info->invert; | 76 | return (info->id == sock_cgroup_classid(&skb->sk->sk_cgrp_data)) ^ |
77 | info->invert; | ||
78 | } | ||
79 | |||
80 | static bool cgroup_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) | ||
81 | { | ||
82 | const struct xt_cgroup_info_v1 *info = par->matchinfo; | ||
83 | struct sock_cgroup_data *skcd = &skb->sk->sk_cgrp_data; | ||
84 | struct cgroup *ancestor = info->priv; | ||
85 | |||
86 | if (!skb->sk || !sk_fullsock(skb->sk)) | ||
87 | return false; | ||
88 | |||
89 | if (ancestor) | ||
90 | return cgroup_is_descendant(sock_cgroup_ptr(skcd), ancestor) ^ | ||
91 | info->invert_path; | ||
92 | else | ||
93 | return (info->classid == sock_cgroup_classid(skcd)) ^ | ||
94 | info->invert_classid; | ||
95 | } | ||
96 | |||
97 | static void cgroup_mt_destroy_v1(const struct xt_mtdtor_param *par) | ||
98 | { | ||
99 | struct xt_cgroup_info_v1 *info = par->matchinfo; | ||
100 | |||
101 | if (info->priv) | ||
102 | cgroup_put(info->priv); | ||
46 | } | 103 | } |
47 | 104 | ||
48 | static struct xt_match cgroup_mt_reg __read_mostly = { | 105 | static struct xt_match cgroup_mt_reg[] __read_mostly = { |
49 | .name = "cgroup", | 106 | { |
50 | .revision = 0, | 107 | .name = "cgroup", |
51 | .family = NFPROTO_UNSPEC, | 108 | .revision = 0, |
52 | .checkentry = cgroup_mt_check, | 109 | .family = NFPROTO_UNSPEC, |
53 | .match = cgroup_mt, | 110 | .checkentry = cgroup_mt_check_v0, |
54 | .matchsize = sizeof(struct xt_cgroup_info), | 111 | .match = cgroup_mt_v0, |
55 | .me = THIS_MODULE, | 112 | .matchsize = sizeof(struct xt_cgroup_info_v0), |
56 | .hooks = (1 << NF_INET_LOCAL_OUT) | | 113 | .me = THIS_MODULE, |
57 | (1 << NF_INET_POST_ROUTING) | | 114 | .hooks = (1 << NF_INET_LOCAL_OUT) | |
58 | (1 << NF_INET_LOCAL_IN), | 115 | (1 << NF_INET_POST_ROUTING) | |
116 | (1 << NF_INET_LOCAL_IN), | ||
117 | }, | ||
118 | { | ||
119 | .name = "cgroup", | ||
120 | .revision = 1, | ||
121 | .family = NFPROTO_UNSPEC, | ||
122 | .checkentry = cgroup_mt_check_v1, | ||
123 | .match = cgroup_mt_v1, | ||
124 | .matchsize = sizeof(struct xt_cgroup_info_v1), | ||
125 | .destroy = cgroup_mt_destroy_v1, | ||
126 | .me = THIS_MODULE, | ||
127 | .hooks = (1 << NF_INET_LOCAL_OUT) | | ||
128 | (1 << NF_INET_POST_ROUTING) | | ||
129 | (1 << NF_INET_LOCAL_IN), | ||
130 | }, | ||
59 | }; | 131 | }; |
60 | 132 | ||
61 | static int __init cgroup_mt_init(void) | 133 | static int __init cgroup_mt_init(void) |
62 | { | 134 | { |
63 | return xt_register_match(&cgroup_mt_reg); | 135 | return xt_register_matches(cgroup_mt_reg, ARRAY_SIZE(cgroup_mt_reg)); |
64 | } | 136 | } |
65 | 137 | ||
66 | static void __exit cgroup_mt_exit(void) | 138 | static void __exit cgroup_mt_exit(void) |
67 | { | 139 | { |
68 | xt_unregister_match(&cgroup_mt_reg); | 140 | xt_unregister_matches(cgroup_mt_reg, ARRAY_SIZE(cgroup_mt_reg)); |
69 | } | 141 | } |
70 | 142 | ||
71 | module_init(cgroup_mt_init); | 143 | module_init(cgroup_mt_init); |
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index df8801e02a32..4e3c3affd285 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c | |||
@@ -61,8 +61,8 @@ static const struct nla_policy xt_osf_policy[OSF_ATTR_MAX + 1] = { | |||
61 | [OSF_ATTR_FINGER] = { .len = sizeof(struct xt_osf_user_finger) }, | 61 | [OSF_ATTR_FINGER] = { .len = sizeof(struct xt_osf_user_finger) }, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb, | 64 | static int xt_osf_add_callback(struct net *net, struct sock *ctnl, |
65 | const struct nlmsghdr *nlh, | 65 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
66 | const struct nlattr * const osf_attrs[]) | 66 | const struct nlattr * const osf_attrs[]) |
67 | { | 67 | { |
68 | struct xt_osf_user_finger *f; | 68 | struct xt_osf_user_finger *f; |
@@ -104,7 +104,8 @@ static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb, | |||
104 | return err; | 104 | return err; |
105 | } | 105 | } |
106 | 106 | ||
107 | static int xt_osf_remove_callback(struct sock *ctnl, struct sk_buff *skb, | 107 | static int xt_osf_remove_callback(struct net *net, struct sock *ctnl, |
108 | struct sk_buff *skb, | ||
108 | const struct nlmsghdr *nlh, | 109 | const struct nlmsghdr *nlh, |
109 | const struct nlattr * const osf_attrs[]) | 110 | const struct nlattr * const osf_attrs[]) |
110 | { | 111 | { |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 59651af8cc27..81dc1bb6e016 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -2915,6 +2915,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
2915 | 2915 | ||
2916 | cb = &nlk->cb; | 2916 | cb = &nlk->cb; |
2917 | memset(cb, 0, sizeof(*cb)); | 2917 | memset(cb, 0, sizeof(*cb)); |
2918 | cb->start = control->start; | ||
2918 | cb->dump = control->dump; | 2919 | cb->dump = control->dump; |
2919 | cb->done = control->done; | 2920 | cb->done = control->done; |
2920 | cb->nlh = nlh; | 2921 | cb->nlh = nlh; |
@@ -2927,6 +2928,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
2927 | 2928 | ||
2928 | mutex_unlock(nlk->cb_mutex); | 2929 | mutex_unlock(nlk->cb_mutex); |
2929 | 2930 | ||
2931 | if (cb->start) | ||
2932 | cb->start(cb); | ||
2933 | |||
2930 | ret = netlink_dump(sk); | 2934 | ret = netlink_dump(sk); |
2931 | sock_put(sk); | 2935 | sock_put(sk); |
2932 | 2936 | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index bc0e504f33a6..8e63662c6fb0 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -513,6 +513,20 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, | |||
513 | } | 513 | } |
514 | EXPORT_SYMBOL(genlmsg_put); | 514 | EXPORT_SYMBOL(genlmsg_put); |
515 | 515 | ||
516 | static int genl_lock_start(struct netlink_callback *cb) | ||
517 | { | ||
518 | /* our ops are always const - netlink API doesn't propagate that */ | ||
519 | const struct genl_ops *ops = cb->data; | ||
520 | int rc = 0; | ||
521 | |||
522 | if (ops->start) { | ||
523 | genl_lock(); | ||
524 | rc = ops->start(cb); | ||
525 | genl_unlock(); | ||
526 | } | ||
527 | return rc; | ||
528 | } | ||
529 | |||
516 | static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | 530 | static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) |
517 | { | 531 | { |
518 | /* our ops are always const - netlink API doesn't propagate that */ | 532 | /* our ops are always const - netlink API doesn't propagate that */ |
@@ -577,6 +591,7 @@ static int genl_family_rcv_msg(struct genl_family *family, | |||
577 | .module = family->module, | 591 | .module = family->module, |
578 | /* we have const, but the netlink API doesn't */ | 592 | /* we have const, but the netlink API doesn't */ |
579 | .data = (void *)ops, | 593 | .data = (void *)ops, |
594 | .start = genl_lock_start, | ||
580 | .dump = genl_lock_dumpit, | 595 | .dump = genl_lock_dumpit, |
581 | .done = genl_lock_done, | 596 | .done = genl_lock_done, |
582 | }; | 597 | }; |
@@ -588,6 +603,7 @@ static int genl_family_rcv_msg(struct genl_family *family, | |||
588 | } else { | 603 | } else { |
589 | struct netlink_dump_control c = { | 604 | struct netlink_dump_control c = { |
590 | .module = family->module, | 605 | .module = family->module, |
606 | .start = ops->start, | ||
591 | .dump = ops->dumpit, | 607 | .dump = ops->dumpit, |
592 | .done = ops->done, | 608 | .done = ops->done, |
593 | }; | 609 | }; |
diff --git a/net/nfc/core.c b/net/nfc/core.c index 1fe3d3b362c0..122bb81da918 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -953,6 +953,19 @@ out: | |||
953 | } | 953 | } |
954 | EXPORT_SYMBOL(nfc_se_transaction); | 954 | EXPORT_SYMBOL(nfc_se_transaction); |
955 | 955 | ||
956 | int nfc_se_connectivity(struct nfc_dev *dev, u8 se_idx) | ||
957 | { | ||
958 | int rc; | ||
959 | |||
960 | pr_debug("connectivity: %x\n", se_idx); | ||
961 | |||
962 | device_lock(&dev->dev); | ||
963 | rc = nfc_genl_se_connectivity(dev, se_idx); | ||
964 | device_unlock(&dev->dev); | ||
965 | return rc; | ||
966 | } | ||
967 | EXPORT_SYMBOL(nfc_se_connectivity); | ||
968 | |||
956 | static void nfc_release(struct device *d) | 969 | static void nfc_release(struct device *d) |
957 | { | 970 | { |
958 | struct nfc_dev *dev = to_nfc_dev(d); | 971 | struct nfc_dev *dev = to_nfc_dev(d); |
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 23c2a118ac9f..dd9003f38822 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c | |||
@@ -20,7 +20,8 @@ | |||
20 | #include "digital.h" | 20 | #include "digital.h" |
21 | 21 | ||
22 | #define DIGITAL_PROTO_NFCA_RF_TECH \ | 22 | #define DIGITAL_PROTO_NFCA_RF_TECH \ |
23 | (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK) | 23 | (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | \ |
24 | NFC_PROTO_NFC_DEP_MASK | NFC_PROTO_ISO14443_MASK) | ||
24 | 25 | ||
25 | #define DIGITAL_PROTO_NFCB_RF_TECH NFC_PROTO_ISO14443_B_MASK | 26 | #define DIGITAL_PROTO_NFCB_RF_TECH NFC_PROTO_ISO14443_B_MASK |
26 | 27 | ||
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index b7de0da46acd..ecf0a0196f18 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c | |||
@@ -572,7 +572,7 @@ static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, | |||
572 | if (sock_writeable(sk) && sk->sk_state == LLCP_CONNECTED) | 572 | if (sock_writeable(sk) && sk->sk_state == LLCP_CONNECTED) |
573 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | 573 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; |
574 | else | 574 | else |
575 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 575 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
576 | 576 | ||
577 | pr_debug("mask 0x%x\n", mask); | 577 | pr_debug("mask 0x%x\n", mask); |
578 | 578 | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 10c99a578421..fbb7a2b57b44 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -610,14 +610,14 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type, | |||
610 | struct nci_core_conn_create_cmd *cmd; | 610 | struct nci_core_conn_create_cmd *cmd; |
611 | struct core_conn_create_data data; | 611 | struct core_conn_create_data data; |
612 | 612 | ||
613 | if (!number_destination_params) | ||
614 | return -EINVAL; | ||
615 | |||
613 | data.length = params_len + sizeof(struct nci_core_conn_create_cmd); | 616 | data.length = params_len + sizeof(struct nci_core_conn_create_cmd); |
614 | cmd = kzalloc(data.length, GFP_KERNEL); | 617 | cmd = kzalloc(data.length, GFP_KERNEL); |
615 | if (!cmd) | 618 | if (!cmd) |
616 | return -ENOMEM; | 619 | return -ENOMEM; |
617 | 620 | ||
618 | if (!number_destination_params) | ||
619 | return -EINVAL; | ||
620 | |||
621 | cmd->destination_type = destination_type; | 621 | cmd->destination_type = destination_type; |
622 | cmd->number_destination_params = number_destination_params; | 622 | cmd->number_destination_params = number_destination_params; |
623 | memcpy(cmd->params, params, params_len); | 623 | memcpy(cmd->params, params, params_len); |
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c index 2aedac15cb59..a0ab26d535dc 100644 --- a/net/nfc/nci/hci.c +++ b/net/nfc/nci/hci.c | |||
@@ -676,7 +676,7 @@ int nci_hci_connect_gate(struct nci_dev *ndev, | |||
676 | break; | 676 | break; |
677 | default: | 677 | default: |
678 | pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r); | 678 | pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r); |
679 | if (pipe < 0) | 679 | if (pipe == NCI_HCI_INVALID_PIPE) |
680 | return r; | 680 | return r; |
681 | pipe_created = true; | 681 | pipe_created = true; |
682 | break; | 682 | break; |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index f58c1fba1026..ea023b35f1c2 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -552,6 +552,43 @@ free_msg: | |||
552 | return -EMSGSIZE; | 552 | return -EMSGSIZE; |
553 | } | 553 | } |
554 | 554 | ||
555 | int nfc_genl_se_connectivity(struct nfc_dev *dev, u8 se_idx) | ||
556 | { | ||
557 | struct nfc_se *se; | ||
558 | struct sk_buff *msg; | ||
559 | void *hdr; | ||
560 | |||
561 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
562 | if (!msg) | ||
563 | return -ENOMEM; | ||
564 | |||
565 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
566 | NFC_EVENT_SE_CONNECTIVITY); | ||
567 | if (!hdr) | ||
568 | goto free_msg; | ||
569 | |||
570 | se = nfc_find_se(dev, se_idx); | ||
571 | if (!se) | ||
572 | goto free_msg; | ||
573 | |||
574 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || | ||
575 | nla_put_u32(msg, NFC_ATTR_SE_INDEX, se_idx) || | ||
576 | nla_put_u8(msg, NFC_ATTR_SE_TYPE, se->type)) | ||
577 | goto nla_put_failure; | ||
578 | |||
579 | genlmsg_end(msg, hdr); | ||
580 | |||
581 | genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL); | ||
582 | |||
583 | return 0; | ||
584 | |||
585 | nla_put_failure: | ||
586 | genlmsg_cancel(msg, hdr); | ||
587 | free_msg: | ||
588 | nlmsg_free(msg); | ||
589 | return -EMSGSIZE; | ||
590 | } | ||
591 | |||
555 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | 592 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, |
556 | u32 portid, u32 seq, | 593 | u32 portid, u32 seq, |
557 | struct netlink_callback *cb, | 594 | struct netlink_callback *cb, |
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index c20b784ad720..6c6f76b370b1 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -105,6 +105,7 @@ int nfc_genl_se_added(struct nfc_dev *dev, u32 se_idx, u16 type); | |||
105 | int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx); | 105 | int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx); |
106 | int nfc_genl_se_transaction(struct nfc_dev *dev, u8 se_idx, | 106 | int nfc_genl_se_transaction(struct nfc_dev *dev, u8 se_idx, |
107 | struct nfc_evt_transaction *evt_transaction); | 107 | struct nfc_evt_transaction *evt_transaction); |
108 | int nfc_genl_se_connectivity(struct nfc_dev *dev, u8 se_idx); | ||
108 | 109 | ||
109 | struct nfc_dev *nfc_get_device(unsigned int idx); | 110 | struct nfc_dev *nfc_get_device(unsigned int idx); |
110 | 111 | ||
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index c2cc11168fd5..ee6ff8ffc12d 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c | |||
@@ -53,6 +53,8 @@ struct ovs_conntrack_info { | |||
53 | struct md_labels labels; | 53 | struct md_labels labels; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info); | ||
57 | |||
56 | static u16 key_to_nfproto(const struct sw_flow_key *key) | 58 | static u16 key_to_nfproto(const struct sw_flow_key *key) |
57 | { | 59 | { |
58 | switch (ntohs(key->eth.type)) { | 60 | switch (ntohs(key->eth.type)) { |
@@ -141,6 +143,7 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state, | |||
141 | * previously sent the packet to conntrack via the ct action. | 143 | * previously sent the packet to conntrack via the ct action. |
142 | */ | 144 | */ |
143 | static void ovs_ct_update_key(const struct sk_buff *skb, | 145 | static void ovs_ct_update_key(const struct sk_buff *skb, |
146 | const struct ovs_conntrack_info *info, | ||
144 | struct sw_flow_key *key, bool post_ct) | 147 | struct sw_flow_key *key, bool post_ct) |
145 | { | 148 | { |
146 | const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt; | 149 | const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt; |
@@ -158,13 +161,15 @@ static void ovs_ct_update_key(const struct sk_buff *skb, | |||
158 | zone = nf_ct_zone(ct); | 161 | zone = nf_ct_zone(ct); |
159 | } else if (post_ct) { | 162 | } else if (post_ct) { |
160 | state = OVS_CS_F_TRACKED | OVS_CS_F_INVALID; | 163 | state = OVS_CS_F_TRACKED | OVS_CS_F_INVALID; |
164 | if (info) | ||
165 | zone = &info->zone; | ||
161 | } | 166 | } |
162 | __ovs_ct_update_key(key, state, zone, ct); | 167 | __ovs_ct_update_key(key, state, zone, ct); |
163 | } | 168 | } |
164 | 169 | ||
165 | void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key) | 170 | void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key) |
166 | { | 171 | { |
167 | ovs_ct_update_key(skb, key, false); | 172 | ovs_ct_update_key(skb, NULL, key, false); |
168 | } | 173 | } |
169 | 174 | ||
170 | int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb) | 175 | int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb) |
@@ -300,10 +305,10 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key, | |||
300 | u16 zone, struct sk_buff *skb) | 305 | u16 zone, struct sk_buff *skb) |
301 | { | 306 | { |
302 | struct ovs_skb_cb ovs_cb = *OVS_CB(skb); | 307 | struct ovs_skb_cb ovs_cb = *OVS_CB(skb); |
308 | int err; | ||
303 | 309 | ||
304 | if (key->eth.type == htons(ETH_P_IP)) { | 310 | if (key->eth.type == htons(ETH_P_IP)) { |
305 | enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone; | 311 | enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone; |
306 | int err; | ||
307 | 312 | ||
308 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | 313 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
309 | err = ip_defrag(net, skb, user); | 314 | err = ip_defrag(net, skb, user); |
@@ -314,28 +319,13 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key, | |||
314 | #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) | 319 | #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) |
315 | } else if (key->eth.type == htons(ETH_P_IPV6)) { | 320 | } else if (key->eth.type == htons(ETH_P_IPV6)) { |
316 | enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone; | 321 | enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone; |
317 | struct sk_buff *reasm; | ||
318 | 322 | ||
319 | memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); | 323 | memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); |
320 | reasm = nf_ct_frag6_gather(net, skb, user); | 324 | err = nf_ct_frag6_gather(net, skb, user); |
321 | if (!reasm) | 325 | if (err) |
322 | return -EINPROGRESS; | 326 | return err; |
323 | |||
324 | if (skb == reasm) { | ||
325 | kfree_skb(skb); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | /* Don't free 'skb' even though it is one of the original | ||
330 | * fragments, as we're going to morph it into the head. | ||
331 | */ | ||
332 | skb_get(skb); | ||
333 | nf_ct_frag6_consume_orig(reasm); | ||
334 | 327 | ||
335 | key->ip.proto = ipv6_hdr(reasm)->nexthdr; | 328 | key->ip.proto = ipv6_hdr(skb)->nexthdr; |
336 | skb_morph(skb, reasm); | ||
337 | skb->next = reasm->next; | ||
338 | consume_skb(reasm); | ||
339 | ovs_cb.mru = IP6CB(skb)->frag_max_size; | 329 | ovs_cb.mru = IP6CB(skb)->frag_max_size; |
340 | #endif | 330 | #endif |
341 | } else { | 331 | } else { |
@@ -418,7 +408,7 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key, | |||
418 | } | 408 | } |
419 | } | 409 | } |
420 | 410 | ||
421 | ovs_ct_update_key(skb, key, true); | 411 | ovs_ct_update_key(skb, info, key, true); |
422 | 412 | ||
423 | return 0; | 413 | return 0; |
424 | } | 414 | } |
@@ -693,6 +683,10 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, | |||
693 | OVS_NLERR(log, "Failed to allocate conntrack template"); | 683 | OVS_NLERR(log, "Failed to allocate conntrack template"); |
694 | return -ENOMEM; | 684 | return -ENOMEM; |
695 | } | 685 | } |
686 | |||
687 | __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status); | ||
688 | nf_conntrack_get(&ct_info.ct->ct_general); | ||
689 | |||
696 | if (helper) { | 690 | if (helper) { |
697 | err = ovs_ct_add_helper(&ct_info, helper, key, log); | 691 | err = ovs_ct_add_helper(&ct_info, helper, key, log); |
698 | if (err) | 692 | if (err) |
@@ -704,11 +698,9 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, | |||
704 | if (err) | 698 | if (err) |
705 | goto err_free_ct; | 699 | goto err_free_ct; |
706 | 700 | ||
707 | __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status); | ||
708 | nf_conntrack_get(&ct_info.ct->ct_general); | ||
709 | return 0; | 701 | return 0; |
710 | err_free_ct: | 702 | err_free_ct: |
711 | nf_conntrack_free(ct_info.ct); | 703 | __ovs_ct_free_action(&ct_info); |
712 | return err; | 704 | return err; |
713 | } | 705 | } |
714 | 706 | ||
@@ -750,6 +742,11 @@ void ovs_ct_free_action(const struct nlattr *a) | |||
750 | { | 742 | { |
751 | struct ovs_conntrack_info *ct_info = nla_data(a); | 743 | struct ovs_conntrack_info *ct_info = nla_data(a); |
752 | 744 | ||
745 | __ovs_ct_free_action(ct_info); | ||
746 | } | ||
747 | |||
748 | static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info) | ||
749 | { | ||
753 | if (ct_info->helper) | 750 | if (ct_info->helper) |
754 | module_put(ct_info->helper->me); | 751 | module_put(ct_info->helper->me); |
755 | if (ct_info->ct) | 752 | if (ct_info->ct) |
diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c index a7a80a6b77b0..653d073bae45 100644 --- a/net/openvswitch/dp_notify.c +++ b/net/openvswitch/dp_notify.c | |||
@@ -58,7 +58,7 @@ void ovs_dp_notify_wq(struct work_struct *work) | |||
58 | struct hlist_node *n; | 58 | struct hlist_node *n; |
59 | 59 | ||
60 | hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node) { | 60 | hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node) { |
61 | if (vport->ops->type != OVS_VPORT_TYPE_NETDEV) | 61 | if (vport->ops->type == OVS_VPORT_TYPE_INTERNAL) |
62 | continue; | 62 | continue; |
63 | 63 | ||
64 | if (!(vport->dev->priv_flags & IFF_OVS_DATAPATH)) | 64 | if (!(vport->dev->priv_flags & IFF_OVS_DATAPATH)) |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 907d6fd28ede..d1bd4a45ca2d 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -2434,7 +2434,10 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) | |||
2434 | if (!start) | 2434 | if (!start) |
2435 | return -EMSGSIZE; | 2435 | return -EMSGSIZE; |
2436 | 2436 | ||
2437 | err = ovs_nla_put_tunnel_info(skb, tun_info); | 2437 | err = ip_tun_to_nlattr(skb, &tun_info->key, |
2438 | ip_tunnel_info_opts(tun_info), | ||
2439 | tun_info->options_len, | ||
2440 | ip_tunnel_info_af(tun_info)); | ||
2438 | if (err) | 2441 | if (err) |
2439 | return err; | 2442 | return err; |
2440 | nla_nest_end(skb, start); | 2443 | nla_nest_end(skb, start); |
diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c index efb736bb6855..30ab8e127288 100644 --- a/net/openvswitch/vport-geneve.c +++ b/net/openvswitch/vport-geneve.c | |||
@@ -34,7 +34,7 @@ static struct vport_ops ovs_geneve_vport_ops; | |||
34 | * @dst_port: destination port. | 34 | * @dst_port: destination port. |
35 | */ | 35 | */ |
36 | struct geneve_port { | 36 | struct geneve_port { |
37 | u16 port_no; | 37 | u16 dst_port; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static inline struct geneve_port *geneve_vport(const struct vport *vport) | 40 | static inline struct geneve_port *geneve_vport(const struct vport *vport) |
@@ -47,7 +47,7 @@ static int geneve_get_options(const struct vport *vport, | |||
47 | { | 47 | { |
48 | struct geneve_port *geneve_port = geneve_vport(vport); | 48 | struct geneve_port *geneve_port = geneve_vport(vport); |
49 | 49 | ||
50 | if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, geneve_port->port_no)) | 50 | if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, geneve_port->dst_port)) |
51 | return -EMSGSIZE; | 51 | return -EMSGSIZE; |
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
@@ -83,7 +83,7 @@ static struct vport *geneve_tnl_create(const struct vport_parms *parms) | |||
83 | return vport; | 83 | return vport; |
84 | 84 | ||
85 | geneve_port = geneve_vport(vport); | 85 | geneve_port = geneve_vport(vport); |
86 | geneve_port->port_no = dst_port; | 86 | geneve_port->dst_port = dst_port; |
87 | 87 | ||
88 | rtnl_lock(); | 88 | rtnl_lock(); |
89 | dev = geneve_dev_create_fb(net, parms->name, NET_NAME_USER, dst_port); | 89 | dev = geneve_dev_create_fb(net, parms->name, NET_NAME_USER, dst_port); |
@@ -117,7 +117,6 @@ static struct vport_ops ovs_geneve_vport_ops = { | |||
117 | .destroy = ovs_netdev_tunnel_destroy, | 117 | .destroy = ovs_netdev_tunnel_destroy, |
118 | .get_options = geneve_get_options, | 118 | .get_options = geneve_get_options, |
119 | .send = dev_queue_xmit, | 119 | .send = dev_queue_xmit, |
120 | .owner = THIS_MODULE, | ||
121 | }; | 120 | }; |
122 | 121 | ||
123 | static int __init ovs_geneve_tnl_init(void) | 122 | static int __init ovs_geneve_tnl_init(void) |
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index c3257d78d3d2..7f8897f33a67 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c | |||
@@ -89,7 +89,6 @@ static struct vport_ops ovs_gre_vport_ops = { | |||
89 | .create = gre_create, | 89 | .create = gre_create, |
90 | .send = dev_queue_xmit, | 90 | .send = dev_queue_xmit, |
91 | .destroy = ovs_netdev_tunnel_destroy, | 91 | .destroy = ovs_netdev_tunnel_destroy, |
92 | .owner = THIS_MODULE, | ||
93 | }; | 92 | }; |
94 | 93 | ||
95 | static int __init ovs_gre_tnl_init(void) | 94 | static int __init ovs_gre_tnl_init(void) |
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index b327368a3848..6a6adf314363 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c | |||
@@ -105,7 +105,7 @@ struct vport *ovs_netdev_link(struct vport *vport, const char *name) | |||
105 | 105 | ||
106 | rtnl_lock(); | 106 | rtnl_lock(); |
107 | err = netdev_master_upper_dev_link(vport->dev, | 107 | err = netdev_master_upper_dev_link(vport->dev, |
108 | get_dpdev(vport->dp)); | 108 | get_dpdev(vport->dp), NULL, NULL); |
109 | if (err) | 109 | if (err) |
110 | goto error_unlock; | 110 | goto error_unlock; |
111 | 111 | ||
@@ -180,9 +180,13 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) | |||
180 | if (vport->dev->priv_flags & IFF_OVS_DATAPATH) | 180 | if (vport->dev->priv_flags & IFF_OVS_DATAPATH) |
181 | ovs_netdev_detach_dev(vport); | 181 | ovs_netdev_detach_dev(vport); |
182 | 182 | ||
183 | /* Early release so we can unregister the device */ | 183 | /* We can be invoked by both explicit vport deletion and |
184 | * underlying netdev deregistration; delete the link only | ||
185 | * if it's not already shutting down. | ||
186 | */ | ||
187 | if (vport->dev->reg_state == NETREG_REGISTERED) | ||
188 | rtnl_delete_link(vport->dev); | ||
184 | dev_put(vport->dev); | 189 | dev_put(vport->dev); |
185 | rtnl_delete_link(vport->dev); | ||
186 | vport->dev = NULL; | 190 | vport->dev = NULL; |
187 | rtnl_unlock(); | 191 | rtnl_unlock(); |
188 | 192 | ||
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 0ac0fd004d7e..31cbc8c5c7db 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
@@ -71,7 +71,7 @@ static struct hlist_head *hash_bucket(const struct net *net, const char *name) | |||
71 | return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)]; | 71 | return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)]; |
72 | } | 72 | } |
73 | 73 | ||
74 | int ovs_vport_ops_register(struct vport_ops *ops) | 74 | int __ovs_vport_ops_register(struct vport_ops *ops) |
75 | { | 75 | { |
76 | int err = -EEXIST; | 76 | int err = -EEXIST; |
77 | struct vport_ops *o; | 77 | struct vport_ops *o; |
@@ -87,7 +87,7 @@ errout: | |||
87 | ovs_unlock(); | 87 | ovs_unlock(); |
88 | return err; | 88 | return err; |
89 | } | 89 | } |
90 | EXPORT_SYMBOL_GPL(ovs_vport_ops_register); | 90 | EXPORT_SYMBOL_GPL(__ovs_vport_ops_register); |
91 | 91 | ||
92 | void ovs_vport_ops_unregister(struct vport_ops *ops) | 92 | void ovs_vport_ops_unregister(struct vport_ops *ops) |
93 | { | 93 | { |
@@ -256,8 +256,8 @@ int ovs_vport_set_options(struct vport *vport, struct nlattr *options) | |||
256 | * | 256 | * |
257 | * @vport: vport to delete. | 257 | * @vport: vport to delete. |
258 | * | 258 | * |
259 | * Detaches @vport from its datapath and destroys it. It is possible to fail | 259 | * Detaches @vport from its datapath and destroys it. ovs_mutex must |
260 | * for reasons such as lack of memory. ovs_mutex must be held. | 260 | * be held. |
261 | */ | 261 | */ |
262 | void ovs_vport_del(struct vport *vport) | 262 | void ovs_vport_del(struct vport *vport) |
263 | { | 263 | { |
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index bdfd82a7c064..c10899cb9040 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h | |||
@@ -70,7 +70,7 @@ struct vport_portids { | |||
70 | 70 | ||
71 | /** | 71 | /** |
72 | * struct vport - one port within a datapath | 72 | * struct vport - one port within a datapath |
73 | * @rcu: RCU callback head for deferred destruction. | 73 | * @dev: Pointer to net_device. |
74 | * @dp: Datapath to which this port belongs. | 74 | * @dp: Datapath to which this port belongs. |
75 | * @upcall_portids: RCU protected 'struct vport_portids'. | 75 | * @upcall_portids: RCU protected 'struct vport_portids'. |
76 | * @port_no: Index into @dp's @ports array. | 76 | * @port_no: Index into @dp's @ports array. |
@@ -78,6 +78,7 @@ struct vport_portids { | |||
78 | * @dp_hash_node: Element in @datapath->ports hash table in datapath.c. | 78 | * @dp_hash_node: Element in @datapath->ports hash table in datapath.c. |
79 | * @ops: Class structure. | 79 | * @ops: Class structure. |
80 | * @detach_list: list used for detaching vport in net-exit call. | 80 | * @detach_list: list used for detaching vport in net-exit call. |
81 | * @rcu: RCU callback head for deferred destruction. | ||
81 | */ | 82 | */ |
82 | struct vport { | 83 | struct vport { |
83 | struct net_device *dev; | 84 | struct net_device *dev; |
@@ -196,28 +197,14 @@ static inline const char *ovs_vport_name(struct vport *vport) | |||
196 | return vport->dev->name; | 197 | return vport->dev->name; |
197 | } | 198 | } |
198 | 199 | ||
199 | int ovs_vport_ops_register(struct vport_ops *ops); | 200 | int __ovs_vport_ops_register(struct vport_ops *ops); |
200 | void ovs_vport_ops_unregister(struct vport_ops *ops); | 201 | #define ovs_vport_ops_register(ops) \ |
201 | 202 | ({ \ | |
202 | static inline struct rtable *ovs_tunnel_route_lookup(struct net *net, | 203 | (ops)->owner = THIS_MODULE; \ |
203 | const struct ip_tunnel_key *key, | 204 | __ovs_vport_ops_register(ops); \ |
204 | u32 mark, | 205 | }) |
205 | struct flowi4 *fl, | ||
206 | u8 protocol) | ||
207 | { | ||
208 | struct rtable *rt; | ||
209 | |||
210 | memset(fl, 0, sizeof(*fl)); | ||
211 | fl->daddr = key->u.ipv4.dst; | ||
212 | fl->saddr = key->u.ipv4.src; | ||
213 | fl->flowi4_tos = RT_TOS(key->tos); | ||
214 | fl->flowi4_mark = mark; | ||
215 | fl->flowi4_proto = protocol; | ||
216 | |||
217 | rt = ip_route_output_key(net, fl); | ||
218 | return rt; | ||
219 | } | ||
220 | 206 | ||
207 | void ovs_vport_ops_unregister(struct vport_ops *ops); | ||
221 | void ovs_vport_send(struct vport *vport, struct sk_buff *skb); | 208 | void ovs_vport_send(struct vport *vport, struct sk_buff *skb); |
222 | 209 | ||
223 | #endif /* vport.h */ | 210 | #endif /* vport.h */ |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 1cf928fb573e..992396aa635c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2329,8 +2329,8 @@ static void tpacket_destruct_skb(struct sk_buff *skb) | |||
2329 | static bool ll_header_truncated(const struct net_device *dev, int len) | 2329 | static bool ll_header_truncated(const struct net_device *dev, int len) |
2330 | { | 2330 | { |
2331 | /* net device doesn't like empty head */ | 2331 | /* net device doesn't like empty head */ |
2332 | if (unlikely(len <= dev->hard_header_len)) { | 2332 | if (unlikely(len < dev->hard_header_len)) { |
2333 | net_warn_ratelimited("%s: packet size is too short (%d <= %d)\n", | 2333 | net_warn_ratelimited("%s: packet size is too short (%d < %d)\n", |
2334 | current->comm, len, dev->hard_header_len); | 2334 | current->comm, len, dev->hard_header_len); |
2335 | return true; | 2335 | return true; |
2336 | } | 2336 | } |
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 10d42f3220ab..f925753668a7 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c | |||
@@ -377,6 +377,10 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, | |||
377 | struct sockaddr_pn sa; | 377 | struct sockaddr_pn sa; |
378 | u16 len; | 378 | u16 len; |
379 | 379 | ||
380 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
381 | if (!skb) | ||
382 | return NET_RX_DROP; | ||
383 | |||
380 | /* check we have at least a full Phonet header */ | 384 | /* check we have at least a full Phonet header */ |
381 | if (!pskb_pull(skb, sizeof(struct phonethdr))) | 385 | if (!pskb_pull(skb, sizeof(struct phonethdr))) |
382 | goto out; | 386 | goto out; |
diff --git a/net/rds/connection.c b/net/rds/connection.c index d4564036a339..e3b118cae81d 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c | |||
@@ -186,12 +186,6 @@ static struct rds_connection *__rds_conn_create(struct net *net, | |||
186 | } | 186 | } |
187 | } | 187 | } |
188 | 188 | ||
189 | if (trans == NULL) { | ||
190 | kmem_cache_free(rds_conn_slab, conn); | ||
191 | conn = ERR_PTR(-ENODEV); | ||
192 | goto out; | ||
193 | } | ||
194 | |||
195 | conn->c_trans = trans; | 189 | conn->c_trans = trans; |
196 | 190 | ||
197 | ret = trans->conn_alloc(conn, gfp); | 191 | ret = trans->conn_alloc(conn, gfp); |
diff --git a/net/rds/page.c b/net/rds/page.c index 9005a2c920ee..5a14e6d6a926 100644 --- a/net/rds/page.c +++ b/net/rds/page.c | |||
@@ -179,37 +179,18 @@ out: | |||
179 | } | 179 | } |
180 | EXPORT_SYMBOL_GPL(rds_page_remainder_alloc); | 180 | EXPORT_SYMBOL_GPL(rds_page_remainder_alloc); |
181 | 181 | ||
182 | static int rds_page_remainder_cpu_notify(struct notifier_block *self, | 182 | void rds_page_exit(void) |
183 | unsigned long action, void *hcpu) | ||
184 | { | 183 | { |
185 | struct rds_page_remainder *rem; | 184 | unsigned int cpu; |
186 | long cpu = (long)hcpu; | ||
187 | 185 | ||
188 | rem = &per_cpu(rds_page_remainders, cpu); | 186 | for_each_possible_cpu(cpu) { |
187 | struct rds_page_remainder *rem; | ||
189 | 188 | ||
190 | rdsdebug("cpu %ld action 0x%lx\n", cpu, action); | 189 | rem = &per_cpu(rds_page_remainders, cpu); |
190 | rdsdebug("cpu %u\n", cpu); | ||
191 | 191 | ||
192 | switch (action) { | ||
193 | case CPU_DEAD: | ||
194 | if (rem->r_page) | 192 | if (rem->r_page) |
195 | __free_page(rem->r_page); | 193 | __free_page(rem->r_page); |
196 | rem->r_page = NULL; | 194 | rem->r_page = NULL; |
197 | break; | ||
198 | } | 195 | } |
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static struct notifier_block rds_page_remainder_nb = { | ||
204 | .notifier_call = rds_page_remainder_cpu_notify, | ||
205 | }; | ||
206 | |||
207 | void rds_page_exit(void) | ||
208 | { | ||
209 | int i; | ||
210 | |||
211 | for_each_possible_cpu(i) | ||
212 | rds_page_remainder_cpu_notify(&rds_page_remainder_nb, | ||
213 | (unsigned long)CPU_DEAD, | ||
214 | (void *)(long)i); | ||
215 | } | 196 | } |
diff --git a/net/rds/send.c b/net/rds/send.c index 827155c2ead1..c9cdb358ea88 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
@@ -1013,11 +1013,13 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) | |||
1013 | release_sock(sk); | 1013 | release_sock(sk); |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | /* racing with another thread binding seems ok here */ | 1016 | lock_sock(sk); |
1017 | if (daddr == 0 || rs->rs_bound_addr == 0) { | 1017 | if (daddr == 0 || rs->rs_bound_addr == 0) { |
1018 | release_sock(sk); | ||
1018 | ret = -ENOTCONN; /* XXX not a great errno */ | 1019 | ret = -ENOTCONN; /* XXX not a great errno */ |
1019 | goto out; | 1020 | goto out; |
1020 | } | 1021 | } |
1022 | release_sock(sk); | ||
1021 | 1023 | ||
1022 | if (payload_len > rds_sk_sndbuf(rs)) { | 1024 | if (payload_len > rds_sk_sndbuf(rs)) { |
1023 | ret = -EMSGSIZE; | 1025 | ret = -EMSGSIZE; |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index b41e9ea2ffff..f53bf3b6558b 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -49,7 +49,6 @@ | |||
49 | struct rfkill { | 49 | struct rfkill { |
50 | spinlock_t lock; | 50 | spinlock_t lock; |
51 | 51 | ||
52 | const char *name; | ||
53 | enum rfkill_type type; | 52 | enum rfkill_type type; |
54 | 53 | ||
55 | unsigned long state; | 54 | unsigned long state; |
@@ -73,6 +72,7 @@ struct rfkill { | |||
73 | struct delayed_work poll_work; | 72 | struct delayed_work poll_work; |
74 | struct work_struct uevent_work; | 73 | struct work_struct uevent_work; |
75 | struct work_struct sync_work; | 74 | struct work_struct sync_work; |
75 | char name[]; | ||
76 | }; | 76 | }; |
77 | #define to_rfkill(d) container_of(d, struct rfkill, dev) | 77 | #define to_rfkill(d) container_of(d, struct rfkill, dev) |
78 | 78 | ||
@@ -876,14 +876,14 @@ struct rfkill * __must_check rfkill_alloc(const char *name, | |||
876 | if (WARN_ON(type == RFKILL_TYPE_ALL || type >= NUM_RFKILL_TYPES)) | 876 | if (WARN_ON(type == RFKILL_TYPE_ALL || type >= NUM_RFKILL_TYPES)) |
877 | return NULL; | 877 | return NULL; |
878 | 878 | ||
879 | rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); | 879 | rfkill = kzalloc(sizeof(*rfkill) + strlen(name) + 1, GFP_KERNEL); |
880 | if (!rfkill) | 880 | if (!rfkill) |
881 | return NULL; | 881 | return NULL; |
882 | 882 | ||
883 | spin_lock_init(&rfkill->lock); | 883 | spin_lock_init(&rfkill->lock); |
884 | INIT_LIST_HEAD(&rfkill->node); | 884 | INIT_LIST_HEAD(&rfkill->node); |
885 | rfkill->type = type; | 885 | rfkill->type = type; |
886 | rfkill->name = name; | 886 | strcpy(rfkill->name, name); |
887 | rfkill->ops = ops; | 887 | rfkill->ops = ops; |
888 | rfkill->data = ops_data; | 888 | rfkill->data = ops_data; |
889 | 889 | ||
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index 93127220cb54..4b1e3f35f06c 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c | |||
@@ -163,10 +163,6 @@ static int rfkill_gpio_remove(struct platform_device *pdev) | |||
163 | 163 | ||
164 | #ifdef CONFIG_ACPI | 164 | #ifdef CONFIG_ACPI |
165 | static const struct acpi_device_id rfkill_acpi_match[] = { | 165 | static const struct acpi_device_id rfkill_acpi_match[] = { |
166 | { "BCM2E1A", RFKILL_TYPE_BLUETOOTH }, | ||
167 | { "BCM2E3D", RFKILL_TYPE_BLUETOOTH }, | ||
168 | { "BCM2E40", RFKILL_TYPE_BLUETOOTH }, | ||
169 | { "BCM2E64", RFKILL_TYPE_BLUETOOTH }, | ||
170 | { "BCM4752", RFKILL_TYPE_GPS }, | 166 | { "BCM4752", RFKILL_TYPE_GPS }, |
171 | { "LNV4752", RFKILL_TYPE_GPS }, | 167 | { "LNV4752", RFKILL_TYPE_GPS }, |
172 | { }, | 168 | { }, |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 1f8a144a5dc2..7e2d1057d8bc 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -67,7 +67,7 @@ static void rxrpc_write_space(struct sock *sk) | |||
67 | if (rxrpc_writable(sk)) { | 67 | if (rxrpc_writable(sk)) { |
68 | struct socket_wq *wq = rcu_dereference(sk->sk_wq); | 68 | struct socket_wq *wq = rcu_dereference(sk->sk_wq); |
69 | 69 | ||
70 | if (wq_has_sleeper(wq)) | 70 | if (skwq_has_sleeper(wq)) |
71 | wake_up_interruptible(&wq->wait); | 71 | wake_up_interruptible(&wq->wait); |
72 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 72 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
73 | } | 73 | } |
diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index e0547f521f20..adc555e0323d 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c | |||
@@ -723,8 +723,10 @@ process_further: | |||
723 | 723 | ||
724 | if ((call->state == RXRPC_CALL_CLIENT_AWAIT_REPLY || | 724 | if ((call->state == RXRPC_CALL_CLIENT_AWAIT_REPLY || |
725 | call->state == RXRPC_CALL_SERVER_AWAIT_ACK) && | 725 | call->state == RXRPC_CALL_SERVER_AWAIT_ACK) && |
726 | hard > tx) | 726 | hard > tx) { |
727 | call->acks_hard = tx; | ||
727 | goto all_acked; | 728 | goto all_acked; |
729 | } | ||
728 | 730 | ||
729 | smp_rmb(); | 731 | smp_rmb(); |
730 | rxrpc_rotate_tx_window(call, hard - 1); | 732 | rxrpc_rotate_tx_window(call, hard - 1); |
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index da3cc09f683e..3f6571651d32 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -896,15 +896,9 @@ int rxrpc_request_key(struct rxrpc_sock *rx, char __user *optval, int optlen) | |||
896 | if (optlen <= 0 || optlen > PAGE_SIZE - 1) | 896 | if (optlen <= 0 || optlen > PAGE_SIZE - 1) |
897 | return -EINVAL; | 897 | return -EINVAL; |
898 | 898 | ||
899 | description = kmalloc(optlen + 1, GFP_KERNEL); | 899 | description = memdup_user_nul(optval, optlen); |
900 | if (!description) | 900 | if (IS_ERR(description)) |
901 | return -ENOMEM; | 901 | return PTR_ERR(description); |
902 | |||
903 | if (copy_from_user(description, optval, optlen)) { | ||
904 | kfree(description); | ||
905 | return -EFAULT; | ||
906 | } | ||
907 | description[optlen] = 0; | ||
908 | 902 | ||
909 | key = request_key(&key_type_rxrpc, description, NULL); | 903 | key = request_key(&key_type_rxrpc, description, NULL); |
910 | if (IS_ERR(key)) { | 904 | if (IS_ERR(key)) { |
@@ -933,15 +927,9 @@ int rxrpc_server_keyring(struct rxrpc_sock *rx, char __user *optval, | |||
933 | if (optlen <= 0 || optlen > PAGE_SIZE - 1) | 927 | if (optlen <= 0 || optlen > PAGE_SIZE - 1) |
934 | return -EINVAL; | 928 | return -EINVAL; |
935 | 929 | ||
936 | description = kmalloc(optlen + 1, GFP_KERNEL); | 930 | description = memdup_user_nul(optval, optlen); |
937 | if (!description) | 931 | if (IS_ERR(description)) |
938 | return -ENOMEM; | 932 | return PTR_ERR(description); |
939 | |||
940 | if (copy_from_user(description, optval, optlen)) { | ||
941 | kfree(description); | ||
942 | return -EFAULT; | ||
943 | } | ||
944 | description[optlen] = 0; | ||
945 | 933 | ||
946 | key = request_key(&key_type_keyring, description, NULL); | 934 | key = request_key(&key_type_keyring, description, NULL); |
947 | if (IS_ERR(key)) { | 935 | if (IS_ERR(key)) { |
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c index a40d3afe93b7..14c4e12c47b0 100644 --- a/net/rxrpc/ar-output.c +++ b/net/rxrpc/ar-output.c | |||
@@ -531,7 +531,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
531 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); | 531 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); |
532 | 532 | ||
533 | /* this should be in poll */ | 533 | /* this should be in poll */ |
534 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 534 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
535 | 535 | ||
536 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 536 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
537 | return -EPIPE; | 537 | return -EPIPE; |
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index daa33432b716..82830824fb1f 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -310,15 +310,21 @@ config NET_SCH_PIE | |||
310 | If unsure, say N. | 310 | If unsure, say N. |
311 | 311 | ||
312 | config NET_SCH_INGRESS | 312 | config NET_SCH_INGRESS |
313 | tristate "Ingress Qdisc" | 313 | tristate "Ingress/classifier-action Qdisc" |
314 | depends on NET_CLS_ACT | 314 | depends on NET_CLS_ACT |
315 | select NET_INGRESS | 315 | select NET_INGRESS |
316 | select NET_EGRESS | ||
316 | ---help--- | 317 | ---help--- |
317 | Say Y here if you want to use classifiers for incoming packets. | 318 | Say Y here if you want to use classifiers for incoming and/or outgoing |
319 | packets. This qdisc doesn't do anything else besides running classifiers, | ||
320 | which can also have actions attached to them. In case of outgoing packets, | ||
321 | classifiers that this qdisc holds are executed in the transmit path | ||
322 | before real enqueuing to an egress qdisc happens. | ||
323 | |||
318 | If unsure, say Y. | 324 | If unsure, say Y. |
319 | 325 | ||
320 | To compile this code as a module, choose M here: the | 326 | To compile this code as a module, choose M here: the module will be |
321 | module will be called sch_ingress. | 327 | called sch_ingress with alias of sch_clsact. |
322 | 328 | ||
323 | config NET_SCH_PLUG | 329 | config NET_SCH_PLUG |
324 | tristate "Plug network traffic until release (PLUG)" | 330 | tristate "Plug network traffic until release (PLUG)" |
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 5faaa5425f7b..8dc84300ee79 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
@@ -79,12 +79,8 @@ static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp, | |||
79 | struct tcf_result *res) | 79 | struct tcf_result *res) |
80 | { | 80 | { |
81 | struct cls_bpf_head *head = rcu_dereference_bh(tp->root); | 81 | struct cls_bpf_head *head = rcu_dereference_bh(tp->root); |
82 | bool at_ingress = skb_at_tc_ingress(skb); | ||
82 | struct cls_bpf_prog *prog; | 83 | struct cls_bpf_prog *prog; |
83 | #ifdef CONFIG_NET_CLS_ACT | ||
84 | bool at_ingress = G_TC_AT(skb->tc_verd) & AT_INGRESS; | ||
85 | #else | ||
86 | bool at_ingress = false; | ||
87 | #endif | ||
88 | int ret = -1; | 84 | int ret = -1; |
89 | 85 | ||
90 | if (unlikely(!skb_mac_header_was_set(skb))) | 86 | if (unlikely(!skb_mac_header_was_set(skb))) |
@@ -295,7 +291,7 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog, | |||
295 | prog->bpf_name = name; | 291 | prog->bpf_name = name; |
296 | prog->filter = fp; | 292 | prog->filter = fp; |
297 | 293 | ||
298 | if (fp->dst_needed) | 294 | if (fp->dst_needed && !(tp->q->flags & TCQ_F_INGRESS)) |
299 | netif_keep_dst(qdisc_dev(tp->q)); | 295 | netif_keep_dst(qdisc_dev(tp->q)); |
300 | 296 | ||
301 | return 0; | 297 | return 0; |
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 57692947ebbe..95b021243233 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c | |||
@@ -252,23 +252,28 @@ static int fl_set_key(struct net *net, struct nlattr **tb, | |||
252 | fl_set_key_val(tb, key->eth.src, TCA_FLOWER_KEY_ETH_SRC, | 252 | fl_set_key_val(tb, key->eth.src, TCA_FLOWER_KEY_ETH_SRC, |
253 | mask->eth.src, TCA_FLOWER_KEY_ETH_SRC_MASK, | 253 | mask->eth.src, TCA_FLOWER_KEY_ETH_SRC_MASK, |
254 | sizeof(key->eth.src)); | 254 | sizeof(key->eth.src)); |
255 | |||
255 | fl_set_key_val(tb, &key->basic.n_proto, TCA_FLOWER_KEY_ETH_TYPE, | 256 | fl_set_key_val(tb, &key->basic.n_proto, TCA_FLOWER_KEY_ETH_TYPE, |
256 | &mask->basic.n_proto, TCA_FLOWER_UNSPEC, | 257 | &mask->basic.n_proto, TCA_FLOWER_UNSPEC, |
257 | sizeof(key->basic.n_proto)); | 258 | sizeof(key->basic.n_proto)); |
259 | |||
258 | if (key->basic.n_proto == htons(ETH_P_IP) || | 260 | if (key->basic.n_proto == htons(ETH_P_IP) || |
259 | key->basic.n_proto == htons(ETH_P_IPV6)) { | 261 | key->basic.n_proto == htons(ETH_P_IPV6)) { |
260 | fl_set_key_val(tb, &key->basic.ip_proto, TCA_FLOWER_KEY_IP_PROTO, | 262 | fl_set_key_val(tb, &key->basic.ip_proto, TCA_FLOWER_KEY_IP_PROTO, |
261 | &mask->basic.ip_proto, TCA_FLOWER_UNSPEC, | 263 | &mask->basic.ip_proto, TCA_FLOWER_UNSPEC, |
262 | sizeof(key->basic.ip_proto)); | 264 | sizeof(key->basic.ip_proto)); |
263 | } | 265 | } |
264 | if (key->control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { | 266 | |
267 | if (tb[TCA_FLOWER_KEY_IPV4_SRC] || tb[TCA_FLOWER_KEY_IPV4_DST]) { | ||
268 | key->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; | ||
265 | fl_set_key_val(tb, &key->ipv4.src, TCA_FLOWER_KEY_IPV4_SRC, | 269 | fl_set_key_val(tb, &key->ipv4.src, TCA_FLOWER_KEY_IPV4_SRC, |
266 | &mask->ipv4.src, TCA_FLOWER_KEY_IPV4_SRC_MASK, | 270 | &mask->ipv4.src, TCA_FLOWER_KEY_IPV4_SRC_MASK, |
267 | sizeof(key->ipv4.src)); | 271 | sizeof(key->ipv4.src)); |
268 | fl_set_key_val(tb, &key->ipv4.dst, TCA_FLOWER_KEY_IPV4_DST, | 272 | fl_set_key_val(tb, &key->ipv4.dst, TCA_FLOWER_KEY_IPV4_DST, |
269 | &mask->ipv4.dst, TCA_FLOWER_KEY_IPV4_DST_MASK, | 273 | &mask->ipv4.dst, TCA_FLOWER_KEY_IPV4_DST_MASK, |
270 | sizeof(key->ipv4.dst)); | 274 | sizeof(key->ipv4.dst)); |
271 | } else if (key->control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { | 275 | } else if (tb[TCA_FLOWER_KEY_IPV6_SRC] || tb[TCA_FLOWER_KEY_IPV6_DST]) { |
276 | key->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; | ||
272 | fl_set_key_val(tb, &key->ipv6.src, TCA_FLOWER_KEY_IPV6_SRC, | 277 | fl_set_key_val(tb, &key->ipv6.src, TCA_FLOWER_KEY_IPV6_SRC, |
273 | &mask->ipv6.src, TCA_FLOWER_KEY_IPV6_SRC_MASK, | 278 | &mask->ipv6.src, TCA_FLOWER_KEY_IPV6_SRC_MASK, |
274 | sizeof(key->ipv6.src)); | 279 | sizeof(key->ipv6.src)); |
@@ -276,6 +281,7 @@ static int fl_set_key(struct net *net, struct nlattr **tb, | |||
276 | &mask->ipv6.dst, TCA_FLOWER_KEY_IPV6_DST_MASK, | 281 | &mask->ipv6.dst, TCA_FLOWER_KEY_IPV6_DST_MASK, |
277 | sizeof(key->ipv6.dst)); | 282 | sizeof(key->ipv6.dst)); |
278 | } | 283 | } |
284 | |||
279 | if (key->basic.ip_proto == IPPROTO_TCP) { | 285 | if (key->basic.ip_proto == IPPROTO_TCP) { |
280 | fl_set_key_val(tb, &key->tp.src, TCA_FLOWER_KEY_TCP_SRC, | 286 | fl_set_key_val(tb, &key->tp.src, TCA_FLOWER_KEY_TCP_SRC, |
281 | &mask->tp.src, TCA_FLOWER_UNSPEC, | 287 | &mask->tp.src, TCA_FLOWER_UNSPEC, |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index f43c8f33f09e..b5c2cf2aa6d4 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -253,7 +253,8 @@ int qdisc_set_default(const char *name) | |||
253 | } | 253 | } |
254 | 254 | ||
255 | /* We know handle. Find qdisc among all qdisc's attached to device | 255 | /* We know handle. Find qdisc among all qdisc's attached to device |
256 | (root qdisc, all its children, children of children etc.) | 256 | * (root qdisc, all its children, children of children etc.) |
257 | * Note: caller either uses rtnl or rcu_read_lock() | ||
257 | */ | 258 | */ |
258 | 259 | ||
259 | static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle) | 260 | static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle) |
@@ -264,7 +265,7 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle) | |||
264 | root->handle == handle) | 265 | root->handle == handle) |
265 | return root; | 266 | return root; |
266 | 267 | ||
267 | list_for_each_entry(q, &root->list, list) { | 268 | list_for_each_entry_rcu(q, &root->list, list) { |
268 | if (q->handle == handle) | 269 | if (q->handle == handle) |
269 | return q; | 270 | return q; |
270 | } | 271 | } |
@@ -277,15 +278,18 @@ void qdisc_list_add(struct Qdisc *q) | |||
277 | struct Qdisc *root = qdisc_dev(q)->qdisc; | 278 | struct Qdisc *root = qdisc_dev(q)->qdisc; |
278 | 279 | ||
279 | WARN_ON_ONCE(root == &noop_qdisc); | 280 | WARN_ON_ONCE(root == &noop_qdisc); |
280 | list_add_tail(&q->list, &root->list); | 281 | ASSERT_RTNL(); |
282 | list_add_tail_rcu(&q->list, &root->list); | ||
281 | } | 283 | } |
282 | } | 284 | } |
283 | EXPORT_SYMBOL(qdisc_list_add); | 285 | EXPORT_SYMBOL(qdisc_list_add); |
284 | 286 | ||
285 | void qdisc_list_del(struct Qdisc *q) | 287 | void qdisc_list_del(struct Qdisc *q) |
286 | { | 288 | { |
287 | if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) | 289 | if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) { |
288 | list_del(&q->list); | 290 | ASSERT_RTNL(); |
291 | list_del_rcu(&q->list); | ||
292 | } | ||
289 | } | 293 | } |
290 | EXPORT_SYMBOL(qdisc_list_del); | 294 | EXPORT_SYMBOL(qdisc_list_del); |
291 | 295 | ||
@@ -750,14 +754,18 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | |||
750 | if (n == 0) | 754 | if (n == 0) |
751 | return; | 755 | return; |
752 | drops = max_t(int, n, 0); | 756 | drops = max_t(int, n, 0); |
757 | rcu_read_lock(); | ||
753 | while ((parentid = sch->parent)) { | 758 | while ((parentid = sch->parent)) { |
754 | if (TC_H_MAJ(parentid) == TC_H_MAJ(TC_H_INGRESS)) | 759 | if (TC_H_MAJ(parentid) == TC_H_MAJ(TC_H_INGRESS)) |
755 | return; | 760 | break; |
756 | 761 | ||
762 | if (sch->flags & TCQ_F_NOPARENT) | ||
763 | break; | ||
764 | /* TODO: perform the search on a per txq basis */ | ||
757 | sch = qdisc_lookup(qdisc_dev(sch), TC_H_MAJ(parentid)); | 765 | sch = qdisc_lookup(qdisc_dev(sch), TC_H_MAJ(parentid)); |
758 | if (sch == NULL) { | 766 | if (sch == NULL) { |
759 | WARN_ON(parentid != TC_H_ROOT); | 767 | WARN_ON_ONCE(parentid != TC_H_ROOT); |
760 | return; | 768 | break; |
761 | } | 769 | } |
762 | cops = sch->ops->cl_ops; | 770 | cops = sch->ops->cl_ops; |
763 | if (cops->qlen_notify) { | 771 | if (cops->qlen_notify) { |
@@ -768,6 +776,7 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | |||
768 | sch->q.qlen -= n; | 776 | sch->q.qlen -= n; |
769 | __qdisc_qstats_drop(sch, drops); | 777 | __qdisc_qstats_drop(sch, drops); |
770 | } | 778 | } |
779 | rcu_read_unlock(); | ||
771 | } | 780 | } |
772 | EXPORT_SYMBOL(qdisc_tree_decrease_qlen); | 781 | EXPORT_SYMBOL(qdisc_tree_decrease_qlen); |
773 | 782 | ||
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index cb5d4ad32946..16bc83b2842a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -658,8 +658,10 @@ static void qdisc_rcu_free(struct rcu_head *head) | |||
658 | { | 658 | { |
659 | struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head); | 659 | struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head); |
660 | 660 | ||
661 | if (qdisc_is_percpu_stats(qdisc)) | 661 | if (qdisc_is_percpu_stats(qdisc)) { |
662 | free_percpu(qdisc->cpu_bstats); | 662 | free_percpu(qdisc->cpu_bstats); |
663 | free_percpu(qdisc->cpu_qstats); | ||
664 | } | ||
663 | 665 | ||
664 | kfree((char *) qdisc - qdisc->padded); | 666 | kfree((char *) qdisc - qdisc->padded); |
665 | } | 667 | } |
@@ -737,7 +739,7 @@ static void attach_one_default_qdisc(struct net_device *dev, | |||
737 | return; | 739 | return; |
738 | } | 740 | } |
739 | if (!netif_is_multiqueue(dev)) | 741 | if (!netif_is_multiqueue(dev)) |
740 | qdisc->flags |= TCQ_F_ONETXQUEUE; | 742 | qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; |
741 | dev_queue->qdisc_sleeping = qdisc; | 743 | dev_queue->qdisc_sleeping = qdisc; |
742 | } | 744 | } |
743 | 745 | ||
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index e7c648fa9dc3..10adbc617905 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* net/sched/sch_ingress.c - Ingress qdisc | 1 | /* net/sched/sch_ingress.c - Ingress and clsact qdisc |
2 | * | ||
2 | * This program is free software; you can redistribute it and/or | 3 | * This program is free software; you can redistribute it and/or |
3 | * modify it under the terms of the GNU General Public License | 4 | * modify it under the terms of the GNU General Public License |
4 | * as published by the Free Software Foundation; either version | 5 | * as published by the Free Software Foundation; either version |
@@ -98,17 +99,100 @@ static struct Qdisc_ops ingress_qdisc_ops __read_mostly = { | |||
98 | .owner = THIS_MODULE, | 99 | .owner = THIS_MODULE, |
99 | }; | 100 | }; |
100 | 101 | ||
102 | static unsigned long clsact_get(struct Qdisc *sch, u32 classid) | ||
103 | { | ||
104 | switch (TC_H_MIN(classid)) { | ||
105 | case TC_H_MIN(TC_H_MIN_INGRESS): | ||
106 | case TC_H_MIN(TC_H_MIN_EGRESS): | ||
107 | return TC_H_MIN(classid); | ||
108 | default: | ||
109 | return 0; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | static unsigned long clsact_bind_filter(struct Qdisc *sch, | ||
114 | unsigned long parent, u32 classid) | ||
115 | { | ||
116 | return clsact_get(sch, classid); | ||
117 | } | ||
118 | |||
119 | static struct tcf_proto __rcu **clsact_find_tcf(struct Qdisc *sch, | ||
120 | unsigned long cl) | ||
121 | { | ||
122 | struct net_device *dev = qdisc_dev(sch); | ||
123 | |||
124 | switch (cl) { | ||
125 | case TC_H_MIN(TC_H_MIN_INGRESS): | ||
126 | return &dev->ingress_cl_list; | ||
127 | case TC_H_MIN(TC_H_MIN_EGRESS): | ||
128 | return &dev->egress_cl_list; | ||
129 | default: | ||
130 | return NULL; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static int clsact_init(struct Qdisc *sch, struct nlattr *opt) | ||
135 | { | ||
136 | net_inc_ingress_queue(); | ||
137 | net_inc_egress_queue(); | ||
138 | |||
139 | sch->flags |= TCQ_F_CPUSTATS; | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static void clsact_destroy(struct Qdisc *sch) | ||
145 | { | ||
146 | struct net_device *dev = qdisc_dev(sch); | ||
147 | |||
148 | tcf_destroy_chain(&dev->ingress_cl_list); | ||
149 | tcf_destroy_chain(&dev->egress_cl_list); | ||
150 | |||
151 | net_dec_ingress_queue(); | ||
152 | net_dec_egress_queue(); | ||
153 | } | ||
154 | |||
155 | static const struct Qdisc_class_ops clsact_class_ops = { | ||
156 | .leaf = ingress_leaf, | ||
157 | .get = clsact_get, | ||
158 | .put = ingress_put, | ||
159 | .walk = ingress_walk, | ||
160 | .tcf_chain = clsact_find_tcf, | ||
161 | .bind_tcf = clsact_bind_filter, | ||
162 | .unbind_tcf = ingress_put, | ||
163 | }; | ||
164 | |||
165 | static struct Qdisc_ops clsact_qdisc_ops __read_mostly = { | ||
166 | .cl_ops = &clsact_class_ops, | ||
167 | .id = "clsact", | ||
168 | .init = clsact_init, | ||
169 | .destroy = clsact_destroy, | ||
170 | .dump = ingress_dump, | ||
171 | .owner = THIS_MODULE, | ||
172 | }; | ||
173 | |||
101 | static int __init ingress_module_init(void) | 174 | static int __init ingress_module_init(void) |
102 | { | 175 | { |
103 | return register_qdisc(&ingress_qdisc_ops); | 176 | int ret; |
177 | |||
178 | ret = register_qdisc(&ingress_qdisc_ops); | ||
179 | if (!ret) { | ||
180 | ret = register_qdisc(&clsact_qdisc_ops); | ||
181 | if (ret) | ||
182 | unregister_qdisc(&ingress_qdisc_ops); | ||
183 | } | ||
184 | |||
185 | return ret; | ||
104 | } | 186 | } |
105 | 187 | ||
106 | static void __exit ingress_module_exit(void) | 188 | static void __exit ingress_module_exit(void) |
107 | { | 189 | { |
108 | unregister_qdisc(&ingress_qdisc_ops); | 190 | unregister_qdisc(&ingress_qdisc_ops); |
191 | unregister_qdisc(&clsact_qdisc_ops); | ||
109 | } | 192 | } |
110 | 193 | ||
111 | module_init(ingress_module_init); | 194 | module_init(ingress_module_init); |
112 | module_exit(ingress_module_exit); | 195 | module_exit(ingress_module_exit); |
113 | 196 | ||
197 | MODULE_ALIAS("sch_clsact"); | ||
114 | MODULE_LICENSE("GPL"); | 198 | MODULE_LICENSE("GPL"); |
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c index f3cbaecd283a..3e82f047caaf 100644 --- a/net/sched/sch_mq.c +++ b/net/sched/sch_mq.c | |||
@@ -63,7 +63,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt) | |||
63 | if (qdisc == NULL) | 63 | if (qdisc == NULL) |
64 | goto err; | 64 | goto err; |
65 | priv->qdiscs[ntx] = qdisc; | 65 | priv->qdiscs[ntx] = qdisc; |
66 | qdisc->flags |= TCQ_F_ONETXQUEUE; | 66 | qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; |
67 | } | 67 | } |
68 | 68 | ||
69 | sch->flags |= TCQ_F_MQROOT; | 69 | sch->flags |= TCQ_F_MQROOT; |
@@ -156,7 +156,7 @@ static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, | |||
156 | 156 | ||
157 | *old = dev_graft_qdisc(dev_queue, new); | 157 | *old = dev_graft_qdisc(dev_queue, new); |
158 | if (new) | 158 | if (new) |
159 | new->flags |= TCQ_F_ONETXQUEUE; | 159 | new->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; |
160 | if (dev->flags & IFF_UP) | 160 | if (dev->flags & IFF_UP) |
161 | dev_activate(dev); | 161 | dev_activate(dev); |
162 | return 0; | 162 | return 0; |
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c index 3811a745452c..ad70ecf57ce7 100644 --- a/net/sched/sch_mqprio.c +++ b/net/sched/sch_mqprio.c | |||
@@ -132,7 +132,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) | |||
132 | goto err; | 132 | goto err; |
133 | } | 133 | } |
134 | priv->qdiscs[i] = qdisc; | 134 | priv->qdiscs[i] = qdisc; |
135 | qdisc->flags |= TCQ_F_ONETXQUEUE; | 135 | qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; |
136 | } | 136 | } |
137 | 137 | ||
138 | /* If the mqprio options indicate that hardware should own | 138 | /* If the mqprio options indicate that hardware should own |
@@ -209,7 +209,7 @@ static int mqprio_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, | |||
209 | *old = dev_graft_qdisc(dev_queue, new); | 209 | *old = dev_graft_qdisc(dev_queue, new); |
210 | 210 | ||
211 | if (new) | 211 | if (new) |
212 | new->flags |= TCQ_F_ONETXQUEUE; | 212 | new->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; |
213 | 213 | ||
214 | if (dev->flags & IFF_UP) | 214 | if (dev->flags & IFF_UP) |
215 | dev_activate(dev); | 215 | dev_activate(dev); |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 559afd0ee7de..2bf8ec92dde4 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -383,6 +383,7 @@ void sctp_association_free(struct sctp_association *asoc) | |||
383 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 383 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
384 | transport = list_entry(pos, struct sctp_transport, transports); | 384 | transport = list_entry(pos, struct sctp_transport, transports); |
385 | list_del_rcu(pos); | 385 | list_del_rcu(pos); |
386 | sctp_unhash_transport(transport); | ||
386 | sctp_transport_free(transport); | 387 | sctp_transport_free(transport); |
387 | } | 388 | } |
388 | 389 | ||
@@ -500,6 +501,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, | |||
500 | 501 | ||
501 | /* Remove this peer from the list. */ | 502 | /* Remove this peer from the list. */ |
502 | list_del_rcu(&peer->transports); | 503 | list_del_rcu(&peer->transports); |
504 | /* Remove this peer from the transport hashtable */ | ||
505 | sctp_unhash_transport(peer); | ||
503 | 506 | ||
504 | /* Get the first transport of asoc. */ | 507 | /* Get the first transport of asoc. */ |
505 | pos = asoc->peer.transport_addr_list.next; | 508 | pos = asoc->peer.transport_addr_list.next; |
@@ -699,6 +702,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
699 | /* Attach the remote transport to our asoc. */ | 702 | /* Attach the remote transport to our asoc. */ |
700 | list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list); | 703 | list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list); |
701 | asoc->peer.transport_count++; | 704 | asoc->peer.transport_count++; |
705 | /* Add this peer into the transport hashtable */ | ||
706 | sctp_hash_transport(peer); | ||
702 | 707 | ||
703 | /* If we do not yet have a primary path, set one. */ | 708 | /* If we do not yet have a primary path, set one. */ |
704 | if (!asoc->peer.primary_path) { | 709 | if (!asoc->peer.primary_path) { |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 9da76ba4d10f..52838eaa1582 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -314,21 +314,16 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, | |||
314 | } | 314 | } |
315 | 315 | ||
316 | /* Find the association that goes with this chunk. | 316 | /* Find the association that goes with this chunk. |
317 | * We do a linear search of the associations for this endpoint. | 317 | * We lookup the transport from hashtable at first, then get association |
318 | * We return the matching transport address too. | 318 | * through t->assoc. |
319 | */ | 319 | */ |
320 | static struct sctp_association *__sctp_endpoint_lookup_assoc( | 320 | struct sctp_association *sctp_endpoint_lookup_assoc( |
321 | const struct sctp_endpoint *ep, | 321 | const struct sctp_endpoint *ep, |
322 | const union sctp_addr *paddr, | 322 | const union sctp_addr *paddr, |
323 | struct sctp_transport **transport) | 323 | struct sctp_transport **transport) |
324 | { | 324 | { |
325 | struct sctp_association *asoc = NULL; | 325 | struct sctp_association *asoc = NULL; |
326 | struct sctp_association *tmp; | 326 | struct sctp_transport *t; |
327 | struct sctp_transport *t = NULL; | ||
328 | struct sctp_hashbucket *head; | ||
329 | struct sctp_ep_common *epb; | ||
330 | int hash; | ||
331 | int rport; | ||
332 | 327 | ||
333 | *transport = NULL; | 328 | *transport = NULL; |
334 | 329 | ||
@@ -337,45 +332,16 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( | |||
337 | */ | 332 | */ |
338 | if (!ep->base.bind_addr.port) | 333 | if (!ep->base.bind_addr.port) |
339 | goto out; | 334 | goto out; |
335 | t = sctp_epaddr_lookup_transport(ep, paddr); | ||
336 | if (!t || t->asoc->temp) | ||
337 | goto out; | ||
340 | 338 | ||
341 | rport = ntohs(paddr->v4.sin_port); | 339 | *transport = t; |
342 | 340 | asoc = t->asoc; | |
343 | hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port, | ||
344 | rport); | ||
345 | head = &sctp_assoc_hashtable[hash]; | ||
346 | read_lock(&head->lock); | ||
347 | sctp_for_each_hentry(epb, &head->chain) { | ||
348 | tmp = sctp_assoc(epb); | ||
349 | if (tmp->ep != ep || rport != tmp->peer.port) | ||
350 | continue; | ||
351 | |||
352 | t = sctp_assoc_lookup_paddr(tmp, paddr); | ||
353 | if (t) { | ||
354 | asoc = tmp; | ||
355 | *transport = t; | ||
356 | break; | ||
357 | } | ||
358 | } | ||
359 | read_unlock(&head->lock); | ||
360 | out: | 341 | out: |
361 | return asoc; | 342 | return asoc; |
362 | } | 343 | } |
363 | 344 | ||
364 | /* Lookup association on an endpoint based on a peer address. BH-safe. */ | ||
365 | struct sctp_association *sctp_endpoint_lookup_assoc( | ||
366 | const struct sctp_endpoint *ep, | ||
367 | const union sctp_addr *paddr, | ||
368 | struct sctp_transport **transport) | ||
369 | { | ||
370 | struct sctp_association *asoc; | ||
371 | |||
372 | local_bh_disable(); | ||
373 | asoc = __sctp_endpoint_lookup_assoc(ep, paddr, transport); | ||
374 | local_bh_enable(); | ||
375 | |||
376 | return asoc; | ||
377 | } | ||
378 | |||
379 | /* Look for any peeled off association from the endpoint that matches the | 345 | /* Look for any peeled off association from the endpoint that matches the |
380 | * given peer address. | 346 | * given peer address. |
381 | */ | 347 | */ |
diff --git a/net/sctp/input.c b/net/sctp/input.c index b6493b3f11a9..d9a6e66c5c8a 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -782,65 +782,135 @@ hit: | |||
782 | return ep; | 782 | return ep; |
783 | } | 783 | } |
784 | 784 | ||
785 | /* Insert association into the hash table. */ | 785 | /* rhashtable for transport */ |
786 | static void __sctp_hash_established(struct sctp_association *asoc) | 786 | struct sctp_hash_cmp_arg { |
787 | const union sctp_addr *laddr; | ||
788 | const union sctp_addr *paddr; | ||
789 | const struct net *net; | ||
790 | }; | ||
791 | |||
792 | static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg, | ||
793 | const void *ptr) | ||
787 | { | 794 | { |
788 | struct net *net = sock_net(asoc->base.sk); | 795 | const struct sctp_hash_cmp_arg *x = arg->key; |
789 | struct sctp_ep_common *epb; | 796 | const struct sctp_transport *t = ptr; |
790 | struct sctp_hashbucket *head; | 797 | struct sctp_association *asoc = t->asoc; |
798 | const struct net *net = x->net; | ||
791 | 799 | ||
792 | epb = &asoc->base; | 800 | if (x->laddr->v4.sin_port != htons(asoc->base.bind_addr.port)) |
801 | return 1; | ||
802 | if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr)) | ||
803 | return 1; | ||
804 | if (!net_eq(sock_net(asoc->base.sk), net)) | ||
805 | return 1; | ||
806 | if (!sctp_bind_addr_match(&asoc->base.bind_addr, | ||
807 | x->laddr, sctp_sk(asoc->base.sk))) | ||
808 | return 1; | ||
793 | 809 | ||
794 | /* Calculate which chain this entry will belong to. */ | 810 | return 0; |
795 | epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port, | 811 | } |
796 | asoc->peer.port); | ||
797 | 812 | ||
798 | head = &sctp_assoc_hashtable[epb->hashent]; | 813 | static inline u32 sctp_hash_obj(const void *data, u32 len, u32 seed) |
814 | { | ||
815 | const struct sctp_transport *t = data; | ||
816 | const union sctp_addr *paddr = &t->ipaddr; | ||
817 | const struct net *net = sock_net(t->asoc->base.sk); | ||
818 | u16 lport = htons(t->asoc->base.bind_addr.port); | ||
819 | u32 addr; | ||
820 | |||
821 | if (paddr->sa.sa_family == AF_INET6) | ||
822 | addr = jhash(&paddr->v6.sin6_addr, 16, seed); | ||
823 | else | ||
824 | addr = paddr->v4.sin_addr.s_addr; | ||
799 | 825 | ||
800 | write_lock(&head->lock); | 826 | return jhash_3words(addr, ((__u32)paddr->v4.sin_port) << 16 | |
801 | hlist_add_head(&epb->node, &head->chain); | 827 | (__force __u32)lport, net_hash_mix(net), seed); |
802 | write_unlock(&head->lock); | ||
803 | } | 828 | } |
804 | 829 | ||
805 | /* Add an association to the hash. Local BH-safe. */ | 830 | static inline u32 sctp_hash_key(const void *data, u32 len, u32 seed) |
806 | void sctp_hash_established(struct sctp_association *asoc) | ||
807 | { | 831 | { |
808 | if (asoc->temp) | 832 | const struct sctp_hash_cmp_arg *x = data; |
809 | return; | 833 | const union sctp_addr *paddr = x->paddr; |
834 | const struct net *net = x->net; | ||
835 | u16 lport = x->laddr->v4.sin_port; | ||
836 | u32 addr; | ||
837 | |||
838 | if (paddr->sa.sa_family == AF_INET6) | ||
839 | addr = jhash(&paddr->v6.sin6_addr, 16, seed); | ||
840 | else | ||
841 | addr = paddr->v4.sin_addr.s_addr; | ||
810 | 842 | ||
811 | local_bh_disable(); | 843 | return jhash_3words(addr, ((__u32)paddr->v4.sin_port) << 16 | |
812 | __sctp_hash_established(asoc); | 844 | (__force __u32)lport, net_hash_mix(net), seed); |
813 | local_bh_enable(); | ||
814 | } | 845 | } |
815 | 846 | ||
816 | /* Remove association from the hash table. */ | 847 | static const struct rhashtable_params sctp_hash_params = { |
817 | static void __sctp_unhash_established(struct sctp_association *asoc) | 848 | .head_offset = offsetof(struct sctp_transport, node), |
849 | .hashfn = sctp_hash_key, | ||
850 | .obj_hashfn = sctp_hash_obj, | ||
851 | .obj_cmpfn = sctp_hash_cmp, | ||
852 | .automatic_shrinking = true, | ||
853 | }; | ||
854 | |||
855 | int sctp_transport_hashtable_init(void) | ||
818 | { | 856 | { |
819 | struct net *net = sock_net(asoc->base.sk); | 857 | return rhashtable_init(&sctp_transport_hashtable, &sctp_hash_params); |
820 | struct sctp_hashbucket *head; | 858 | } |
821 | struct sctp_ep_common *epb; | ||
822 | 859 | ||
823 | epb = &asoc->base; | 860 | void sctp_transport_hashtable_destroy(void) |
861 | { | ||
862 | rhashtable_destroy(&sctp_transport_hashtable); | ||
863 | } | ||
824 | 864 | ||
825 | epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port, | 865 | void sctp_hash_transport(struct sctp_transport *t) |
826 | asoc->peer.port); | 866 | { |
867 | struct sctp_sockaddr_entry *addr; | ||
868 | struct sctp_hash_cmp_arg arg; | ||
869 | |||
870 | addr = list_entry(t->asoc->base.bind_addr.address_list.next, | ||
871 | struct sctp_sockaddr_entry, list); | ||
872 | arg.laddr = &addr->a; | ||
873 | arg.paddr = &t->ipaddr; | ||
874 | arg.net = sock_net(t->asoc->base.sk); | ||
875 | |||
876 | reinsert: | ||
877 | if (rhashtable_lookup_insert_key(&sctp_transport_hashtable, &arg, | ||
878 | &t->node, sctp_hash_params) == -EBUSY) | ||
879 | goto reinsert; | ||
880 | } | ||
827 | 881 | ||
828 | head = &sctp_assoc_hashtable[epb->hashent]; | 882 | void sctp_unhash_transport(struct sctp_transport *t) |
883 | { | ||
884 | rhashtable_remove_fast(&sctp_transport_hashtable, &t->node, | ||
885 | sctp_hash_params); | ||
886 | } | ||
829 | 887 | ||
830 | write_lock(&head->lock); | 888 | struct sctp_transport *sctp_addrs_lookup_transport( |
831 | hlist_del_init(&epb->node); | 889 | struct net *net, |
832 | write_unlock(&head->lock); | 890 | const union sctp_addr *laddr, |
891 | const union sctp_addr *paddr) | ||
892 | { | ||
893 | struct sctp_hash_cmp_arg arg = { | ||
894 | .laddr = laddr, | ||
895 | .paddr = paddr, | ||
896 | .net = net, | ||
897 | }; | ||
898 | |||
899 | return rhashtable_lookup_fast(&sctp_transport_hashtable, &arg, | ||
900 | sctp_hash_params); | ||
833 | } | 901 | } |
834 | 902 | ||
835 | /* Remove association from the hash table. Local BH-safe. */ | 903 | struct sctp_transport *sctp_epaddr_lookup_transport( |
836 | void sctp_unhash_established(struct sctp_association *asoc) | 904 | const struct sctp_endpoint *ep, |
905 | const union sctp_addr *paddr) | ||
837 | { | 906 | { |
838 | if (asoc->temp) | 907 | struct sctp_sockaddr_entry *addr; |
839 | return; | 908 | struct net *net = sock_net(ep->base.sk); |
840 | 909 | ||
841 | local_bh_disable(); | 910 | addr = list_entry(ep->base.bind_addr.address_list.next, |
842 | __sctp_unhash_established(asoc); | 911 | struct sctp_sockaddr_entry, list); |
843 | local_bh_enable(); | 912 | |
913 | return sctp_addrs_lookup_transport(net, &addr->a, paddr); | ||
844 | } | 914 | } |
845 | 915 | ||
846 | /* Look up an association. */ | 916 | /* Look up an association. */ |
@@ -850,38 +920,19 @@ static struct sctp_association *__sctp_lookup_association( | |||
850 | const union sctp_addr *peer, | 920 | const union sctp_addr *peer, |
851 | struct sctp_transport **pt) | 921 | struct sctp_transport **pt) |
852 | { | 922 | { |
853 | struct sctp_hashbucket *head; | 923 | struct sctp_transport *t; |
854 | struct sctp_ep_common *epb; | ||
855 | struct sctp_association *asoc; | ||
856 | struct sctp_transport *transport; | ||
857 | int hash; | ||
858 | 924 | ||
859 | /* Optimize here for direct hit, only listening connections can | 925 | t = sctp_addrs_lookup_transport(net, local, peer); |
860 | * have wildcards anyways. | 926 | if (!t || t->dead || t->asoc->temp) |
861 | */ | 927 | return NULL; |
862 | hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port), | ||
863 | ntohs(peer->v4.sin_port)); | ||
864 | head = &sctp_assoc_hashtable[hash]; | ||
865 | read_lock(&head->lock); | ||
866 | sctp_for_each_hentry(epb, &head->chain) { | ||
867 | asoc = sctp_assoc(epb); | ||
868 | transport = sctp_assoc_is_match(asoc, net, local, peer); | ||
869 | if (transport) | ||
870 | goto hit; | ||
871 | } | ||
872 | |||
873 | read_unlock(&head->lock); | ||
874 | 928 | ||
875 | return NULL; | 929 | sctp_association_hold(t->asoc); |
930 | *pt = t; | ||
876 | 931 | ||
877 | hit: | 932 | return t->asoc; |
878 | *pt = transport; | ||
879 | sctp_association_hold(asoc); | ||
880 | read_unlock(&head->lock); | ||
881 | return asoc; | ||
882 | } | 933 | } |
883 | 934 | ||
884 | /* Look up an association. BH-safe. */ | 935 | /* Look up an association. protected by RCU read lock */ |
885 | static | 936 | static |
886 | struct sctp_association *sctp_lookup_association(struct net *net, | 937 | struct sctp_association *sctp_lookup_association(struct net *net, |
887 | const union sctp_addr *laddr, | 938 | const union sctp_addr *laddr, |
@@ -890,9 +941,9 @@ struct sctp_association *sctp_lookup_association(struct net *net, | |||
890 | { | 941 | { |
891 | struct sctp_association *asoc; | 942 | struct sctp_association *asoc; |
892 | 943 | ||
893 | local_bh_disable(); | 944 | rcu_read_lock(); |
894 | asoc = __sctp_lookup_association(net, laddr, paddr, transportp); | 945 | asoc = __sctp_lookup_association(net, laddr, paddr, transportp); |
895 | local_bh_enable(); | 946 | rcu_read_unlock(); |
896 | 947 | ||
897 | return asoc; | 948 | return asoc; |
898 | } | 949 | } |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index e917d27328ea..ec529121f38a 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -209,6 +209,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
209 | struct sock *sk = skb->sk; | 209 | struct sock *sk = skb->sk; |
210 | struct ipv6_pinfo *np = inet6_sk(sk); | 210 | struct ipv6_pinfo *np = inet6_sk(sk); |
211 | struct flowi6 *fl6 = &transport->fl.u.ip6; | 211 | struct flowi6 *fl6 = &transport->fl.u.ip6; |
212 | int res; | ||
212 | 213 | ||
213 | pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb, | 214 | pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb, |
214 | skb->len, &fl6->saddr, &fl6->daddr); | 215 | skb->len, &fl6->saddr, &fl6->daddr); |
@@ -220,7 +221,10 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
220 | 221 | ||
221 | SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); | 222 | SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); |
222 | 223 | ||
223 | return ip6_xmit(sk, skb, fl6, np->opt, np->tclass); | 224 | rcu_read_lock(); |
225 | res = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), np->tclass); | ||
226 | rcu_read_unlock(); | ||
227 | return res; | ||
224 | } | 228 | } |
225 | 229 | ||
226 | /* Returns the dst cache entry for the given source and destination ip | 230 | /* Returns the dst cache entry for the given source and destination ip |
@@ -262,7 +266,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
262 | pr_debug("src=%pI6 - ", &fl6->saddr); | 266 | pr_debug("src=%pI6 - ", &fl6->saddr); |
263 | } | 267 | } |
264 | 268 | ||
265 | final_p = fl6_update_dst(fl6, np->opt, &final); | 269 | rcu_read_lock(); |
270 | final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); | ||
271 | rcu_read_unlock(); | ||
272 | |||
266 | dst = ip6_dst_lookup_flow(sk, fl6, final_p); | 273 | dst = ip6_dst_lookup_flow(sk, fl6, final_p); |
267 | if (!asoc || saddr) | 274 | if (!asoc || saddr) |
268 | goto out; | 275 | goto out; |
@@ -316,14 +323,13 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
316 | } | 323 | } |
317 | } | 324 | } |
318 | } | 325 | } |
319 | rcu_read_unlock(); | ||
320 | |||
321 | if (baddr) { | 326 | if (baddr) { |
322 | fl6->saddr = baddr->v6.sin6_addr; | 327 | fl6->saddr = baddr->v6.sin6_addr; |
323 | fl6->fl6_sport = baddr->v6.sin6_port; | 328 | fl6->fl6_sport = baddr->v6.sin6_port; |
324 | final_p = fl6_update_dst(fl6, np->opt, &final); | 329 | final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); |
325 | dst = ip6_dst_lookup_flow(sk, fl6, final_p); | 330 | dst = ip6_dst_lookup_flow(sk, fl6, final_p); |
326 | } | 331 | } |
332 | rcu_read_unlock(); | ||
327 | 333 | ||
328 | out: | 334 | out: |
329 | if (!IS_ERR_OR_NULL(dst)) { | 335 | if (!IS_ERR_OR_NULL(dst)) { |
@@ -635,6 +641,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
635 | struct sock *newsk; | 641 | struct sock *newsk; |
636 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); | 642 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); |
637 | struct sctp6_sock *newsctp6sk; | 643 | struct sctp6_sock *newsctp6sk; |
644 | struct ipv6_txoptions *opt; | ||
638 | 645 | ||
639 | newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, 0); | 646 | newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, 0); |
640 | if (!newsk) | 647 | if (!newsk) |
@@ -654,6 +661,13 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
654 | 661 | ||
655 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); | 662 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); |
656 | 663 | ||
664 | rcu_read_lock(); | ||
665 | opt = rcu_dereference(np->opt); | ||
666 | if (opt) | ||
667 | opt = ipv6_dup_options(newsk, opt); | ||
668 | RCU_INIT_POINTER(newnp->opt, opt); | ||
669 | rcu_read_unlock(); | ||
670 | |||
657 | /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() | 671 | /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() |
658 | * and getpeername(). | 672 | * and getpeername(). |
659 | */ | 673 | */ |
diff --git a/net/sctp/output.c b/net/sctp/output.c index abe7c2db2412..9d610eddd19e 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -534,7 +534,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
534 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. | 534 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. |
535 | */ | 535 | */ |
536 | if (!sctp_checksum_disable) { | 536 | if (!sctp_checksum_disable) { |
537 | if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || | 537 | if (!(dst->dev->features & NETIF_F_SCTP_CRC) || |
538 | (dst_xfrm(dst) != NULL) || packet->ipfragok) { | 538 | (dst_xfrm(dst) != NULL) || packet->ipfragok) { |
539 | sh->checksum = sctp_compute_cksum(nskb, 0); | 539 | sh->checksum = sctp_compute_cksum(nskb, 0); |
540 | } else { | 540 | } else { |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 7e8f0a117106..c0380cfb16ae 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -324,6 +324,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
324 | sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : | 324 | sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : |
325 | "illegal chunk"); | 325 | "illegal chunk"); |
326 | 326 | ||
327 | sctp_chunk_hold(chunk); | ||
327 | sctp_outq_tail_data(q, chunk); | 328 | sctp_outq_tail_data(q, chunk); |
328 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) | 329 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) |
329 | SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS); | 330 | SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS); |
@@ -1251,6 +1252,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
1251 | */ | 1252 | */ |
1252 | 1253 | ||
1253 | sack_a_rwnd = ntohl(sack->a_rwnd); | 1254 | sack_a_rwnd = ntohl(sack->a_rwnd); |
1255 | asoc->peer.zero_window_announced = !sack_a_rwnd; | ||
1254 | outstanding = q->outstanding_bytes; | 1256 | outstanding = q->outstanding_bytes; |
1255 | 1257 | ||
1256 | if (outstanding < sack_a_rwnd) | 1258 | if (outstanding < sack_a_rwnd) |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 0697eda5aed8..dfa7eeccb537 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -281,88 +281,136 @@ void sctp_eps_proc_exit(struct net *net) | |||
281 | remove_proc_entry("eps", net->sctp.proc_net_sctp); | 281 | remove_proc_entry("eps", net->sctp.proc_net_sctp); |
282 | } | 282 | } |
283 | 283 | ||
284 | struct sctp_ht_iter { | ||
285 | struct seq_net_private p; | ||
286 | struct rhashtable_iter hti; | ||
287 | }; | ||
284 | 288 | ||
285 | static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) | 289 | static struct sctp_transport *sctp_transport_get_next(struct seq_file *seq) |
286 | { | 290 | { |
287 | if (*pos >= sctp_assoc_hashsize) | 291 | struct sctp_ht_iter *iter = seq->private; |
288 | return NULL; | 292 | struct sctp_transport *t; |
289 | 293 | ||
290 | if (*pos < 0) | 294 | t = rhashtable_walk_next(&iter->hti); |
291 | *pos = 0; | 295 | for (; t; t = rhashtable_walk_next(&iter->hti)) { |
296 | if (IS_ERR(t)) { | ||
297 | if (PTR_ERR(t) == -EAGAIN) | ||
298 | continue; | ||
299 | break; | ||
300 | } | ||
292 | 301 | ||
293 | if (*pos == 0) | 302 | if (net_eq(sock_net(t->asoc->base.sk), seq_file_net(seq)) && |
294 | seq_printf(seq, " ASSOC SOCK STY SST ST HBKT " | 303 | t->asoc->peer.primary_path == t) |
295 | "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT " | 304 | break; |
296 | "RPORT LADDRS <-> RADDRS " | 305 | } |
297 | "HBINT INS OUTS MAXRT T1X T2X RTXC " | ||
298 | "wmema wmemq sndbuf rcvbuf\n"); | ||
299 | 306 | ||
300 | return (void *)pos; | 307 | return t; |
301 | } | 308 | } |
302 | 309 | ||
303 | static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) | 310 | static struct sctp_transport *sctp_transport_get_idx(struct seq_file *seq, |
311 | loff_t pos) | ||
312 | { | ||
313 | void *obj; | ||
314 | |||
315 | while (pos && (obj = sctp_transport_get_next(seq)) && !IS_ERR(obj)) | ||
316 | pos--; | ||
317 | |||
318 | return obj; | ||
319 | } | ||
320 | |||
321 | static int sctp_transport_walk_start(struct seq_file *seq) | ||
304 | { | 322 | { |
323 | struct sctp_ht_iter *iter = seq->private; | ||
324 | int err; | ||
325 | |||
326 | err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti); | ||
327 | if (err) | ||
328 | return err; | ||
329 | |||
330 | err = rhashtable_walk_start(&iter->hti); | ||
331 | |||
332 | return err == -EAGAIN ? 0 : err; | ||
305 | } | 333 | } |
306 | 334 | ||
335 | static void sctp_transport_walk_stop(struct seq_file *seq) | ||
336 | { | ||
337 | struct sctp_ht_iter *iter = seq->private; | ||
338 | |||
339 | rhashtable_walk_stop(&iter->hti); | ||
340 | rhashtable_walk_exit(&iter->hti); | ||
341 | } | ||
342 | |||
343 | static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) | ||
344 | { | ||
345 | int err = sctp_transport_walk_start(seq); | ||
346 | |||
347 | if (err) | ||
348 | return ERR_PTR(err); | ||
349 | |||
350 | return *pos ? sctp_transport_get_idx(seq, *pos) : SEQ_START_TOKEN; | ||
351 | } | ||
352 | |||
353 | static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) | ||
354 | { | ||
355 | sctp_transport_walk_stop(seq); | ||
356 | } | ||
307 | 357 | ||
308 | static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 358 | static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
309 | { | 359 | { |
310 | if (++*pos >= sctp_assoc_hashsize) | 360 | ++*pos; |
311 | return NULL; | ||
312 | 361 | ||
313 | return pos; | 362 | return sctp_transport_get_next(seq); |
314 | } | 363 | } |
315 | 364 | ||
316 | /* Display sctp associations (/proc/net/sctp/assocs). */ | 365 | /* Display sctp associations (/proc/net/sctp/assocs). */ |
317 | static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | 366 | static int sctp_assocs_seq_show(struct seq_file *seq, void *v) |
318 | { | 367 | { |
319 | struct sctp_hashbucket *head; | 368 | struct sctp_transport *transport; |
320 | struct sctp_ep_common *epb; | ||
321 | struct sctp_association *assoc; | 369 | struct sctp_association *assoc; |
370 | struct sctp_ep_common *epb; | ||
322 | struct sock *sk; | 371 | struct sock *sk; |
323 | int hash = *(loff_t *)v; | ||
324 | |||
325 | if (hash >= sctp_assoc_hashsize) | ||
326 | return -ENOMEM; | ||
327 | 372 | ||
328 | head = &sctp_assoc_hashtable[hash]; | 373 | if (v == SEQ_START_TOKEN) { |
329 | local_bh_disable(); | 374 | seq_printf(seq, " ASSOC SOCK STY SST ST HBKT " |
330 | read_lock(&head->lock); | 375 | "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT " |
331 | sctp_for_each_hentry(epb, &head->chain) { | 376 | "RPORT LADDRS <-> RADDRS " |
332 | assoc = sctp_assoc(epb); | 377 | "HBINT INS OUTS MAXRT T1X T2X RTXC " |
333 | sk = epb->sk; | 378 | "wmema wmemq sndbuf rcvbuf\n"); |
334 | if (!net_eq(sock_net(sk), seq_file_net(seq))) | 379 | return 0; |
335 | continue; | ||
336 | seq_printf(seq, | ||
337 | "%8pK %8pK %-3d %-3d %-2d %-4d " | ||
338 | "%4d %8d %8d %7u %5lu %-5d %5d ", | ||
339 | assoc, sk, sctp_sk(sk)->type, sk->sk_state, | ||
340 | assoc->state, hash, | ||
341 | assoc->assoc_id, | ||
342 | assoc->sndbuf_used, | ||
343 | atomic_read(&assoc->rmem_alloc), | ||
344 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), | ||
345 | sock_i_ino(sk), | ||
346 | epb->bind_addr.port, | ||
347 | assoc->peer.port); | ||
348 | seq_printf(seq, " "); | ||
349 | sctp_seq_dump_local_addrs(seq, epb); | ||
350 | seq_printf(seq, "<-> "); | ||
351 | sctp_seq_dump_remote_addrs(seq, assoc); | ||
352 | seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d " | ||
353 | "%8d %8d %8d %8d", | ||
354 | assoc->hbinterval, assoc->c.sinit_max_instreams, | ||
355 | assoc->c.sinit_num_ostreams, assoc->max_retrans, | ||
356 | assoc->init_retries, assoc->shutdown_retries, | ||
357 | assoc->rtx_data_chunks, | ||
358 | atomic_read(&sk->sk_wmem_alloc), | ||
359 | sk->sk_wmem_queued, | ||
360 | sk->sk_sndbuf, | ||
361 | sk->sk_rcvbuf); | ||
362 | seq_printf(seq, "\n"); | ||
363 | } | 380 | } |
364 | read_unlock(&head->lock); | 381 | |
365 | local_bh_enable(); | 382 | transport = (struct sctp_transport *)v; |
383 | assoc = transport->asoc; | ||
384 | epb = &assoc->base; | ||
385 | sk = epb->sk; | ||
386 | |||
387 | seq_printf(seq, | ||
388 | "%8pK %8pK %-3d %-3d %-2d %-4d " | ||
389 | "%4d %8d %8d %7u %5lu %-5d %5d ", | ||
390 | assoc, sk, sctp_sk(sk)->type, sk->sk_state, | ||
391 | assoc->state, 0, | ||
392 | assoc->assoc_id, | ||
393 | assoc->sndbuf_used, | ||
394 | atomic_read(&assoc->rmem_alloc), | ||
395 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), | ||
396 | sock_i_ino(sk), | ||
397 | epb->bind_addr.port, | ||
398 | assoc->peer.port); | ||
399 | seq_printf(seq, " "); | ||
400 | sctp_seq_dump_local_addrs(seq, epb); | ||
401 | seq_printf(seq, "<-> "); | ||
402 | sctp_seq_dump_remote_addrs(seq, assoc); | ||
403 | seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d " | ||
404 | "%8d %8d %8d %8d", | ||
405 | assoc->hbinterval, assoc->c.sinit_max_instreams, | ||
406 | assoc->c.sinit_num_ostreams, assoc->max_retrans, | ||
407 | assoc->init_retries, assoc->shutdown_retries, | ||
408 | assoc->rtx_data_chunks, | ||
409 | atomic_read(&sk->sk_wmem_alloc), | ||
410 | sk->sk_wmem_queued, | ||
411 | sk->sk_sndbuf, | ||
412 | sk->sk_rcvbuf); | ||
413 | seq_printf(seq, "\n"); | ||
366 | 414 | ||
367 | return 0; | 415 | return 0; |
368 | } | 416 | } |
@@ -378,7 +426,7 @@ static const struct seq_operations sctp_assoc_ops = { | |||
378 | static int sctp_assocs_seq_open(struct inode *inode, struct file *file) | 426 | static int sctp_assocs_seq_open(struct inode *inode, struct file *file) |
379 | { | 427 | { |
380 | return seq_open_net(inode, file, &sctp_assoc_ops, | 428 | return seq_open_net(inode, file, &sctp_assoc_ops, |
381 | sizeof(struct seq_net_private)); | 429 | sizeof(struct sctp_ht_iter)); |
382 | } | 430 | } |
383 | 431 | ||
384 | static const struct file_operations sctp_assocs_seq_fops = { | 432 | static const struct file_operations sctp_assocs_seq_fops = { |
@@ -409,112 +457,94 @@ void sctp_assocs_proc_exit(struct net *net) | |||
409 | 457 | ||
410 | static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) | 458 | static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) |
411 | { | 459 | { |
412 | if (*pos >= sctp_assoc_hashsize) | 460 | int err = sctp_transport_walk_start(seq); |
413 | return NULL; | ||
414 | |||
415 | if (*pos < 0) | ||
416 | *pos = 0; | ||
417 | 461 | ||
418 | if (*pos == 0) | 462 | if (err) |
419 | seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " | 463 | return ERR_PTR(err); |
420 | "REM_ADDR_RTX START STATE\n"); | ||
421 | 464 | ||
422 | return (void *)pos; | 465 | return *pos ? sctp_transport_get_idx(seq, *pos) : SEQ_START_TOKEN; |
423 | } | 466 | } |
424 | 467 | ||
425 | static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 468 | static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
426 | { | 469 | { |
427 | if (++*pos >= sctp_assoc_hashsize) | 470 | ++*pos; |
428 | return NULL; | ||
429 | 471 | ||
430 | return pos; | 472 | return sctp_transport_get_next(seq); |
431 | } | 473 | } |
432 | 474 | ||
433 | static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) | 475 | static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) |
434 | { | 476 | { |
477 | sctp_transport_walk_stop(seq); | ||
435 | } | 478 | } |
436 | 479 | ||
437 | static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) | 480 | static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) |
438 | { | 481 | { |
439 | struct sctp_hashbucket *head; | ||
440 | struct sctp_ep_common *epb; | ||
441 | struct sctp_association *assoc; | 482 | struct sctp_association *assoc; |
442 | struct sctp_transport *tsp; | 483 | struct sctp_transport *tsp; |
443 | int hash = *(loff_t *)v; | ||
444 | 484 | ||
445 | if (hash >= sctp_assoc_hashsize) | 485 | if (v == SEQ_START_TOKEN) { |
446 | return -ENOMEM; | 486 | seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " |
487 | "REM_ADDR_RTX START STATE\n"); | ||
488 | return 0; | ||
489 | } | ||
447 | 490 | ||
448 | head = &sctp_assoc_hashtable[hash]; | 491 | tsp = (struct sctp_transport *)v; |
449 | local_bh_disable(); | 492 | assoc = tsp->asoc; |
450 | read_lock(&head->lock); | 493 | |
451 | rcu_read_lock(); | 494 | list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, |
452 | sctp_for_each_hentry(epb, &head->chain) { | 495 | transports) { |
453 | if (!net_eq(sock_net(epb->sk), seq_file_net(seq))) | 496 | if (tsp->dead) |
454 | continue; | 497 | continue; |
455 | assoc = sctp_assoc(epb); | 498 | /* |
456 | list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, | 499 | * The remote address (ADDR) |
457 | transports) { | 500 | */ |
458 | if (tsp->dead) | 501 | tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr); |
459 | continue; | 502 | seq_printf(seq, " "); |
503 | /* | ||
504 | * The association ID (ASSOC_ID) | ||
505 | */ | ||
506 | seq_printf(seq, "%d ", tsp->asoc->assoc_id); | ||
507 | |||
508 | /* | ||
509 | * If the Heartbeat is active (HB_ACT) | ||
510 | * Note: 1 = Active, 0 = Inactive | ||
511 | */ | ||
512 | seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer)); | ||
513 | |||
514 | /* | ||
515 | * Retransmit time out (RTO) | ||
516 | */ | ||
517 | seq_printf(seq, "%lu ", tsp->rto); | ||
518 | |||
519 | /* | ||
520 | * Maximum path retransmit count (PATH_MAX_RTX) | ||
521 | */ | ||
522 | seq_printf(seq, "%d ", tsp->pathmaxrxt); | ||
523 | |||
524 | /* | ||
525 | * remote address retransmit count (REM_ADDR_RTX) | ||
526 | * Note: We don't have a way to tally this at the moment | ||
527 | * so lets just leave it as zero for the moment | ||
528 | */ | ||
529 | seq_puts(seq, "0 "); | ||
530 | |||
531 | /* | ||
532 | * remote address start time (START). This is also not | ||
533 | * currently implemented, but we can record it with a | ||
534 | * jiffies marker in a subsequent patch | ||
535 | */ | ||
536 | seq_puts(seq, "0 "); | ||
537 | |||
538 | /* | ||
539 | * The current state of this destination. I.e. | ||
540 | * SCTP_ACTIVE, SCTP_INACTIVE, ... | ||
541 | */ | ||
542 | seq_printf(seq, "%d", tsp->state); | ||
460 | 543 | ||
461 | /* | 544 | seq_printf(seq, "\n"); |
462 | * The remote address (ADDR) | ||
463 | */ | ||
464 | tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr); | ||
465 | seq_printf(seq, " "); | ||
466 | |||
467 | /* | ||
468 | * The association ID (ASSOC_ID) | ||
469 | */ | ||
470 | seq_printf(seq, "%d ", tsp->asoc->assoc_id); | ||
471 | |||
472 | /* | ||
473 | * If the Heartbeat is active (HB_ACT) | ||
474 | * Note: 1 = Active, 0 = Inactive | ||
475 | */ | ||
476 | seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer)); | ||
477 | |||
478 | /* | ||
479 | * Retransmit time out (RTO) | ||
480 | */ | ||
481 | seq_printf(seq, "%lu ", tsp->rto); | ||
482 | |||
483 | /* | ||
484 | * Maximum path retransmit count (PATH_MAX_RTX) | ||
485 | */ | ||
486 | seq_printf(seq, "%d ", tsp->pathmaxrxt); | ||
487 | |||
488 | /* | ||
489 | * remote address retransmit count (REM_ADDR_RTX) | ||
490 | * Note: We don't have a way to tally this at the moment | ||
491 | * so lets just leave it as zero for the moment | ||
492 | */ | ||
493 | seq_puts(seq, "0 "); | ||
494 | |||
495 | /* | ||
496 | * remote address start time (START). This is also not | ||
497 | * currently implemented, but we can record it with a | ||
498 | * jiffies marker in a subsequent patch | ||
499 | */ | ||
500 | seq_puts(seq, "0 "); | ||
501 | |||
502 | /* | ||
503 | * The current state of this destination. I.e. | ||
504 | * SCTP_ACTIVE, SCTP_INACTIVE, ... | ||
505 | */ | ||
506 | seq_printf(seq, "%d", tsp->state); | ||
507 | |||
508 | seq_printf(seq, "\n"); | ||
509 | } | ||
510 | } | 545 | } |
511 | 546 | ||
512 | rcu_read_unlock(); | ||
513 | read_unlock(&head->lock); | ||
514 | local_bh_enable(); | ||
515 | |||
516 | return 0; | 547 | return 0; |
517 | |||
518 | } | 548 | } |
519 | 549 | ||
520 | static const struct seq_operations sctp_remaddr_ops = { | 550 | static const struct seq_operations sctp_remaddr_ops = { |
@@ -533,7 +563,7 @@ void sctp_remaddr_proc_exit(struct net *net) | |||
533 | static int sctp_remaddr_seq_open(struct inode *inode, struct file *file) | 563 | static int sctp_remaddr_seq_open(struct inode *inode, struct file *file) |
534 | { | 564 | { |
535 | return seq_open_net(inode, file, &sctp_remaddr_ops, | 565 | return seq_open_net(inode, file, &sctp_remaddr_ops, |
536 | sizeof(struct seq_net_private)); | 566 | sizeof(struct sctp_ht_iter)); |
537 | } | 567 | } |
538 | 568 | ||
539 | static const struct file_operations sctp_remaddr_seq_fops = { | 569 | static const struct file_operations sctp_remaddr_seq_fops = { |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 3d9ea9a48289..ab0d538a74ed 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1223,6 +1223,9 @@ static int __net_init sctp_defaults_init(struct net *net) | |||
1223 | /* Max.Burst - 4 */ | 1223 | /* Max.Burst - 4 */ |
1224 | net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST; | 1224 | net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST; |
1225 | 1225 | ||
1226 | /* Enable pf state by default */ | ||
1227 | net->sctp.pf_enable = 1; | ||
1228 | |||
1226 | /* Association.Max.Retrans - 10 attempts | 1229 | /* Association.Max.Retrans - 10 attempts |
1227 | * Path.Max.Retrans - 5 attempts (per destination address) | 1230 | * Path.Max.Retrans - 5 attempts (per destination address) |
1228 | * Max.Init.Retransmits - 8 attempts | 1231 | * Max.Init.Retransmits - 8 attempts |
@@ -1413,24 +1416,6 @@ static __init int sctp_init(void) | |||
1413 | for (order = 0; (1UL << order) < goal; order++) | 1416 | for (order = 0; (1UL << order) < goal; order++) |
1414 | ; | 1417 | ; |
1415 | 1418 | ||
1416 | do { | ||
1417 | sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE / | ||
1418 | sizeof(struct sctp_hashbucket); | ||
1419 | if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0) | ||
1420 | continue; | ||
1421 | sctp_assoc_hashtable = (struct sctp_hashbucket *) | ||
1422 | __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order); | ||
1423 | } while (!sctp_assoc_hashtable && --order > 0); | ||
1424 | if (!sctp_assoc_hashtable) { | ||
1425 | pr_err("Failed association hash alloc\n"); | ||
1426 | status = -ENOMEM; | ||
1427 | goto err_ahash_alloc; | ||
1428 | } | ||
1429 | for (i = 0; i < sctp_assoc_hashsize; i++) { | ||
1430 | rwlock_init(&sctp_assoc_hashtable[i].lock); | ||
1431 | INIT_HLIST_HEAD(&sctp_assoc_hashtable[i].chain); | ||
1432 | } | ||
1433 | |||
1434 | /* Allocate and initialize the endpoint hash table. */ | 1419 | /* Allocate and initialize the endpoint hash table. */ |
1435 | sctp_ep_hashsize = 64; | 1420 | sctp_ep_hashsize = 64; |
1436 | sctp_ep_hashtable = | 1421 | sctp_ep_hashtable = |
@@ -1452,7 +1437,7 @@ static __init int sctp_init(void) | |||
1452 | if ((sctp_port_hashsize > (64 * 1024)) && order > 0) | 1437 | if ((sctp_port_hashsize > (64 * 1024)) && order > 0) |
1453 | continue; | 1438 | continue; |
1454 | sctp_port_hashtable = (struct sctp_bind_hashbucket *) | 1439 | sctp_port_hashtable = (struct sctp_bind_hashbucket *) |
1455 | __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order); | 1440 | __get_free_pages(GFP_KERNEL | __GFP_NOWARN, order); |
1456 | } while (!sctp_port_hashtable && --order > 0); | 1441 | } while (!sctp_port_hashtable && --order > 0); |
1457 | if (!sctp_port_hashtable) { | 1442 | if (!sctp_port_hashtable) { |
1458 | pr_err("Failed bind hash alloc\n"); | 1443 | pr_err("Failed bind hash alloc\n"); |
@@ -1464,8 +1449,10 @@ static __init int sctp_init(void) | |||
1464 | INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); | 1449 | INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); |
1465 | } | 1450 | } |
1466 | 1451 | ||
1467 | pr_info("Hash tables configured (established %d bind %d)\n", | 1452 | if (sctp_transport_hashtable_init()) |
1468 | sctp_assoc_hashsize, sctp_port_hashsize); | 1453 | goto err_thash_alloc; |
1454 | |||
1455 | pr_info("Hash tables configured (bind %d)\n", sctp_port_hashsize); | ||
1469 | 1456 | ||
1470 | sctp_sysctl_register(); | 1457 | sctp_sysctl_register(); |
1471 | 1458 | ||
@@ -1518,12 +1505,10 @@ err_register_defaults: | |||
1518 | get_order(sctp_port_hashsize * | 1505 | get_order(sctp_port_hashsize * |
1519 | sizeof(struct sctp_bind_hashbucket))); | 1506 | sizeof(struct sctp_bind_hashbucket))); |
1520 | err_bhash_alloc: | 1507 | err_bhash_alloc: |
1508 | sctp_transport_hashtable_destroy(); | ||
1509 | err_thash_alloc: | ||
1521 | kfree(sctp_ep_hashtable); | 1510 | kfree(sctp_ep_hashtable); |
1522 | err_ehash_alloc: | 1511 | err_ehash_alloc: |
1523 | free_pages((unsigned long)sctp_assoc_hashtable, | ||
1524 | get_order(sctp_assoc_hashsize * | ||
1525 | sizeof(struct sctp_hashbucket))); | ||
1526 | err_ahash_alloc: | ||
1527 | percpu_counter_destroy(&sctp_sockets_allocated); | 1512 | percpu_counter_destroy(&sctp_sockets_allocated); |
1528 | err_percpu_counter_init: | 1513 | err_percpu_counter_init: |
1529 | kmem_cache_destroy(sctp_chunk_cachep); | 1514 | kmem_cache_destroy(sctp_chunk_cachep); |
@@ -1557,13 +1542,11 @@ static __exit void sctp_exit(void) | |||
1557 | 1542 | ||
1558 | sctp_sysctl_unregister(); | 1543 | sctp_sysctl_unregister(); |
1559 | 1544 | ||
1560 | free_pages((unsigned long)sctp_assoc_hashtable, | ||
1561 | get_order(sctp_assoc_hashsize * | ||
1562 | sizeof(struct sctp_hashbucket))); | ||
1563 | kfree(sctp_ep_hashtable); | ||
1564 | free_pages((unsigned long)sctp_port_hashtable, | 1545 | free_pages((unsigned long)sctp_port_hashtable, |
1565 | get_order(sctp_port_hashsize * | 1546 | get_order(sctp_port_hashsize * |
1566 | sizeof(struct sctp_bind_hashbucket))); | 1547 | sizeof(struct sctp_bind_hashbucket))); |
1548 | kfree(sctp_ep_hashtable); | ||
1549 | sctp_transport_hashtable_destroy(); | ||
1567 | 1550 | ||
1568 | percpu_counter_destroy(&sctp_sockets_allocated); | 1551 | percpu_counter_destroy(&sctp_sockets_allocated); |
1569 | 1552 | ||
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 763e06a55155..5d6a03fad378 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1652,7 +1652,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, | |||
1652 | 1652 | ||
1653 | /* Set an expiration time for the cookie. */ | 1653 | /* Set an expiration time for the cookie. */ |
1654 | cookie->c.expiration = ktime_add(asoc->cookie_life, | 1654 | cookie->c.expiration = ktime_add(asoc->cookie_life, |
1655 | ktime_get()); | 1655 | ktime_get_real()); |
1656 | 1656 | ||
1657 | /* Copy the peer's init packet. */ | 1657 | /* Copy the peer's init packet. */ |
1658 | memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr, | 1658 | memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr, |
@@ -1780,7 +1780,7 @@ no_hmac: | |||
1780 | if (sock_flag(ep->base.sk, SOCK_TIMESTAMP)) | 1780 | if (sock_flag(ep->base.sk, SOCK_TIMESTAMP)) |
1781 | kt = skb_get_ktime(skb); | 1781 | kt = skb_get_ktime(skb); |
1782 | else | 1782 | else |
1783 | kt = ktime_get(); | 1783 | kt = ktime_get_real(); |
1784 | 1784 | ||
1785 | if (!asoc && ktime_before(bear_cookie->expiration, kt)) { | 1785 | if (!asoc && ktime_before(bear_cookie->expiration, kt)) { |
1786 | /* | 1786 | /* |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 6098d4c42fa9..2e21384697c2 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -63,7 +63,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
63 | static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, | 63 | static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, |
64 | sctp_state_t state, | 64 | sctp_state_t state, |
65 | struct sctp_endpoint *ep, | 65 | struct sctp_endpoint *ep, |
66 | struct sctp_association *asoc, | 66 | struct sctp_association **asoc, |
67 | void *event_arg, | 67 | void *event_arg, |
68 | sctp_disposition_t status, | 68 | sctp_disposition_t status, |
69 | sctp_cmd_seq_t *commands, | 69 | sctp_cmd_seq_t *commands, |
@@ -477,6 +477,8 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands, | |||
477 | struct sctp_transport *transport, | 477 | struct sctp_transport *transport, |
478 | int is_hb) | 478 | int is_hb) |
479 | { | 479 | { |
480 | struct net *net = sock_net(asoc->base.sk); | ||
481 | |||
480 | /* The check for association's overall error counter exceeding the | 482 | /* The check for association's overall error counter exceeding the |
481 | * threshold is done in the state function. | 483 | * threshold is done in the state function. |
482 | */ | 484 | */ |
@@ -503,7 +505,8 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands, | |||
503 | * is SCTP_ACTIVE, then mark this transport as Partially Failed, | 505 | * is SCTP_ACTIVE, then mark this transport as Partially Failed, |
504 | * see SCTP Quick Failover Draft, section 5.1 | 506 | * see SCTP Quick Failover Draft, section 5.1 |
505 | */ | 507 | */ |
506 | if ((transport->state == SCTP_ACTIVE) && | 508 | if (net->sctp.pf_enable && |
509 | (transport->state == SCTP_ACTIVE) && | ||
507 | (asoc->pf_retrans < transport->pathmaxrxt) && | 510 | (asoc->pf_retrans < transport->pathmaxrxt) && |
508 | (transport->error_count > asoc->pf_retrans)) { | 511 | (transport->error_count > asoc->pf_retrans)) { |
509 | 512 | ||
@@ -863,7 +866,6 @@ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds, | |||
863 | (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK)) | 866 | (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK)) |
864 | return; | 867 | return; |
865 | 868 | ||
866 | sctp_unhash_established(asoc); | ||
867 | sctp_association_free(asoc); | 869 | sctp_association_free(asoc); |
868 | } | 870 | } |
869 | 871 | ||
@@ -1123,7 +1125,7 @@ int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype, | |||
1123 | debug_post_sfn(); | 1125 | debug_post_sfn(); |
1124 | 1126 | ||
1125 | error = sctp_side_effects(event_type, subtype, state, | 1127 | error = sctp_side_effects(event_type, subtype, state, |
1126 | ep, asoc, event_arg, status, | 1128 | ep, &asoc, event_arg, status, |
1127 | &commands, gfp); | 1129 | &commands, gfp); |
1128 | debug_post_sfx(); | 1130 | debug_post_sfx(); |
1129 | 1131 | ||
@@ -1136,7 +1138,7 @@ int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype, | |||
1136 | static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, | 1138 | static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, |
1137 | sctp_state_t state, | 1139 | sctp_state_t state, |
1138 | struct sctp_endpoint *ep, | 1140 | struct sctp_endpoint *ep, |
1139 | struct sctp_association *asoc, | 1141 | struct sctp_association **asoc, |
1140 | void *event_arg, | 1142 | void *event_arg, |
1141 | sctp_disposition_t status, | 1143 | sctp_disposition_t status, |
1142 | sctp_cmd_seq_t *commands, | 1144 | sctp_cmd_seq_t *commands, |
@@ -1151,7 +1153,7 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, | |||
1151 | * disposition SCTP_DISPOSITION_CONSUME. | 1153 | * disposition SCTP_DISPOSITION_CONSUME. |
1152 | */ | 1154 | */ |
1153 | if (0 != (error = sctp_cmd_interpreter(event_type, subtype, state, | 1155 | if (0 != (error = sctp_cmd_interpreter(event_type, subtype, state, |
1154 | ep, asoc, | 1156 | ep, *asoc, |
1155 | event_arg, status, | 1157 | event_arg, status, |
1156 | commands, gfp))) | 1158 | commands, gfp))) |
1157 | goto bail; | 1159 | goto bail; |
@@ -1174,11 +1176,12 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, | |||
1174 | break; | 1176 | break; |
1175 | 1177 | ||
1176 | case SCTP_DISPOSITION_DELETE_TCB: | 1178 | case SCTP_DISPOSITION_DELETE_TCB: |
1179 | case SCTP_DISPOSITION_ABORT: | ||
1177 | /* This should now be a command. */ | 1180 | /* This should now be a command. */ |
1181 | *asoc = NULL; | ||
1178 | break; | 1182 | break; |
1179 | 1183 | ||
1180 | case SCTP_DISPOSITION_CONSUME: | 1184 | case SCTP_DISPOSITION_CONSUME: |
1181 | case SCTP_DISPOSITION_ABORT: | ||
1182 | /* | 1185 | /* |
1183 | * We should no longer have much work to do here as the | 1186 | * We should no longer have much work to do here as the |
1184 | * real work has been done as explicit commands above. | 1187 | * real work has been done as explicit commands above. |
@@ -1266,7 +1269,6 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1266 | asoc = cmd->obj.asoc; | 1269 | asoc = cmd->obj.asoc; |
1267 | BUG_ON(asoc->peer.primary_path == NULL); | 1270 | BUG_ON(asoc->peer.primary_path == NULL); |
1268 | sctp_endpoint_add_asoc(ep, asoc); | 1271 | sctp_endpoint_add_asoc(ep, asoc); |
1269 | sctp_hash_established(asoc); | ||
1270 | break; | 1272 | break; |
1271 | 1273 | ||
1272 | case SCTP_CMD_UPDATE_ASSOC: | 1274 | case SCTP_CMD_UPDATE_ASSOC: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 6f46aa16cb76..f1f08c8f277b 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -2976,7 +2976,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net, | |||
2976 | SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS); | 2976 | SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS); |
2977 | goto discard_force; | 2977 | goto discard_force; |
2978 | case SCTP_IERROR_NO_DATA: | 2978 | case SCTP_IERROR_NO_DATA: |
2979 | goto consume; | 2979 | return SCTP_DISPOSITION_ABORT; |
2980 | case SCTP_IERROR_PROTO_VIOLATION: | 2980 | case SCTP_IERROR_PROTO_VIOLATION: |
2981 | return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, | 2981 | return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, |
2982 | (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t)); | 2982 | (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t)); |
@@ -3043,9 +3043,6 @@ discard_noforce: | |||
3043 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force); | 3043 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force); |
3044 | 3044 | ||
3045 | return SCTP_DISPOSITION_DISCARD; | 3045 | return SCTP_DISPOSITION_DISCARD; |
3046 | consume: | ||
3047 | return SCTP_DISPOSITION_CONSUME; | ||
3048 | |||
3049 | } | 3046 | } |
3050 | 3047 | ||
3051 | /* | 3048 | /* |
@@ -3093,7 +3090,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(struct net *net, | |||
3093 | case SCTP_IERROR_BAD_STREAM: | 3090 | case SCTP_IERROR_BAD_STREAM: |
3094 | break; | 3091 | break; |
3095 | case SCTP_IERROR_NO_DATA: | 3092 | case SCTP_IERROR_NO_DATA: |
3096 | goto consume; | 3093 | return SCTP_DISPOSITION_ABORT; |
3097 | case SCTP_IERROR_PROTO_VIOLATION: | 3094 | case SCTP_IERROR_PROTO_VIOLATION: |
3098 | return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, | 3095 | return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, |
3099 | (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t)); | 3096 | (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t)); |
@@ -3119,7 +3116,6 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(struct net *net, | |||
3119 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); | 3116 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); |
3120 | } | 3117 | } |
3121 | 3118 | ||
3122 | consume: | ||
3123 | return SCTP_DISPOSITION_CONSUME; | 3119 | return SCTP_DISPOSITION_CONSUME; |
3124 | } | 3120 | } |
3125 | 3121 | ||
@@ -4825,11 +4821,9 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( | |||
4825 | * if necessary to fill gaps. | 4821 | * if necessary to fill gaps. |
4826 | */ | 4822 | */ |
4827 | struct sctp_chunk *abort = arg; | 4823 | struct sctp_chunk *abort = arg; |
4828 | sctp_disposition_t retval; | ||
4829 | 4824 | ||
4830 | retval = SCTP_DISPOSITION_CONSUME; | 4825 | if (abort) |
4831 | 4826 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | |
4832 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
4833 | 4827 | ||
4834 | /* Even if we can't send the ABORT due to low memory delete the | 4828 | /* Even if we can't send the ABORT due to low memory delete the |
4835 | * TCB. This is a departure from our typical NOMEM handling. | 4829 | * TCB. This is a departure from our typical NOMEM handling. |
@@ -4844,7 +4838,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( | |||
4844 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); | 4838 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
4845 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); | 4839 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
4846 | 4840 | ||
4847 | return retval; | 4841 | return SCTP_DISPOSITION_ABORT; |
4848 | } | 4842 | } |
4849 | 4843 | ||
4850 | /* We tried an illegal operation on an association which is closed. */ | 4844 | /* We tried an illegal operation on an association which is closed. */ |
@@ -4959,14 +4953,13 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
4959 | sctp_cmd_seq_t *commands) | 4953 | sctp_cmd_seq_t *commands) |
4960 | { | 4954 | { |
4961 | struct sctp_chunk *abort = arg; | 4955 | struct sctp_chunk *abort = arg; |
4962 | sctp_disposition_t retval; | ||
4963 | 4956 | ||
4964 | /* Stop T1-init timer */ | 4957 | /* Stop T1-init timer */ |
4965 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 4958 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
4966 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 4959 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
4967 | retval = SCTP_DISPOSITION_CONSUME; | ||
4968 | 4960 | ||
4969 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | 4961 | if (abort) |
4962 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
4970 | 4963 | ||
4971 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 4964 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
4972 | SCTP_STATE(SCTP_STATE_CLOSED)); | 4965 | SCTP_STATE(SCTP_STATE_CLOSED)); |
@@ -4983,7 +4976,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
4983 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4976 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
4984 | SCTP_PERR(SCTP_ERROR_USER_ABORT)); | 4977 | SCTP_PERR(SCTP_ERROR_USER_ABORT)); |
4985 | 4978 | ||
4986 | return retval; | 4979 | return SCTP_DISPOSITION_ABORT; |
4987 | } | 4980 | } |
4988 | 4981 | ||
4989 | /* | 4982 | /* |
@@ -5412,7 +5405,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(struct net *net, | |||
5412 | SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS); | 5405 | SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS); |
5413 | 5406 | ||
5414 | if (asoc->overall_error_count >= asoc->max_retrans) { | 5407 | if (asoc->overall_error_count >= asoc->max_retrans) { |
5415 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) { | 5408 | if (asoc->peer.zero_window_announced && |
5409 | asoc->state == SCTP_STATE_SHUTDOWN_PENDING) { | ||
5416 | /* | 5410 | /* |
5417 | * We are here likely because the receiver had its rwnd | 5411 | * We are here likely because the receiver had its rwnd |
5418 | * closed for a while and we have not been able to | 5412 | * closed for a while and we have not been able to |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 897c01c029ca..9bb80ec4c08f 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -972,7 +972,7 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
972 | return -EFAULT; | 972 | return -EFAULT; |
973 | 973 | ||
974 | /* Alloc space for the address array in kernel memory. */ | 974 | /* Alloc space for the address array in kernel memory. */ |
975 | kaddrs = kmalloc(addrs_size, GFP_KERNEL); | 975 | kaddrs = kmalloc(addrs_size, GFP_USER | __GFP_NOWARN); |
976 | if (unlikely(!kaddrs)) | 976 | if (unlikely(!kaddrs)) |
977 | return -ENOMEM; | 977 | return -ENOMEM; |
978 | 978 | ||
@@ -1228,7 +1228,6 @@ out_free: | |||
1228 | * To the hash table, try to unhash it, just in case, its a noop | 1228 | * To the hash table, try to unhash it, just in case, its a noop |
1229 | * if it wasn't hashed so we're safe | 1229 | * if it wasn't hashed so we're safe |
1230 | */ | 1230 | */ |
1231 | sctp_unhash_established(asoc); | ||
1232 | sctp_association_free(asoc); | 1231 | sctp_association_free(asoc); |
1233 | } | 1232 | } |
1234 | return err; | 1233 | return err; |
@@ -1301,8 +1300,9 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
1301 | int addrs_size, | 1300 | int addrs_size, |
1302 | sctp_assoc_t *assoc_id) | 1301 | sctp_assoc_t *assoc_id) |
1303 | { | 1302 | { |
1304 | int err = 0; | ||
1305 | struct sockaddr *kaddrs; | 1303 | struct sockaddr *kaddrs; |
1304 | gfp_t gfp = GFP_KERNEL; | ||
1305 | int err = 0; | ||
1306 | 1306 | ||
1307 | pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n", | 1307 | pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n", |
1308 | __func__, sk, addrs, addrs_size); | 1308 | __func__, sk, addrs, addrs_size); |
@@ -1315,7 +1315,9 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
1315 | return -EFAULT; | 1315 | return -EFAULT; |
1316 | 1316 | ||
1317 | /* Alloc space for the address array in kernel memory. */ | 1317 | /* Alloc space for the address array in kernel memory. */ |
1318 | kaddrs = kmalloc(addrs_size, GFP_KERNEL); | 1318 | if (sk->sk_socket->file) |
1319 | gfp = GFP_USER | __GFP_NOWARN; | ||
1320 | kaddrs = kmalloc(addrs_size, gfp); | ||
1319 | if (unlikely(!kaddrs)) | 1321 | if (unlikely(!kaddrs)) |
1320 | return -ENOMEM; | 1322 | return -ENOMEM; |
1321 | 1323 | ||
@@ -1501,7 +1503,6 @@ static void sctp_close(struct sock *sk, long timeout) | |||
1501 | * ABORT or SHUTDOWN based on the linger options. | 1503 | * ABORT or SHUTDOWN based on the linger options. |
1502 | */ | 1504 | */ |
1503 | if (sctp_state(asoc, CLOSED)) { | 1505 | if (sctp_state(asoc, CLOSED)) { |
1504 | sctp_unhash_established(asoc); | ||
1505 | sctp_association_free(asoc); | 1506 | sctp_association_free(asoc); |
1506 | continue; | 1507 | continue; |
1507 | } | 1508 | } |
@@ -1513,8 +1514,7 @@ static void sctp_close(struct sock *sk, long timeout) | |||
1513 | struct sctp_chunk *chunk; | 1514 | struct sctp_chunk *chunk; |
1514 | 1515 | ||
1515 | chunk = sctp_make_abort_user(asoc, NULL, 0); | 1516 | chunk = sctp_make_abort_user(asoc, NULL, 0); |
1516 | if (chunk) | 1517 | sctp_primitive_ABORT(net, asoc, chunk); |
1517 | sctp_primitive_ABORT(net, asoc, chunk); | ||
1518 | } else | 1518 | } else |
1519 | sctp_primitive_SHUTDOWN(net, asoc, NULL); | 1519 | sctp_primitive_SHUTDOWN(net, asoc, NULL); |
1520 | } | 1520 | } |
@@ -1952,8 +1952,6 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) | |||
1952 | 1952 | ||
1953 | /* Now send the (possibly) fragmented message. */ | 1953 | /* Now send the (possibly) fragmented message. */ |
1954 | list_for_each_entry(chunk, &datamsg->chunks, frag_list) { | 1954 | list_for_each_entry(chunk, &datamsg->chunks, frag_list) { |
1955 | sctp_chunk_hold(chunk); | ||
1956 | |||
1957 | /* Do accounting for the write space. */ | 1955 | /* Do accounting for the write space. */ |
1958 | sctp_set_owner_w(chunk); | 1956 | sctp_set_owner_w(chunk); |
1959 | 1957 | ||
@@ -1966,15 +1964,13 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) | |||
1966 | * breaks. | 1964 | * breaks. |
1967 | */ | 1965 | */ |
1968 | err = sctp_primitive_SEND(net, asoc, datamsg); | 1966 | err = sctp_primitive_SEND(net, asoc, datamsg); |
1967 | sctp_datamsg_put(datamsg); | ||
1969 | /* Did the lower layer accept the chunk? */ | 1968 | /* Did the lower layer accept the chunk? */ |
1970 | if (err) { | 1969 | if (err) |
1971 | sctp_datamsg_free(datamsg); | ||
1972 | goto out_free; | 1970 | goto out_free; |
1973 | } | ||
1974 | 1971 | ||
1975 | pr_debug("%s: we sent primitively\n", __func__); | 1972 | pr_debug("%s: we sent primitively\n", __func__); |
1976 | 1973 | ||
1977 | sctp_datamsg_put(datamsg); | ||
1978 | err = msg_len; | 1974 | err = msg_len; |
1979 | 1975 | ||
1980 | if (unlikely(wait_connect)) { | 1976 | if (unlikely(wait_connect)) { |
@@ -1988,10 +1984,8 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) | |||
1988 | goto out_unlock; | 1984 | goto out_unlock; |
1989 | 1985 | ||
1990 | out_free: | 1986 | out_free: |
1991 | if (new_asoc) { | 1987 | if (new_asoc) |
1992 | sctp_unhash_established(asoc); | ||
1993 | sctp_association_free(asoc); | 1988 | sctp_association_free(asoc); |
1994 | } | ||
1995 | out_unlock: | 1989 | out_unlock: |
1996 | release_sock(sk); | 1990 | release_sock(sk); |
1997 | 1991 | ||
@@ -4928,7 +4922,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | |||
4928 | to = optval + offsetof(struct sctp_getaddrs, addrs); | 4922 | to = optval + offsetof(struct sctp_getaddrs, addrs); |
4929 | space_left = len - offsetof(struct sctp_getaddrs, addrs); | 4923 | space_left = len - offsetof(struct sctp_getaddrs, addrs); |
4930 | 4924 | ||
4931 | addrs = kmalloc(space_left, GFP_KERNEL); | 4925 | addrs = kmalloc(space_left, GFP_USER | __GFP_NOWARN); |
4932 | if (!addrs) | 4926 | if (!addrs) |
4933 | return -ENOMEM; | 4927 | return -ENOMEM; |
4934 | 4928 | ||
@@ -5777,7 +5771,7 @@ static int sctp_getsockopt_assoc_ids(struct sock *sk, int len, | |||
5777 | 5771 | ||
5778 | len = sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num; | 5772 | len = sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num; |
5779 | 5773 | ||
5780 | ids = kmalloc(len, GFP_KERNEL); | 5774 | ids = kmalloc(len, GFP_USER | __GFP_NOWARN); |
5781 | if (unlikely(!ids)) | 5775 | if (unlikely(!ids)) |
5782 | return -ENOMEM; | 5776 | return -ENOMEM; |
5783 | 5777 | ||
@@ -6458,7 +6452,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
6458 | if (sctp_writeable(sk)) { | 6452 | if (sctp_writeable(sk)) { |
6459 | mask |= POLLOUT | POLLWRNORM; | 6453 | mask |= POLLOUT | POLLWRNORM; |
6460 | } else { | 6454 | } else { |
6461 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 6455 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
6462 | /* | 6456 | /* |
6463 | * Since the socket is not locked, the buffer | 6457 | * Since the socket is not locked, the buffer |
6464 | * might be made available after the writeable check and | 6458 | * might be made available after the writeable check and |
@@ -6801,26 +6795,30 @@ no_packet: | |||
6801 | static void __sctp_write_space(struct sctp_association *asoc) | 6795 | static void __sctp_write_space(struct sctp_association *asoc) |
6802 | { | 6796 | { |
6803 | struct sock *sk = asoc->base.sk; | 6797 | struct sock *sk = asoc->base.sk; |
6804 | struct socket *sock = sk->sk_socket; | ||
6805 | 6798 | ||
6806 | if ((sctp_wspace(asoc) > 0) && sock) { | 6799 | if (sctp_wspace(asoc) <= 0) |
6807 | if (waitqueue_active(&asoc->wait)) | 6800 | return; |
6808 | wake_up_interruptible(&asoc->wait); | ||
6809 | 6801 | ||
6810 | if (sctp_writeable(sk)) { | 6802 | if (waitqueue_active(&asoc->wait)) |
6811 | wait_queue_head_t *wq = sk_sleep(sk); | 6803 | wake_up_interruptible(&asoc->wait); |
6812 | 6804 | ||
6813 | if (wq && waitqueue_active(wq)) | 6805 | if (sctp_writeable(sk)) { |
6814 | wake_up_interruptible(wq); | 6806 | struct socket_wq *wq; |
6807 | |||
6808 | rcu_read_lock(); | ||
6809 | wq = rcu_dereference(sk->sk_wq); | ||
6810 | if (wq) { | ||
6811 | if (waitqueue_active(&wq->wait)) | ||
6812 | wake_up_interruptible(&wq->wait); | ||
6815 | 6813 | ||
6816 | /* Note that we try to include the Async I/O support | 6814 | /* Note that we try to include the Async I/O support |
6817 | * here by modeling from the current TCP/UDP code. | 6815 | * here by modeling from the current TCP/UDP code. |
6818 | * We have not tested with it yet. | 6816 | * We have not tested with it yet. |
6819 | */ | 6817 | */ |
6820 | if (!(sk->sk_shutdown & SEND_SHUTDOWN)) | 6818 | if (!(sk->sk_shutdown & SEND_SHUTDOWN)) |
6821 | sock_wake_async(sock, | 6819 | sock_wake_async(wq, SOCK_WAKE_SPACE, POLL_OUT); |
6822 | SOCK_WAKE_SPACE, POLL_OUT); | ||
6823 | } | 6820 | } |
6821 | rcu_read_unlock(); | ||
6824 | } | 6822 | } |
6825 | } | 6823 | } |
6826 | 6824 | ||
@@ -6978,7 +6976,7 @@ void sctp_data_ready(struct sock *sk) | |||
6978 | 6976 | ||
6979 | rcu_read_lock(); | 6977 | rcu_read_lock(); |
6980 | wq = rcu_dereference(sk->sk_wq); | 6978 | wq = rcu_dereference(sk->sk_wq); |
6981 | if (wq_has_sleeper(wq)) | 6979 | if (skwq_has_sleeper(wq)) |
6982 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | | 6980 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | |
6983 | POLLRDNORM | POLLRDBAND); | 6981 | POLLRDNORM | POLLRDBAND); |
6984 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 6982 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
@@ -7163,6 +7161,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
7163 | newsk->sk_type = sk->sk_type; | 7161 | newsk->sk_type = sk->sk_type; |
7164 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; | 7162 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; |
7165 | newsk->sk_flags = sk->sk_flags; | 7163 | newsk->sk_flags = sk->sk_flags; |
7164 | newsk->sk_tsflags = sk->sk_tsflags; | ||
7166 | newsk->sk_no_check_tx = sk->sk_no_check_tx; | 7165 | newsk->sk_no_check_tx = sk->sk_no_check_tx; |
7167 | newsk->sk_no_check_rx = sk->sk_no_check_rx; | 7166 | newsk->sk_no_check_rx = sk->sk_no_check_rx; |
7168 | newsk->sk_reuse = sk->sk_reuse; | 7167 | newsk->sk_reuse = sk->sk_reuse; |
@@ -7195,6 +7194,11 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
7195 | newinet->mc_ttl = 1; | 7194 | newinet->mc_ttl = 1; |
7196 | newinet->mc_index = 0; | 7195 | newinet->mc_index = 0; |
7197 | newinet->mc_list = NULL; | 7196 | newinet->mc_list = NULL; |
7197 | |||
7198 | if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) | ||
7199 | net_enable_timestamp(); | ||
7200 | |||
7201 | security_sk_clone(sk, newsk); | ||
7198 | } | 7202 | } |
7199 | 7203 | ||
7200 | static inline void sctp_copy_descendant(struct sock *sk_to, | 7204 | static inline void sctp_copy_descendant(struct sock *sk_to, |
@@ -7375,6 +7379,13 @@ struct proto sctp_prot = { | |||
7375 | 7379 | ||
7376 | #if IS_ENABLED(CONFIG_IPV6) | 7380 | #if IS_ENABLED(CONFIG_IPV6) |
7377 | 7381 | ||
7382 | #include <net/transp_v6.h> | ||
7383 | static void sctp_v6_destroy_sock(struct sock *sk) | ||
7384 | { | ||
7385 | sctp_destroy_sock(sk); | ||
7386 | inet6_destroy_sock(sk); | ||
7387 | } | ||
7388 | |||
7378 | struct proto sctpv6_prot = { | 7389 | struct proto sctpv6_prot = { |
7379 | .name = "SCTPv6", | 7390 | .name = "SCTPv6", |
7380 | .owner = THIS_MODULE, | 7391 | .owner = THIS_MODULE, |
@@ -7384,7 +7395,7 @@ struct proto sctpv6_prot = { | |||
7384 | .accept = sctp_accept, | 7395 | .accept = sctp_accept, |
7385 | .ioctl = sctp_ioctl, | 7396 | .ioctl = sctp_ioctl, |
7386 | .init = sctp_init_sock, | 7397 | .init = sctp_init_sock, |
7387 | .destroy = sctp_destroy_sock, | 7398 | .destroy = sctp_v6_destroy_sock, |
7388 | .shutdown = sctp_shutdown, | 7399 | .shutdown = sctp_shutdown, |
7389 | .setsockopt = sctp_setsockopt, | 7400 | .setsockopt = sctp_setsockopt, |
7390 | .getsockopt = sctp_getsockopt, | 7401 | .getsockopt = sctp_getsockopt, |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 26d50c565f54..daf8554fd42a 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -308,6 +308,13 @@ static struct ctl_table sctp_net_table[] = { | |||
308 | .extra1 = &max_autoclose_min, | 308 | .extra1 = &max_autoclose_min, |
309 | .extra2 = &max_autoclose_max, | 309 | .extra2 = &max_autoclose_max, |
310 | }, | 310 | }, |
311 | { | ||
312 | .procname = "pf_enable", | ||
313 | .data = &init_net.sctp.pf_enable, | ||
314 | .maxlen = sizeof(int), | ||
315 | .mode = 0644, | ||
316 | .proc_handler = proc_dointvec, | ||
317 | }, | ||
311 | 318 | ||
312 | { /* sentinel */ } | 319 | { /* sentinel */ } |
313 | }; | 320 | }; |
@@ -320,7 +327,7 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, | |||
320 | struct ctl_table tbl; | 327 | struct ctl_table tbl; |
321 | bool changed = false; | 328 | bool changed = false; |
322 | char *none = "none"; | 329 | char *none = "none"; |
323 | char tmp[8]; | 330 | char tmp[8] = {0}; |
324 | int ret; | 331 | int ret; |
325 | 332 | ||
326 | memset(&tbl, 0, sizeof(struct ctl_table)); | 333 | memset(&tbl, 0, sizeof(struct ctl_table)); |
diff --git a/net/socket.c b/net/socket.c index dd2c247c99e3..91c2de6f5020 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -257,6 +257,7 @@ static struct inode *sock_alloc_inode(struct super_block *sb) | |||
257 | } | 257 | } |
258 | init_waitqueue_head(&wq->wait); | 258 | init_waitqueue_head(&wq->wait); |
259 | wq->fasync_list = NULL; | 259 | wq->fasync_list = NULL; |
260 | wq->flags = 0; | ||
260 | RCU_INIT_POINTER(ei->socket.wq, wq); | 261 | RCU_INIT_POINTER(ei->socket.wq, wq); |
261 | 262 | ||
262 | ei->socket.state = SS_UNCONNECTED; | 263 | ei->socket.state = SS_UNCONNECTED; |
@@ -1056,27 +1057,20 @@ static int sock_fasync(int fd, struct file *filp, int on) | |||
1056 | return 0; | 1057 | return 0; |
1057 | } | 1058 | } |
1058 | 1059 | ||
1059 | /* This function may be called only under socket lock or callback_lock or rcu_lock */ | 1060 | /* This function may be called only under rcu_lock */ |
1060 | 1061 | ||
1061 | int sock_wake_async(struct socket *sock, int how, int band) | 1062 | int sock_wake_async(struct socket_wq *wq, int how, int band) |
1062 | { | 1063 | { |
1063 | struct socket_wq *wq; | 1064 | if (!wq || !wq->fasync_list) |
1064 | |||
1065 | if (!sock) | ||
1066 | return -1; | ||
1067 | rcu_read_lock(); | ||
1068 | wq = rcu_dereference(sock->wq); | ||
1069 | if (!wq || !wq->fasync_list) { | ||
1070 | rcu_read_unlock(); | ||
1071 | return -1; | 1065 | return -1; |
1072 | } | 1066 | |
1073 | switch (how) { | 1067 | switch (how) { |
1074 | case SOCK_WAKE_WAITD: | 1068 | case SOCK_WAKE_WAITD: |
1075 | if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) | 1069 | if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags)) |
1076 | break; | 1070 | break; |
1077 | goto call_kill; | 1071 | goto call_kill; |
1078 | case SOCK_WAKE_SPACE: | 1072 | case SOCK_WAKE_SPACE: |
1079 | if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags)) | 1073 | if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags)) |
1080 | break; | 1074 | break; |
1081 | /* fall through */ | 1075 | /* fall through */ |
1082 | case SOCK_WAKE_IO: | 1076 | case SOCK_WAKE_IO: |
@@ -1086,7 +1080,7 @@ call_kill: | |||
1086 | case SOCK_WAKE_URG: | 1080 | case SOCK_WAKE_URG: |
1087 | kill_fasync(&wq->fasync_list, SIGURG, band); | 1081 | kill_fasync(&wq->fasync_list, SIGURG, band); |
1088 | } | 1082 | } |
1089 | rcu_read_unlock(); | 1083 | |
1090 | return 0; | 1084 | return 0; |
1091 | } | 1085 | } |
1092 | EXPORT_SYMBOL(sock_wake_async); | 1086 | EXPORT_SYMBOL(sock_wake_async); |
@@ -1702,6 +1696,7 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, | |||
1702 | msg.msg_name = addr ? (struct sockaddr *)&address : NULL; | 1696 | msg.msg_name = addr ? (struct sockaddr *)&address : NULL; |
1703 | /* We assume all kernel code knows the size of sockaddr_storage */ | 1697 | /* We assume all kernel code knows the size of sockaddr_storage */ |
1704 | msg.msg_namelen = 0; | 1698 | msg.msg_namelen = 0; |
1699 | msg.msg_iocb = NULL; | ||
1705 | if (sock->file->f_flags & O_NONBLOCK) | 1700 | if (sock->file->f_flags & O_NONBLOCK) |
1706 | flags |= MSG_DONTWAIT; | 1701 | flags |= MSG_DONTWAIT; |
1707 | err = sock_recvmsg(sock, &msg, iov_iter_count(&msg.msg_iter), flags); | 1702 | err = sock_recvmsg(sock, &msg, iov_iter_count(&msg.msg_iter), flags); |
@@ -2046,6 +2041,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
2046 | if (err) | 2041 | if (err) |
2047 | break; | 2042 | break; |
2048 | ++datagrams; | 2043 | ++datagrams; |
2044 | cond_resched(); | ||
2049 | } | 2045 | } |
2050 | 2046 | ||
2051 | fput_light(sock->file, fput_needed); | 2047 | fput_light(sock->file, fput_needed); |
@@ -2241,6 +2237,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
2241 | /* Out of band data, return right away */ | 2237 | /* Out of band data, return right away */ |
2242 | if (msg_sys.msg_flags & MSG_OOB) | 2238 | if (msg_sys.msg_flags & MSG_OOB) |
2243 | break; | 2239 | break; |
2240 | cond_resched(); | ||
2244 | } | 2241 | } |
2245 | 2242 | ||
2246 | out_put: | 2243 | out_put: |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 95f82d8d4888..229956bf8457 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -353,20 +353,12 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) | |||
353 | { | 353 | { |
354 | struct rpc_xprt *xprt = req->rq_xprt; | 354 | struct rpc_xprt *xprt = req->rq_xprt; |
355 | struct svc_serv *bc_serv = xprt->bc_serv; | 355 | struct svc_serv *bc_serv = xprt->bc_serv; |
356 | struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf; | ||
357 | 356 | ||
358 | spin_lock(&xprt->bc_pa_lock); | 357 | spin_lock(&xprt->bc_pa_lock); |
359 | list_del(&req->rq_bc_pa_list); | 358 | list_del(&req->rq_bc_pa_list); |
360 | xprt_dec_alloc_count(xprt, 1); | 359 | xprt_dec_alloc_count(xprt, 1); |
361 | spin_unlock(&xprt->bc_pa_lock); | 360 | spin_unlock(&xprt->bc_pa_lock); |
362 | 361 | ||
363 | if (copied <= rq_rcv_buf->head[0].iov_len) { | ||
364 | rq_rcv_buf->head[0].iov_len = copied; | ||
365 | rq_rcv_buf->page_len = 0; | ||
366 | } else { | ||
367 | rq_rcv_buf->page_len = copied - rq_rcv_buf->head[0].iov_len; | ||
368 | } | ||
369 | |||
370 | req->rq_private_buf.len = copied; | 362 | req->rq_private_buf.len = copied; |
371 | set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | 363 | set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); |
372 | 364 | ||
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index f14f24ee9983..73ad57a59989 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -250,11 +250,11 @@ void rpc_destroy_wait_queue(struct rpc_wait_queue *queue) | |||
250 | } | 250 | } |
251 | EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue); | 251 | EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue); |
252 | 252 | ||
253 | static int rpc_wait_bit_killable(struct wait_bit_key *key) | 253 | static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode) |
254 | { | 254 | { |
255 | if (fatal_signal_pending(current)) | ||
256 | return -ERESTARTSYS; | ||
257 | freezable_schedule_unsafe(); | 255 | freezable_schedule_unsafe(); |
256 | if (signal_pending_state(mode, current)) | ||
257 | return -ERESTARTSYS; | ||
258 | return 0; | 258 | return 0; |
259 | } | 259 | } |
260 | 260 | ||
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 7fccf9675df8..cc9852897395 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -1363,7 +1363,19 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, | |||
1363 | memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); | 1363 | memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); |
1364 | memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); | 1364 | memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); |
1365 | memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); | 1365 | memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); |
1366 | |||
1367 | /* Adjust the argument buffer length */ | ||
1366 | rqstp->rq_arg.len = req->rq_private_buf.len; | 1368 | rqstp->rq_arg.len = req->rq_private_buf.len; |
1369 | if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { | ||
1370 | rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len; | ||
1371 | rqstp->rq_arg.page_len = 0; | ||
1372 | } else if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len + | ||
1373 | rqstp->rq_arg.page_len) | ||
1374 | rqstp->rq_arg.page_len = rqstp->rq_arg.len - | ||
1375 | rqstp->rq_arg.head[0].iov_len; | ||
1376 | else | ||
1377 | rqstp->rq_arg.len = rqstp->rq_arg.head[0].iov_len + | ||
1378 | rqstp->rq_arg.page_len; | ||
1367 | 1379 | ||
1368 | /* reset result send buffer "put" position */ | 1380 | /* reset result send buffer "put" position */ |
1369 | resv->iov_len = 0; | 1381 | resv->iov_len = 0; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 1d1a70498910..2ffaf6a79499 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -398,7 +398,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, | |||
398 | if (unlikely(!sock)) | 398 | if (unlikely(!sock)) |
399 | return -ENOTSOCK; | 399 | return -ENOTSOCK; |
400 | 400 | ||
401 | clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); | 401 | clear_bit(SOCKWQ_ASYNC_NOSPACE, &sock->flags); |
402 | if (base != 0) { | 402 | if (base != 0) { |
403 | addr = NULL; | 403 | addr = NULL; |
404 | addrlen = 0; | 404 | addrlen = 0; |
@@ -442,7 +442,7 @@ static void xs_nospace_callback(struct rpc_task *task) | |||
442 | struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt); | 442 | struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt); |
443 | 443 | ||
444 | transport->inet->sk_write_pending--; | 444 | transport->inet->sk_write_pending--; |
445 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 445 | clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags); |
446 | } | 446 | } |
447 | 447 | ||
448 | /** | 448 | /** |
@@ -467,7 +467,7 @@ static int xs_nospace(struct rpc_task *task) | |||
467 | 467 | ||
468 | /* Don't race with disconnect */ | 468 | /* Don't race with disconnect */ |
469 | if (xprt_connected(xprt)) { | 469 | if (xprt_connected(xprt)) { |
470 | if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) { | 470 | if (test_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags)) { |
471 | /* | 471 | /* |
472 | * Notify TCP that we're limited by the application | 472 | * Notify TCP that we're limited by the application |
473 | * window size | 473 | * window size |
@@ -478,7 +478,7 @@ static int xs_nospace(struct rpc_task *task) | |||
478 | xprt_wait_for_buffer_space(task, xs_nospace_callback); | 478 | xprt_wait_for_buffer_space(task, xs_nospace_callback); |
479 | } | 479 | } |
480 | } else { | 480 | } else { |
481 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 481 | clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags); |
482 | ret = -ENOTCONN; | 482 | ret = -ENOTCONN; |
483 | } | 483 | } |
484 | 484 | ||
@@ -626,7 +626,7 @@ process_status: | |||
626 | case -EPERM: | 626 | case -EPERM: |
627 | /* When the server has died, an ICMP port unreachable message | 627 | /* When the server has died, an ICMP port unreachable message |
628 | * prompts ECONNREFUSED. */ | 628 | * prompts ECONNREFUSED. */ |
629 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 629 | clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags); |
630 | } | 630 | } |
631 | 631 | ||
632 | return status; | 632 | return status; |
@@ -715,7 +715,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
715 | case -EADDRINUSE: | 715 | case -EADDRINUSE: |
716 | case -ENOBUFS: | 716 | case -ENOBUFS: |
717 | case -EPIPE: | 717 | case -EPIPE: |
718 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 718 | clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags); |
719 | } | 719 | } |
720 | 720 | ||
721 | return status; | 721 | return status; |
@@ -1618,7 +1618,7 @@ static void xs_write_space(struct sock *sk) | |||
1618 | 1618 | ||
1619 | if (unlikely(!(xprt = xprt_from_sock(sk)))) | 1619 | if (unlikely(!(xprt = xprt_from_sock(sk)))) |
1620 | return; | 1620 | return; |
1621 | if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0) | 1621 | if (test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &sock->flags) == 0) |
1622 | return; | 1622 | return; |
1623 | 1623 | ||
1624 | xprt_write_space(xprt); | 1624 | xprt_write_space(xprt); |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index f34e535e93bd..ebc661d3b6e3 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -345,6 +345,8 @@ static size_t switchdev_obj_size(const struct switchdev_obj *obj) | |||
345 | return sizeof(struct switchdev_obj_ipv4_fib); | 345 | return sizeof(struct switchdev_obj_ipv4_fib); |
346 | case SWITCHDEV_OBJ_ID_PORT_FDB: | 346 | case SWITCHDEV_OBJ_ID_PORT_FDB: |
347 | return sizeof(struct switchdev_obj_port_fdb); | 347 | return sizeof(struct switchdev_obj_port_fdb); |
348 | case SWITCHDEV_OBJ_ID_PORT_MDB: | ||
349 | return sizeof(struct switchdev_obj_port_mdb); | ||
348 | default: | 350 | default: |
349 | BUG(); | 351 | BUG(); |
350 | } | 352 | } |
@@ -723,6 +725,7 @@ static int switchdev_port_vlan_fill(struct sk_buff *skb, struct net_device *dev, | |||
723 | u32 filter_mask) | 725 | u32 filter_mask) |
724 | { | 726 | { |
725 | struct switchdev_vlan_dump dump = { | 727 | struct switchdev_vlan_dump dump = { |
728 | .vlan.obj.orig_dev = dev, | ||
726 | .vlan.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, | 729 | .vlan.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, |
727 | .skb = skb, | 730 | .skb = skb, |
728 | .filter_mask = filter_mask, | 731 | .filter_mask = filter_mask, |
@@ -757,6 +760,7 @@ int switchdev_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, | |||
757 | int nlflags) | 760 | int nlflags) |
758 | { | 761 | { |
759 | struct switchdev_attr attr = { | 762 | struct switchdev_attr attr = { |
763 | .orig_dev = dev, | ||
760 | .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, | 764 | .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, |
761 | }; | 765 | }; |
762 | u16 mode = BRIDGE_MODE_UNDEF; | 766 | u16 mode = BRIDGE_MODE_UNDEF; |
@@ -778,6 +782,7 @@ static int switchdev_port_br_setflag(struct net_device *dev, | |||
778 | unsigned long brport_flag) | 782 | unsigned long brport_flag) |
779 | { | 783 | { |
780 | struct switchdev_attr attr = { | 784 | struct switchdev_attr attr = { |
785 | .orig_dev = dev, | ||
781 | .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, | 786 | .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, |
782 | }; | 787 | }; |
783 | u8 flag = nla_get_u8(nlattr); | 788 | u8 flag = nla_get_u8(nlattr); |
@@ -853,6 +858,7 @@ static int switchdev_port_br_afspec(struct net_device *dev, | |||
853 | struct nlattr *attr; | 858 | struct nlattr *attr; |
854 | struct bridge_vlan_info *vinfo; | 859 | struct bridge_vlan_info *vinfo; |
855 | struct switchdev_obj_port_vlan vlan = { | 860 | struct switchdev_obj_port_vlan vlan = { |
861 | .obj.orig_dev = dev, | ||
856 | .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, | 862 | .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, |
857 | }; | 863 | }; |
858 | int rem; | 864 | int rem; |
@@ -975,6 +981,7 @@ int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | |||
975 | u16 vid, u16 nlm_flags) | 981 | u16 vid, u16 nlm_flags) |
976 | { | 982 | { |
977 | struct switchdev_obj_port_fdb fdb = { | 983 | struct switchdev_obj_port_fdb fdb = { |
984 | .obj.orig_dev = dev, | ||
978 | .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, | 985 | .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, |
979 | .vid = vid, | 986 | .vid = vid, |
980 | }; | 987 | }; |
@@ -1000,6 +1007,7 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], | |||
1000 | u16 vid) | 1007 | u16 vid) |
1001 | { | 1008 | { |
1002 | struct switchdev_obj_port_fdb fdb = { | 1009 | struct switchdev_obj_port_fdb fdb = { |
1010 | .obj.orig_dev = dev, | ||
1003 | .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, | 1011 | .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, |
1004 | .vid = vid, | 1012 | .vid = vid, |
1005 | }; | 1013 | }; |
@@ -1077,6 +1085,7 @@ int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, | |||
1077 | struct net_device *filter_dev, int idx) | 1085 | struct net_device *filter_dev, int idx) |
1078 | { | 1086 | { |
1079 | struct switchdev_fdb_dump dump = { | 1087 | struct switchdev_fdb_dump dump = { |
1088 | .fdb.obj.orig_dev = dev, | ||
1080 | .fdb.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, | 1089 | .fdb.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, |
1081 | .dev = dev, | 1090 | .dev = dev, |
1082 | .skb = skb, | 1091 | .skb = skb, |
@@ -1135,6 +1144,7 @@ static struct net_device *switchdev_get_dev_by_nhs(struct fib_info *fi) | |||
1135 | if (!dev) | 1144 | if (!dev) |
1136 | return NULL; | 1145 | return NULL; |
1137 | 1146 | ||
1147 | attr.orig_dev = dev; | ||
1138 | if (switchdev_port_attr_get(dev, &attr)) | 1148 | if (switchdev_port_attr_get(dev, &attr)) |
1139 | return NULL; | 1149 | return NULL; |
1140 | 1150 | ||
@@ -1194,6 +1204,7 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, | |||
1194 | if (!dev) | 1204 | if (!dev) |
1195 | return 0; | 1205 | return 0; |
1196 | 1206 | ||
1207 | ipv4_fib.obj.orig_dev = dev; | ||
1197 | err = switchdev_port_obj_add(dev, &ipv4_fib.obj); | 1208 | err = switchdev_port_obj_add(dev, &ipv4_fib.obj); |
1198 | if (!err) | 1209 | if (!err) |
1199 | fi->fib_flags |= RTNH_F_OFFLOAD; | 1210 | fi->fib_flags |= RTNH_F_OFFLOAD; |
@@ -1238,6 +1249,7 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, | |||
1238 | if (!dev) | 1249 | if (!dev) |
1239 | return 0; | 1250 | return 0; |
1240 | 1251 | ||
1252 | ipv4_fib.obj.orig_dev = dev; | ||
1241 | err = switchdev_port_obj_del(dev, &ipv4_fib.obj); | 1253 | err = switchdev_port_obj_del(dev, &ipv4_fib.obj); |
1242 | if (!err) | 1254 | if (!err) |
1243 | fi->fib_flags &= ~RTNH_F_OFFLOAD; | 1255 | fi->fib_flags &= ~RTNH_F_OFFLOAD; |
@@ -1270,10 +1282,12 @@ static bool switchdev_port_same_parent_id(struct net_device *a, | |||
1270 | struct net_device *b) | 1282 | struct net_device *b) |
1271 | { | 1283 | { |
1272 | struct switchdev_attr a_attr = { | 1284 | struct switchdev_attr a_attr = { |
1285 | .orig_dev = a, | ||
1273 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, | 1286 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, |
1274 | .flags = SWITCHDEV_F_NO_RECURSE, | 1287 | .flags = SWITCHDEV_F_NO_RECURSE, |
1275 | }; | 1288 | }; |
1276 | struct switchdev_attr b_attr = { | 1289 | struct switchdev_attr b_attr = { |
1290 | .orig_dev = b, | ||
1277 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, | 1291 | .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, |
1278 | .flags = SWITCHDEV_F_NO_RECURSE, | 1292 | .flags = SWITCHDEV_F_NO_RECURSE, |
1279 | }; | 1293 | }; |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 9dc239dfe192..e401108360a2 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -332,131 +332,15 @@ void tipc_bcast_remove_peer(struct net *net, struct tipc_link *rcv_l) | |||
332 | tipc_sk_rcv(net, inputq); | 332 | tipc_sk_rcv(net, inputq); |
333 | } | 333 | } |
334 | 334 | ||
335 | static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb, | ||
336 | struct tipc_stats *stats) | ||
337 | { | ||
338 | int i; | ||
339 | struct nlattr *nest; | ||
340 | |||
341 | struct nla_map { | ||
342 | __u32 key; | ||
343 | __u32 val; | ||
344 | }; | ||
345 | |||
346 | struct nla_map map[] = { | ||
347 | {TIPC_NLA_STATS_RX_INFO, stats->recv_info}, | ||
348 | {TIPC_NLA_STATS_RX_FRAGMENTS, stats->recv_fragments}, | ||
349 | {TIPC_NLA_STATS_RX_FRAGMENTED, stats->recv_fragmented}, | ||
350 | {TIPC_NLA_STATS_RX_BUNDLES, stats->recv_bundles}, | ||
351 | {TIPC_NLA_STATS_RX_BUNDLED, stats->recv_bundled}, | ||
352 | {TIPC_NLA_STATS_TX_INFO, stats->sent_info}, | ||
353 | {TIPC_NLA_STATS_TX_FRAGMENTS, stats->sent_fragments}, | ||
354 | {TIPC_NLA_STATS_TX_FRAGMENTED, stats->sent_fragmented}, | ||
355 | {TIPC_NLA_STATS_TX_BUNDLES, stats->sent_bundles}, | ||
356 | {TIPC_NLA_STATS_TX_BUNDLED, stats->sent_bundled}, | ||
357 | {TIPC_NLA_STATS_RX_NACKS, stats->recv_nacks}, | ||
358 | {TIPC_NLA_STATS_RX_DEFERRED, stats->deferred_recv}, | ||
359 | {TIPC_NLA_STATS_TX_NACKS, stats->sent_nacks}, | ||
360 | {TIPC_NLA_STATS_TX_ACKS, stats->sent_acks}, | ||
361 | {TIPC_NLA_STATS_RETRANSMITTED, stats->retransmitted}, | ||
362 | {TIPC_NLA_STATS_DUPLICATES, stats->duplicates}, | ||
363 | {TIPC_NLA_STATS_LINK_CONGS, stats->link_congs}, | ||
364 | {TIPC_NLA_STATS_MAX_QUEUE, stats->max_queue_sz}, | ||
365 | {TIPC_NLA_STATS_AVG_QUEUE, stats->queue_sz_counts ? | ||
366 | (stats->accu_queue_sz / stats->queue_sz_counts) : 0} | ||
367 | }; | ||
368 | |||
369 | nest = nla_nest_start(skb, TIPC_NLA_LINK_STATS); | ||
370 | if (!nest) | ||
371 | return -EMSGSIZE; | ||
372 | |||
373 | for (i = 0; i < ARRAY_SIZE(map); i++) | ||
374 | if (nla_put_u32(skb, map[i].key, map[i].val)) | ||
375 | goto msg_full; | ||
376 | |||
377 | nla_nest_end(skb, nest); | ||
378 | |||
379 | return 0; | ||
380 | msg_full: | ||
381 | nla_nest_cancel(skb, nest); | ||
382 | |||
383 | return -EMSGSIZE; | ||
384 | } | ||
385 | |||
386 | int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg) | ||
387 | { | ||
388 | int err; | ||
389 | void *hdr; | ||
390 | struct nlattr *attrs; | ||
391 | struct nlattr *prop; | ||
392 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
393 | struct tipc_link *bcl = tn->bcl; | ||
394 | |||
395 | if (!bcl) | ||
396 | return 0; | ||
397 | |||
398 | tipc_bcast_lock(net); | ||
399 | |||
400 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, | ||
401 | NLM_F_MULTI, TIPC_NL_LINK_GET); | ||
402 | if (!hdr) | ||
403 | return -EMSGSIZE; | ||
404 | |||
405 | attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK); | ||
406 | if (!attrs) | ||
407 | goto msg_full; | ||
408 | |||
409 | /* The broadcast link is always up */ | ||
410 | if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP)) | ||
411 | goto attr_msg_full; | ||
412 | |||
413 | if (nla_put_flag(msg->skb, TIPC_NLA_LINK_BROADCAST)) | ||
414 | goto attr_msg_full; | ||
415 | if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name)) | ||
416 | goto attr_msg_full; | ||
417 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->rcv_nxt)) | ||
418 | goto attr_msg_full; | ||
419 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->snd_nxt)) | ||
420 | goto attr_msg_full; | ||
421 | |||
422 | prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP); | ||
423 | if (!prop) | ||
424 | goto attr_msg_full; | ||
425 | if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->window)) | ||
426 | goto prop_msg_full; | ||
427 | nla_nest_end(msg->skb, prop); | ||
428 | |||
429 | err = __tipc_nl_add_bc_link_stat(msg->skb, &bcl->stats); | ||
430 | if (err) | ||
431 | goto attr_msg_full; | ||
432 | |||
433 | tipc_bcast_unlock(net); | ||
434 | nla_nest_end(msg->skb, attrs); | ||
435 | genlmsg_end(msg->skb, hdr); | ||
436 | |||
437 | return 0; | ||
438 | |||
439 | prop_msg_full: | ||
440 | nla_nest_cancel(msg->skb, prop); | ||
441 | attr_msg_full: | ||
442 | nla_nest_cancel(msg->skb, attrs); | ||
443 | msg_full: | ||
444 | tipc_bcast_unlock(net); | ||
445 | genlmsg_cancel(msg->skb, hdr); | ||
446 | |||
447 | return -EMSGSIZE; | ||
448 | } | ||
449 | |||
450 | int tipc_bclink_reset_stats(struct net *net) | 335 | int tipc_bclink_reset_stats(struct net *net) |
451 | { | 336 | { |
452 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 337 | struct tipc_link *l = tipc_bc_sndlink(net); |
453 | struct tipc_link *bcl = tn->bcl; | ||
454 | 338 | ||
455 | if (!bcl) | 339 | if (!l) |
456 | return -ENOPROTOOPT; | 340 | return -ENOPROTOOPT; |
457 | 341 | ||
458 | tipc_bcast_lock(net); | 342 | tipc_bcast_lock(net); |
459 | memset(&bcl->stats, 0, sizeof(bcl->stats)); | 343 | tipc_link_reset_stats(l); |
460 | tipc_bcast_unlock(net); | 344 | tipc_bcast_unlock(net); |
461 | return 0; | 345 | return 0; |
462 | } | 346 | } |
@@ -530,9 +414,7 @@ enomem: | |||
530 | 414 | ||
531 | void tipc_bcast_reinit(struct net *net) | 415 | void tipc_bcast_reinit(struct net *net) |
532 | { | 416 | { |
533 | struct tipc_bc_base *b = tipc_bc_base(net); | 417 | tipc_link_reinit(tipc_bc_sndlink(net), tipc_own_addr(net)); |
534 | |||
535 | msg_set_prevnode(b->link->pmsg, tipc_own_addr(net)); | ||
536 | } | 418 | } |
537 | 419 | ||
538 | void tipc_bcast_stop(struct net *net) | 420 | void tipc_bcast_stop(struct net *net) |
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 2855b9356a15..1944c6c00bb9 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
@@ -43,6 +43,7 @@ struct tipc_node; | |||
43 | struct tipc_msg; | 43 | struct tipc_msg; |
44 | struct tipc_nl_msg; | 44 | struct tipc_nl_msg; |
45 | struct tipc_node_map; | 45 | struct tipc_node_map; |
46 | extern const char tipc_bclink_name[]; | ||
46 | 47 | ||
47 | int tipc_bcast_init(struct net *net); | 48 | int tipc_bcast_init(struct net *net); |
48 | void tipc_bcast_reinit(struct net *net); | 49 | void tipc_bcast_reinit(struct net *net); |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 648f2a67f314..802ffad3200d 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -71,7 +71,7 @@ static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = { | |||
71 | [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED } | 71 | [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED } |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr); | 74 | static void bearer_disable(struct net *net, struct tipc_bearer *b); |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * tipc_media_find - locates specified media object by name | 77 | * tipc_media_find - locates specified media object by name |
@@ -107,13 +107,13 @@ static struct tipc_media *media_find_id(u8 type) | |||
107 | void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a) | 107 | void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a) |
108 | { | 108 | { |
109 | char addr_str[MAX_ADDR_STR]; | 109 | char addr_str[MAX_ADDR_STR]; |
110 | struct tipc_media *m_ptr; | 110 | struct tipc_media *m; |
111 | int ret; | 111 | int ret; |
112 | 112 | ||
113 | m_ptr = media_find_id(a->media_id); | 113 | m = media_find_id(a->media_id); |
114 | 114 | ||
115 | if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str))) | 115 | if (m && !m->addr2str(a, addr_str, sizeof(addr_str))) |
116 | ret = scnprintf(buf, len, "%s(%s)", m_ptr->name, addr_str); | 116 | ret = scnprintf(buf, len, "%s(%s)", m->name, addr_str); |
117 | else { | 117 | else { |
118 | u32 i; | 118 | u32 i; |
119 | 119 | ||
@@ -175,13 +175,13 @@ static int bearer_name_validate(const char *name, | |||
175 | struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name) | 175 | struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name) |
176 | { | 176 | { |
177 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 177 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
178 | struct tipc_bearer *b_ptr; | 178 | struct tipc_bearer *b; |
179 | u32 i; | 179 | u32 i; |
180 | 180 | ||
181 | for (i = 0; i < MAX_BEARERS; i++) { | 181 | for (i = 0; i < MAX_BEARERS; i++) { |
182 | b_ptr = rtnl_dereference(tn->bearer_list[i]); | 182 | b = rtnl_dereference(tn->bearer_list[i]); |
183 | if (b_ptr && (!strcmp(b_ptr->name, name))) | 183 | if (b && (!strcmp(b->name, name))) |
184 | return b_ptr; | 184 | return b; |
185 | } | 185 | } |
186 | return NULL; | 186 | return NULL; |
187 | } | 187 | } |
@@ -189,24 +189,24 @@ struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name) | |||
189 | void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest) | 189 | void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest) |
190 | { | 190 | { |
191 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 191 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
192 | struct tipc_bearer *b_ptr; | 192 | struct tipc_bearer *b; |
193 | 193 | ||
194 | rcu_read_lock(); | 194 | rcu_read_lock(); |
195 | b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); | 195 | b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); |
196 | if (b_ptr) | 196 | if (b) |
197 | tipc_disc_add_dest(b_ptr->link_req); | 197 | tipc_disc_add_dest(b->link_req); |
198 | rcu_read_unlock(); | 198 | rcu_read_unlock(); |
199 | } | 199 | } |
200 | 200 | ||
201 | void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) | 201 | void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) |
202 | { | 202 | { |
203 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 203 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
204 | struct tipc_bearer *b_ptr; | 204 | struct tipc_bearer *b; |
205 | 205 | ||
206 | rcu_read_lock(); | 206 | rcu_read_lock(); |
207 | b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); | 207 | b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); |
208 | if (b_ptr) | 208 | if (b) |
209 | tipc_disc_remove_dest(b_ptr->link_req); | 209 | tipc_disc_remove_dest(b->link_req); |
210 | rcu_read_unlock(); | 210 | rcu_read_unlock(); |
211 | } | 211 | } |
212 | 212 | ||
@@ -218,8 +218,8 @@ static int tipc_enable_bearer(struct net *net, const char *name, | |||
218 | struct nlattr *attr[]) | 218 | struct nlattr *attr[]) |
219 | { | 219 | { |
220 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 220 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
221 | struct tipc_bearer *b_ptr; | 221 | struct tipc_bearer *b; |
222 | struct tipc_media *m_ptr; | 222 | struct tipc_media *m; |
223 | struct tipc_bearer_names b_names; | 223 | struct tipc_bearer_names b_names; |
224 | char addr_string[16]; | 224 | char addr_string[16]; |
225 | u32 bearer_id; | 225 | u32 bearer_id; |
@@ -255,31 +255,31 @@ static int tipc_enable_bearer(struct net *net, const char *name, | |||
255 | return -EINVAL; | 255 | return -EINVAL; |
256 | } | 256 | } |
257 | 257 | ||
258 | m_ptr = tipc_media_find(b_names.media_name); | 258 | m = tipc_media_find(b_names.media_name); |
259 | if (!m_ptr) { | 259 | if (!m) { |
260 | pr_warn("Bearer <%s> rejected, media <%s> not registered\n", | 260 | pr_warn("Bearer <%s> rejected, media <%s> not registered\n", |
261 | name, b_names.media_name); | 261 | name, b_names.media_name); |
262 | return -EINVAL; | 262 | return -EINVAL; |
263 | } | 263 | } |
264 | 264 | ||
265 | if (priority == TIPC_MEDIA_LINK_PRI) | 265 | if (priority == TIPC_MEDIA_LINK_PRI) |
266 | priority = m_ptr->priority; | 266 | priority = m->priority; |
267 | 267 | ||
268 | restart: | 268 | restart: |
269 | bearer_id = MAX_BEARERS; | 269 | bearer_id = MAX_BEARERS; |
270 | with_this_prio = 1; | 270 | with_this_prio = 1; |
271 | for (i = MAX_BEARERS; i-- != 0; ) { | 271 | for (i = MAX_BEARERS; i-- != 0; ) { |
272 | b_ptr = rtnl_dereference(tn->bearer_list[i]); | 272 | b = rtnl_dereference(tn->bearer_list[i]); |
273 | if (!b_ptr) { | 273 | if (!b) { |
274 | bearer_id = i; | 274 | bearer_id = i; |
275 | continue; | 275 | continue; |
276 | } | 276 | } |
277 | if (!strcmp(name, b_ptr->name)) { | 277 | if (!strcmp(name, b->name)) { |
278 | pr_warn("Bearer <%s> rejected, already enabled\n", | 278 | pr_warn("Bearer <%s> rejected, already enabled\n", |
279 | name); | 279 | name); |
280 | return -EINVAL; | 280 | return -EINVAL; |
281 | } | 281 | } |
282 | if ((b_ptr->priority == priority) && | 282 | if ((b->priority == priority) && |
283 | (++with_this_prio > 2)) { | 283 | (++with_this_prio > 2)) { |
284 | if (priority-- == 0) { | 284 | if (priority-- == 0) { |
285 | pr_warn("Bearer <%s> rejected, duplicate priority\n", | 285 | pr_warn("Bearer <%s> rejected, duplicate priority\n", |
@@ -297,35 +297,35 @@ restart: | |||
297 | return -EINVAL; | 297 | return -EINVAL; |
298 | } | 298 | } |
299 | 299 | ||
300 | b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC); | 300 | b = kzalloc(sizeof(*b), GFP_ATOMIC); |
301 | if (!b_ptr) | 301 | if (!b) |
302 | return -ENOMEM; | 302 | return -ENOMEM; |
303 | 303 | ||
304 | strcpy(b_ptr->name, name); | 304 | strcpy(b->name, name); |
305 | b_ptr->media = m_ptr; | 305 | b->media = m; |
306 | res = m_ptr->enable_media(net, b_ptr, attr); | 306 | res = m->enable_media(net, b, attr); |
307 | if (res) { | 307 | if (res) { |
308 | pr_warn("Bearer <%s> rejected, enable failure (%d)\n", | 308 | pr_warn("Bearer <%s> rejected, enable failure (%d)\n", |
309 | name, -res); | 309 | name, -res); |
310 | return -EINVAL; | 310 | return -EINVAL; |
311 | } | 311 | } |
312 | 312 | ||
313 | b_ptr->identity = bearer_id; | 313 | b->identity = bearer_id; |
314 | b_ptr->tolerance = m_ptr->tolerance; | 314 | b->tolerance = m->tolerance; |
315 | b_ptr->window = m_ptr->window; | 315 | b->window = m->window; |
316 | b_ptr->domain = disc_domain; | 316 | b->domain = disc_domain; |
317 | b_ptr->net_plane = bearer_id + 'A'; | 317 | b->net_plane = bearer_id + 'A'; |
318 | b_ptr->priority = priority; | 318 | b->priority = priority; |
319 | 319 | ||
320 | res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr); | 320 | res = tipc_disc_create(net, b, &b->bcast_addr); |
321 | if (res) { | 321 | if (res) { |
322 | bearer_disable(net, b_ptr); | 322 | bearer_disable(net, b); |
323 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", | 323 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", |
324 | name); | 324 | name); |
325 | return -EINVAL; | 325 | return -EINVAL; |
326 | } | 326 | } |
327 | 327 | ||
328 | rcu_assign_pointer(tn->bearer_list[bearer_id], b_ptr); | 328 | rcu_assign_pointer(tn->bearer_list[bearer_id], b); |
329 | 329 | ||
330 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 330 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", |
331 | name, | 331 | name, |
@@ -336,11 +336,11 @@ restart: | |||
336 | /** | 336 | /** |
337 | * tipc_reset_bearer - Reset all links established over this bearer | 337 | * tipc_reset_bearer - Reset all links established over this bearer |
338 | */ | 338 | */ |
339 | static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) | 339 | static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b) |
340 | { | 340 | { |
341 | pr_info("Resetting bearer <%s>\n", b_ptr->name); | 341 | pr_info("Resetting bearer <%s>\n", b->name); |
342 | tipc_node_delete_links(net, b_ptr->identity); | 342 | tipc_node_delete_links(net, b->identity); |
343 | tipc_disc_reset(net, b_ptr); | 343 | tipc_disc_reset(net, b); |
344 | return 0; | 344 | return 0; |
345 | } | 345 | } |
346 | 346 | ||
@@ -349,26 +349,26 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) | |||
349 | * | 349 | * |
350 | * Note: This routine assumes caller holds RTNL lock. | 350 | * Note: This routine assumes caller holds RTNL lock. |
351 | */ | 351 | */ |
352 | static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr) | 352 | static void bearer_disable(struct net *net, struct tipc_bearer *b) |
353 | { | 353 | { |
354 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 354 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
355 | u32 i; | 355 | u32 i; |
356 | 356 | ||
357 | pr_info("Disabling bearer <%s>\n", b_ptr->name); | 357 | pr_info("Disabling bearer <%s>\n", b->name); |
358 | b_ptr->media->disable_media(b_ptr); | 358 | b->media->disable_media(b); |
359 | 359 | ||
360 | tipc_node_delete_links(net, b_ptr->identity); | 360 | tipc_node_delete_links(net, b->identity); |
361 | RCU_INIT_POINTER(b_ptr->media_ptr, NULL); | 361 | RCU_INIT_POINTER(b->media_ptr, NULL); |
362 | if (b_ptr->link_req) | 362 | if (b->link_req) |
363 | tipc_disc_delete(b_ptr->link_req); | 363 | tipc_disc_delete(b->link_req); |
364 | 364 | ||
365 | for (i = 0; i < MAX_BEARERS; i++) { | 365 | for (i = 0; i < MAX_BEARERS; i++) { |
366 | if (b_ptr == rtnl_dereference(tn->bearer_list[i])) { | 366 | if (b == rtnl_dereference(tn->bearer_list[i])) { |
367 | RCU_INIT_POINTER(tn->bearer_list[i], NULL); | 367 | RCU_INIT_POINTER(tn->bearer_list[i], NULL); |
368 | break; | 368 | break; |
369 | } | 369 | } |
370 | } | 370 | } |
371 | kfree_rcu(b_ptr, rcu); | 371 | kfree_rcu(b, rcu); |
372 | } | 372 | } |
373 | 373 | ||
374 | int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, | 374 | int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, |
@@ -411,7 +411,7 @@ void tipc_disable_l2_media(struct tipc_bearer *b) | |||
411 | /** | 411 | /** |
412 | * tipc_l2_send_msg - send a TIPC packet out over an L2 interface | 412 | * tipc_l2_send_msg - send a TIPC packet out over an L2 interface |
413 | * @buf: the packet to be sent | 413 | * @buf: the packet to be sent |
414 | * @b_ptr: the bearer through which the packet is to be sent | 414 | * @b: the bearer through which the packet is to be sent |
415 | * @dest: peer destination address | 415 | * @dest: peer destination address |
416 | */ | 416 | */ |
417 | int tipc_l2_send_msg(struct net *net, struct sk_buff *skb, | 417 | int tipc_l2_send_msg(struct net *net, struct sk_buff *skb, |
@@ -532,14 +532,14 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, | |||
532 | static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev, | 532 | static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev, |
533 | struct packet_type *pt, struct net_device *orig_dev) | 533 | struct packet_type *pt, struct net_device *orig_dev) |
534 | { | 534 | { |
535 | struct tipc_bearer *b_ptr; | 535 | struct tipc_bearer *b; |
536 | 536 | ||
537 | rcu_read_lock(); | 537 | rcu_read_lock(); |
538 | b_ptr = rcu_dereference_rtnl(dev->tipc_ptr); | 538 | b = rcu_dereference_rtnl(dev->tipc_ptr); |
539 | if (likely(b_ptr)) { | 539 | if (likely(b)) { |
540 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { | 540 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { |
541 | buf->next = NULL; | 541 | buf->next = NULL; |
542 | tipc_rcv(dev_net(dev), buf, b_ptr); | 542 | tipc_rcv(dev_net(dev), buf, b); |
543 | rcu_read_unlock(); | 543 | rcu_read_unlock(); |
544 | return NET_RX_SUCCESS; | 544 | return NET_RX_SUCCESS; |
545 | } | 545 | } |
@@ -564,13 +564,13 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
564 | { | 564 | { |
565 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 565 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
566 | struct net *net = dev_net(dev); | 566 | struct net *net = dev_net(dev); |
567 | struct tipc_bearer *b_ptr; | 567 | struct tipc_bearer *b; |
568 | 568 | ||
569 | b_ptr = rtnl_dereference(dev->tipc_ptr); | 569 | b = rtnl_dereference(dev->tipc_ptr); |
570 | if (!b_ptr) | 570 | if (!b) |
571 | return NOTIFY_DONE; | 571 | return NOTIFY_DONE; |
572 | 572 | ||
573 | b_ptr->mtu = dev->mtu; | 573 | b->mtu = dev->mtu; |
574 | 574 | ||
575 | switch (evt) { | 575 | switch (evt) { |
576 | case NETDEV_CHANGE: | 576 | case NETDEV_CHANGE: |
@@ -578,16 +578,16 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
578 | break; | 578 | break; |
579 | case NETDEV_GOING_DOWN: | 579 | case NETDEV_GOING_DOWN: |
580 | case NETDEV_CHANGEMTU: | 580 | case NETDEV_CHANGEMTU: |
581 | tipc_reset_bearer(net, b_ptr); | 581 | tipc_reset_bearer(net, b); |
582 | break; | 582 | break; |
583 | case NETDEV_CHANGEADDR: | 583 | case NETDEV_CHANGEADDR: |
584 | b_ptr->media->raw2addr(b_ptr, &b_ptr->addr, | 584 | b->media->raw2addr(b, &b->addr, |
585 | (char *)dev->dev_addr); | 585 | (char *)dev->dev_addr); |
586 | tipc_reset_bearer(net, b_ptr); | 586 | tipc_reset_bearer(net, b); |
587 | break; | 587 | break; |
588 | case NETDEV_UNREGISTER: | 588 | case NETDEV_UNREGISTER: |
589 | case NETDEV_CHANGENAME: | 589 | case NETDEV_CHANGENAME: |
590 | bearer_disable(dev_net(dev), b_ptr); | 590 | bearer_disable(dev_net(dev), b); |
591 | break; | 591 | break; |
592 | } | 592 | } |
593 | return NOTIFY_OK; | 593 | return NOTIFY_OK; |
@@ -623,13 +623,13 @@ void tipc_bearer_cleanup(void) | |||
623 | void tipc_bearer_stop(struct net *net) | 623 | void tipc_bearer_stop(struct net *net) |
624 | { | 624 | { |
625 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 625 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
626 | struct tipc_bearer *b_ptr; | 626 | struct tipc_bearer *b; |
627 | u32 i; | 627 | u32 i; |
628 | 628 | ||
629 | for (i = 0; i < MAX_BEARERS; i++) { | 629 | for (i = 0; i < MAX_BEARERS; i++) { |
630 | b_ptr = rtnl_dereference(tn->bearer_list[i]); | 630 | b = rtnl_dereference(tn->bearer_list[i]); |
631 | if (b_ptr) { | 631 | if (b) { |
632 | bearer_disable(net, b_ptr); | 632 | bearer_disable(net, b); |
633 | tn->bearer_list[i] = NULL; | 633 | tn->bearer_list[i] = NULL; |
634 | } | 634 | } |
635 | } | 635 | } |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 552185bc4773..e31820516774 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -103,11 +103,11 @@ struct tipc_bearer; | |||
103 | */ | 103 | */ |
104 | struct tipc_media { | 104 | struct tipc_media { |
105 | int (*send_msg)(struct net *net, struct sk_buff *buf, | 105 | int (*send_msg)(struct net *net, struct sk_buff *buf, |
106 | struct tipc_bearer *b_ptr, | 106 | struct tipc_bearer *b, |
107 | struct tipc_media_addr *dest); | 107 | struct tipc_media_addr *dest); |
108 | int (*enable_media)(struct net *net, struct tipc_bearer *b_ptr, | 108 | int (*enable_media)(struct net *net, struct tipc_bearer *b, |
109 | struct nlattr *attr[]); | 109 | struct nlattr *attr[]); |
110 | void (*disable_media)(struct tipc_bearer *b_ptr); | 110 | void (*disable_media)(struct tipc_bearer *b); |
111 | int (*addr2str)(struct tipc_media_addr *addr, | 111 | int (*addr2str)(struct tipc_media_addr *addr, |
112 | char *strbuf, | 112 | char *strbuf, |
113 | int bufsz); | 113 | int bufsz); |
@@ -176,7 +176,7 @@ struct tipc_bearer_names { | |||
176 | * TIPC routines available to supported media types | 176 | * TIPC routines available to supported media types |
177 | */ | 177 | */ |
178 | 178 | ||
179 | void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr); | 179 | void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b); |
180 | 180 | ||
181 | /* | 181 | /* |
182 | * Routines made available to TIPC by supported media types | 182 | * Routines made available to TIPC by supported media types |
diff --git a/net/tipc/core.h b/net/tipc/core.h index 18e95a8020cd..5504d63503df 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -118,6 +118,11 @@ static inline int tipc_netid(struct net *net) | |||
118 | return tipc_net(net)->net_id; | 118 | return tipc_net(net)->net_id; |
119 | } | 119 | } |
120 | 120 | ||
121 | static inline struct list_head *tipc_nodes(struct net *net) | ||
122 | { | ||
123 | return &tipc_net(net)->node_list; | ||
124 | } | ||
125 | |||
121 | static inline u16 mod(u16 x) | 126 | static inline u16 mod(u16 x) |
122 | { | 127 | { |
123 | return x & 0xffffu; | 128 | return x & 0xffffu; |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index afe8c47c4085..f1e738e80535 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -75,14 +75,14 @@ struct tipc_link_req { | |||
75 | * tipc_disc_init_msg - initialize a link setup message | 75 | * tipc_disc_init_msg - initialize a link setup message |
76 | * @net: the applicable net namespace | 76 | * @net: the applicable net namespace |
77 | * @type: message type (request or response) | 77 | * @type: message type (request or response) |
78 | * @b_ptr: ptr to bearer issuing message | 78 | * @b: ptr to bearer issuing message |
79 | */ | 79 | */ |
80 | static void tipc_disc_init_msg(struct net *net, struct sk_buff *buf, u32 type, | 80 | static void tipc_disc_init_msg(struct net *net, struct sk_buff *buf, u32 type, |
81 | struct tipc_bearer *b_ptr) | 81 | struct tipc_bearer *b) |
82 | { | 82 | { |
83 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 83 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
84 | struct tipc_msg *msg; | 84 | struct tipc_msg *msg; |
85 | u32 dest_domain = b_ptr->domain; | 85 | u32 dest_domain = b->domain; |
86 | 86 | ||
87 | msg = buf_msg(buf); | 87 | msg = buf_msg(buf); |
88 | tipc_msg_init(tn->own_addr, msg, LINK_CONFIG, type, | 88 | tipc_msg_init(tn->own_addr, msg, LINK_CONFIG, type, |
@@ -92,16 +92,16 @@ static void tipc_disc_init_msg(struct net *net, struct sk_buff *buf, u32 type, | |||
92 | msg_set_node_capabilities(msg, TIPC_NODE_CAPABILITIES); | 92 | msg_set_node_capabilities(msg, TIPC_NODE_CAPABILITIES); |
93 | msg_set_dest_domain(msg, dest_domain); | 93 | msg_set_dest_domain(msg, dest_domain); |
94 | msg_set_bc_netid(msg, tn->net_id); | 94 | msg_set_bc_netid(msg, tn->net_id); |
95 | b_ptr->media->addr2msg(msg_media_addr(msg), &b_ptr->addr); | 95 | b->media->addr2msg(msg_media_addr(msg), &b->addr); |
96 | } | 96 | } |
97 | 97 | ||
98 | /** | 98 | /** |
99 | * disc_dupl_alert - issue node address duplication alert | 99 | * disc_dupl_alert - issue node address duplication alert |
100 | * @b_ptr: pointer to bearer detecting duplication | 100 | * @b: pointer to bearer detecting duplication |
101 | * @node_addr: duplicated node address | 101 | * @node_addr: duplicated node address |
102 | * @media_addr: media address advertised by duplicated node | 102 | * @media_addr: media address advertised by duplicated node |
103 | */ | 103 | */ |
104 | static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr, | 104 | static void disc_dupl_alert(struct tipc_bearer *b, u32 node_addr, |
105 | struct tipc_media_addr *media_addr) | 105 | struct tipc_media_addr *media_addr) |
106 | { | 106 | { |
107 | char node_addr_str[16]; | 107 | char node_addr_str[16]; |
@@ -111,7 +111,7 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr, | |||
111 | tipc_media_addr_printf(media_addr_str, sizeof(media_addr_str), | 111 | tipc_media_addr_printf(media_addr_str, sizeof(media_addr_str), |
112 | media_addr); | 112 | media_addr); |
113 | pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str, | 113 | pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str, |
114 | media_addr_str, b_ptr->name); | 114 | media_addr_str, b->name); |
115 | } | 115 | } |
116 | 116 | ||
117 | /** | 117 | /** |
@@ -261,13 +261,13 @@ exit: | |||
261 | /** | 261 | /** |
262 | * tipc_disc_create - create object to send periodic link setup requests | 262 | * tipc_disc_create - create object to send periodic link setup requests |
263 | * @net: the applicable net namespace | 263 | * @net: the applicable net namespace |
264 | * @b_ptr: ptr to bearer issuing requests | 264 | * @b: ptr to bearer issuing requests |
265 | * @dest: destination address for request messages | 265 | * @dest: destination address for request messages |
266 | * @dest_domain: network domain to which links can be established | 266 | * @dest_domain: network domain to which links can be established |
267 | * | 267 | * |
268 | * Returns 0 if successful, otherwise -errno. | 268 | * Returns 0 if successful, otherwise -errno. |
269 | */ | 269 | */ |
270 | int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr, | 270 | int tipc_disc_create(struct net *net, struct tipc_bearer *b, |
271 | struct tipc_media_addr *dest) | 271 | struct tipc_media_addr *dest) |
272 | { | 272 | { |
273 | struct tipc_link_req *req; | 273 | struct tipc_link_req *req; |
@@ -282,17 +282,17 @@ int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr, | |||
282 | return -ENOMEM; | 282 | return -ENOMEM; |
283 | } | 283 | } |
284 | 284 | ||
285 | tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b_ptr); | 285 | tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b); |
286 | memcpy(&req->dest, dest, sizeof(*dest)); | 286 | memcpy(&req->dest, dest, sizeof(*dest)); |
287 | req->net = net; | 287 | req->net = net; |
288 | req->bearer_id = b_ptr->identity; | 288 | req->bearer_id = b->identity; |
289 | req->domain = b_ptr->domain; | 289 | req->domain = b->domain; |
290 | req->num_nodes = 0; | 290 | req->num_nodes = 0; |
291 | req->timer_intv = TIPC_LINK_REQ_INIT; | 291 | req->timer_intv = TIPC_LINK_REQ_INIT; |
292 | spin_lock_init(&req->lock); | 292 | spin_lock_init(&req->lock); |
293 | setup_timer(&req->timer, disc_timeout, (unsigned long)req); | 293 | setup_timer(&req->timer, disc_timeout, (unsigned long)req); |
294 | mod_timer(&req->timer, jiffies + req->timer_intv); | 294 | mod_timer(&req->timer, jiffies + req->timer_intv); |
295 | b_ptr->link_req = req; | 295 | b->link_req = req; |
296 | skb = skb_clone(req->buf, GFP_ATOMIC); | 296 | skb = skb_clone(req->buf, GFP_ATOMIC); |
297 | if (skb) | 297 | if (skb) |
298 | tipc_bearer_xmit_skb(net, req->bearer_id, skb, &req->dest); | 298 | tipc_bearer_xmit_skb(net, req->bearer_id, skb, &req->dest); |
@@ -313,19 +313,19 @@ void tipc_disc_delete(struct tipc_link_req *req) | |||
313 | /** | 313 | /** |
314 | * tipc_disc_reset - reset object to send periodic link setup requests | 314 | * tipc_disc_reset - reset object to send periodic link setup requests |
315 | * @net: the applicable net namespace | 315 | * @net: the applicable net namespace |
316 | * @b_ptr: ptr to bearer issuing requests | 316 | * @b: ptr to bearer issuing requests |
317 | * @dest_domain: network domain to which links can be established | 317 | * @dest_domain: network domain to which links can be established |
318 | */ | 318 | */ |
319 | void tipc_disc_reset(struct net *net, struct tipc_bearer *b_ptr) | 319 | void tipc_disc_reset(struct net *net, struct tipc_bearer *b) |
320 | { | 320 | { |
321 | struct tipc_link_req *req = b_ptr->link_req; | 321 | struct tipc_link_req *req = b->link_req; |
322 | struct sk_buff *skb; | 322 | struct sk_buff *skb; |
323 | 323 | ||
324 | spin_lock_bh(&req->lock); | 324 | spin_lock_bh(&req->lock); |
325 | tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b_ptr); | 325 | tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b); |
326 | req->net = net; | 326 | req->net = net; |
327 | req->bearer_id = b_ptr->identity; | 327 | req->bearer_id = b->identity; |
328 | req->domain = b_ptr->domain; | 328 | req->domain = b->domain; |
329 | req->num_nodes = 0; | 329 | req->num_nodes = 0; |
330 | req->timer_intv = TIPC_LINK_REQ_INIT; | 330 | req->timer_intv = TIPC_LINK_REQ_INIT; |
331 | mod_timer(&req->timer, jiffies + req->timer_intv); | 331 | mod_timer(&req->timer, jiffies + req->timer_intv); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 9efbdbde2b08..0c2944fb9ae0 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -45,28 +45,156 @@ | |||
45 | 45 | ||
46 | #include <linux/pkt_sched.h> | 46 | #include <linux/pkt_sched.h> |
47 | 47 | ||
48 | struct tipc_stats { | ||
49 | u32 sent_info; /* used in counting # sent packets */ | ||
50 | u32 recv_info; /* used in counting # recv'd packets */ | ||
51 | u32 sent_states; | ||
52 | u32 recv_states; | ||
53 | u32 sent_probes; | ||
54 | u32 recv_probes; | ||
55 | u32 sent_nacks; | ||
56 | u32 recv_nacks; | ||
57 | u32 sent_acks; | ||
58 | u32 sent_bundled; | ||
59 | u32 sent_bundles; | ||
60 | u32 recv_bundled; | ||
61 | u32 recv_bundles; | ||
62 | u32 retransmitted; | ||
63 | u32 sent_fragmented; | ||
64 | u32 sent_fragments; | ||
65 | u32 recv_fragmented; | ||
66 | u32 recv_fragments; | ||
67 | u32 link_congs; /* # port sends blocked by congestion */ | ||
68 | u32 deferred_recv; | ||
69 | u32 duplicates; | ||
70 | u32 max_queue_sz; /* send queue size high water mark */ | ||
71 | u32 accu_queue_sz; /* used for send queue size profiling */ | ||
72 | u32 queue_sz_counts; /* used for send queue size profiling */ | ||
73 | u32 msg_length_counts; /* used for message length profiling */ | ||
74 | u32 msg_lengths_total; /* used for message length profiling */ | ||
75 | u32 msg_length_profile[7]; /* used for msg. length profiling */ | ||
76 | }; | ||
77 | |||
78 | /** | ||
79 | * struct tipc_link - TIPC link data structure | ||
80 | * @addr: network address of link's peer node | ||
81 | * @name: link name character string | ||
82 | * @media_addr: media address to use when sending messages over link | ||
83 | * @timer: link timer | ||
84 | * @net: pointer to namespace struct | ||
85 | * @refcnt: reference counter for permanent references (owner node & timer) | ||
86 | * @peer_session: link session # being used by peer end of link | ||
87 | * @peer_bearer_id: bearer id used by link's peer endpoint | ||
88 | * @bearer_id: local bearer id used by link | ||
89 | * @tolerance: minimum link continuity loss needed to reset link [in ms] | ||
90 | * @keepalive_intv: link keepalive timer interval | ||
91 | * @abort_limit: # of unacknowledged continuity probes needed to reset link | ||
92 | * @state: current state of link FSM | ||
93 | * @peer_caps: bitmap describing capabilities of peer node | ||
94 | * @silent_intv_cnt: # of timer intervals without any reception from peer | ||
95 | * @proto_msg: template for control messages generated by link | ||
96 | * @pmsg: convenience pointer to "proto_msg" field | ||
97 | * @priority: current link priority | ||
98 | * @net_plane: current link network plane ('A' through 'H') | ||
99 | * @backlog_limit: backlog queue congestion thresholds (indexed by importance) | ||
100 | * @exp_msg_count: # of tunnelled messages expected during link changeover | ||
101 | * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset | ||
102 | * @mtu: current maximum packet size for this link | ||
103 | * @advertised_mtu: advertised own mtu when link is being established | ||
104 | * @transmitq: queue for sent, non-acked messages | ||
105 | * @backlogq: queue for messages waiting to be sent | ||
106 | * @snt_nxt: next sequence number to use for outbound messages | ||
107 | * @last_retransmitted: sequence number of most recently retransmitted message | ||
108 | * @stale_count: # of identical retransmit requests made by peer | ||
109 | * @ackers: # of peers that needs to ack each packet before it can be released | ||
110 | * @acked: # last packet acked by a certain peer. Used for broadcast. | ||
111 | * @rcv_nxt: next sequence number to expect for inbound messages | ||
112 | * @deferred_queue: deferred queue saved OOS b'cast message received from node | ||
113 | * @unacked_window: # of inbound messages rx'd without ack'ing back to peer | ||
114 | * @inputq: buffer queue for messages to be delivered upwards | ||
115 | * @namedq: buffer queue for name table messages to be delivered upwards | ||
116 | * @next_out: ptr to first unsent outbound message in queue | ||
117 | * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate | ||
118 | * @long_msg_seq_no: next identifier to use for outbound fragmented messages | ||
119 | * @reasm_buf: head of partially reassembled inbound message fragments | ||
120 | * @bc_rcvr: marks that this is a broadcast receiver link | ||
121 | * @stats: collects statistics regarding link activity | ||
122 | */ | ||
123 | struct tipc_link { | ||
124 | u32 addr; | ||
125 | char name[TIPC_MAX_LINK_NAME]; | ||
126 | struct tipc_media_addr *media_addr; | ||
127 | struct net *net; | ||
128 | |||
129 | /* Management and link supervision data */ | ||
130 | u32 peer_session; | ||
131 | u32 peer_bearer_id; | ||
132 | u32 bearer_id; | ||
133 | u32 tolerance; | ||
134 | unsigned long keepalive_intv; | ||
135 | u32 abort_limit; | ||
136 | u32 state; | ||
137 | u16 peer_caps; | ||
138 | bool active; | ||
139 | u32 silent_intv_cnt; | ||
140 | struct { | ||
141 | unchar hdr[INT_H_SIZE]; | ||
142 | unchar body[TIPC_MAX_IF_NAME]; | ||
143 | } proto_msg; | ||
144 | struct tipc_msg *pmsg; | ||
145 | u32 priority; | ||
146 | char net_plane; | ||
147 | |||
148 | /* Failover/synch */ | ||
149 | u16 drop_point; | ||
150 | struct sk_buff *failover_reasm_skb; | ||
151 | |||
152 | /* Max packet negotiation */ | ||
153 | u16 mtu; | ||
154 | u16 advertised_mtu; | ||
155 | |||
156 | /* Sending */ | ||
157 | struct sk_buff_head transmq; | ||
158 | struct sk_buff_head backlogq; | ||
159 | struct { | ||
160 | u16 len; | ||
161 | u16 limit; | ||
162 | } backlog[5]; | ||
163 | u16 snd_nxt; | ||
164 | u16 last_retransm; | ||
165 | u16 window; | ||
166 | u32 stale_count; | ||
167 | |||
168 | /* Reception */ | ||
169 | u16 rcv_nxt; | ||
170 | u32 rcv_unacked; | ||
171 | struct sk_buff_head deferdq; | ||
172 | struct sk_buff_head *inputq; | ||
173 | struct sk_buff_head *namedq; | ||
174 | |||
175 | /* Congestion handling */ | ||
176 | struct sk_buff_head wakeupq; | ||
177 | |||
178 | /* Fragmentation/reassembly */ | ||
179 | struct sk_buff *reasm_buf; | ||
180 | |||
181 | /* Broadcast */ | ||
182 | u16 ackers; | ||
183 | u16 acked; | ||
184 | struct tipc_link *bc_rcvlink; | ||
185 | struct tipc_link *bc_sndlink; | ||
186 | int nack_state; | ||
187 | bool bc_peer_is_up; | ||
188 | |||
189 | /* Statistics */ | ||
190 | struct tipc_stats stats; | ||
191 | }; | ||
192 | |||
48 | /* | 193 | /* |
49 | * Error message prefixes | 194 | * Error message prefixes |
50 | */ | 195 | */ |
51 | static const char *link_co_err = "Link tunneling error, "; | 196 | static const char *link_co_err = "Link tunneling error, "; |
52 | static const char *link_rst_msg = "Resetting link "; | 197 | static const char *link_rst_msg = "Resetting link "; |
53 | static const char tipc_bclink_name[] = "broadcast-link"; | ||
54 | |||
55 | static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { | ||
56 | [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC }, | ||
57 | [TIPC_NLA_LINK_NAME] = { | ||
58 | .type = NLA_STRING, | ||
59 | .len = TIPC_MAX_LINK_NAME | ||
60 | }, | ||
61 | [TIPC_NLA_LINK_MTU] = { .type = NLA_U32 }, | ||
62 | [TIPC_NLA_LINK_BROADCAST] = { .type = NLA_FLAG }, | ||
63 | [TIPC_NLA_LINK_UP] = { .type = NLA_FLAG }, | ||
64 | [TIPC_NLA_LINK_ACTIVE] = { .type = NLA_FLAG }, | ||
65 | [TIPC_NLA_LINK_PROP] = { .type = NLA_NESTED }, | ||
66 | [TIPC_NLA_LINK_STATS] = { .type = NLA_NESTED }, | ||
67 | [TIPC_NLA_LINK_RX] = { .type = NLA_U32 }, | ||
68 | [TIPC_NLA_LINK_TX] = { .type = NLA_U32 } | ||
69 | }; | ||
70 | 198 | ||
71 | /* Properties valid for media, bearar and link */ | 199 | /* Properties valid for media, bearar and link */ |
72 | static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { | 200 | static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { |
@@ -117,8 +245,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
117 | static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | 245 | static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, |
118 | u16 rcvgap, int tolerance, int priority, | 246 | u16 rcvgap, int tolerance, int priority, |
119 | struct sk_buff_head *xmitq); | 247 | struct sk_buff_head *xmitq); |
120 | static void link_reset_statistics(struct tipc_link *l_ptr); | 248 | static void link_print(struct tipc_link *l, const char *str); |
121 | static void link_print(struct tipc_link *l_ptr, const char *str); | ||
122 | static void tipc_link_build_nack_msg(struct tipc_link *l, | 249 | static void tipc_link_build_nack_msg(struct tipc_link *l, |
123 | struct sk_buff_head *xmitq); | 250 | struct sk_buff_head *xmitq); |
124 | static void tipc_link_build_bc_init_msg(struct tipc_link *l, | 251 | static void tipc_link_build_bc_init_msg(struct tipc_link *l, |
@@ -183,6 +310,36 @@ void tipc_link_set_active(struct tipc_link *l, bool active) | |||
183 | l->active = active; | 310 | l->active = active; |
184 | } | 311 | } |
185 | 312 | ||
313 | u32 tipc_link_id(struct tipc_link *l) | ||
314 | { | ||
315 | return l->peer_bearer_id << 16 | l->bearer_id; | ||
316 | } | ||
317 | |||
318 | int tipc_link_window(struct tipc_link *l) | ||
319 | { | ||
320 | return l->window; | ||
321 | } | ||
322 | |||
323 | int tipc_link_prio(struct tipc_link *l) | ||
324 | { | ||
325 | return l->priority; | ||
326 | } | ||
327 | |||
328 | unsigned long tipc_link_tolerance(struct tipc_link *l) | ||
329 | { | ||
330 | return l->tolerance; | ||
331 | } | ||
332 | |||
333 | struct sk_buff_head *tipc_link_inputq(struct tipc_link *l) | ||
334 | { | ||
335 | return l->inputq; | ||
336 | } | ||
337 | |||
338 | char tipc_link_plane(struct tipc_link *l) | ||
339 | { | ||
340 | return l->net_plane; | ||
341 | } | ||
342 | |||
186 | void tipc_link_add_bc_peer(struct tipc_link *snd_l, | 343 | void tipc_link_add_bc_peer(struct tipc_link *snd_l, |
187 | struct tipc_link *uc_l, | 344 | struct tipc_link *uc_l, |
188 | struct sk_buff_head *xmitq) | 345 | struct sk_buff_head *xmitq) |
@@ -191,6 +348,7 @@ void tipc_link_add_bc_peer(struct tipc_link *snd_l, | |||
191 | 348 | ||
192 | snd_l->ackers++; | 349 | snd_l->ackers++; |
193 | rcv_l->acked = snd_l->snd_nxt - 1; | 350 | rcv_l->acked = snd_l->snd_nxt - 1; |
351 | snd_l->state = LINK_ESTABLISHED; | ||
194 | tipc_link_build_bc_init_msg(uc_l, xmitq); | 352 | tipc_link_build_bc_init_msg(uc_l, xmitq); |
195 | } | 353 | } |
196 | 354 | ||
@@ -206,6 +364,7 @@ void tipc_link_remove_bc_peer(struct tipc_link *snd_l, | |||
206 | rcv_l->state = LINK_RESET; | 364 | rcv_l->state = LINK_RESET; |
207 | if (!snd_l->ackers) { | 365 | if (!snd_l->ackers) { |
208 | tipc_link_reset(snd_l); | 366 | tipc_link_reset(snd_l); |
367 | snd_l->state = LINK_RESET; | ||
209 | __skb_queue_purge(xmitq); | 368 | __skb_queue_purge(xmitq); |
210 | } | 369 | } |
211 | } | 370 | } |
@@ -225,11 +384,31 @@ int tipc_link_mtu(struct tipc_link *l) | |||
225 | return l->mtu; | 384 | return l->mtu; |
226 | } | 385 | } |
227 | 386 | ||
387 | u16 tipc_link_rcv_nxt(struct tipc_link *l) | ||
388 | { | ||
389 | return l->rcv_nxt; | ||
390 | } | ||
391 | |||
392 | u16 tipc_link_acked(struct tipc_link *l) | ||
393 | { | ||
394 | return l->acked; | ||
395 | } | ||
396 | |||
397 | char *tipc_link_name(struct tipc_link *l) | ||
398 | { | ||
399 | return l->name; | ||
400 | } | ||
401 | |||
228 | static u32 link_own_addr(struct tipc_link *l) | 402 | static u32 link_own_addr(struct tipc_link *l) |
229 | { | 403 | { |
230 | return msg_prevnode(l->pmsg); | 404 | return msg_prevnode(l->pmsg); |
231 | } | 405 | } |
232 | 406 | ||
407 | void tipc_link_reinit(struct tipc_link *l, u32 addr) | ||
408 | { | ||
409 | msg_set_prevnode(l->pmsg, addr); | ||
410 | } | ||
411 | |||
233 | /** | 412 | /** |
234 | * tipc_link_create - create a new link | 413 | * tipc_link_create - create a new link |
235 | * @n: pointer to associated node | 414 | * @n: pointer to associated node |
@@ -692,7 +871,7 @@ void tipc_link_reset(struct tipc_link *l) | |||
692 | l->stats.recv_info = 0; | 871 | l->stats.recv_info = 0; |
693 | l->stale_count = 0; | 872 | l->stale_count = 0; |
694 | l->bc_peer_is_up = false; | 873 | l->bc_peer_is_up = false; |
695 | link_reset_statistics(l); | 874 | tipc_link_reset_stats(l); |
696 | } | 875 | } |
697 | 876 | ||
698 | /** | 877 | /** |
@@ -1085,8 +1264,9 @@ drop: | |||
1085 | /* | 1264 | /* |
1086 | * Send protocol message to the other endpoint. | 1265 | * Send protocol message to the other endpoint. |
1087 | */ | 1266 | */ |
1088 | void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, int probe_msg, | 1267 | static void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, |
1089 | u32 gap, u32 tolerance, u32 priority) | 1268 | int probe_msg, u32 gap, u32 tolerance, |
1269 | u32 priority) | ||
1090 | { | 1270 | { |
1091 | struct sk_buff *skb = NULL; | 1271 | struct sk_buff *skb = NULL; |
1092 | struct sk_buff_head xmitq; | 1272 | struct sk_buff_head xmitq; |
@@ -1260,6 +1440,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1260 | /* fall thru' */ | 1440 | /* fall thru' */ |
1261 | 1441 | ||
1262 | case ACTIVATE_MSG: | 1442 | case ACTIVATE_MSG: |
1443 | skb_linearize(skb); | ||
1444 | hdr = buf_msg(skb); | ||
1263 | 1445 | ||
1264 | /* Complete own link name with peer's interface name */ | 1446 | /* Complete own link name with peer's interface name */ |
1265 | if_name = strrchr(l->name, ':') + 1; | 1447 | if_name = strrchr(l->name, ':') + 1; |
@@ -1525,53 +1707,17 @@ void tipc_link_set_queue_limits(struct tipc_link *l, u32 win) | |||
1525 | l->backlog[TIPC_SYSTEM_IMPORTANCE].limit = max_bulk; | 1707 | l->backlog[TIPC_SYSTEM_IMPORTANCE].limit = max_bulk; |
1526 | } | 1708 | } |
1527 | 1709 | ||
1528 | /* tipc_link_find_owner - locate owner node of link by link's name | ||
1529 | * @net: the applicable net namespace | ||
1530 | * @name: pointer to link name string | ||
1531 | * @bearer_id: pointer to index in 'node->links' array where the link was found. | ||
1532 | * | ||
1533 | * Returns pointer to node owning the link, or 0 if no matching link is found. | ||
1534 | */ | ||
1535 | static struct tipc_node *tipc_link_find_owner(struct net *net, | ||
1536 | const char *link_name, | ||
1537 | unsigned int *bearer_id) | ||
1538 | { | ||
1539 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
1540 | struct tipc_link *l_ptr; | ||
1541 | struct tipc_node *n_ptr; | ||
1542 | struct tipc_node *found_node = NULL; | ||
1543 | int i; | ||
1544 | |||
1545 | *bearer_id = 0; | ||
1546 | rcu_read_lock(); | ||
1547 | list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { | ||
1548 | tipc_node_lock(n_ptr); | ||
1549 | for (i = 0; i < MAX_BEARERS; i++) { | ||
1550 | l_ptr = n_ptr->links[i].link; | ||
1551 | if (l_ptr && !strcmp(l_ptr->name, link_name)) { | ||
1552 | *bearer_id = i; | ||
1553 | found_node = n_ptr; | ||
1554 | break; | ||
1555 | } | ||
1556 | } | ||
1557 | tipc_node_unlock(n_ptr); | ||
1558 | if (found_node) | ||
1559 | break; | ||
1560 | } | ||
1561 | rcu_read_unlock(); | ||
1562 | |||
1563 | return found_node; | ||
1564 | } | ||
1565 | |||
1566 | /** | 1710 | /** |
1567 | * link_reset_statistics - reset link statistics | 1711 | * link_reset_stats - reset link statistics |
1568 | * @l_ptr: pointer to link | 1712 | * @l: pointer to link |
1569 | */ | 1713 | */ |
1570 | static void link_reset_statistics(struct tipc_link *l_ptr) | 1714 | void tipc_link_reset_stats(struct tipc_link *l) |
1571 | { | 1715 | { |
1572 | memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); | 1716 | memset(&l->stats, 0, sizeof(l->stats)); |
1573 | l_ptr->stats.sent_info = l_ptr->snd_nxt; | 1717 | if (!link_is_bc_sndlink(l)) { |
1574 | l_ptr->stats.recv_info = l_ptr->rcv_nxt; | 1718 | l->stats.sent_info = l->snd_nxt; |
1719 | l->stats.recv_info = l->rcv_nxt; | ||
1720 | } | ||
1575 | } | 1721 | } |
1576 | 1722 | ||
1577 | static void link_print(struct tipc_link *l, const char *str) | 1723 | static void link_print(struct tipc_link *l, const char *str) |
@@ -1624,84 +1770,6 @@ int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]) | |||
1624 | return 0; | 1770 | return 0; |
1625 | } | 1771 | } |
1626 | 1772 | ||
1627 | int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) | ||
1628 | { | ||
1629 | int err; | ||
1630 | int res = 0; | ||
1631 | int bearer_id; | ||
1632 | char *name; | ||
1633 | struct tipc_link *link; | ||
1634 | struct tipc_node *node; | ||
1635 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; | ||
1636 | struct net *net = sock_net(skb->sk); | ||
1637 | |||
1638 | if (!info->attrs[TIPC_NLA_LINK]) | ||
1639 | return -EINVAL; | ||
1640 | |||
1641 | err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, | ||
1642 | info->attrs[TIPC_NLA_LINK], | ||
1643 | tipc_nl_link_policy); | ||
1644 | if (err) | ||
1645 | return err; | ||
1646 | |||
1647 | if (!attrs[TIPC_NLA_LINK_NAME]) | ||
1648 | return -EINVAL; | ||
1649 | |||
1650 | name = nla_data(attrs[TIPC_NLA_LINK_NAME]); | ||
1651 | |||
1652 | if (strcmp(name, tipc_bclink_name) == 0) | ||
1653 | return tipc_nl_bc_link_set(net, attrs); | ||
1654 | |||
1655 | node = tipc_link_find_owner(net, name, &bearer_id); | ||
1656 | if (!node) | ||
1657 | return -EINVAL; | ||
1658 | |||
1659 | tipc_node_lock(node); | ||
1660 | |||
1661 | link = node->links[bearer_id].link; | ||
1662 | if (!link) { | ||
1663 | res = -EINVAL; | ||
1664 | goto out; | ||
1665 | } | ||
1666 | |||
1667 | if (attrs[TIPC_NLA_LINK_PROP]) { | ||
1668 | struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; | ||
1669 | |||
1670 | err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP], | ||
1671 | props); | ||
1672 | if (err) { | ||
1673 | res = err; | ||
1674 | goto out; | ||
1675 | } | ||
1676 | |||
1677 | if (props[TIPC_NLA_PROP_TOL]) { | ||
1678 | u32 tol; | ||
1679 | |||
1680 | tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); | ||
1681 | link->tolerance = tol; | ||
1682 | tipc_link_proto_xmit(link, STATE_MSG, 0, 0, tol, 0); | ||
1683 | } | ||
1684 | if (props[TIPC_NLA_PROP_PRIO]) { | ||
1685 | u32 prio; | ||
1686 | |||
1687 | prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); | ||
1688 | link->priority = prio; | ||
1689 | tipc_link_proto_xmit(link, STATE_MSG, 0, 0, 0, prio); | ||
1690 | } | ||
1691 | if (props[TIPC_NLA_PROP_WIN]) { | ||
1692 | u32 win; | ||
1693 | |||
1694 | win = nla_get_u32(props[TIPC_NLA_PROP_WIN]); | ||
1695 | tipc_link_set_queue_limits(link, win); | ||
1696 | } | ||
1697 | } | ||
1698 | |||
1699 | out: | ||
1700 | tipc_node_unlock(node); | ||
1701 | |||
1702 | return res; | ||
1703 | } | ||
1704 | |||
1705 | static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s) | 1773 | static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s) |
1706 | { | 1774 | { |
1707 | int i; | 1775 | int i; |
@@ -1768,8 +1836,8 @@ msg_full: | |||
1768 | } | 1836 | } |
1769 | 1837 | ||
1770 | /* Caller should hold appropriate locks to protect the link */ | 1838 | /* Caller should hold appropriate locks to protect the link */ |
1771 | static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, | 1839 | int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, |
1772 | struct tipc_link *link, int nlflags) | 1840 | struct tipc_link *link, int nlflags) |
1773 | { | 1841 | { |
1774 | int err; | 1842 | int err; |
1775 | void *hdr; | 1843 | void *hdr; |
@@ -1838,198 +1906,134 @@ msg_full: | |||
1838 | return -EMSGSIZE; | 1906 | return -EMSGSIZE; |
1839 | } | 1907 | } |
1840 | 1908 | ||
1841 | /* Caller should hold node lock */ | 1909 | static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb, |
1842 | static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg, | 1910 | struct tipc_stats *stats) |
1843 | struct tipc_node *node, u32 *prev_link) | ||
1844 | { | 1911 | { |
1845 | u32 i; | 1912 | int i; |
1846 | int err; | 1913 | struct nlattr *nest; |
1847 | |||
1848 | for (i = *prev_link; i < MAX_BEARERS; i++) { | ||
1849 | *prev_link = i; | ||
1850 | |||
1851 | if (!node->links[i].link) | ||
1852 | continue; | ||
1853 | 1914 | ||
1854 | err = __tipc_nl_add_link(net, msg, | 1915 | struct nla_map { |
1855 | node->links[i].link, NLM_F_MULTI); | 1916 | __u32 key; |
1856 | if (err) | 1917 | __u32 val; |
1857 | return err; | 1918 | }; |
1858 | } | ||
1859 | *prev_link = 0; | ||
1860 | 1919 | ||
1861 | return 0; | 1920 | struct nla_map map[] = { |
1862 | } | 1921 | {TIPC_NLA_STATS_RX_INFO, stats->recv_info}, |
1922 | {TIPC_NLA_STATS_RX_FRAGMENTS, stats->recv_fragments}, | ||
1923 | {TIPC_NLA_STATS_RX_FRAGMENTED, stats->recv_fragmented}, | ||
1924 | {TIPC_NLA_STATS_RX_BUNDLES, stats->recv_bundles}, | ||
1925 | {TIPC_NLA_STATS_RX_BUNDLED, stats->recv_bundled}, | ||
1926 | {TIPC_NLA_STATS_TX_INFO, stats->sent_info}, | ||
1927 | {TIPC_NLA_STATS_TX_FRAGMENTS, stats->sent_fragments}, | ||
1928 | {TIPC_NLA_STATS_TX_FRAGMENTED, stats->sent_fragmented}, | ||
1929 | {TIPC_NLA_STATS_TX_BUNDLES, stats->sent_bundles}, | ||
1930 | {TIPC_NLA_STATS_TX_BUNDLED, stats->sent_bundled}, | ||
1931 | {TIPC_NLA_STATS_RX_NACKS, stats->recv_nacks}, | ||
1932 | {TIPC_NLA_STATS_RX_DEFERRED, stats->deferred_recv}, | ||
1933 | {TIPC_NLA_STATS_TX_NACKS, stats->sent_nacks}, | ||
1934 | {TIPC_NLA_STATS_TX_ACKS, stats->sent_acks}, | ||
1935 | {TIPC_NLA_STATS_RETRANSMITTED, stats->retransmitted}, | ||
1936 | {TIPC_NLA_STATS_DUPLICATES, stats->duplicates}, | ||
1937 | {TIPC_NLA_STATS_LINK_CONGS, stats->link_congs}, | ||
1938 | {TIPC_NLA_STATS_MAX_QUEUE, stats->max_queue_sz}, | ||
1939 | {TIPC_NLA_STATS_AVG_QUEUE, stats->queue_sz_counts ? | ||
1940 | (stats->accu_queue_sz / stats->queue_sz_counts) : 0} | ||
1941 | }; | ||
1863 | 1942 | ||
1864 | int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) | 1943 | nest = nla_nest_start(skb, TIPC_NLA_LINK_STATS); |
1865 | { | 1944 | if (!nest) |
1866 | struct net *net = sock_net(skb->sk); | 1945 | return -EMSGSIZE; |
1867 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
1868 | struct tipc_node *node; | ||
1869 | struct tipc_nl_msg msg; | ||
1870 | u32 prev_node = cb->args[0]; | ||
1871 | u32 prev_link = cb->args[1]; | ||
1872 | int done = cb->args[2]; | ||
1873 | int err; | ||
1874 | 1946 | ||
1875 | if (done) | 1947 | for (i = 0; i < ARRAY_SIZE(map); i++) |
1876 | return 0; | 1948 | if (nla_put_u32(skb, map[i].key, map[i].val)) |
1949 | goto msg_full; | ||
1877 | 1950 | ||
1878 | msg.skb = skb; | 1951 | nla_nest_end(skb, nest); |
1879 | msg.portid = NETLINK_CB(cb->skb).portid; | ||
1880 | msg.seq = cb->nlh->nlmsg_seq; | ||
1881 | |||
1882 | rcu_read_lock(); | ||
1883 | if (prev_node) { | ||
1884 | node = tipc_node_find(net, prev_node); | ||
1885 | if (!node) { | ||
1886 | /* We never set seq or call nl_dump_check_consistent() | ||
1887 | * this means that setting prev_seq here will cause the | ||
1888 | * consistence check to fail in the netlink callback | ||
1889 | * handler. Resulting in the last NLMSG_DONE message | ||
1890 | * having the NLM_F_DUMP_INTR flag set. | ||
1891 | */ | ||
1892 | cb->prev_seq = 1; | ||
1893 | goto out; | ||
1894 | } | ||
1895 | tipc_node_put(node); | ||
1896 | |||
1897 | list_for_each_entry_continue_rcu(node, &tn->node_list, | ||
1898 | list) { | ||
1899 | tipc_node_lock(node); | ||
1900 | err = __tipc_nl_add_node_links(net, &msg, node, | ||
1901 | &prev_link); | ||
1902 | tipc_node_unlock(node); | ||
1903 | if (err) | ||
1904 | goto out; | ||
1905 | |||
1906 | prev_node = node->addr; | ||
1907 | } | ||
1908 | } else { | ||
1909 | err = tipc_nl_add_bc_link(net, &msg); | ||
1910 | if (err) | ||
1911 | goto out; | ||
1912 | |||
1913 | list_for_each_entry_rcu(node, &tn->node_list, list) { | ||
1914 | tipc_node_lock(node); | ||
1915 | err = __tipc_nl_add_node_links(net, &msg, node, | ||
1916 | &prev_link); | ||
1917 | tipc_node_unlock(node); | ||
1918 | if (err) | ||
1919 | goto out; | ||
1920 | |||
1921 | prev_node = node->addr; | ||
1922 | } | ||
1923 | } | ||
1924 | done = 1; | ||
1925 | out: | ||
1926 | rcu_read_unlock(); | ||
1927 | 1952 | ||
1928 | cb->args[0] = prev_node; | 1953 | return 0; |
1929 | cb->args[1] = prev_link; | 1954 | msg_full: |
1930 | cb->args[2] = done; | 1955 | nla_nest_cancel(skb, nest); |
1931 | 1956 | ||
1932 | return skb->len; | 1957 | return -EMSGSIZE; |
1933 | } | 1958 | } |
1934 | 1959 | ||
1935 | int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) | 1960 | int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg) |
1936 | { | 1961 | { |
1937 | struct net *net = genl_info_net(info); | ||
1938 | struct tipc_nl_msg msg; | ||
1939 | char *name; | ||
1940 | int err; | 1962 | int err; |
1963 | void *hdr; | ||
1964 | struct nlattr *attrs; | ||
1965 | struct nlattr *prop; | ||
1966 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
1967 | struct tipc_link *bcl = tn->bcl; | ||
1941 | 1968 | ||
1942 | msg.portid = info->snd_portid; | 1969 | if (!bcl) |
1943 | msg.seq = info->snd_seq; | 1970 | return 0; |
1944 | |||
1945 | if (!info->attrs[TIPC_NLA_LINK_NAME]) | ||
1946 | return -EINVAL; | ||
1947 | name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]); | ||
1948 | 1971 | ||
1949 | msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 1972 | tipc_bcast_lock(net); |
1950 | if (!msg.skb) | ||
1951 | return -ENOMEM; | ||
1952 | 1973 | ||
1953 | if (strcmp(name, tipc_bclink_name) == 0) { | 1974 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, |
1954 | err = tipc_nl_add_bc_link(net, &msg); | 1975 | NLM_F_MULTI, TIPC_NL_LINK_GET); |
1955 | if (err) { | 1976 | if (!hdr) |
1956 | nlmsg_free(msg.skb); | 1977 | return -EMSGSIZE; |
1957 | return err; | ||
1958 | } | ||
1959 | } else { | ||
1960 | int bearer_id; | ||
1961 | struct tipc_node *node; | ||
1962 | struct tipc_link *link; | ||
1963 | 1978 | ||
1964 | node = tipc_link_find_owner(net, name, &bearer_id); | 1979 | attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK); |
1965 | if (!node) | 1980 | if (!attrs) |
1966 | return -EINVAL; | 1981 | goto msg_full; |
1967 | 1982 | ||
1968 | tipc_node_lock(node); | 1983 | /* The broadcast link is always up */ |
1969 | link = node->links[bearer_id].link; | 1984 | if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP)) |
1970 | if (!link) { | 1985 | goto attr_msg_full; |
1971 | tipc_node_unlock(node); | ||
1972 | nlmsg_free(msg.skb); | ||
1973 | return -EINVAL; | ||
1974 | } | ||
1975 | 1986 | ||
1976 | err = __tipc_nl_add_link(net, &msg, link, 0); | 1987 | if (nla_put_flag(msg->skb, TIPC_NLA_LINK_BROADCAST)) |
1977 | tipc_node_unlock(node); | 1988 | goto attr_msg_full; |
1978 | if (err) { | 1989 | if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name)) |
1979 | nlmsg_free(msg.skb); | 1990 | goto attr_msg_full; |
1980 | return err; | 1991 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->rcv_nxt)) |
1981 | } | 1992 | goto attr_msg_full; |
1982 | } | 1993 | if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->snd_nxt)) |
1994 | goto attr_msg_full; | ||
1983 | 1995 | ||
1984 | return genlmsg_reply(msg.skb, info); | 1996 | prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP); |
1985 | } | 1997 | if (!prop) |
1998 | goto attr_msg_full; | ||
1999 | if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->window)) | ||
2000 | goto prop_msg_full; | ||
2001 | nla_nest_end(msg->skb, prop); | ||
1986 | 2002 | ||
1987 | int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) | 2003 | err = __tipc_nl_add_bc_link_stat(msg->skb, &bcl->stats); |
1988 | { | ||
1989 | int err; | ||
1990 | char *link_name; | ||
1991 | unsigned int bearer_id; | ||
1992 | struct tipc_link *link; | ||
1993 | struct tipc_node *node; | ||
1994 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; | ||
1995 | struct net *net = sock_net(skb->sk); | ||
1996 | |||
1997 | if (!info->attrs[TIPC_NLA_LINK]) | ||
1998 | return -EINVAL; | ||
1999 | |||
2000 | err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, | ||
2001 | info->attrs[TIPC_NLA_LINK], | ||
2002 | tipc_nl_link_policy); | ||
2003 | if (err) | 2004 | if (err) |
2004 | return err; | 2005 | goto attr_msg_full; |
2005 | |||
2006 | if (!attrs[TIPC_NLA_LINK_NAME]) | ||
2007 | return -EINVAL; | ||
2008 | |||
2009 | link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]); | ||
2010 | 2006 | ||
2011 | if (strcmp(link_name, tipc_bclink_name) == 0) { | 2007 | tipc_bcast_unlock(net); |
2012 | err = tipc_bclink_reset_stats(net); | 2008 | nla_nest_end(msg->skb, attrs); |
2013 | if (err) | 2009 | genlmsg_end(msg->skb, hdr); |
2014 | return err; | ||
2015 | return 0; | ||
2016 | } | ||
2017 | 2010 | ||
2018 | node = tipc_link_find_owner(net, link_name, &bearer_id); | 2011 | return 0; |
2019 | if (!node) | ||
2020 | return -EINVAL; | ||
2021 | 2012 | ||
2022 | tipc_node_lock(node); | 2013 | prop_msg_full: |
2014 | nla_nest_cancel(msg->skb, prop); | ||
2015 | attr_msg_full: | ||
2016 | nla_nest_cancel(msg->skb, attrs); | ||
2017 | msg_full: | ||
2018 | tipc_bcast_unlock(net); | ||
2019 | genlmsg_cancel(msg->skb, hdr); | ||
2023 | 2020 | ||
2024 | link = node->links[bearer_id].link; | 2021 | return -EMSGSIZE; |
2025 | if (!link) { | 2022 | } |
2026 | tipc_node_unlock(node); | ||
2027 | return -EINVAL; | ||
2028 | } | ||
2029 | 2023 | ||
2030 | link_reset_statistics(link); | 2024 | void tipc_link_set_tolerance(struct tipc_link *l, u32 tol) |
2025 | { | ||
2026 | l->tolerance = tol; | ||
2027 | tipc_link_proto_xmit(l, STATE_MSG, 0, 0, tol, 0); | ||
2028 | } | ||
2031 | 2029 | ||
2032 | tipc_node_unlock(node); | 2030 | void tipc_link_set_prio(struct tipc_link *l, u32 prio) |
2031 | { | ||
2032 | l->priority = prio; | ||
2033 | tipc_link_proto_xmit(l, STATE_MSG, 0, 0, 0, prio); | ||
2034 | } | ||
2033 | 2035 | ||
2034 | return 0; | 2036 | void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit) |
2037 | { | ||
2038 | l->abort_limit = limit; | ||
2035 | } | 2039 | } |
diff --git a/net/tipc/link.h b/net/tipc/link.h index 66d859b66c84..b2ae0f4276af 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -45,10 +45,6 @@ | |||
45 | */ | 45 | */ |
46 | #define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ | 46 | #define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ |
47 | 47 | ||
48 | /* Out-of-range value for link sequence numbers | ||
49 | */ | ||
50 | #define INVALID_LINK_SEQ 0x10000 | ||
51 | |||
52 | /* Link FSM events: | 48 | /* Link FSM events: |
53 | */ | 49 | */ |
54 | enum { | 50 | enum { |
@@ -75,151 +71,6 @@ enum { | |||
75 | */ | 71 | */ |
76 | #define MAX_PKT_DEFAULT 1500 | 72 | #define MAX_PKT_DEFAULT 1500 |
77 | 73 | ||
78 | struct tipc_stats { | ||
79 | u32 sent_info; /* used in counting # sent packets */ | ||
80 | u32 recv_info; /* used in counting # recv'd packets */ | ||
81 | u32 sent_states; | ||
82 | u32 recv_states; | ||
83 | u32 sent_probes; | ||
84 | u32 recv_probes; | ||
85 | u32 sent_nacks; | ||
86 | u32 recv_nacks; | ||
87 | u32 sent_acks; | ||
88 | u32 sent_bundled; | ||
89 | u32 sent_bundles; | ||
90 | u32 recv_bundled; | ||
91 | u32 recv_bundles; | ||
92 | u32 retransmitted; | ||
93 | u32 sent_fragmented; | ||
94 | u32 sent_fragments; | ||
95 | u32 recv_fragmented; | ||
96 | u32 recv_fragments; | ||
97 | u32 link_congs; /* # port sends blocked by congestion */ | ||
98 | u32 deferred_recv; | ||
99 | u32 duplicates; | ||
100 | u32 max_queue_sz; /* send queue size high water mark */ | ||
101 | u32 accu_queue_sz; /* used for send queue size profiling */ | ||
102 | u32 queue_sz_counts; /* used for send queue size profiling */ | ||
103 | u32 msg_length_counts; /* used for message length profiling */ | ||
104 | u32 msg_lengths_total; /* used for message length profiling */ | ||
105 | u32 msg_length_profile[7]; /* used for msg. length profiling */ | ||
106 | }; | ||
107 | |||
108 | /** | ||
109 | * struct tipc_link - TIPC link data structure | ||
110 | * @addr: network address of link's peer node | ||
111 | * @name: link name character string | ||
112 | * @media_addr: media address to use when sending messages over link | ||
113 | * @timer: link timer | ||
114 | * @net: pointer to namespace struct | ||
115 | * @refcnt: reference counter for permanent references (owner node & timer) | ||
116 | * @peer_session: link session # being used by peer end of link | ||
117 | * @peer_bearer_id: bearer id used by link's peer endpoint | ||
118 | * @bearer_id: local bearer id used by link | ||
119 | * @tolerance: minimum link continuity loss needed to reset link [in ms] | ||
120 | * @keepalive_intv: link keepalive timer interval | ||
121 | * @abort_limit: # of unacknowledged continuity probes needed to reset link | ||
122 | * @state: current state of link FSM | ||
123 | * @peer_caps: bitmap describing capabilities of peer node | ||
124 | * @silent_intv_cnt: # of timer intervals without any reception from peer | ||
125 | * @proto_msg: template for control messages generated by link | ||
126 | * @pmsg: convenience pointer to "proto_msg" field | ||
127 | * @priority: current link priority | ||
128 | * @net_plane: current link network plane ('A' through 'H') | ||
129 | * @backlog_limit: backlog queue congestion thresholds (indexed by importance) | ||
130 | * @exp_msg_count: # of tunnelled messages expected during link changeover | ||
131 | * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset | ||
132 | * @mtu: current maximum packet size for this link | ||
133 | * @advertised_mtu: advertised own mtu when link is being established | ||
134 | * @transmitq: queue for sent, non-acked messages | ||
135 | * @backlogq: queue for messages waiting to be sent | ||
136 | * @snt_nxt: next sequence number to use for outbound messages | ||
137 | * @last_retransmitted: sequence number of most recently retransmitted message | ||
138 | * @stale_count: # of identical retransmit requests made by peer | ||
139 | * @ackers: # of peers that needs to ack each packet before it can be released | ||
140 | * @acked: # last packet acked by a certain peer. Used for broadcast. | ||
141 | * @rcv_nxt: next sequence number to expect for inbound messages | ||
142 | * @deferred_queue: deferred queue saved OOS b'cast message received from node | ||
143 | * @unacked_window: # of inbound messages rx'd without ack'ing back to peer | ||
144 | * @inputq: buffer queue for messages to be delivered upwards | ||
145 | * @namedq: buffer queue for name table messages to be delivered upwards | ||
146 | * @next_out: ptr to first unsent outbound message in queue | ||
147 | * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate | ||
148 | * @long_msg_seq_no: next identifier to use for outbound fragmented messages | ||
149 | * @reasm_buf: head of partially reassembled inbound message fragments | ||
150 | * @bc_rcvr: marks that this is a broadcast receiver link | ||
151 | * @stats: collects statistics regarding link activity | ||
152 | */ | ||
153 | struct tipc_link { | ||
154 | u32 addr; | ||
155 | char name[TIPC_MAX_LINK_NAME]; | ||
156 | struct tipc_media_addr *media_addr; | ||
157 | struct net *net; | ||
158 | |||
159 | /* Management and link supervision data */ | ||
160 | u32 peer_session; | ||
161 | u32 peer_bearer_id; | ||
162 | u32 bearer_id; | ||
163 | u32 tolerance; | ||
164 | unsigned long keepalive_intv; | ||
165 | u32 abort_limit; | ||
166 | u32 state; | ||
167 | u16 peer_caps; | ||
168 | bool active; | ||
169 | u32 silent_intv_cnt; | ||
170 | struct { | ||
171 | unchar hdr[INT_H_SIZE]; | ||
172 | unchar body[TIPC_MAX_IF_NAME]; | ||
173 | } proto_msg; | ||
174 | struct tipc_msg *pmsg; | ||
175 | u32 priority; | ||
176 | char net_plane; | ||
177 | |||
178 | /* Failover/synch */ | ||
179 | u16 drop_point; | ||
180 | struct sk_buff *failover_reasm_skb; | ||
181 | |||
182 | /* Max packet negotiation */ | ||
183 | u16 mtu; | ||
184 | u16 advertised_mtu; | ||
185 | |||
186 | /* Sending */ | ||
187 | struct sk_buff_head transmq; | ||
188 | struct sk_buff_head backlogq; | ||
189 | struct { | ||
190 | u16 len; | ||
191 | u16 limit; | ||
192 | } backlog[5]; | ||
193 | u16 snd_nxt; | ||
194 | u16 last_retransm; | ||
195 | u16 window; | ||
196 | u32 stale_count; | ||
197 | |||
198 | /* Reception */ | ||
199 | u16 rcv_nxt; | ||
200 | u32 rcv_unacked; | ||
201 | struct sk_buff_head deferdq; | ||
202 | struct sk_buff_head *inputq; | ||
203 | struct sk_buff_head *namedq; | ||
204 | |||
205 | /* Congestion handling */ | ||
206 | struct sk_buff_head wakeupq; | ||
207 | |||
208 | /* Fragmentation/reassembly */ | ||
209 | struct sk_buff *reasm_buf; | ||
210 | |||
211 | /* Broadcast */ | ||
212 | u16 ackers; | ||
213 | u16 acked; | ||
214 | struct tipc_link *bc_rcvlink; | ||
215 | struct tipc_link *bc_sndlink; | ||
216 | int nack_state; | ||
217 | bool bc_peer_is_up; | ||
218 | |||
219 | /* Statistics */ | ||
220 | struct tipc_stats stats; | ||
221 | }; | ||
222 | |||
223 | bool tipc_link_create(struct net *net, char *if_name, int bearer_id, | 74 | bool tipc_link_create(struct net *net, char *if_name, int bearer_id, |
224 | int tolerance, char net_plane, u32 mtu, int priority, | 75 | int tolerance, char net_plane, u32 mtu, int priority, |
225 | int window, u32 session, u32 ownnode, u32 peer, | 76 | int window, u32 session, u32 ownnode, u32 peer, |
@@ -235,11 +86,11 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, | |||
235 | struct sk_buff_head *namedq, | 86 | struct sk_buff_head *namedq, |
236 | struct tipc_link *bc_sndlink, | 87 | struct tipc_link *bc_sndlink, |
237 | struct tipc_link **link); | 88 | struct tipc_link **link); |
89 | void tipc_link_reinit(struct tipc_link *l, u32 addr); | ||
238 | void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, | 90 | void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, |
239 | int mtyp, struct sk_buff_head *xmitq); | 91 | int mtyp, struct sk_buff_head *xmitq); |
240 | void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq); | 92 | void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq); |
241 | int tipc_link_fsm_evt(struct tipc_link *l, int evt); | 93 | int tipc_link_fsm_evt(struct tipc_link *l, int evt); |
242 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); | ||
243 | bool tipc_link_is_up(struct tipc_link *l); | 94 | bool tipc_link_is_up(struct tipc_link *l); |
244 | bool tipc_link_peer_is_down(struct tipc_link *l); | 95 | bool tipc_link_peer_is_down(struct tipc_link *l); |
245 | bool tipc_link_is_reset(struct tipc_link *l); | 96 | bool tipc_link_is_reset(struct tipc_link *l); |
@@ -248,15 +99,25 @@ bool tipc_link_is_synching(struct tipc_link *l); | |||
248 | bool tipc_link_is_failingover(struct tipc_link *l); | 99 | bool tipc_link_is_failingover(struct tipc_link *l); |
249 | bool tipc_link_is_blocked(struct tipc_link *l); | 100 | bool tipc_link_is_blocked(struct tipc_link *l); |
250 | void tipc_link_set_active(struct tipc_link *l, bool active); | 101 | void tipc_link_set_active(struct tipc_link *l, bool active); |
251 | void tipc_link_reset(struct tipc_link *l_ptr); | 102 | void tipc_link_reset(struct tipc_link *l); |
252 | int tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list, | 103 | void tipc_link_reset_stats(struct tipc_link *l); |
104 | int tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list, | ||
253 | struct sk_buff_head *xmitq); | 105 | struct sk_buff_head *xmitq); |
106 | struct sk_buff_head *tipc_link_inputq(struct tipc_link *l); | ||
107 | u16 tipc_link_rcv_nxt(struct tipc_link *l); | ||
108 | u16 tipc_link_acked(struct tipc_link *l); | ||
109 | u32 tipc_link_id(struct tipc_link *l); | ||
110 | char *tipc_link_name(struct tipc_link *l); | ||
111 | char tipc_link_plane(struct tipc_link *l); | ||
112 | int tipc_link_prio(struct tipc_link *l); | ||
113 | int tipc_link_window(struct tipc_link *l); | ||
114 | unsigned long tipc_link_tolerance(struct tipc_link *l); | ||
115 | void tipc_link_set_tolerance(struct tipc_link *l, u32 tol); | ||
116 | void tipc_link_set_prio(struct tipc_link *l, u32 prio); | ||
117 | void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit); | ||
254 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 window); | 118 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 window); |
255 | 119 | int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, | |
256 | int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb); | 120 | struct tipc_link *link, int nlflags); |
257 | int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info); | ||
258 | int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info); | ||
259 | int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info); | ||
260 | int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); | 121 | int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); |
261 | int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq); | 122 | int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq); |
262 | int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, | 123 | int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index c07612bab95c..ebe9d0ff6e9e 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -84,31 +84,6 @@ static struct sk_buff *named_prepare_buf(struct net *net, u32 type, u32 size, | |||
84 | return buf; | 84 | return buf; |
85 | } | 85 | } |
86 | 86 | ||
87 | void named_cluster_distribute(struct net *net, struct sk_buff *skb) | ||
88 | { | ||
89 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
90 | struct sk_buff *oskb; | ||
91 | struct tipc_node *node; | ||
92 | u32 dnode; | ||
93 | |||
94 | rcu_read_lock(); | ||
95 | list_for_each_entry_rcu(node, &tn->node_list, list) { | ||
96 | dnode = node->addr; | ||
97 | if (in_own_node(net, dnode)) | ||
98 | continue; | ||
99 | if (!tipc_node_is_up(node)) | ||
100 | continue; | ||
101 | oskb = pskb_copy(skb, GFP_ATOMIC); | ||
102 | if (!oskb) | ||
103 | break; | ||
104 | msg_set_destnode(buf_msg(oskb), dnode); | ||
105 | tipc_node_xmit_skb(net, oskb, dnode, 0); | ||
106 | } | ||
107 | rcu_read_unlock(); | ||
108 | |||
109 | kfree_skb(skb); | ||
110 | } | ||
111 | |||
112 | /** | 87 | /** |
113 | * tipc_named_publish - tell other nodes about a new publication by this node | 88 | * tipc_named_publish - tell other nodes about a new publication by this node |
114 | */ | 89 | */ |
@@ -226,42 +201,6 @@ void tipc_named_node_up(struct net *net, u32 dnode) | |||
226 | tipc_node_xmit(net, &head, dnode, 0); | 201 | tipc_node_xmit(net, &head, dnode, 0); |
227 | } | 202 | } |
228 | 203 | ||
229 | static void tipc_publ_subscribe(struct net *net, struct publication *publ, | ||
230 | u32 addr) | ||
231 | { | ||
232 | struct tipc_node *node; | ||
233 | |||
234 | if (in_own_node(net, addr)) | ||
235 | return; | ||
236 | |||
237 | node = tipc_node_find(net, addr); | ||
238 | if (!node) { | ||
239 | pr_warn("Node subscription rejected, unknown node 0x%x\n", | ||
240 | addr); | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | tipc_node_lock(node); | ||
245 | list_add_tail(&publ->nodesub_list, &node->publ_list); | ||
246 | tipc_node_unlock(node); | ||
247 | tipc_node_put(node); | ||
248 | } | ||
249 | |||
250 | static void tipc_publ_unsubscribe(struct net *net, struct publication *publ, | ||
251 | u32 addr) | ||
252 | { | ||
253 | struct tipc_node *node; | ||
254 | |||
255 | node = tipc_node_find(net, addr); | ||
256 | if (!node) | ||
257 | return; | ||
258 | |||
259 | tipc_node_lock(node); | ||
260 | list_del_init(&publ->nodesub_list); | ||
261 | tipc_node_unlock(node); | ||
262 | tipc_node_put(node); | ||
263 | } | ||
264 | |||
265 | /** | 204 | /** |
266 | * tipc_publ_purge - remove publication associated with a failed node | 205 | * tipc_publ_purge - remove publication associated with a failed node |
267 | * | 206 | * |
@@ -277,7 +216,7 @@ static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr) | |||
277 | p = tipc_nametbl_remove_publ(net, publ->type, publ->lower, | 216 | p = tipc_nametbl_remove_publ(net, publ->type, publ->lower, |
278 | publ->node, publ->ref, publ->key); | 217 | publ->node, publ->ref, publ->key); |
279 | if (p) | 218 | if (p) |
280 | tipc_publ_unsubscribe(net, p, addr); | 219 | tipc_node_unsubscribe(net, &p->nodesub_list, addr); |
281 | spin_unlock_bh(&tn->nametbl_lock); | 220 | spin_unlock_bh(&tn->nametbl_lock); |
282 | 221 | ||
283 | if (p != publ) { | 222 | if (p != publ) { |
@@ -317,7 +256,7 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, | |||
317 | TIPC_CLUSTER_SCOPE, node, | 256 | TIPC_CLUSTER_SCOPE, node, |
318 | ntohl(i->ref), ntohl(i->key)); | 257 | ntohl(i->ref), ntohl(i->key)); |
319 | if (publ) { | 258 | if (publ) { |
320 | tipc_publ_subscribe(net, publ, node); | 259 | tipc_node_subscribe(net, &publ->nodesub_list, node); |
321 | return true; | 260 | return true; |
322 | } | 261 | } |
323 | } else if (dtype == WITHDRAWAL) { | 262 | } else if (dtype == WITHDRAWAL) { |
@@ -326,7 +265,7 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, | |||
326 | node, ntohl(i->ref), | 265 | node, ntohl(i->ref), |
327 | ntohl(i->key)); | 266 | ntohl(i->key)); |
328 | if (publ) { | 267 | if (publ) { |
329 | tipc_publ_unsubscribe(net, publ, node); | 268 | tipc_node_unsubscribe(net, &publ->nodesub_list, node); |
330 | kfree_rcu(publ, rcu); | 269 | kfree_rcu(publ, rcu); |
331 | return true; | 270 | return true; |
332 | } | 271 | } |
@@ -397,6 +336,7 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) | |||
397 | 336 | ||
398 | spin_lock_bh(&tn->nametbl_lock); | 337 | spin_lock_bh(&tn->nametbl_lock); |
399 | for (skb = skb_dequeue(inputq); skb; skb = skb_dequeue(inputq)) { | 338 | for (skb = skb_dequeue(inputq); skb; skb = skb_dequeue(inputq)) { |
339 | skb_linearize(skb); | ||
400 | msg = buf_msg(skb); | 340 | msg = buf_msg(skb); |
401 | mtype = msg_type(msg); | 341 | mtype = msg_type(msg); |
402 | item = (struct distr_item *)msg_data(msg); | 342 | item = (struct distr_item *)msg_data(msg); |
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index dd2d9fd80da2..1264ba0af937 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h | |||
@@ -69,7 +69,6 @@ struct distr_item { | |||
69 | 69 | ||
70 | struct sk_buff *tipc_named_publish(struct net *net, struct publication *publ); | 70 | struct sk_buff *tipc_named_publish(struct net *net, struct publication *publ); |
71 | struct sk_buff *tipc_named_withdraw(struct net *net, struct publication *publ); | 71 | struct sk_buff *tipc_named_withdraw(struct net *net, struct publication *publ); |
72 | void named_cluster_distribute(struct net *net, struct sk_buff *buf); | ||
73 | void tipc_named_node_up(struct net *net, u32 dnode); | 72 | void tipc_named_node_up(struct net *net, u32 dnode); |
74 | void tipc_named_rcv(struct net *net, struct sk_buff_head *msg_queue); | 73 | void tipc_named_rcv(struct net *net, struct sk_buff_head *msg_queue); |
75 | void tipc_named_reinit(struct net *net); | 74 | void tipc_named_reinit(struct net *net); |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 0f47f08bf38f..91fce70291a8 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "subscr.h" | 42 | #include "subscr.h" |
43 | #include "bcast.h" | 43 | #include "bcast.h" |
44 | #include "addr.h" | 44 | #include "addr.h" |
45 | #include "node.h" | ||
45 | #include <net/genetlink.h> | 46 | #include <net/genetlink.h> |
46 | 47 | ||
47 | #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ | 48 | #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ |
@@ -677,7 +678,7 @@ struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, | |||
677 | spin_unlock_bh(&tn->nametbl_lock); | 678 | spin_unlock_bh(&tn->nametbl_lock); |
678 | 679 | ||
679 | if (buf) | 680 | if (buf) |
680 | named_cluster_distribute(net, buf); | 681 | tipc_node_broadcast(net, buf); |
681 | return publ; | 682 | return publ; |
682 | } | 683 | } |
683 | 684 | ||
@@ -709,7 +710,7 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, | |||
709 | spin_unlock_bh(&tn->nametbl_lock); | 710 | spin_unlock_bh(&tn->nametbl_lock); |
710 | 711 | ||
711 | if (skb) { | 712 | if (skb) { |
712 | named_cluster_distribute(net, skb); | 713 | tipc_node_broadcast(net, skb); |
713 | return 1; | 714 | return 1; |
714 | } | 715 | } |
715 | return 0; | 716 | return 0; |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 7f6475efc984..8975b0135b76 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
@@ -101,18 +101,18 @@ static const struct genl_ops tipc_genl_v2_ops[] = { | |||
101 | }, | 101 | }, |
102 | { | 102 | { |
103 | .cmd = TIPC_NL_LINK_GET, | 103 | .cmd = TIPC_NL_LINK_GET, |
104 | .doit = tipc_nl_link_get, | 104 | .doit = tipc_nl_node_get_link, |
105 | .dumpit = tipc_nl_link_dump, | 105 | .dumpit = tipc_nl_node_dump_link, |
106 | .policy = tipc_nl_policy, | 106 | .policy = tipc_nl_policy, |
107 | }, | 107 | }, |
108 | { | 108 | { |
109 | .cmd = TIPC_NL_LINK_SET, | 109 | .cmd = TIPC_NL_LINK_SET, |
110 | .doit = tipc_nl_link_set, | 110 | .doit = tipc_nl_node_set_link, |
111 | .policy = tipc_nl_policy, | 111 | .policy = tipc_nl_policy, |
112 | }, | 112 | }, |
113 | { | 113 | { |
114 | .cmd = TIPC_NL_LINK_RESET_STATS, | 114 | .cmd = TIPC_NL_LINK_RESET_STATS, |
115 | .doit = tipc_nl_link_reset_stats, | 115 | .doit = tipc_nl_node_reset_link_stats, |
116 | .policy = tipc_nl_policy, | 116 | .policy = tipc_nl_policy, |
117 | }, | 117 | }, |
118 | { | 118 | { |
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 1eadc95e1132..2c016fdefe97 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
@@ -1023,25 +1023,25 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) | |||
1023 | msg->req_type = TIPC_TLV_LINK_NAME; | 1023 | msg->req_type = TIPC_TLV_LINK_NAME; |
1024 | msg->rep_size = ULTRA_STRING_MAX_LEN; | 1024 | msg->rep_size = ULTRA_STRING_MAX_LEN; |
1025 | msg->rep_type = TIPC_TLV_ULTRA_STRING; | 1025 | msg->rep_type = TIPC_TLV_ULTRA_STRING; |
1026 | dump.dumpit = tipc_nl_link_dump; | 1026 | dump.dumpit = tipc_nl_node_dump_link; |
1027 | dump.format = tipc_nl_compat_link_stat_dump; | 1027 | dump.format = tipc_nl_compat_link_stat_dump; |
1028 | return tipc_nl_compat_dumpit(&dump, msg); | 1028 | return tipc_nl_compat_dumpit(&dump, msg); |
1029 | case TIPC_CMD_GET_LINKS: | 1029 | case TIPC_CMD_GET_LINKS: |
1030 | msg->req_type = TIPC_TLV_NET_ADDR; | 1030 | msg->req_type = TIPC_TLV_NET_ADDR; |
1031 | msg->rep_size = ULTRA_STRING_MAX_LEN; | 1031 | msg->rep_size = ULTRA_STRING_MAX_LEN; |
1032 | dump.dumpit = tipc_nl_link_dump; | 1032 | dump.dumpit = tipc_nl_node_dump_link; |
1033 | dump.format = tipc_nl_compat_link_dump; | 1033 | dump.format = tipc_nl_compat_link_dump; |
1034 | return tipc_nl_compat_dumpit(&dump, msg); | 1034 | return tipc_nl_compat_dumpit(&dump, msg); |
1035 | case TIPC_CMD_SET_LINK_TOL: | 1035 | case TIPC_CMD_SET_LINK_TOL: |
1036 | case TIPC_CMD_SET_LINK_PRI: | 1036 | case TIPC_CMD_SET_LINK_PRI: |
1037 | case TIPC_CMD_SET_LINK_WINDOW: | 1037 | case TIPC_CMD_SET_LINK_WINDOW: |
1038 | msg->req_type = TIPC_TLV_LINK_CONFIG; | 1038 | msg->req_type = TIPC_TLV_LINK_CONFIG; |
1039 | doit.doit = tipc_nl_link_set; | 1039 | doit.doit = tipc_nl_node_set_link; |
1040 | doit.transcode = tipc_nl_compat_link_set; | 1040 | doit.transcode = tipc_nl_compat_link_set; |
1041 | return tipc_nl_compat_doit(&doit, msg); | 1041 | return tipc_nl_compat_doit(&doit, msg); |
1042 | case TIPC_CMD_RESET_LINK_STATS: | 1042 | case TIPC_CMD_RESET_LINK_STATS: |
1043 | msg->req_type = TIPC_TLV_LINK_NAME; | 1043 | msg->req_type = TIPC_TLV_LINK_NAME; |
1044 | doit.doit = tipc_nl_link_reset_stats; | 1044 | doit.doit = tipc_nl_node_reset_link_stats; |
1045 | doit.transcode = tipc_nl_compat_link_reset_stats; | 1045 | doit.transcode = tipc_nl_compat_link_reset_stats; |
1046 | return tipc_nl_compat_doit(&doit, msg); | 1046 | return tipc_nl_compat_doit(&doit, msg); |
1047 | case TIPC_CMD_SHOW_NAME_TABLE: | 1047 | case TIPC_CMD_SHOW_NAME_TABLE: |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 20cddec0a43c..fa97d9649a28 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -42,6 +42,84 @@ | |||
42 | #include "bcast.h" | 42 | #include "bcast.h" |
43 | #include "discover.h" | 43 | #include "discover.h" |
44 | 44 | ||
45 | #define INVALID_NODE_SIG 0x10000 | ||
46 | |||
47 | /* Flags used to take different actions according to flag type | ||
48 | * TIPC_NOTIFY_NODE_DOWN: notify node is down | ||
49 | * TIPC_NOTIFY_NODE_UP: notify node is up | ||
50 | * TIPC_DISTRIBUTE_NAME: publish or withdraw link state name type | ||
51 | */ | ||
52 | enum { | ||
53 | TIPC_NOTIFY_NODE_DOWN = (1 << 3), | ||
54 | TIPC_NOTIFY_NODE_UP = (1 << 4), | ||
55 | TIPC_NOTIFY_LINK_UP = (1 << 6), | ||
56 | TIPC_NOTIFY_LINK_DOWN = (1 << 7) | ||
57 | }; | ||
58 | |||
59 | struct tipc_link_entry { | ||
60 | struct tipc_link *link; | ||
61 | spinlock_t lock; /* per link */ | ||
62 | u32 mtu; | ||
63 | struct sk_buff_head inputq; | ||
64 | struct tipc_media_addr maddr; | ||
65 | }; | ||
66 | |||
67 | struct tipc_bclink_entry { | ||
68 | struct tipc_link *link; | ||
69 | struct sk_buff_head inputq1; | ||
70 | struct sk_buff_head arrvq; | ||
71 | struct sk_buff_head inputq2; | ||
72 | struct sk_buff_head namedq; | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * struct tipc_node - TIPC node structure | ||
77 | * @addr: network address of node | ||
78 | * @ref: reference counter to node object | ||
79 | * @lock: rwlock governing access to structure | ||
80 | * @net: the applicable net namespace | ||
81 | * @hash: links to adjacent nodes in unsorted hash chain | ||
82 | * @inputq: pointer to input queue containing messages for msg event | ||
83 | * @namedq: pointer to name table input queue with name table messages | ||
84 | * @active_links: bearer ids of active links, used as index into links[] array | ||
85 | * @links: array containing references to all links to node | ||
86 | * @action_flags: bit mask of different types of node actions | ||
87 | * @state: connectivity state vs peer node | ||
88 | * @sync_point: sequence number where synch/failover is finished | ||
89 | * @list: links to adjacent nodes in sorted list of cluster's nodes | ||
90 | * @working_links: number of working links to node (both active and standby) | ||
91 | * @link_cnt: number of links to node | ||
92 | * @capabilities: bitmap, indicating peer node's functional capabilities | ||
93 | * @signature: node instance identifier | ||
94 | * @link_id: local and remote bearer ids of changing link, if any | ||
95 | * @publ_list: list of publications | ||
96 | * @rcu: rcu struct for tipc_node | ||
97 | */ | ||
98 | struct tipc_node { | ||
99 | u32 addr; | ||
100 | struct kref kref; | ||
101 | rwlock_t lock; | ||
102 | struct net *net; | ||
103 | struct hlist_node hash; | ||
104 | int active_links[2]; | ||
105 | struct tipc_link_entry links[MAX_BEARERS]; | ||
106 | struct tipc_bclink_entry bc_entry; | ||
107 | int action_flags; | ||
108 | struct list_head list; | ||
109 | int state; | ||
110 | u16 sync_point; | ||
111 | int link_cnt; | ||
112 | u16 working_links; | ||
113 | u16 capabilities; | ||
114 | u32 signature; | ||
115 | u32 link_id; | ||
116 | struct list_head publ_list; | ||
117 | struct list_head conn_sks; | ||
118 | unsigned long keepalive_intv; | ||
119 | struct timer_list timer; | ||
120 | struct rcu_head rcu; | ||
121 | }; | ||
122 | |||
45 | /* Node FSM states and events: | 123 | /* Node FSM states and events: |
46 | */ | 124 | */ |
47 | enum { | 125 | enum { |
@@ -75,6 +153,9 @@ static void node_lost_contact(struct tipc_node *n, struct sk_buff_head *inputq); | |||
75 | static void tipc_node_delete(struct tipc_node *node); | 153 | static void tipc_node_delete(struct tipc_node *node); |
76 | static void tipc_node_timeout(unsigned long data); | 154 | static void tipc_node_timeout(unsigned long data); |
77 | static void tipc_node_fsm_evt(struct tipc_node *n, int evt); | 155 | static void tipc_node_fsm_evt(struct tipc_node *n, int evt); |
156 | static struct tipc_node *tipc_node_find(struct net *net, u32 addr); | ||
157 | static void tipc_node_put(struct tipc_node *node); | ||
158 | static bool tipc_node_is_up(struct tipc_node *n); | ||
78 | 159 | ||
79 | struct tipc_sock_conn { | 160 | struct tipc_sock_conn { |
80 | u32 port; | 161 | u32 port; |
@@ -83,12 +164,54 @@ struct tipc_sock_conn { | |||
83 | struct list_head list; | 164 | struct list_head list; |
84 | }; | 165 | }; |
85 | 166 | ||
167 | static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { | ||
168 | [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC }, | ||
169 | [TIPC_NLA_LINK_NAME] = { | ||
170 | .type = NLA_STRING, | ||
171 | .len = TIPC_MAX_LINK_NAME | ||
172 | }, | ||
173 | [TIPC_NLA_LINK_MTU] = { .type = NLA_U32 }, | ||
174 | [TIPC_NLA_LINK_BROADCAST] = { .type = NLA_FLAG }, | ||
175 | [TIPC_NLA_LINK_UP] = { .type = NLA_FLAG }, | ||
176 | [TIPC_NLA_LINK_ACTIVE] = { .type = NLA_FLAG }, | ||
177 | [TIPC_NLA_LINK_PROP] = { .type = NLA_NESTED }, | ||
178 | [TIPC_NLA_LINK_STATS] = { .type = NLA_NESTED }, | ||
179 | [TIPC_NLA_LINK_RX] = { .type = NLA_U32 }, | ||
180 | [TIPC_NLA_LINK_TX] = { .type = NLA_U32 } | ||
181 | }; | ||
182 | |||
86 | static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { | 183 | static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { |
87 | [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC }, | 184 | [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC }, |
88 | [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 }, | 185 | [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 }, |
89 | [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG } | 186 | [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG } |
90 | }; | 187 | }; |
91 | 188 | ||
189 | static struct tipc_link *node_active_link(struct tipc_node *n, int sel) | ||
190 | { | ||
191 | int bearer_id = n->active_links[sel & 1]; | ||
192 | |||
193 | if (unlikely(bearer_id == INVALID_BEARER_ID)) | ||
194 | return NULL; | ||
195 | |||
196 | return n->links[bearer_id].link; | ||
197 | } | ||
198 | |||
199 | int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel) | ||
200 | { | ||
201 | struct tipc_node *n; | ||
202 | int bearer_id; | ||
203 | unsigned int mtu = MAX_MSG_SIZE; | ||
204 | |||
205 | n = tipc_node_find(net, addr); | ||
206 | if (unlikely(!n)) | ||
207 | return mtu; | ||
208 | |||
209 | bearer_id = n->active_links[sel & 1]; | ||
210 | if (likely(bearer_id != INVALID_BEARER_ID)) | ||
211 | mtu = n->links[bearer_id].mtu; | ||
212 | tipc_node_put(n); | ||
213 | return mtu; | ||
214 | } | ||
92 | /* | 215 | /* |
93 | * A trivial power-of-two bitmask technique is used for speed, since this | 216 | * A trivial power-of-two bitmask technique is used for speed, since this |
94 | * operation is done for every incoming TIPC packet. The number of hash table | 217 | * operation is done for every incoming TIPC packet. The number of hash table |
@@ -107,7 +230,7 @@ static void tipc_node_kref_release(struct kref *kref) | |||
107 | tipc_node_delete(node); | 230 | tipc_node_delete(node); |
108 | } | 231 | } |
109 | 232 | ||
110 | void tipc_node_put(struct tipc_node *node) | 233 | static void tipc_node_put(struct tipc_node *node) |
111 | { | 234 | { |
112 | kref_put(&node->kref, tipc_node_kref_release); | 235 | kref_put(&node->kref, tipc_node_kref_release); |
113 | } | 236 | } |
@@ -120,7 +243,7 @@ static void tipc_node_get(struct tipc_node *node) | |||
120 | /* | 243 | /* |
121 | * tipc_node_find - locate specified node object, if it exists | 244 | * tipc_node_find - locate specified node object, if it exists |
122 | */ | 245 | */ |
123 | struct tipc_node *tipc_node_find(struct net *net, u32 addr) | 246 | static struct tipc_node *tipc_node_find(struct net *net, u32 addr) |
124 | { | 247 | { |
125 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 248 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
126 | struct tipc_node *node; | 249 | struct tipc_node *node; |
@@ -141,66 +264,122 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr) | |||
141 | return NULL; | 264 | return NULL; |
142 | } | 265 | } |
143 | 266 | ||
267 | static void tipc_node_read_lock(struct tipc_node *n) | ||
268 | { | ||
269 | read_lock_bh(&n->lock); | ||
270 | } | ||
271 | |||
272 | static void tipc_node_read_unlock(struct tipc_node *n) | ||
273 | { | ||
274 | read_unlock_bh(&n->lock); | ||
275 | } | ||
276 | |||
277 | static void tipc_node_write_lock(struct tipc_node *n) | ||
278 | { | ||
279 | write_lock_bh(&n->lock); | ||
280 | } | ||
281 | |||
282 | static void tipc_node_write_unlock(struct tipc_node *n) | ||
283 | { | ||
284 | struct net *net = n->net; | ||
285 | u32 addr = 0; | ||
286 | u32 flags = n->action_flags; | ||
287 | u32 link_id = 0; | ||
288 | struct list_head *publ_list; | ||
289 | |||
290 | if (likely(!flags)) { | ||
291 | write_unlock_bh(&n->lock); | ||
292 | return; | ||
293 | } | ||
294 | |||
295 | addr = n->addr; | ||
296 | link_id = n->link_id; | ||
297 | publ_list = &n->publ_list; | ||
298 | |||
299 | n->action_flags &= ~(TIPC_NOTIFY_NODE_DOWN | TIPC_NOTIFY_NODE_UP | | ||
300 | TIPC_NOTIFY_LINK_DOWN | TIPC_NOTIFY_LINK_UP); | ||
301 | |||
302 | write_unlock_bh(&n->lock); | ||
303 | |||
304 | if (flags & TIPC_NOTIFY_NODE_DOWN) | ||
305 | tipc_publ_notify(net, publ_list, addr); | ||
306 | |||
307 | if (flags & TIPC_NOTIFY_NODE_UP) | ||
308 | tipc_named_node_up(net, addr); | ||
309 | |||
310 | if (flags & TIPC_NOTIFY_LINK_UP) | ||
311 | tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, | ||
312 | TIPC_NODE_SCOPE, link_id, addr); | ||
313 | |||
314 | if (flags & TIPC_NOTIFY_LINK_DOWN) | ||
315 | tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, | ||
316 | link_id, addr); | ||
317 | } | ||
318 | |||
144 | struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) | 319 | struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities) |
145 | { | 320 | { |
146 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 321 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
147 | struct tipc_node *n_ptr, *temp_node; | 322 | struct tipc_node *n, *temp_node; |
323 | int i; | ||
148 | 324 | ||
149 | spin_lock_bh(&tn->node_list_lock); | 325 | spin_lock_bh(&tn->node_list_lock); |
150 | n_ptr = tipc_node_find(net, addr); | 326 | n = tipc_node_find(net, addr); |
151 | if (n_ptr) | 327 | if (n) |
152 | goto exit; | 328 | goto exit; |
153 | n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); | 329 | n = kzalloc(sizeof(*n), GFP_ATOMIC); |
154 | if (!n_ptr) { | 330 | if (!n) { |
155 | pr_warn("Node creation failed, no memory\n"); | 331 | pr_warn("Node creation failed, no memory\n"); |
156 | goto exit; | 332 | goto exit; |
157 | } | 333 | } |
158 | n_ptr->addr = addr; | 334 | n->addr = addr; |
159 | n_ptr->net = net; | 335 | n->net = net; |
160 | n_ptr->capabilities = capabilities; | 336 | n->capabilities = capabilities; |
161 | kref_init(&n_ptr->kref); | 337 | kref_init(&n->kref); |
162 | spin_lock_init(&n_ptr->lock); | 338 | rwlock_init(&n->lock); |
163 | INIT_HLIST_NODE(&n_ptr->hash); | 339 | INIT_HLIST_NODE(&n->hash); |
164 | INIT_LIST_HEAD(&n_ptr->list); | 340 | INIT_LIST_HEAD(&n->list); |
165 | INIT_LIST_HEAD(&n_ptr->publ_list); | 341 | INIT_LIST_HEAD(&n->publ_list); |
166 | INIT_LIST_HEAD(&n_ptr->conn_sks); | 342 | INIT_LIST_HEAD(&n->conn_sks); |
167 | skb_queue_head_init(&n_ptr->bc_entry.namedq); | 343 | skb_queue_head_init(&n->bc_entry.namedq); |
168 | skb_queue_head_init(&n_ptr->bc_entry.inputq1); | 344 | skb_queue_head_init(&n->bc_entry.inputq1); |
169 | __skb_queue_head_init(&n_ptr->bc_entry.arrvq); | 345 | __skb_queue_head_init(&n->bc_entry.arrvq); |
170 | skb_queue_head_init(&n_ptr->bc_entry.inputq2); | 346 | skb_queue_head_init(&n->bc_entry.inputq2); |
171 | hlist_add_head_rcu(&n_ptr->hash, &tn->node_htable[tipc_hashfn(addr)]); | 347 | for (i = 0; i < MAX_BEARERS; i++) |
348 | spin_lock_init(&n->links[i].lock); | ||
349 | hlist_add_head_rcu(&n->hash, &tn->node_htable[tipc_hashfn(addr)]); | ||
172 | list_for_each_entry_rcu(temp_node, &tn->node_list, list) { | 350 | list_for_each_entry_rcu(temp_node, &tn->node_list, list) { |
173 | if (n_ptr->addr < temp_node->addr) | 351 | if (n->addr < temp_node->addr) |
174 | break; | 352 | break; |
175 | } | 353 | } |
176 | list_add_tail_rcu(&n_ptr->list, &temp_node->list); | 354 | list_add_tail_rcu(&n->list, &temp_node->list); |
177 | n_ptr->state = SELF_DOWN_PEER_LEAVING; | 355 | n->state = SELF_DOWN_PEER_LEAVING; |
178 | n_ptr->signature = INVALID_NODE_SIG; | 356 | n->signature = INVALID_NODE_SIG; |
179 | n_ptr->active_links[0] = INVALID_BEARER_ID; | 357 | n->active_links[0] = INVALID_BEARER_ID; |
180 | n_ptr->active_links[1] = INVALID_BEARER_ID; | 358 | n->active_links[1] = INVALID_BEARER_ID; |
181 | if (!tipc_link_bc_create(net, tipc_own_addr(net), n_ptr->addr, | 359 | if (!tipc_link_bc_create(net, tipc_own_addr(net), n->addr, |
182 | U16_MAX, tipc_bc_sndlink(net)->window, | 360 | U16_MAX, |
183 | n_ptr->capabilities, | 361 | tipc_link_window(tipc_bc_sndlink(net)), |
184 | &n_ptr->bc_entry.inputq1, | 362 | n->capabilities, |
185 | &n_ptr->bc_entry.namedq, | 363 | &n->bc_entry.inputq1, |
364 | &n->bc_entry.namedq, | ||
186 | tipc_bc_sndlink(net), | 365 | tipc_bc_sndlink(net), |
187 | &n_ptr->bc_entry.link)) { | 366 | &n->bc_entry.link)) { |
188 | pr_warn("Broadcast rcv link creation failed, no memory\n"); | 367 | pr_warn("Broadcast rcv link creation failed, no memory\n"); |
189 | kfree(n_ptr); | 368 | kfree(n); |
190 | n_ptr = NULL; | 369 | n = NULL; |
191 | goto exit; | 370 | goto exit; |
192 | } | 371 | } |
193 | tipc_node_get(n_ptr); | 372 | tipc_node_get(n); |
194 | setup_timer(&n_ptr->timer, tipc_node_timeout, (unsigned long)n_ptr); | 373 | setup_timer(&n->timer, tipc_node_timeout, (unsigned long)n); |
195 | n_ptr->keepalive_intv = U32_MAX; | 374 | n->keepalive_intv = U32_MAX; |
196 | exit: | 375 | exit: |
197 | spin_unlock_bh(&tn->node_list_lock); | 376 | spin_unlock_bh(&tn->node_list_lock); |
198 | return n_ptr; | 377 | return n; |
199 | } | 378 | } |
200 | 379 | ||
201 | static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l) | 380 | static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l) |
202 | { | 381 | { |
203 | unsigned long tol = l->tolerance; | 382 | unsigned long tol = tipc_link_tolerance(l); |
204 | unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4; | 383 | unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4; |
205 | unsigned long keepalive_intv = msecs_to_jiffies(intv); | 384 | unsigned long keepalive_intv = msecs_to_jiffies(intv); |
206 | 385 | ||
@@ -209,7 +388,7 @@ static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l) | |||
209 | n->keepalive_intv = keepalive_intv; | 388 | n->keepalive_intv = keepalive_intv; |
210 | 389 | ||
211 | /* Ensure link's abort limit corresponds to current interval */ | 390 | /* Ensure link's abort limit corresponds to current interval */ |
212 | l->abort_limit = l->tolerance / jiffies_to_msecs(n->keepalive_intv); | 391 | tipc_link_set_abort_limit(l, tol / jiffies_to_msecs(n->keepalive_intv)); |
213 | } | 392 | } |
214 | 393 | ||
215 | static void tipc_node_delete(struct tipc_node *node) | 394 | static void tipc_node_delete(struct tipc_node *node) |
@@ -234,6 +413,42 @@ void tipc_node_stop(struct net *net) | |||
234 | spin_unlock_bh(&tn->node_list_lock); | 413 | spin_unlock_bh(&tn->node_list_lock); |
235 | } | 414 | } |
236 | 415 | ||
416 | void tipc_node_subscribe(struct net *net, struct list_head *subscr, u32 addr) | ||
417 | { | ||
418 | struct tipc_node *n; | ||
419 | |||
420 | if (in_own_node(net, addr)) | ||
421 | return; | ||
422 | |||
423 | n = tipc_node_find(net, addr); | ||
424 | if (!n) { | ||
425 | pr_warn("Node subscribe rejected, unknown node 0x%x\n", addr); | ||
426 | return; | ||
427 | } | ||
428 | tipc_node_write_lock(n); | ||
429 | list_add_tail(subscr, &n->publ_list); | ||
430 | tipc_node_write_unlock(n); | ||
431 | tipc_node_put(n); | ||
432 | } | ||
433 | |||
434 | void tipc_node_unsubscribe(struct net *net, struct list_head *subscr, u32 addr) | ||
435 | { | ||
436 | struct tipc_node *n; | ||
437 | |||
438 | if (in_own_node(net, addr)) | ||
439 | return; | ||
440 | |||
441 | n = tipc_node_find(net, addr); | ||
442 | if (!n) { | ||
443 | pr_warn("Node unsubscribe rejected, unknown node 0x%x\n", addr); | ||
444 | return; | ||
445 | } | ||
446 | tipc_node_write_lock(n); | ||
447 | list_del_init(subscr); | ||
448 | tipc_node_write_unlock(n); | ||
449 | tipc_node_put(n); | ||
450 | } | ||
451 | |||
237 | int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) | 452 | int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) |
238 | { | 453 | { |
239 | struct tipc_node *node; | 454 | struct tipc_node *node; |
@@ -257,9 +472,9 @@ int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) | |||
257 | conn->port = port; | 472 | conn->port = port; |
258 | conn->peer_port = peer_port; | 473 | conn->peer_port = peer_port; |
259 | 474 | ||
260 | tipc_node_lock(node); | 475 | tipc_node_write_lock(node); |
261 | list_add_tail(&conn->list, &node->conn_sks); | 476 | list_add_tail(&conn->list, &node->conn_sks); |
262 | tipc_node_unlock(node); | 477 | tipc_node_write_unlock(node); |
263 | exit: | 478 | exit: |
264 | tipc_node_put(node); | 479 | tipc_node_put(node); |
265 | return err; | 480 | return err; |
@@ -277,14 +492,14 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) | |||
277 | if (!node) | 492 | if (!node) |
278 | return; | 493 | return; |
279 | 494 | ||
280 | tipc_node_lock(node); | 495 | tipc_node_write_lock(node); |
281 | list_for_each_entry_safe(conn, safe, &node->conn_sks, list) { | 496 | list_for_each_entry_safe(conn, safe, &node->conn_sks, list) { |
282 | if (port != conn->port) | 497 | if (port != conn->port) |
283 | continue; | 498 | continue; |
284 | list_del(&conn->list); | 499 | list_del(&conn->list); |
285 | kfree(conn); | 500 | kfree(conn); |
286 | } | 501 | } |
287 | tipc_node_unlock(node); | 502 | tipc_node_write_unlock(node); |
288 | tipc_node_put(node); | 503 | tipc_node_put(node); |
289 | } | 504 | } |
290 | 505 | ||
@@ -301,14 +516,16 @@ static void tipc_node_timeout(unsigned long data) | |||
301 | __skb_queue_head_init(&xmitq); | 516 | __skb_queue_head_init(&xmitq); |
302 | 517 | ||
303 | for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) { | 518 | for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) { |
304 | tipc_node_lock(n); | 519 | tipc_node_read_lock(n); |
305 | le = &n->links[bearer_id]; | 520 | le = &n->links[bearer_id]; |
521 | spin_lock_bh(&le->lock); | ||
306 | if (le->link) { | 522 | if (le->link) { |
307 | /* Link tolerance may change asynchronously: */ | 523 | /* Link tolerance may change asynchronously: */ |
308 | tipc_node_calculate_timer(n, le->link); | 524 | tipc_node_calculate_timer(n, le->link); |
309 | rc = tipc_link_timeout(le->link, &xmitq); | 525 | rc = tipc_link_timeout(le->link, &xmitq); |
310 | } | 526 | } |
311 | tipc_node_unlock(n); | 527 | spin_unlock_bh(&le->lock); |
528 | tipc_node_read_unlock(n); | ||
312 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr); | 529 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr); |
313 | if (rc & TIPC_LINK_DOWN_EVT) | 530 | if (rc & TIPC_LINK_DOWN_EVT) |
314 | tipc_node_link_down(n, bearer_id, false); | 531 | tipc_node_link_down(n, bearer_id, false); |
@@ -340,16 +557,16 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id, | |||
340 | 557 | ||
341 | n->working_links++; | 558 | n->working_links++; |
342 | n->action_flags |= TIPC_NOTIFY_LINK_UP; | 559 | n->action_flags |= TIPC_NOTIFY_LINK_UP; |
343 | n->link_id = nl->peer_bearer_id << 16 | bearer_id; | 560 | n->link_id = tipc_link_id(nl); |
344 | 561 | ||
345 | /* Leave room for tunnel header when returning 'mtu' to users: */ | 562 | /* Leave room for tunnel header when returning 'mtu' to users: */ |
346 | n->links[bearer_id].mtu = nl->mtu - INT_H_SIZE; | 563 | n->links[bearer_id].mtu = tipc_link_mtu(nl) - INT_H_SIZE; |
347 | 564 | ||
348 | tipc_bearer_add_dest(n->net, bearer_id, n->addr); | 565 | tipc_bearer_add_dest(n->net, bearer_id, n->addr); |
349 | tipc_bcast_inc_bearer_dst_cnt(n->net, bearer_id); | 566 | tipc_bcast_inc_bearer_dst_cnt(n->net, bearer_id); |
350 | 567 | ||
351 | pr_debug("Established link <%s> on network plane %c\n", | 568 | pr_debug("Established link <%s> on network plane %c\n", |
352 | nl->name, nl->net_plane); | 569 | tipc_link_name(nl), tipc_link_plane(nl)); |
353 | 570 | ||
354 | /* First link? => give it both slots */ | 571 | /* First link? => give it both slots */ |
355 | if (!ol) { | 572 | if (!ol) { |
@@ -362,17 +579,17 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id, | |||
362 | } | 579 | } |
363 | 580 | ||
364 | /* Second link => redistribute slots */ | 581 | /* Second link => redistribute slots */ |
365 | if (nl->priority > ol->priority) { | 582 | if (tipc_link_prio(nl) > tipc_link_prio(ol)) { |
366 | pr_debug("Old link <%s> becomes standby\n", ol->name); | 583 | pr_debug("Old link <%s> becomes standby\n", tipc_link_name(ol)); |
367 | *slot0 = bearer_id; | 584 | *slot0 = bearer_id; |
368 | *slot1 = bearer_id; | 585 | *slot1 = bearer_id; |
369 | tipc_link_set_active(nl, true); | 586 | tipc_link_set_active(nl, true); |
370 | tipc_link_set_active(ol, false); | 587 | tipc_link_set_active(ol, false); |
371 | } else if (nl->priority == ol->priority) { | 588 | } else if (tipc_link_prio(nl) == tipc_link_prio(ol)) { |
372 | tipc_link_set_active(nl, true); | 589 | tipc_link_set_active(nl, true); |
373 | *slot1 = bearer_id; | 590 | *slot1 = bearer_id; |
374 | } else { | 591 | } else { |
375 | pr_debug("New link <%s> is standby\n", nl->name); | 592 | pr_debug("New link <%s> is standby\n", tipc_link_name(nl)); |
376 | } | 593 | } |
377 | 594 | ||
378 | /* Prepare synchronization with first link */ | 595 | /* Prepare synchronization with first link */ |
@@ -387,9 +604,9 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id, | |||
387 | static void tipc_node_link_up(struct tipc_node *n, int bearer_id, | 604 | static void tipc_node_link_up(struct tipc_node *n, int bearer_id, |
388 | struct sk_buff_head *xmitq) | 605 | struct sk_buff_head *xmitq) |
389 | { | 606 | { |
390 | tipc_node_lock(n); | 607 | tipc_node_write_lock(n); |
391 | __tipc_node_link_up(n, bearer_id, xmitq); | 608 | __tipc_node_link_up(n, bearer_id, xmitq); |
392 | tipc_node_unlock(n); | 609 | tipc_node_write_unlock(n); |
393 | } | 610 | } |
394 | 611 | ||
395 | /** | 612 | /** |
@@ -402,7 +619,7 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id, | |||
402 | struct tipc_link_entry *le = &n->links[*bearer_id]; | 619 | struct tipc_link_entry *le = &n->links[*bearer_id]; |
403 | int *slot0 = &n->active_links[0]; | 620 | int *slot0 = &n->active_links[0]; |
404 | int *slot1 = &n->active_links[1]; | 621 | int *slot1 = &n->active_links[1]; |
405 | int i, highest = 0; | 622 | int i, highest = 0, prio; |
406 | struct tipc_link *l, *_l, *tnl; | 623 | struct tipc_link *l, *_l, *tnl; |
407 | 624 | ||
408 | l = n->links[*bearer_id].link; | 625 | l = n->links[*bearer_id].link; |
@@ -411,12 +628,12 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id, | |||
411 | 628 | ||
412 | n->working_links--; | 629 | n->working_links--; |
413 | n->action_flags |= TIPC_NOTIFY_LINK_DOWN; | 630 | n->action_flags |= TIPC_NOTIFY_LINK_DOWN; |
414 | n->link_id = l->peer_bearer_id << 16 | *bearer_id; | 631 | n->link_id = tipc_link_id(l); |
415 | 632 | ||
416 | tipc_bearer_remove_dest(n->net, *bearer_id, n->addr); | 633 | tipc_bearer_remove_dest(n->net, *bearer_id, n->addr); |
417 | 634 | ||
418 | pr_debug("Lost link <%s> on network plane %c\n", | 635 | pr_debug("Lost link <%s> on network plane %c\n", |
419 | l->name, l->net_plane); | 636 | tipc_link_name(l), tipc_link_plane(l)); |
420 | 637 | ||
421 | /* Select new active link if any available */ | 638 | /* Select new active link if any available */ |
422 | *slot0 = INVALID_BEARER_ID; | 639 | *slot0 = INVALID_BEARER_ID; |
@@ -427,10 +644,11 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id, | |||
427 | continue; | 644 | continue; |
428 | if (_l == l) | 645 | if (_l == l) |
429 | continue; | 646 | continue; |
430 | if (_l->priority < highest) | 647 | prio = tipc_link_prio(_l); |
648 | if (prio < highest) | ||
431 | continue; | 649 | continue; |
432 | if (_l->priority > highest) { | 650 | if (prio > highest) { |
433 | highest = _l->priority; | 651 | highest = prio; |
434 | *slot0 = i; | 652 | *slot0 = i; |
435 | *slot1 = i; | 653 | *slot1 = i; |
436 | continue; | 654 | continue; |
@@ -453,17 +671,17 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id, | |||
453 | tipc_bcast_dec_bearer_dst_cnt(n->net, *bearer_id); | 671 | tipc_bcast_dec_bearer_dst_cnt(n->net, *bearer_id); |
454 | 672 | ||
455 | /* There is still a working link => initiate failover */ | 673 | /* There is still a working link => initiate failover */ |
456 | tnl = node_active_link(n, 0); | 674 | *bearer_id = n->active_links[0]; |
675 | tnl = n->links[*bearer_id].link; | ||
457 | tipc_link_fsm_evt(tnl, LINK_SYNCH_END_EVT); | 676 | tipc_link_fsm_evt(tnl, LINK_SYNCH_END_EVT); |
458 | tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); | 677 | tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); |
459 | n->sync_point = tnl->rcv_nxt + (U16_MAX / 2 - 1); | 678 | n->sync_point = tipc_link_rcv_nxt(tnl) + (U16_MAX / 2 - 1); |
460 | tipc_link_tnl_prepare(l, tnl, FAILOVER_MSG, xmitq); | 679 | tipc_link_tnl_prepare(l, tnl, FAILOVER_MSG, xmitq); |
461 | tipc_link_reset(l); | 680 | tipc_link_reset(l); |
462 | tipc_link_fsm_evt(l, LINK_RESET_EVT); | 681 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
463 | tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); | 682 | tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); |
464 | tipc_node_fsm_evt(n, NODE_FAILOVER_BEGIN_EVT); | 683 | tipc_node_fsm_evt(n, NODE_FAILOVER_BEGIN_EVT); |
465 | *maddr = &n->links[tnl->bearer_id].maddr; | 684 | *maddr = &n->links[*bearer_id].maddr; |
466 | *bearer_id = tnl->bearer_id; | ||
467 | } | 685 | } |
468 | 686 | ||
469 | static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | 687 | static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) |
@@ -478,7 +696,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | |||
478 | 696 | ||
479 | __skb_queue_head_init(&xmitq); | 697 | __skb_queue_head_init(&xmitq); |
480 | 698 | ||
481 | tipc_node_lock(n); | 699 | tipc_node_write_lock(n); |
482 | if (!tipc_link_is_establishing(l)) { | 700 | if (!tipc_link_is_establishing(l)) { |
483 | __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr); | 701 | __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr); |
484 | if (delete) { | 702 | if (delete) { |
@@ -490,12 +708,12 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | |||
490 | /* Defuse pending tipc_node_link_up() */ | 708 | /* Defuse pending tipc_node_link_up() */ |
491 | tipc_link_fsm_evt(l, LINK_RESET_EVT); | 709 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
492 | } | 710 | } |
493 | tipc_node_unlock(n); | 711 | tipc_node_write_unlock(n); |
494 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); | 712 | tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); |
495 | tipc_sk_rcv(n->net, &le->inputq); | 713 | tipc_sk_rcv(n->net, &le->inputq); |
496 | } | 714 | } |
497 | 715 | ||
498 | bool tipc_node_is_up(struct tipc_node *n) | 716 | static bool tipc_node_is_up(struct tipc_node *n) |
499 | { | 717 | { |
500 | return n->active_links[0] != INVALID_BEARER_ID; | 718 | return n->active_links[0] != INVALID_BEARER_ID; |
501 | } | 719 | } |
@@ -523,7 +741,7 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
523 | if (!n) | 741 | if (!n) |
524 | return; | 742 | return; |
525 | 743 | ||
526 | tipc_node_lock(n); | 744 | tipc_node_write_lock(n); |
527 | 745 | ||
528 | le = &n->links[b->identity]; | 746 | le = &n->links[b->identity]; |
529 | 747 | ||
@@ -626,7 +844,7 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
626 | } | 844 | } |
627 | memcpy(&le->maddr, maddr, sizeof(*maddr)); | 845 | memcpy(&le->maddr, maddr, sizeof(*maddr)); |
628 | exit: | 846 | exit: |
629 | tipc_node_unlock(n); | 847 | tipc_node_write_unlock(n); |
630 | if (reset && !tipc_link_is_reset(l)) | 848 | if (reset && !tipc_link_is_reset(l)) |
631 | tipc_node_link_down(n, b->identity, false); | 849 | tipc_node_link_down(n, b->identity, false); |
632 | tipc_node_put(n); | 850 | tipc_node_put(n); |
@@ -834,24 +1052,6 @@ illegal_evt: | |||
834 | pr_err("Illegal node fsm evt %x in state %x\n", evt, state); | 1052 | pr_err("Illegal node fsm evt %x in state %x\n", evt, state); |
835 | } | 1053 | } |
836 | 1054 | ||
837 | bool tipc_node_filter_pkt(struct tipc_node *n, struct tipc_msg *hdr) | ||
838 | { | ||
839 | int state = n->state; | ||
840 | |||
841 | if (likely(state == SELF_UP_PEER_UP)) | ||
842 | return true; | ||
843 | |||
844 | if (state == SELF_LEAVING_PEER_DOWN) | ||
845 | return false; | ||
846 | |||
847 | if (state == SELF_DOWN_PEER_LEAVING) { | ||
848 | if (msg_peer_node_is_up(hdr)) | ||
849 | return false; | ||
850 | } | ||
851 | |||
852 | return true; | ||
853 | } | ||
854 | |||
855 | static void node_lost_contact(struct tipc_node *n, | 1055 | static void node_lost_contact(struct tipc_node *n, |
856 | struct sk_buff_head *inputq) | 1056 | struct sk_buff_head *inputq) |
857 | { | 1057 | { |
@@ -913,56 +1113,18 @@ int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 addr, | |||
913 | if (bearer_id >= MAX_BEARERS) | 1113 | if (bearer_id >= MAX_BEARERS) |
914 | goto exit; | 1114 | goto exit; |
915 | 1115 | ||
916 | tipc_node_lock(node); | 1116 | tipc_node_read_lock(node); |
917 | link = node->links[bearer_id].link; | 1117 | link = node->links[bearer_id].link; |
918 | if (link) { | 1118 | if (link) { |
919 | strncpy(linkname, link->name, len); | 1119 | strncpy(linkname, tipc_link_name(link), len); |
920 | err = 0; | 1120 | err = 0; |
921 | } | 1121 | } |
922 | exit: | 1122 | exit: |
923 | tipc_node_unlock(node); | 1123 | tipc_node_read_unlock(node); |
924 | tipc_node_put(node); | 1124 | tipc_node_put(node); |
925 | return err; | 1125 | return err; |
926 | } | 1126 | } |
927 | 1127 | ||
928 | void tipc_node_unlock(struct tipc_node *node) | ||
929 | { | ||
930 | struct net *net = node->net; | ||
931 | u32 addr = 0; | ||
932 | u32 flags = node->action_flags; | ||
933 | u32 link_id = 0; | ||
934 | struct list_head *publ_list; | ||
935 | |||
936 | if (likely(!flags)) { | ||
937 | spin_unlock_bh(&node->lock); | ||
938 | return; | ||
939 | } | ||
940 | |||
941 | addr = node->addr; | ||
942 | link_id = node->link_id; | ||
943 | publ_list = &node->publ_list; | ||
944 | |||
945 | node->action_flags &= ~(TIPC_NOTIFY_NODE_DOWN | TIPC_NOTIFY_NODE_UP | | ||
946 | TIPC_NOTIFY_LINK_DOWN | TIPC_NOTIFY_LINK_UP); | ||
947 | |||
948 | spin_unlock_bh(&node->lock); | ||
949 | |||
950 | if (flags & TIPC_NOTIFY_NODE_DOWN) | ||
951 | tipc_publ_notify(net, publ_list, addr); | ||
952 | |||
953 | if (flags & TIPC_NOTIFY_NODE_UP) | ||
954 | tipc_named_node_up(net, addr); | ||
955 | |||
956 | if (flags & TIPC_NOTIFY_LINK_UP) | ||
957 | tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, | ||
958 | TIPC_NODE_SCOPE, link_id, addr); | ||
959 | |||
960 | if (flags & TIPC_NOTIFY_LINK_DOWN) | ||
961 | tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, | ||
962 | link_id, addr); | ||
963 | |||
964 | } | ||
965 | |||
966 | /* Caller should hold node lock for the passed node */ | 1128 | /* Caller should hold node lock for the passed node */ |
967 | static int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node) | 1129 | static int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node) |
968 | { | 1130 | { |
@@ -997,20 +1159,6 @@ msg_full: | |||
997 | return -EMSGSIZE; | 1159 | return -EMSGSIZE; |
998 | } | 1160 | } |
999 | 1161 | ||
1000 | static struct tipc_link *tipc_node_select_link(struct tipc_node *n, int sel, | ||
1001 | int *bearer_id, | ||
1002 | struct tipc_media_addr **maddr) | ||
1003 | { | ||
1004 | int id = n->active_links[sel & 1]; | ||
1005 | |||
1006 | if (unlikely(id < 0)) | ||
1007 | return NULL; | ||
1008 | |||
1009 | *bearer_id = id; | ||
1010 | *maddr = &n->links[id].maddr; | ||
1011 | return n->links[id].link; | ||
1012 | } | ||
1013 | |||
1014 | /** | 1162 | /** |
1015 | * tipc_node_xmit() is the general link level function for message sending | 1163 | * tipc_node_xmit() is the general link level function for message sending |
1016 | * @net: the applicable net namespace | 1164 | * @net: the applicable net namespace |
@@ -1023,29 +1171,32 @@ static struct tipc_link *tipc_node_select_link(struct tipc_node *n, int sel, | |||
1023 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, | 1171 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, |
1024 | u32 dnode, int selector) | 1172 | u32 dnode, int selector) |
1025 | { | 1173 | { |
1026 | struct tipc_link *l = NULL; | 1174 | struct tipc_link_entry *le = NULL; |
1027 | struct tipc_node *n; | 1175 | struct tipc_node *n; |
1028 | struct sk_buff_head xmitq; | 1176 | struct sk_buff_head xmitq; |
1029 | struct tipc_media_addr *maddr; | 1177 | int bearer_id = -1; |
1030 | int bearer_id; | ||
1031 | int rc = -EHOSTUNREACH; | 1178 | int rc = -EHOSTUNREACH; |
1032 | 1179 | ||
1033 | __skb_queue_head_init(&xmitq); | 1180 | __skb_queue_head_init(&xmitq); |
1034 | n = tipc_node_find(net, dnode); | 1181 | n = tipc_node_find(net, dnode); |
1035 | if (likely(n)) { | 1182 | if (likely(n)) { |
1036 | tipc_node_lock(n); | 1183 | tipc_node_read_lock(n); |
1037 | l = tipc_node_select_link(n, selector, &bearer_id, &maddr); | 1184 | bearer_id = n->active_links[selector & 1]; |
1038 | if (likely(l)) | 1185 | if (bearer_id >= 0) { |
1039 | rc = tipc_link_xmit(l, list, &xmitq); | 1186 | le = &n->links[bearer_id]; |
1040 | tipc_node_unlock(n); | 1187 | spin_lock_bh(&le->lock); |
1041 | if (unlikely(rc == -ENOBUFS)) | 1188 | rc = tipc_link_xmit(le->link, list, &xmitq); |
1189 | spin_unlock_bh(&le->lock); | ||
1190 | } | ||
1191 | tipc_node_read_unlock(n); | ||
1192 | if (likely(!rc)) | ||
1193 | tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr); | ||
1194 | else if (rc == -ENOBUFS) | ||
1042 | tipc_node_link_down(n, bearer_id, false); | 1195 | tipc_node_link_down(n, bearer_id, false); |
1043 | tipc_node_put(n); | 1196 | tipc_node_put(n); |
1197 | return rc; | ||
1044 | } | 1198 | } |
1045 | if (likely(!rc)) { | 1199 | |
1046 | tipc_bearer_xmit(net, bearer_id, &xmitq, maddr); | ||
1047 | return 0; | ||
1048 | } | ||
1049 | if (likely(in_own_node(net, dnode))) { | 1200 | if (likely(in_own_node(net, dnode))) { |
1050 | tipc_sk_rcv(net, list); | 1201 | tipc_sk_rcv(net, list); |
1051 | return 0; | 1202 | return 0; |
@@ -1075,6 +1226,30 @@ int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode, | |||
1075 | return 0; | 1226 | return 0; |
1076 | } | 1227 | } |
1077 | 1228 | ||
1229 | void tipc_node_broadcast(struct net *net, struct sk_buff *skb) | ||
1230 | { | ||
1231 | struct sk_buff *txskb; | ||
1232 | struct tipc_node *n; | ||
1233 | u32 dst; | ||
1234 | |||
1235 | rcu_read_lock(); | ||
1236 | list_for_each_entry_rcu(n, tipc_nodes(net), list) { | ||
1237 | dst = n->addr; | ||
1238 | if (in_own_node(net, dst)) | ||
1239 | continue; | ||
1240 | if (!tipc_node_is_up(n)) | ||
1241 | continue; | ||
1242 | txskb = pskb_copy(skb, GFP_ATOMIC); | ||
1243 | if (!txskb) | ||
1244 | break; | ||
1245 | msg_set_destnode(buf_msg(txskb), dst); | ||
1246 | tipc_node_xmit_skb(net, txskb, dst, 0); | ||
1247 | } | ||
1248 | rcu_read_unlock(); | ||
1249 | |||
1250 | kfree_skb(skb); | ||
1251 | } | ||
1252 | |||
1078 | /** | 1253 | /** |
1079 | * tipc_node_bc_rcv - process TIPC broadcast packet arriving from off-node | 1254 | * tipc_node_bc_rcv - process TIPC broadcast packet arriving from off-node |
1080 | * @net: the applicable net namespace | 1255 | * @net: the applicable net namespace |
@@ -1116,9 +1291,9 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id | |||
1116 | 1291 | ||
1117 | /* Broadcast ACKs are sent on a unicast link */ | 1292 | /* Broadcast ACKs are sent on a unicast link */ |
1118 | if (rc & TIPC_LINK_SND_BC_ACK) { | 1293 | if (rc & TIPC_LINK_SND_BC_ACK) { |
1119 | tipc_node_lock(n); | 1294 | tipc_node_read_lock(n); |
1120 | tipc_link_build_ack_msg(le->link, &xmitq); | 1295 | tipc_link_build_ack_msg(le->link, &xmitq); |
1121 | tipc_node_unlock(n); | 1296 | tipc_node_read_unlock(n); |
1122 | } | 1297 | } |
1123 | 1298 | ||
1124 | if (!skb_queue_empty(&xmitq)) | 1299 | if (!skb_queue_empty(&xmitq)) |
@@ -1151,30 +1326,30 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | |||
1151 | u16 oseqno = msg_seqno(hdr); | 1326 | u16 oseqno = msg_seqno(hdr); |
1152 | u16 iseqno = msg_seqno(msg_get_wrapped(hdr)); | 1327 | u16 iseqno = msg_seqno(msg_get_wrapped(hdr)); |
1153 | u16 exp_pkts = msg_msgcnt(hdr); | 1328 | u16 exp_pkts = msg_msgcnt(hdr); |
1154 | u16 rcv_nxt, syncpt, dlv_nxt; | 1329 | u16 rcv_nxt, syncpt, dlv_nxt, inputq_len; |
1155 | int state = n->state; | 1330 | int state = n->state; |
1156 | struct tipc_link *l, *tnl, *pl = NULL; | 1331 | struct tipc_link *l, *tnl, *pl = NULL; |
1157 | struct tipc_media_addr *maddr; | 1332 | struct tipc_media_addr *maddr; |
1158 | int i, pb_id; | 1333 | int pb_id; |
1159 | 1334 | ||
1160 | l = n->links[bearer_id].link; | 1335 | l = n->links[bearer_id].link; |
1161 | if (!l) | 1336 | if (!l) |
1162 | return false; | 1337 | return false; |
1163 | rcv_nxt = l->rcv_nxt; | 1338 | rcv_nxt = tipc_link_rcv_nxt(l); |
1164 | 1339 | ||
1165 | 1340 | ||
1166 | if (likely((state == SELF_UP_PEER_UP) && (usr != TUNNEL_PROTOCOL))) | 1341 | if (likely((state == SELF_UP_PEER_UP) && (usr != TUNNEL_PROTOCOL))) |
1167 | return true; | 1342 | return true; |
1168 | 1343 | ||
1169 | /* Find parallel link, if any */ | 1344 | /* Find parallel link, if any */ |
1170 | for (i = 0; i < MAX_BEARERS; i++) { | 1345 | for (pb_id = 0; pb_id < MAX_BEARERS; pb_id++) { |
1171 | if ((i != bearer_id) && n->links[i].link) { | 1346 | if ((pb_id != bearer_id) && n->links[pb_id].link) { |
1172 | pl = n->links[i].link; | 1347 | pl = n->links[pb_id].link; |
1173 | break; | 1348 | break; |
1174 | } | 1349 | } |
1175 | } | 1350 | } |
1176 | 1351 | ||
1177 | /* Update node accesibility if applicable */ | 1352 | /* Check and update node accesibility if applicable */ |
1178 | if (state == SELF_UP_PEER_COMING) { | 1353 | if (state == SELF_UP_PEER_COMING) { |
1179 | if (!tipc_link_is_up(l)) | 1354 | if (!tipc_link_is_up(l)) |
1180 | return true; | 1355 | return true; |
@@ -1187,8 +1362,12 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | |||
1187 | if (msg_peer_node_is_up(hdr)) | 1362 | if (msg_peer_node_is_up(hdr)) |
1188 | return false; | 1363 | return false; |
1189 | tipc_node_fsm_evt(n, PEER_LOST_CONTACT_EVT); | 1364 | tipc_node_fsm_evt(n, PEER_LOST_CONTACT_EVT); |
1365 | return true; | ||
1190 | } | 1366 | } |
1191 | 1367 | ||
1368 | if (state == SELF_LEAVING_PEER_DOWN) | ||
1369 | return false; | ||
1370 | |||
1192 | /* Ignore duplicate packets */ | 1371 | /* Ignore duplicate packets */ |
1193 | if ((usr != LINK_PROTOCOL) && less(oseqno, rcv_nxt)) | 1372 | if ((usr != LINK_PROTOCOL) && less(oseqno, rcv_nxt)) |
1194 | return true; | 1373 | return true; |
@@ -1197,9 +1376,9 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | |||
1197 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == FAILOVER_MSG)) { | 1376 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == FAILOVER_MSG)) { |
1198 | syncpt = oseqno + exp_pkts - 1; | 1377 | syncpt = oseqno + exp_pkts - 1; |
1199 | if (pl && tipc_link_is_up(pl)) { | 1378 | if (pl && tipc_link_is_up(pl)) { |
1200 | pb_id = pl->bearer_id; | ||
1201 | __tipc_node_link_down(n, &pb_id, xmitq, &maddr); | 1379 | __tipc_node_link_down(n, &pb_id, xmitq, &maddr); |
1202 | tipc_skb_queue_splice_tail_init(pl->inputq, l->inputq); | 1380 | tipc_skb_queue_splice_tail_init(tipc_link_inputq(pl), |
1381 | tipc_link_inputq(l)); | ||
1203 | } | 1382 | } |
1204 | /* If pkts arrive out of order, use lowest calculated syncpt */ | 1383 | /* If pkts arrive out of order, use lowest calculated syncpt */ |
1205 | if (less(syncpt, n->sync_point)) | 1384 | if (less(syncpt, n->sync_point)) |
@@ -1232,19 +1411,18 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | |||
1232 | tipc_link_fsm_evt(l, LINK_SYNCH_BEGIN_EVT); | 1411 | tipc_link_fsm_evt(l, LINK_SYNCH_BEGIN_EVT); |
1233 | tipc_node_fsm_evt(n, NODE_SYNCH_BEGIN_EVT); | 1412 | tipc_node_fsm_evt(n, NODE_SYNCH_BEGIN_EVT); |
1234 | } | 1413 | } |
1235 | if (less(syncpt, n->sync_point)) | ||
1236 | n->sync_point = syncpt; | ||
1237 | } | 1414 | } |
1238 | 1415 | ||
1239 | /* Open tunnel link when parallel link reaches synch point */ | 1416 | /* Open tunnel link when parallel link reaches synch point */ |
1240 | if ((n->state == NODE_SYNCHING) && tipc_link_is_synching(l)) { | 1417 | if (n->state == NODE_SYNCHING) { |
1241 | if (tipc_link_is_synching(l)) { | 1418 | if (tipc_link_is_synching(l)) { |
1242 | tnl = l; | 1419 | tnl = l; |
1243 | } else { | 1420 | } else { |
1244 | tnl = pl; | 1421 | tnl = pl; |
1245 | pl = l; | 1422 | pl = l; |
1246 | } | 1423 | } |
1247 | dlv_nxt = pl->rcv_nxt - mod(skb_queue_len(pl->inputq)); | 1424 | inputq_len = skb_queue_len(tipc_link_inputq(pl)); |
1425 | dlv_nxt = tipc_link_rcv_nxt(pl) - inputq_len; | ||
1248 | if (more(dlv_nxt, n->sync_point)) { | 1426 | if (more(dlv_nxt, n->sync_point)) { |
1249 | tipc_link_fsm_evt(tnl, LINK_SYNCH_END_EVT); | 1427 | tipc_link_fsm_evt(tnl, LINK_SYNCH_END_EVT); |
1250 | tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); | 1428 | tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); |
@@ -1304,22 +1482,32 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
1304 | /* Ensure broadcast reception is in synch with peer's send state */ | 1482 | /* Ensure broadcast reception is in synch with peer's send state */ |
1305 | if (unlikely(usr == LINK_PROTOCOL)) | 1483 | if (unlikely(usr == LINK_PROTOCOL)) |
1306 | tipc_bcast_sync_rcv(net, n->bc_entry.link, hdr); | 1484 | tipc_bcast_sync_rcv(net, n->bc_entry.link, hdr); |
1307 | else if (unlikely(n->bc_entry.link->acked != bc_ack)) | 1485 | else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack)) |
1308 | tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack); | 1486 | tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack); |
1309 | 1487 | ||
1310 | tipc_node_lock(n); | 1488 | /* Receive packet directly if conditions permit */ |
1311 | 1489 | tipc_node_read_lock(n); | |
1312 | /* Is reception permitted at the moment ? */ | 1490 | if (likely((n->state == SELF_UP_PEER_UP) && (usr != TUNNEL_PROTOCOL))) { |
1313 | if (!tipc_node_filter_pkt(n, hdr)) | 1491 | spin_lock_bh(&le->lock); |
1314 | goto unlock; | 1492 | if (le->link) { |
1315 | 1493 | rc = tipc_link_rcv(le->link, skb, &xmitq); | |
1316 | /* Check and if necessary update node state */ | 1494 | skb = NULL; |
1317 | if (likely(tipc_node_check_state(n, skb, bearer_id, &xmitq))) { | 1495 | } |
1318 | rc = tipc_link_rcv(le->link, skb, &xmitq); | 1496 | spin_unlock_bh(&le->lock); |
1319 | skb = NULL; | 1497 | } |
1498 | tipc_node_read_unlock(n); | ||
1499 | |||
1500 | /* Check/update node state before receiving */ | ||
1501 | if (unlikely(skb)) { | ||
1502 | tipc_node_write_lock(n); | ||
1503 | if (tipc_node_check_state(n, skb, bearer_id, &xmitq)) { | ||
1504 | if (le->link) { | ||
1505 | rc = tipc_link_rcv(le->link, skb, &xmitq); | ||
1506 | skb = NULL; | ||
1507 | } | ||
1508 | } | ||
1509 | tipc_node_write_unlock(n); | ||
1320 | } | 1510 | } |
1321 | unlock: | ||
1322 | tipc_node_unlock(n); | ||
1323 | 1511 | ||
1324 | if (unlikely(rc & TIPC_LINK_UP_EVT)) | 1512 | if (unlikely(rc & TIPC_LINK_UP_EVT)) |
1325 | tipc_node_link_up(n, bearer_id, &xmitq); | 1513 | tipc_node_link_up(n, bearer_id, &xmitq); |
@@ -1384,15 +1572,15 @@ int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
1384 | continue; | 1572 | continue; |
1385 | } | 1573 | } |
1386 | 1574 | ||
1387 | tipc_node_lock(node); | 1575 | tipc_node_read_lock(node); |
1388 | err = __tipc_nl_add_node(&msg, node); | 1576 | err = __tipc_nl_add_node(&msg, node); |
1389 | if (err) { | 1577 | if (err) { |
1390 | last_addr = node->addr; | 1578 | last_addr = node->addr; |
1391 | tipc_node_unlock(node); | 1579 | tipc_node_read_unlock(node); |
1392 | goto out; | 1580 | goto out; |
1393 | } | 1581 | } |
1394 | 1582 | ||
1395 | tipc_node_unlock(node); | 1583 | tipc_node_read_unlock(node); |
1396 | } | 1584 | } |
1397 | done = 1; | 1585 | done = 1; |
1398 | out: | 1586 | out: |
@@ -1402,3 +1590,314 @@ out: | |||
1402 | 1590 | ||
1403 | return skb->len; | 1591 | return skb->len; |
1404 | } | 1592 | } |
1593 | |||
1594 | /* tipc_node_find_by_name - locate owner node of link by link's name | ||
1595 | * @net: the applicable net namespace | ||
1596 | * @name: pointer to link name string | ||
1597 | * @bearer_id: pointer to index in 'node->links' array where the link was found. | ||
1598 | * | ||
1599 | * Returns pointer to node owning the link, or 0 if no matching link is found. | ||
1600 | */ | ||
1601 | static struct tipc_node *tipc_node_find_by_name(struct net *net, | ||
1602 | const char *link_name, | ||
1603 | unsigned int *bearer_id) | ||
1604 | { | ||
1605 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
1606 | struct tipc_link *l; | ||
1607 | struct tipc_node *n; | ||
1608 | struct tipc_node *found_node = NULL; | ||
1609 | int i; | ||
1610 | |||
1611 | *bearer_id = 0; | ||
1612 | rcu_read_lock(); | ||
1613 | list_for_each_entry_rcu(n, &tn->node_list, list) { | ||
1614 | tipc_node_read_lock(n); | ||
1615 | for (i = 0; i < MAX_BEARERS; i++) { | ||
1616 | l = n->links[i].link; | ||
1617 | if (l && !strcmp(tipc_link_name(l), link_name)) { | ||
1618 | *bearer_id = i; | ||
1619 | found_node = n; | ||
1620 | break; | ||
1621 | } | ||
1622 | } | ||
1623 | tipc_node_read_unlock(n); | ||
1624 | if (found_node) | ||
1625 | break; | ||
1626 | } | ||
1627 | rcu_read_unlock(); | ||
1628 | |||
1629 | return found_node; | ||
1630 | } | ||
1631 | |||
1632 | int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info) | ||
1633 | { | ||
1634 | int err; | ||
1635 | int res = 0; | ||
1636 | int bearer_id; | ||
1637 | char *name; | ||
1638 | struct tipc_link *link; | ||
1639 | struct tipc_node *node; | ||
1640 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; | ||
1641 | struct net *net = sock_net(skb->sk); | ||
1642 | |||
1643 | if (!info->attrs[TIPC_NLA_LINK]) | ||
1644 | return -EINVAL; | ||
1645 | |||
1646 | err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, | ||
1647 | info->attrs[TIPC_NLA_LINK], | ||
1648 | tipc_nl_link_policy); | ||
1649 | if (err) | ||
1650 | return err; | ||
1651 | |||
1652 | if (!attrs[TIPC_NLA_LINK_NAME]) | ||
1653 | return -EINVAL; | ||
1654 | |||
1655 | name = nla_data(attrs[TIPC_NLA_LINK_NAME]); | ||
1656 | |||
1657 | if (strcmp(name, tipc_bclink_name) == 0) | ||
1658 | return tipc_nl_bc_link_set(net, attrs); | ||
1659 | |||
1660 | node = tipc_node_find_by_name(net, name, &bearer_id); | ||
1661 | if (!node) | ||
1662 | return -EINVAL; | ||
1663 | |||
1664 | tipc_node_read_lock(node); | ||
1665 | |||
1666 | link = node->links[bearer_id].link; | ||
1667 | if (!link) { | ||
1668 | res = -EINVAL; | ||
1669 | goto out; | ||
1670 | } | ||
1671 | |||
1672 | if (attrs[TIPC_NLA_LINK_PROP]) { | ||
1673 | struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; | ||
1674 | |||
1675 | err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP], | ||
1676 | props); | ||
1677 | if (err) { | ||
1678 | res = err; | ||
1679 | goto out; | ||
1680 | } | ||
1681 | |||
1682 | if (props[TIPC_NLA_PROP_TOL]) { | ||
1683 | u32 tol; | ||
1684 | |||
1685 | tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); | ||
1686 | tipc_link_set_tolerance(link, tol); | ||
1687 | } | ||
1688 | if (props[TIPC_NLA_PROP_PRIO]) { | ||
1689 | u32 prio; | ||
1690 | |||
1691 | prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); | ||
1692 | tipc_link_set_prio(link, prio); | ||
1693 | } | ||
1694 | if (props[TIPC_NLA_PROP_WIN]) { | ||
1695 | u32 win; | ||
1696 | |||
1697 | win = nla_get_u32(props[TIPC_NLA_PROP_WIN]); | ||
1698 | tipc_link_set_queue_limits(link, win); | ||
1699 | } | ||
1700 | } | ||
1701 | |||
1702 | out: | ||
1703 | tipc_node_read_unlock(node); | ||
1704 | |||
1705 | return res; | ||
1706 | } | ||
1707 | |||
1708 | int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info) | ||
1709 | { | ||
1710 | struct net *net = genl_info_net(info); | ||
1711 | struct tipc_nl_msg msg; | ||
1712 | char *name; | ||
1713 | int err; | ||
1714 | |||
1715 | msg.portid = info->snd_portid; | ||
1716 | msg.seq = info->snd_seq; | ||
1717 | |||
1718 | if (!info->attrs[TIPC_NLA_LINK_NAME]) | ||
1719 | return -EINVAL; | ||
1720 | name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]); | ||
1721 | |||
1722 | msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
1723 | if (!msg.skb) | ||
1724 | return -ENOMEM; | ||
1725 | |||
1726 | if (strcmp(name, tipc_bclink_name) == 0) { | ||
1727 | err = tipc_nl_add_bc_link(net, &msg); | ||
1728 | if (err) { | ||
1729 | nlmsg_free(msg.skb); | ||
1730 | return err; | ||
1731 | } | ||
1732 | } else { | ||
1733 | int bearer_id; | ||
1734 | struct tipc_node *node; | ||
1735 | struct tipc_link *link; | ||
1736 | |||
1737 | node = tipc_node_find_by_name(net, name, &bearer_id); | ||
1738 | if (!node) | ||
1739 | return -EINVAL; | ||
1740 | |||
1741 | tipc_node_read_lock(node); | ||
1742 | link = node->links[bearer_id].link; | ||
1743 | if (!link) { | ||
1744 | tipc_node_read_unlock(node); | ||
1745 | nlmsg_free(msg.skb); | ||
1746 | return -EINVAL; | ||
1747 | } | ||
1748 | |||
1749 | err = __tipc_nl_add_link(net, &msg, link, 0); | ||
1750 | tipc_node_read_unlock(node); | ||
1751 | if (err) { | ||
1752 | nlmsg_free(msg.skb); | ||
1753 | return err; | ||
1754 | } | ||
1755 | } | ||
1756 | |||
1757 | return genlmsg_reply(msg.skb, info); | ||
1758 | } | ||
1759 | |||
1760 | int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info) | ||
1761 | { | ||
1762 | int err; | ||
1763 | char *link_name; | ||
1764 | unsigned int bearer_id; | ||
1765 | struct tipc_link *link; | ||
1766 | struct tipc_node *node; | ||
1767 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; | ||
1768 | struct net *net = sock_net(skb->sk); | ||
1769 | struct tipc_link_entry *le; | ||
1770 | |||
1771 | if (!info->attrs[TIPC_NLA_LINK]) | ||
1772 | return -EINVAL; | ||
1773 | |||
1774 | err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, | ||
1775 | info->attrs[TIPC_NLA_LINK], | ||
1776 | tipc_nl_link_policy); | ||
1777 | if (err) | ||
1778 | return err; | ||
1779 | |||
1780 | if (!attrs[TIPC_NLA_LINK_NAME]) | ||
1781 | return -EINVAL; | ||
1782 | |||
1783 | link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]); | ||
1784 | |||
1785 | if (strcmp(link_name, tipc_bclink_name) == 0) { | ||
1786 | err = tipc_bclink_reset_stats(net); | ||
1787 | if (err) | ||
1788 | return err; | ||
1789 | return 0; | ||
1790 | } | ||
1791 | |||
1792 | node = tipc_node_find_by_name(net, link_name, &bearer_id); | ||
1793 | if (!node) | ||
1794 | return -EINVAL; | ||
1795 | |||
1796 | le = &node->links[bearer_id]; | ||
1797 | tipc_node_read_lock(node); | ||
1798 | spin_lock_bh(&le->lock); | ||
1799 | link = node->links[bearer_id].link; | ||
1800 | if (!link) { | ||
1801 | spin_unlock_bh(&le->lock); | ||
1802 | tipc_node_read_unlock(node); | ||
1803 | return -EINVAL; | ||
1804 | } | ||
1805 | tipc_link_reset_stats(link); | ||
1806 | spin_unlock_bh(&le->lock); | ||
1807 | tipc_node_read_unlock(node); | ||
1808 | return 0; | ||
1809 | } | ||
1810 | |||
1811 | /* Caller should hold node lock */ | ||
1812 | static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg, | ||
1813 | struct tipc_node *node, u32 *prev_link) | ||
1814 | { | ||
1815 | u32 i; | ||
1816 | int err; | ||
1817 | |||
1818 | for (i = *prev_link; i < MAX_BEARERS; i++) { | ||
1819 | *prev_link = i; | ||
1820 | |||
1821 | if (!node->links[i].link) | ||
1822 | continue; | ||
1823 | |||
1824 | err = __tipc_nl_add_link(net, msg, | ||
1825 | node->links[i].link, NLM_F_MULTI); | ||
1826 | if (err) | ||
1827 | return err; | ||
1828 | } | ||
1829 | *prev_link = 0; | ||
1830 | |||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1834 | int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb) | ||
1835 | { | ||
1836 | struct net *net = sock_net(skb->sk); | ||
1837 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
1838 | struct tipc_node *node; | ||
1839 | struct tipc_nl_msg msg; | ||
1840 | u32 prev_node = cb->args[0]; | ||
1841 | u32 prev_link = cb->args[1]; | ||
1842 | int done = cb->args[2]; | ||
1843 | int err; | ||
1844 | |||
1845 | if (done) | ||
1846 | return 0; | ||
1847 | |||
1848 | msg.skb = skb; | ||
1849 | msg.portid = NETLINK_CB(cb->skb).portid; | ||
1850 | msg.seq = cb->nlh->nlmsg_seq; | ||
1851 | |||
1852 | rcu_read_lock(); | ||
1853 | if (prev_node) { | ||
1854 | node = tipc_node_find(net, prev_node); | ||
1855 | if (!node) { | ||
1856 | /* We never set seq or call nl_dump_check_consistent() | ||
1857 | * this means that setting prev_seq here will cause the | ||
1858 | * consistence check to fail in the netlink callback | ||
1859 | * handler. Resulting in the last NLMSG_DONE message | ||
1860 | * having the NLM_F_DUMP_INTR flag set. | ||
1861 | */ | ||
1862 | cb->prev_seq = 1; | ||
1863 | goto out; | ||
1864 | } | ||
1865 | tipc_node_put(node); | ||
1866 | |||
1867 | list_for_each_entry_continue_rcu(node, &tn->node_list, | ||
1868 | list) { | ||
1869 | tipc_node_read_lock(node); | ||
1870 | err = __tipc_nl_add_node_links(net, &msg, node, | ||
1871 | &prev_link); | ||
1872 | tipc_node_read_unlock(node); | ||
1873 | if (err) | ||
1874 | goto out; | ||
1875 | |||
1876 | prev_node = node->addr; | ||
1877 | } | ||
1878 | } else { | ||
1879 | err = tipc_nl_add_bc_link(net, &msg); | ||
1880 | if (err) | ||
1881 | goto out; | ||
1882 | |||
1883 | list_for_each_entry_rcu(node, &tn->node_list, list) { | ||
1884 | tipc_node_read_lock(node); | ||
1885 | err = __tipc_nl_add_node_links(net, &msg, node, | ||
1886 | &prev_link); | ||
1887 | tipc_node_read_unlock(node); | ||
1888 | if (err) | ||
1889 | goto out; | ||
1890 | |||
1891 | prev_node = node->addr; | ||
1892 | } | ||
1893 | } | ||
1894 | done = 1; | ||
1895 | out: | ||
1896 | rcu_read_unlock(); | ||
1897 | |||
1898 | cb->args[0] = prev_node; | ||
1899 | cb->args[1] = prev_link; | ||
1900 | cb->args[2] = done; | ||
1901 | |||
1902 | return skb->len; | ||
1903 | } | ||
diff --git a/net/tipc/node.h b/net/tipc/node.h index 6734562d3c6e..f39d9d06e8bb 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -42,23 +42,6 @@ | |||
42 | #include "bearer.h" | 42 | #include "bearer.h" |
43 | #include "msg.h" | 43 | #include "msg.h" |
44 | 44 | ||
45 | /* Out-of-range value for node signature */ | ||
46 | #define INVALID_NODE_SIG 0x10000 | ||
47 | |||
48 | #define INVALID_BEARER_ID -1 | ||
49 | |||
50 | /* Flags used to take different actions according to flag type | ||
51 | * TIPC_NOTIFY_NODE_DOWN: notify node is down | ||
52 | * TIPC_NOTIFY_NODE_UP: notify node is up | ||
53 | * TIPC_DISTRIBUTE_NAME: publish or withdraw link state name type | ||
54 | */ | ||
55 | enum { | ||
56 | TIPC_NOTIFY_NODE_DOWN = (1 << 3), | ||
57 | TIPC_NOTIFY_NODE_UP = (1 << 4), | ||
58 | TIPC_NOTIFY_LINK_UP = (1 << 6), | ||
59 | TIPC_NOTIFY_LINK_DOWN = (1 << 7) | ||
60 | }; | ||
61 | |||
62 | /* Optional capabilities supported by this code version | 45 | /* Optional capabilities supported by this code version |
63 | */ | 46 | */ |
64 | enum { | 47 | enum { |
@@ -66,72 +49,8 @@ enum { | |||
66 | }; | 49 | }; |
67 | 50 | ||
68 | #define TIPC_NODE_CAPABILITIES TIPC_BCAST_SYNCH | 51 | #define TIPC_NODE_CAPABILITIES TIPC_BCAST_SYNCH |
52 | #define INVALID_BEARER_ID -1 | ||
69 | 53 | ||
70 | struct tipc_link_entry { | ||
71 | struct tipc_link *link; | ||
72 | u32 mtu; | ||
73 | struct sk_buff_head inputq; | ||
74 | struct tipc_media_addr maddr; | ||
75 | }; | ||
76 | |||
77 | struct tipc_bclink_entry { | ||
78 | struct tipc_link *link; | ||
79 | struct sk_buff_head inputq1; | ||
80 | struct sk_buff_head arrvq; | ||
81 | struct sk_buff_head inputq2; | ||
82 | struct sk_buff_head namedq; | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * struct tipc_node - TIPC node structure | ||
87 | * @addr: network address of node | ||
88 | * @ref: reference counter to node object | ||
89 | * @lock: spinlock governing access to structure | ||
90 | * @net: the applicable net namespace | ||
91 | * @hash: links to adjacent nodes in unsorted hash chain | ||
92 | * @inputq: pointer to input queue containing messages for msg event | ||
93 | * @namedq: pointer to name table input queue with name table messages | ||
94 | * @active_links: bearer ids of active links, used as index into links[] array | ||
95 | * @links: array containing references to all links to node | ||
96 | * @action_flags: bit mask of different types of node actions | ||
97 | * @state: connectivity state vs peer node | ||
98 | * @sync_point: sequence number where synch/failover is finished | ||
99 | * @list: links to adjacent nodes in sorted list of cluster's nodes | ||
100 | * @working_links: number of working links to node (both active and standby) | ||
101 | * @link_cnt: number of links to node | ||
102 | * @capabilities: bitmap, indicating peer node's functional capabilities | ||
103 | * @signature: node instance identifier | ||
104 | * @link_id: local and remote bearer ids of changing link, if any | ||
105 | * @publ_list: list of publications | ||
106 | * @rcu: rcu struct for tipc_node | ||
107 | */ | ||
108 | struct tipc_node { | ||
109 | u32 addr; | ||
110 | struct kref kref; | ||
111 | spinlock_t lock; | ||
112 | struct net *net; | ||
113 | struct hlist_node hash; | ||
114 | int active_links[2]; | ||
115 | struct tipc_link_entry links[MAX_BEARERS]; | ||
116 | struct tipc_bclink_entry bc_entry; | ||
117 | int action_flags; | ||
118 | struct list_head list; | ||
119 | int state; | ||
120 | u16 sync_point; | ||
121 | int link_cnt; | ||
122 | u16 working_links; | ||
123 | u16 capabilities; | ||
124 | u32 signature; | ||
125 | u32 link_id; | ||
126 | struct list_head publ_list; | ||
127 | struct list_head conn_sks; | ||
128 | unsigned long keepalive_intv; | ||
129 | struct timer_list timer; | ||
130 | struct rcu_head rcu; | ||
131 | }; | ||
132 | |||
133 | struct tipc_node *tipc_node_find(struct net *net, u32 addr); | ||
134 | void tipc_node_put(struct tipc_node *node); | ||
135 | void tipc_node_stop(struct net *net); | 54 | void tipc_node_stop(struct net *net); |
136 | void tipc_node_check_dest(struct net *net, u32 onode, | 55 | void tipc_node_check_dest(struct net *net, u32 onode, |
137 | struct tipc_bearer *bearer, | 56 | struct tipc_bearer *bearer, |
@@ -139,50 +58,22 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
139 | struct tipc_media_addr *maddr, | 58 | struct tipc_media_addr *maddr, |
140 | bool *respond, bool *dupl_addr); | 59 | bool *respond, bool *dupl_addr); |
141 | void tipc_node_delete_links(struct net *net, int bearer_id); | 60 | void tipc_node_delete_links(struct net *net, int bearer_id); |
142 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | ||
143 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | ||
144 | bool tipc_node_is_up(struct tipc_node *n); | ||
145 | int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, | 61 | int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, |
146 | char *linkname, size_t len); | 62 | char *linkname, size_t len); |
147 | void tipc_node_unlock(struct tipc_node *node); | ||
148 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, | 63 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, |
149 | int selector); | 64 | int selector); |
150 | int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, | 65 | int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, |
151 | u32 selector); | 66 | u32 selector); |
67 | void tipc_node_subscribe(struct net *net, struct list_head *subscr, u32 addr); | ||
68 | void tipc_node_unsubscribe(struct net *net, struct list_head *subscr, u32 addr); | ||
69 | void tipc_node_broadcast(struct net *net, struct sk_buff *skb); | ||
152 | int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port); | 70 | int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port); |
153 | void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port); | 71 | void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port); |
72 | int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel); | ||
154 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb); | 73 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb); |
155 | 74 | int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb); | |
156 | static inline void tipc_node_lock(struct tipc_node *node) | 75 | int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info); |
157 | { | 76 | int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info); |
158 | spin_lock_bh(&node->lock); | 77 | int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info); |
159 | } | ||
160 | |||
161 | static inline struct tipc_link *node_active_link(struct tipc_node *n, int sel) | ||
162 | { | ||
163 | int bearer_id = n->active_links[sel & 1]; | ||
164 | |||
165 | if (unlikely(bearer_id == INVALID_BEARER_ID)) | ||
166 | return NULL; | ||
167 | |||
168 | return n->links[bearer_id].link; | ||
169 | } | ||
170 | |||
171 | static inline unsigned int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel) | ||
172 | { | ||
173 | struct tipc_node *n; | ||
174 | int bearer_id; | ||
175 | unsigned int mtu = MAX_MSG_SIZE; | ||
176 | |||
177 | n = tipc_node_find(net, addr); | ||
178 | if (unlikely(!n)) | ||
179 | return mtu; | ||
180 | |||
181 | bearer_id = n->active_links[sel & 1]; | ||
182 | if (likely(bearer_id != INVALID_BEARER_ID)) | ||
183 | mtu = n->links[bearer_id].mtu; | ||
184 | tipc_node_put(n); | ||
185 | return mtu; | ||
186 | } | ||
187 | 78 | ||
188 | #endif | 79 | #endif |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 552dbaba9cf3..69c29050f14a 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -105,6 +105,7 @@ struct tipc_sock { | |||
105 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb); | 105 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb); |
106 | static void tipc_data_ready(struct sock *sk); | 106 | static void tipc_data_ready(struct sock *sk); |
107 | static void tipc_write_space(struct sock *sk); | 107 | static void tipc_write_space(struct sock *sk); |
108 | static void tipc_sock_destruct(struct sock *sk); | ||
108 | static int tipc_release(struct socket *sock); | 109 | static int tipc_release(struct socket *sock); |
109 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); | 110 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); |
110 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); | 111 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); |
@@ -381,6 +382,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, | |||
381 | sk->sk_rcvbuf = sysctl_tipc_rmem[1]; | 382 | sk->sk_rcvbuf = sysctl_tipc_rmem[1]; |
382 | sk->sk_data_ready = tipc_data_ready; | 383 | sk->sk_data_ready = tipc_data_ready; |
383 | sk->sk_write_space = tipc_write_space; | 384 | sk->sk_write_space = tipc_write_space; |
385 | sk->sk_destruct = tipc_sock_destruct; | ||
384 | tsk->conn_timeout = CONN_TIMEOUT_DEFAULT; | 386 | tsk->conn_timeout = CONN_TIMEOUT_DEFAULT; |
385 | tsk->sent_unacked = 0; | 387 | tsk->sent_unacked = 0; |
386 | atomic_set(&tsk->dupl_rcvcnt, 0); | 388 | atomic_set(&tsk->dupl_rcvcnt, 0); |
@@ -470,9 +472,6 @@ static int tipc_release(struct socket *sock) | |||
470 | tipc_node_remove_conn(net, dnode, tsk->portid); | 472 | tipc_node_remove_conn(net, dnode, tsk->portid); |
471 | } | 473 | } |
472 | 474 | ||
473 | /* Discard any remaining (connection-based) messages in receive queue */ | ||
474 | __skb_queue_purge(&sk->sk_receive_queue); | ||
475 | |||
476 | /* Reject any messages that accumulated in backlog queue */ | 475 | /* Reject any messages that accumulated in backlog queue */ |
477 | sock->state = SS_DISCONNECTING; | 476 | sock->state = SS_DISCONNECTING; |
478 | release_sock(sk); | 477 | release_sock(sk); |
@@ -1492,7 +1491,7 @@ static void tipc_write_space(struct sock *sk) | |||
1492 | 1491 | ||
1493 | rcu_read_lock(); | 1492 | rcu_read_lock(); |
1494 | wq = rcu_dereference(sk->sk_wq); | 1493 | wq = rcu_dereference(sk->sk_wq); |
1495 | if (wq_has_sleeper(wq)) | 1494 | if (skwq_has_sleeper(wq)) |
1496 | wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | | 1495 | wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | |
1497 | POLLWRNORM | POLLWRBAND); | 1496 | POLLWRNORM | POLLWRBAND); |
1498 | rcu_read_unlock(); | 1497 | rcu_read_unlock(); |
@@ -1509,12 +1508,17 @@ static void tipc_data_ready(struct sock *sk) | |||
1509 | 1508 | ||
1510 | rcu_read_lock(); | 1509 | rcu_read_lock(); |
1511 | wq = rcu_dereference(sk->sk_wq); | 1510 | wq = rcu_dereference(sk->sk_wq); |
1512 | if (wq_has_sleeper(wq)) | 1511 | if (skwq_has_sleeper(wq)) |
1513 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | | 1512 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | |
1514 | POLLRDNORM | POLLRDBAND); | 1513 | POLLRDNORM | POLLRDBAND); |
1515 | rcu_read_unlock(); | 1514 | rcu_read_unlock(); |
1516 | } | 1515 | } |
1517 | 1516 | ||
1517 | static void tipc_sock_destruct(struct sock *sk) | ||
1518 | { | ||
1519 | __skb_queue_purge(&sk->sk_receive_queue); | ||
1520 | } | ||
1521 | |||
1518 | /** | 1522 | /** |
1519 | * filter_connect - Handle all incoming messages for a connection-based socket | 1523 | * filter_connect - Handle all incoming messages for a connection-based socket |
1520 | * @tsk: TIPC socket | 1524 | * @tsk: TIPC socket |
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index ad2719ad4c1b..d63a911e7fe2 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c | |||
@@ -48,7 +48,6 @@ | |||
48 | #include <linux/tipc_netlink.h> | 48 | #include <linux/tipc_netlink.h> |
49 | #include "core.h" | 49 | #include "core.h" |
50 | #include "bearer.h" | 50 | #include "bearer.h" |
51 | #include "msg.h" | ||
52 | 51 | ||
53 | /* IANA assigned UDP port */ | 52 | /* IANA assigned UDP port */ |
54 | #define UDP_PORT_DEFAULT 6118 | 53 | #define UDP_PORT_DEFAULT 6118 |
@@ -158,8 +157,11 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
158 | struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value; | 157 | struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value; |
159 | struct rtable *rt; | 158 | struct rtable *rt; |
160 | 159 | ||
161 | if (skb_headroom(skb) < UDP_MIN_HEADROOM) | 160 | if (skb_headroom(skb) < UDP_MIN_HEADROOM) { |
162 | pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC); | 161 | err = pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC); |
162 | if (err) | ||
163 | goto tx_error; | ||
164 | } | ||
163 | 165 | ||
164 | skb_set_inner_protocol(skb, htons(ETH_P_TIPC)); | 166 | skb_set_inner_protocol(skb, htons(ETH_P_TIPC)); |
165 | ub = rcu_dereference_rtnl(b->media_ptr); | 167 | ub = rcu_dereference_rtnl(b->media_ptr); |
@@ -180,15 +182,9 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
180 | goto tx_error; | 182 | goto tx_error; |
181 | } | 183 | } |
182 | ttl = ip4_dst_hoplimit(&rt->dst); | 184 | ttl = ip4_dst_hoplimit(&rt->dst); |
183 | err = udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, | 185 | udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, |
184 | src->ipv4.s_addr, | 186 | dst->ipv4.s_addr, 0, ttl, 0, src->udp_port, |
185 | dst->ipv4.s_addr, 0, ttl, 0, | 187 | dst->udp_port, false, true); |
186 | src->udp_port, dst->udp_port, | ||
187 | false, true); | ||
188 | if (err < 0) { | ||
189 | ip_rt_put(rt); | ||
190 | goto tx_error; | ||
191 | } | ||
192 | #if IS_ENABLED(CONFIG_IPV6) | 188 | #if IS_ENABLED(CONFIG_IPV6) |
193 | } else { | 189 | } else { |
194 | struct dst_entry *ndst; | 190 | struct dst_entry *ndst; |
@@ -221,10 +217,6 @@ static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb) | |||
221 | { | 217 | { |
222 | struct udp_bearer *ub; | 218 | struct udp_bearer *ub; |
223 | struct tipc_bearer *b; | 219 | struct tipc_bearer *b; |
224 | int usr = msg_user(buf_msg(skb)); | ||
225 | |||
226 | if ((usr == LINK_PROTOCOL) || (usr == NAME_DISTRIBUTOR)) | ||
227 | skb_linearize(skb); | ||
228 | 220 | ||
229 | ub = rcu_dereference_sk_user_data(sk); | 221 | ub = rcu_dereference_sk_user_data(sk); |
230 | if (!ub) { | 222 | if (!ub) { |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 955ec152cb71..c5bf5ef2bf89 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -326,6 +326,118 @@ found: | |||
326 | return s; | 326 | return s; |
327 | } | 327 | } |
328 | 328 | ||
329 | /* Support code for asymmetrically connected dgram sockets | ||
330 | * | ||
331 | * If a datagram socket is connected to a socket not itself connected | ||
332 | * to the first socket (eg, /dev/log), clients may only enqueue more | ||
333 | * messages if the present receive queue of the server socket is not | ||
334 | * "too large". This means there's a second writeability condition | ||
335 | * poll and sendmsg need to test. The dgram recv code will do a wake | ||
336 | * up on the peer_wait wait queue of a socket upon reception of a | ||
337 | * datagram which needs to be propagated to sleeping would-be writers | ||
338 | * since these might not have sent anything so far. This can't be | ||
339 | * accomplished via poll_wait because the lifetime of the server | ||
340 | * socket might be less than that of its clients if these break their | ||
341 | * association with it or if the server socket is closed while clients | ||
342 | * are still connected to it and there's no way to inform "a polling | ||
343 | * implementation" that it should let go of a certain wait queue | ||
344 | * | ||
345 | * In order to propagate a wake up, a wait_queue_t of the client | ||
346 | * socket is enqueued on the peer_wait queue of the server socket | ||
347 | * whose wake function does a wake_up on the ordinary client socket | ||
348 | * wait queue. This connection is established whenever a write (or | ||
349 | * poll for write) hit the flow control condition and broken when the | ||
350 | * association to the server socket is dissolved or after a wake up | ||
351 | * was relayed. | ||
352 | */ | ||
353 | |||
354 | static int unix_dgram_peer_wake_relay(wait_queue_t *q, unsigned mode, int flags, | ||
355 | void *key) | ||
356 | { | ||
357 | struct unix_sock *u; | ||
358 | wait_queue_head_t *u_sleep; | ||
359 | |||
360 | u = container_of(q, struct unix_sock, peer_wake); | ||
361 | |||
362 | __remove_wait_queue(&unix_sk(u->peer_wake.private)->peer_wait, | ||
363 | q); | ||
364 | u->peer_wake.private = NULL; | ||
365 | |||
366 | /* relaying can only happen while the wq still exists */ | ||
367 | u_sleep = sk_sleep(&u->sk); | ||
368 | if (u_sleep) | ||
369 | wake_up_interruptible_poll(u_sleep, key); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int unix_dgram_peer_wake_connect(struct sock *sk, struct sock *other) | ||
375 | { | ||
376 | struct unix_sock *u, *u_other; | ||
377 | int rc; | ||
378 | |||
379 | u = unix_sk(sk); | ||
380 | u_other = unix_sk(other); | ||
381 | rc = 0; | ||
382 | spin_lock(&u_other->peer_wait.lock); | ||
383 | |||
384 | if (!u->peer_wake.private) { | ||
385 | u->peer_wake.private = other; | ||
386 | __add_wait_queue(&u_other->peer_wait, &u->peer_wake); | ||
387 | |||
388 | rc = 1; | ||
389 | } | ||
390 | |||
391 | spin_unlock(&u_other->peer_wait.lock); | ||
392 | return rc; | ||
393 | } | ||
394 | |||
395 | static void unix_dgram_peer_wake_disconnect(struct sock *sk, | ||
396 | struct sock *other) | ||
397 | { | ||
398 | struct unix_sock *u, *u_other; | ||
399 | |||
400 | u = unix_sk(sk); | ||
401 | u_other = unix_sk(other); | ||
402 | spin_lock(&u_other->peer_wait.lock); | ||
403 | |||
404 | if (u->peer_wake.private == other) { | ||
405 | __remove_wait_queue(&u_other->peer_wait, &u->peer_wake); | ||
406 | u->peer_wake.private = NULL; | ||
407 | } | ||
408 | |||
409 | spin_unlock(&u_other->peer_wait.lock); | ||
410 | } | ||
411 | |||
412 | static void unix_dgram_peer_wake_disconnect_wakeup(struct sock *sk, | ||
413 | struct sock *other) | ||
414 | { | ||
415 | unix_dgram_peer_wake_disconnect(sk, other); | ||
416 | wake_up_interruptible_poll(sk_sleep(sk), | ||
417 | POLLOUT | | ||
418 | POLLWRNORM | | ||
419 | POLLWRBAND); | ||
420 | } | ||
421 | |||
422 | /* preconditions: | ||
423 | * - unix_peer(sk) == other | ||
424 | * - association is stable | ||
425 | */ | ||
426 | static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other) | ||
427 | { | ||
428 | int connected; | ||
429 | |||
430 | connected = unix_dgram_peer_wake_connect(sk, other); | ||
431 | |||
432 | if (unix_recvq_full(other)) | ||
433 | return 1; | ||
434 | |||
435 | if (connected) | ||
436 | unix_dgram_peer_wake_disconnect(sk, other); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
329 | static int unix_writable(const struct sock *sk) | 441 | static int unix_writable(const struct sock *sk) |
330 | { | 442 | { |
331 | return sk->sk_state != TCP_LISTEN && | 443 | return sk->sk_state != TCP_LISTEN && |
@@ -339,7 +451,7 @@ static void unix_write_space(struct sock *sk) | |||
339 | rcu_read_lock(); | 451 | rcu_read_lock(); |
340 | if (unix_writable(sk)) { | 452 | if (unix_writable(sk)) { |
341 | wq = rcu_dereference(sk->sk_wq); | 453 | wq = rcu_dereference(sk->sk_wq); |
342 | if (wq_has_sleeper(wq)) | 454 | if (skwq_has_sleeper(wq)) |
343 | wake_up_interruptible_sync_poll(&wq->wait, | 455 | wake_up_interruptible_sync_poll(&wq->wait, |
344 | POLLOUT | POLLWRNORM | POLLWRBAND); | 456 | POLLOUT | POLLWRNORM | POLLWRBAND); |
345 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 457 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
@@ -431,6 +543,8 @@ static void unix_release_sock(struct sock *sk, int embrion) | |||
431 | skpair->sk_state_change(skpair); | 543 | skpair->sk_state_change(skpair); |
432 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); | 544 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); |
433 | } | 545 | } |
546 | |||
547 | unix_dgram_peer_wake_disconnect(sk, skpair); | ||
434 | sock_put(skpair); /* It may now die */ | 548 | sock_put(skpair); /* It may now die */ |
435 | unix_peer(sk) = NULL; | 549 | unix_peer(sk) = NULL; |
436 | } | 550 | } |
@@ -666,6 +780,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern) | |||
666 | INIT_LIST_HEAD(&u->link); | 780 | INIT_LIST_HEAD(&u->link); |
667 | mutex_init(&u->readlock); /* single task reading lock */ | 781 | mutex_init(&u->readlock); /* single task reading lock */ |
668 | init_waitqueue_head(&u->peer_wait); | 782 | init_waitqueue_head(&u->peer_wait); |
783 | init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay); | ||
669 | unix_insert_socket(unix_sockets_unbound(sk), sk); | 784 | unix_insert_socket(unix_sockets_unbound(sk), sk); |
670 | out: | 785 | out: |
671 | if (sk == NULL) | 786 | if (sk == NULL) |
@@ -838,32 +953,20 @@ fail: | |||
838 | return NULL; | 953 | return NULL; |
839 | } | 954 | } |
840 | 955 | ||
841 | static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) | 956 | static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode, |
957 | struct path *res) | ||
842 | { | 958 | { |
843 | struct dentry *dentry; | 959 | int err; |
844 | struct path path; | ||
845 | int err = 0; | ||
846 | /* | ||
847 | * Get the parent directory, calculate the hash for last | ||
848 | * component. | ||
849 | */ | ||
850 | dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | ||
851 | err = PTR_ERR(dentry); | ||
852 | if (IS_ERR(dentry)) | ||
853 | return err; | ||
854 | 960 | ||
855 | /* | 961 | err = security_path_mknod(path, dentry, mode, 0); |
856 | * All right, let's create it. | ||
857 | */ | ||
858 | err = security_path_mknod(&path, dentry, mode, 0); | ||
859 | if (!err) { | 962 | if (!err) { |
860 | err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0); | 963 | err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0); |
861 | if (!err) { | 964 | if (!err) { |
862 | res->mnt = mntget(path.mnt); | 965 | res->mnt = mntget(path->mnt); |
863 | res->dentry = dget(dentry); | 966 | res->dentry = dget(dentry); |
864 | } | 967 | } |
865 | } | 968 | } |
866 | done_path_create(&path, dentry); | 969 | |
867 | return err; | 970 | return err; |
868 | } | 971 | } |
869 | 972 | ||
@@ -874,10 +977,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
874 | struct unix_sock *u = unix_sk(sk); | 977 | struct unix_sock *u = unix_sk(sk); |
875 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; | 978 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
876 | char *sun_path = sunaddr->sun_path; | 979 | char *sun_path = sunaddr->sun_path; |
877 | int err; | 980 | int err, name_err; |
878 | unsigned int hash; | 981 | unsigned int hash; |
879 | struct unix_address *addr; | 982 | struct unix_address *addr; |
880 | struct hlist_head *list; | 983 | struct hlist_head *list; |
984 | struct path path; | ||
985 | struct dentry *dentry; | ||
881 | 986 | ||
882 | err = -EINVAL; | 987 | err = -EINVAL; |
883 | if (sunaddr->sun_family != AF_UNIX) | 988 | if (sunaddr->sun_family != AF_UNIX) |
@@ -893,14 +998,34 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
893 | goto out; | 998 | goto out; |
894 | addr_len = err; | 999 | addr_len = err; |
895 | 1000 | ||
1001 | name_err = 0; | ||
1002 | dentry = NULL; | ||
1003 | if (sun_path[0]) { | ||
1004 | /* Get the parent directory, calculate the hash for last | ||
1005 | * component. | ||
1006 | */ | ||
1007 | dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | ||
1008 | |||
1009 | if (IS_ERR(dentry)) { | ||
1010 | /* delay report until after 'already bound' check */ | ||
1011 | name_err = PTR_ERR(dentry); | ||
1012 | dentry = NULL; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
896 | err = mutex_lock_interruptible(&u->readlock); | 1016 | err = mutex_lock_interruptible(&u->readlock); |
897 | if (err) | 1017 | if (err) |
898 | goto out; | 1018 | goto out_path; |
899 | 1019 | ||
900 | err = -EINVAL; | 1020 | err = -EINVAL; |
901 | if (u->addr) | 1021 | if (u->addr) |
902 | goto out_up; | 1022 | goto out_up; |
903 | 1023 | ||
1024 | if (name_err) { | ||
1025 | err = name_err == -EEXIST ? -EADDRINUSE : name_err; | ||
1026 | goto out_up; | ||
1027 | } | ||
1028 | |||
904 | err = -ENOMEM; | 1029 | err = -ENOMEM; |
905 | addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); | 1030 | addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); |
906 | if (!addr) | 1031 | if (!addr) |
@@ -911,11 +1036,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
911 | addr->hash = hash ^ sk->sk_type; | 1036 | addr->hash = hash ^ sk->sk_type; |
912 | atomic_set(&addr->refcnt, 1); | 1037 | atomic_set(&addr->refcnt, 1); |
913 | 1038 | ||
914 | if (sun_path[0]) { | 1039 | if (dentry) { |
915 | struct path path; | 1040 | struct path u_path; |
916 | umode_t mode = S_IFSOCK | | 1041 | umode_t mode = S_IFSOCK | |
917 | (SOCK_INODE(sock)->i_mode & ~current_umask()); | 1042 | (SOCK_INODE(sock)->i_mode & ~current_umask()); |
918 | err = unix_mknod(sun_path, mode, &path); | 1043 | err = unix_mknod(dentry, &path, mode, &u_path); |
919 | if (err) { | 1044 | if (err) { |
920 | if (err == -EEXIST) | 1045 | if (err == -EEXIST) |
921 | err = -EADDRINUSE; | 1046 | err = -EADDRINUSE; |
@@ -923,9 +1048,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
923 | goto out_up; | 1048 | goto out_up; |
924 | } | 1049 | } |
925 | addr->hash = UNIX_HASH_SIZE; | 1050 | addr->hash = UNIX_HASH_SIZE; |
926 | hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1); | 1051 | hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1); |
927 | spin_lock(&unix_table_lock); | 1052 | spin_lock(&unix_table_lock); |
928 | u->path = path; | 1053 | u->path = u_path; |
929 | list = &unix_socket_table[hash]; | 1054 | list = &unix_socket_table[hash]; |
930 | } else { | 1055 | } else { |
931 | spin_lock(&unix_table_lock); | 1056 | spin_lock(&unix_table_lock); |
@@ -948,6 +1073,10 @@ out_unlock: | |||
948 | spin_unlock(&unix_table_lock); | 1073 | spin_unlock(&unix_table_lock); |
949 | out_up: | 1074 | out_up: |
950 | mutex_unlock(&u->readlock); | 1075 | mutex_unlock(&u->readlock); |
1076 | out_path: | ||
1077 | if (dentry) | ||
1078 | done_path_create(&path, dentry); | ||
1079 | |||
951 | out: | 1080 | out: |
952 | return err; | 1081 | return err; |
953 | } | 1082 | } |
@@ -1033,6 +1162,8 @@ restart: | |||
1033 | if (unix_peer(sk)) { | 1162 | if (unix_peer(sk)) { |
1034 | struct sock *old_peer = unix_peer(sk); | 1163 | struct sock *old_peer = unix_peer(sk); |
1035 | unix_peer(sk) = other; | 1164 | unix_peer(sk) = other; |
1165 | unix_dgram_peer_wake_disconnect_wakeup(sk, old_peer); | ||
1166 | |||
1036 | unix_state_double_unlock(sk, other); | 1167 | unix_state_double_unlock(sk, other); |
1037 | 1168 | ||
1038 | if (other != old_peer) | 1169 | if (other != old_peer) |
@@ -1382,6 +1513,21 @@ static void unix_destruct_scm(struct sk_buff *skb) | |||
1382 | sock_wfree(skb); | 1513 | sock_wfree(skb); |
1383 | } | 1514 | } |
1384 | 1515 | ||
1516 | /* | ||
1517 | * The "user->unix_inflight" variable is protected by the garbage | ||
1518 | * collection lock, and we just read it locklessly here. If you go | ||
1519 | * over the limit, there might be a tiny race in actually noticing | ||
1520 | * it across threads. Tough. | ||
1521 | */ | ||
1522 | static inline bool too_many_unix_fds(struct task_struct *p) | ||
1523 | { | ||
1524 | struct user_struct *user = current_user(); | ||
1525 | |||
1526 | if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE))) | ||
1527 | return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); | ||
1528 | return false; | ||
1529 | } | ||
1530 | |||
1385 | #define MAX_RECURSION_LEVEL 4 | 1531 | #define MAX_RECURSION_LEVEL 4 |
1386 | 1532 | ||
1387 | static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | 1533 | static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) |
@@ -1390,6 +1536,9 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | |||
1390 | unsigned char max_level = 0; | 1536 | unsigned char max_level = 0; |
1391 | int unix_sock_count = 0; | 1537 | int unix_sock_count = 0; |
1392 | 1538 | ||
1539 | if (too_many_unix_fds(current)) | ||
1540 | return -ETOOMANYREFS; | ||
1541 | |||
1393 | for (i = scm->fp->count - 1; i >= 0; i--) { | 1542 | for (i = scm->fp->count - 1; i >= 0; i--) { |
1394 | struct sock *sk = unix_get_socket(scm->fp->fp[i]); | 1543 | struct sock *sk = unix_get_socket(scm->fp->fp[i]); |
1395 | 1544 | ||
@@ -1411,10 +1560,8 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | |||
1411 | if (!UNIXCB(skb).fp) | 1560 | if (!UNIXCB(skb).fp) |
1412 | return -ENOMEM; | 1561 | return -ENOMEM; |
1413 | 1562 | ||
1414 | if (unix_sock_count) { | 1563 | for (i = scm->fp->count - 1; i >= 0; i--) |
1415 | for (i = scm->fp->count - 1; i >= 0; i--) | 1564 | unix_inflight(scm->fp->fp[i]); |
1416 | unix_inflight(scm->fp->fp[i]); | ||
1417 | } | ||
1418 | return max_level; | 1565 | return max_level; |
1419 | } | 1566 | } |
1420 | 1567 | ||
@@ -1434,6 +1581,14 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen | |||
1434 | return err; | 1581 | return err; |
1435 | } | 1582 | } |
1436 | 1583 | ||
1584 | static bool unix_passcred_enabled(const struct socket *sock, | ||
1585 | const struct sock *other) | ||
1586 | { | ||
1587 | return test_bit(SOCK_PASSCRED, &sock->flags) || | ||
1588 | !other->sk_socket || | ||
1589 | test_bit(SOCK_PASSCRED, &other->sk_socket->flags); | ||
1590 | } | ||
1591 | |||
1437 | /* | 1592 | /* |
1438 | * Some apps rely on write() giving SCM_CREDENTIALS | 1593 | * Some apps rely on write() giving SCM_CREDENTIALS |
1439 | * We include credentials if source or destination socket | 1594 | * We include credentials if source or destination socket |
@@ -1444,14 +1599,41 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock, | |||
1444 | { | 1599 | { |
1445 | if (UNIXCB(skb).pid) | 1600 | if (UNIXCB(skb).pid) |
1446 | return; | 1601 | return; |
1447 | if (test_bit(SOCK_PASSCRED, &sock->flags) || | 1602 | if (unix_passcred_enabled(sock, other)) { |
1448 | !other->sk_socket || | ||
1449 | test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) { | ||
1450 | UNIXCB(skb).pid = get_pid(task_tgid(current)); | 1603 | UNIXCB(skb).pid = get_pid(task_tgid(current)); |
1451 | current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid); | 1604 | current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid); |
1452 | } | 1605 | } |
1453 | } | 1606 | } |
1454 | 1607 | ||
1608 | static int maybe_init_creds(struct scm_cookie *scm, | ||
1609 | struct socket *socket, | ||
1610 | const struct sock *other) | ||
1611 | { | ||
1612 | int err; | ||
1613 | struct msghdr msg = { .msg_controllen = 0 }; | ||
1614 | |||
1615 | err = scm_send(socket, &msg, scm, false); | ||
1616 | if (err) | ||
1617 | return err; | ||
1618 | |||
1619 | if (unix_passcred_enabled(socket, other)) { | ||
1620 | scm->pid = get_pid(task_tgid(current)); | ||
1621 | current_uid_gid(&scm->creds.uid, &scm->creds.gid); | ||
1622 | } | ||
1623 | return err; | ||
1624 | } | ||
1625 | |||
1626 | static bool unix_skb_scm_eq(struct sk_buff *skb, | ||
1627 | struct scm_cookie *scm) | ||
1628 | { | ||
1629 | const struct unix_skb_parms *u = &UNIXCB(skb); | ||
1630 | |||
1631 | return u->pid == scm->pid && | ||
1632 | uid_eq(u->uid, scm->creds.uid) && | ||
1633 | gid_eq(u->gid, scm->creds.gid) && | ||
1634 | unix_secdata_eq(scm, skb); | ||
1635 | } | ||
1636 | |||
1455 | /* | 1637 | /* |
1456 | * Send AF_UNIX data. | 1638 | * Send AF_UNIX data. |
1457 | */ | 1639 | */ |
@@ -1472,6 +1654,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1472 | struct scm_cookie scm; | 1654 | struct scm_cookie scm; |
1473 | int max_level; | 1655 | int max_level; |
1474 | int data_len = 0; | 1656 | int data_len = 0; |
1657 | int sk_locked; | ||
1475 | 1658 | ||
1476 | wait_for_unix_gc(); | 1659 | wait_for_unix_gc(); |
1477 | err = scm_send(sock, msg, &scm, false); | 1660 | err = scm_send(sock, msg, &scm, false); |
@@ -1550,12 +1733,14 @@ restart: | |||
1550 | goto out_free; | 1733 | goto out_free; |
1551 | } | 1734 | } |
1552 | 1735 | ||
1736 | sk_locked = 0; | ||
1553 | unix_state_lock(other); | 1737 | unix_state_lock(other); |
1738 | restart_locked: | ||
1554 | err = -EPERM; | 1739 | err = -EPERM; |
1555 | if (!unix_may_send(sk, other)) | 1740 | if (!unix_may_send(sk, other)) |
1556 | goto out_unlock; | 1741 | goto out_unlock; |
1557 | 1742 | ||
1558 | if (sock_flag(other, SOCK_DEAD)) { | 1743 | if (unlikely(sock_flag(other, SOCK_DEAD))) { |
1559 | /* | 1744 | /* |
1560 | * Check with 1003.1g - what should | 1745 | * Check with 1003.1g - what should |
1561 | * datagram error | 1746 | * datagram error |
@@ -1563,10 +1748,14 @@ restart: | |||
1563 | unix_state_unlock(other); | 1748 | unix_state_unlock(other); |
1564 | sock_put(other); | 1749 | sock_put(other); |
1565 | 1750 | ||
1751 | if (!sk_locked) | ||
1752 | unix_state_lock(sk); | ||
1753 | |||
1566 | err = 0; | 1754 | err = 0; |
1567 | unix_state_lock(sk); | ||
1568 | if (unix_peer(sk) == other) { | 1755 | if (unix_peer(sk) == other) { |
1569 | unix_peer(sk) = NULL; | 1756 | unix_peer(sk) = NULL; |
1757 | unix_dgram_peer_wake_disconnect_wakeup(sk, other); | ||
1758 | |||
1570 | unix_state_unlock(sk); | 1759 | unix_state_unlock(sk); |
1571 | 1760 | ||
1572 | unix_dgram_disconnected(sk, other); | 1761 | unix_dgram_disconnected(sk, other); |
@@ -1592,21 +1781,38 @@ restart: | |||
1592 | goto out_unlock; | 1781 | goto out_unlock; |
1593 | } | 1782 | } |
1594 | 1783 | ||
1595 | if (unix_peer(other) != sk && unix_recvq_full(other)) { | 1784 | if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) { |
1596 | if (!timeo) { | 1785 | if (timeo) { |
1597 | err = -EAGAIN; | 1786 | timeo = unix_wait_for_peer(other, timeo); |
1598 | goto out_unlock; | 1787 | |
1788 | err = sock_intr_errno(timeo); | ||
1789 | if (signal_pending(current)) | ||
1790 | goto out_free; | ||
1791 | |||
1792 | goto restart; | ||
1599 | } | 1793 | } |
1600 | 1794 | ||
1601 | timeo = unix_wait_for_peer(other, timeo); | 1795 | if (!sk_locked) { |
1796 | unix_state_unlock(other); | ||
1797 | unix_state_double_lock(sk, other); | ||
1798 | } | ||
1602 | 1799 | ||
1603 | err = sock_intr_errno(timeo); | 1800 | if (unix_peer(sk) != other || |
1604 | if (signal_pending(current)) | 1801 | unix_dgram_peer_wake_me(sk, other)) { |
1605 | goto out_free; | 1802 | err = -EAGAIN; |
1803 | sk_locked = 1; | ||
1804 | goto out_unlock; | ||
1805 | } | ||
1606 | 1806 | ||
1607 | goto restart; | 1807 | if (!sk_locked) { |
1808 | sk_locked = 1; | ||
1809 | goto restart_locked; | ||
1810 | } | ||
1608 | } | 1811 | } |
1609 | 1812 | ||
1813 | if (unlikely(sk_locked)) | ||
1814 | unix_state_unlock(sk); | ||
1815 | |||
1610 | if (sock_flag(other, SOCK_RCVTSTAMP)) | 1816 | if (sock_flag(other, SOCK_RCVTSTAMP)) |
1611 | __net_timestamp(skb); | 1817 | __net_timestamp(skb); |
1612 | maybe_add_creds(skb, sock, other); | 1818 | maybe_add_creds(skb, sock, other); |
@@ -1620,6 +1826,8 @@ restart: | |||
1620 | return len; | 1826 | return len; |
1621 | 1827 | ||
1622 | out_unlock: | 1828 | out_unlock: |
1829 | if (sk_locked) | ||
1830 | unix_state_unlock(sk); | ||
1623 | unix_state_unlock(other); | 1831 | unix_state_unlock(other); |
1624 | out_free: | 1832 | out_free: |
1625 | kfree_skb(skb); | 1833 | kfree_skb(skb); |
@@ -1741,8 +1949,10 @@ out_err: | |||
1741 | static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page, | 1949 | static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page, |
1742 | int offset, size_t size, int flags) | 1950 | int offset, size_t size, int flags) |
1743 | { | 1951 | { |
1744 | int err = 0; | 1952 | int err; |
1745 | bool send_sigpipe = true; | 1953 | bool send_sigpipe = false; |
1954 | bool init_scm = true; | ||
1955 | struct scm_cookie scm; | ||
1746 | struct sock *other, *sk = socket->sk; | 1956 | struct sock *other, *sk = socket->sk; |
1747 | struct sk_buff *skb, *newskb = NULL, *tail = NULL; | 1957 | struct sk_buff *skb, *newskb = NULL, *tail = NULL; |
1748 | 1958 | ||
@@ -1760,7 +1970,7 @@ alloc_skb: | |||
1760 | newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT, | 1970 | newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT, |
1761 | &err, 0); | 1971 | &err, 0); |
1762 | if (!newskb) | 1972 | if (!newskb) |
1763 | return err; | 1973 | goto err; |
1764 | } | 1974 | } |
1765 | 1975 | ||
1766 | /* we must acquire readlock as we modify already present | 1976 | /* we must acquire readlock as we modify already present |
@@ -1769,12 +1979,12 @@ alloc_skb: | |||
1769 | err = mutex_lock_interruptible(&unix_sk(other)->readlock); | 1979 | err = mutex_lock_interruptible(&unix_sk(other)->readlock); |
1770 | if (err) { | 1980 | if (err) { |
1771 | err = flags & MSG_DONTWAIT ? -EAGAIN : -ERESTARTSYS; | 1981 | err = flags & MSG_DONTWAIT ? -EAGAIN : -ERESTARTSYS; |
1772 | send_sigpipe = false; | ||
1773 | goto err; | 1982 | goto err; |
1774 | } | 1983 | } |
1775 | 1984 | ||
1776 | if (sk->sk_shutdown & SEND_SHUTDOWN) { | 1985 | if (sk->sk_shutdown & SEND_SHUTDOWN) { |
1777 | err = -EPIPE; | 1986 | err = -EPIPE; |
1987 | send_sigpipe = true; | ||
1778 | goto err_unlock; | 1988 | goto err_unlock; |
1779 | } | 1989 | } |
1780 | 1990 | ||
@@ -1783,17 +1993,27 @@ alloc_skb: | |||
1783 | if (sock_flag(other, SOCK_DEAD) || | 1993 | if (sock_flag(other, SOCK_DEAD) || |
1784 | other->sk_shutdown & RCV_SHUTDOWN) { | 1994 | other->sk_shutdown & RCV_SHUTDOWN) { |
1785 | err = -EPIPE; | 1995 | err = -EPIPE; |
1996 | send_sigpipe = true; | ||
1786 | goto err_state_unlock; | 1997 | goto err_state_unlock; |
1787 | } | 1998 | } |
1788 | 1999 | ||
2000 | if (init_scm) { | ||
2001 | err = maybe_init_creds(&scm, socket, other); | ||
2002 | if (err) | ||
2003 | goto err_state_unlock; | ||
2004 | init_scm = false; | ||
2005 | } | ||
2006 | |||
1789 | skb = skb_peek_tail(&other->sk_receive_queue); | 2007 | skb = skb_peek_tail(&other->sk_receive_queue); |
1790 | if (tail && tail == skb) { | 2008 | if (tail && tail == skb) { |
1791 | skb = newskb; | 2009 | skb = newskb; |
1792 | } else if (!skb) { | 2010 | } else if (!skb || !unix_skb_scm_eq(skb, &scm)) { |
1793 | if (newskb) | 2011 | if (newskb) { |
1794 | skb = newskb; | 2012 | skb = newskb; |
1795 | else | 2013 | } else { |
2014 | tail = skb; | ||
1796 | goto alloc_skb; | 2015 | goto alloc_skb; |
2016 | } | ||
1797 | } else if (newskb) { | 2017 | } else if (newskb) { |
1798 | /* this is fast path, we don't necessarily need to | 2018 | /* this is fast path, we don't necessarily need to |
1799 | * call to kfree_skb even though with newskb == NULL | 2019 | * call to kfree_skb even though with newskb == NULL |
@@ -1814,6 +2034,9 @@ alloc_skb: | |||
1814 | atomic_add(size, &sk->sk_wmem_alloc); | 2034 | atomic_add(size, &sk->sk_wmem_alloc); |
1815 | 2035 | ||
1816 | if (newskb) { | 2036 | if (newskb) { |
2037 | err = unix_scm_to_skb(&scm, skb, false); | ||
2038 | if (err) | ||
2039 | goto err_state_unlock; | ||
1817 | spin_lock(&other->sk_receive_queue.lock); | 2040 | spin_lock(&other->sk_receive_queue.lock); |
1818 | __skb_queue_tail(&other->sk_receive_queue, newskb); | 2041 | __skb_queue_tail(&other->sk_receive_queue, newskb); |
1819 | spin_unlock(&other->sk_receive_queue.lock); | 2042 | spin_unlock(&other->sk_receive_queue.lock); |
@@ -1823,7 +2046,7 @@ alloc_skb: | |||
1823 | mutex_unlock(&unix_sk(other)->readlock); | 2046 | mutex_unlock(&unix_sk(other)->readlock); |
1824 | 2047 | ||
1825 | other->sk_data_ready(other); | 2048 | other->sk_data_ready(other); |
1826 | 2049 | scm_destroy(&scm); | |
1827 | return size; | 2050 | return size; |
1828 | 2051 | ||
1829 | err_state_unlock: | 2052 | err_state_unlock: |
@@ -1834,6 +2057,8 @@ err: | |||
1834 | kfree_skb(newskb); | 2057 | kfree_skb(newskb); |
1835 | if (send_sigpipe && !(flags & MSG_NOSIGNAL)) | 2058 | if (send_sigpipe && !(flags & MSG_NOSIGNAL)) |
1836 | send_sig(SIGPIPE, current, 0); | 2059 | send_sig(SIGPIPE, current, 0); |
2060 | if (!init_scm) | ||
2061 | scm_destroy(&scm); | ||
1837 | return err; | 2062 | return err; |
1838 | } | 2063 | } |
1839 | 2064 | ||
@@ -1883,8 +2108,8 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
1883 | struct scm_cookie scm; | 2108 | struct scm_cookie scm; |
1884 | struct sock *sk = sock->sk; | 2109 | struct sock *sk = sock->sk; |
1885 | struct unix_sock *u = unix_sk(sk); | 2110 | struct unix_sock *u = unix_sk(sk); |
1886 | int noblock = flags & MSG_DONTWAIT; | 2111 | struct sk_buff *skb, *last; |
1887 | struct sk_buff *skb; | 2112 | long timeo; |
1888 | int err; | 2113 | int err; |
1889 | int peeked, skip; | 2114 | int peeked, skip; |
1890 | 2115 | ||
@@ -1892,30 +2117,38 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
1892 | if (flags&MSG_OOB) | 2117 | if (flags&MSG_OOB) |
1893 | goto out; | 2118 | goto out; |
1894 | 2119 | ||
1895 | err = mutex_lock_interruptible(&u->readlock); | 2120 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
1896 | if (unlikely(err)) { | ||
1897 | /* recvmsg() in non blocking mode is supposed to return -EAGAIN | ||
1898 | * sk_rcvtimeo is not honored by mutex_lock_interruptible() | ||
1899 | */ | ||
1900 | err = noblock ? -EAGAIN : -ERESTARTSYS; | ||
1901 | goto out; | ||
1902 | } | ||
1903 | 2121 | ||
1904 | skip = sk_peek_offset(sk, flags); | 2122 | do { |
2123 | mutex_lock(&u->readlock); | ||
1905 | 2124 | ||
1906 | skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err); | 2125 | skip = sk_peek_offset(sk, flags); |
1907 | if (!skb) { | 2126 | skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err, |
2127 | &last); | ||
2128 | if (skb) | ||
2129 | break; | ||
2130 | |||
2131 | mutex_unlock(&u->readlock); | ||
2132 | |||
2133 | if (err != -EAGAIN) | ||
2134 | break; | ||
2135 | } while (timeo && | ||
2136 | !__skb_wait_for_more_packets(sk, &err, &timeo, last)); | ||
2137 | |||
2138 | if (!skb) { /* implies readlock unlocked */ | ||
1908 | unix_state_lock(sk); | 2139 | unix_state_lock(sk); |
1909 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ | 2140 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ |
1910 | if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && | 2141 | if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && |
1911 | (sk->sk_shutdown & RCV_SHUTDOWN)) | 2142 | (sk->sk_shutdown & RCV_SHUTDOWN)) |
1912 | err = 0; | 2143 | err = 0; |
1913 | unix_state_unlock(sk); | 2144 | unix_state_unlock(sk); |
1914 | goto out_unlock; | 2145 | goto out; |
1915 | } | 2146 | } |
1916 | 2147 | ||
1917 | wake_up_interruptible_sync_poll(&u->peer_wait, | 2148 | if (wq_has_sleeper(&u->peer_wait)) |
1918 | POLLOUT | POLLWRNORM | POLLWRBAND); | 2149 | wake_up_interruptible_sync_poll(&u->peer_wait, |
2150 | POLLOUT | POLLWRNORM | | ||
2151 | POLLWRBAND); | ||
1919 | 2152 | ||
1920 | if (msg->msg_name) | 2153 | if (msg->msg_name) |
1921 | unix_copy_addr(msg, skb->sk); | 2154 | unix_copy_addr(msg, skb->sk); |
@@ -1967,7 +2200,6 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | |||
1967 | 2200 | ||
1968 | out_free: | 2201 | out_free: |
1969 | skb_free_datagram(sk, skb); | 2202 | skb_free_datagram(sk, skb); |
1970 | out_unlock: | ||
1971 | mutex_unlock(&u->readlock); | 2203 | mutex_unlock(&u->readlock); |
1972 | out: | 2204 | out: |
1973 | return err; | 2205 | return err; |
@@ -1996,7 +2228,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, | |||
1996 | !timeo) | 2228 | !timeo) |
1997 | break; | 2229 | break; |
1998 | 2230 | ||
1999 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2231 | sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
2000 | unix_state_unlock(sk); | 2232 | unix_state_unlock(sk); |
2001 | timeo = freezable_schedule_timeout(timeo); | 2233 | timeo = freezable_schedule_timeout(timeo); |
2002 | unix_state_lock(sk); | 2234 | unix_state_lock(sk); |
@@ -2004,7 +2236,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, | |||
2004 | if (sock_flag(sk, SOCK_DEAD)) | 2236 | if (sock_flag(sk, SOCK_DEAD)) |
2005 | break; | 2237 | break; |
2006 | 2238 | ||
2007 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2239 | sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
2008 | } | 2240 | } |
2009 | 2241 | ||
2010 | finish_wait(sk_sleep(sk), &wait); | 2242 | finish_wait(sk_sleep(sk), &wait); |
@@ -2061,14 +2293,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state) | |||
2061 | /* Lock the socket to prevent queue disordering | 2293 | /* Lock the socket to prevent queue disordering |
2062 | * while sleeps in memcpy_tomsg | 2294 | * while sleeps in memcpy_tomsg |
2063 | */ | 2295 | */ |
2064 | err = mutex_lock_interruptible(&u->readlock); | 2296 | mutex_lock(&u->readlock); |
2065 | if (unlikely(err)) { | ||
2066 | /* recvmsg() in non blocking mode is supposed to return -EAGAIN | ||
2067 | * sk_rcvtimeo is not honored by mutex_lock_interruptible() | ||
2068 | */ | ||
2069 | err = noblock ? -EAGAIN : -ERESTARTSYS; | ||
2070 | goto out; | ||
2071 | } | ||
2072 | 2297 | ||
2073 | if (flags & MSG_PEEK) | 2298 | if (flags & MSG_PEEK) |
2074 | skip = sk_peek_offset(sk, flags); | 2299 | skip = sk_peek_offset(sk, flags); |
@@ -2112,12 +2337,12 @@ again: | |||
2112 | timeo = unix_stream_data_wait(sk, timeo, last, | 2337 | timeo = unix_stream_data_wait(sk, timeo, last, |
2113 | last_len); | 2338 | last_len); |
2114 | 2339 | ||
2115 | if (signal_pending(current) || | 2340 | if (signal_pending(current)) { |
2116 | mutex_lock_interruptible(&u->readlock)) { | ||
2117 | err = sock_intr_errno(timeo); | 2341 | err = sock_intr_errno(timeo); |
2118 | goto out; | 2342 | goto out; |
2119 | } | 2343 | } |
2120 | 2344 | ||
2345 | mutex_lock(&u->readlock); | ||
2121 | continue; | 2346 | continue; |
2122 | unlock: | 2347 | unlock: |
2123 | unix_state_unlock(sk); | 2348 | unix_state_unlock(sk); |
@@ -2137,10 +2362,7 @@ unlock: | |||
2137 | 2362 | ||
2138 | if (check_creds) { | 2363 | if (check_creds) { |
2139 | /* Never glue messages from different writers */ | 2364 | /* Never glue messages from different writers */ |
2140 | if ((UNIXCB(skb).pid != scm.pid) || | 2365 | if (!unix_skb_scm_eq(skb, &scm)) |
2141 | !uid_eq(UNIXCB(skb).uid, scm.creds.uid) || | ||
2142 | !gid_eq(UNIXCB(skb).gid, scm.creds.gid) || | ||
2143 | !unix_secdata_eq(&scm, skb)) | ||
2144 | break; | 2366 | break; |
2145 | } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { | 2367 | } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { |
2146 | /* Copy credentials */ | 2368 | /* Copy credentials */ |
@@ -2476,20 +2698,22 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2476 | return mask; | 2698 | return mask; |
2477 | 2699 | ||
2478 | writable = unix_writable(sk); | 2700 | writable = unix_writable(sk); |
2479 | other = unix_peer_get(sk); | 2701 | if (writable) { |
2480 | if (other) { | 2702 | unix_state_lock(sk); |
2481 | if (unix_peer(other) != sk) { | 2703 | |
2482 | sock_poll_wait(file, &unix_sk(other)->peer_wait, wait); | 2704 | other = unix_peer(sk); |
2483 | if (unix_recvq_full(other)) | 2705 | if (other && unix_peer(other) != sk && |
2484 | writable = 0; | 2706 | unix_recvq_full(other) && |
2485 | } | 2707 | unix_dgram_peer_wake_me(sk, other)) |
2486 | sock_put(other); | 2708 | writable = 0; |
2709 | |||
2710 | unix_state_unlock(sk); | ||
2487 | } | 2711 | } |
2488 | 2712 | ||
2489 | if (writable) | 2713 | if (writable) |
2490 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | 2714 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; |
2491 | else | 2715 | else |
2492 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 2716 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
2493 | 2717 | ||
2494 | return mask; | 2718 | return mask; |
2495 | } | 2719 | } |
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index a73a226f2d33..8fcdc2283af5 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c | |||
@@ -120,11 +120,11 @@ void unix_inflight(struct file *fp) | |||
120 | { | 120 | { |
121 | struct sock *s = unix_get_socket(fp); | 121 | struct sock *s = unix_get_socket(fp); |
122 | 122 | ||
123 | spin_lock(&unix_gc_lock); | ||
124 | |||
123 | if (s) { | 125 | if (s) { |
124 | struct unix_sock *u = unix_sk(s); | 126 | struct unix_sock *u = unix_sk(s); |
125 | 127 | ||
126 | spin_lock(&unix_gc_lock); | ||
127 | |||
128 | if (atomic_long_inc_return(&u->inflight) == 1) { | 128 | if (atomic_long_inc_return(&u->inflight) == 1) { |
129 | BUG_ON(!list_empty(&u->link)); | 129 | BUG_ON(!list_empty(&u->link)); |
130 | list_add_tail(&u->link, &gc_inflight_list); | 130 | list_add_tail(&u->link, &gc_inflight_list); |
@@ -132,25 +132,28 @@ void unix_inflight(struct file *fp) | |||
132 | BUG_ON(list_empty(&u->link)); | 132 | BUG_ON(list_empty(&u->link)); |
133 | } | 133 | } |
134 | unix_tot_inflight++; | 134 | unix_tot_inflight++; |
135 | spin_unlock(&unix_gc_lock); | ||
136 | } | 135 | } |
136 | fp->f_cred->user->unix_inflight++; | ||
137 | spin_unlock(&unix_gc_lock); | ||
137 | } | 138 | } |
138 | 139 | ||
139 | void unix_notinflight(struct file *fp) | 140 | void unix_notinflight(struct file *fp) |
140 | { | 141 | { |
141 | struct sock *s = unix_get_socket(fp); | 142 | struct sock *s = unix_get_socket(fp); |
142 | 143 | ||
144 | spin_lock(&unix_gc_lock); | ||
145 | |||
143 | if (s) { | 146 | if (s) { |
144 | struct unix_sock *u = unix_sk(s); | 147 | struct unix_sock *u = unix_sk(s); |
145 | 148 | ||
146 | spin_lock(&unix_gc_lock); | ||
147 | BUG_ON(list_empty(&u->link)); | 149 | BUG_ON(list_empty(&u->link)); |
148 | 150 | ||
149 | if (atomic_long_dec_and_test(&u->inflight)) | 151 | if (atomic_long_dec_and_test(&u->inflight)) |
150 | list_del_init(&u->link); | 152 | list_del_init(&u->link); |
151 | unix_tot_inflight--; | 153 | unix_tot_inflight--; |
152 | spin_unlock(&unix_gc_lock); | ||
153 | } | 154 | } |
155 | fp->f_cred->user->unix_inflight--; | ||
156 | spin_unlock(&unix_gc_lock); | ||
154 | } | 157 | } |
155 | 158 | ||
156 | static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), | 159 | static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), |
diff --git a/net/vmw_vsock/vmci_transport.h b/net/vmw_vsock/vmci_transport.h index 2ad46f39649f..1820e74a5752 100644 --- a/net/vmw_vsock/vmci_transport.h +++ b/net/vmw_vsock/vmci_transport.h | |||
@@ -121,7 +121,7 @@ struct vmci_transport { | |||
121 | u64 queue_pair_max_size; | 121 | u64 queue_pair_max_size; |
122 | u32 detach_sub_id; | 122 | u32 detach_sub_id; |
123 | union vmci_transport_notify notify; | 123 | union vmci_transport_notify notify; |
124 | struct vmci_transport_notify_ops *notify_ops; | 124 | const struct vmci_transport_notify_ops *notify_ops; |
125 | struct list_head elem; | 125 | struct list_head elem; |
126 | struct sock *sk; | 126 | struct sock *sk; |
127 | spinlock_t lock; /* protects sk. */ | 127 | spinlock_t lock; /* protects sk. */ |
diff --git a/net/vmw_vsock/vmci_transport_notify.c b/net/vmw_vsock/vmci_transport_notify.c index 9b7f207f2bee..fd8cf0214d51 100644 --- a/net/vmw_vsock/vmci_transport_notify.c +++ b/net/vmw_vsock/vmci_transport_notify.c | |||
@@ -661,7 +661,7 @@ static void vmci_transport_notify_pkt_process_negotiate(struct sock *sk) | |||
661 | } | 661 | } |
662 | 662 | ||
663 | /* Socket control packet based operations. */ | 663 | /* Socket control packet based operations. */ |
664 | struct vmci_transport_notify_ops vmci_transport_notify_pkt_ops = { | 664 | const struct vmci_transport_notify_ops vmci_transport_notify_pkt_ops = { |
665 | vmci_transport_notify_pkt_socket_init, | 665 | vmci_transport_notify_pkt_socket_init, |
666 | vmci_transport_notify_pkt_socket_destruct, | 666 | vmci_transport_notify_pkt_socket_destruct, |
667 | vmci_transport_notify_pkt_poll_in, | 667 | vmci_transport_notify_pkt_poll_in, |
diff --git a/net/vmw_vsock/vmci_transport_notify.h b/net/vmw_vsock/vmci_transport_notify.h index 7df793249b6c..3c464d394a8f 100644 --- a/net/vmw_vsock/vmci_transport_notify.h +++ b/net/vmw_vsock/vmci_transport_notify.h | |||
@@ -77,7 +77,8 @@ struct vmci_transport_notify_ops { | |||
77 | void (*process_negotiate) (struct sock *sk); | 77 | void (*process_negotiate) (struct sock *sk); |
78 | }; | 78 | }; |
79 | 79 | ||
80 | extern struct vmci_transport_notify_ops vmci_transport_notify_pkt_ops; | 80 | extern const struct vmci_transport_notify_ops vmci_transport_notify_pkt_ops; |
81 | extern struct vmci_transport_notify_ops vmci_transport_notify_pkt_q_state_ops; | 81 | extern const |
82 | struct vmci_transport_notify_ops vmci_transport_notify_pkt_q_state_ops; | ||
82 | 83 | ||
83 | #endif /* __VMCI_TRANSPORT_NOTIFY_H__ */ | 84 | #endif /* __VMCI_TRANSPORT_NOTIFY_H__ */ |
diff --git a/net/vmw_vsock/vmci_transport_notify_qstate.c b/net/vmw_vsock/vmci_transport_notify_qstate.c index dc9c7929a2f9..21e591dafb03 100644 --- a/net/vmw_vsock/vmci_transport_notify_qstate.c +++ b/net/vmw_vsock/vmci_transport_notify_qstate.c | |||
@@ -419,7 +419,7 @@ vmci_transport_notify_pkt_send_pre_enqueue( | |||
419 | } | 419 | } |
420 | 420 | ||
421 | /* Socket always on control packet based operations. */ | 421 | /* Socket always on control packet based operations. */ |
422 | struct vmci_transport_notify_ops vmci_transport_notify_pkt_q_state_ops = { | 422 | const struct vmci_transport_notify_ops vmci_transport_notify_pkt_q_state_ops = { |
423 | vmci_transport_notify_pkt_socket_init, | 423 | vmci_transport_notify_pkt_socket_init, |
424 | vmci_transport_notify_pkt_socket_destruct, | 424 | vmci_transport_notify_pkt_socket_destruct, |
425 | vmci_transport_notify_pkt_poll_in, | 425 | vmci_transport_notify_pkt_poll_in, |
diff --git a/net/wireless/core.h b/net/wireless/core.h index a618b4b86fa4..022ccad06cbe 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -416,13 +416,6 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
416 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); | 416 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); |
417 | void cfg80211_process_wdev_events(struct wireless_dev *wdev); | 417 | void cfg80211_process_wdev_events(struct wireless_dev *wdev); |
418 | 418 | ||
419 | int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | ||
420 | struct wireless_dev *wdev, | ||
421 | enum nl80211_iftype iftype, | ||
422 | struct ieee80211_channel *chan, | ||
423 | enum cfg80211_chan_mode chanmode, | ||
424 | u8 radar_detect); | ||
425 | |||
426 | /** | 419 | /** |
427 | * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable | 420 | * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable |
428 | * @wiphy: the wiphy to validate against | 421 | * @wiphy: the wiphy to validate against |
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c index dc0e59e53dbf..6beab0cfcb99 100644 --- a/net/wireless/lib80211_crypt_ccmp.c +++ b/net/wireless/lib80211_crypt_ccmp.c | |||
@@ -311,8 +311,8 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
311 | } | 311 | } |
312 | keyidx >>= 6; | 312 | keyidx >>= 6; |
313 | if (key->key_idx != keyidx) { | 313 | if (key->key_idx != keyidx) { |
314 | printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame " | 314 | net_dbg_ratelimited("CCMP: RX tkey->key_idx=%d frame keyidx=%d\n", |
315 | "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv); | 315 | key->key_idx, keyidx); |
316 | return -6; | 316 | return -6; |
317 | } | 317 | } |
318 | if (!key->key_set) { | 318 | if (!key->key_set) { |
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index 8c90ba79e56e..3cd819539241 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c | |||
@@ -434,8 +434,8 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
434 | } | 434 | } |
435 | keyidx >>= 6; | 435 | keyidx >>= 6; |
436 | if (tkey->key_idx != keyidx) { | 436 | if (tkey->key_idx != keyidx) { |
437 | printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame " | 437 | net_dbg_ratelimited("TKIP: RX tkey->key_idx=%d frame keyidx=%d\n", |
438 | "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv); | 438 | tkey->key_idx, keyidx); |
439 | return -6; | 439 | return -6; |
440 | } | 440 | } |
441 | if (!tkey->key_set) { | 441 | if (!tkey->key_set) { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c71e274c810a..d4786f2802aa 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -4256,8 +4256,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
4256 | * station. Include these parameters here and will check them in | 4256 | * station. Include these parameters here and will check them in |
4257 | * cfg80211_check_station_change(). | 4257 | * cfg80211_check_station_change(). |
4258 | */ | 4258 | */ |
4259 | if (info->attrs[NL80211_ATTR_PEER_AID]) | 4259 | if (info->attrs[NL80211_ATTR_STA_AID]) |
4260 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); | 4260 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); |
4261 | 4261 | ||
4262 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | 4262 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) |
4263 | params.listen_interval = | 4263 | params.listen_interval = |
@@ -4359,6 +4359,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
4359 | struct net_device *dev = info->user_ptr[1]; | 4359 | struct net_device *dev = info->user_ptr[1]; |
4360 | struct station_parameters params; | 4360 | struct station_parameters params; |
4361 | u8 *mac_addr = NULL; | 4361 | u8 *mac_addr = NULL; |
4362 | u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
4363 | BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
4362 | 4364 | ||
4363 | memset(¶ms, 0, sizeof(params)); | 4365 | memset(¶ms, 0, sizeof(params)); |
4364 | 4366 | ||
@@ -4470,10 +4472,23 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
4470 | /* allow authenticated/associated only if driver handles it */ | 4472 | /* allow authenticated/associated only if driver handles it */ |
4471 | if (!(rdev->wiphy.features & | 4473 | if (!(rdev->wiphy.features & |
4472 | NL80211_FEATURE_FULL_AP_CLIENT_STATE) && | 4474 | NL80211_FEATURE_FULL_AP_CLIENT_STATE) && |
4473 | params.sta_flags_mask & | 4475 | params.sta_flags_mask & auth_assoc) |
4474 | (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | 4476 | return -EINVAL; |
4475 | BIT(NL80211_STA_FLAG_ASSOCIATED))) | 4477 | |
4476 | return -EINVAL; | 4478 | /* Older userspace, or userspace wanting to be compatible with |
4479 | * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth | ||
4480 | * and assoc flags in the mask, but assumes the station will be | ||
4481 | * added as associated anyway since this was the required driver | ||
4482 | * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was | ||
4483 | * introduced. | ||
4484 | * In order to not bother drivers with this quirk in the API | ||
4485 | * set the flags in both the mask and set for new stations in | ||
4486 | * this case. | ||
4487 | */ | ||
4488 | if (!(params.sta_flags_mask & auth_assoc)) { | ||
4489 | params.sta_flags_mask |= auth_assoc; | ||
4490 | params.sta_flags_set |= auth_assoc; | ||
4491 | } | ||
4477 | 4492 | ||
4478 | /* must be last in here for error handling */ | 4493 | /* must be last in here for error handling */ |
4479 | params.vlan = get_vlan(info, rdev); | 4494 | params.vlan = get_vlan(info, rdev); |
@@ -5997,6 +6012,24 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5997 | return err; | 6012 | return err; |
5998 | } | 6013 | } |
5999 | 6014 | ||
6015 | static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info) | ||
6016 | { | ||
6017 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
6018 | struct wireless_dev *wdev = info->user_ptr[1]; | ||
6019 | |||
6020 | if (!rdev->ops->abort_scan) | ||
6021 | return -EOPNOTSUPP; | ||
6022 | |||
6023 | if (rdev->scan_msg) | ||
6024 | return 0; | ||
6025 | |||
6026 | if (!rdev->scan_req) | ||
6027 | return -ENOENT; | ||
6028 | |||
6029 | rdev_abort_scan(rdev, wdev); | ||
6030 | return 0; | ||
6031 | } | ||
6032 | |||
6000 | static int | 6033 | static int |
6001 | nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans, | 6034 | nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans, |
6002 | struct cfg80211_sched_scan_request *request, | 6035 | struct cfg80211_sched_scan_request *request, |
@@ -6507,8 +6540,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
6507 | if (WARN_ON(!cac_time_ms)) | 6540 | if (WARN_ON(!cac_time_ms)) |
6508 | cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; | 6541 | cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; |
6509 | 6542 | ||
6510 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef, | 6543 | err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms); |
6511 | cac_time_ms); | ||
6512 | if (!err) { | 6544 | if (!err) { |
6513 | wdev->chandef = chandef; | 6545 | wdev->chandef = chandef; |
6514 | wdev->cac_started = true; | 6546 | wdev->cac_started = true; |
@@ -7571,7 +7603,7 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info) | |||
7571 | if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate)) | 7603 | if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate)) |
7572 | return -EINVAL; | 7604 | return -EINVAL; |
7573 | 7605 | ||
7574 | err = rdev->ops->set_mcast_rate(&rdev->wiphy, dev, mcast_rate); | 7606 | err = rdev_set_mcast_rate(rdev, dev, mcast_rate); |
7575 | 7607 | ||
7576 | return err; | 7608 | return err; |
7577 | } | 7609 | } |
@@ -7941,8 +7973,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
7941 | if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) { | 7973 | if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) { |
7942 | if (!(rdev->wiphy.features & | 7974 | if (!(rdev->wiphy.features & |
7943 | NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) || | 7975 | NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) || |
7944 | !(rdev->wiphy.features & NL80211_FEATURE_QUIET)) | 7976 | !(rdev->wiphy.features & NL80211_FEATURE_QUIET)) { |
7977 | kzfree(connkeys); | ||
7945 | return -EINVAL; | 7978 | return -EINVAL; |
7979 | } | ||
7946 | connect.flags |= ASSOC_REQ_USE_RRM; | 7980 | connect.flags |= ASSOC_REQ_USE_RRM; |
7947 | } | 7981 | } |
7948 | 7982 | ||
@@ -9503,6 +9537,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
9503 | if (new_triggers.tcp && new_triggers.tcp->sock) | 9537 | if (new_triggers.tcp && new_triggers.tcp->sock) |
9504 | sock_release(new_triggers.tcp->sock); | 9538 | sock_release(new_triggers.tcp->sock); |
9505 | kfree(new_triggers.tcp); | 9539 | kfree(new_triggers.tcp); |
9540 | kfree(new_triggers.nd_config); | ||
9506 | return err; | 9541 | return err; |
9507 | } | 9542 | } |
9508 | #endif | 9543 | #endif |
@@ -9716,7 +9751,7 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info) | |||
9716 | 9751 | ||
9717 | if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) { | 9752 | if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) { |
9718 | cfg80211_rdev_free_coalesce(rdev); | 9753 | cfg80211_rdev_free_coalesce(rdev); |
9719 | rdev->ops->set_coalesce(&rdev->wiphy, NULL); | 9754 | rdev_set_coalesce(rdev, NULL); |
9720 | return 0; | 9755 | return 0; |
9721 | } | 9756 | } |
9722 | 9757 | ||
@@ -9744,7 +9779,7 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info) | |||
9744 | i++; | 9779 | i++; |
9745 | } | 9780 | } |
9746 | 9781 | ||
9747 | err = rdev->ops->set_coalesce(&rdev->wiphy, &new_coalesce); | 9782 | err = rdev_set_coalesce(rdev, &new_coalesce); |
9748 | if (err) | 9783 | if (err) |
9749 | goto error; | 9784 | goto error; |
9750 | 9785 | ||
@@ -10946,6 +10981,14 @@ static const struct genl_ops nl80211_ops[] = { | |||
10946 | NL80211_FLAG_NEED_RTNL, | 10981 | NL80211_FLAG_NEED_RTNL, |
10947 | }, | 10982 | }, |
10948 | { | 10983 | { |
10984 | .cmd = NL80211_CMD_ABORT_SCAN, | ||
10985 | .doit = nl80211_abort_scan, | ||
10986 | .policy = nl80211_policy, | ||
10987 | .flags = GENL_ADMIN_PERM, | ||
10988 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | ||
10989 | NL80211_FLAG_NEED_RTNL, | ||
10990 | }, | ||
10991 | { | ||
10949 | .cmd = NL80211_CMD_GET_SCAN, | 10992 | .cmd = NL80211_CMD_GET_SCAN, |
10950 | .policy = nl80211_policy, | 10993 | .policy = nl80211_policy, |
10951 | .dumpit = nl80211_dump_scan, | 10994 | .dumpit = nl80211_dump_scan, |
diff --git a/net/wireless/ocb.c b/net/wireless/ocb.c index c00d4a792319..e64dbf16330c 100644 --- a/net/wireless/ocb.c +++ b/net/wireless/ocb.c | |||
@@ -29,6 +29,9 @@ int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev, | |||
29 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB) | 29 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB) |
30 | return -EOPNOTSUPP; | 30 | return -EOPNOTSUPP; |
31 | 31 | ||
32 | if (!rdev->ops->join_ocb) | ||
33 | return -EOPNOTSUPP; | ||
34 | |||
32 | if (WARN_ON(!setup->chandef.chan)) | 35 | if (WARN_ON(!setup->chandef.chan)) |
33 | return -EINVAL; | 36 | return -EINVAL; |
34 | 37 | ||
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index c23516d0f807..8ae0c04f9fc7 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -427,6 +427,14 @@ static inline int rdev_scan(struct cfg80211_registered_device *rdev, | |||
427 | return ret; | 427 | return ret; |
428 | } | 428 | } |
429 | 429 | ||
430 | static inline void rdev_abort_scan(struct cfg80211_registered_device *rdev, | ||
431 | struct wireless_dev *wdev) | ||
432 | { | ||
433 | trace_rdev_abort_scan(&rdev->wiphy, wdev); | ||
434 | rdev->ops->abort_scan(&rdev->wiphy, wdev); | ||
435 | trace_rdev_return_void(&rdev->wiphy); | ||
436 | } | ||
437 | |||
430 | static inline int rdev_auth(struct cfg80211_registered_device *rdev, | 438 | static inline int rdev_auth(struct cfg80211_registered_device *rdev, |
431 | struct net_device *dev, | 439 | struct net_device *dev, |
432 | struct cfg80211_auth_request *req) | 440 | struct cfg80211_auth_request *req) |
@@ -1020,4 +1028,47 @@ rdev_tdls_cancel_channel_switch(struct cfg80211_registered_device *rdev, | |||
1020 | trace_rdev_return_void(&rdev->wiphy); | 1028 | trace_rdev_return_void(&rdev->wiphy); |
1021 | } | 1029 | } |
1022 | 1030 | ||
1031 | static inline int | ||
1032 | rdev_start_radar_detection(struct cfg80211_registered_device *rdev, | ||
1033 | struct net_device *dev, | ||
1034 | struct cfg80211_chan_def *chandef, | ||
1035 | u32 cac_time_ms) | ||
1036 | { | ||
1037 | int ret = -ENOTSUPP; | ||
1038 | |||
1039 | trace_rdev_start_radar_detection(&rdev->wiphy, dev, chandef, | ||
1040 | cac_time_ms); | ||
1041 | if (rdev->ops->start_radar_detection) | ||
1042 | ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev, | ||
1043 | chandef, cac_time_ms); | ||
1044 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
1045 | return ret; | ||
1046 | } | ||
1047 | |||
1048 | static inline int | ||
1049 | rdev_set_mcast_rate(struct cfg80211_registered_device *rdev, | ||
1050 | struct net_device *dev, | ||
1051 | int mcast_rate[IEEE80211_NUM_BANDS]) | ||
1052 | { | ||
1053 | int ret = -ENOTSUPP; | ||
1054 | |||
1055 | trace_rdev_set_mcast_rate(&rdev->wiphy, dev, mcast_rate); | ||
1056 | if (rdev->ops->set_mcast_rate) | ||
1057 | ret = rdev->ops->set_mcast_rate(&rdev->wiphy, dev, mcast_rate); | ||
1058 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | static inline int | ||
1063 | rdev_set_coalesce(struct cfg80211_registered_device *rdev, | ||
1064 | struct cfg80211_coalesce *coalesce) | ||
1065 | { | ||
1066 | int ret = -ENOTSUPP; | ||
1067 | |||
1068 | trace_rdev_set_coalesce(&rdev->wiphy, coalesce); | ||
1069 | if (rdev->ops->set_coalesce) | ||
1070 | ret = rdev->ops->set_coalesce(&rdev->wiphy, coalesce); | ||
1071 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
1072 | return ret; | ||
1073 | } | ||
1023 | #endif /* __CFG80211_RDEV_OPS */ | 1074 | #endif /* __CFG80211_RDEV_OPS */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2e8d6f39ed56..3b0ce1c484a3 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1052,7 +1052,7 @@ static u32 map_regdom_flags(u32 rd_flags) | |||
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | static const struct ieee80211_reg_rule * | 1054 | static const struct ieee80211_reg_rule * |
1055 | freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq, | 1055 | freq_reg_info_regd(u32 center_freq, |
1056 | const struct ieee80211_regdomain *regd, u32 bw) | 1056 | const struct ieee80211_regdomain *regd, u32 bw) |
1057 | { | 1057 | { |
1058 | int i; | 1058 | int i; |
@@ -1097,7 +1097,7 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw) | |||
1097 | u32 bw; | 1097 | u32 bw; |
1098 | 1098 | ||
1099 | for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) { | 1099 | for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) { |
1100 | reg_rule = freq_reg_info_regd(wiphy, center_freq, regd, bw); | 1100 | reg_rule = freq_reg_info_regd(center_freq, regd, bw); |
1101 | if (!IS_ERR(reg_rule)) | 1101 | if (!IS_ERR(reg_rule)) |
1102 | return reg_rule; | 1102 | return reg_rule; |
1103 | } | 1103 | } |
@@ -1166,6 +1166,41 @@ static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, | |||
1166 | #endif | 1166 | #endif |
1167 | } | 1167 | } |
1168 | 1168 | ||
1169 | static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd, | ||
1170 | const struct ieee80211_reg_rule *reg_rule, | ||
1171 | const struct ieee80211_channel *chan) | ||
1172 | { | ||
1173 | const struct ieee80211_freq_range *freq_range = NULL; | ||
1174 | u32 max_bandwidth_khz, bw_flags = 0; | ||
1175 | |||
1176 | freq_range = ®_rule->freq_range; | ||
1177 | |||
1178 | max_bandwidth_khz = freq_range->max_bandwidth_khz; | ||
1179 | /* Check if auto calculation requested */ | ||
1180 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) | ||
1181 | max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); | ||
1182 | |||
1183 | /* If we get a reg_rule we can assume that at least 5Mhz fit */ | ||
1184 | if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq), | ||
1185 | MHZ_TO_KHZ(10))) | ||
1186 | bw_flags |= IEEE80211_CHAN_NO_10MHZ; | ||
1187 | if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq), | ||
1188 | MHZ_TO_KHZ(20))) | ||
1189 | bw_flags |= IEEE80211_CHAN_NO_20MHZ; | ||
1190 | |||
1191 | if (max_bandwidth_khz < MHZ_TO_KHZ(10)) | ||
1192 | bw_flags |= IEEE80211_CHAN_NO_10MHZ; | ||
1193 | if (max_bandwidth_khz < MHZ_TO_KHZ(20)) | ||
1194 | bw_flags |= IEEE80211_CHAN_NO_20MHZ; | ||
1195 | if (max_bandwidth_khz < MHZ_TO_KHZ(40)) | ||
1196 | bw_flags |= IEEE80211_CHAN_NO_HT40; | ||
1197 | if (max_bandwidth_khz < MHZ_TO_KHZ(80)) | ||
1198 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; | ||
1199 | if (max_bandwidth_khz < MHZ_TO_KHZ(160)) | ||
1200 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; | ||
1201 | return bw_flags; | ||
1202 | } | ||
1203 | |||
1169 | /* | 1204 | /* |
1170 | * Note that right now we assume the desired channel bandwidth | 1205 | * Note that right now we assume the desired channel bandwidth |
1171 | * is always 20 MHz for each individual channel (HT40 uses 20 MHz | 1206 | * is always 20 MHz for each individual channel (HT40 uses 20 MHz |
@@ -1178,11 +1213,9 @@ static void handle_channel(struct wiphy *wiphy, | |||
1178 | u32 flags, bw_flags = 0; | 1213 | u32 flags, bw_flags = 0; |
1179 | const struct ieee80211_reg_rule *reg_rule = NULL; | 1214 | const struct ieee80211_reg_rule *reg_rule = NULL; |
1180 | const struct ieee80211_power_rule *power_rule = NULL; | 1215 | const struct ieee80211_power_rule *power_rule = NULL; |
1181 | const struct ieee80211_freq_range *freq_range = NULL; | ||
1182 | struct wiphy *request_wiphy = NULL; | 1216 | struct wiphy *request_wiphy = NULL; |
1183 | struct regulatory_request *lr = get_last_request(); | 1217 | struct regulatory_request *lr = get_last_request(); |
1184 | const struct ieee80211_regdomain *regd; | 1218 | const struct ieee80211_regdomain *regd; |
1185 | u32 max_bandwidth_khz; | ||
1186 | 1219 | ||
1187 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); | 1220 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); |
1188 | 1221 | ||
@@ -1223,31 +1256,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
1223 | chan_reg_rule_print_dbg(regd, chan, reg_rule); | 1256 | chan_reg_rule_print_dbg(regd, chan, reg_rule); |
1224 | 1257 | ||
1225 | power_rule = ®_rule->power_rule; | 1258 | power_rule = ®_rule->power_rule; |
1226 | freq_range = ®_rule->freq_range; | 1259 | bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan); |
1227 | |||
1228 | max_bandwidth_khz = freq_range->max_bandwidth_khz; | ||
1229 | /* Check if auto calculation requested */ | ||
1230 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) | ||
1231 | max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); | ||
1232 | |||
1233 | /* If we get a reg_rule we can assume that at least 5Mhz fit */ | ||
1234 | if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq), | ||
1235 | MHZ_TO_KHZ(10))) | ||
1236 | bw_flags |= IEEE80211_CHAN_NO_10MHZ; | ||
1237 | if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq), | ||
1238 | MHZ_TO_KHZ(20))) | ||
1239 | bw_flags |= IEEE80211_CHAN_NO_20MHZ; | ||
1240 | |||
1241 | if (max_bandwidth_khz < MHZ_TO_KHZ(10)) | ||
1242 | bw_flags |= IEEE80211_CHAN_NO_10MHZ; | ||
1243 | if (max_bandwidth_khz < MHZ_TO_KHZ(20)) | ||
1244 | bw_flags |= IEEE80211_CHAN_NO_20MHZ; | ||
1245 | if (max_bandwidth_khz < MHZ_TO_KHZ(40)) | ||
1246 | bw_flags |= IEEE80211_CHAN_NO_HT40; | ||
1247 | if (max_bandwidth_khz < MHZ_TO_KHZ(80)) | ||
1248 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; | ||
1249 | if (max_bandwidth_khz < MHZ_TO_KHZ(160)) | ||
1250 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; | ||
1251 | 1260 | ||
1252 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 1261 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
1253 | request_wiphy && request_wiphy == wiphy && | 1262 | request_wiphy && request_wiphy == wiphy && |
@@ -1760,13 +1769,10 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1760 | u32 bw_flags = 0; | 1769 | u32 bw_flags = 0; |
1761 | const struct ieee80211_reg_rule *reg_rule = NULL; | 1770 | const struct ieee80211_reg_rule *reg_rule = NULL; |
1762 | const struct ieee80211_power_rule *power_rule = NULL; | 1771 | const struct ieee80211_power_rule *power_rule = NULL; |
1763 | const struct ieee80211_freq_range *freq_range = NULL; | ||
1764 | u32 max_bandwidth_khz; | ||
1765 | u32 bw; | 1772 | u32 bw; |
1766 | 1773 | ||
1767 | for (bw = MHZ_TO_KHZ(20); bw >= MHZ_TO_KHZ(5); bw = bw / 2) { | 1774 | for (bw = MHZ_TO_KHZ(20); bw >= MHZ_TO_KHZ(5); bw = bw / 2) { |
1768 | reg_rule = freq_reg_info_regd(wiphy, | 1775 | reg_rule = freq_reg_info_regd(MHZ_TO_KHZ(chan->center_freq), |
1769 | MHZ_TO_KHZ(chan->center_freq), | ||
1770 | regd, bw); | 1776 | regd, bw); |
1771 | if (!IS_ERR(reg_rule)) | 1777 | if (!IS_ERR(reg_rule)) |
1772 | break; | 1778 | break; |
@@ -1787,31 +1793,7 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1787 | chan_reg_rule_print_dbg(regd, chan, reg_rule); | 1793 | chan_reg_rule_print_dbg(regd, chan, reg_rule); |
1788 | 1794 | ||
1789 | power_rule = ®_rule->power_rule; | 1795 | power_rule = ®_rule->power_rule; |
1790 | freq_range = ®_rule->freq_range; | 1796 | bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan); |
1791 | |||
1792 | max_bandwidth_khz = freq_range->max_bandwidth_khz; | ||
1793 | /* Check if auto calculation requested */ | ||
1794 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) | ||
1795 | max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); | ||
1796 | |||
1797 | /* If we get a reg_rule we can assume that at least 5Mhz fit */ | ||
1798 | if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq), | ||
1799 | MHZ_TO_KHZ(10))) | ||
1800 | bw_flags |= IEEE80211_CHAN_NO_10MHZ; | ||
1801 | if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq), | ||
1802 | MHZ_TO_KHZ(20))) | ||
1803 | bw_flags |= IEEE80211_CHAN_NO_20MHZ; | ||
1804 | |||
1805 | if (max_bandwidth_khz < MHZ_TO_KHZ(10)) | ||
1806 | bw_flags |= IEEE80211_CHAN_NO_10MHZ; | ||
1807 | if (max_bandwidth_khz < MHZ_TO_KHZ(20)) | ||
1808 | bw_flags |= IEEE80211_CHAN_NO_20MHZ; | ||
1809 | if (max_bandwidth_khz < MHZ_TO_KHZ(40)) | ||
1810 | bw_flags |= IEEE80211_CHAN_NO_HT40; | ||
1811 | if (max_bandwidth_khz < MHZ_TO_KHZ(80)) | ||
1812 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; | ||
1813 | if (max_bandwidth_khz < MHZ_TO_KHZ(160)) | ||
1814 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; | ||
1815 | 1797 | ||
1816 | chan->dfs_state_entered = jiffies; | 1798 | chan->dfs_state_entered = jiffies; |
1817 | chan->dfs_state = NL80211_DFS_USABLE; | 1799 | chan->dfs_state = NL80211_DFS_USABLE; |
@@ -3029,6 +3011,7 @@ int set_regdom(const struct ieee80211_regdomain *rd, | |||
3029 | break; | 3011 | break; |
3030 | default: | 3012 | default: |
3031 | WARN(1, "invalid initiator %d\n", lr->initiator); | 3013 | WARN(1, "invalid initiator %d\n", lr->initiator); |
3014 | kfree(rd); | ||
3032 | return -EINVAL; | 3015 | return -EINVAL; |
3033 | } | 3016 | } |
3034 | 3017 | ||
@@ -3221,8 +3204,10 @@ int __init regulatory_init(void) | |||
3221 | /* We always try to get an update for the static regdomain */ | 3204 | /* We always try to get an update for the static regdomain */ |
3222 | err = regulatory_hint_core(cfg80211_world_regdom->alpha2); | 3205 | err = regulatory_hint_core(cfg80211_world_regdom->alpha2); |
3223 | if (err) { | 3206 | if (err) { |
3224 | if (err == -ENOMEM) | 3207 | if (err == -ENOMEM) { |
3208 | platform_device_unregister(reg_pdev); | ||
3225 | return err; | 3209 | return err; |
3210 | } | ||
3226 | /* | 3211 | /* |
3227 | * N.B. kobject_uevent_env() can fail mainly for when we're out | 3212 | * N.B. kobject_uevent_env() can fail mainly for when we're out |
3228 | * memory which is handled and propagated appropriately above | 3213 | * memory which is handled and propagated appropriately above |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 0c392d36781b..09b242b09bed 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -623,12 +623,24 @@ DECLARE_EVENT_CLASS(station_add_change, | |||
623 | __field(u32, sta_flags_set) | 623 | __field(u32, sta_flags_set) |
624 | __field(u32, sta_modify_mask) | 624 | __field(u32, sta_modify_mask) |
625 | __field(int, listen_interval) | 625 | __field(int, listen_interval) |
626 | __field(u16, capability) | ||
626 | __field(u16, aid) | 627 | __field(u16, aid) |
627 | __field(u8, plink_action) | 628 | __field(u8, plink_action) |
628 | __field(u8, plink_state) | 629 | __field(u8, plink_state) |
629 | __field(u8, uapsd_queues) | 630 | __field(u8, uapsd_queues) |
631 | __field(u8, max_sp) | ||
632 | __field(u8, opmode_notif) | ||
633 | __field(bool, opmode_notif_used) | ||
630 | __array(u8, ht_capa, (int)sizeof(struct ieee80211_ht_cap)) | 634 | __array(u8, ht_capa, (int)sizeof(struct ieee80211_ht_cap)) |
635 | __array(u8, vht_capa, (int)sizeof(struct ieee80211_vht_cap)) | ||
631 | __array(char, vlan, IFNAMSIZ) | 636 | __array(char, vlan, IFNAMSIZ) |
637 | __dynamic_array(u8, supported_rates, | ||
638 | params->supported_rates_len) | ||
639 | __dynamic_array(u8, ext_capab, params->ext_capab_len) | ||
640 | __dynamic_array(u8, supported_channels, | ||
641 | params->supported_channels_len) | ||
642 | __dynamic_array(u8, supported_oper_classes, | ||
643 | params->supported_oper_classes_len) | ||
632 | ), | 644 | ), |
633 | TP_fast_assign( | 645 | TP_fast_assign( |
634 | WIPHY_ASSIGN; | 646 | WIPHY_ASSIGN; |
@@ -646,9 +658,35 @@ DECLARE_EVENT_CLASS(station_add_change, | |||
646 | if (params->ht_capa) | 658 | if (params->ht_capa) |
647 | memcpy(__entry->ht_capa, params->ht_capa, | 659 | memcpy(__entry->ht_capa, params->ht_capa, |
648 | sizeof(struct ieee80211_ht_cap)); | 660 | sizeof(struct ieee80211_ht_cap)); |
661 | memset(__entry->vht_capa, 0, sizeof(struct ieee80211_vht_cap)); | ||
662 | if (params->vht_capa) | ||
663 | memcpy(__entry->vht_capa, params->vht_capa, | ||
664 | sizeof(struct ieee80211_vht_cap)); | ||
649 | memset(__entry->vlan, 0, sizeof(__entry->vlan)); | 665 | memset(__entry->vlan, 0, sizeof(__entry->vlan)); |
650 | if (params->vlan) | 666 | if (params->vlan) |
651 | memcpy(__entry->vlan, params->vlan->name, IFNAMSIZ); | 667 | memcpy(__entry->vlan, params->vlan->name, IFNAMSIZ); |
668 | if (params->supported_rates && params->supported_rates_len) | ||
669 | memcpy(__get_dynamic_array(supported_rates), | ||
670 | params->supported_rates, | ||
671 | params->supported_rates_len); | ||
672 | if (params->ext_capab && params->ext_capab_len) | ||
673 | memcpy(__get_dynamic_array(ext_capab), | ||
674 | params->ext_capab, | ||
675 | params->ext_capab_len); | ||
676 | if (params->supported_channels && | ||
677 | params->supported_channels_len) | ||
678 | memcpy(__get_dynamic_array(supported_channels), | ||
679 | params->supported_channels, | ||
680 | params->supported_channels_len); | ||
681 | if (params->supported_oper_classes && | ||
682 | params->supported_oper_classes_len) | ||
683 | memcpy(__get_dynamic_array(supported_oper_classes), | ||
684 | params->supported_oper_classes, | ||
685 | params->supported_oper_classes_len); | ||
686 | __entry->max_sp = params->max_sp; | ||
687 | __entry->capability = params->capability; | ||
688 | __entry->opmode_notif = params->opmode_notif; | ||
689 | __entry->opmode_notif_used = params->opmode_notif_used; | ||
652 | ), | 690 | ), |
653 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT | 691 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT |
654 | ", station flags mask: %u, station flags set: %u, " | 692 | ", station flags mask: %u, station flags set: %u, " |
@@ -2818,6 +2856,71 @@ TRACE_EVENT(cfg80211_stop_iface, | |||
2818 | WIPHY_PR_ARG, WDEV_PR_ARG) | 2856 | WIPHY_PR_ARG, WDEV_PR_ARG) |
2819 | ); | 2857 | ); |
2820 | 2858 | ||
2859 | TRACE_EVENT(rdev_start_radar_detection, | ||
2860 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
2861 | struct cfg80211_chan_def *chandef, | ||
2862 | u32 cac_time_ms), | ||
2863 | TP_ARGS(wiphy, netdev, chandef, cac_time_ms), | ||
2864 | TP_STRUCT__entry( | ||
2865 | WIPHY_ENTRY | ||
2866 | NETDEV_ENTRY | ||
2867 | CHAN_DEF_ENTRY | ||
2868 | __field(u32, cac_time_ms) | ||
2869 | ), | ||
2870 | TP_fast_assign( | ||
2871 | WIPHY_ASSIGN; | ||
2872 | NETDEV_ASSIGN; | ||
2873 | CHAN_DEF_ASSIGN(chandef); | ||
2874 | __entry->cac_time_ms = cac_time_ms; | ||
2875 | ), | ||
2876 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT | ||
2877 | ", cac_time_ms=%u", | ||
2878 | WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, | ||
2879 | __entry->cac_time_ms) | ||
2880 | ); | ||
2881 | |||
2882 | TRACE_EVENT(rdev_set_mcast_rate, | ||
2883 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
2884 | int mcast_rate[IEEE80211_NUM_BANDS]), | ||
2885 | TP_ARGS(wiphy, netdev, mcast_rate), | ||
2886 | TP_STRUCT__entry( | ||
2887 | WIPHY_ENTRY | ||
2888 | NETDEV_ENTRY | ||
2889 | __array(int, mcast_rate, IEEE80211_NUM_BANDS) | ||
2890 | ), | ||
2891 | TP_fast_assign( | ||
2892 | WIPHY_ASSIGN; | ||
2893 | NETDEV_ASSIGN; | ||
2894 | memcpy(__entry->mcast_rate, mcast_rate, | ||
2895 | sizeof(int) * IEEE80211_NUM_BANDS); | ||
2896 | ), | ||
2897 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " | ||
2898 | "mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 60GHz=0x%x]", | ||
2899 | WIPHY_PR_ARG, NETDEV_PR_ARG, | ||
2900 | __entry->mcast_rate[IEEE80211_BAND_2GHZ], | ||
2901 | __entry->mcast_rate[IEEE80211_BAND_5GHZ], | ||
2902 | __entry->mcast_rate[IEEE80211_BAND_60GHZ]) | ||
2903 | ); | ||
2904 | |||
2905 | TRACE_EVENT(rdev_set_coalesce, | ||
2906 | TP_PROTO(struct wiphy *wiphy, struct cfg80211_coalesce *coalesce), | ||
2907 | TP_ARGS(wiphy, coalesce), | ||
2908 | TP_STRUCT__entry( | ||
2909 | WIPHY_ENTRY | ||
2910 | __field(int, n_rules) | ||
2911 | ), | ||
2912 | TP_fast_assign( | ||
2913 | WIPHY_ASSIGN; | ||
2914 | __entry->n_rules = coalesce ? coalesce->n_rules : 0; | ||
2915 | ), | ||
2916 | TP_printk(WIPHY_PR_FMT ", n_rules=%d", | ||
2917 | WIPHY_PR_ARG, __entry->n_rules) | ||
2918 | ); | ||
2919 | |||
2920 | DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan, | ||
2921 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), | ||
2922 | TP_ARGS(wiphy, wdev) | ||
2923 | ); | ||
2821 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ | 2924 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ |
2822 | 2925 | ||
2823 | #undef TRACE_INCLUDE_PATH | 2926 | #undef TRACE_INCLUDE_PATH |
diff --git a/net/wireless/util.c b/net/wireless/util.c index baf7218cec15..92770427b211 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -1325,13 +1325,6 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen, | |||
1325 | } | 1325 | } |
1326 | EXPORT_SYMBOL(ieee80211_ie_split_ric); | 1326 | EXPORT_SYMBOL(ieee80211_ie_split_ric); |
1327 | 1327 | ||
1328 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | ||
1329 | const u8 *ids, int n_ids, size_t offset) | ||
1330 | { | ||
1331 | return ieee80211_ie_split_ric(ies, ielen, ids, n_ids, NULL, 0, offset); | ||
1332 | } | ||
1333 | EXPORT_SYMBOL(ieee80211_ie_split); | ||
1334 | |||
1335 | bool ieee80211_operating_class_to_band(u8 operating_class, | 1328 | bool ieee80211_operating_class_to_band(u8 operating_class, |
1336 | enum ieee80211_band *band) | 1329 | enum ieee80211_band *band) |
1337 | { | 1330 | { |
@@ -1620,120 +1613,6 @@ int cfg80211_check_combinations(struct wiphy *wiphy, | |||
1620 | } | 1613 | } |
1621 | EXPORT_SYMBOL(cfg80211_check_combinations); | 1614 | EXPORT_SYMBOL(cfg80211_check_combinations); |
1622 | 1615 | ||
1623 | int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | ||
1624 | struct wireless_dev *wdev, | ||
1625 | enum nl80211_iftype iftype, | ||
1626 | struct ieee80211_channel *chan, | ||
1627 | enum cfg80211_chan_mode chanmode, | ||
1628 | u8 radar_detect) | ||
1629 | { | ||
1630 | struct wireless_dev *wdev_iter; | ||
1631 | int num[NUM_NL80211_IFTYPES]; | ||
1632 | struct ieee80211_channel | ||
1633 | *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS]; | ||
1634 | struct ieee80211_channel *ch; | ||
1635 | enum cfg80211_chan_mode chmode; | ||
1636 | int num_different_channels = 0; | ||
1637 | int total = 1; | ||
1638 | int i; | ||
1639 | |||
1640 | ASSERT_RTNL(); | ||
1641 | |||
1642 | if (WARN_ON(hweight32(radar_detect) > 1)) | ||
1643 | return -EINVAL; | ||
1644 | |||
1645 | if (WARN_ON(iftype >= NUM_NL80211_IFTYPES)) | ||
1646 | return -EINVAL; | ||
1647 | |||
1648 | /* Always allow software iftypes */ | ||
1649 | if (rdev->wiphy.software_iftypes & BIT(iftype)) { | ||
1650 | if (radar_detect) | ||
1651 | return -EINVAL; | ||
1652 | return 0; | ||
1653 | } | ||
1654 | |||
1655 | memset(num, 0, sizeof(num)); | ||
1656 | memset(used_channels, 0, sizeof(used_channels)); | ||
1657 | |||
1658 | num[iftype] = 1; | ||
1659 | |||
1660 | /* TODO: We'll probably not need this anymore, since this | ||
1661 | * should only be called with CHAN_MODE_UNDEFINED. There are | ||
1662 | * still a couple of pending calls where other chanmodes are | ||
1663 | * used, but we should get rid of them. | ||
1664 | */ | ||
1665 | switch (chanmode) { | ||
1666 | case CHAN_MODE_UNDEFINED: | ||
1667 | break; | ||
1668 | case CHAN_MODE_SHARED: | ||
1669 | WARN_ON(!chan); | ||
1670 | used_channels[0] = chan; | ||
1671 | num_different_channels++; | ||
1672 | break; | ||
1673 | case CHAN_MODE_EXCLUSIVE: | ||
1674 | num_different_channels++; | ||
1675 | break; | ||
1676 | } | ||
1677 | |||
1678 | list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { | ||
1679 | if (wdev_iter == wdev) | ||
1680 | continue; | ||
1681 | if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) { | ||
1682 | if (!wdev_iter->p2p_started) | ||
1683 | continue; | ||
1684 | } else if (wdev_iter->netdev) { | ||
1685 | if (!netif_running(wdev_iter->netdev)) | ||
1686 | continue; | ||
1687 | } else { | ||
1688 | WARN_ON(1); | ||
1689 | } | ||
1690 | |||
1691 | if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) | ||
1692 | continue; | ||
1693 | |||
1694 | /* | ||
1695 | * We may be holding the "wdev" mutex, but now need to lock | ||
1696 | * wdev_iter. This is OK because once we get here wdev_iter | ||
1697 | * is not wdev (tested above), but we need to use the nested | ||
1698 | * locking for lockdep. | ||
1699 | */ | ||
1700 | mutex_lock_nested(&wdev_iter->mtx, 1); | ||
1701 | __acquire(wdev_iter->mtx); | ||
1702 | cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect); | ||
1703 | wdev_unlock(wdev_iter); | ||
1704 | |||
1705 | switch (chmode) { | ||
1706 | case CHAN_MODE_UNDEFINED: | ||
1707 | break; | ||
1708 | case CHAN_MODE_SHARED: | ||
1709 | for (i = 0; i < CFG80211_MAX_NUM_DIFFERENT_CHANNELS; i++) | ||
1710 | if (!used_channels[i] || used_channels[i] == ch) | ||
1711 | break; | ||
1712 | |||
1713 | if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS) | ||
1714 | return -EBUSY; | ||
1715 | |||
1716 | if (used_channels[i] == NULL) { | ||
1717 | used_channels[i] = ch; | ||
1718 | num_different_channels++; | ||
1719 | } | ||
1720 | break; | ||
1721 | case CHAN_MODE_EXCLUSIVE: | ||
1722 | num_different_channels++; | ||
1723 | break; | ||
1724 | } | ||
1725 | |||
1726 | num[wdev_iter->iftype]++; | ||
1727 | total++; | ||
1728 | } | ||
1729 | |||
1730 | if (total == 1 && !radar_detect) | ||
1731 | return 0; | ||
1732 | |||
1733 | return cfg80211_check_combinations(&rdev->wiphy, num_different_channels, | ||
1734 | radar_detect, num); | ||
1735 | } | ||
1736 | |||
1737 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, | 1616 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, |
1738 | const u8 *rates, unsigned int n_rates, | 1617 | const u8 *rates, unsigned int n_rates, |
1739 | u32 *mask) | 1618 | u32 *mask) |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 09bfcbac63bb..b5e665b3cfb0 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -303,6 +303,14 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp) | |||
303 | } | 303 | } |
304 | EXPORT_SYMBOL(xfrm_policy_alloc); | 304 | EXPORT_SYMBOL(xfrm_policy_alloc); |
305 | 305 | ||
306 | static void xfrm_policy_destroy_rcu(struct rcu_head *head) | ||
307 | { | ||
308 | struct xfrm_policy *policy = container_of(head, struct xfrm_policy, rcu); | ||
309 | |||
310 | security_xfrm_policy_free(policy->security); | ||
311 | kfree(policy); | ||
312 | } | ||
313 | |||
306 | /* Destroy xfrm_policy: descendant resources must be released to this moment. */ | 314 | /* Destroy xfrm_policy: descendant resources must be released to this moment. */ |
307 | 315 | ||
308 | void xfrm_policy_destroy(struct xfrm_policy *policy) | 316 | void xfrm_policy_destroy(struct xfrm_policy *policy) |
@@ -312,8 +320,7 @@ void xfrm_policy_destroy(struct xfrm_policy *policy) | |||
312 | if (del_timer(&policy->timer) || del_timer(&policy->polq.hold_timer)) | 320 | if (del_timer(&policy->timer) || del_timer(&policy->polq.hold_timer)) |
313 | BUG(); | 321 | BUG(); |
314 | 322 | ||
315 | security_xfrm_policy_free(policy->security); | 323 | call_rcu(&policy->rcu, xfrm_policy_destroy_rcu); |
316 | kfree(policy); | ||
317 | } | 324 | } |
318 | EXPORT_SYMBOL(xfrm_policy_destroy); | 325 | EXPORT_SYMBOL(xfrm_policy_destroy); |
319 | 326 | ||
@@ -1214,8 +1221,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir, | |||
1214 | struct xfrm_policy *pol; | 1221 | struct xfrm_policy *pol; |
1215 | struct net *net = sock_net(sk); | 1222 | struct net *net = sock_net(sk); |
1216 | 1223 | ||
1224 | rcu_read_lock(); | ||
1217 | read_lock_bh(&net->xfrm.xfrm_policy_lock); | 1225 | read_lock_bh(&net->xfrm.xfrm_policy_lock); |
1218 | if ((pol = sk->sk_policy[dir]) != NULL) { | 1226 | pol = rcu_dereference(sk->sk_policy[dir]); |
1227 | if (pol != NULL) { | ||
1219 | bool match = xfrm_selector_match(&pol->selector, fl, | 1228 | bool match = xfrm_selector_match(&pol->selector, fl, |
1220 | sk->sk_family); | 1229 | sk->sk_family); |
1221 | int err = 0; | 1230 | int err = 0; |
@@ -1239,6 +1248,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir, | |||
1239 | } | 1248 | } |
1240 | out: | 1249 | out: |
1241 | read_unlock_bh(&net->xfrm.xfrm_policy_lock); | 1250 | read_unlock_bh(&net->xfrm.xfrm_policy_lock); |
1251 | rcu_read_unlock(); | ||
1242 | return pol; | 1252 | return pol; |
1243 | } | 1253 | } |
1244 | 1254 | ||
@@ -1307,13 +1317,14 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1307 | #endif | 1317 | #endif |
1308 | 1318 | ||
1309 | write_lock_bh(&net->xfrm.xfrm_policy_lock); | 1319 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
1310 | old_pol = sk->sk_policy[dir]; | 1320 | old_pol = rcu_dereference_protected(sk->sk_policy[dir], |
1311 | sk->sk_policy[dir] = pol; | 1321 | lockdep_is_held(&net->xfrm.xfrm_policy_lock)); |
1312 | if (pol) { | 1322 | if (pol) { |
1313 | pol->curlft.add_time = get_seconds(); | 1323 | pol->curlft.add_time = get_seconds(); |
1314 | pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0); | 1324 | pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0); |
1315 | xfrm_sk_policy_link(pol, dir); | 1325 | xfrm_sk_policy_link(pol, dir); |
1316 | } | 1326 | } |
1327 | rcu_assign_pointer(sk->sk_policy[dir], pol); | ||
1317 | if (old_pol) { | 1328 | if (old_pol) { |
1318 | if (pol) | 1329 | if (pol) |
1319 | xfrm_policy_requeue(old_pol, pol); | 1330 | xfrm_policy_requeue(old_pol, pol); |
@@ -1361,17 +1372,26 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir) | |||
1361 | return newp; | 1372 | return newp; |
1362 | } | 1373 | } |
1363 | 1374 | ||
1364 | int __xfrm_sk_clone_policy(struct sock *sk) | 1375 | int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk) |
1365 | { | 1376 | { |
1366 | struct xfrm_policy *p0 = sk->sk_policy[0], | 1377 | const struct xfrm_policy *p; |
1367 | *p1 = sk->sk_policy[1]; | 1378 | struct xfrm_policy *np; |
1379 | int i, ret = 0; | ||
1368 | 1380 | ||
1369 | sk->sk_policy[0] = sk->sk_policy[1] = NULL; | 1381 | rcu_read_lock(); |
1370 | if (p0 && (sk->sk_policy[0] = clone_policy(p0, 0)) == NULL) | 1382 | for (i = 0; i < 2; i++) { |
1371 | return -ENOMEM; | 1383 | p = rcu_dereference(osk->sk_policy[i]); |
1372 | if (p1 && (sk->sk_policy[1] = clone_policy(p1, 1)) == NULL) | 1384 | if (p) { |
1373 | return -ENOMEM; | 1385 | np = clone_policy(p, i); |
1374 | return 0; | 1386 | if (unlikely(!np)) { |
1387 | ret = -ENOMEM; | ||
1388 | break; | ||
1389 | } | ||
1390 | rcu_assign_pointer(sk->sk_policy[i], np); | ||
1391 | } | ||
1392 | } | ||
1393 | rcu_read_unlock(); | ||
1394 | return ret; | ||
1375 | } | 1395 | } |
1376 | 1396 | ||
1377 | static int | 1397 | static int |
@@ -2198,6 +2218,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, | |||
2198 | xdst = NULL; | 2218 | xdst = NULL; |
2199 | route = NULL; | 2219 | route = NULL; |
2200 | 2220 | ||
2221 | sk = sk_const_to_full_sk(sk); | ||
2201 | if (sk && sk->sk_policy[XFRM_POLICY_OUT]) { | 2222 | if (sk && sk->sk_policy[XFRM_POLICY_OUT]) { |
2202 | num_pols = 1; | 2223 | num_pols = 1; |
2203 | pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); | 2224 | pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); |
@@ -2477,6 +2498,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
2477 | } | 2498 | } |
2478 | 2499 | ||
2479 | pol = NULL; | 2500 | pol = NULL; |
2501 | sk = sk_to_full_sk(sk); | ||
2480 | if (sk && sk->sk_policy[dir]) { | 2502 | if (sk && sk->sk_policy[dir]) { |
2481 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); | 2503 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); |
2482 | if (IS_ERR(pol)) { | 2504 | if (IS_ERR(pol)) { |
@@ -2804,7 +2826,6 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, | |||
2804 | 2826 | ||
2805 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | 2827 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) |
2806 | { | 2828 | { |
2807 | struct net *net; | ||
2808 | int err = 0; | 2829 | int err = 0; |
2809 | if (unlikely(afinfo == NULL)) | 2830 | if (unlikely(afinfo == NULL)) |
2810 | return -EINVAL; | 2831 | return -EINVAL; |
@@ -2835,26 +2856,6 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2835 | } | 2856 | } |
2836 | spin_unlock(&xfrm_policy_afinfo_lock); | 2857 | spin_unlock(&xfrm_policy_afinfo_lock); |
2837 | 2858 | ||
2838 | rtnl_lock(); | ||
2839 | for_each_net(net) { | ||
2840 | struct dst_ops *xfrm_dst_ops; | ||
2841 | |||
2842 | switch (afinfo->family) { | ||
2843 | case AF_INET: | ||
2844 | xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops; | ||
2845 | break; | ||
2846 | #if IS_ENABLED(CONFIG_IPV6) | ||
2847 | case AF_INET6: | ||
2848 | xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops; | ||
2849 | break; | ||
2850 | #endif | ||
2851 | default: | ||
2852 | BUG(); | ||
2853 | } | ||
2854 | *xfrm_dst_ops = *afinfo->dst_ops; | ||
2855 | } | ||
2856 | rtnl_unlock(); | ||
2857 | |||
2858 | return err; | 2859 | return err; |
2859 | } | 2860 | } |
2860 | EXPORT_SYMBOL(xfrm_policy_register_afinfo); | 2861 | EXPORT_SYMBOL(xfrm_policy_register_afinfo); |
@@ -2890,22 +2891,6 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2890 | } | 2891 | } |
2891 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); | 2892 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); |
2892 | 2893 | ||
2893 | static void __net_init xfrm_dst_ops_init(struct net *net) | ||
2894 | { | ||
2895 | struct xfrm_policy_afinfo *afinfo; | ||
2896 | |||
2897 | rcu_read_lock(); | ||
2898 | afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET]); | ||
2899 | if (afinfo) | ||
2900 | net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops; | ||
2901 | #if IS_ENABLED(CONFIG_IPV6) | ||
2902 | afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET6]); | ||
2903 | if (afinfo) | ||
2904 | net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops; | ||
2905 | #endif | ||
2906 | rcu_read_unlock(); | ||
2907 | } | ||
2908 | |||
2909 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) | 2894 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) |
2910 | { | 2895 | { |
2911 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 2896 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
@@ -3054,7 +3039,6 @@ static int __net_init xfrm_net_init(struct net *net) | |||
3054 | rv = xfrm_policy_init(net); | 3039 | rv = xfrm_policy_init(net); |
3055 | if (rv < 0) | 3040 | if (rv < 0) |
3056 | goto out_policy; | 3041 | goto out_policy; |
3057 | xfrm_dst_ops_init(net); | ||
3058 | rv = xfrm_sysctl_init(net); | 3042 | rv = xfrm_sysctl_init(net); |
3059 | if (rv < 0) | 3043 | if (rv < 0) |
3060 | goto out_sysctl; | 3044 | goto out_sysctl; |