aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-10-08 12:50:38 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-08 12:50:38 -0400
commit364ae953a48152be11f1aa424cbfd943b7762b0d (patch)
tree6873b352af1aa2dd6baa223b951eff4d6e74b1ae /net/ipv4
parent075f664689b40217539ebfe856fab73d302a15f1 (diff)
parentf39a9410ed0503278fd5edc559fa019051413039 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter.c7
-rw-r--r--net/ipv4/netfilter/Kconfig128
-rw-r--r--net/ipv4/netfilter/Makefile4
-rw-r--r--net/ipv4/netfilter/arp_tables.c116
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c15
-rw-r--r--net/ipv4/netfilter/arptable_filter.c8
-rw-r--r--net/ipv4/netfilter/ip_tables.c177
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c29
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c17
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c21
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c30
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c26
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c21
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c19
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c15
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c23
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c35
-rw-r--r--net/ipv4/netfilter/ipt_ah.c24
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c20
-rw-r--r--net/ipv4/netfilter/ipt_recent.c501
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c9
-rw-r--r--net/ipv4/netfilter/iptable_filter.c6
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c10
-rw-r--r--net/ipv4/netfilter/iptable_raw.c4
-rw-r--r--net/ipv4/netfilter/iptable_security.c6
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c68
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c73
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c22
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c96
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c72
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c3
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c92
33 files changed, 606 insertions, 1093 deletions
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 01671ad51ed3..6efdb70b3eb2 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -12,6 +12,7 @@
12/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ 12/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
13int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) 13int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
14{ 14{
15 struct net *net = dev_net(skb->dst->dev);
15 const struct iphdr *iph = ip_hdr(skb); 16 const struct iphdr *iph = ip_hdr(skb);
16 struct rtable *rt; 17 struct rtable *rt;
17 struct flowi fl = {}; 18 struct flowi fl = {};
@@ -19,7 +20,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
19 unsigned int hh_len; 20 unsigned int hh_len;
20 unsigned int type; 21 unsigned int type;
21 22
22 type = inet_addr_type(&init_net, iph->saddr); 23 type = inet_addr_type(net, iph->saddr);
23 if (skb->sk && inet_sk(skb->sk)->transparent) 24 if (skb->sk && inet_sk(skb->sk)->transparent)
24 type = RTN_LOCAL; 25 type = RTN_LOCAL;
25 if (addr_type == RTN_UNSPEC) 26 if (addr_type == RTN_UNSPEC)
@@ -36,7 +37,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
36 fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; 37 fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
37 fl.mark = skb->mark; 38 fl.mark = skb->mark;
38 fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; 39 fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
39 if (ip_route_output_key(&init_net, &rt, &fl) != 0) 40 if (ip_route_output_key(net, &rt, &fl) != 0)
40 return -1; 41 return -1;
41 42
42 /* Drop old route. */ 43 /* Drop old route. */
@@ -46,7 +47,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
46 /* non-local src, find valid iif to satisfy 47 /* non-local src, find valid iif to satisfy
47 * rp-filter when calling ip_route_input. */ 48 * rp-filter when calling ip_route_input. */
48 fl.nl_u.ip4_u.daddr = iph->saddr; 49 fl.nl_u.ip4_u.daddr = iph->saddr;
49 if (ip_route_output_key(&init_net, &rt, &fl) != 0) 50 if (ip_route_output_key(net, &rt, &fl) != 0)
50 return -1; 51 return -1;
51 52
52 odst = skb->dst; 53 odst = skb->dst;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 90eb7cb47e77..3816e1dc9295 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -5,10 +5,15 @@
5menu "IP: Netfilter Configuration" 5menu "IP: Netfilter Configuration"
6 depends on INET && NETFILTER 6 depends on INET && NETFILTER
7 7
8config NF_DEFRAG_IPV4
9 tristate
10 default n
11
8config NF_CONNTRACK_IPV4 12config NF_CONNTRACK_IPV4
9 tristate "IPv4 connection tracking support (required for NAT)" 13 tristate "IPv4 connection tracking support (required for NAT)"
10 depends on NF_CONNTRACK 14 depends on NF_CONNTRACK
11 default m if NETFILTER_ADVANCED=n 15 default m if NETFILTER_ADVANCED=n
16 select NF_DEFRAG_IPV4
12 ---help--- 17 ---help---
13 Connection tracking keeps a record of what packets have passed 18 Connection tracking keeps a record of what packets have passed
14 through your machine, in order to figure out how they are related 19 through your machine, in order to figure out how they are related
@@ -56,23 +61,30 @@ config IP_NF_IPTABLES
56 61
57 To compile it as a module, choose M here. If unsure, say N. 62 To compile it as a module, choose M here. If unsure, say N.
58 63
64if IP_NF_IPTABLES
65
59# The matches. 66# The matches.
60config IP_NF_MATCH_RECENT 67config IP_NF_MATCH_ADDRTYPE
61 tristate '"recent" match support' 68 tristate '"addrtype" address type match support'
62 depends on IP_NF_IPTABLES
63 depends on NETFILTER_ADVANCED 69 depends on NETFILTER_ADVANCED
64 help 70 help
65 This match is used for creating one or many lists of recently 71 This option allows you to match what routing thinks of an address,
66 used addresses and then matching against that/those list(s). 72 eg. UNICAST, LOCAL, BROADCAST, ...
67 73
68 Short options are available by using 'iptables -m recent -h' 74 If you want to compile it as a module, say M here and read
69 Official Website: <http://snowman.net/projects/ipt_recent/> 75 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
76
77config IP_NF_MATCH_AH
78 tristate '"ah" match support'
79 depends on NETFILTER_ADVANCED
80 help
81 This match extension allows you to match a range of SPIs
82 inside AH header of IPSec packets.
70 83
71 To compile it as a module, choose M here. If unsure, say N. 84 To compile it as a module, choose M here. If unsure, say N.
72 85
73config IP_NF_MATCH_ECN 86config IP_NF_MATCH_ECN
74 tristate '"ecn" match support' 87 tristate '"ecn" match support'
75 depends on IP_NF_IPTABLES
76 depends on NETFILTER_ADVANCED 88 depends on NETFILTER_ADVANCED
77 help 89 help
78 This option adds a `ECN' match, which allows you to match against 90 This option adds a `ECN' match, which allows you to match against
@@ -80,19 +92,8 @@ config IP_NF_MATCH_ECN
80 92
81 To compile it as a module, choose M here. If unsure, say N. 93 To compile it as a module, choose M here. If unsure, say N.
82 94
83config IP_NF_MATCH_AH
84 tristate '"ah" match support'
85 depends on IP_NF_IPTABLES
86 depends on NETFILTER_ADVANCED
87 help
88 This match extension allows you to match a range of SPIs
89 inside AH header of IPSec packets.
90
91 To compile it as a module, choose M here. If unsure, say N.
92
93config IP_NF_MATCH_TTL 95config IP_NF_MATCH_TTL
94 tristate '"ttl" match support' 96 tristate '"ttl" match support'
95 depends on IP_NF_IPTABLES
96 depends on NETFILTER_ADVANCED 97 depends on NETFILTER_ADVANCED
97 help 98 help
98 This adds CONFIG_IP_NF_MATCH_TTL option, which enabled the user 99 This adds CONFIG_IP_NF_MATCH_TTL option, which enabled the user
@@ -100,21 +101,9 @@ config IP_NF_MATCH_TTL
100 101
101 To compile it as a module, choose M here. If unsure, say N. 102 To compile it as a module, choose M here. If unsure, say N.
102 103
103config IP_NF_MATCH_ADDRTYPE
104 tristate '"addrtype" address type match support'
105 depends on IP_NF_IPTABLES
106 depends on NETFILTER_ADVANCED
107 help
108 This option allows you to match what routing thinks of an address,
109 eg. UNICAST, LOCAL, BROADCAST, ...
110
111 If you want to compile it as a module, say M here and read
112 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
113
114# `filter', generic and specific targets 104# `filter', generic and specific targets
115config IP_NF_FILTER 105config IP_NF_FILTER
116 tristate "Packet filtering" 106 tristate "Packet filtering"
117 depends on IP_NF_IPTABLES
118 default m if NETFILTER_ADVANCED=n 107 default m if NETFILTER_ADVANCED=n
119 help 108 help
120 Packet filtering defines a table `filter', which has a series of 109 Packet filtering defines a table `filter', which has a series of
@@ -136,7 +125,6 @@ config IP_NF_TARGET_REJECT
136 125
137config IP_NF_TARGET_LOG 126config IP_NF_TARGET_LOG
138 tristate "LOG target support" 127 tristate "LOG target support"
139 depends on IP_NF_IPTABLES
140 default m if NETFILTER_ADVANCED=n 128 default m if NETFILTER_ADVANCED=n
141 help 129 help
142 This option adds a `LOG' target, which allows you to create rules in 130 This option adds a `LOG' target, which allows you to create rules in
@@ -146,7 +134,6 @@ config IP_NF_TARGET_LOG
146 134
147config IP_NF_TARGET_ULOG 135config IP_NF_TARGET_ULOG
148 tristate "ULOG target support" 136 tristate "ULOG target support"
149 depends on IP_NF_IPTABLES
150 default m if NETFILTER_ADVANCED=n 137 default m if NETFILTER_ADVANCED=n
151 ---help--- 138 ---help---
152 139
@@ -167,7 +154,7 @@ config IP_NF_TARGET_ULOG
167# NAT + specific targets: nf_conntrack 154# NAT + specific targets: nf_conntrack
168config NF_NAT 155config NF_NAT
169 tristate "Full NAT" 156 tristate "Full NAT"
170 depends on IP_NF_IPTABLES && NF_CONNTRACK_IPV4 157 depends on NF_CONNTRACK_IPV4
171 default m if NETFILTER_ADVANCED=n 158 default m if NETFILTER_ADVANCED=n
172 help 159 help
173 The Full NAT option allows masquerading, port forwarding and other 160 The Full NAT option allows masquerading, port forwarding and other
@@ -194,26 +181,26 @@ config IP_NF_TARGET_MASQUERADE
194 181
195 To compile it as a module, choose M here. If unsure, say N. 182 To compile it as a module, choose M here. If unsure, say N.
196 183
197config IP_NF_TARGET_REDIRECT 184config IP_NF_TARGET_NETMAP
198 tristate "REDIRECT target support" 185 tristate "NETMAP target support"
199 depends on NF_NAT 186 depends on NF_NAT
200 depends on NETFILTER_ADVANCED 187 depends on NETFILTER_ADVANCED
201 help 188 help
202 REDIRECT is a special case of NAT: all incoming connections are 189 NETMAP is an implementation of static 1:1 NAT mapping of network
203 mapped onto the incoming interface's address, causing the packets to 190 addresses. It maps the network address part, while keeping the host
204 come to the local machine instead of passing through. This is 191 address part intact.
205 useful for transparent proxies.
206 192
207 To compile it as a module, choose M here. If unsure, say N. 193 To compile it as a module, choose M here. If unsure, say N.
208 194
209config IP_NF_TARGET_NETMAP 195config IP_NF_TARGET_REDIRECT
210 tristate "NETMAP target support" 196 tristate "REDIRECT target support"
211 depends on NF_NAT 197 depends on NF_NAT
212 depends on NETFILTER_ADVANCED 198 depends on NETFILTER_ADVANCED
213 help 199 help
214 NETMAP is an implementation of static 1:1 NAT mapping of network 200 REDIRECT is a special case of NAT: all incoming connections are
215 addresses. It maps the network address part, while keeping the host 201 mapped onto the incoming interface's address, causing the packets to
216 address part intact. 202 come to the local machine instead of passing through. This is
203 useful for transparent proxies.
217 204
218 To compile it as a module, choose M here. If unsure, say N. 205 To compile it as a module, choose M here. If unsure, say N.
219 206
@@ -262,44 +249,43 @@ config NF_NAT_PROTO_SCTP
262 249
263config NF_NAT_FTP 250config NF_NAT_FTP
264 tristate 251 tristate
265 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 252 depends on NF_CONNTRACK && NF_NAT
266 default NF_NAT && NF_CONNTRACK_FTP 253 default NF_NAT && NF_CONNTRACK_FTP
267 254
268config NF_NAT_IRC 255config NF_NAT_IRC
269 tristate 256 tristate
270 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 257 depends on NF_CONNTRACK && NF_NAT
271 default NF_NAT && NF_CONNTRACK_IRC 258 default NF_NAT && NF_CONNTRACK_IRC
272 259
273config NF_NAT_TFTP 260config NF_NAT_TFTP
274 tristate 261 tristate
275 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 262 depends on NF_CONNTRACK && NF_NAT
276 default NF_NAT && NF_CONNTRACK_TFTP 263 default NF_NAT && NF_CONNTRACK_TFTP
277 264
278config NF_NAT_AMANDA 265config NF_NAT_AMANDA
279 tristate 266 tristate
280 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 267 depends on NF_CONNTRACK && NF_NAT
281 default NF_NAT && NF_CONNTRACK_AMANDA 268 default NF_NAT && NF_CONNTRACK_AMANDA
282 269
283config NF_NAT_PPTP 270config NF_NAT_PPTP
284 tristate 271 tristate
285 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 272 depends on NF_CONNTRACK && NF_NAT
286 default NF_NAT && NF_CONNTRACK_PPTP 273 default NF_NAT && NF_CONNTRACK_PPTP
287 select NF_NAT_PROTO_GRE 274 select NF_NAT_PROTO_GRE
288 275
289config NF_NAT_H323 276config NF_NAT_H323
290 tristate 277 tristate
291 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 278 depends on NF_CONNTRACK && NF_NAT
292 default NF_NAT && NF_CONNTRACK_H323 279 default NF_NAT && NF_CONNTRACK_H323
293 280
294config NF_NAT_SIP 281config NF_NAT_SIP
295 tristate 282 tristate
296 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 283 depends on NF_CONNTRACK && NF_NAT
297 default NF_NAT && NF_CONNTRACK_SIP 284 default NF_NAT && NF_CONNTRACK_SIP
298 285
299# mangle + specific targets 286# mangle + specific targets
300config IP_NF_MANGLE 287config IP_NF_MANGLE
301 tristate "Packet mangling" 288 tristate "Packet mangling"
302 depends on IP_NF_IPTABLES
303 default m if NETFILTER_ADVANCED=n 289 default m if NETFILTER_ADVANCED=n
304 help 290 help
305 This option adds a `mangle' table to iptables: see the man page for 291 This option adds a `mangle' table to iptables: see the man page for
@@ -308,6 +294,19 @@ config IP_NF_MANGLE
308 294
309 To compile it as a module, choose M here. If unsure, say N. 295 To compile it as a module, choose M here. If unsure, say N.
310 296
297config IP_NF_TARGET_CLUSTERIP
298 tristate "CLUSTERIP target support (EXPERIMENTAL)"
299 depends on IP_NF_MANGLE && EXPERIMENTAL
300 depends on NF_CONNTRACK_IPV4
301 depends on NETFILTER_ADVANCED
302 select NF_CONNTRACK_MARK
303 help
304 The CLUSTERIP target allows you to build load-balancing clusters of
305 network servers without having a dedicated load-balancing
306 router/server/switch.
307
308 To compile it as a module, choose M here. If unsure, say N.
309
311config IP_NF_TARGET_ECN 310config IP_NF_TARGET_ECN
312 tristate "ECN target support" 311 tristate "ECN target support"
313 depends on IP_NF_MANGLE 312 depends on IP_NF_MANGLE
@@ -338,23 +337,9 @@ config IP_NF_TARGET_TTL
338 337
339 To compile it as a module, choose M here. If unsure, say N. 338 To compile it as a module, choose M here. If unsure, say N.
340 339
341config IP_NF_TARGET_CLUSTERIP
342 tristate "CLUSTERIP target support (EXPERIMENTAL)"
343 depends on IP_NF_MANGLE && EXPERIMENTAL
344 depends on NF_CONNTRACK_IPV4
345 depends on NETFILTER_ADVANCED
346 select NF_CONNTRACK_MARK
347 help
348 The CLUSTERIP target allows you to build load-balancing clusters of
349 network servers without having a dedicated load-balancing
350 router/server/switch.
351
352 To compile it as a module, choose M here. If unsure, say N.
353
354# raw + specific targets 340# raw + specific targets
355config IP_NF_RAW 341config IP_NF_RAW
356 tristate 'raw table support (required for NOTRACK/TRACE)' 342 tristate 'raw table support (required for NOTRACK/TRACE)'
357 depends on IP_NF_IPTABLES
358 depends on NETFILTER_ADVANCED 343 depends on NETFILTER_ADVANCED
359 help 344 help
360 This option adds a `raw' table to iptables. This table is the very 345 This option adds a `raw' table to iptables. This table is the very
@@ -367,7 +352,6 @@ config IP_NF_RAW
367# security table for MAC policy 352# security table for MAC policy
368config IP_NF_SECURITY 353config IP_NF_SECURITY
369 tristate "Security table" 354 tristate "Security table"
370 depends on IP_NF_IPTABLES
371 depends on SECURITY 355 depends on SECURITY
372 depends on NETFILTER_ADVANCED 356 depends on NETFILTER_ADVANCED
373 help 357 help
@@ -376,6 +360,8 @@ config IP_NF_SECURITY
376 360
377 If unsure, say N. 361 If unsure, say N.
378 362
363endif # IP_NF_IPTABLES
364
379# ARP tables 365# ARP tables
380config IP_NF_ARPTABLES 366config IP_NF_ARPTABLES
381 tristate "ARP tables support" 367 tristate "ARP tables support"
@@ -388,9 +374,10 @@ config IP_NF_ARPTABLES
388 374
389 To compile it as a module, choose M here. If unsure, say N. 375 To compile it as a module, choose M here. If unsure, say N.
390 376
377if IP_NF_ARPTABLES
378
391config IP_NF_ARPFILTER 379config IP_NF_ARPFILTER
392 tristate "ARP packet filtering" 380 tristate "ARP packet filtering"
393 depends on IP_NF_ARPTABLES
394 help 381 help
395 ARP packet filtering defines a table `filter', which has a series of 382 ARP packet filtering defines a table `filter', which has a series of
396 rules for simple ARP packet filtering at local input and 383 rules for simple ARP packet filtering at local input and
@@ -401,10 +388,11 @@ config IP_NF_ARPFILTER
401 388
402config IP_NF_ARP_MANGLE 389config IP_NF_ARP_MANGLE
403 tristate "ARP payload mangling" 390 tristate "ARP payload mangling"
404 depends on IP_NF_ARPTABLES
405 help 391 help
406 Allows altering the ARP packet payload: source and destination 392 Allows altering the ARP packet payload: source and destination
407 hardware and network addresses. 393 hardware and network addresses.
408 394
395endif # IP_NF_ARPTABLES
396
409endmenu 397endmenu
410 398
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 3f31291f37ce..5f9b650d90fc 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -18,6 +18,9 @@ obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
18 18
19obj-$(CONFIG_NF_NAT) += nf_nat.o 19obj-$(CONFIG_NF_NAT) += nf_nat.o
20 20
21# defrag
22obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
23
21# NAT helpers (nf_conntrack) 24# NAT helpers (nf_conntrack)
22obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o 25obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
23obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o 26obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
@@ -48,7 +51,6 @@ obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o
48obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o 51obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
49obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o 52obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
50obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o 53obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
51obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
52obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 54obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
53 55
54# targets 56# targets
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 03e83a65aec5..8d70d29f1ccf 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -200,15 +200,12 @@ static inline int arp_checkentry(const struct arpt_arp *arp)
200 return 1; 200 return 1;
201} 201}
202 202
203static unsigned int arpt_error(struct sk_buff *skb, 203static unsigned int
204 const struct net_device *in, 204arpt_error(struct sk_buff *skb, const struct xt_target_param *par)
205 const struct net_device *out,
206 unsigned int hooknum,
207 const struct xt_target *target,
208 const void *targinfo)
209{ 205{
210 if (net_ratelimit()) 206 if (net_ratelimit())
211 printk("arp_tables: error: '%s'\n", (char *)targinfo); 207 printk("arp_tables: error: '%s'\n",
208 (const char *)par->targinfo);
212 209
213 return NF_DROP; 210 return NF_DROP;
214} 211}
@@ -232,6 +229,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
232 const char *indev, *outdev; 229 const char *indev, *outdev;
233 void *table_base; 230 void *table_base;
234 const struct xt_table_info *private; 231 const struct xt_table_info *private;
232 struct xt_target_param tgpar;
235 233
236 if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) 234 if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
237 return NF_DROP; 235 return NF_DROP;
@@ -245,6 +243,11 @@ unsigned int arpt_do_table(struct sk_buff *skb,
245 e = get_entry(table_base, private->hook_entry[hook]); 243 e = get_entry(table_base, private->hook_entry[hook]);
246 back = get_entry(table_base, private->underflow[hook]); 244 back = get_entry(table_base, private->underflow[hook]);
247 245
246 tgpar.in = in;
247 tgpar.out = out;
248 tgpar.hooknum = hook;
249 tgpar.family = NFPROTO_ARP;
250
248 arp = arp_hdr(skb); 251 arp = arp_hdr(skb);
249 do { 252 do {
250 if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { 253 if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
@@ -290,11 +293,10 @@ unsigned int arpt_do_table(struct sk_buff *skb,
290 /* Targets which reenter must return 293 /* Targets which reenter must return
291 * abs. verdicts 294 * abs. verdicts
292 */ 295 */
296 tgpar.target = t->u.kernel.target;
297 tgpar.targinfo = t->data;
293 verdict = t->u.kernel.target->target(skb, 298 verdict = t->u.kernel.target->target(skb,
294 in, out, 299 &tgpar);
295 hook,
296 t->u.kernel.target,
297 t->data);
298 300
299 /* Target might have changed stuff. */ 301 /* Target might have changed stuff. */
300 arp = arp_hdr(skb); 302 arp = arp_hdr(skb);
@@ -456,23 +458,24 @@ static inline int check_entry(struct arpt_entry *e, const char *name)
456 458
457static inline int check_target(struct arpt_entry *e, const char *name) 459static inline int check_target(struct arpt_entry *e, const char *name)
458{ 460{
459 struct arpt_entry_target *t; 461 struct arpt_entry_target *t = arpt_get_target(e);
460 struct xt_target *target;
461 int ret; 462 int ret;
462 463 struct xt_tgchk_param par = {
463 t = arpt_get_target(e); 464 .table = name,
464 target = t->u.kernel.target; 465 .entryinfo = e,
465 466 .target = t->u.kernel.target,
466 ret = xt_check_target(target, NF_ARP, t->u.target_size - sizeof(*t), 467 .targinfo = t->data,
467 name, e->comefrom, 0, 0); 468 .hook_mask = e->comefrom,
468 if (!ret && t->u.kernel.target->checkentry 469 .family = NFPROTO_ARP,
469 && !t->u.kernel.target->checkentry(name, e, target, t->data, 470 };
470 e->comefrom)) { 471
472 ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
473 if (ret < 0) {
471 duprintf("arp_tables: check failed for `%s'.\n", 474 duprintf("arp_tables: check failed for `%s'.\n",
472 t->u.kernel.target->name); 475 t->u.kernel.target->name);
473 ret = -EINVAL; 476 return ret;
474 } 477 }
475 return ret; 478 return 0;
476} 479}
477 480
478static inline int 481static inline int
@@ -488,7 +491,8 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
488 return ret; 491 return ret;
489 492
490 t = arpt_get_target(e); 493 t = arpt_get_target(e);
491 target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name, 494 target = try_then_request_module(xt_find_target(NFPROTO_ARP,
495 t->u.user.name,
492 t->u.user.revision), 496 t->u.user.revision),
493 "arpt_%s", t->u.user.name); 497 "arpt_%s", t->u.user.name);
494 if (IS_ERR(target) || !target) { 498 if (IS_ERR(target) || !target) {
@@ -554,15 +558,19 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
554 558
555static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) 559static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)
556{ 560{
561 struct xt_tgdtor_param par;
557 struct arpt_entry_target *t; 562 struct arpt_entry_target *t;
558 563
559 if (i && (*i)-- == 0) 564 if (i && (*i)-- == 0)
560 return 1; 565 return 1;
561 566
562 t = arpt_get_target(e); 567 t = arpt_get_target(e);
563 if (t->u.kernel.target->destroy) 568 par.target = t->u.kernel.target;
564 t->u.kernel.target->destroy(t->u.kernel.target, t->data); 569 par.targinfo = t->data;
565 module_put(t->u.kernel.target->me); 570 par.family = NFPROTO_ARP;
571 if (par.target->destroy != NULL)
572 par.target->destroy(&par);
573 module_put(par.target->me);
566 return 0; 574 return 0;
567} 575}
568 576
@@ -788,7 +796,7 @@ static void compat_standard_from_user(void *dst, void *src)
788 int v = *(compat_int_t *)src; 796 int v = *(compat_int_t *)src;
789 797
790 if (v > 0) 798 if (v > 0)
791 v += xt_compat_calc_jump(NF_ARP, v); 799 v += xt_compat_calc_jump(NFPROTO_ARP, v);
792 memcpy(dst, &v, sizeof(v)); 800 memcpy(dst, &v, sizeof(v));
793} 801}
794 802
@@ -797,7 +805,7 @@ static int compat_standard_to_user(void __user *dst, void *src)
797 compat_int_t cv = *(int *)src; 805 compat_int_t cv = *(int *)src;
798 806
799 if (cv > 0) 807 if (cv > 0)
800 cv -= xt_compat_calc_jump(NF_ARP, cv); 808 cv -= xt_compat_calc_jump(NFPROTO_ARP, cv);
801 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; 809 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
802} 810}
803 811
@@ -815,7 +823,7 @@ static int compat_calc_entry(struct arpt_entry *e,
815 t = arpt_get_target(e); 823 t = arpt_get_target(e);
816 off += xt_compat_target_offset(t->u.kernel.target); 824 off += xt_compat_target_offset(t->u.kernel.target);
817 newinfo->size -= off; 825 newinfo->size -= off;
818 ret = xt_compat_add_offset(NF_ARP, entry_offset, off); 826 ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off);
819 if (ret) 827 if (ret)
820 return ret; 828 return ret;
821 829
@@ -866,9 +874,9 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
866 name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; 874 name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
867#ifdef CONFIG_COMPAT 875#ifdef CONFIG_COMPAT
868 if (compat) 876 if (compat)
869 xt_compat_lock(NF_ARP); 877 xt_compat_lock(NFPROTO_ARP);
870#endif 878#endif
871 t = try_then_request_module(xt_find_table_lock(net, NF_ARP, name), 879 t = try_then_request_module(xt_find_table_lock(net, NFPROTO_ARP, name),
872 "arptable_%s", name); 880 "arptable_%s", name);
873 if (t && !IS_ERR(t)) { 881 if (t && !IS_ERR(t)) {
874 struct arpt_getinfo info; 882 struct arpt_getinfo info;
@@ -878,7 +886,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
878 if (compat) { 886 if (compat) {
879 struct xt_table_info tmp; 887 struct xt_table_info tmp;
880 ret = compat_table_info(private, &tmp); 888 ret = compat_table_info(private, &tmp);
881 xt_compat_flush_offsets(NF_ARP); 889 xt_compat_flush_offsets(NFPROTO_ARP);
882 private = &tmp; 890 private = &tmp;
883 } 891 }
884#endif 892#endif
@@ -901,7 +909,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
901 ret = t ? PTR_ERR(t) : -ENOENT; 909 ret = t ? PTR_ERR(t) : -ENOENT;
902#ifdef CONFIG_COMPAT 910#ifdef CONFIG_COMPAT
903 if (compat) 911 if (compat)
904 xt_compat_unlock(NF_ARP); 912 xt_compat_unlock(NFPROTO_ARP);
905#endif 913#endif
906 return ret; 914 return ret;
907} 915}
@@ -925,7 +933,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
925 return -EINVAL; 933 return -EINVAL;
926 } 934 }
927 935
928 t = xt_find_table_lock(net, NF_ARP, get.name); 936 t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
929 if (t && !IS_ERR(t)) { 937 if (t && !IS_ERR(t)) {
930 const struct xt_table_info *private = t->private; 938 const struct xt_table_info *private = t->private;
931 939
@@ -967,7 +975,7 @@ static int __do_replace(struct net *net, const char *name,
967 goto out; 975 goto out;
968 } 976 }
969 977
970 t = try_then_request_module(xt_find_table_lock(net, NF_ARP, name), 978 t = try_then_request_module(xt_find_table_lock(net, NFPROTO_ARP, name),
971 "arptable_%s", name); 979 "arptable_%s", name);
972 if (!t || IS_ERR(t)) { 980 if (!t || IS_ERR(t)) {
973 ret = t ? PTR_ERR(t) : -ENOENT; 981 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1134,7 +1142,7 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len,
1134 goto free; 1142 goto free;
1135 } 1143 }
1136 1144
1137 t = xt_find_table_lock(net, NF_ARP, name); 1145 t = xt_find_table_lock(net, NFPROTO_ARP, name);
1138 if (!t || IS_ERR(t)) { 1146 if (!t || IS_ERR(t)) {
1139 ret = t ? PTR_ERR(t) : -ENOENT; 1147 ret = t ? PTR_ERR(t) : -ENOENT;
1140 goto free; 1148 goto free;
@@ -1218,7 +1226,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
1218 entry_offset = (void *)e - (void *)base; 1226 entry_offset = (void *)e - (void *)base;
1219 1227
1220 t = compat_arpt_get_target(e); 1228 t = compat_arpt_get_target(e);
1221 target = try_then_request_module(xt_find_target(NF_ARP, 1229 target = try_then_request_module(xt_find_target(NFPROTO_ARP,
1222 t->u.user.name, 1230 t->u.user.name,
1223 t->u.user.revision), 1231 t->u.user.revision),
1224 "arpt_%s", t->u.user.name); 1232 "arpt_%s", t->u.user.name);
@@ -1232,7 +1240,7 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
1232 1240
1233 off += xt_compat_target_offset(target); 1241 off += xt_compat_target_offset(target);
1234 *size += off; 1242 *size += off;
1235 ret = xt_compat_add_offset(NF_ARP, entry_offset, off); 1243 ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off);
1236 if (ret) 1244 if (ret)
1237 goto release_target; 1245 goto release_target;
1238 1246
@@ -1333,7 +1341,7 @@ static int translate_compat_table(const char *name,
1333 1341
1334 duprintf("translate_compat_table: size %u\n", info->size); 1342 duprintf("translate_compat_table: size %u\n", info->size);
1335 j = 0; 1343 j = 0;
1336 xt_compat_lock(NF_ARP); 1344 xt_compat_lock(NFPROTO_ARP);
1337 /* Walk through entries, checking offsets. */ 1345 /* Walk through entries, checking offsets. */
1338 ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, 1346 ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size,
1339 check_compat_entry_size_and_hooks, 1347 check_compat_entry_size_and_hooks,
@@ -1383,8 +1391,8 @@ static int translate_compat_table(const char *name,
1383 ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, 1391 ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size,
1384 compat_copy_entry_from_user, 1392 compat_copy_entry_from_user,
1385 &pos, &size, name, newinfo, entry1); 1393 &pos, &size, name, newinfo, entry1);
1386 xt_compat_flush_offsets(NF_ARP); 1394 xt_compat_flush_offsets(NFPROTO_ARP);
1387 xt_compat_unlock(NF_ARP); 1395 xt_compat_unlock(NFPROTO_ARP);
1388 if (ret) 1396 if (ret)
1389 goto free_newinfo; 1397 goto free_newinfo;
1390 1398
@@ -1420,8 +1428,8 @@ out:
1420 COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); 1428 COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1421 return ret; 1429 return ret;
1422out_unlock: 1430out_unlock:
1423 xt_compat_flush_offsets(NF_ARP); 1431 xt_compat_flush_offsets(NFPROTO_ARP);
1424 xt_compat_unlock(NF_ARP); 1432 xt_compat_unlock(NFPROTO_ARP);
1425 goto out; 1433 goto out;
1426} 1434}
1427 1435
@@ -1607,8 +1615,8 @@ static int compat_get_entries(struct net *net,
1607 return -EINVAL; 1615 return -EINVAL;
1608 } 1616 }
1609 1617
1610 xt_compat_lock(NF_ARP); 1618 xt_compat_lock(NFPROTO_ARP);
1611 t = xt_find_table_lock(net, NF_ARP, get.name); 1619 t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
1612 if (t && !IS_ERR(t)) { 1620 if (t && !IS_ERR(t)) {
1613 const struct xt_table_info *private = t->private; 1621 const struct xt_table_info *private = t->private;
1614 struct xt_table_info info; 1622 struct xt_table_info info;
@@ -1623,13 +1631,13 @@ static int compat_get_entries(struct net *net,
1623 private->size, get.size); 1631 private->size, get.size);
1624 ret = -EAGAIN; 1632 ret = -EAGAIN;
1625 } 1633 }
1626 xt_compat_flush_offsets(NF_ARP); 1634 xt_compat_flush_offsets(NFPROTO_ARP);
1627 module_put(t->me); 1635 module_put(t->me);
1628 xt_table_unlock(t); 1636 xt_table_unlock(t);
1629 } else 1637 } else
1630 ret = t ? PTR_ERR(t) : -ENOENT; 1638 ret = t ? PTR_ERR(t) : -ENOENT;
1631 1639
1632 xt_compat_unlock(NF_ARP); 1640 xt_compat_unlock(NFPROTO_ARP);
1633 return ret; 1641 return ret;
1634} 1642}
1635 1643
@@ -1709,7 +1717,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1709 break; 1717 break;
1710 } 1718 }
1711 1719
1712 try_then_request_module(xt_find_revision(NF_ARP, rev.name, 1720 try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name,
1713 rev.revision, 1, &ret), 1721 rev.revision, 1, &ret),
1714 "arpt_%s", rev.name); 1722 "arpt_%s", rev.name);
1715 break; 1723 break;
@@ -1787,7 +1795,7 @@ void arpt_unregister_table(struct xt_table *table)
1787static struct xt_target arpt_standard_target __read_mostly = { 1795static struct xt_target arpt_standard_target __read_mostly = {
1788 .name = ARPT_STANDARD_TARGET, 1796 .name = ARPT_STANDARD_TARGET,
1789 .targetsize = sizeof(int), 1797 .targetsize = sizeof(int),
1790 .family = NF_ARP, 1798 .family = NFPROTO_ARP,
1791#ifdef CONFIG_COMPAT 1799#ifdef CONFIG_COMPAT
1792 .compatsize = sizeof(compat_int_t), 1800 .compatsize = sizeof(compat_int_t),
1793 .compat_from_user = compat_standard_from_user, 1801 .compat_from_user = compat_standard_from_user,
@@ -1799,7 +1807,7 @@ static struct xt_target arpt_error_target __read_mostly = {
1799 .name = ARPT_ERROR_TARGET, 1807 .name = ARPT_ERROR_TARGET,
1800 .target = arpt_error, 1808 .target = arpt_error,
1801 .targetsize = ARPT_FUNCTION_MAXNAMELEN, 1809 .targetsize = ARPT_FUNCTION_MAXNAMELEN,
1802 .family = NF_ARP, 1810 .family = NFPROTO_ARP,
1803}; 1811};
1804 1812
1805static struct nf_sockopt_ops arpt_sockopts = { 1813static struct nf_sockopt_ops arpt_sockopts = {
@@ -1821,12 +1829,12 @@ static struct nf_sockopt_ops arpt_sockopts = {
1821 1829
1822static int __net_init arp_tables_net_init(struct net *net) 1830static int __net_init arp_tables_net_init(struct net *net)
1823{ 1831{
1824 return xt_proto_init(net, NF_ARP); 1832 return xt_proto_init(net, NFPROTO_ARP);
1825} 1833}
1826 1834
1827static void __net_exit arp_tables_net_exit(struct net *net) 1835static void __net_exit arp_tables_net_exit(struct net *net)
1828{ 1836{
1829 xt_proto_fini(net, NF_ARP); 1837 xt_proto_fini(net, NFPROTO_ARP);
1830} 1838}
1831 1839
1832static struct pernet_operations arp_tables_net_ops = { 1840static struct pernet_operations arp_tables_net_ops = {
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index a385959d2655..b0d5b1d0a769 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -9,12 +9,9 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
9MODULE_DESCRIPTION("arptables arp payload mangle target"); 9MODULE_DESCRIPTION("arptables arp payload mangle target");
10 10
11static unsigned int 11static unsigned int
12target(struct sk_buff *skb, 12target(struct sk_buff *skb, const struct xt_target_param *par)
13 const struct net_device *in, const struct net_device *out,
14 unsigned int hooknum, const struct xt_target *target,
15 const void *targinfo)
16{ 13{
17 const struct arpt_mangle *mangle = targinfo; 14 const struct arpt_mangle *mangle = par->targinfo;
18 const struct arphdr *arp; 15 const struct arphdr *arp;
19 unsigned char *arpptr; 16 unsigned char *arpptr;
20 int pln, hln; 17 int pln, hln;
@@ -57,11 +54,9 @@ target(struct sk_buff *skb,
57 return mangle->target; 54 return mangle->target;
58} 55}
59 56
60static bool 57static bool checkentry(const struct xt_tgchk_param *par)
61checkentry(const char *tablename, const void *e, const struct xt_target *target,
62 void *targinfo, unsigned int hook_mask)
63{ 58{
64 const struct arpt_mangle *mangle = targinfo; 59 const struct arpt_mangle *mangle = par->targinfo;
65 60
66 if (mangle->flags & ~ARPT_MANGLE_MASK || 61 if (mangle->flags & ~ARPT_MANGLE_MASK ||
67 !(mangle->flags & ARPT_MANGLE_MASK)) 62 !(mangle->flags & ARPT_MANGLE_MASK))
@@ -75,7 +70,7 @@ checkentry(const char *tablename, const void *e, const struct xt_target *target,
75 70
76static struct xt_target arpt_mangle_reg __read_mostly = { 71static struct xt_target arpt_mangle_reg __read_mostly = {
77 .name = "mangle", 72 .name = "mangle",
78 .family = NF_ARP, 73 .family = NFPROTO_ARP,
79 .target = target, 74 .target = target,
80 .targetsize = sizeof(struct arpt_mangle), 75 .targetsize = sizeof(struct arpt_mangle),
81 .checkentry = checkentry, 76 .checkentry = checkentry,
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 082f5dd3156c..bee3d117661a 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -51,7 +51,7 @@ static struct xt_table packet_filter = {
51 .lock = __RW_LOCK_UNLOCKED(packet_filter.lock), 51 .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
52 .private = NULL, 52 .private = NULL,
53 .me = THIS_MODULE, 53 .me = THIS_MODULE,
54 .af = NF_ARP, 54 .af = NFPROTO_ARP,
55}; 55};
56 56
57/* The work comes in here from netfilter.c */ 57/* The work comes in here from netfilter.c */
@@ -89,21 +89,21 @@ static struct nf_hook_ops arpt_ops[] __read_mostly = {
89 { 89 {
90 .hook = arpt_in_hook, 90 .hook = arpt_in_hook,
91 .owner = THIS_MODULE, 91 .owner = THIS_MODULE,
92 .pf = NF_ARP, 92 .pf = NFPROTO_ARP,
93 .hooknum = NF_ARP_IN, 93 .hooknum = NF_ARP_IN,
94 .priority = NF_IP_PRI_FILTER, 94 .priority = NF_IP_PRI_FILTER,
95 }, 95 },
96 { 96 {
97 .hook = arpt_out_hook, 97 .hook = arpt_out_hook,
98 .owner = THIS_MODULE, 98 .owner = THIS_MODULE,
99 .pf = NF_ARP, 99 .pf = NFPROTO_ARP,
100 .hooknum = NF_ARP_OUT, 100 .hooknum = NF_ARP_OUT,
101 .priority = NF_IP_PRI_FILTER, 101 .priority = NF_IP_PRI_FILTER,
102 }, 102 },
103 { 103 {
104 .hook = arpt_forward_hook, 104 .hook = arpt_forward_hook,
105 .owner = THIS_MODULE, 105 .owner = THIS_MODULE,
106 .pf = NF_ARP, 106 .pf = NFPROTO_ARP,
107 .hooknum = NF_ARP_FORWARD, 107 .hooknum = NF_ARP_FORWARD,
108 .priority = NF_IP_PRI_FILTER, 108 .priority = NF_IP_PRI_FILTER,
109 }, 109 },
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 4e7c719445c2..213fb27debc1 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -171,31 +171,25 @@ ip_checkentry(const struct ipt_ip *ip)
171} 171}
172 172
173static unsigned int 173static unsigned int
174ipt_error(struct sk_buff *skb, 174ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
175 const struct net_device *in,
176 const struct net_device *out,
177 unsigned int hooknum,
178 const struct xt_target *target,
179 const void *targinfo)
180{ 175{
181 if (net_ratelimit()) 176 if (net_ratelimit())
182 printk("ip_tables: error: `%s'\n", (char *)targinfo); 177 printk("ip_tables: error: `%s'\n",
178 (const char *)par->targinfo);
183 179
184 return NF_DROP; 180 return NF_DROP;
185} 181}
186 182
187/* Performance critical - called for every packet */ 183/* Performance critical - called for every packet */
188static inline bool 184static inline bool
189do_match(struct ipt_entry_match *m, 185do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
190 const struct sk_buff *skb, 186 struct xt_match_param *par)
191 const struct net_device *in,
192 const struct net_device *out,
193 int offset,
194 bool *hotdrop)
195{ 187{
188 par->match = m->u.kernel.match;
189 par->matchinfo = m->data;
190
196 /* Stop iteration if it doesn't match */ 191 /* Stop iteration if it doesn't match */
197 if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data, 192 if (!m->u.kernel.match->match(skb, par))
198 offset, ip_hdrlen(skb), hotdrop))
199 return true; 193 return true;
200 else 194 else
201 return false; 195 return false;
@@ -326,7 +320,6 @@ ipt_do_table(struct sk_buff *skb,
326 struct xt_table *table) 320 struct xt_table *table)
327{ 321{
328 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 322 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
329 u_int16_t offset;
330 const struct iphdr *ip; 323 const struct iphdr *ip;
331 u_int16_t datalen; 324 u_int16_t datalen;
332 bool hotdrop = false; 325 bool hotdrop = false;
@@ -336,6 +329,8 @@ ipt_do_table(struct sk_buff *skb,
336 void *table_base; 329 void *table_base;
337 struct ipt_entry *e, *back; 330 struct ipt_entry *e, *back;
338 struct xt_table_info *private; 331 struct xt_table_info *private;
332 struct xt_match_param mtpar;
333 struct xt_target_param tgpar;
339 334
340 /* Initialization */ 335 /* Initialization */
341 ip = ip_hdr(skb); 336 ip = ip_hdr(skb);
@@ -348,7 +343,13 @@ ipt_do_table(struct sk_buff *skb,
348 * things we don't know, ie. tcp syn flag or ports). If the 343 * things we don't know, ie. tcp syn flag or ports). If the
349 * rule is also a fragment-specific rule, non-fragments won't 344 * rule is also a fragment-specific rule, non-fragments won't
350 * match it. */ 345 * match it. */
351 offset = ntohs(ip->frag_off) & IP_OFFSET; 346 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
347 mtpar.thoff = ip_hdrlen(skb);
348 mtpar.hotdrop = &hotdrop;
349 mtpar.in = tgpar.in = in;
350 mtpar.out = tgpar.out = out;
351 mtpar.family = tgpar.family = NFPROTO_IPV4;
352 tgpar.hooknum = hook;
352 353
353 read_lock_bh(&table->lock); 354 read_lock_bh(&table->lock);
354 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 355 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
@@ -362,12 +363,11 @@ ipt_do_table(struct sk_buff *skb,
362 do { 363 do {
363 IP_NF_ASSERT(e); 364 IP_NF_ASSERT(e);
364 IP_NF_ASSERT(back); 365 IP_NF_ASSERT(back);
365 if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) { 366 if (ip_packet_match(ip, indev, outdev,
367 &e->ip, mtpar.fragoff)) {
366 struct ipt_entry_target *t; 368 struct ipt_entry_target *t;
367 369
368 if (IPT_MATCH_ITERATE(e, do_match, 370 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
369 skb, in, out,
370 offset, &hotdrop) != 0)
371 goto no_match; 371 goto no_match;
372 372
373 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); 373 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
@@ -413,16 +413,14 @@ ipt_do_table(struct sk_buff *skb,
413 } else { 413 } else {
414 /* Targets which reenter must return 414 /* Targets which reenter must return
415 abs. verdicts */ 415 abs. verdicts */
416 tgpar.target = t->u.kernel.target;
417 tgpar.targinfo = t->data;
416#ifdef CONFIG_NETFILTER_DEBUG 418#ifdef CONFIG_NETFILTER_DEBUG
417 ((struct ipt_entry *)table_base)->comefrom 419 ((struct ipt_entry *)table_base)->comefrom
418 = 0xeeeeeeec; 420 = 0xeeeeeeec;
419#endif 421#endif
420 verdict = t->u.kernel.target->target(skb, 422 verdict = t->u.kernel.target->target(skb,
421 in, out, 423 &tgpar);
422 hook,
423 t->u.kernel.target,
424 t->data);
425
426#ifdef CONFIG_NETFILTER_DEBUG 424#ifdef CONFIG_NETFILTER_DEBUG
427 if (((struct ipt_entry *)table_base)->comefrom 425 if (((struct ipt_entry *)table_base)->comefrom
428 != 0xeeeeeeec 426 != 0xeeeeeeec
@@ -575,12 +573,17 @@ mark_source_chains(struct xt_table_info *newinfo,
575static int 573static int
576cleanup_match(struct ipt_entry_match *m, unsigned int *i) 574cleanup_match(struct ipt_entry_match *m, unsigned int *i)
577{ 575{
576 struct xt_mtdtor_param par;
577
578 if (i && (*i)-- == 0) 578 if (i && (*i)-- == 0)
579 return 1; 579 return 1;
580 580
581 if (m->u.kernel.match->destroy) 581 par.match = m->u.kernel.match;
582 m->u.kernel.match->destroy(m->u.kernel.match, m->data); 582 par.matchinfo = m->data;
583 module_put(m->u.kernel.match->me); 583 par.family = NFPROTO_IPV4;
584 if (par.match->destroy != NULL)
585 par.match->destroy(&par);
586 module_put(par.match->me);
584 return 0; 587 return 0;
585} 588}
586 589
@@ -606,34 +609,28 @@ check_entry(struct ipt_entry *e, const char *name)
606} 609}
607 610
608static int 611static int
609check_match(struct ipt_entry_match *m, const char *name, 612check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
610 const struct ipt_ip *ip, 613 unsigned int *i)
611 unsigned int hookmask, unsigned int *i)
612{ 614{
613 struct xt_match *match; 615 const struct ipt_ip *ip = par->entryinfo;
614 int ret; 616 int ret;
615 617
616 match = m->u.kernel.match; 618 par->match = m->u.kernel.match;
617 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m), 619 par->matchinfo = m->data;
618 name, hookmask, ip->proto, 620
619 ip->invflags & IPT_INV_PROTO); 621 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
620 if (!ret && m->u.kernel.match->checkentry 622 ip->proto, ip->invflags & IPT_INV_PROTO);
621 && !m->u.kernel.match->checkentry(name, ip, match, m->data, 623 if (ret < 0) {
622 hookmask)) {
623 duprintf("ip_tables: check failed for `%s'.\n", 624 duprintf("ip_tables: check failed for `%s'.\n",
624 m->u.kernel.match->name); 625 par.match->name);
625 ret = -EINVAL; 626 return ret;
626 } 627 }
627 if (!ret) 628 ++*i;
628 (*i)++; 629 return 0;
629 return ret;
630} 630}
631 631
632static int 632static int
633find_check_match(struct ipt_entry_match *m, 633find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
634 const char *name,
635 const struct ipt_ip *ip,
636 unsigned int hookmask,
637 unsigned int *i) 634 unsigned int *i)
638{ 635{
639 struct xt_match *match; 636 struct xt_match *match;
@@ -648,7 +645,7 @@ find_check_match(struct ipt_entry_match *m,
648 } 645 }
649 m->u.kernel.match = match; 646 m->u.kernel.match = match;
650 647
651 ret = check_match(m, name, ip, hookmask, i); 648 ret = check_match(m, par, i);
652 if (ret) 649 if (ret)
653 goto err; 650 goto err;
654 651
@@ -660,23 +657,25 @@ err:
660 657
661static int check_target(struct ipt_entry *e, const char *name) 658static int check_target(struct ipt_entry *e, const char *name)
662{ 659{
663 struct ipt_entry_target *t; 660 struct ipt_entry_target *t = ipt_get_target(e);
664 struct xt_target *target; 661 struct xt_tgchk_param par = {
662 .table = name,
663 .entryinfo = e,
664 .target = t->u.kernel.target,
665 .targinfo = t->data,
666 .hook_mask = e->comefrom,
667 .family = NFPROTO_IPV4,
668 };
665 int ret; 669 int ret;
666 670
667 t = ipt_get_target(e); 671 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
668 target = t->u.kernel.target; 672 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
669 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), 673 if (ret < 0) {
670 name, e->comefrom, e->ip.proto,
671 e->ip.invflags & IPT_INV_PROTO);
672 if (!ret && t->u.kernel.target->checkentry
673 && !t->u.kernel.target->checkentry(name, e, target, t->data,
674 e->comefrom)) {
675 duprintf("ip_tables: check failed for `%s'.\n", 674 duprintf("ip_tables: check failed for `%s'.\n",
676 t->u.kernel.target->name); 675 t->u.kernel.target->name);
677 ret = -EINVAL; 676 return ret;
678 } 677 }
679 return ret; 678 return 0;
680} 679}
681 680
682static int 681static int
@@ -687,14 +686,18 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
687 struct xt_target *target; 686 struct xt_target *target;
688 int ret; 687 int ret;
689 unsigned int j; 688 unsigned int j;
689 struct xt_mtchk_param mtpar;
690 690
691 ret = check_entry(e, name); 691 ret = check_entry(e, name);
692 if (ret) 692 if (ret)
693 return ret; 693 return ret;
694 694
695 j = 0; 695 j = 0;
696 ret = IPT_MATCH_ITERATE(e, find_check_match, name, &e->ip, 696 mtpar.table = name;
697 e->comefrom, &j); 697 mtpar.entryinfo = &e->ip;
698 mtpar.hook_mask = e->comefrom;
699 mtpar.family = NFPROTO_IPV4;
700 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
698 if (ret != 0) 701 if (ret != 0)
699 goto cleanup_matches; 702 goto cleanup_matches;
700 703
@@ -769,6 +772,7 @@ check_entry_size_and_hooks(struct ipt_entry *e,
769static int 772static int
770cleanup_entry(struct ipt_entry *e, unsigned int *i) 773cleanup_entry(struct ipt_entry *e, unsigned int *i)
771{ 774{
775 struct xt_tgdtor_param par;
772 struct ipt_entry_target *t; 776 struct ipt_entry_target *t;
773 777
774 if (i && (*i)-- == 0) 778 if (i && (*i)-- == 0)
@@ -777,9 +781,13 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
777 /* Cleanup all matches */ 781 /* Cleanup all matches */
778 IPT_MATCH_ITERATE(e, cleanup_match, NULL); 782 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
779 t = ipt_get_target(e); 783 t = ipt_get_target(e);
780 if (t->u.kernel.target->destroy) 784
781 t->u.kernel.target->destroy(t->u.kernel.target, t->data); 785 par.target = t->u.kernel.target;
782 module_put(t->u.kernel.target->me); 786 par.targinfo = t->data;
787 par.family = NFPROTO_IPV4;
788 if (par.target->destroy != NULL)
789 par.target->destroy(&par);
790 module_put(par.target->me);
783 return 0; 791 return 0;
784} 792}
785 793
@@ -1648,12 +1656,16 @@ static int
1648compat_check_entry(struct ipt_entry *e, const char *name, 1656compat_check_entry(struct ipt_entry *e, const char *name,
1649 unsigned int *i) 1657 unsigned int *i)
1650{ 1658{
1659 struct xt_mtchk_param mtpar;
1651 unsigned int j; 1660 unsigned int j;
1652 int ret; 1661 int ret;
1653 1662
1654 j = 0; 1663 j = 0;
1655 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, 1664 mtpar.table = name;
1656 e->comefrom, &j); 1665 mtpar.entryinfo = &e->ip;
1666 mtpar.hook_mask = e->comefrom;
1667 mtpar.family = NFPROTO_IPV4;
1668 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1657 if (ret) 1669 if (ret)
1658 goto cleanup_matches; 1670 goto cleanup_matches;
1659 1671
@@ -2121,30 +2133,23 @@ icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2121} 2133}
2122 2134
2123static bool 2135static bool
2124icmp_match(const struct sk_buff *skb, 2136icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2125 const struct net_device *in,
2126 const struct net_device *out,
2127 const struct xt_match *match,
2128 const void *matchinfo,
2129 int offset,
2130 unsigned int protoff,
2131 bool *hotdrop)
2132{ 2137{
2133 const struct icmphdr *ic; 2138 const struct icmphdr *ic;
2134 struct icmphdr _icmph; 2139 struct icmphdr _icmph;
2135 const struct ipt_icmp *icmpinfo = matchinfo; 2140 const struct ipt_icmp *icmpinfo = par->matchinfo;
2136 2141
2137 /* Must not be a fragment. */ 2142 /* Must not be a fragment. */
2138 if (offset) 2143 if (par->fragoff != 0)
2139 return false; 2144 return false;
2140 2145
2141 ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph); 2146 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2142 if (ic == NULL) { 2147 if (ic == NULL) {
2143 /* We've been asked to examine this packet, and we 2148 /* We've been asked to examine this packet, and we
2144 * can't. Hence, no choice but to drop. 2149 * can't. Hence, no choice but to drop.
2145 */ 2150 */
2146 duprintf("Dropping evil ICMP tinygram.\n"); 2151 duprintf("Dropping evil ICMP tinygram.\n");
2147 *hotdrop = true; 2152 *par->hotdrop = true;
2148 return false; 2153 return false;
2149 } 2154 }
2150 2155
@@ -2155,15 +2160,9 @@ icmp_match(const struct sk_buff *skb,
2155 !!(icmpinfo->invflags&IPT_ICMP_INV)); 2160 !!(icmpinfo->invflags&IPT_ICMP_INV));
2156} 2161}
2157 2162
2158/* Called when user tries to insert an entry of this type. */ 2163static bool icmp_checkentry(const struct xt_mtchk_param *par)
2159static bool
2160icmp_checkentry(const char *tablename,
2161 const void *entry,
2162 const struct xt_match *match,
2163 void *matchinfo,
2164 unsigned int hook_mask)
2165{ 2164{
2166 const struct ipt_icmp *icmpinfo = matchinfo; 2165 const struct ipt_icmp *icmpinfo = par->matchinfo;
2167 2166
2168 /* Must specify no unknown invflags */ 2167 /* Must specify no unknown invflags */
2169 return !(icmpinfo->invflags & ~IPT_ICMP_INV); 2168 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index fafe8ebb4c55..7ac1677419a9 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -281,11 +281,9 @@ clusterip_responsible(const struct clusterip_config *config, u_int32_t hash)
281 ***********************************************************************/ 281 ***********************************************************************/
282 282
283static unsigned int 283static unsigned int
284clusterip_tg(struct sk_buff *skb, const struct net_device *in, 284clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par)
285 const struct net_device *out, unsigned int hooknum,
286 const struct xt_target *target, const void *targinfo)
287{ 285{
288 const struct ipt_clusterip_tgt_info *cipinfo = targinfo; 286 const struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
289 struct nf_conn *ct; 287 struct nf_conn *ct;
290 enum ip_conntrack_info ctinfo; 288 enum ip_conntrack_info ctinfo;
291 u_int32_t hash; 289 u_int32_t hash;
@@ -349,13 +347,10 @@ clusterip_tg(struct sk_buff *skb, const struct net_device *in,
349 return XT_CONTINUE; 347 return XT_CONTINUE;
350} 348}
351 349
352static bool 350static bool clusterip_tg_check(const struct xt_tgchk_param *par)
353clusterip_tg_check(const char *tablename, const void *e_void,
354 const struct xt_target *target, void *targinfo,
355 unsigned int hook_mask)
356{ 351{
357 struct ipt_clusterip_tgt_info *cipinfo = targinfo; 352 struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
358 const struct ipt_entry *e = e_void; 353 const struct ipt_entry *e = par->entryinfo;
359 354
360 struct clusterip_config *config; 355 struct clusterip_config *config;
361 356
@@ -406,9 +401,9 @@ clusterip_tg_check(const char *tablename, const void *e_void,
406 } 401 }
407 cipinfo->config = config; 402 cipinfo->config = config;
408 403
409 if (nf_ct_l3proto_try_module_get(target->family) < 0) { 404 if (nf_ct_l3proto_try_module_get(par->target->family) < 0) {
410 printk(KERN_WARNING "can't load conntrack support for " 405 printk(KERN_WARNING "can't load conntrack support for "
411 "proto=%u\n", target->family); 406 "proto=%u\n", par->target->family);
412 return false; 407 return false;
413 } 408 }
414 409
@@ -416,9 +411,9 @@ clusterip_tg_check(const char *tablename, const void *e_void,
416} 411}
417 412
418/* drop reference count of cluster config when rule is deleted */ 413/* drop reference count of cluster config when rule is deleted */
419static void clusterip_tg_destroy(const struct xt_target *target, void *targinfo) 414static void clusterip_tg_destroy(const struct xt_tgdtor_param *par)
420{ 415{
421 const struct ipt_clusterip_tgt_info *cipinfo = targinfo; 416 const struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
422 417
423 /* if no more entries are referencing the config, remove it 418 /* if no more entries are referencing the config, remove it
424 * from the list and destroy the proc entry */ 419 * from the list and destroy the proc entry */
@@ -426,7 +421,7 @@ static void clusterip_tg_destroy(const struct xt_target *target, void *targinfo)
426 421
427 clusterip_config_put(cipinfo->config); 422 clusterip_config_put(cipinfo->config);
428 423
429 nf_ct_l3proto_module_put(target->family); 424 nf_ct_l3proto_module_put(par->target->family);
430} 425}
431 426
432#ifdef CONFIG_COMPAT 427#ifdef CONFIG_COMPAT
@@ -445,7 +440,7 @@ struct compat_ipt_clusterip_tgt_info
445 440
446static struct xt_target clusterip_tg_reg __read_mostly = { 441static struct xt_target clusterip_tg_reg __read_mostly = {
447 .name = "CLUSTERIP", 442 .name = "CLUSTERIP",
448 .family = AF_INET, 443 .family = NFPROTO_IPV4,
449 .target = clusterip_tg, 444 .target = clusterip_tg,
450 .checkentry = clusterip_tg_check, 445 .checkentry = clusterip_tg_check,
451 .destroy = clusterip_tg_destroy, 446 .destroy = clusterip_tg_destroy,
@@ -546,7 +541,7 @@ arp_mangle(unsigned int hook,
546 541
547static struct nf_hook_ops cip_arp_ops __read_mostly = { 542static struct nf_hook_ops cip_arp_ops __read_mostly = {
548 .hook = arp_mangle, 543 .hook = arp_mangle,
549 .pf = NF_ARP, 544 .pf = NFPROTO_ARP,
550 .hooknum = NF_ARP_OUT, 545 .hooknum = NF_ARP_OUT,
551 .priority = -1 546 .priority = -1
552}; 547};
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index d60139c134ca..f7e2fa0974dc 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -77,11 +77,9 @@ set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
77} 77}
78 78
79static unsigned int 79static unsigned int
80ecn_tg(struct sk_buff *skb, const struct net_device *in, 80ecn_tg(struct sk_buff *skb, const struct xt_target_param *par)
81 const struct net_device *out, unsigned int hooknum,
82 const struct xt_target *target, const void *targinfo)
83{ 81{
84 const struct ipt_ECN_info *einfo = targinfo; 82 const struct ipt_ECN_info *einfo = par->targinfo;
85 83
86 if (einfo->operation & IPT_ECN_OP_SET_IP) 84 if (einfo->operation & IPT_ECN_OP_SET_IP)
87 if (!set_ect_ip(skb, einfo)) 85 if (!set_ect_ip(skb, einfo))
@@ -95,13 +93,10 @@ ecn_tg(struct sk_buff *skb, const struct net_device *in,
95 return XT_CONTINUE; 93 return XT_CONTINUE;
96} 94}
97 95
98static bool 96static bool ecn_tg_check(const struct xt_tgchk_param *par)
99ecn_tg_check(const char *tablename, const void *e_void,
100 const struct xt_target *target, void *targinfo,
101 unsigned int hook_mask)
102{ 97{
103 const struct ipt_ECN_info *einfo = targinfo; 98 const struct ipt_ECN_info *einfo = par->targinfo;
104 const struct ipt_entry *e = e_void; 99 const struct ipt_entry *e = par->entryinfo;
105 100
106 if (einfo->operation & IPT_ECN_OP_MASK) { 101 if (einfo->operation & IPT_ECN_OP_MASK) {
107 printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", 102 printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
@@ -124,7 +119,7 @@ ecn_tg_check(const char *tablename, const void *e_void,
124 119
125static struct xt_target ecn_tg_reg __read_mostly = { 120static struct xt_target ecn_tg_reg __read_mostly = {
126 .name = "ECN", 121 .name = "ECN",
127 .family = AF_INET, 122 .family = NFPROTO_IPV4,
128 .target = ecn_tg, 123 .target = ecn_tg,
129 .targetsize = sizeof(struct ipt_ECN_info), 124 .targetsize = sizeof(struct ipt_ECN_info),
130 .table = "mangle", 125 .table = "mangle",
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 0af14137137b..fc6ce04a3e35 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -375,7 +375,7 @@ static struct nf_loginfo default_loginfo = {
375}; 375};
376 376
377static void 377static void
378ipt_log_packet(unsigned int pf, 378ipt_log_packet(u_int8_t pf,
379 unsigned int hooknum, 379 unsigned int hooknum,
380 const struct sk_buff *skb, 380 const struct sk_buff *skb,
381 const struct net_device *in, 381 const struct net_device *in,
@@ -426,28 +426,23 @@ ipt_log_packet(unsigned int pf,
426} 426}
427 427
428static unsigned int 428static unsigned int
429log_tg(struct sk_buff *skb, const struct net_device *in, 429log_tg(struct sk_buff *skb, const struct xt_target_param *par)
430 const struct net_device *out, unsigned int hooknum,
431 const struct xt_target *target, const void *targinfo)
432{ 430{
433 const struct ipt_log_info *loginfo = targinfo; 431 const struct ipt_log_info *loginfo = par->targinfo;
434 struct nf_loginfo li; 432 struct nf_loginfo li;
435 433
436 li.type = NF_LOG_TYPE_LOG; 434 li.type = NF_LOG_TYPE_LOG;
437 li.u.log.level = loginfo->level; 435 li.u.log.level = loginfo->level;
438 li.u.log.logflags = loginfo->logflags; 436 li.u.log.logflags = loginfo->logflags;
439 437
440 ipt_log_packet(PF_INET, hooknum, skb, in, out, &li, 438 ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, par->out, &li,
441 loginfo->prefix); 439 loginfo->prefix);
442 return XT_CONTINUE; 440 return XT_CONTINUE;
443} 441}
444 442
445static bool 443static bool log_tg_check(const struct xt_tgchk_param *par)
446log_tg_check(const char *tablename, const void *e,
447 const struct xt_target *target, void *targinfo,
448 unsigned int hook_mask)
449{ 444{
450 const struct ipt_log_info *loginfo = targinfo; 445 const struct ipt_log_info *loginfo = par->targinfo;
451 446
452 if (loginfo->level >= 8) { 447 if (loginfo->level >= 8) {
453 pr_debug("LOG: level %u >= 8\n", loginfo->level); 448 pr_debug("LOG: level %u >= 8\n", loginfo->level);
@@ -463,7 +458,7 @@ log_tg_check(const char *tablename, const void *e,
463 458
464static struct xt_target log_tg_reg __read_mostly = { 459static struct xt_target log_tg_reg __read_mostly = {
465 .name = "LOG", 460 .name = "LOG",
466 .family = AF_INET, 461 .family = NFPROTO_IPV4,
467 .target = log_tg, 462 .target = log_tg,
468 .targetsize = sizeof(struct ipt_log_info), 463 .targetsize = sizeof(struct ipt_log_info),
469 .checkentry = log_tg_check, 464 .checkentry = log_tg_check,
@@ -483,7 +478,7 @@ static int __init log_tg_init(void)
483 ret = xt_register_target(&log_tg_reg); 478 ret = xt_register_target(&log_tg_reg);
484 if (ret < 0) 479 if (ret < 0)
485 return ret; 480 return ret;
486 nf_log_register(PF_INET, &ipt_log_logger); 481 nf_log_register(NFPROTO_IPV4, &ipt_log_logger);
487 return 0; 482 return 0;
488} 483}
489 484
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 0841aefaa503..f389f60cb105 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -31,12 +31,9 @@ MODULE_DESCRIPTION("Xtables: automatic-address SNAT");
31static DEFINE_RWLOCK(masq_lock); 31static DEFINE_RWLOCK(masq_lock);
32 32
33/* FIXME: Multiple targets. --RR */ 33/* FIXME: Multiple targets. --RR */
34static bool 34static bool masquerade_tg_check(const struct xt_tgchk_param *par)
35masquerade_tg_check(const char *tablename, const void *e,
36 const struct xt_target *target, void *targinfo,
37 unsigned int hook_mask)
38{ 35{
39 const struct nf_nat_multi_range_compat *mr = targinfo; 36 const struct nf_nat_multi_range_compat *mr = par->targinfo;
40 37
41 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 38 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
42 pr_debug("masquerade_check: bad MAP_IPS.\n"); 39 pr_debug("masquerade_check: bad MAP_IPS.\n");
@@ -50,9 +47,7 @@ masquerade_tg_check(const char *tablename, const void *e,
50} 47}
51 48
52static unsigned int 49static unsigned int
53masquerade_tg(struct sk_buff *skb, const struct net_device *in, 50masquerade_tg(struct sk_buff *skb, const struct xt_target_param *par)
54 const struct net_device *out, unsigned int hooknum,
55 const struct xt_target *target, const void *targinfo)
56{ 51{
57 struct nf_conn *ct; 52 struct nf_conn *ct;
58 struct nf_conn_nat *nat; 53 struct nf_conn_nat *nat;
@@ -62,7 +57,7 @@ masquerade_tg(struct sk_buff *skb, const struct net_device *in,
62 const struct rtable *rt; 57 const struct rtable *rt;
63 __be32 newsrc; 58 __be32 newsrc;
64 59
65 NF_CT_ASSERT(hooknum == NF_INET_POST_ROUTING); 60 NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING);
66 61
67 ct = nf_ct_get(skb, &ctinfo); 62 ct = nf_ct_get(skb, &ctinfo);
68 nat = nfct_nat(ct); 63 nat = nfct_nat(ct);
@@ -76,16 +71,16 @@ masquerade_tg(struct sk_buff *skb, const struct net_device *in,
76 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0) 71 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
77 return NF_ACCEPT; 72 return NF_ACCEPT;
78 73
79 mr = targinfo; 74 mr = par->targinfo;
80 rt = skb->rtable; 75 rt = skb->rtable;
81 newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE); 76 newsrc = inet_select_addr(par->out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
82 if (!newsrc) { 77 if (!newsrc) {
83 printk("MASQUERADE: %s ate my IP address\n", out->name); 78 printk("MASQUERADE: %s ate my IP address\n", par->out->name);
84 return NF_DROP; 79 return NF_DROP;
85 } 80 }
86 81
87 write_lock_bh(&masq_lock); 82 write_lock_bh(&masq_lock);
88 nat->masq_index = out->ifindex; 83 nat->masq_index = par->out->ifindex;
89 write_unlock_bh(&masq_lock); 84 write_unlock_bh(&masq_lock);
90 85
91 /* Transfer from original range. */ 86 /* Transfer from original range. */
@@ -119,9 +114,7 @@ static int masq_device_event(struct notifier_block *this,
119 void *ptr) 114 void *ptr)
120{ 115{
121 const struct net_device *dev = ptr; 116 const struct net_device *dev = ptr;
122 117 struct net *net = dev_net(dev);
123 if (!net_eq(dev_net(dev), &init_net))
124 return NOTIFY_DONE;
125 118
126 if (event == NETDEV_DOWN) { 119 if (event == NETDEV_DOWN) {
127 /* Device was downed. Search entire table for 120 /* Device was downed. Search entire table for
@@ -129,7 +122,8 @@ static int masq_device_event(struct notifier_block *this,
129 and forget them. */ 122 and forget them. */
130 NF_CT_ASSERT(dev->ifindex != 0); 123 NF_CT_ASSERT(dev->ifindex != 0);
131 124
132 nf_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex); 125 nf_ct_iterate_cleanup(net, device_cmp,
126 (void *)(long)dev->ifindex);
133 } 127 }
134 128
135 return NOTIFY_DONE; 129 return NOTIFY_DONE;
@@ -153,7 +147,7 @@ static struct notifier_block masq_inet_notifier = {
153 147
154static struct xt_target masquerade_tg_reg __read_mostly = { 148static struct xt_target masquerade_tg_reg __read_mostly = {
155 .name = "MASQUERADE", 149 .name = "MASQUERADE",
156 .family = AF_INET, 150 .family = NFPROTO_IPV4,
157 .target = masquerade_tg, 151 .target = masquerade_tg,
158 .targetsize = sizeof(struct nf_nat_multi_range_compat), 152 .targetsize = sizeof(struct nf_nat_multi_range_compat),
159 .table = "nat", 153 .table = "nat",
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 6739abfd1521..7c29582d4ec8 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -22,12 +22,9 @@ MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); 22MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
23MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); 23MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets");
24 24
25static bool 25static bool netmap_tg_check(const struct xt_tgchk_param *par)
26netmap_tg_check(const char *tablename, const void *e,
27 const struct xt_target *target, void *targinfo,
28 unsigned int hook_mask)
29{ 26{
30 const struct nf_nat_multi_range_compat *mr = targinfo; 27 const struct nf_nat_multi_range_compat *mr = par->targinfo;
31 28
32 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { 29 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
33 pr_debug("NETMAP:check: bad MAP_IPS.\n"); 30 pr_debug("NETMAP:check: bad MAP_IPS.\n");
@@ -41,24 +38,23 @@ netmap_tg_check(const char *tablename, const void *e,
41} 38}
42 39
43static unsigned int 40static unsigned int
44netmap_tg(struct sk_buff *skb, const struct net_device *in, 41netmap_tg(struct sk_buff *skb, const struct xt_target_param *par)
45 const struct net_device *out, unsigned int hooknum,
46 const struct xt_target *target, const void *targinfo)
47{ 42{
48 struct nf_conn *ct; 43 struct nf_conn *ct;
49 enum ip_conntrack_info ctinfo; 44 enum ip_conntrack_info ctinfo;
50 __be32 new_ip, netmask; 45 __be32 new_ip, netmask;
51 const struct nf_nat_multi_range_compat *mr = targinfo; 46 const struct nf_nat_multi_range_compat *mr = par->targinfo;
52 struct nf_nat_range newrange; 47 struct nf_nat_range newrange;
53 48
54 NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING 49 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
55 || hooknum == NF_INET_POST_ROUTING 50 par->hooknum == NF_INET_POST_ROUTING ||
56 || hooknum == NF_INET_LOCAL_OUT); 51 par->hooknum == NF_INET_LOCAL_OUT);
57 ct = nf_ct_get(skb, &ctinfo); 52 ct = nf_ct_get(skb, &ctinfo);
58 53
59 netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); 54 netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
60 55
61 if (hooknum == NF_INET_PRE_ROUTING || hooknum == NF_INET_LOCAL_OUT) 56 if (par->hooknum == NF_INET_PRE_ROUTING ||
57 par->hooknum == NF_INET_LOCAL_OUT)
62 new_ip = ip_hdr(skb)->daddr & ~netmask; 58 new_ip = ip_hdr(skb)->daddr & ~netmask;
63 else 59 else
64 new_ip = ip_hdr(skb)->saddr & ~netmask; 60 new_ip = ip_hdr(skb)->saddr & ~netmask;
@@ -70,12 +66,12 @@ netmap_tg(struct sk_buff *skb, const struct net_device *in,
70 mr->range[0].min, mr->range[0].max }); 66 mr->range[0].min, mr->range[0].max });
71 67
72 /* Hand modified range to generic setup. */ 68 /* Hand modified range to generic setup. */
73 return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(hooknum)); 69 return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
74} 70}
75 71
76static struct xt_target netmap_tg_reg __read_mostly = { 72static struct xt_target netmap_tg_reg __read_mostly = {
77 .name = "NETMAP", 73 .name = "NETMAP",
78 .family = AF_INET, 74 .family = NFPROTO_IPV4,
79 .target = netmap_tg, 75 .target = netmap_tg,
80 .targetsize = sizeof(struct nf_nat_multi_range_compat), 76 .targetsize = sizeof(struct nf_nat_multi_range_compat),
81 .table = "nat", 77 .table = "nat",
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 5c6292449d13..698e5e78685b 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -26,12 +26,9 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
26MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); 26MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
27 27
28/* FIXME: Take multiple ranges --RR */ 28/* FIXME: Take multiple ranges --RR */
29static bool 29static bool redirect_tg_check(const struct xt_tgchk_param *par)
30redirect_tg_check(const char *tablename, const void *e,
31 const struct xt_target *target, void *targinfo,
32 unsigned int hook_mask)
33{ 30{
34 const struct nf_nat_multi_range_compat *mr = targinfo; 31 const struct nf_nat_multi_range_compat *mr = par->targinfo;
35 32
36 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 33 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
37 pr_debug("redirect_check: bad MAP_IPS.\n"); 34 pr_debug("redirect_check: bad MAP_IPS.\n");
@@ -45,24 +42,22 @@ redirect_tg_check(const char *tablename, const void *e,
45} 42}
46 43
47static unsigned int 44static unsigned int
48redirect_tg(struct sk_buff *skb, const struct net_device *in, 45redirect_tg(struct sk_buff *skb, const struct xt_target_param *par)
49 const struct net_device *out, unsigned int hooknum,
50 const struct xt_target *target, const void *targinfo)
51{ 46{
52 struct nf_conn *ct; 47 struct nf_conn *ct;
53 enum ip_conntrack_info ctinfo; 48 enum ip_conntrack_info ctinfo;
54 __be32 newdst; 49 __be32 newdst;
55 const struct nf_nat_multi_range_compat *mr = targinfo; 50 const struct nf_nat_multi_range_compat *mr = par->targinfo;
56 struct nf_nat_range newrange; 51 struct nf_nat_range newrange;
57 52
58 NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING 53 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
59 || hooknum == NF_INET_LOCAL_OUT); 54 par->hooknum == NF_INET_LOCAL_OUT);
60 55
61 ct = nf_ct_get(skb, &ctinfo); 56 ct = nf_ct_get(skb, &ctinfo);
62 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); 57 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
63 58
64 /* Local packets: make them go to loopback */ 59 /* Local packets: make them go to loopback */
65 if (hooknum == NF_INET_LOCAL_OUT) 60 if (par->hooknum == NF_INET_LOCAL_OUT)
66 newdst = htonl(0x7F000001); 61 newdst = htonl(0x7F000001);
67 else { 62 else {
68 struct in_device *indev; 63 struct in_device *indev;
@@ -92,7 +87,7 @@ redirect_tg(struct sk_buff *skb, const struct net_device *in,
92 87
93static struct xt_target redirect_tg_reg __read_mostly = { 88static struct xt_target redirect_tg_reg __read_mostly = {
94 .name = "REDIRECT", 89 .name = "REDIRECT",
95 .family = AF_INET, 90 .family = NFPROTO_IPV4,
96 .target = redirect_tg, 91 .target = redirect_tg,
97 .targetsize = sizeof(struct nf_nat_multi_range_compat), 92 .targetsize = sizeof(struct nf_nat_multi_range_compat),
98 .table = "nat", 93 .table = "nat",
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 2639872849da..0b4b6e0ff2b9 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -136,11 +136,9 @@ static inline void send_unreach(struct sk_buff *skb_in, int code)
136} 136}
137 137
138static unsigned int 138static unsigned int
139reject_tg(struct sk_buff *skb, const struct net_device *in, 139reject_tg(struct sk_buff *skb, const struct xt_target_param *par)
140 const struct net_device *out, unsigned int hooknum,
141 const struct xt_target *target, const void *targinfo)
142{ 140{
143 const struct ipt_reject_info *reject = targinfo; 141 const struct ipt_reject_info *reject = par->targinfo;
144 142
145 /* WARNING: This code causes reentry within iptables. 143 /* WARNING: This code causes reentry within iptables.
146 This means that the iptables jump stack is now crap. We 144 This means that the iptables jump stack is now crap. We
@@ -168,7 +166,7 @@ reject_tg(struct sk_buff *skb, const struct net_device *in,
168 send_unreach(skb, ICMP_PKT_FILTERED); 166 send_unreach(skb, ICMP_PKT_FILTERED);
169 break; 167 break;
170 case IPT_TCP_RESET: 168 case IPT_TCP_RESET:
171 send_reset(skb, hooknum); 169 send_reset(skb, par->hooknum);
172 case IPT_ICMP_ECHOREPLY: 170 case IPT_ICMP_ECHOREPLY:
173 /* Doesn't happen. */ 171 /* Doesn't happen. */
174 break; 172 break;
@@ -177,13 +175,10 @@ reject_tg(struct sk_buff *skb, const struct net_device *in,
177 return NF_DROP; 175 return NF_DROP;
178} 176}
179 177
180static bool 178static bool reject_tg_check(const struct xt_tgchk_param *par)
181reject_tg_check(const char *tablename, const void *e_void,
182 const struct xt_target *target, void *targinfo,
183 unsigned int hook_mask)
184{ 179{
185 const struct ipt_reject_info *rejinfo = targinfo; 180 const struct ipt_reject_info *rejinfo = par->targinfo;
186 const struct ipt_entry *e = e_void; 181 const struct ipt_entry *e = par->entryinfo;
187 182
188 if (rejinfo->with == IPT_ICMP_ECHOREPLY) { 183 if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
189 printk("ipt_REJECT: ECHOREPLY no longer supported.\n"); 184 printk("ipt_REJECT: ECHOREPLY no longer supported.\n");
@@ -201,7 +196,7 @@ reject_tg_check(const char *tablename, const void *e_void,
201 196
202static struct xt_target reject_tg_reg __read_mostly = { 197static struct xt_target reject_tg_reg __read_mostly = {
203 .name = "REJECT", 198 .name = "REJECT",
204 .family = AF_INET, 199 .family = NFPROTO_IPV4,
205 .target = reject_tg, 200 .target = reject_tg,
206 .targetsize = sizeof(struct ipt_reject_info), 201 .targetsize = sizeof(struct ipt_reject_info),
207 .table = "filter", 202 .table = "filter",
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index 30eed65e7338..6d76aae90cc0 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -20,12 +20,10 @@ MODULE_DESCRIPTION("Xtables: IPv4 TTL field modification target");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21 21
22static unsigned int 22static unsigned int
23ttl_tg(struct sk_buff *skb, const struct net_device *in, 23ttl_tg(struct sk_buff *skb, const struct xt_target_param *par)
24 const struct net_device *out, unsigned int hooknum,
25 const struct xt_target *target, const void *targinfo)
26{ 24{
27 struct iphdr *iph; 25 struct iphdr *iph;
28 const struct ipt_TTL_info *info = targinfo; 26 const struct ipt_TTL_info *info = par->targinfo;
29 int new_ttl; 27 int new_ttl;
30 28
31 if (!skb_make_writable(skb, skb->len)) 29 if (!skb_make_writable(skb, skb->len))
@@ -61,12 +59,9 @@ ttl_tg(struct sk_buff *skb, const struct net_device *in,
61 return XT_CONTINUE; 59 return XT_CONTINUE;
62} 60}
63 61
64static bool 62static bool ttl_tg_check(const struct xt_tgchk_param *par)
65ttl_tg_check(const char *tablename, const void *e,
66 const struct xt_target *target, void *targinfo,
67 unsigned int hook_mask)
68{ 63{
69 const struct ipt_TTL_info *info = targinfo; 64 const struct ipt_TTL_info *info = par->targinfo;
70 65
71 if (info->mode > IPT_TTL_MAXMODE) { 66 if (info->mode > IPT_TTL_MAXMODE) {
72 printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", 67 printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
@@ -80,7 +75,7 @@ ttl_tg_check(const char *tablename, const void *e,
80 75
81static struct xt_target ttl_tg_reg __read_mostly = { 76static struct xt_target ttl_tg_reg __read_mostly = {
82 .name = "TTL", 77 .name = "TTL",
83 .family = AF_INET, 78 .family = NFPROTO_IPV4,
84 .target = ttl_tg, 79 .target = ttl_tg,
85 .targetsize = sizeof(struct ipt_TTL_info), 80 .targetsize = sizeof(struct ipt_TTL_info),
86 .table = "mangle", 81 .table = "mangle",
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index b192756c6d0d..18a2826b57c6 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -281,18 +281,14 @@ alloc_failure:
281} 281}
282 282
283static unsigned int 283static unsigned int
284ulog_tg(struct sk_buff *skb, const struct net_device *in, 284ulog_tg(struct sk_buff *skb, const struct xt_target_param *par)
285 const struct net_device *out, unsigned int hooknum,
286 const struct xt_target *target, const void *targinfo)
287{ 285{
288 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; 286 ipt_ulog_packet(par->hooknum, skb, par->in, par->out,
289 287 par->targinfo, NULL);
290 ipt_ulog_packet(hooknum, skb, in, out, loginfo, NULL);
291
292 return XT_CONTINUE; 288 return XT_CONTINUE;
293} 289}
294 290
295static void ipt_logfn(unsigned int pf, 291static void ipt_logfn(u_int8_t pf,
296 unsigned int hooknum, 292 unsigned int hooknum,
297 const struct sk_buff *skb, 293 const struct sk_buff *skb,
298 const struct net_device *in, 294 const struct net_device *in,
@@ -317,12 +313,9 @@ static void ipt_logfn(unsigned int pf,
317 ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); 313 ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
318} 314}
319 315
320static bool 316static bool ulog_tg_check(const struct xt_tgchk_param *par)
321ulog_tg_check(const char *tablename, const void *e,
322 const struct xt_target *target, void *targinfo,
323 unsigned int hookmask)
324{ 317{
325 const struct ipt_ulog_info *loginfo = targinfo; 318 const struct ipt_ulog_info *loginfo = par->targinfo;
326 319
327 if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { 320 if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
328 pr_debug("ipt_ULOG: prefix term %i\n", 321 pr_debug("ipt_ULOG: prefix term %i\n",
@@ -374,7 +367,7 @@ static int ulog_tg_compat_to_user(void __user *dst, void *src)
374 367
375static struct xt_target ulog_tg_reg __read_mostly = { 368static struct xt_target ulog_tg_reg __read_mostly = {
376 .name = "ULOG", 369 .name = "ULOG",
377 .family = AF_INET, 370 .family = NFPROTO_IPV4,
378 .target = ulog_tg, 371 .target = ulog_tg,
379 .targetsize = sizeof(struct ipt_ulog_info), 372 .targetsize = sizeof(struct ipt_ulog_info),
380 .checkentry = ulog_tg_check, 373 .checkentry = ulog_tg_check,
@@ -419,7 +412,7 @@ static int __init ulog_tg_init(void)
419 return ret; 412 return ret;
420 } 413 }
421 if (nflog) 414 if (nflog)
422 nf_log_register(PF_INET, &ipt_ulog_logger); 415 nf_log_register(NFPROTO_IPV4, &ipt_ulog_logger);
423 416
424 return 0; 417 return 0;
425} 418}
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index 462a22c97877..88762f02779d 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -30,12 +30,9 @@ static inline bool match_type(const struct net_device *dev, __be32 addr,
30} 30}
31 31
32static bool 32static bool
33addrtype_mt_v0(const struct sk_buff *skb, const struct net_device *in, 33addrtype_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
34 const struct net_device *out, const struct xt_match *match,
35 const void *matchinfo, int offset, unsigned int protoff,
36 bool *hotdrop)
37{ 34{
38 const struct ipt_addrtype_info *info = matchinfo; 35 const struct ipt_addrtype_info *info = par->matchinfo;
39 const struct iphdr *iph = ip_hdr(skb); 36 const struct iphdr *iph = ip_hdr(skb);
40 bool ret = true; 37 bool ret = true;
41 38
@@ -50,20 +47,17 @@ addrtype_mt_v0(const struct sk_buff *skb, const struct net_device *in,
50} 47}
51 48
52static bool 49static bool
53addrtype_mt_v1(const struct sk_buff *skb, const struct net_device *in, 50addrtype_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par)
54 const struct net_device *out, const struct xt_match *match,
55 const void *matchinfo, int offset, unsigned int protoff,
56 bool *hotdrop)
57{ 51{
58 const struct ipt_addrtype_info_v1 *info = matchinfo; 52 const struct ipt_addrtype_info_v1 *info = par->matchinfo;
59 const struct iphdr *iph = ip_hdr(skb); 53 const struct iphdr *iph = ip_hdr(skb);
60 const struct net_device *dev = NULL; 54 const struct net_device *dev = NULL;
61 bool ret = true; 55 bool ret = true;
62 56
63 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) 57 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN)
64 dev = in; 58 dev = par->in;
65 else if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) 59 else if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT)
66 dev = out; 60 dev = par->out;
67 61
68 if (info->source) 62 if (info->source)
69 ret &= match_type(dev, iph->saddr, info->source) ^ 63 ret &= match_type(dev, iph->saddr, info->source) ^
@@ -74,12 +68,9 @@ addrtype_mt_v1(const struct sk_buff *skb, const struct net_device *in,
74 return ret; 68 return ret;
75} 69}
76 70
77static bool 71static bool addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par)
78addrtype_mt_checkentry_v1(const char *tablename, const void *ip_void,
79 const struct xt_match *match, void *matchinfo,
80 unsigned int hook_mask)
81{ 72{
82 struct ipt_addrtype_info_v1 *info = matchinfo; 73 struct ipt_addrtype_info_v1 *info = par->matchinfo;
83 74
84 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN && 75 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN &&
85 info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { 76 info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
@@ -88,14 +79,16 @@ addrtype_mt_checkentry_v1(const char *tablename, const void *ip_void,
88 return false; 79 return false;
89 } 80 }
90 81
91 if (hook_mask & (1 << NF_INET_PRE_ROUTING | 1 << NF_INET_LOCAL_IN) && 82 if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
83 (1 << NF_INET_LOCAL_IN)) &&
92 info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { 84 info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
93 printk(KERN_ERR "ipt_addrtype: output interface limitation " 85 printk(KERN_ERR "ipt_addrtype: output interface limitation "
94 "not valid in PRE_ROUTING and INPUT\n"); 86 "not valid in PRE_ROUTING and INPUT\n");
95 return false; 87 return false;
96 } 88 }
97 89
98 if (hook_mask & (1 << NF_INET_POST_ROUTING | 1 << NF_INET_LOCAL_OUT) && 90 if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
91 (1 << NF_INET_LOCAL_OUT)) &&
99 info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { 92 info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
100 printk(KERN_ERR "ipt_addrtype: input interface limitation " 93 printk(KERN_ERR "ipt_addrtype: input interface limitation "
101 "not valid in POST_ROUTING and OUTPUT\n"); 94 "not valid in POST_ROUTING and OUTPUT\n");
@@ -108,14 +101,14 @@ addrtype_mt_checkentry_v1(const char *tablename, const void *ip_void,
108static struct xt_match addrtype_mt_reg[] __read_mostly = { 101static struct xt_match addrtype_mt_reg[] __read_mostly = {
109 { 102 {
110 .name = "addrtype", 103 .name = "addrtype",
111 .family = AF_INET, 104 .family = NFPROTO_IPV4,
112 .match = addrtype_mt_v0, 105 .match = addrtype_mt_v0,
113 .matchsize = sizeof(struct ipt_addrtype_info), 106 .matchsize = sizeof(struct ipt_addrtype_info),
114 .me = THIS_MODULE 107 .me = THIS_MODULE
115 }, 108 },
116 { 109 {
117 .name = "addrtype", 110 .name = "addrtype",
118 .family = AF_INET, 111 .family = NFPROTO_IPV4,
119 .revision = 1, 112 .revision = 1,
120 .match = addrtype_mt_v1, 113 .match = addrtype_mt_v1,
121 .checkentry = addrtype_mt_checkentry_v1, 114 .checkentry = addrtype_mt_checkentry_v1,
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index e977989629c7..0104c0b399de 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -36,27 +36,23 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
36 return r; 36 return r;
37} 37}
38 38
39static bool 39static bool ah_mt(const struct sk_buff *skb, const struct xt_match_param *par)
40ah_mt(const struct sk_buff *skb, const struct net_device *in,
41 const struct net_device *out, const struct xt_match *match,
42 const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
43{ 40{
44 struct ip_auth_hdr _ahdr; 41 struct ip_auth_hdr _ahdr;
45 const struct ip_auth_hdr *ah; 42 const struct ip_auth_hdr *ah;
46 const struct ipt_ah *ahinfo = matchinfo; 43 const struct ipt_ah *ahinfo = par->matchinfo;
47 44
48 /* Must not be a fragment. */ 45 /* Must not be a fragment. */
49 if (offset) 46 if (par->fragoff != 0)
50 return false; 47 return false;
51 48
52 ah = skb_header_pointer(skb, protoff, 49 ah = skb_header_pointer(skb, par->thoff, sizeof(_ahdr), &_ahdr);
53 sizeof(_ahdr), &_ahdr);
54 if (ah == NULL) { 50 if (ah == NULL) {
55 /* We've been asked to examine this packet, and we 51 /* We've been asked to examine this packet, and we
56 * can't. Hence, no choice but to drop. 52 * can't. Hence, no choice but to drop.
57 */ 53 */
58 duprintf("Dropping evil AH tinygram.\n"); 54 duprintf("Dropping evil AH tinygram.\n");
59 *hotdrop = true; 55 *par->hotdrop = true;
60 return 0; 56 return 0;
61 } 57 }
62 58
@@ -65,13 +61,9 @@ ah_mt(const struct sk_buff *skb, const struct net_device *in,
65 !!(ahinfo->invflags & IPT_AH_INV_SPI)); 61 !!(ahinfo->invflags & IPT_AH_INV_SPI));
66} 62}
67 63
68/* Called when user tries to insert an entry of this type. */ 64static bool ah_mt_check(const struct xt_mtchk_param *par)
69static bool
70ah_mt_check(const char *tablename, const void *ip_void,
71 const struct xt_match *match, void *matchinfo,
72 unsigned int hook_mask)
73{ 65{
74 const struct ipt_ah *ahinfo = matchinfo; 66 const struct ipt_ah *ahinfo = par->matchinfo;
75 67
76 /* Must specify no unknown invflags */ 68 /* Must specify no unknown invflags */
77 if (ahinfo->invflags & ~IPT_AH_INV_MASK) { 69 if (ahinfo->invflags & ~IPT_AH_INV_MASK) {
@@ -83,7 +75,7 @@ ah_mt_check(const char *tablename, const void *ip_void,
83 75
84static struct xt_match ah_mt_reg __read_mostly = { 76static struct xt_match ah_mt_reg __read_mostly = {
85 .name = "ah", 77 .name = "ah",
86 .family = AF_INET, 78 .family = NFPROTO_IPV4,
87 .match = ah_mt, 79 .match = ah_mt,
88 .matchsize = sizeof(struct ipt_ah), 80 .matchsize = sizeof(struct ipt_ah),
89 .proto = IPPROTO_AH, 81 .proto = IPPROTO_AH,
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index 749de8284ce5..6289b64144c6 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -67,12 +67,9 @@ static inline bool match_tcp(const struct sk_buff *skb,
67 return true; 67 return true;
68} 68}
69 69
70static bool 70static bool ecn_mt(const struct sk_buff *skb, const struct xt_match_param *par)
71ecn_mt(const struct sk_buff *skb, const struct net_device *in,
72 const struct net_device *out, const struct xt_match *match,
73 const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
74{ 71{
75 const struct ipt_ecn_info *info = matchinfo; 72 const struct ipt_ecn_info *info = par->matchinfo;
76 73
77 if (info->operation & IPT_ECN_OP_MATCH_IP) 74 if (info->operation & IPT_ECN_OP_MATCH_IP)
78 if (!match_ip(skb, info)) 75 if (!match_ip(skb, info))
@@ -81,20 +78,17 @@ ecn_mt(const struct sk_buff *skb, const struct net_device *in,
81 if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { 78 if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
82 if (ip_hdr(skb)->protocol != IPPROTO_TCP) 79 if (ip_hdr(skb)->protocol != IPPROTO_TCP)
83 return false; 80 return false;
84 if (!match_tcp(skb, info, hotdrop)) 81 if (!match_tcp(skb, info, par->hotdrop))
85 return false; 82 return false;
86 } 83 }
87 84
88 return true; 85 return true;
89} 86}
90 87
91static bool 88static bool ecn_mt_check(const struct xt_mtchk_param *par)
92ecn_mt_check(const char *tablename, const void *ip_void,
93 const struct xt_match *match, void *matchinfo,
94 unsigned int hook_mask)
95{ 89{
96 const struct ipt_ecn_info *info = matchinfo; 90 const struct ipt_ecn_info *info = par->matchinfo;
97 const struct ipt_ip *ip = ip_void; 91 const struct ipt_ip *ip = par->entryinfo;
98 92
99 if (info->operation & IPT_ECN_OP_MATCH_MASK) 93 if (info->operation & IPT_ECN_OP_MATCH_MASK)
100 return false; 94 return false;
@@ -114,7 +108,7 @@ ecn_mt_check(const char *tablename, const void *ip_void,
114 108
115static struct xt_match ecn_mt_reg __read_mostly = { 109static struct xt_match ecn_mt_reg __read_mostly = {
116 .name = "ecn", 110 .name = "ecn",
117 .family = AF_INET, 111 .family = NFPROTO_IPV4,
118 .match = ecn_mt, 112 .match = ecn_mt,
119 .matchsize = sizeof(struct ipt_ecn_info), 113 .matchsize = sizeof(struct ipt_ecn_info),
120 .checkentry = ecn_mt_check, 114 .checkentry = ecn_mt_check,
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
deleted file mode 100644
index 3974d7cae5c0..000000000000
--- a/net/ipv4/netfilter/ipt_recent.c
+++ /dev/null
@@ -1,501 +0,0 @@
1/*
2 * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This is a replacement of the old ipt_recent module, which carried the
9 * following copyright notice:
10 *
11 * Author: Stephen Frost <sfrost@snowman.net>
12 * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org
13 */
14#include <linux/init.h>
15#include <linux/ip.h>
16#include <linux/moduleparam.h>
17#include <linux/proc_fs.h>
18#include <linux/seq_file.h>
19#include <linux/string.h>
20#include <linux/ctype.h>
21#include <linux/list.h>
22#include <linux/random.h>
23#include <linux/jhash.h>
24#include <linux/bitops.h>
25#include <linux/skbuff.h>
26#include <linux/inet.h>
27#include <net/net_namespace.h>
28
29#include <linux/netfilter/x_tables.h>
30#include <linux/netfilter_ipv4/ipt_recent.h>
31
32MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
33MODULE_DESCRIPTION("Xtables: \"recently-seen\" host matching for IPv4");
34MODULE_LICENSE("GPL");
35
36static unsigned int ip_list_tot = 100;
37static unsigned int ip_pkt_list_tot = 20;
38static unsigned int ip_list_hash_size = 0;
39static unsigned int ip_list_perms = 0644;
40static unsigned int ip_list_uid = 0;
41static unsigned int ip_list_gid = 0;
42module_param(ip_list_tot, uint, 0400);
43module_param(ip_pkt_list_tot, uint, 0400);
44module_param(ip_list_hash_size, uint, 0400);
45module_param(ip_list_perms, uint, 0400);
46module_param(ip_list_uid, uint, 0400);
47module_param(ip_list_gid, uint, 0400);
48MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list");
49MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)");
50MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs");
51MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files");
52MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/ipt_recent/* files");
53MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/ipt_recent/* files");
54
55struct recent_entry {
56 struct list_head list;
57 struct list_head lru_list;
58 __be32 addr;
59 u_int8_t ttl;
60 u_int8_t index;
61 u_int16_t nstamps;
62 unsigned long stamps[0];
63};
64
65struct recent_table {
66 struct list_head list;
67 char name[IPT_RECENT_NAME_LEN];
68#ifdef CONFIG_PROC_FS
69 struct proc_dir_entry *proc;
70#endif
71 unsigned int refcnt;
72 unsigned int entries;
73 struct list_head lru_list;
74 struct list_head iphash[0];
75};
76
77static LIST_HEAD(tables);
78static DEFINE_SPINLOCK(recent_lock);
79static DEFINE_MUTEX(recent_mutex);
80
81#ifdef CONFIG_PROC_FS
82static struct proc_dir_entry *proc_dir;
83static const struct file_operations recent_fops;
84#endif
85
86static u_int32_t hash_rnd;
87static int hash_rnd_initted;
88
89static unsigned int recent_entry_hash(__be32 addr)
90{
91 if (!hash_rnd_initted) {
92 get_random_bytes(&hash_rnd, 4);
93 hash_rnd_initted = 1;
94 }
95 return jhash_1word((__force u32)addr, hash_rnd) & (ip_list_hash_size - 1);
96}
97
98static struct recent_entry *
99recent_entry_lookup(const struct recent_table *table, __be32 addr, u_int8_t ttl)
100{
101 struct recent_entry *e;
102 unsigned int h;
103
104 h = recent_entry_hash(addr);
105 list_for_each_entry(e, &table->iphash[h], list)
106 if (e->addr == addr && (ttl == e->ttl || !ttl || !e->ttl))
107 return e;
108 return NULL;
109}
110
111static void recent_entry_remove(struct recent_table *t, struct recent_entry *e)
112{
113 list_del(&e->list);
114 list_del(&e->lru_list);
115 kfree(e);
116 t->entries--;
117}
118
119static struct recent_entry *
120recent_entry_init(struct recent_table *t, __be32 addr, u_int8_t ttl)
121{
122 struct recent_entry *e;
123
124 if (t->entries >= ip_list_tot) {
125 e = list_entry(t->lru_list.next, struct recent_entry, lru_list);
126 recent_entry_remove(t, e);
127 }
128 e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * ip_pkt_list_tot,
129 GFP_ATOMIC);
130 if (e == NULL)
131 return NULL;
132 e->addr = addr;
133 e->ttl = ttl;
134 e->stamps[0] = jiffies;
135 e->nstamps = 1;
136 e->index = 1;
137 list_add_tail(&e->list, &t->iphash[recent_entry_hash(addr)]);
138 list_add_tail(&e->lru_list, &t->lru_list);
139 t->entries++;
140 return e;
141}
142
143static void recent_entry_update(struct recent_table *t, struct recent_entry *e)
144{
145 e->stamps[e->index++] = jiffies;
146 if (e->index > e->nstamps)
147 e->nstamps = e->index;
148 e->index %= ip_pkt_list_tot;
149 list_move_tail(&e->lru_list, &t->lru_list);
150}
151
152static struct recent_table *recent_table_lookup(const char *name)
153{
154 struct recent_table *t;
155
156 list_for_each_entry(t, &tables, list)
157 if (!strcmp(t->name, name))
158 return t;
159 return NULL;
160}
161
162static void recent_table_flush(struct recent_table *t)
163{
164 struct recent_entry *e, *next;
165 unsigned int i;
166
167 for (i = 0; i < ip_list_hash_size; i++)
168 list_for_each_entry_safe(e, next, &t->iphash[i], list)
169 recent_entry_remove(t, e);
170}
171
172static bool
173recent_mt(const struct sk_buff *skb, const struct net_device *in,
174 const struct net_device *out, const struct xt_match *match,
175 const void *matchinfo, int offset, unsigned int protoff,
176 bool *hotdrop)
177{
178 const struct ipt_recent_info *info = matchinfo;
179 struct recent_table *t;
180 struct recent_entry *e;
181 __be32 addr;
182 u_int8_t ttl;
183 bool ret = info->invert;
184
185 if (info->side == IPT_RECENT_DEST)
186 addr = ip_hdr(skb)->daddr;
187 else
188 addr = ip_hdr(skb)->saddr;
189
190 ttl = ip_hdr(skb)->ttl;
191 /* use TTL as seen before forwarding */
192 if (out && !skb->sk)
193 ttl++;
194
195 spin_lock_bh(&recent_lock);
196 t = recent_table_lookup(info->name);
197 e = recent_entry_lookup(t, addr,
198 info->check_set & IPT_RECENT_TTL ? ttl : 0);
199 if (e == NULL) {
200 if (!(info->check_set & IPT_RECENT_SET))
201 goto out;
202 e = recent_entry_init(t, addr, ttl);
203 if (e == NULL)
204 *hotdrop = true;
205 ret = !ret;
206 goto out;
207 }
208
209 if (info->check_set & IPT_RECENT_SET)
210 ret = !ret;
211 else if (info->check_set & IPT_RECENT_REMOVE) {
212 recent_entry_remove(t, e);
213 ret = !ret;
214 } else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) {
215 unsigned long time = jiffies - info->seconds * HZ;
216 unsigned int i, hits = 0;
217
218 for (i = 0; i < e->nstamps; i++) {
219 if (info->seconds && time_after(time, e->stamps[i]))
220 continue;
221 if (++hits >= info->hit_count) {
222 ret = !ret;
223 break;
224 }
225 }
226 }
227
228 if (info->check_set & IPT_RECENT_SET ||
229 (info->check_set & IPT_RECENT_UPDATE && ret)) {
230 recent_entry_update(t, e);
231 e->ttl = ttl;
232 }
233out:
234 spin_unlock_bh(&recent_lock);
235 return ret;
236}
237
238static bool
239recent_mt_check(const char *tablename, const void *ip,
240 const struct xt_match *match, void *matchinfo,
241 unsigned int hook_mask)
242{
243 const struct ipt_recent_info *info = matchinfo;
244 struct recent_table *t;
245 unsigned i;
246 bool ret = false;
247
248 if (hweight8(info->check_set &
249 (IPT_RECENT_SET | IPT_RECENT_REMOVE |
250 IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1)
251 return false;
252 if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) &&
253 (info->seconds || info->hit_count))
254 return false;
255 if (info->hit_count > ip_pkt_list_tot)
256 return false;
257 if (info->name[0] == '\0' ||
258 strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
259 return false;
260
261 mutex_lock(&recent_mutex);
262 t = recent_table_lookup(info->name);
263 if (t != NULL) {
264 t->refcnt++;
265 ret = true;
266 goto out;
267 }
268
269 t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
270 GFP_KERNEL);
271 if (t == NULL)
272 goto out;
273 t->refcnt = 1;
274 strcpy(t->name, info->name);
275 INIT_LIST_HEAD(&t->lru_list);
276 for (i = 0; i < ip_list_hash_size; i++)
277 INIT_LIST_HEAD(&t->iphash[i]);
278#ifdef CONFIG_PROC_FS
279 t->proc = proc_create(t->name, ip_list_perms, proc_dir, &recent_fops);
280 if (t->proc == NULL) {
281 kfree(t);
282 goto out;
283 }
284 t->proc->uid = ip_list_uid;
285 t->proc->gid = ip_list_gid;
286 t->proc->data = t;
287#endif
288 spin_lock_bh(&recent_lock);
289 list_add_tail(&t->list, &tables);
290 spin_unlock_bh(&recent_lock);
291 ret = true;
292out:
293 mutex_unlock(&recent_mutex);
294 return ret;
295}
296
297static void recent_mt_destroy(const struct xt_match *match, void *matchinfo)
298{
299 const struct ipt_recent_info *info = matchinfo;
300 struct recent_table *t;
301
302 mutex_lock(&recent_mutex);
303 t = recent_table_lookup(info->name);
304 if (--t->refcnt == 0) {
305 spin_lock_bh(&recent_lock);
306 list_del(&t->list);
307 spin_unlock_bh(&recent_lock);
308#ifdef CONFIG_PROC_FS
309 remove_proc_entry(t->name, proc_dir);
310#endif
311 recent_table_flush(t);
312 kfree(t);
313 }
314 mutex_unlock(&recent_mutex);
315}
316
317#ifdef CONFIG_PROC_FS
318struct recent_iter_state {
319 struct recent_table *table;
320 unsigned int bucket;
321};
322
323static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
324 __acquires(recent_lock)
325{
326 struct recent_iter_state *st = seq->private;
327 const struct recent_table *t = st->table;
328 struct recent_entry *e;
329 loff_t p = *pos;
330
331 spin_lock_bh(&recent_lock);
332
333 for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++)
334 list_for_each_entry(e, &t->iphash[st->bucket], list)
335 if (p-- == 0)
336 return e;
337 return NULL;
338}
339
340static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos)
341{
342 struct recent_iter_state *st = seq->private;
343 const struct recent_table *t = st->table;
344 struct recent_entry *e = v;
345 struct list_head *head = e->list.next;
346
347 while (head == &t->iphash[st->bucket]) {
348 if (++st->bucket >= ip_list_hash_size)
349 return NULL;
350 head = t->iphash[st->bucket].next;
351 }
352 (*pos)++;
353 return list_entry(head, struct recent_entry, list);
354}
355
356static void recent_seq_stop(struct seq_file *s, void *v)
357 __releases(recent_lock)
358{
359 spin_unlock_bh(&recent_lock);
360}
361
362static int recent_seq_show(struct seq_file *seq, void *v)
363{
364 const struct recent_entry *e = v;
365 unsigned int i;
366
367 i = (e->index - 1) % ip_pkt_list_tot;
368 seq_printf(seq, "src=%u.%u.%u.%u ttl: %u last_seen: %lu oldest_pkt: %u",
369 NIPQUAD(e->addr), e->ttl, e->stamps[i], e->index);
370 for (i = 0; i < e->nstamps; i++)
371 seq_printf(seq, "%s %lu", i ? "," : "", e->stamps[i]);
372 seq_printf(seq, "\n");
373 return 0;
374}
375
376static const struct seq_operations recent_seq_ops = {
377 .start = recent_seq_start,
378 .next = recent_seq_next,
379 .stop = recent_seq_stop,
380 .show = recent_seq_show,
381};
382
383static int recent_seq_open(struct inode *inode, struct file *file)
384{
385 struct proc_dir_entry *pde = PDE(inode);
386 struct recent_iter_state *st;
387
388 st = __seq_open_private(file, &recent_seq_ops, sizeof(*st));
389 if (st == NULL)
390 return -ENOMEM;
391
392 st->table = pde->data;
393 return 0;
394}
395
396static ssize_t recent_proc_write(struct file *file, const char __user *input,
397 size_t size, loff_t *loff)
398{
399 const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
400 struct recent_table *t = pde->data;
401 struct recent_entry *e;
402 char buf[sizeof("+255.255.255.255")], *c = buf;
403 __be32 addr;
404 int add;
405
406 if (size > sizeof(buf))
407 size = sizeof(buf);
408 if (copy_from_user(buf, input, size))
409 return -EFAULT;
410 while (isspace(*c))
411 c++;
412
413 if (size - (c - buf) < 5)
414 return c - buf;
415 if (!strncmp(c, "clear", 5)) {
416 c += 5;
417 spin_lock_bh(&recent_lock);
418 recent_table_flush(t);
419 spin_unlock_bh(&recent_lock);
420 return c - buf;
421 }
422
423 switch (*c) {
424 case '-':
425 add = 0;
426 c++;
427 break;
428 case '+':
429 c++;
430 default:
431 add = 1;
432 break;
433 }
434 addr = in_aton(c);
435
436 spin_lock_bh(&recent_lock);
437 e = recent_entry_lookup(t, addr, 0);
438 if (e == NULL) {
439 if (add)
440 recent_entry_init(t, addr, 0);
441 } else {
442 if (add)
443 recent_entry_update(t, e);
444 else
445 recent_entry_remove(t, e);
446 }
447 spin_unlock_bh(&recent_lock);
448 return size;
449}
450
451static const struct file_operations recent_fops = {
452 .open = recent_seq_open,
453 .read = seq_read,
454 .write = recent_proc_write,
455 .release = seq_release_private,
456 .owner = THIS_MODULE,
457};
458#endif /* CONFIG_PROC_FS */
459
460static struct xt_match recent_mt_reg __read_mostly = {
461 .name = "recent",
462 .family = AF_INET,
463 .match = recent_mt,
464 .matchsize = sizeof(struct ipt_recent_info),
465 .checkentry = recent_mt_check,
466 .destroy = recent_mt_destroy,
467 .me = THIS_MODULE,
468};
469
470static int __init recent_mt_init(void)
471{
472 int err;
473
474 if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255)
475 return -EINVAL;
476 ip_list_hash_size = 1 << fls(ip_list_tot);
477
478 err = xt_register_match(&recent_mt_reg);
479#ifdef CONFIG_PROC_FS
480 if (err)
481 return err;
482 proc_dir = proc_mkdir("ipt_recent", init_net.proc_net);
483 if (proc_dir == NULL) {
484 xt_unregister_match(&recent_mt_reg);
485 err = -ENOMEM;
486 }
487#endif
488 return err;
489}
490
491static void __exit recent_mt_exit(void)
492{
493 BUG_ON(!list_empty(&tables));
494 xt_unregister_match(&recent_mt_reg);
495#ifdef CONFIG_PROC_FS
496 remove_proc_entry("ipt_recent", init_net.proc_net);
497#endif
498}
499
500module_init(recent_mt_init);
501module_exit(recent_mt_exit);
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index e0b8caeb710c..297f1cbf4ff5 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -18,12 +18,9 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
18MODULE_DESCRIPTION("Xtables: IPv4 TTL field match"); 18MODULE_DESCRIPTION("Xtables: IPv4 TTL field match");
19MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
20 20
21static bool 21static bool ttl_mt(const struct sk_buff *skb, const struct xt_match_param *par)
22ttl_mt(const struct sk_buff *skb, const struct net_device *in,
23 const struct net_device *out, const struct xt_match *match,
24 const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
25{ 22{
26 const struct ipt_ttl_info *info = matchinfo; 23 const struct ipt_ttl_info *info = par->matchinfo;
27 const u8 ttl = ip_hdr(skb)->ttl; 24 const u8 ttl = ip_hdr(skb)->ttl;
28 25
29 switch (info->mode) { 26 switch (info->mode) {
@@ -46,7 +43,7 @@ ttl_mt(const struct sk_buff *skb, const struct net_device *in,
46 43
47static struct xt_match ttl_mt_reg __read_mostly = { 44static struct xt_match ttl_mt_reg __read_mostly = {
48 .name = "ttl", 45 .name = "ttl",
49 .family = AF_INET, 46 .family = NFPROTO_IPV4,
50 .match = ttl_mt, 47 .match = ttl_mt,
51 .matchsize = sizeof(struct ipt_ttl_info), 48 .matchsize = sizeof(struct ipt_ttl_info),
52 .me = THIS_MODULE, 49 .me = THIS_MODULE,
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 1ea677dcf845..c9224310ebae 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -70,7 +70,7 @@ ipt_local_in_hook(unsigned int hook,
70 int (*okfn)(struct sk_buff *)) 70 int (*okfn)(struct sk_buff *))
71{ 71{
72 return ipt_do_table(skb, hook, in, out, 72 return ipt_do_table(skb, hook, in, out,
73 nf_local_in_net(in, out)->ipv4.iptable_filter); 73 dev_net(in)->ipv4.iptable_filter);
74} 74}
75 75
76static unsigned int 76static unsigned int
@@ -81,7 +81,7 @@ ipt_hook(unsigned int hook,
81 int (*okfn)(struct sk_buff *)) 81 int (*okfn)(struct sk_buff *))
82{ 82{
83 return ipt_do_table(skb, hook, in, out, 83 return ipt_do_table(skb, hook, in, out,
84 nf_forward_net(in, out)->ipv4.iptable_filter); 84 dev_net(in)->ipv4.iptable_filter);
85} 85}
86 86
87static unsigned int 87static unsigned int
@@ -101,7 +101,7 @@ ipt_local_out_hook(unsigned int hook,
101 } 101 }
102 102
103 return ipt_do_table(skb, hook, in, out, 103 return ipt_do_table(skb, hook, in, out,
104 nf_local_out_net(in, out)->ipv4.iptable_filter); 104 dev_net(out)->ipv4.iptable_filter);
105} 105}
106 106
107static struct nf_hook_ops ipt_ops[] __read_mostly = { 107static struct nf_hook_ops ipt_ops[] __read_mostly = {
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index da59182f2226..69f2c4287146 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -81,7 +81,7 @@ ipt_pre_routing_hook(unsigned int hook,
81 int (*okfn)(struct sk_buff *)) 81 int (*okfn)(struct sk_buff *))
82{ 82{
83 return ipt_do_table(skb, hook, in, out, 83 return ipt_do_table(skb, hook, in, out,
84 nf_pre_routing_net(in, out)->ipv4.iptable_mangle); 84 dev_net(in)->ipv4.iptable_mangle);
85} 85}
86 86
87static unsigned int 87static unsigned int
@@ -92,7 +92,7 @@ ipt_post_routing_hook(unsigned int hook,
92 int (*okfn)(struct sk_buff *)) 92 int (*okfn)(struct sk_buff *))
93{ 93{
94 return ipt_do_table(skb, hook, in, out, 94 return ipt_do_table(skb, hook, in, out,
95 nf_post_routing_net(in, out)->ipv4.iptable_mangle); 95 dev_net(out)->ipv4.iptable_mangle);
96} 96}
97 97
98static unsigned int 98static unsigned int
@@ -103,7 +103,7 @@ ipt_local_in_hook(unsigned int hook,
103 int (*okfn)(struct sk_buff *)) 103 int (*okfn)(struct sk_buff *))
104{ 104{
105 return ipt_do_table(skb, hook, in, out, 105 return ipt_do_table(skb, hook, in, out,
106 nf_local_in_net(in, out)->ipv4.iptable_mangle); 106 dev_net(in)->ipv4.iptable_mangle);
107} 107}
108 108
109static unsigned int 109static unsigned int
@@ -114,7 +114,7 @@ ipt_forward_hook(unsigned int hook,
114 int (*okfn)(struct sk_buff *)) 114 int (*okfn)(struct sk_buff *))
115{ 115{
116 return ipt_do_table(skb, hook, in, out, 116 return ipt_do_table(skb, hook, in, out,
117 nf_forward_net(in, out)->ipv4.iptable_mangle); 117 dev_net(in)->ipv4.iptable_mangle);
118} 118}
119 119
120static unsigned int 120static unsigned int
@@ -147,7 +147,7 @@ ipt_local_hook(unsigned int hook,
147 tos = iph->tos; 147 tos = iph->tos;
148 148
149 ret = ipt_do_table(skb, hook, in, out, 149 ret = ipt_do_table(skb, hook, in, out,
150 nf_local_out_net(in, out)->ipv4.iptable_mangle); 150 dev_net(out)->ipv4.iptable_mangle);
151 /* Reroute for ANY change. */ 151 /* Reroute for ANY change. */
152 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { 152 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
153 iph = ip_hdr(skb); 153 iph = ip_hdr(skb);
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index fddce7754b72..8faebfe638f1 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -53,7 +53,7 @@ ipt_hook(unsigned int hook,
53 int (*okfn)(struct sk_buff *)) 53 int (*okfn)(struct sk_buff *))
54{ 54{
55 return ipt_do_table(skb, hook, in, out, 55 return ipt_do_table(skb, hook, in, out,
56 nf_pre_routing_net(in, out)->ipv4.iptable_raw); 56 dev_net(in)->ipv4.iptable_raw);
57} 57}
58 58
59static unsigned int 59static unsigned int
@@ -72,7 +72,7 @@ ipt_local_hook(unsigned int hook,
72 return NF_ACCEPT; 72 return NF_ACCEPT;
73 } 73 }
74 return ipt_do_table(skb, hook, in, out, 74 return ipt_do_table(skb, hook, in, out,
75 nf_local_out_net(in, out)->ipv4.iptable_raw); 75 dev_net(out)->ipv4.iptable_raw);
76} 76}
77 77
78/* 'raw' is the very first table. */ 78/* 'raw' is the very first table. */
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index db6d312128e1..36f3be3cc428 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -73,7 +73,7 @@ ipt_local_in_hook(unsigned int hook,
73 int (*okfn)(struct sk_buff *)) 73 int (*okfn)(struct sk_buff *))
74{ 74{
75 return ipt_do_table(skb, hook, in, out, 75 return ipt_do_table(skb, hook, in, out,
76 nf_local_in_net(in, out)->ipv4.iptable_security); 76 dev_net(in)->ipv4.iptable_security);
77} 77}
78 78
79static unsigned int 79static unsigned int
@@ -84,7 +84,7 @@ ipt_forward_hook(unsigned int hook,
84 int (*okfn)(struct sk_buff *)) 84 int (*okfn)(struct sk_buff *))
85{ 85{
86 return ipt_do_table(skb, hook, in, out, 86 return ipt_do_table(skb, hook, in, out,
87 nf_forward_net(in, out)->ipv4.iptable_security); 87 dev_net(in)->ipv4.iptable_security);
88} 88}
89 89
90static unsigned int 90static unsigned int
@@ -103,7 +103,7 @@ ipt_local_out_hook(unsigned int hook,
103 return NF_ACCEPT; 103 return NF_ACCEPT;
104 } 104 }
105 return ipt_do_table(skb, hook, in, out, 105 return ipt_do_table(skb, hook, in, out,
106 nf_local_out_net(in, out)->ipv4.iptable_security); 106 dev_net(out)->ipv4.iptable_security);
107} 107}
108 108
109static struct nf_hook_ops ipt_ops[] __read_mostly = { 109static struct nf_hook_ops ipt_ops[] __read_mostly = {
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 5a955c440364..4a7c35275396 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -1,3 +1,4 @@
1
1/* (C) 1999-2001 Paul `Rusty' Russell 2/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 3 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 * 4 *
@@ -24,6 +25,7 @@
24#include <net/netfilter/nf_conntrack_core.h> 25#include <net/netfilter/nf_conntrack_core.h>
25#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 26#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
26#include <net/netfilter/nf_nat_helper.h> 27#include <net/netfilter/nf_nat_helper.h>
28#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
27 29
28int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb, 30int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
29 struct nf_conn *ct, 31 struct nf_conn *ct,
@@ -63,23 +65,6 @@ static int ipv4_print_tuple(struct seq_file *s,
63 NIPQUAD(tuple->dst.u3.ip)); 65 NIPQUAD(tuple->dst.u3.ip));
64} 66}
65 67
66/* Returns new sk_buff, or NULL */
67static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
68{
69 int err;
70
71 skb_orphan(skb);
72
73 local_bh_disable();
74 err = ip_defrag(skb, user);
75 local_bh_enable();
76
77 if (!err)
78 ip_send_check(ip_hdr(skb));
79
80 return err;
81}
82
83static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, 68static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
84 unsigned int *dataoff, u_int8_t *protonum) 69 unsigned int *dataoff, u_int8_t *protonum)
85{ 70{
@@ -144,35 +129,13 @@ out:
144 return nf_conntrack_confirm(skb); 129 return nf_conntrack_confirm(skb);
145} 130}
146 131
147static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
148 struct sk_buff *skb,
149 const struct net_device *in,
150 const struct net_device *out,
151 int (*okfn)(struct sk_buff *))
152{
153 /* Previously seen (loopback)? Ignore. Do this before
154 fragment check. */
155 if (skb->nfct)
156 return NF_ACCEPT;
157
158 /* Gather fragments. */
159 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
160 if (nf_ct_ipv4_gather_frags(skb,
161 hooknum == NF_INET_PRE_ROUTING ?
162 IP_DEFRAG_CONNTRACK_IN :
163 IP_DEFRAG_CONNTRACK_OUT))
164 return NF_STOLEN;
165 }
166 return NF_ACCEPT;
167}
168
169static unsigned int ipv4_conntrack_in(unsigned int hooknum, 132static unsigned int ipv4_conntrack_in(unsigned int hooknum,
170 struct sk_buff *skb, 133 struct sk_buff *skb,
171 const struct net_device *in, 134 const struct net_device *in,
172 const struct net_device *out, 135 const struct net_device *out,
173 int (*okfn)(struct sk_buff *)) 136 int (*okfn)(struct sk_buff *))
174{ 137{
175 return nf_conntrack_in(PF_INET, hooknum, skb); 138 return nf_conntrack_in(dev_net(in), PF_INET, hooknum, skb);
176} 139}
177 140
178static unsigned int ipv4_conntrack_local(unsigned int hooknum, 141static unsigned int ipv4_conntrack_local(unsigned int hooknum,
@@ -188,20 +151,13 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
188 printk("ipt_hook: happy cracking.\n"); 151 printk("ipt_hook: happy cracking.\n");
189 return NF_ACCEPT; 152 return NF_ACCEPT;
190 } 153 }
191 return nf_conntrack_in(PF_INET, hooknum, skb); 154 return nf_conntrack_in(dev_net(out), PF_INET, hooknum, skb);
192} 155}
193 156
194/* Connection tracking may drop packets, but never alters them, so 157/* Connection tracking may drop packets, but never alters them, so
195 make it the first hook. */ 158 make it the first hook. */
196static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = { 159static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
197 { 160 {
198 .hook = ipv4_conntrack_defrag,
199 .owner = THIS_MODULE,
200 .pf = PF_INET,
201 .hooknum = NF_INET_PRE_ROUTING,
202 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
203 },
204 {
205 .hook = ipv4_conntrack_in, 161 .hook = ipv4_conntrack_in,
206 .owner = THIS_MODULE, 162 .owner = THIS_MODULE,
207 .pf = PF_INET, 163 .pf = PF_INET,
@@ -209,13 +165,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
209 .priority = NF_IP_PRI_CONNTRACK, 165 .priority = NF_IP_PRI_CONNTRACK,
210 }, 166 },
211 { 167 {
212 .hook = ipv4_conntrack_defrag,
213 .owner = THIS_MODULE,
214 .pf = PF_INET,
215 .hooknum = NF_INET_LOCAL_OUT,
216 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
217 },
218 {
219 .hook = ipv4_conntrack_local, 168 .hook = ipv4_conntrack_local,
220 .owner = THIS_MODULE, 169 .owner = THIS_MODULE,
221 .pf = PF_INET, 170 .pf = PF_INET,
@@ -254,7 +203,7 @@ static ctl_table ip_ct_sysctl_table[] = {
254 { 203 {
255 .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT, 204 .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT,
256 .procname = "ip_conntrack_count", 205 .procname = "ip_conntrack_count",
257 .data = &nf_conntrack_count, 206 .data = &init_net.ct.count,
258 .maxlen = sizeof(int), 207 .maxlen = sizeof(int),
259 .mode = 0444, 208 .mode = 0444,
260 .proc_handler = &proc_dointvec, 209 .proc_handler = &proc_dointvec,
@@ -270,7 +219,7 @@ static ctl_table ip_ct_sysctl_table[] = {
270 { 219 {
271 .ctl_name = NET_IPV4_NF_CONNTRACK_CHECKSUM, 220 .ctl_name = NET_IPV4_NF_CONNTRACK_CHECKSUM,
272 .procname = "ip_conntrack_checksum", 221 .procname = "ip_conntrack_checksum",
273 .data = &nf_conntrack_checksum, 222 .data = &init_net.ct.sysctl_checksum,
274 .maxlen = sizeof(int), 223 .maxlen = sizeof(int),
275 .mode = 0644, 224 .mode = 0644,
276 .proc_handler = &proc_dointvec, 225 .proc_handler = &proc_dointvec,
@@ -278,7 +227,7 @@ static ctl_table ip_ct_sysctl_table[] = {
278 { 227 {
279 .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID, 228 .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
280 .procname = "ip_conntrack_log_invalid", 229 .procname = "ip_conntrack_log_invalid",
281 .data = &nf_ct_log_invalid, 230 .data = &init_net.ct.sysctl_log_invalid,
282 .maxlen = sizeof(unsigned int), 231 .maxlen = sizeof(unsigned int),
283 .mode = 0644, 232 .mode = 0644,
284 .proc_handler = &proc_dointvec_minmax, 233 .proc_handler = &proc_dointvec_minmax,
@@ -323,7 +272,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
323 return -EINVAL; 272 return -EINVAL;
324 } 273 }
325 274
326 h = nf_conntrack_find_get(&tuple); 275 h = nf_conntrack_find_get(sock_net(sk), &tuple);
327 if (h) { 276 if (h) {
328 struct sockaddr_in sin; 277 struct sockaddr_in sin;
329 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); 278 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
@@ -422,6 +371,7 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
422 int ret = 0; 371 int ret = 0;
423 372
424 need_conntrack(); 373 need_conntrack();
374 nf_defrag_ipv4_enable();
425 375
426 ret = nf_register_sockopt(&so_getorigdst); 376 ret = nf_register_sockopt(&so_getorigdst);
427 if (ret < 0) { 377 if (ret < 0) {
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 3a020720e40b..313ebf00ee36 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -21,18 +21,20 @@
21#include <net/netfilter/nf_conntrack_acct.h> 21#include <net/netfilter/nf_conntrack_acct.h>
22 22
23struct ct_iter_state { 23struct ct_iter_state {
24 struct seq_net_private p;
24 unsigned int bucket; 25 unsigned int bucket;
25}; 26};
26 27
27static struct hlist_node *ct_get_first(struct seq_file *seq) 28static struct hlist_node *ct_get_first(struct seq_file *seq)
28{ 29{
30 struct net *net = seq_file_net(seq);
29 struct ct_iter_state *st = seq->private; 31 struct ct_iter_state *st = seq->private;
30 struct hlist_node *n; 32 struct hlist_node *n;
31 33
32 for (st->bucket = 0; 34 for (st->bucket = 0;
33 st->bucket < nf_conntrack_htable_size; 35 st->bucket < nf_conntrack_htable_size;
34 st->bucket++) { 36 st->bucket++) {
35 n = rcu_dereference(nf_conntrack_hash[st->bucket].first); 37 n = rcu_dereference(net->ct.hash[st->bucket].first);
36 if (n) 38 if (n)
37 return n; 39 return n;
38 } 40 }
@@ -42,13 +44,14 @@ static struct hlist_node *ct_get_first(struct seq_file *seq)
42static struct hlist_node *ct_get_next(struct seq_file *seq, 44static struct hlist_node *ct_get_next(struct seq_file *seq,
43 struct hlist_node *head) 45 struct hlist_node *head)
44{ 46{
47 struct net *net = seq_file_net(seq);
45 struct ct_iter_state *st = seq->private; 48 struct ct_iter_state *st = seq->private;
46 49
47 head = rcu_dereference(head->next); 50 head = rcu_dereference(head->next);
48 while (head == NULL) { 51 while (head == NULL) {
49 if (++st->bucket >= nf_conntrack_htable_size) 52 if (++st->bucket >= nf_conntrack_htable_size)
50 return NULL; 53 return NULL;
51 head = rcu_dereference(nf_conntrack_hash[st->bucket].first); 54 head = rcu_dereference(net->ct.hash[st->bucket].first);
52 } 55 }
53 return head; 56 return head;
54} 57}
@@ -158,8 +161,8 @@ static const struct seq_operations ct_seq_ops = {
158 161
159static int ct_open(struct inode *inode, struct file *file) 162static int ct_open(struct inode *inode, struct file *file)
160{ 163{
161 return seq_open_private(file, &ct_seq_ops, 164 return seq_open_net(inode, file, &ct_seq_ops,
162 sizeof(struct ct_iter_state)); 165 sizeof(struct ct_iter_state));
163} 166}
164 167
165static const struct file_operations ct_file_ops = { 168static const struct file_operations ct_file_ops = {
@@ -167,21 +170,23 @@ static const struct file_operations ct_file_ops = {
167 .open = ct_open, 170 .open = ct_open,
168 .read = seq_read, 171 .read = seq_read,
169 .llseek = seq_lseek, 172 .llseek = seq_lseek,
170 .release = seq_release_private, 173 .release = seq_release_net,
171}; 174};
172 175
173/* expects */ 176/* expects */
174struct ct_expect_iter_state { 177struct ct_expect_iter_state {
178 struct seq_net_private p;
175 unsigned int bucket; 179 unsigned int bucket;
176}; 180};
177 181
178static struct hlist_node *ct_expect_get_first(struct seq_file *seq) 182static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
179{ 183{
184 struct net *net = seq_file_net(seq);
180 struct ct_expect_iter_state *st = seq->private; 185 struct ct_expect_iter_state *st = seq->private;
181 struct hlist_node *n; 186 struct hlist_node *n;
182 187
183 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { 188 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
184 n = rcu_dereference(nf_ct_expect_hash[st->bucket].first); 189 n = rcu_dereference(net->ct.expect_hash[st->bucket].first);
185 if (n) 190 if (n)
186 return n; 191 return n;
187 } 192 }
@@ -191,13 +196,14 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
191static struct hlist_node *ct_expect_get_next(struct seq_file *seq, 196static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
192 struct hlist_node *head) 197 struct hlist_node *head)
193{ 198{
199 struct net *net = seq_file_net(seq);
194 struct ct_expect_iter_state *st = seq->private; 200 struct ct_expect_iter_state *st = seq->private;
195 201
196 head = rcu_dereference(head->next); 202 head = rcu_dereference(head->next);
197 while (head == NULL) { 203 while (head == NULL) {
198 if (++st->bucket >= nf_ct_expect_hsize) 204 if (++st->bucket >= nf_ct_expect_hsize)
199 return NULL; 205 return NULL;
200 head = rcu_dereference(nf_ct_expect_hash[st->bucket].first); 206 head = rcu_dereference(net->ct.expect_hash[st->bucket].first);
201 } 207 }
202 return head; 208 return head;
203} 209}
@@ -265,8 +271,8 @@ static const struct seq_operations exp_seq_ops = {
265 271
266static int exp_open(struct inode *inode, struct file *file) 272static int exp_open(struct inode *inode, struct file *file)
267{ 273{
268 return seq_open_private(file, &exp_seq_ops, 274 return seq_open_net(inode, file, &exp_seq_ops,
269 sizeof(struct ct_expect_iter_state)); 275 sizeof(struct ct_expect_iter_state));
270} 276}
271 277
272static const struct file_operations ip_exp_file_ops = { 278static const struct file_operations ip_exp_file_ops = {
@@ -274,11 +280,12 @@ static const struct file_operations ip_exp_file_ops = {
274 .open = exp_open, 280 .open = exp_open,
275 .read = seq_read, 281 .read = seq_read,
276 .llseek = seq_lseek, 282 .llseek = seq_lseek,
277 .release = seq_release_private, 283 .release = seq_release_net,
278}; 284};
279 285
280static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) 286static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
281{ 287{
288 struct net *net = seq_file_net(seq);
282 int cpu; 289 int cpu;
283 290
284 if (*pos == 0) 291 if (*pos == 0)
@@ -288,7 +295,7 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
288 if (!cpu_possible(cpu)) 295 if (!cpu_possible(cpu))
289 continue; 296 continue;
290 *pos = cpu+1; 297 *pos = cpu+1;
291 return &per_cpu(nf_conntrack_stat, cpu); 298 return per_cpu_ptr(net->ct.stat, cpu);
292 } 299 }
293 300
294 return NULL; 301 return NULL;
@@ -296,13 +303,14 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
296 303
297static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) 304static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
298{ 305{
306 struct net *net = seq_file_net(seq);
299 int cpu; 307 int cpu;
300 308
301 for (cpu = *pos; cpu < NR_CPUS; ++cpu) { 309 for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
302 if (!cpu_possible(cpu)) 310 if (!cpu_possible(cpu))
303 continue; 311 continue;
304 *pos = cpu+1; 312 *pos = cpu+1;
305 return &per_cpu(nf_conntrack_stat, cpu); 313 return per_cpu_ptr(net->ct.stat, cpu);
306 } 314 }
307 315
308 return NULL; 316 return NULL;
@@ -314,7 +322,8 @@ static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
314 322
315static int ct_cpu_seq_show(struct seq_file *seq, void *v) 323static int ct_cpu_seq_show(struct seq_file *seq, void *v)
316{ 324{
317 unsigned int nr_conntracks = atomic_read(&nf_conntrack_count); 325 struct net *net = seq_file_net(seq);
326 unsigned int nr_conntracks = atomic_read(&net->ct.count);
318 const struct ip_conntrack_stat *st = v; 327 const struct ip_conntrack_stat *st = v;
319 328
320 if (v == SEQ_START_TOKEN) { 329 if (v == SEQ_START_TOKEN) {
@@ -354,7 +363,8 @@ static const struct seq_operations ct_cpu_seq_ops = {
354 363
355static int ct_cpu_seq_open(struct inode *inode, struct file *file) 364static int ct_cpu_seq_open(struct inode *inode, struct file *file)
356{ 365{
357 return seq_open(file, &ct_cpu_seq_ops); 366 return seq_open_net(inode, file, &ct_cpu_seq_ops,
367 sizeof(struct seq_net_private));
358} 368}
359 369
360static const struct file_operations ct_cpu_seq_fops = { 370static const struct file_operations ct_cpu_seq_fops = {
@@ -362,39 +372,54 @@ static const struct file_operations ct_cpu_seq_fops = {
362 .open = ct_cpu_seq_open, 372 .open = ct_cpu_seq_open,
363 .read = seq_read, 373 .read = seq_read,
364 .llseek = seq_lseek, 374 .llseek = seq_lseek,
365 .release = seq_release, 375 .release = seq_release_net,
366}; 376};
367 377
368int __init nf_conntrack_ipv4_compat_init(void) 378static int __net_init ip_conntrack_net_init(struct net *net)
369{ 379{
370 struct proc_dir_entry *proc, *proc_exp, *proc_stat; 380 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
371 381
372 proc = proc_net_fops_create(&init_net, "ip_conntrack", 0440, &ct_file_ops); 382 proc = proc_net_fops_create(net, "ip_conntrack", 0440, &ct_file_ops);
373 if (!proc) 383 if (!proc)
374 goto err1; 384 goto err1;
375 385
376 proc_exp = proc_net_fops_create(&init_net, "ip_conntrack_expect", 0440, 386 proc_exp = proc_net_fops_create(net, "ip_conntrack_expect", 0440,
377 &ip_exp_file_ops); 387 &ip_exp_file_ops);
378 if (!proc_exp) 388 if (!proc_exp)
379 goto err2; 389 goto err2;
380 390
381 proc_stat = proc_create("ip_conntrack", S_IRUGO, 391 proc_stat = proc_create("ip_conntrack", S_IRUGO,
382 init_net.proc_net_stat, &ct_cpu_seq_fops); 392 net->proc_net_stat, &ct_cpu_seq_fops);
383 if (!proc_stat) 393 if (!proc_stat)
384 goto err3; 394 goto err3;
385 return 0; 395 return 0;
386 396
387err3: 397err3:
388 proc_net_remove(&init_net, "ip_conntrack_expect"); 398 proc_net_remove(net, "ip_conntrack_expect");
389err2: 399err2:
390 proc_net_remove(&init_net, "ip_conntrack"); 400 proc_net_remove(net, "ip_conntrack");
391err1: 401err1:
392 return -ENOMEM; 402 return -ENOMEM;
393} 403}
394 404
405static void __net_exit ip_conntrack_net_exit(struct net *net)
406{
407 remove_proc_entry("ip_conntrack", net->proc_net_stat);
408 proc_net_remove(net, "ip_conntrack_expect");
409 proc_net_remove(net, "ip_conntrack");
410}
411
412static struct pernet_operations ip_conntrack_net_ops = {
413 .init = ip_conntrack_net_init,
414 .exit = ip_conntrack_net_exit,
415};
416
417int __init nf_conntrack_ipv4_compat_init(void)
418{
419 return register_pernet_subsys(&ip_conntrack_net_ops);
420}
421
395void __exit nf_conntrack_ipv4_compat_fini(void) 422void __exit nf_conntrack_ipv4_compat_fini(void)
396{ 423{
397 remove_proc_entry("ip_conntrack", init_net.proc_net_stat); 424 unregister_pernet_subsys(&ip_conntrack_net_ops);
398 proc_net_remove(&init_net, "ip_conntrack_expect");
399 proc_net_remove(&init_net, "ip_conntrack");
400} 425}
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 97791048fa9b..4e8879220222 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -79,7 +79,7 @@ static int icmp_packet(struct nf_conn *ct,
79 const struct sk_buff *skb, 79 const struct sk_buff *skb,
80 unsigned int dataoff, 80 unsigned int dataoff,
81 enum ip_conntrack_info ctinfo, 81 enum ip_conntrack_info ctinfo,
82 int pf, 82 u_int8_t pf,
83 unsigned int hooknum) 83 unsigned int hooknum)
84{ 84{
85 /* Try to delete connection immediately after all replies: 85 /* Try to delete connection immediately after all replies:
@@ -91,7 +91,7 @@ static int icmp_packet(struct nf_conn *ct,
91 nf_ct_kill_acct(ct, ctinfo, skb); 91 nf_ct_kill_acct(ct, ctinfo, skb);
92 } else { 92 } else {
93 atomic_inc(&ct->proto.icmp.count); 93 atomic_inc(&ct->proto.icmp.count);
94 nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); 94 nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
95 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); 95 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout);
96 } 96 }
97 97
@@ -123,7 +123,7 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
123 123
124/* Returns conntrack if it dealt with ICMP, and filled in skb fields */ 124/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
125static int 125static int
126icmp_error_message(struct sk_buff *skb, 126icmp_error_message(struct net *net, struct sk_buff *skb,
127 enum ip_conntrack_info *ctinfo, 127 enum ip_conntrack_info *ctinfo,
128 unsigned int hooknum) 128 unsigned int hooknum)
129{ 129{
@@ -155,7 +155,7 @@ icmp_error_message(struct sk_buff *skb,
155 155
156 *ctinfo = IP_CT_RELATED; 156 *ctinfo = IP_CT_RELATED;
157 157
158 h = nf_conntrack_find_get(&innertuple); 158 h = nf_conntrack_find_get(net, &innertuple);
159 if (!h) { 159 if (!h) {
160 pr_debug("icmp_error_message: no match\n"); 160 pr_debug("icmp_error_message: no match\n");
161 return -NF_ACCEPT; 161 return -NF_ACCEPT;
@@ -172,8 +172,8 @@ icmp_error_message(struct sk_buff *skb,
172 172
173/* Small and modified version of icmp_rcv */ 173/* Small and modified version of icmp_rcv */
174static int 174static int
175icmp_error(struct sk_buff *skb, unsigned int dataoff, 175icmp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
176 enum ip_conntrack_info *ctinfo, int pf, unsigned int hooknum) 176 enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum)
177{ 177{
178 const struct icmphdr *icmph; 178 const struct icmphdr *icmph;
179 struct icmphdr _ih; 179 struct icmphdr _ih;
@@ -181,16 +181,16 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
181 /* Not enough header? */ 181 /* Not enough header? */
182 icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih); 182 icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih);
183 if (icmph == NULL) { 183 if (icmph == NULL) {
184 if (LOG_INVALID(IPPROTO_ICMP)) 184 if (LOG_INVALID(net, IPPROTO_ICMP))
185 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 185 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
186 "nf_ct_icmp: short packet "); 186 "nf_ct_icmp: short packet ");
187 return -NF_ACCEPT; 187 return -NF_ACCEPT;
188 } 188 }
189 189
190 /* See ip_conntrack_proto_tcp.c */ 190 /* See ip_conntrack_proto_tcp.c */
191 if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING && 191 if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
192 nf_ip_checksum(skb, hooknum, dataoff, 0)) { 192 nf_ip_checksum(skb, hooknum, dataoff, 0)) {
193 if (LOG_INVALID(IPPROTO_ICMP)) 193 if (LOG_INVALID(net, IPPROTO_ICMP))
194 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 194 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
195 "nf_ct_icmp: bad HW ICMP checksum "); 195 "nf_ct_icmp: bad HW ICMP checksum ");
196 return -NF_ACCEPT; 196 return -NF_ACCEPT;
@@ -203,7 +203,7 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
203 * discarded. 203 * discarded.
204 */ 204 */
205 if (icmph->type > NR_ICMP_TYPES) { 205 if (icmph->type > NR_ICMP_TYPES) {
206 if (LOG_INVALID(IPPROTO_ICMP)) 206 if (LOG_INVALID(net, IPPROTO_ICMP))
207 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 207 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
208 "nf_ct_icmp: invalid ICMP type "); 208 "nf_ct_icmp: invalid ICMP type ");
209 return -NF_ACCEPT; 209 return -NF_ACCEPT;
@@ -217,7 +217,7 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
217 && icmph->type != ICMP_REDIRECT) 217 && icmph->type != ICMP_REDIRECT)
218 return NF_ACCEPT; 218 return NF_ACCEPT;
219 219
220 return icmp_error_message(skb, ctinfo, hooknum); 220 return icmp_error_message(net, skb, ctinfo, hooknum);
221} 221}
222 222
223#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 223#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
new file mode 100644
index 000000000000..aa2c50a180f7
--- /dev/null
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -0,0 +1,96 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/ip.h>
11#include <linux/netfilter.h>
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <net/route.h>
15#include <net/ip.h>
16
17#include <linux/netfilter_ipv4.h>
18#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
19
20/* Returns new sk_buff, or NULL */
21static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
22{
23 int err;
24
25 skb_orphan(skb);
26
27 local_bh_disable();
28 err = ip_defrag(skb, user);
29 local_bh_enable();
30
31 if (!err)
32 ip_send_check(ip_hdr(skb));
33
34 return err;
35}
36
37static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
38 struct sk_buff *skb,
39 const struct net_device *in,
40 const struct net_device *out,
41 int (*okfn)(struct sk_buff *))
42{
43#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
44 /* Previously seen (loopback)? Ignore. Do this before
45 fragment check. */
46 if (skb->nfct)
47 return NF_ACCEPT;
48#endif
49
50 /* Gather fragments. */
51 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
52 if (nf_ct_ipv4_gather_frags(skb,
53 hooknum == NF_INET_PRE_ROUTING ?
54 IP_DEFRAG_CONNTRACK_IN :
55 IP_DEFRAG_CONNTRACK_OUT))
56 return NF_STOLEN;
57 }
58 return NF_ACCEPT;
59}
60
61static struct nf_hook_ops ipv4_defrag_ops[] = {
62 {
63 .hook = ipv4_conntrack_defrag,
64 .owner = THIS_MODULE,
65 .pf = PF_INET,
66 .hooknum = NF_INET_PRE_ROUTING,
67 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
68 },
69 {
70 .hook = ipv4_conntrack_defrag,
71 .owner = THIS_MODULE,
72 .pf = PF_INET,
73 .hooknum = NF_INET_LOCAL_OUT,
74 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
75 },
76};
77
78static int __init nf_defrag_init(void)
79{
80 return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
81}
82
83static void __exit nf_defrag_fini(void)
84{
85 nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
86}
87
88void nf_defrag_ipv4_enable(void)
89{
90}
91EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable);
92
93module_init(nf_defrag_init);
94module_exit(nf_defrag_fini);
95
96MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 6c6a3cba8d50..2ac9eaf1a8c9 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -37,9 +37,6 @@ static struct nf_conntrack_l3proto *l3proto __read_mostly;
37 37
38/* Calculated at init based on memory size */ 38/* Calculated at init based on memory size */
39static unsigned int nf_nat_htable_size __read_mostly; 39static unsigned int nf_nat_htable_size __read_mostly;
40static int nf_nat_vmalloced;
41
42static struct hlist_head *bysource __read_mostly;
43 40
44#define MAX_IP_NAT_PROTO 256 41#define MAX_IP_NAT_PROTO 256
45static const struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO] 42static const struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]
@@ -145,7 +142,8 @@ same_src(const struct nf_conn *ct,
145 142
146/* Only called for SRC manip */ 143/* Only called for SRC manip */
147static int 144static int
148find_appropriate_src(const struct nf_conntrack_tuple *tuple, 145find_appropriate_src(struct net *net,
146 const struct nf_conntrack_tuple *tuple,
149 struct nf_conntrack_tuple *result, 147 struct nf_conntrack_tuple *result,
150 const struct nf_nat_range *range) 148 const struct nf_nat_range *range)
151{ 149{
@@ -155,7 +153,7 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple,
155 const struct hlist_node *n; 153 const struct hlist_node *n;
156 154
157 rcu_read_lock(); 155 rcu_read_lock();
158 hlist_for_each_entry_rcu(nat, n, &bysource[h], bysource) { 156 hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) {
159 ct = nat->ct; 157 ct = nat->ct;
160 if (same_src(ct, tuple)) { 158 if (same_src(ct, tuple)) {
161 /* Copy source part from reply tuple. */ 159 /* Copy source part from reply tuple. */
@@ -231,6 +229,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
231 struct nf_conn *ct, 229 struct nf_conn *ct,
232 enum nf_nat_manip_type maniptype) 230 enum nf_nat_manip_type maniptype)
233{ 231{
232 struct net *net = nf_ct_net(ct);
234 const struct nf_nat_protocol *proto; 233 const struct nf_nat_protocol *proto;
235 234
236 /* 1) If this srcip/proto/src-proto-part is currently mapped, 235 /* 1) If this srcip/proto/src-proto-part is currently mapped,
@@ -242,7 +241,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
242 manips not an issue. */ 241 manips not an issue. */
243 if (maniptype == IP_NAT_MANIP_SRC && 242 if (maniptype == IP_NAT_MANIP_SRC &&
244 !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { 243 !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
245 if (find_appropriate_src(orig_tuple, tuple, range)) { 244 if (find_appropriate_src(net, orig_tuple, tuple, range)) {
246 pr_debug("get_unique_tuple: Found current src map\n"); 245 pr_debug("get_unique_tuple: Found current src map\n");
247 if (!nf_nat_used_tuple(tuple, ct)) 246 if (!nf_nat_used_tuple(tuple, ct))
248 return; 247 return;
@@ -283,6 +282,7 @@ nf_nat_setup_info(struct nf_conn *ct,
283 const struct nf_nat_range *range, 282 const struct nf_nat_range *range,
284 enum nf_nat_manip_type maniptype) 283 enum nf_nat_manip_type maniptype)
285{ 284{
285 struct net *net = nf_ct_net(ct);
286 struct nf_conntrack_tuple curr_tuple, new_tuple; 286 struct nf_conntrack_tuple curr_tuple, new_tuple;
287 struct nf_conn_nat *nat; 287 struct nf_conn_nat *nat;
288 int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); 288 int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
@@ -334,7 +334,8 @@ nf_nat_setup_info(struct nf_conn *ct,
334 /* nf_conntrack_alter_reply might re-allocate exntension aera */ 334 /* nf_conntrack_alter_reply might re-allocate exntension aera */
335 nat = nfct_nat(ct); 335 nat = nfct_nat(ct);
336 nat->ct = ct; 336 nat->ct = ct;
337 hlist_add_head_rcu(&nat->bysource, &bysource[srchash]); 337 hlist_add_head_rcu(&nat->bysource,
338 &net->ipv4.nat_bysource[srchash]);
338 spin_unlock_bh(&nf_nat_lock); 339 spin_unlock_bh(&nf_nat_lock);
339 } 340 }
340 341
@@ -583,6 +584,40 @@ static struct nf_ct_ext_type nat_extend __read_mostly = {
583 .flags = NF_CT_EXT_F_PREALLOC, 584 .flags = NF_CT_EXT_F_PREALLOC,
584}; 585};
585 586
587static int __net_init nf_nat_net_init(struct net *net)
588{
589 net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
590 &net->ipv4.nat_vmalloced);
591 if (!net->ipv4.nat_bysource)
592 return -ENOMEM;
593 return 0;
594}
595
596/* Clear NAT section of all conntracks, in case we're loaded again. */
597static int clean_nat(struct nf_conn *i, void *data)
598{
599 struct nf_conn_nat *nat = nfct_nat(i);
600
601 if (!nat)
602 return 0;
603 memset(nat, 0, sizeof(*nat));
604 i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
605 return 0;
606}
607
608static void __net_exit nf_nat_net_exit(struct net *net)
609{
610 nf_ct_iterate_cleanup(net, &clean_nat, NULL);
611 synchronize_rcu();
612 nf_ct_free_hashtable(net->ipv4.nat_bysource, net->ipv4.nat_vmalloced,
613 nf_nat_htable_size);
614}
615
616static struct pernet_operations nf_nat_net_ops = {
617 .init = nf_nat_net_init,
618 .exit = nf_nat_net_exit,
619};
620
586static int __init nf_nat_init(void) 621static int __init nf_nat_init(void)
587{ 622{
588 size_t i; 623 size_t i;
@@ -599,12 +634,9 @@ static int __init nf_nat_init(void)
599 /* Leave them the same for the moment. */ 634 /* Leave them the same for the moment. */
600 nf_nat_htable_size = nf_conntrack_htable_size; 635 nf_nat_htable_size = nf_conntrack_htable_size;
601 636
602 bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, 637 ret = register_pernet_subsys(&nf_nat_net_ops);
603 &nf_nat_vmalloced); 638 if (ret < 0)
604 if (!bysource) {
605 ret = -ENOMEM;
606 goto cleanup_extend; 639 goto cleanup_extend;
607 }
608 640
609 /* Sew in builtin protocols. */ 641 /* Sew in builtin protocols. */
610 spin_lock_bh(&nf_nat_lock); 642 spin_lock_bh(&nf_nat_lock);
@@ -629,23 +661,9 @@ static int __init nf_nat_init(void)
629 return ret; 661 return ret;
630} 662}
631 663
632/* Clear NAT section of all conntracks, in case we're loaded again. */
633static int clean_nat(struct nf_conn *i, void *data)
634{
635 struct nf_conn_nat *nat = nfct_nat(i);
636
637 if (!nat)
638 return 0;
639 memset(nat, 0, sizeof(*nat));
640 i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
641 return 0;
642}
643
644static void __exit nf_nat_cleanup(void) 664static void __exit nf_nat_cleanup(void)
645{ 665{
646 nf_ct_iterate_cleanup(&clean_nat, NULL); 666 unregister_pernet_subsys(&nf_nat_net_ops);
647 synchronize_rcu();
648 nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
649 nf_ct_l3proto_put(l3proto); 667 nf_ct_l3proto_put(l3proto);
650 nf_ct_extend_unregister(&nat_extend); 668 nf_ct_extend_unregister(&nat_extend);
651 rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL); 669 rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 112dcfa12900..cf7a42bf9820 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -193,7 +193,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb,
193 nf_conntrack_tcp_update(skb, ip_hdrlen(skb), 193 nf_conntrack_tcp_update(skb, ip_hdrlen(skb),
194 ct, CTINFO2DIR(ctinfo)); 194 ct, CTINFO2DIR(ctinfo));
195 195
196 nf_conntrack_event_cache(IPCT_NATSEQADJ, skb); 196 nf_conntrack_event_cache(IPCT_NATSEQADJ, ct);
197 } 197 }
198 return 1; 198 return 1;
199} 199}
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index da3d91a5ef5c..9eb171056c63 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -40,6 +40,7 @@ MODULE_ALIAS("ip_nat_pptp");
40static void pptp_nat_expected(struct nf_conn *ct, 40static void pptp_nat_expected(struct nf_conn *ct,
41 struct nf_conntrack_expect *exp) 41 struct nf_conntrack_expect *exp)
42{ 42{
43 struct net *net = nf_ct_net(ct);
43 const struct nf_conn *master = ct->master; 44 const struct nf_conn *master = ct->master;
44 struct nf_conntrack_expect *other_exp; 45 struct nf_conntrack_expect *other_exp;
45 struct nf_conntrack_tuple t; 46 struct nf_conntrack_tuple t;
@@ -73,7 +74,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
73 74
74 pr_debug("trying to unexpect other dir: "); 75 pr_debug("trying to unexpect other dir: ");
75 nf_ct_dump_tuple_ip(&t); 76 nf_ct_dump_tuple_ip(&t);
76 other_exp = nf_ct_expect_find_get(&t); 77 other_exp = nf_ct_expect_find_get(net, &t);
77 if (other_exp) { 78 if (other_exp) {
78 nf_ct_unexpect_related(other_exp); 79 nf_ct_unexpect_related(other_exp);
79 nf_ct_expect_put(other_exp); 80 nf_ct_expect_put(other_exp);
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index e8b4d0d4439e..bea54a685109 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -33,7 +33,7 @@ static struct
33 struct ipt_replace repl; 33 struct ipt_replace repl;
34 struct ipt_standard entries[3]; 34 struct ipt_standard entries[3];
35 struct ipt_error term; 35 struct ipt_error term;
36} nat_initial_table __initdata = { 36} nat_initial_table __net_initdata = {
37 .repl = { 37 .repl = {
38 .name = "nat", 38 .name = "nat",
39 .valid_hooks = NAT_VALID_HOOKS, 39 .valid_hooks = NAT_VALID_HOOKS,
@@ -58,47 +58,42 @@ static struct
58 .term = IPT_ERROR_INIT, /* ERROR */ 58 .term = IPT_ERROR_INIT, /* ERROR */
59}; 59};
60 60
61static struct xt_table __nat_table = { 61static struct xt_table nat_table = {
62 .name = "nat", 62 .name = "nat",
63 .valid_hooks = NAT_VALID_HOOKS, 63 .valid_hooks = NAT_VALID_HOOKS,
64 .lock = __RW_LOCK_UNLOCKED(__nat_table.lock), 64 .lock = __RW_LOCK_UNLOCKED(__nat_table.lock),
65 .me = THIS_MODULE, 65 .me = THIS_MODULE,
66 .af = AF_INET, 66 .af = AF_INET,
67}; 67};
68static struct xt_table *nat_table;
69 68
70/* Source NAT */ 69/* Source NAT */
71static unsigned int ipt_snat_target(struct sk_buff *skb, 70static unsigned int
72 const struct net_device *in, 71ipt_snat_target(struct sk_buff *skb, const struct xt_target_param *par)
73 const struct net_device *out,
74 unsigned int hooknum,
75 const struct xt_target *target,
76 const void *targinfo)
77{ 72{
78 struct nf_conn *ct; 73 struct nf_conn *ct;
79 enum ip_conntrack_info ctinfo; 74 enum ip_conntrack_info ctinfo;
80 const struct nf_nat_multi_range_compat *mr = targinfo; 75 const struct nf_nat_multi_range_compat *mr = par->targinfo;
81 76
82 NF_CT_ASSERT(hooknum == NF_INET_POST_ROUTING); 77 NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING);
83 78
84 ct = nf_ct_get(skb, &ctinfo); 79 ct = nf_ct_get(skb, &ctinfo);
85 80
86 /* Connection must be valid and new. */ 81 /* Connection must be valid and new. */
87 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || 82 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
88 ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); 83 ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
89 NF_CT_ASSERT(out); 84 NF_CT_ASSERT(par->out != NULL);
90 85
91 return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); 86 return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC);
92} 87}
93 88
94/* Before 2.6.11 we did implicit source NAT if required. Warn about change. */ 89/* Before 2.6.11 we did implicit source NAT if required. Warn about change. */
95static void warn_if_extra_mangle(__be32 dstip, __be32 srcip) 90static void warn_if_extra_mangle(struct net *net, __be32 dstip, __be32 srcip)
96{ 91{
97 static int warned = 0; 92 static int warned = 0;
98 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } }; 93 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
99 struct rtable *rt; 94 struct rtable *rt;
100 95
101 if (ip_route_output_key(&init_net, &rt, &fl) != 0) 96 if (ip_route_output_key(net, &rt, &fl) != 0)
102 return; 97 return;
103 98
104 if (rt->rt_src != srcip && !warned) { 99 if (rt->rt_src != srcip && !warned) {
@@ -110,40 +105,32 @@ static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
110 ip_rt_put(rt); 105 ip_rt_put(rt);
111} 106}
112 107
113static unsigned int ipt_dnat_target(struct sk_buff *skb, 108static unsigned int
114 const struct net_device *in, 109ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par)
115 const struct net_device *out,
116 unsigned int hooknum,
117 const struct xt_target *target,
118 const void *targinfo)
119{ 110{
120 struct nf_conn *ct; 111 struct nf_conn *ct;
121 enum ip_conntrack_info ctinfo; 112 enum ip_conntrack_info ctinfo;
122 const struct nf_nat_multi_range_compat *mr = targinfo; 113 const struct nf_nat_multi_range_compat *mr = par->targinfo;
123 114
124 NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING || 115 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
125 hooknum == NF_INET_LOCAL_OUT); 116 par->hooknum == NF_INET_LOCAL_OUT);
126 117
127 ct = nf_ct_get(skb, &ctinfo); 118 ct = nf_ct_get(skb, &ctinfo);
128 119
129 /* Connection must be valid and new. */ 120 /* Connection must be valid and new. */
130 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); 121 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
131 122
132 if (hooknum == NF_INET_LOCAL_OUT && 123 if (par->hooknum == NF_INET_LOCAL_OUT &&
133 mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) 124 mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
134 warn_if_extra_mangle(ip_hdr(skb)->daddr, 125 warn_if_extra_mangle(dev_net(par->out), ip_hdr(skb)->daddr,
135 mr->range[0].min_ip); 126 mr->range[0].min_ip);
136 127
137 return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); 128 return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST);
138} 129}
139 130
140static bool ipt_snat_checkentry(const char *tablename, 131static bool ipt_snat_checkentry(const struct xt_tgchk_param *par)
141 const void *entry,
142 const struct xt_target *target,
143 void *targinfo,
144 unsigned int hook_mask)
145{ 132{
146 const struct nf_nat_multi_range_compat *mr = targinfo; 133 const struct nf_nat_multi_range_compat *mr = par->targinfo;
147 134
148 /* Must be a valid range */ 135 /* Must be a valid range */
149 if (mr->rangesize != 1) { 136 if (mr->rangesize != 1) {
@@ -153,13 +140,9 @@ static bool ipt_snat_checkentry(const char *tablename,
153 return true; 140 return true;
154} 141}
155 142
156static bool ipt_dnat_checkentry(const char *tablename, 143static bool ipt_dnat_checkentry(const struct xt_tgchk_param *par)
157 const void *entry,
158 const struct xt_target *target,
159 void *targinfo,
160 unsigned int hook_mask)
161{ 144{
162 const struct nf_nat_multi_range_compat *mr = targinfo; 145 const struct nf_nat_multi_range_compat *mr = par->targinfo;
163 146
164 /* Must be a valid range */ 147 /* Must be a valid range */
165 if (mr->rangesize != 1) { 148 if (mr->rangesize != 1) {
@@ -194,9 +177,10 @@ int nf_nat_rule_find(struct sk_buff *skb,
194 const struct net_device *out, 177 const struct net_device *out,
195 struct nf_conn *ct) 178 struct nf_conn *ct)
196{ 179{
180 struct net *net = nf_ct_net(ct);
197 int ret; 181 int ret;
198 182
199 ret = ipt_do_table(skb, hooknum, in, out, nat_table); 183 ret = ipt_do_table(skb, hooknum, in, out, net->ipv4.nat_table);
200 184
201 if (ret == NF_ACCEPT) { 185 if (ret == NF_ACCEPT) {
202 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) 186 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
@@ -226,14 +210,32 @@ static struct xt_target ipt_dnat_reg __read_mostly = {
226 .family = AF_INET, 210 .family = AF_INET,
227}; 211};
228 212
213static int __net_init nf_nat_rule_net_init(struct net *net)
214{
215 net->ipv4.nat_table = ipt_register_table(net, &nat_table,
216 &nat_initial_table.repl);
217 if (IS_ERR(net->ipv4.nat_table))
218 return PTR_ERR(net->ipv4.nat_table);
219 return 0;
220}
221
222static void __net_exit nf_nat_rule_net_exit(struct net *net)
223{
224 ipt_unregister_table(net->ipv4.nat_table);
225}
226
227static struct pernet_operations nf_nat_rule_net_ops = {
228 .init = nf_nat_rule_net_init,
229 .exit = nf_nat_rule_net_exit,
230};
231
229int __init nf_nat_rule_init(void) 232int __init nf_nat_rule_init(void)
230{ 233{
231 int ret; 234 int ret;
232 235
233 nat_table = ipt_register_table(&init_net, &__nat_table, 236 ret = register_pernet_subsys(&nf_nat_rule_net_ops);
234 &nat_initial_table.repl); 237 if (ret != 0)
235 if (IS_ERR(nat_table)) 238 goto out;
236 return PTR_ERR(nat_table);
237 ret = xt_register_target(&ipt_snat_reg); 239 ret = xt_register_target(&ipt_snat_reg);
238 if (ret != 0) 240 if (ret != 0)
239 goto unregister_table; 241 goto unregister_table;
@@ -247,8 +249,8 @@ int __init nf_nat_rule_init(void)
247 unregister_snat: 249 unregister_snat:
248 xt_unregister_target(&ipt_snat_reg); 250 xt_unregister_target(&ipt_snat_reg);
249 unregister_table: 251 unregister_table:
250 ipt_unregister_table(nat_table); 252 unregister_pernet_subsys(&nf_nat_rule_net_ops);
251 253 out:
252 return ret; 254 return ret;
253} 255}
254 256
@@ -256,5 +258,5 @@ void nf_nat_rule_cleanup(void)
256{ 258{
257 xt_unregister_target(&ipt_dnat_reg); 259 xt_unregister_target(&ipt_dnat_reg);
258 xt_unregister_target(&ipt_snat_reg); 260 xt_unregister_target(&ipt_snat_reg);
259 ipt_unregister_table(nat_table); 261 unregister_pernet_subsys(&nf_nat_rule_net_ops);
260} 262}