diff options
author | David S. Miller <davem@davemloft.net> | 2012-08-22 21:48:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-22 21:48:52 -0400 |
commit | bf277b0ccea7d2422b85e232017ce3fddbe9c49c (patch) | |
tree | 252232255b8a6024eccf2fea668bb89de5ae3073 /net | |
parent | bba6ec7e4963e30366359686f34e5bdb00b1a066 (diff) | |
parent | 90efbed18a30d78145419cdbd44f9ec152efeb16 (diff) |
Merge git://1984.lsi.us.es/nf-next
Pablo Neira Ayuso says:
====================
This is the first batch of Netfilter and IPVS updates for your
net-next tree. Mostly cleanups for the Netfilter side. They are:
* Remove unnecessary RTNL locking now that we have support
for namespace in nf_conntrack, from Patrick McHardy.
* Cleanup to eliminate unnecessary goto in the initialization
path of several Netfilter tables, from Jean Sacren.
* Another cleanup from Wu Fengguang, this time to PTR_RET instead
of if IS_ERR then return PTR_ERR.
* Use list_for_each_entry_continue_rcu in nf_iterate, from
Michael Wang.
* Add pmtu_disc sysctl option to disable PMTU in their tunneling
transmitter, from Julian Anastasov.
* Generalize application protocol registration in IPVS and modify
IPVS FTP helper to use it, from Julian Anastasov.
* update Kconfig. The IPVS FTP helper depends on the Netfilter FTP
helper for NAT support, from Julian Anastasov.
* Add logic to update PMTU for IPIP packets in IPVS, again
from Julian Anastasov.
* A couple of sparse warning fixes for IPVS and Netfilter from
Claudiu Ghioc and Patrick McHardy respectively.
Patrick's IPv6 NAT changes will follow after this batch, I need
to flush this batch first before refreshing my tree.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/netfilter/ebtable_filter.c | 4 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtable_nat.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_filter.c | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_mangle.c | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_raw.c | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_security.c | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_filter.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_raw.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_security.c | 5 | ||||
-rw-r--r-- | net/netfilter/core.c | 10 | ||||
-rw-r--r-- | net/netfilter/ipvs/Kconfig | 3 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_app.c | 58 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 76 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 16 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ftp.c | 21 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_xmit.c | 83 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 5 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_acct.c | 4 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_cthelper.c | 2 | ||||
-rw-r--r-- | net/netfilter/xt_NFQUEUE.c | 8 | ||||
-rw-r--r-- | net/netfilter/xt_osf.c | 2 |
22 files changed, 219 insertions, 129 deletions
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 42e6bd094574..3c2e9dced9e0 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c | |||
@@ -100,9 +100,7 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { | |||
100 | static int __net_init frame_filter_net_init(struct net *net) | 100 | static int __net_init frame_filter_net_init(struct net *net) |
101 | { | 101 | { |
102 | net->xt.frame_filter = ebt_register_table(net, &frame_filter); | 102 | net->xt.frame_filter = ebt_register_table(net, &frame_filter); |
103 | if (IS_ERR(net->xt.frame_filter)) | 103 | return PTR_RET(net->xt.frame_filter); |
104 | return PTR_ERR(net->xt.frame_filter); | ||
105 | return 0; | ||
106 | } | 104 | } |
107 | 105 | ||
108 | static void __net_exit frame_filter_net_exit(struct net *net) | 106 | static void __net_exit frame_filter_net_exit(struct net *net) |
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 6dc2f878ae05..10871bc77908 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c | |||
@@ -100,9 +100,7 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { | |||
100 | static int __net_init frame_nat_net_init(struct net *net) | 100 | static int __net_init frame_nat_net_init(struct net *net) |
101 | { | 101 | { |
102 | net->xt.frame_nat = ebt_register_table(net, &frame_nat); | 102 | net->xt.frame_nat = ebt_register_table(net, &frame_nat); |
103 | if (IS_ERR(net->xt.frame_nat)) | 103 | return PTR_RET(net->xt.frame_nat); |
104 | return PTR_ERR(net->xt.frame_nat); | ||
105 | return 0; | ||
106 | } | 104 | } |
107 | 105 | ||
108 | static void __net_exit frame_nat_net_exit(struct net *net) | 106 | static void __net_exit frame_nat_net_exit(struct net *net) |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 851acec852d2..6b3da5cf54e9 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -69,9 +69,7 @@ static int __net_init iptable_filter_net_init(struct net *net) | |||
69 | net->ipv4.iptable_filter = | 69 | net->ipv4.iptable_filter = |
70 | ipt_register_table(net, &packet_filter, repl); | 70 | ipt_register_table(net, &packet_filter, repl); |
71 | kfree(repl); | 71 | kfree(repl); |
72 | if (IS_ERR(net->ipv4.iptable_filter)) | 72 | return PTR_RET(net->ipv4.iptable_filter); |
73 | return PTR_ERR(net->ipv4.iptable_filter); | ||
74 | return 0; | ||
75 | } | 73 | } |
76 | 74 | ||
77 | static void __net_exit iptable_filter_net_exit(struct net *net) | 75 | static void __net_exit iptable_filter_net_exit(struct net *net) |
@@ -96,14 +94,10 @@ static int __init iptable_filter_init(void) | |||
96 | filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); | 94 | filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); |
97 | if (IS_ERR(filter_ops)) { | 95 | if (IS_ERR(filter_ops)) { |
98 | ret = PTR_ERR(filter_ops); | 96 | ret = PTR_ERR(filter_ops); |
99 | goto cleanup_table; | 97 | unregister_pernet_subsys(&iptable_filter_net_ops); |
100 | } | 98 | } |
101 | 99 | ||
102 | return ret; | 100 | return ret; |
103 | |||
104 | cleanup_table: | ||
105 | unregister_pernet_subsys(&iptable_filter_net_ops); | ||
106 | return ret; | ||
107 | } | 101 | } |
108 | 102 | ||
109 | static void __exit iptable_filter_fini(void) | 103 | static void __exit iptable_filter_fini(void) |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index aef5d1fbe77d..85d88f206447 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -104,9 +104,7 @@ static int __net_init iptable_mangle_net_init(struct net *net) | |||
104 | net->ipv4.iptable_mangle = | 104 | net->ipv4.iptable_mangle = |
105 | ipt_register_table(net, &packet_mangler, repl); | 105 | ipt_register_table(net, &packet_mangler, repl); |
106 | kfree(repl); | 106 | kfree(repl); |
107 | if (IS_ERR(net->ipv4.iptable_mangle)) | 107 | return PTR_RET(net->ipv4.iptable_mangle); |
108 | return PTR_ERR(net->ipv4.iptable_mangle); | ||
109 | return 0; | ||
110 | } | 108 | } |
111 | 109 | ||
112 | static void __net_exit iptable_mangle_net_exit(struct net *net) | 110 | static void __net_exit iptable_mangle_net_exit(struct net *net) |
@@ -131,14 +129,10 @@ static int __init iptable_mangle_init(void) | |||
131 | mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); | 129 | mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); |
132 | if (IS_ERR(mangle_ops)) { | 130 | if (IS_ERR(mangle_ops)) { |
133 | ret = PTR_ERR(mangle_ops); | 131 | ret = PTR_ERR(mangle_ops); |
134 | goto cleanup_table; | 132 | unregister_pernet_subsys(&iptable_mangle_net_ops); |
135 | } | 133 | } |
136 | 134 | ||
137 | return ret; | 135 | return ret; |
138 | |||
139 | cleanup_table: | ||
140 | unregister_pernet_subsys(&iptable_mangle_net_ops); | ||
141 | return ret; | ||
142 | } | 136 | } |
143 | 137 | ||
144 | static void __exit iptable_mangle_fini(void) | 138 | static void __exit iptable_mangle_fini(void) |
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 07fb710cd722..03d9696d3c6e 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -48,9 +48,7 @@ static int __net_init iptable_raw_net_init(struct net *net) | |||
48 | net->ipv4.iptable_raw = | 48 | net->ipv4.iptable_raw = |
49 | ipt_register_table(net, &packet_raw, repl); | 49 | ipt_register_table(net, &packet_raw, repl); |
50 | kfree(repl); | 50 | kfree(repl); |
51 | if (IS_ERR(net->ipv4.iptable_raw)) | 51 | return PTR_RET(net->ipv4.iptable_raw); |
52 | return PTR_ERR(net->ipv4.iptable_raw); | ||
53 | return 0; | ||
54 | } | 52 | } |
55 | 53 | ||
56 | static void __net_exit iptable_raw_net_exit(struct net *net) | 54 | static void __net_exit iptable_raw_net_exit(struct net *net) |
@@ -75,14 +73,10 @@ static int __init iptable_raw_init(void) | |||
75 | rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); | 73 | rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); |
76 | if (IS_ERR(rawtable_ops)) { | 74 | if (IS_ERR(rawtable_ops)) { |
77 | ret = PTR_ERR(rawtable_ops); | 75 | ret = PTR_ERR(rawtable_ops); |
78 | goto cleanup_table; | 76 | unregister_pernet_subsys(&iptable_raw_net_ops); |
79 | } | 77 | } |
80 | 78 | ||
81 | return ret; | 79 | return ret; |
82 | |||
83 | cleanup_table: | ||
84 | unregister_pernet_subsys(&iptable_raw_net_ops); | ||
85 | return ret; | ||
86 | } | 80 | } |
87 | 81 | ||
88 | static void __exit iptable_raw_fini(void) | 82 | static void __exit iptable_raw_fini(void) |
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index be45bdc4c602..b283d8e2601a 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c | |||
@@ -66,10 +66,7 @@ static int __net_init iptable_security_net_init(struct net *net) | |||
66 | net->ipv4.iptable_security = | 66 | net->ipv4.iptable_security = |
67 | ipt_register_table(net, &security_table, repl); | 67 | ipt_register_table(net, &security_table, repl); |
68 | kfree(repl); | 68 | kfree(repl); |
69 | if (IS_ERR(net->ipv4.iptable_security)) | 69 | return PTR_RET(net->ipv4.iptable_security); |
70 | return PTR_ERR(net->ipv4.iptable_security); | ||
71 | |||
72 | return 0; | ||
73 | } | 70 | } |
74 | 71 | ||
75 | static void __net_exit iptable_security_net_exit(struct net *net) | 72 | static void __net_exit iptable_security_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 325e59a0224f..beb5777d2043 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -61,9 +61,7 @@ static int __net_init ip6table_filter_net_init(struct net *net) | |||
61 | net->ipv6.ip6table_filter = | 61 | net->ipv6.ip6table_filter = |
62 | ip6t_register_table(net, &packet_filter, repl); | 62 | ip6t_register_table(net, &packet_filter, repl); |
63 | kfree(repl); | 63 | kfree(repl); |
64 | if (IS_ERR(net->ipv6.ip6table_filter)) | 64 | return PTR_RET(net->ipv6.ip6table_filter); |
65 | return PTR_ERR(net->ipv6.ip6table_filter); | ||
66 | return 0; | ||
67 | } | 65 | } |
68 | 66 | ||
69 | static void __net_exit ip6table_filter_net_exit(struct net *net) | 67 | static void __net_exit ip6table_filter_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 4d782405f125..7431121b87de 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -97,9 +97,7 @@ static int __net_init ip6table_mangle_net_init(struct net *net) | |||
97 | net->ipv6.ip6table_mangle = | 97 | net->ipv6.ip6table_mangle = |
98 | ip6t_register_table(net, &packet_mangler, repl); | 98 | ip6t_register_table(net, &packet_mangler, repl); |
99 | kfree(repl); | 99 | kfree(repl); |
100 | if (IS_ERR(net->ipv6.ip6table_mangle)) | 100 | return PTR_RET(net->ipv6.ip6table_mangle); |
101 | return PTR_ERR(net->ipv6.ip6table_mangle); | ||
102 | return 0; | ||
103 | } | 101 | } |
104 | 102 | ||
105 | static void __net_exit ip6table_mangle_net_exit(struct net *net) | 103 | static void __net_exit ip6table_mangle_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 5b9926a011bd..60d1bddff7a0 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -40,9 +40,7 @@ static int __net_init ip6table_raw_net_init(struct net *net) | |||
40 | net->ipv6.ip6table_raw = | 40 | net->ipv6.ip6table_raw = |
41 | ip6t_register_table(net, &packet_raw, repl); | 41 | ip6t_register_table(net, &packet_raw, repl); |
42 | kfree(repl); | 42 | kfree(repl); |
43 | if (IS_ERR(net->ipv6.ip6table_raw)) | 43 | return PTR_RET(net->ipv6.ip6table_raw); |
44 | return PTR_ERR(net->ipv6.ip6table_raw); | ||
45 | return 0; | ||
46 | } | 44 | } |
47 | 45 | ||
48 | static void __net_exit ip6table_raw_net_exit(struct net *net) | 46 | static void __net_exit ip6table_raw_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 91aa2b4d83c9..db155351339c 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c | |||
@@ -58,10 +58,7 @@ static int __net_init ip6table_security_net_init(struct net *net) | |||
58 | net->ipv6.ip6table_security = | 58 | net->ipv6.ip6table_security = |
59 | ip6t_register_table(net, &security_table, repl); | 59 | ip6t_register_table(net, &security_table, repl); |
60 | kfree(repl); | 60 | kfree(repl); |
61 | if (IS_ERR(net->ipv6.ip6table_security)) | 61 | return PTR_RET(net->ipv6.ip6table_security); |
62 | return PTR_ERR(net->ipv6.ip6table_security); | ||
63 | |||
64 | return 0; | ||
65 | } | 62 | } |
66 | 63 | ||
67 | static void __net_exit ip6table_security_net_exit(struct net *net) | 64 | static void __net_exit ip6table_security_net_exit(struct net *net) |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 0bc6b60db4df..8f4b0b2b6f80 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -131,14 +131,13 @@ unsigned int nf_iterate(struct list_head *head, | |||
131 | int hook_thresh) | 131 | int hook_thresh) |
132 | { | 132 | { |
133 | unsigned int verdict; | 133 | unsigned int verdict; |
134 | struct nf_hook_ops *elem = list_entry_rcu(*i, struct nf_hook_ops, list); | ||
134 | 135 | ||
135 | /* | 136 | /* |
136 | * The caller must not block between calls to this | 137 | * The caller must not block between calls to this |
137 | * function because of risk of continuing from deleted element. | 138 | * function because of risk of continuing from deleted element. |
138 | */ | 139 | */ |
139 | list_for_each_continue_rcu(*i, head) { | 140 | list_for_each_entry_continue_rcu(elem, head, list) { |
140 | struct nf_hook_ops *elem = (struct nf_hook_ops *)*i; | ||
141 | |||
142 | if (hook_thresh > elem->priority) | 141 | if (hook_thresh > elem->priority) |
143 | continue; | 142 | continue; |
144 | 143 | ||
@@ -155,11 +154,14 @@ repeat: | |||
155 | continue; | 154 | continue; |
156 | } | 155 | } |
157 | #endif | 156 | #endif |
158 | if (verdict != NF_REPEAT) | 157 | if (verdict != NF_REPEAT) { |
158 | *i = &elem->list; | ||
159 | return verdict; | 159 | return verdict; |
160 | } | ||
160 | goto repeat; | 161 | goto repeat; |
161 | } | 162 | } |
162 | } | 163 | } |
164 | *i = &elem->list; | ||
163 | return NF_ACCEPT; | 165 | return NF_ACCEPT; |
164 | } | 166 | } |
165 | 167 | ||
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index f9871385a65e..8b2cffdfdd99 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig | |||
@@ -250,7 +250,8 @@ comment 'IPVS application helper' | |||
250 | 250 | ||
251 | config IP_VS_FTP | 251 | config IP_VS_FTP |
252 | tristate "FTP protocol helper" | 252 | tristate "FTP protocol helper" |
253 | depends on IP_VS_PROTO_TCP && NF_CONNTRACK && NF_NAT | 253 | depends on IP_VS_PROTO_TCP && NF_CONNTRACK && NF_NAT && \ |
254 | NF_CONNTRACK_FTP | ||
254 | select IP_VS_NFCT | 255 | select IP_VS_NFCT |
255 | ---help--- | 256 | ---help--- |
256 | FTP is a protocol that transfers IP address and/or port number in | 257 | FTP is a protocol that transfers IP address and/or port number in |
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 64f9e8f13207..9713e6e86d47 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c | |||
@@ -180,22 +180,38 @@ register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto, | |||
180 | } | 180 | } |
181 | 181 | ||
182 | 182 | ||
183 | /* | 183 | /* Register application for netns */ |
184 | * ip_vs_app registration routine | 184 | struct ip_vs_app *register_ip_vs_app(struct net *net, struct ip_vs_app *app) |
185 | */ | ||
186 | int register_ip_vs_app(struct net *net, struct ip_vs_app *app) | ||
187 | { | 185 | { |
188 | struct netns_ipvs *ipvs = net_ipvs(net); | 186 | struct netns_ipvs *ipvs = net_ipvs(net); |
189 | /* increase the module use count */ | 187 | struct ip_vs_app *a; |
190 | ip_vs_use_count_inc(); | 188 | int err = 0; |
189 | |||
190 | if (!ipvs) | ||
191 | return ERR_PTR(-ENOENT); | ||
191 | 192 | ||
192 | mutex_lock(&__ip_vs_app_mutex); | 193 | mutex_lock(&__ip_vs_app_mutex); |
193 | 194 | ||
194 | list_add(&app->a_list, &ipvs->app_list); | 195 | list_for_each_entry(a, &ipvs->app_list, a_list) { |
196 | if (!strcmp(app->name, a->name)) { | ||
197 | err = -EEXIST; | ||
198 | goto out_unlock; | ||
199 | } | ||
200 | } | ||
201 | a = kmemdup(app, sizeof(*app), GFP_KERNEL); | ||
202 | if (!a) { | ||
203 | err = -ENOMEM; | ||
204 | goto out_unlock; | ||
205 | } | ||
206 | INIT_LIST_HEAD(&a->incs_list); | ||
207 | list_add(&a->a_list, &ipvs->app_list); | ||
208 | /* increase the module use count */ | ||
209 | ip_vs_use_count_inc(); | ||
195 | 210 | ||
211 | out_unlock: | ||
196 | mutex_unlock(&__ip_vs_app_mutex); | 212 | mutex_unlock(&__ip_vs_app_mutex); |
197 | 213 | ||
198 | return 0; | 214 | return err ? ERR_PTR(err) : a; |
199 | } | 215 | } |
200 | 216 | ||
201 | 217 | ||
@@ -205,20 +221,29 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app) | |||
205 | */ | 221 | */ |
206 | void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) | 222 | void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) |
207 | { | 223 | { |
208 | struct ip_vs_app *inc, *nxt; | 224 | struct netns_ipvs *ipvs = net_ipvs(net); |
225 | struct ip_vs_app *a, *anxt, *inc, *nxt; | ||
226 | |||
227 | if (!ipvs) | ||
228 | return; | ||
209 | 229 | ||
210 | mutex_lock(&__ip_vs_app_mutex); | 230 | mutex_lock(&__ip_vs_app_mutex); |
211 | 231 | ||
212 | list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { | 232 | list_for_each_entry_safe(a, anxt, &ipvs->app_list, a_list) { |
213 | ip_vs_app_inc_release(net, inc); | 233 | if (app && strcmp(app->name, a->name)) |
214 | } | 234 | continue; |
235 | list_for_each_entry_safe(inc, nxt, &a->incs_list, a_list) { | ||
236 | ip_vs_app_inc_release(net, inc); | ||
237 | } | ||
215 | 238 | ||
216 | list_del(&app->a_list); | 239 | list_del(&a->a_list); |
240 | kfree(a); | ||
217 | 241 | ||
218 | mutex_unlock(&__ip_vs_app_mutex); | 242 | /* decrease the module use count */ |
243 | ip_vs_use_count_dec(); | ||
244 | } | ||
219 | 245 | ||
220 | /* decrease the module use count */ | 246 | mutex_unlock(&__ip_vs_app_mutex); |
221 | ip_vs_use_count_dec(); | ||
222 | } | 247 | } |
223 | 248 | ||
224 | 249 | ||
@@ -586,5 +611,6 @@ int __net_init ip_vs_app_net_init(struct net *net) | |||
586 | 611 | ||
587 | void __net_exit ip_vs_app_net_cleanup(struct net *net) | 612 | void __net_exit ip_vs_app_net_cleanup(struct net *net) |
588 | { | 613 | { |
614 | unregister_ip_vs_app(net, NULL /* all */); | ||
589 | proc_net_remove(net, "ip_vs_app"); | 615 | proc_net_remove(net, "ip_vs_app"); |
590 | } | 616 | } |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index b54eccef40b5..58918e20f9d5 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1303,7 +1303,8 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1303 | struct ip_vs_conn *cp; | 1303 | struct ip_vs_conn *cp; |
1304 | struct ip_vs_protocol *pp; | 1304 | struct ip_vs_protocol *pp; |
1305 | struct ip_vs_proto_data *pd; | 1305 | struct ip_vs_proto_data *pd; |
1306 | unsigned int offset, ihl, verdict; | 1306 | unsigned int offset, offset2, ihl, verdict; |
1307 | bool ipip; | ||
1307 | 1308 | ||
1308 | *related = 1; | 1309 | *related = 1; |
1309 | 1310 | ||
@@ -1345,6 +1346,21 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1345 | 1346 | ||
1346 | net = skb_net(skb); | 1347 | net = skb_net(skb); |
1347 | 1348 | ||
1349 | /* Special case for errors for IPIP packets */ | ||
1350 | ipip = false; | ||
1351 | if (cih->protocol == IPPROTO_IPIP) { | ||
1352 | if (unlikely(cih->frag_off & htons(IP_OFFSET))) | ||
1353 | return NF_ACCEPT; | ||
1354 | /* Error for our IPIP must arrive at LOCAL_IN */ | ||
1355 | if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) | ||
1356 | return NF_ACCEPT; | ||
1357 | offset += cih->ihl * 4; | ||
1358 | cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); | ||
1359 | if (cih == NULL) | ||
1360 | return NF_ACCEPT; /* The packet looks wrong, ignore */ | ||
1361 | ipip = true; | ||
1362 | } | ||
1363 | |||
1348 | pd = ip_vs_proto_data_get(net, cih->protocol); | 1364 | pd = ip_vs_proto_data_get(net, cih->protocol); |
1349 | if (!pd) | 1365 | if (!pd) |
1350 | return NF_ACCEPT; | 1366 | return NF_ACCEPT; |
@@ -1358,11 +1374,14 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1358 | IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset, | 1374 | IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset, |
1359 | "Checking incoming ICMP for"); | 1375 | "Checking incoming ICMP for"); |
1360 | 1376 | ||
1377 | offset2 = offset; | ||
1361 | offset += cih->ihl * 4; | 1378 | offset += cih->ihl * 4; |
1362 | 1379 | ||
1363 | ip_vs_fill_iphdr(AF_INET, cih, &ciph); | 1380 | ip_vs_fill_iphdr(AF_INET, cih, &ciph); |
1364 | /* The embedded headers contain source and dest in reverse order */ | 1381 | /* The embedded headers contain source and dest in reverse order. |
1365 | cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, 1); | 1382 | * For IPIP this is error for request, not for reply. |
1383 | */ | ||
1384 | cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, ipip ? 0 : 1); | ||
1366 | if (!cp) | 1385 | if (!cp) |
1367 | return NF_ACCEPT; | 1386 | return NF_ACCEPT; |
1368 | 1387 | ||
@@ -1376,6 +1395,57 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1376 | goto out; | 1395 | goto out; |
1377 | } | 1396 | } |
1378 | 1397 | ||
1398 | if (ipip) { | ||
1399 | __be32 info = ic->un.gateway; | ||
1400 | |||
1401 | /* Update the MTU */ | ||
1402 | if (ic->type == ICMP_DEST_UNREACH && | ||
1403 | ic->code == ICMP_FRAG_NEEDED) { | ||
1404 | struct ip_vs_dest *dest = cp->dest; | ||
1405 | u32 mtu = ntohs(ic->un.frag.mtu); | ||
1406 | |||
1407 | /* Strip outer IP and ICMP, go to IPIP header */ | ||
1408 | __skb_pull(skb, ihl + sizeof(_icmph)); | ||
1409 | offset2 -= ihl + sizeof(_icmph); | ||
1410 | skb_reset_network_header(skb); | ||
1411 | IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n", | ||
1412 | &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, mtu); | ||
1413 | rcu_read_lock(); | ||
1414 | ipv4_update_pmtu(skb, dev_net(skb->dev), | ||
1415 | mtu, 0, 0, 0, 0); | ||
1416 | rcu_read_unlock(); | ||
1417 | /* Client uses PMTUD? */ | ||
1418 | if (!(cih->frag_off & htons(IP_DF))) | ||
1419 | goto ignore_ipip; | ||
1420 | /* Prefer the resulting PMTU */ | ||
1421 | if (dest) { | ||
1422 | spin_lock(&dest->dst_lock); | ||
1423 | if (dest->dst_cache) | ||
1424 | mtu = dst_mtu(dest->dst_cache); | ||
1425 | spin_unlock(&dest->dst_lock); | ||
1426 | } | ||
1427 | if (mtu > 68 + sizeof(struct iphdr)) | ||
1428 | mtu -= sizeof(struct iphdr); | ||
1429 | info = htonl(mtu); | ||
1430 | } | ||
1431 | /* Strip outer IP, ICMP and IPIP, go to IP header of | ||
1432 | * original request. | ||
1433 | */ | ||
1434 | __skb_pull(skb, offset2); | ||
1435 | skb_reset_network_header(skb); | ||
1436 | IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n", | ||
1437 | &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, | ||
1438 | ic->type, ic->code, ntohl(info)); | ||
1439 | icmp_send(skb, ic->type, ic->code, info); | ||
1440 | /* ICMP can be shorter but anyways, account it */ | ||
1441 | ip_vs_out_stats(cp, skb); | ||
1442 | |||
1443 | ignore_ipip: | ||
1444 | consume_skb(skb); | ||
1445 | verdict = NF_STOLEN; | ||
1446 | goto out; | ||
1447 | } | ||
1448 | |||
1379 | /* do the statistics and put it back */ | 1449 | /* do the statistics and put it back */ |
1380 | ip_vs_in_stats(cp, skb); | 1450 | ip_vs_in_stats(cp, skb); |
1381 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) | 1451 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 72bf32a84874..3c601378d27e 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -1801,6 +1801,12 @@ static struct ctl_table vs_vars[] = { | |||
1801 | .mode = 0644, | 1801 | .mode = 0644, |
1802 | .proc_handler = proc_dointvec, | 1802 | .proc_handler = proc_dointvec, |
1803 | }, | 1803 | }, |
1804 | { | ||
1805 | .procname = "pmtu_disc", | ||
1806 | .maxlen = sizeof(int), | ||
1807 | .mode = 0644, | ||
1808 | .proc_handler = proc_dointvec, | ||
1809 | }, | ||
1804 | #ifdef CONFIG_IP_VS_DEBUG | 1810 | #ifdef CONFIG_IP_VS_DEBUG |
1805 | { | 1811 | { |
1806 | .procname = "debug_level", | 1812 | .procname = "debug_level", |
@@ -3676,7 +3682,7 @@ static void ip_vs_genl_unregister(void) | |||
3676 | * per netns intit/exit func. | 3682 | * per netns intit/exit func. |
3677 | */ | 3683 | */ |
3678 | #ifdef CONFIG_SYSCTL | 3684 | #ifdef CONFIG_SYSCTL |
3679 | int __net_init ip_vs_control_net_init_sysctl(struct net *net) | 3685 | static int __net_init ip_vs_control_net_init_sysctl(struct net *net) |
3680 | { | 3686 | { |
3681 | int idx; | 3687 | int idx; |
3682 | struct netns_ipvs *ipvs = net_ipvs(net); | 3688 | struct netns_ipvs *ipvs = net_ipvs(net); |
@@ -3727,6 +3733,8 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net) | |||
3727 | ipvs->sysctl_sync_retries = clamp_t(int, DEFAULT_SYNC_RETRIES, 0, 3); | 3733 | ipvs->sysctl_sync_retries = clamp_t(int, DEFAULT_SYNC_RETRIES, 0, 3); |
3728 | tbl[idx++].data = &ipvs->sysctl_sync_retries; | 3734 | tbl[idx++].data = &ipvs->sysctl_sync_retries; |
3729 | tbl[idx++].data = &ipvs->sysctl_nat_icmp_send; | 3735 | tbl[idx++].data = &ipvs->sysctl_nat_icmp_send; |
3736 | ipvs->sysctl_pmtu_disc = 1; | ||
3737 | tbl[idx++].data = &ipvs->sysctl_pmtu_disc; | ||
3730 | 3738 | ||
3731 | 3739 | ||
3732 | ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); | 3740 | ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); |
@@ -3744,7 +3752,7 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net) | |||
3744 | return 0; | 3752 | return 0; |
3745 | } | 3753 | } |
3746 | 3754 | ||
3747 | void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) | 3755 | static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) |
3748 | { | 3756 | { |
3749 | struct netns_ipvs *ipvs = net_ipvs(net); | 3757 | struct netns_ipvs *ipvs = net_ipvs(net); |
3750 | 3758 | ||
@@ -3755,8 +3763,8 @@ void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) | |||
3755 | 3763 | ||
3756 | #else | 3764 | #else |
3757 | 3765 | ||
3758 | int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; } | 3766 | static int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; } |
3759 | void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { } | 3767 | static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { } |
3760 | 3768 | ||
3761 | #endif | 3769 | #endif |
3762 | 3770 | ||
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index b20b29c903ef..ad70b7e4ac4a 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c | |||
@@ -441,16 +441,10 @@ static int __net_init __ip_vs_ftp_init(struct net *net) | |||
441 | 441 | ||
442 | if (!ipvs) | 442 | if (!ipvs) |
443 | return -ENOENT; | 443 | return -ENOENT; |
444 | app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL); | ||
445 | if (!app) | ||
446 | return -ENOMEM; | ||
447 | INIT_LIST_HEAD(&app->a_list); | ||
448 | INIT_LIST_HEAD(&app->incs_list); | ||
449 | ipvs->ftp_app = app; | ||
450 | 444 | ||
451 | ret = register_ip_vs_app(net, app); | 445 | app = register_ip_vs_app(net, &ip_vs_ftp); |
452 | if (ret) | 446 | if (IS_ERR(app)) |
453 | goto err_exit; | 447 | return PTR_ERR(app); |
454 | 448 | ||
455 | for (i = 0; i < ports_count; i++) { | 449 | for (i = 0; i < ports_count; i++) { |
456 | if (!ports[i]) | 450 | if (!ports[i]) |
@@ -464,9 +458,7 @@ static int __net_init __ip_vs_ftp_init(struct net *net) | |||
464 | return 0; | 458 | return 0; |
465 | 459 | ||
466 | err_unreg: | 460 | err_unreg: |
467 | unregister_ip_vs_app(net, app); | 461 | unregister_ip_vs_app(net, &ip_vs_ftp); |
468 | err_exit: | ||
469 | kfree(ipvs->ftp_app); | ||
470 | return ret; | 462 | return ret; |
471 | } | 463 | } |
472 | /* | 464 | /* |
@@ -474,10 +466,7 @@ err_exit: | |||
474 | */ | 466 | */ |
475 | static void __ip_vs_ftp_exit(struct net *net) | 467 | static void __ip_vs_ftp_exit(struct net *net) |
476 | { | 468 | { |
477 | struct netns_ipvs *ipvs = net_ipvs(net); | 469 | unregister_ip_vs_app(net, &ip_vs_ftp); |
478 | |||
479 | unregister_ip_vs_app(net, ipvs->ftp_app); | ||
480 | kfree(ipvs->ftp_app); | ||
481 | } | 470 | } |
482 | 471 | ||
483 | static struct pernet_operations ip_vs_ftp_ops = { | 472 | static struct pernet_operations ip_vs_ftp_ops = { |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 65b616ae1716..543a554008af 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -49,6 +49,7 @@ enum { | |||
49 | IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to | 49 | IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to |
50 | * local | 50 | * local |
51 | */ | 51 | */ |
52 | IP_VS_RT_MODE_CONNECT = 8, /* Always bind route to saddr */ | ||
52 | }; | 53 | }; |
53 | 54 | ||
54 | /* | 55 | /* |
@@ -84,6 +85,42 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos) | |||
84 | return dst; | 85 | return dst; |
85 | } | 86 | } |
86 | 87 | ||
88 | /* Get route to daddr, update *saddr, optionally bind route to saddr */ | ||
89 | static struct rtable *do_output_route4(struct net *net, __be32 daddr, | ||
90 | u32 rtos, int rt_mode, __be32 *saddr) | ||
91 | { | ||
92 | struct flowi4 fl4; | ||
93 | struct rtable *rt; | ||
94 | int loop = 0; | ||
95 | |||
96 | memset(&fl4, 0, sizeof(fl4)); | ||
97 | fl4.daddr = daddr; | ||
98 | fl4.saddr = (rt_mode & IP_VS_RT_MODE_CONNECT) ? *saddr : 0; | ||
99 | fl4.flowi4_tos = rtos; | ||
100 | |||
101 | retry: | ||
102 | rt = ip_route_output_key(net, &fl4); | ||
103 | if (IS_ERR(rt)) { | ||
104 | /* Invalid saddr ? */ | ||
105 | if (PTR_ERR(rt) == -EINVAL && *saddr && | ||
106 | rt_mode & IP_VS_RT_MODE_CONNECT && !loop) { | ||
107 | *saddr = 0; | ||
108 | flowi4_update_output(&fl4, 0, rtos, daddr, 0); | ||
109 | goto retry; | ||
110 | } | ||
111 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", &daddr); | ||
112 | return NULL; | ||
113 | } else if (!*saddr && rt_mode & IP_VS_RT_MODE_CONNECT && fl4.saddr) { | ||
114 | ip_rt_put(rt); | ||
115 | *saddr = fl4.saddr; | ||
116 | flowi4_update_output(&fl4, 0, rtos, daddr, fl4.saddr); | ||
117 | loop++; | ||
118 | goto retry; | ||
119 | } | ||
120 | *saddr = fl4.saddr; | ||
121 | return rt; | ||
122 | } | ||
123 | |||
87 | /* Get route to destination or remote server */ | 124 | /* Get route to destination or remote server */ |
88 | static struct rtable * | 125 | static struct rtable * |
89 | __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | 126 | __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, |
@@ -98,20 +135,13 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
98 | spin_lock(&dest->dst_lock); | 135 | spin_lock(&dest->dst_lock); |
99 | if (!(rt = (struct rtable *) | 136 | if (!(rt = (struct rtable *) |
100 | __ip_vs_dst_check(dest, rtos))) { | 137 | __ip_vs_dst_check(dest, rtos))) { |
101 | struct flowi4 fl4; | 138 | rt = do_output_route4(net, dest->addr.ip, rtos, |
102 | 139 | rt_mode, &dest->dst_saddr.ip); | |
103 | memset(&fl4, 0, sizeof(fl4)); | 140 | if (!rt) { |
104 | fl4.daddr = dest->addr.ip; | ||
105 | fl4.flowi4_tos = rtos; | ||
106 | rt = ip_route_output_key(net, &fl4); | ||
107 | if (IS_ERR(rt)) { | ||
108 | spin_unlock(&dest->dst_lock); | 141 | spin_unlock(&dest->dst_lock); |
109 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", | ||
110 | &dest->addr.ip); | ||
111 | return NULL; | 142 | return NULL; |
112 | } | 143 | } |
113 | __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); | 144 | __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); |
114 | dest->dst_saddr.ip = fl4.saddr; | ||
115 | IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, " | 145 | IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, " |
116 | "rtos=%X\n", | 146 | "rtos=%X\n", |
117 | &dest->addr.ip, &dest->dst_saddr.ip, | 147 | &dest->addr.ip, &dest->dst_saddr.ip, |
@@ -122,19 +152,17 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
122 | *ret_saddr = dest->dst_saddr.ip; | 152 | *ret_saddr = dest->dst_saddr.ip; |
123 | spin_unlock(&dest->dst_lock); | 153 | spin_unlock(&dest->dst_lock); |
124 | } else { | 154 | } else { |
125 | struct flowi4 fl4; | 155 | __be32 saddr = htonl(INADDR_ANY); |
126 | 156 | ||
127 | memset(&fl4, 0, sizeof(fl4)); | 157 | /* For such unconfigured boxes avoid many route lookups |
128 | fl4.daddr = daddr; | 158 | * for performance reasons because we do not remember saddr |
129 | fl4.flowi4_tos = rtos; | 159 | */ |
130 | rt = ip_route_output_key(net, &fl4); | 160 | rt_mode &= ~IP_VS_RT_MODE_CONNECT; |
131 | if (IS_ERR(rt)) { | 161 | rt = do_output_route4(net, daddr, rtos, rt_mode, &saddr); |
132 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", | 162 | if (!rt) |
133 | &daddr); | ||
134 | return NULL; | 163 | return NULL; |
135 | } | ||
136 | if (ret_saddr) | 164 | if (ret_saddr) |
137 | *ret_saddr = fl4.saddr; | 165 | *ret_saddr = saddr; |
138 | } | 166 | } |
139 | 167 | ||
140 | local = rt->rt_flags & RTCF_LOCAL; | 168 | local = rt->rt_flags & RTCF_LOCAL; |
@@ -331,6 +359,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest) | |||
331 | old_dst = dest->dst_cache; | 359 | old_dst = dest->dst_cache; |
332 | dest->dst_cache = NULL; | 360 | dest->dst_cache = NULL; |
333 | dst_release(old_dst); | 361 | dst_release(old_dst); |
362 | dest->dst_saddr.ip = 0; | ||
334 | } | 363 | } |
335 | 364 | ||
336 | #define IP_VS_XMIT_TUNNEL(skb, cp) \ | 365 | #define IP_VS_XMIT_TUNNEL(skb, cp) \ |
@@ -766,12 +795,13 @@ int | |||
766 | ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | 795 | ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
767 | struct ip_vs_protocol *pp) | 796 | struct ip_vs_protocol *pp) |
768 | { | 797 | { |
798 | struct netns_ipvs *ipvs = net_ipvs(skb_net(skb)); | ||
769 | struct rtable *rt; /* Route to the other host */ | 799 | struct rtable *rt; /* Route to the other host */ |
770 | __be32 saddr; /* Source for tunnel */ | 800 | __be32 saddr; /* Source for tunnel */ |
771 | struct net_device *tdev; /* Device to other host */ | 801 | struct net_device *tdev; /* Device to other host */ |
772 | struct iphdr *old_iph = ip_hdr(skb); | 802 | struct iphdr *old_iph = ip_hdr(skb); |
773 | u8 tos = old_iph->tos; | 803 | u8 tos = old_iph->tos; |
774 | __be16 df = old_iph->frag_off; | 804 | __be16 df; |
775 | struct iphdr *iph; /* Our new IP header */ | 805 | struct iphdr *iph; /* Our new IP header */ |
776 | unsigned int max_headroom; /* The extra header space needed */ | 806 | unsigned int max_headroom; /* The extra header space needed */ |
777 | int mtu; | 807 | int mtu; |
@@ -781,7 +811,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
781 | 811 | ||
782 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, | 812 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, |
783 | RT_TOS(tos), IP_VS_RT_MODE_LOCAL | | 813 | RT_TOS(tos), IP_VS_RT_MODE_LOCAL | |
784 | IP_VS_RT_MODE_NON_LOCAL, | 814 | IP_VS_RT_MODE_NON_LOCAL | |
815 | IP_VS_RT_MODE_CONNECT, | ||
785 | &saddr))) | 816 | &saddr))) |
786 | goto tx_error_icmp; | 817 | goto tx_error_icmp; |
787 | if (rt->rt_flags & RTCF_LOCAL) { | 818 | if (rt->rt_flags & RTCF_LOCAL) { |
@@ -796,13 +827,13 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
796 | IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__); | 827 | IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__); |
797 | goto tx_error_put; | 828 | goto tx_error_put; |
798 | } | 829 | } |
799 | if (skb_dst(skb)) | 830 | if (rt_is_output_route(skb_rtable(skb))) |
800 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); | 831 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); |
801 | 832 | ||
802 | df |= (old_iph->frag_off & htons(IP_DF)); | 833 | /* Copy DF, reset fragment offset and MF */ |
834 | df = sysctl_pmtu_disc(ipvs) ? old_iph->frag_off & htons(IP_DF) : 0; | ||
803 | 835 | ||
804 | if ((old_iph->frag_off & htons(IP_DF) && | 836 | if (df && mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb)) { |
805 | mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb))) { | ||
806 | icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu)); | 837 | icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu)); |
807 | IP_VS_DBG_RL("%s(): frag needed\n", __func__); | 838 | IP_VS_DBG_RL("%s(): frag needed\n", __func__); |
808 | goto tx_error_put; | 839 | goto tx_error_put; |
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 0dc63854390f..51e928db48c8 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/notifier.h> | 21 | #include <linux/notifier.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
24 | #include <linux/rtnetlink.h> | ||
25 | 24 | ||
26 | #include <net/netfilter/nf_conntrack.h> | 25 | #include <net/netfilter/nf_conntrack.h> |
27 | #include <net/netfilter/nf_conntrack_l3proto.h> | 26 | #include <net/netfilter/nf_conntrack_l3proto.h> |
@@ -294,9 +293,7 @@ void nf_conntrack_l3proto_unregister(struct net *net, | |||
294 | nf_ct_l3proto_unregister_sysctl(net, proto); | 293 | nf_ct_l3proto_unregister_sysctl(net, proto); |
295 | 294 | ||
296 | /* Remove all contrack entries for this protocol */ | 295 | /* Remove all contrack entries for this protocol */ |
297 | rtnl_lock(); | ||
298 | nf_ct_iterate_cleanup(net, kill_l3proto, proto); | 296 | nf_ct_iterate_cleanup(net, kill_l3proto, proto); |
299 | rtnl_unlock(); | ||
300 | } | 297 | } |
301 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); | 298 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); |
302 | 299 | ||
@@ -502,9 +499,7 @@ void nf_conntrack_l4proto_unregister(struct net *net, | |||
502 | nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); | 499 | nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); |
503 | 500 | ||
504 | /* Remove all contrack entries for this protocol */ | 501 | /* Remove all contrack entries for this protocol */ |
505 | rtnl_lock(); | ||
506 | nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); | 502 | nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); |
507 | rtnl_unlock(); | ||
508 | } | 503 | } |
509 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); | 504 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); |
510 | 505 | ||
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index b2e7310ca0b8..d7ec92879071 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c | |||
@@ -79,11 +79,11 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb, | |||
79 | 79 | ||
80 | if (tb[NFACCT_BYTES]) { | 80 | if (tb[NFACCT_BYTES]) { |
81 | atomic64_set(&nfacct->bytes, | 81 | atomic64_set(&nfacct->bytes, |
82 | be64_to_cpu(nla_get_u64(tb[NFACCT_BYTES]))); | 82 | be64_to_cpu(nla_get_be64(tb[NFACCT_BYTES]))); |
83 | } | 83 | } |
84 | if (tb[NFACCT_PKTS]) { | 84 | if (tb[NFACCT_PKTS]) { |
85 | atomic64_set(&nfacct->pkts, | 85 | atomic64_set(&nfacct->pkts, |
86 | be64_to_cpu(nla_get_u64(tb[NFACCT_PKTS]))); | 86 | be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS]))); |
87 | } | 87 | } |
88 | atomic_set(&nfacct->refcnt, 1); | 88 | atomic_set(&nfacct->refcnt, 1); |
89 | list_add_tail_rcu(&nfacct->head, &nfnl_acct_list); | 89 | list_add_tail_rcu(&nfacct->head, &nfnl_acct_list); |
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index d6836193d479..32a1ba3f3e27 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c | |||
@@ -74,7 +74,7 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, | |||
74 | if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) | 74 | if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) |
75 | return -EINVAL; | 75 | return -EINVAL; |
76 | 76 | ||
77 | tuple->src.l3num = ntohs(nla_get_u16(tb[NFCTH_TUPLE_L3PROTONUM])); | 77 | tuple->src.l3num = ntohs(nla_get_be16(tb[NFCTH_TUPLE_L3PROTONUM])); |
78 | tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]); | 78 | tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]); |
79 | 79 | ||
80 | return 0; | 80 | return 0; |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 7babe7d68716..817f9e9f2b16 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -43,7 +43,7 @@ static u32 hash_v4(const struct sk_buff *skb) | |||
43 | const struct iphdr *iph = ip_hdr(skb); | 43 | const struct iphdr *iph = ip_hdr(skb); |
44 | 44 | ||
45 | /* packets in either direction go into same queue */ | 45 | /* packets in either direction go into same queue */ |
46 | if (iph->saddr < iph->daddr) | 46 | if ((__force u32)iph->saddr < (__force u32)iph->daddr) |
47 | return jhash_3words((__force u32)iph->saddr, | 47 | return jhash_3words((__force u32)iph->saddr, |
48 | (__force u32)iph->daddr, iph->protocol, jhash_initval); | 48 | (__force u32)iph->daddr, iph->protocol, jhash_initval); |
49 | 49 | ||
@@ -57,7 +57,8 @@ static u32 hash_v6(const struct sk_buff *skb) | |||
57 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 57 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
58 | u32 a, b, c; | 58 | u32 a, b, c; |
59 | 59 | ||
60 | if (ip6h->saddr.s6_addr32[3] < ip6h->daddr.s6_addr32[3]) { | 60 | if ((__force u32)ip6h->saddr.s6_addr32[3] < |
61 | (__force u32)ip6h->daddr.s6_addr32[3]) { | ||
61 | a = (__force u32) ip6h->saddr.s6_addr32[3]; | 62 | a = (__force u32) ip6h->saddr.s6_addr32[3]; |
62 | b = (__force u32) ip6h->daddr.s6_addr32[3]; | 63 | b = (__force u32) ip6h->daddr.s6_addr32[3]; |
63 | } else { | 64 | } else { |
@@ -65,7 +66,8 @@ static u32 hash_v6(const struct sk_buff *skb) | |||
65 | a = (__force u32) ip6h->daddr.s6_addr32[3]; | 66 | a = (__force u32) ip6h->daddr.s6_addr32[3]; |
66 | } | 67 | } |
67 | 68 | ||
68 | if (ip6h->saddr.s6_addr32[1] < ip6h->daddr.s6_addr32[1]) | 69 | if ((__force u32)ip6h->saddr.s6_addr32[1] < |
70 | (__force u32)ip6h->daddr.s6_addr32[1]) | ||
69 | c = (__force u32) ip6h->saddr.s6_addr32[1]; | 71 | c = (__force u32) ip6h->saddr.s6_addr32[1]; |
70 | else | 72 | else |
71 | c = (__force u32) ip6h->daddr.s6_addr32[1]; | 73 | c = (__force u32) ip6h->daddr.s6_addr32[1]; |
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 846f895cb656..a5e673d32bda 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c | |||
@@ -269,7 +269,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) | |||
269 | mss <<= 8; | 269 | mss <<= 8; |
270 | mss |= optp[2]; | 270 | mss |= optp[2]; |
271 | 271 | ||
272 | mss = ntohs(mss); | 272 | mss = ntohs((__force __be16)mss); |
273 | break; | 273 | break; |
274 | case OSFOPT_TS: | 274 | case OSFOPT_TS: |
275 | loop_cont = 1; | 275 | loop_cont = 1; |