aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/netfilter/ebt_log.c1
-rw-r--r--net/ipv4/netfilter/Kconfig250
-rw-r--r--net/ipv4/netfilter/Makefile21
-rw-r--r--net/ipv4/netfilter/arp_tables.c444
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c7
-rw-r--r--net/ipv4/netfilter/arptable_filter.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c842
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c3
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c2
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c3
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c2
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c2
-rw-r--r--net/ipv4/netfilter/ipt_NFQUEUE.c70
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c2
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c3
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c2
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c3
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c2
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c2
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c4
-rw-r--r--net/ipv4/netfilter/ipt_ah.c6
-rw-r--r--net/ipv4/netfilter/ipt_dscp.c4
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c5
-rw-r--r--net/ipv4/netfilter/ipt_esp.c6
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c3
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c4
-rw-r--r--net/ipv4/netfilter/ipt_length.c64
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c10
-rw-r--r--net/ipv4/netfilter/ipt_owner.c3
-rw-r--r--net/ipv4/netfilter/ipt_physdev.c135
-rw-r--r--net/ipv4/netfilter/ipt_recent.c6
-rw-r--r--net/ipv4/netfilter/ipt_tos.c3
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c4
-rw-r--r--net/ipv4/netfilter/iptable_filter.c3
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c1
-rw-r--r--net/ipv4/netfilter/iptable_raw.c3
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c7
-rw-r--r--net/ipv6/netfilter/Kconfig72
-rw-r--r--net/ipv6/netfilter/Makefile6
-rw-r--r--net/ipv6/netfilter/ip6_tables.c828
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c2
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c2
-rw-r--r--net/ipv6/netfilter/ip6t_MARK.c81
-rw-r--r--net/ipv6/netfilter/ip6t_NFQUEUE.c70
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c3
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c2
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c2
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c2
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c2
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c2
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c2
-rw-r--r--net/ipv6/netfilter/ip6t_length.c66
-rw-r--r--net/ipv6/netfilter/ip6t_limit.c147
-rw-r--r--net/ipv6/netfilter/ip6t_mac.c81
-rw-r--r--net/ipv6/netfilter/ip6t_mark.c66
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c3
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c2
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c2
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c1
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c1
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c8
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c45
-rw-r--r--net/netfilter/Kconfig258
-rw-r--r--net/netfilter/Makefile37
-rw-r--r--net/netfilter/nf_conntrack_standalone.c4
-rw-r--r--net/netfilter/x_tables.c624
-rw-r--r--net/netfilter/xt_CLASSIFY.c (renamed from net/ipv4/netfilter/ipt_CLASSIFY.c)41
-rw-r--r--net/netfilter/xt_CONNMARK.c (renamed from net/ipv4/netfilter/ipt_CONNMARK.c)51
-rw-r--r--net/netfilter/xt_MARK.c (renamed from net/ipv4/netfilter/ipt_MARK.c)79
-rw-r--r--net/netfilter/xt_NFQUEUE.c107
-rw-r--r--net/netfilter/xt_NOTRACK.c (renamed from net/ipv4/netfilter/ipt_NOTRACK.c)38
-rw-r--r--net/netfilter/xt_comment.c (renamed from net/ipv4/netfilter/ipt_comment.c)35
-rw-r--r--net/netfilter/xt_connbytes.c (renamed from net/ipv4/netfilter/ipt_connbytes.c)73
-rw-r--r--net/netfilter/xt_connmark.c (renamed from net/ipv4/netfilter/ipt_connmark.c)41
-rw-r--r--net/netfilter/xt_conntrack.c (renamed from net/ipv4/netfilter/ipt_conntrack.c)110
-rw-r--r--net/netfilter/xt_dccp.c (renamed from net/ipv4/netfilter/ipt_dccp.c)105
-rw-r--r--net/netfilter/xt_helper.c (renamed from net/ipv4/netfilter/ipt_helper.c)56
-rw-r--r--net/netfilter/xt_length.c98
-rw-r--r--net/netfilter/xt_limit.c (renamed from net/ipv4/netfilter/ipt_limit.c)48
-rw-r--r--net/netfilter/xt_mac.c (renamed from net/ipv4/netfilter/ipt_mac.c)38
-rw-r--r--net/netfilter/xt_mark.c (renamed from net/ipv4/netfilter/ipt_mark.c)38
-rw-r--r--net/netfilter/xt_physdev.c (renamed from net/ipv6/netfilter/ip6t_physdev.c)82
-rw-r--r--net/netfilter/xt_pkttype.c (renamed from net/ipv4/netfilter/ipt_pkttype.c)46
-rw-r--r--net/netfilter/xt_realm.c (renamed from net/ipv4/netfilter/ipt_realm.c)25
-rw-r--r--net/netfilter/xt_sctp.c (renamed from net/ipv4/netfilter/ipt_sctp.c)109
-rw-r--r--net/netfilter/xt_state.c (renamed from net/ipv4/netfilter/ipt_state.c)50
-rw-r--r--net/netfilter/xt_string.c (renamed from net/ipv4/netfilter/ipt_string.c)40
-rw-r--r--net/netfilter/xt_tcpmss.c (renamed from net/ipv4/netfilter/ipt_tcpmss.c)69
-rw-r--r--net/netfilter/xt_tcpudp.c333
-rw-r--r--net/sched/act_ipt.c2
98 files changed, 2646 insertions, 3446 deletions
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 9f6e0193ae10..a29c1232c420 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -15,6 +15,7 @@
15#include <linux/netfilter.h> 15#include <linux/netfilter.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/ip.h> 17#include <linux/ip.h>
18#include <linux/in.h>
18#include <linux/if_arp.h> 19#include <linux/if_arp.h>
19#include <linux/spinlock.h> 20#include <linux/spinlock.h>
20 21
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index a9893ec03e02..db783036e4d8 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -182,6 +182,7 @@ config IP_NF_QUEUE
182 182
183config IP_NF_IPTABLES 183config IP_NF_IPTABLES
184 tristate "IP tables support (required for filtering/masq/NAT)" 184 tristate "IP tables support (required for filtering/masq/NAT)"
185 depends on NETFILTER_XTABLES
185 help 186 help
186 iptables is a general, extensible packet identification framework. 187 iptables is a general, extensible packet identification framework.
187 The packet filtering and full NAT (masquerading, port forwarding, 188 The packet filtering and full NAT (masquerading, port forwarding,
@@ -191,16 +192,6 @@ config IP_NF_IPTABLES
191 To compile it as a module, choose M here. If unsure, say N. 192 To compile it as a module, choose M here. If unsure, say N.
192 193
193# The matches. 194# The matches.
194config IP_NF_MATCH_LIMIT
195 tristate "limit match support"
196 depends on IP_NF_IPTABLES
197 help
198 limit matching allows you to control the rate at which a rule can be
199 matched: mainly useful in combination with the LOG target ("LOG
200 target support", below) and to avoid some Denial of Service attacks.
201
202 To compile it as a module, choose M here. If unsure, say N.
203
204config IP_NF_MATCH_IPRANGE 195config IP_NF_MATCH_IPRANGE
205 tristate "IP range match support" 196 tristate "IP range match support"
206 depends on IP_NF_IPTABLES 197 depends on IP_NF_IPTABLES
@@ -210,37 +201,6 @@ config IP_NF_MATCH_IPRANGE
210 201
211 To compile it as a module, choose M here. If unsure, say N. 202 To compile it as a module, choose M here. If unsure, say N.
212 203
213config IP_NF_MATCH_MAC
214 tristate "MAC address match support"
215 depends on IP_NF_IPTABLES
216 help
217 MAC matching allows you to match packets based on the source
218 Ethernet address of the packet.
219
220 To compile it as a module, choose M here. If unsure, say N.
221
222config IP_NF_MATCH_PKTTYPE
223 tristate "Packet type match support"
224 depends on IP_NF_IPTABLES
225 help
226 Packet type matching allows you to match a packet by
227 its "class", eg. BROADCAST, MULTICAST, ...
228
229 Typical usage:
230 iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
231
232 To compile it as a module, choose M here. If unsure, say N.
233
234config IP_NF_MATCH_MARK
235 tristate "netfilter MARK match support"
236 depends on IP_NF_IPTABLES
237 help
238 Netfilter mark matching allows you to match packets based on the
239 `nfmark' value in the packet. This can be set by the MARK target
240 (see below).
241
242 To compile it as a module, choose M here. If unsure, say N.
243
244config IP_NF_MATCH_MULTIPORT 204config IP_NF_MATCH_MULTIPORT
245 tristate "Multiple port match support" 205 tristate "Multiple port match support"
246 depends on IP_NF_IPTABLES 206 depends on IP_NF_IPTABLES
@@ -301,15 +261,6 @@ config IP_NF_MATCH_AH_ESP
301 261
302 To compile it as a module, choose M here. If unsure, say N. 262 To compile it as a module, choose M here. If unsure, say N.
303 263
304config IP_NF_MATCH_LENGTH
305 tristate "LENGTH match support"
306 depends on IP_NF_IPTABLES
307 help
308 This option allows you to match the length of a packet against a
309 specific value or range of values.
310
311 To compile it as a module, choose M here. If unsure, say N.
312
313config IP_NF_MATCH_TTL 264config IP_NF_MATCH_TTL
314 tristate "TTL match support" 265 tristate "TTL match support"
315 depends on IP_NF_IPTABLES 266 depends on IP_NF_IPTABLES
@@ -319,50 +270,6 @@ config IP_NF_MATCH_TTL
319 270
320 To compile it as a module, choose M here. If unsure, say N. 271 To compile it as a module, choose M here. If unsure, say N.
321 272
322config IP_NF_MATCH_TCPMSS
323 tristate "tcpmss match support"
324 depends on IP_NF_IPTABLES
325 help
326 This option adds a `tcpmss' match, which allows you to examine the
327 MSS value of TCP SYN packets, which control the maximum packet size
328 for that connection.
329
330 To compile it as a module, choose M here. If unsure, say N.
331
332config IP_NF_MATCH_HELPER
333 tristate "Helper match support"
334 depends on IP_NF_IPTABLES
335 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
336 help
337 Helper matching allows you to match packets in dynamic connections
338 tracked by a conntrack-helper, ie. ip_conntrack_ftp
339
340 To compile it as a module, choose M here. If unsure, say Y.
341
342config IP_NF_MATCH_STATE
343 tristate "Connection state match support"
344 depends on IP_NF_IPTABLES
345 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
346 help
347 Connection state matching allows you to match packets based on their
348 relationship to a tracked connection (ie. previous packets). This
349 is a powerful tool for packet classification.
350
351 To compile it as a module, choose M here. If unsure, say N.
352
353config IP_NF_MATCH_CONNTRACK
354 tristate "Connection tracking match support"
355 depends on IP_NF_IPTABLES
356 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
357 help
358 This is a general conntrack match module, a superset of the state match.
359
360 It allows matching on additional conntrack information, which is
361 useful in complex configurations, such as NAT gateways with multiple
362 internet links or tunnels.
363
364 To compile it as a module, choose M here. If unsure, say N.
365
366config IP_NF_MATCH_OWNER 273config IP_NF_MATCH_OWNER
367 tristate "Owner match support" 274 tristate "Owner match support"
368 depends on IP_NF_IPTABLES 275 depends on IP_NF_IPTABLES
@@ -372,15 +279,6 @@ config IP_NF_MATCH_OWNER
372 279
373 To compile it as a module, choose M here. If unsure, say N. 280 To compile it as a module, choose M here. If unsure, say N.
374 281
375config IP_NF_MATCH_PHYSDEV
376 tristate "Physdev match support"
377 depends on IP_NF_IPTABLES && BRIDGE_NETFILTER
378 help
379 Physdev packet matching matches against the physical bridge ports
380 the IP packet arrived on or will leave by.
381
382 To compile it as a module, choose M here. If unsure, say N.
383
384config IP_NF_MATCH_ADDRTYPE 282config IP_NF_MATCH_ADDRTYPE
385 tristate 'address type match support' 283 tristate 'address type match support'
386 depends on IP_NF_IPTABLES 284 depends on IP_NF_IPTABLES
@@ -391,75 +289,6 @@ config IP_NF_MATCH_ADDRTYPE
391 If you want to compile it as a module, say M here and read 289 If you want to compile it as a module, say M here and read
392 <file:Documentation/modules.txt>. If unsure, say `N'. 290 <file:Documentation/modules.txt>. If unsure, say `N'.
393 291
394config IP_NF_MATCH_REALM
395 tristate 'realm match support'
396 depends on IP_NF_IPTABLES
397 select NET_CLS_ROUTE
398 help
399 This option adds a `realm' match, which allows you to use the realm
400 key from the routing subsystem inside iptables.
401
402 This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
403 in tc world.
404
405 If you want to compile it as a module, say M here and read
406 <file:Documentation/modules.txt>. If unsure, say `N'.
407
408config IP_NF_MATCH_SCTP
409 tristate 'SCTP protocol match support'
410 depends on IP_NF_IPTABLES
411 help
412 With this option enabled, you will be able to use the iptables
413 `sctp' match in order to match on SCTP source/destination ports
414 and SCTP chunk types.
415
416 If you want to compile it as a module, say M here and read
417 <file:Documentation/modules.txt>. If unsure, say `N'.
418
419config IP_NF_MATCH_DCCP
420 tristate 'DCCP protocol match support'
421 depends on IP_NF_IPTABLES
422 help
423 With this option enabled, you will be able to use the iptables
424 `dccp' match in order to match on DCCP source/destination ports
425 and DCCP flags.
426
427 If you want to compile it as a module, say M here and read
428 <file:Documentation/modules.txt>. If unsure, say `N'.
429
430config IP_NF_MATCH_COMMENT
431 tristate 'comment match support'
432 depends on IP_NF_IPTABLES
433 help
434 This option adds a `comment' dummy-match, which allows you to put
435 comments in your iptables ruleset.
436
437 If you want to compile it as a module, say M here and read
438 <file:Documentation/modules.txt>. If unsure, say `N'.
439
440config IP_NF_MATCH_CONNMARK
441 tristate 'Connection mark match support'
442 depends on IP_NF_IPTABLES
443 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
444 help
445 This option adds a `connmark' match, which allows you to match the
446 connection mark value previously set for the session by `CONNMARK'.
447
448 If you want to compile it as a module, say M here and read
449 <file:Documentation/modules.txt>. The module will be called
450 ipt_connmark.o. If unsure, say `N'.
451
452config IP_NF_MATCH_CONNBYTES
453 tristate 'Connection byte/packet counter match support'
454 depends on IP_NF_IPTABLES
455 depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK_IPV4)
456 help
457 This option adds a `connbytes' match, which allows you to match the
458 number of bytes and/or packets for each direction within a connection.
459
460 If you want to compile it as a module, say M here and read
461 <file:Documentation/modules.txt>. If unsure, say `N'.
462
463config IP_NF_MATCH_HASHLIMIT 292config IP_NF_MATCH_HASHLIMIT
464 tristate 'hashlimit match support' 293 tristate 'hashlimit match support'
465 depends on IP_NF_IPTABLES 294 depends on IP_NF_IPTABLES
@@ -474,19 +303,6 @@ config IP_NF_MATCH_HASHLIMIT
474 destination IP' or `500pps from any given source IP' with a single 303 destination IP' or `500pps from any given source IP' with a single
475 IPtables rule. 304 IPtables rule.
476 305
477config IP_NF_MATCH_STRING
478 tristate 'string match support'
479 depends on IP_NF_IPTABLES
480 select TEXTSEARCH
481 select TEXTSEARCH_KMP
482 select TEXTSEARCH_BM
483 select TEXTSEARCH_FSM
484 help
485 This option adds a `string' match, which allows you to look for
486 pattern matchings in packets.
487
488 To compile it as a module, choose M here. If unsure, say N.
489
490config IP_NF_MATCH_POLICY 306config IP_NF_MATCH_POLICY
491 tristate "IPsec policy match support" 307 tristate "IPsec policy match support"
492 depends on IP_NF_IPTABLES && XFRM 308 depends on IP_NF_IPTABLES && XFRM
@@ -572,17 +388,6 @@ config IP_NF_TARGET_TCPMSS
572 388
573 To compile it as a module, choose M here. If unsure, say N. 389 To compile it as a module, choose M here. If unsure, say N.
574 390
575config IP_NF_TARGET_NFQUEUE
576 tristate "NFQUEUE Target Support"
577 depends on IP_NF_IPTABLES
578 help
579 This Target replaced the old obsolete QUEUE target.
580
581 As opposed to QUEUE, it supports 65535 different queues,
582 not just one.
583
584 To compile it as a module, choose M here. If unsure, say N.
585
586# NAT + specific targets 391# NAT + specific targets
587config IP_NF_NAT 392config IP_NF_NAT
588 tristate "Full NAT" 393 tristate "Full NAT"
@@ -735,31 +540,6 @@ config IP_NF_TARGET_DSCP
735 540
736 To compile it as a module, choose M here. If unsure, say N. 541 To compile it as a module, choose M here. If unsure, say N.
737 542
738config IP_NF_TARGET_MARK
739 tristate "MARK target support"
740 depends on IP_NF_MANGLE
741 help
742 This option adds a `MARK' target, which allows you to create rules
743 in the `mangle' table which alter the netfilter mark (nfmark) field
744 associated with the packet prior to routing. This can change
745 the routing method (see `Use netfilter MARK value as routing
746 key') and can also be used by other subsystems to change their
747 behavior.
748
749 To compile it as a module, choose M here. If unsure, say N.
750
751config IP_NF_TARGET_CLASSIFY
752 tristate "CLASSIFY target support"
753 depends on IP_NF_MANGLE
754 help
755 This option adds a `CLASSIFY' target, which enables the user to set
756 the priority of a packet. Some qdiscs can use this value for
757 classification, among these are:
758
759 atm, cbq, dsmark, pfifo_fast, htb, prio
760
761 To compile it as a module, choose M here. If unsure, say N.
762
763config IP_NF_TARGET_TTL 543config IP_NF_TARGET_TTL
764 tristate 'TTL target support' 544 tristate 'TTL target support'
765 depends on IP_NF_MANGLE 545 depends on IP_NF_MANGLE
@@ -774,19 +554,6 @@ config IP_NF_TARGET_TTL
774 554
775 To compile it as a module, choose M here. If unsure, say N. 555 To compile it as a module, choose M here. If unsure, say N.
776 556
777config IP_NF_TARGET_CONNMARK
778 tristate 'CONNMARK target support'
779 depends on IP_NF_MANGLE
780 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
781 help
782 This option adds a `CONNMARK' target, which allows one to manipulate
783 the connection mark value. Similar to the MARK target, but
784 affects the connection mark value rather than the packet mark value.
785
786 If you want to compile it as a module, say M here and read
787 <file:Documentation/modules.txt>. The module will be called
788 ipt_CONNMARK.o. If unsure, say `N'.
789
790config IP_NF_TARGET_CLUSTERIP 557config IP_NF_TARGET_CLUSTERIP
791 tristate "CLUSTERIP target support (EXPERIMENTAL)" 558 tristate "CLUSTERIP target support (EXPERIMENTAL)"
792 depends on IP_NF_MANGLE && EXPERIMENTAL 559 depends on IP_NF_MANGLE && EXPERIMENTAL
@@ -810,23 +577,10 @@ config IP_NF_RAW
810 If you want to compile it as a module, say M here and read 577 If you want to compile it as a module, say M here and read
811 <file:Documentation/modules.txt>. If unsure, say `N'. 578 <file:Documentation/modules.txt>. If unsure, say `N'.
812 579
813config IP_NF_TARGET_NOTRACK
814 tristate 'NOTRACK target support'
815 depends on IP_NF_RAW
816 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
817 help
818 The NOTRACK target allows a select rule to specify
819 which packets *not* to enter the conntrack/NAT
820 subsystem with all the consequences (no ICMP error tracking,
821 no protocol helpers for the selected packets).
822
823 If you want to compile it as a module, say M here and read
824 <file:Documentation/modules.txt>. If unsure, say `N'.
825
826
827# ARP tables 580# ARP tables
828config IP_NF_ARPTABLES 581config IP_NF_ARPTABLES
829 tristate "ARP tables support" 582 tristate "ARP tables support"
583 depends on NETFILTER_XTABLES
830 help 584 help
831 arptables is a general, extensible packet identification framework. 585 arptables is a general, extensible packet identification framework.
832 The ARP packet filtering and mangling (manipulation)subsystems 586 The ARP packet filtering and mangling (manipulation)subsystems
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 549b01a648b3..bcefe64b9317 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -47,14 +47,8 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
47 47
48# matches 48# matches
49obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o 49obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
50obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
51obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o 50obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
52obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
53obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o
54obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
55obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
56obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o 51obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
57obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
58obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o 52obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
59obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o 53obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
60obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o 54obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
@@ -62,40 +56,25 @@ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
62obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o 56obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
63obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o 57obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
64obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o 58obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
65obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
66obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 59obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
67obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
68obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
69obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
70obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
71obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
72obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
73obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o 60obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
74obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
75obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o 61obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
76obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o
77obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
78 62
79# targets 63# targets
80obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o 64obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
81obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o 65obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
82obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 66obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
83obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o 67obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
84obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
85obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 68obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
86obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 69obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
87obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 70obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
88obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o 71obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
89obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
90obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o 72obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
91obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 73obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
92obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
93obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o 74obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
94obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o 75obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
95obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
96obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 76obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
97obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o 77obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
98obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o
99 78
100# generic ARP tables 79# generic ARP tables
101obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o 80obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index b6d5284c8020..afe3d8f8177d 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -24,6 +24,7 @@
24#include <asm/uaccess.h> 24#include <asm/uaccess.h>
25#include <asm/semaphore.h> 25#include <asm/semaphore.h>
26 26
27#include <linux/netfilter/x_tables.h>
27#include <linux/netfilter_arp/arp_tables.h> 28#include <linux/netfilter_arp/arp_tables.h>
28 29
29MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
@@ -55,28 +56,9 @@ do { \
55#else 56#else
56#define ARP_NF_ASSERT(x) 57#define ARP_NF_ASSERT(x)
57#endif 58#endif
58#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
59 59
60static DECLARE_MUTEX(arpt_mutex);
61
62#define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
63#define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
64#include <linux/netfilter_ipv4/listhelp.h> 60#include <linux/netfilter_ipv4/listhelp.h>
65 61
66struct arpt_table_info {
67 unsigned int size;
68 unsigned int number;
69 unsigned int initial_entries;
70 unsigned int hook_entry[NF_ARP_NUMHOOKS];
71 unsigned int underflow[NF_ARP_NUMHOOKS];
72 void *entries[NR_CPUS];
73};
74
75static LIST_HEAD(arpt_target);
76static LIST_HEAD(arpt_tables);
77#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
78#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
79
80static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 62static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
81 char *hdr_addr, int len) 63 char *hdr_addr, int len)
82{ 64{
@@ -223,9 +205,9 @@ static inline int arp_checkentry(const struct arpt_arp *arp)
223} 205}
224 206
225static unsigned int arpt_error(struct sk_buff **pskb, 207static unsigned int arpt_error(struct sk_buff **pskb,
226 unsigned int hooknum,
227 const struct net_device *in, 208 const struct net_device *in,
228 const struct net_device *out, 209 const struct net_device *out,
210 unsigned int hooknum,
229 const void *targinfo, 211 const void *targinfo,
230 void *userinfo) 212 void *userinfo)
231{ 213{
@@ -254,6 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
254 struct arpt_entry *e, *back; 236 struct arpt_entry *e, *back;
255 const char *indev, *outdev; 237 const char *indev, *outdev;
256 void *table_base; 238 void *table_base;
239 struct xt_table_info *private = table->private;
257 240
258 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ 241 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
259 if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + 242 if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) +
@@ -265,9 +248,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
265 outdev = out ? out->name : nulldevname; 248 outdev = out ? out->name : nulldevname;
266 249
267 read_lock_bh(&table->lock); 250 read_lock_bh(&table->lock);
268 table_base = (void *)table->private->entries[smp_processor_id()]; 251 table_base = (void *)private->entries[smp_processor_id()];
269 e = get_entry(table_base, table->private->hook_entry[hook]); 252 e = get_entry(table_base, private->hook_entry[hook]);
270 back = get_entry(table_base, table->private->underflow[hook]); 253 back = get_entry(table_base, private->underflow[hook]);
271 254
272 arp = (*pskb)->nh.arph; 255 arp = (*pskb)->nh.arph;
273 do { 256 do {
@@ -315,8 +298,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
315 * abs. verdicts 298 * abs. verdicts
316 */ 299 */
317 verdict = t->u.kernel.target->target(pskb, 300 verdict = t->u.kernel.target->target(pskb,
318 hook,
319 in, out, 301 in, out,
302 hook,
320 t->data, 303 t->data,
321 userdata); 304 userdata);
322 305
@@ -341,106 +324,6 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
341 return verdict; 324 return verdict;
342} 325}
343 326
344/*
345 * These are weird, but module loading must not be done with mutex
346 * held (since they will register), and we have to have a single
347 * function to use try_then_request_module().
348 */
349
350/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
351static inline struct arpt_table *find_table_lock(const char *name)
352{
353 struct arpt_table *t;
354
355 if (down_interruptible(&arpt_mutex) != 0)
356 return ERR_PTR(-EINTR);
357
358 list_for_each_entry(t, &arpt_tables, list)
359 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
360 return t;
361 up(&arpt_mutex);
362 return NULL;
363}
364
365
366/* Find target, grabs ref. Returns ERR_PTR() on error. */
367static inline struct arpt_target *find_target(const char *name, u8 revision)
368{
369 struct arpt_target *t;
370 int err = 0;
371
372 if (down_interruptible(&arpt_mutex) != 0)
373 return ERR_PTR(-EINTR);
374
375 list_for_each_entry(t, &arpt_target, list) {
376 if (strcmp(t->name, name) == 0) {
377 if (t->revision == revision) {
378 if (try_module_get(t->me)) {
379 up(&arpt_mutex);
380 return t;
381 }
382 } else
383 err = -EPROTOTYPE; /* Found something. */
384 }
385 }
386 up(&arpt_mutex);
387 return ERR_PTR(err);
388}
389
390struct arpt_target *arpt_find_target(const char *name, u8 revision)
391{
392 struct arpt_target *target;
393
394 target = try_then_request_module(find_target(name, revision),
395 "arpt_%s", name);
396 if (IS_ERR(target) || !target)
397 return NULL;
398 return target;
399}
400
401static int target_revfn(const char *name, u8 revision, int *bestp)
402{
403 struct arpt_target *t;
404 int have_rev = 0;
405
406 list_for_each_entry(t, &arpt_target, list) {
407 if (strcmp(t->name, name) == 0) {
408 if (t->revision > *bestp)
409 *bestp = t->revision;
410 if (t->revision == revision)
411 have_rev =1;
412 }
413 }
414 return have_rev;
415}
416
417/* Returns true or false (if no such extension at all) */
418static inline int find_revision(const char *name, u8 revision,
419 int (*revfn)(const char *, u8, int *),
420 int *err)
421{
422 int have_rev, best = -1;
423
424 if (down_interruptible(&arpt_mutex) != 0) {
425 *err = -EINTR;
426 return 1;
427 }
428 have_rev = revfn(name, revision, &best);
429 up(&arpt_mutex);
430
431 /* Nothing at all? Return 0 to try loading module. */
432 if (best == -1) {
433 *err = -ENOENT;
434 return 0;
435 }
436
437 *err = best;
438 if (!have_rev)
439 *err = -EPROTONOSUPPORT;
440 return 1;
441}
442
443
444/* All zeroes == unconditional rule. */ 327/* All zeroes == unconditional rule. */
445static inline int unconditional(const struct arpt_arp *arp) 328static inline int unconditional(const struct arpt_arp *arp)
446{ 329{
@@ -456,7 +339,7 @@ static inline int unconditional(const struct arpt_arp *arp)
456/* Figures out from what hook each rule can be called: returns 0 if 339/* Figures out from what hook each rule can be called: returns 0 if
457 * there are loops. Puts hook bitmask in comefrom. 340 * there are loops. Puts hook bitmask in comefrom.
458 */ 341 */
459static int mark_source_chains(struct arpt_table_info *newinfo, 342static int mark_source_chains(struct xt_table_info *newinfo,
460 unsigned int valid_hooks, void *entry0) 343 unsigned int valid_hooks, void *entry0)
461{ 344{
462 unsigned int hook; 345 unsigned int hook;
@@ -587,8 +470,8 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
587 } 470 }
588 471
589 t = arpt_get_target(e); 472 t = arpt_get_target(e);
590 target = try_then_request_module(find_target(t->u.user.name, 473 target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name,
591 t->u.user.revision), 474 t->u.user.revision),
592 "arpt_%s", t->u.user.name); 475 "arpt_%s", t->u.user.name);
593 if (IS_ERR(target) || !target) { 476 if (IS_ERR(target) || !target) {
594 duprintf("check_entry: `%s' not found\n", t->u.user.name); 477 duprintf("check_entry: `%s' not found\n", t->u.user.name);
@@ -622,7 +505,7 @@ out:
622} 505}
623 506
624static inline int check_entry_size_and_hooks(struct arpt_entry *e, 507static inline int check_entry_size_and_hooks(struct arpt_entry *e,
625 struct arpt_table_info *newinfo, 508 struct xt_table_info *newinfo,
626 unsigned char *base, 509 unsigned char *base,
627 unsigned char *limit, 510 unsigned char *limit,
628 const unsigned int *hook_entries, 511 const unsigned int *hook_entries,
@@ -656,7 +539,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
656 < 0 (not ARPT_RETURN). --RR */ 539 < 0 (not ARPT_RETURN). --RR */
657 540
658 /* Clear counters and comefrom */ 541 /* Clear counters and comefrom */
659 e->counters = ((struct arpt_counters) { 0, 0 }); 542 e->counters = ((struct xt_counters) { 0, 0 });
660 e->comefrom = 0; 543 e->comefrom = 0;
661 544
662 (*i)++; 545 (*i)++;
@@ -683,7 +566,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)
683 */ 566 */
684static int translate_table(const char *name, 567static int translate_table(const char *name,
685 unsigned int valid_hooks, 568 unsigned int valid_hooks,
686 struct arpt_table_info *newinfo, 569 struct xt_table_info *newinfo,
687 void *entry0, 570 void *entry0,
688 unsigned int size, 571 unsigned int size,
689 unsigned int number, 572 unsigned int number,
@@ -764,34 +647,9 @@ static int translate_table(const char *name,
764 return ret; 647 return ret;
765} 648}
766 649
767static struct arpt_table_info *replace_table(struct arpt_table *table,
768 unsigned int num_counters,
769 struct arpt_table_info *newinfo,
770 int *error)
771{
772 struct arpt_table_info *oldinfo;
773
774 /* Do the substitution. */
775 write_lock_bh(&table->lock);
776 /* Check inside lock: is the old number correct? */
777 if (num_counters != table->private->number) {
778 duprintf("num_counters != table->private->number (%u/%u)\n",
779 num_counters, table->private->number);
780 write_unlock_bh(&table->lock);
781 *error = -EAGAIN;
782 return NULL;
783 }
784 oldinfo = table->private;
785 table->private = newinfo;
786 newinfo->initial_entries = oldinfo->initial_entries;
787 write_unlock_bh(&table->lock);
788
789 return oldinfo;
790}
791
792/* Gets counters. */ 650/* Gets counters. */
793static inline int add_entry_to_counter(const struct arpt_entry *e, 651static inline int add_entry_to_counter(const struct arpt_entry *e,
794 struct arpt_counters total[], 652 struct xt_counters total[],
795 unsigned int *i) 653 unsigned int *i)
796{ 654{
797 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 655 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -801,7 +659,7 @@ static inline int add_entry_to_counter(const struct arpt_entry *e,
801} 659}
802 660
803static inline int set_entry_to_counter(const struct arpt_entry *e, 661static inline int set_entry_to_counter(const struct arpt_entry *e,
804 struct arpt_counters total[], 662 struct xt_counters total[],
805 unsigned int *i) 663 unsigned int *i)
806{ 664{
807 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 665 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -810,8 +668,8 @@ static inline int set_entry_to_counter(const struct arpt_entry *e,
810 return 0; 668 return 0;
811} 669}
812 670
813static void get_counters(const struct arpt_table_info *t, 671static void get_counters(const struct xt_table_info *t,
814 struct arpt_counters counters[]) 672 struct xt_counters counters[])
815{ 673{
816 unsigned int cpu; 674 unsigned int cpu;
817 unsigned int i; 675 unsigned int i;
@@ -849,7 +707,8 @@ static int copy_entries_to_user(unsigned int total_size,
849{ 707{
850 unsigned int off, num, countersize; 708 unsigned int off, num, countersize;
851 struct arpt_entry *e; 709 struct arpt_entry *e;
852 struct arpt_counters *counters; 710 struct xt_counters *counters;
711 struct xt_table_info *private = table->private;
853 int ret = 0; 712 int ret = 0;
854 void *loc_cpu_entry; 713 void *loc_cpu_entry;
855 714
@@ -857,18 +716,18 @@ static int copy_entries_to_user(unsigned int total_size,
857 * (other than comefrom, which userspace doesn't care 716 * (other than comefrom, which userspace doesn't care
858 * about). 717 * about).
859 */ 718 */
860 countersize = sizeof(struct arpt_counters) * table->private->number; 719 countersize = sizeof(struct xt_counters) * private->number;
861 counters = vmalloc(countersize); 720 counters = vmalloc_node(countersize, numa_node_id());
862 721
863 if (counters == NULL) 722 if (counters == NULL)
864 return -ENOMEM; 723 return -ENOMEM;
865 724
866 /* First, sum counters... */ 725 /* First, sum counters... */
867 write_lock_bh(&table->lock); 726 write_lock_bh(&table->lock);
868 get_counters(table->private, counters); 727 get_counters(private, counters);
869 write_unlock_bh(&table->lock); 728 write_unlock_bh(&table->lock);
870 729
871 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 730 loc_cpu_entry = private->entries[raw_smp_processor_id()];
872 /* ... then copy entire thing ... */ 731 /* ... then copy entire thing ... */
873 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { 732 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
874 ret = -EFAULT; 733 ret = -EFAULT;
@@ -911,75 +770,34 @@ static int get_entries(const struct arpt_get_entries *entries,
911 int ret; 770 int ret;
912 struct arpt_table *t; 771 struct arpt_table *t;
913 772
914 t = find_table_lock(entries->name); 773 t = xt_find_table_lock(NF_ARP, entries->name);
915 if (t || !IS_ERR(t)) { 774 if (t || !IS_ERR(t)) {
775 struct xt_table_info *private = t->private;
916 duprintf("t->private->number = %u\n", 776 duprintf("t->private->number = %u\n",
917 t->private->number); 777 private->number);
918 if (entries->size == t->private->size) 778 if (entries->size == private->size)
919 ret = copy_entries_to_user(t->private->size, 779 ret = copy_entries_to_user(private->size,
920 t, uptr->entrytable); 780 t, uptr->entrytable);
921 else { 781 else {
922 duprintf("get_entries: I've got %u not %u!\n", 782 duprintf("get_entries: I've got %u not %u!\n",
923 t->private->size, 783 private->size, entries->size);
924 entries->size);
925 ret = -EINVAL; 784 ret = -EINVAL;
926 } 785 }
927 module_put(t->me); 786 module_put(t->me);
928 up(&arpt_mutex); 787 xt_table_unlock(t);
929 } else 788 } else
930 ret = t ? PTR_ERR(t) : -ENOENT; 789 ret = t ? PTR_ERR(t) : -ENOENT;
931 790
932 return ret; 791 return ret;
933} 792}
934 793
935static void free_table_info(struct arpt_table_info *info)
936{
937 int cpu;
938 for_each_cpu(cpu) {
939 if (info->size <= PAGE_SIZE)
940 kfree(info->entries[cpu]);
941 else
942 vfree(info->entries[cpu]);
943 }
944 kfree(info);
945}
946
947static struct arpt_table_info *alloc_table_info(unsigned int size)
948{
949 struct arpt_table_info *newinfo;
950 int cpu;
951
952 newinfo = kzalloc(sizeof(struct arpt_table_info), GFP_KERNEL);
953 if (!newinfo)
954 return NULL;
955
956 newinfo->size = size;
957
958 for_each_cpu(cpu) {
959 if (size <= PAGE_SIZE)
960 newinfo->entries[cpu] = kmalloc_node(size,
961 GFP_KERNEL,
962 cpu_to_node(cpu));
963 else
964 newinfo->entries[cpu] = vmalloc_node(size,
965 cpu_to_node(cpu));
966
967 if (newinfo->entries[cpu] == NULL) {
968 free_table_info(newinfo);
969 return NULL;
970 }
971 }
972
973 return newinfo;
974}
975
976static int do_replace(void __user *user, unsigned int len) 794static int do_replace(void __user *user, unsigned int len)
977{ 795{
978 int ret; 796 int ret;
979 struct arpt_replace tmp; 797 struct arpt_replace tmp;
980 struct arpt_table *t; 798 struct arpt_table *t;
981 struct arpt_table_info *newinfo, *oldinfo; 799 struct xt_table_info *newinfo, *oldinfo;
982 struct arpt_counters *counters; 800 struct xt_counters *counters;
983 void *loc_cpu_entry, *loc_cpu_old_entry; 801 void *loc_cpu_entry, *loc_cpu_old_entry;
984 802
985 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 803 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
@@ -989,11 +807,7 @@ static int do_replace(void __user *user, unsigned int len)
989 if (len != sizeof(tmp) + tmp.size) 807 if (len != sizeof(tmp) + tmp.size)
990 return -ENOPROTOOPT; 808 return -ENOPROTOOPT;
991 809
992 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 810 newinfo = xt_alloc_table_info(tmp.size);
993 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
994 return -ENOMEM;
995
996 newinfo = alloc_table_info(tmp.size);
997 if (!newinfo) 811 if (!newinfo)
998 return -ENOMEM; 812 return -ENOMEM;
999 813
@@ -1005,7 +819,7 @@ static int do_replace(void __user *user, unsigned int len)
1005 goto free_newinfo; 819 goto free_newinfo;
1006 } 820 }
1007 821
1008 counters = vmalloc(tmp.num_counters * sizeof(struct arpt_counters)); 822 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1009 if (!counters) { 823 if (!counters) {
1010 ret = -ENOMEM; 824 ret = -ENOMEM;
1011 goto free_newinfo; 825 goto free_newinfo;
@@ -1019,7 +833,7 @@ static int do_replace(void __user *user, unsigned int len)
1019 833
1020 duprintf("arp_tables: Translated table\n"); 834 duprintf("arp_tables: Translated table\n");
1021 835
1022 t = try_then_request_module(find_table_lock(tmp.name), 836 t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name),
1023 "arptable_%s", tmp.name); 837 "arptable_%s", tmp.name);
1024 if (!t || IS_ERR(t)) { 838 if (!t || IS_ERR(t)) {
1025 ret = t ? PTR_ERR(t) : -ENOENT; 839 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1034,7 +848,7 @@ static int do_replace(void __user *user, unsigned int len)
1034 goto put_module; 848 goto put_module;
1035 } 849 }
1036 850
1037 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 851 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1038 if (!oldinfo) 852 if (!oldinfo)
1039 goto put_module; 853 goto put_module;
1040 854
@@ -1054,23 +868,23 @@ static int do_replace(void __user *user, unsigned int len)
1054 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 868 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1055 ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); 869 ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1056 870
1057 free_table_info(oldinfo); 871 xt_free_table_info(oldinfo);
1058 if (copy_to_user(tmp.counters, counters, 872 if (copy_to_user(tmp.counters, counters,
1059 sizeof(struct arpt_counters) * tmp.num_counters) != 0) 873 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1060 ret = -EFAULT; 874 ret = -EFAULT;
1061 vfree(counters); 875 vfree(counters);
1062 up(&arpt_mutex); 876 xt_table_unlock(t);
1063 return ret; 877 return ret;
1064 878
1065 put_module: 879 put_module:
1066 module_put(t->me); 880 module_put(t->me);
1067 up(&arpt_mutex); 881 xt_table_unlock(t);
1068 free_newinfo_counters_untrans: 882 free_newinfo_counters_untrans:
1069 ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 883 ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1070 free_newinfo_counters: 884 free_newinfo_counters:
1071 vfree(counters); 885 vfree(counters);
1072 free_newinfo: 886 free_newinfo:
1073 free_table_info(newinfo); 887 xt_free_table_info(newinfo);
1074 return ret; 888 return ret;
1075} 889}
1076 890
@@ -1078,7 +892,7 @@ static int do_replace(void __user *user, unsigned int len)
1078 * and everything is OK. 892 * and everything is OK.
1079 */ 893 */
1080static inline int add_counter_to_entry(struct arpt_entry *e, 894static inline int add_counter_to_entry(struct arpt_entry *e,
1081 const struct arpt_counters addme[], 895 const struct xt_counters addme[],
1082 unsigned int *i) 896 unsigned int *i)
1083{ 897{
1084 898
@@ -1091,15 +905,16 @@ static inline int add_counter_to_entry(struct arpt_entry *e,
1091static int do_add_counters(void __user *user, unsigned int len) 905static int do_add_counters(void __user *user, unsigned int len)
1092{ 906{
1093 unsigned int i; 907 unsigned int i;
1094 struct arpt_counters_info tmp, *paddc; 908 struct xt_counters_info tmp, *paddc;
1095 struct arpt_table *t; 909 struct arpt_table *t;
910 struct xt_table_info *private;
1096 int ret = 0; 911 int ret = 0;
1097 void *loc_cpu_entry; 912 void *loc_cpu_entry;
1098 913
1099 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 914 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1100 return -EFAULT; 915 return -EFAULT;
1101 916
1102 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct arpt_counters)) 917 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1103 return -EINVAL; 918 return -EINVAL;
1104 919
1105 paddc = vmalloc(len); 920 paddc = vmalloc(len);
@@ -1111,29 +926,30 @@ static int do_add_counters(void __user *user, unsigned int len)
1111 goto free; 926 goto free;
1112 } 927 }
1113 928
1114 t = find_table_lock(tmp.name); 929 t = xt_find_table_lock(NF_ARP, tmp.name);
1115 if (!t || IS_ERR(t)) { 930 if (!t || IS_ERR(t)) {
1116 ret = t ? PTR_ERR(t) : -ENOENT; 931 ret = t ? PTR_ERR(t) : -ENOENT;
1117 goto free; 932 goto free;
1118 } 933 }
1119 934
1120 write_lock_bh(&t->lock); 935 write_lock_bh(&t->lock);
1121 if (t->private->number != paddc->num_counters) { 936 private = t->private;
937 if (private->number != paddc->num_counters) {
1122 ret = -EINVAL; 938 ret = -EINVAL;
1123 goto unlock_up_free; 939 goto unlock_up_free;
1124 } 940 }
1125 941
1126 i = 0; 942 i = 0;
1127 /* Choose the copy that is on our node */ 943 /* Choose the copy that is on our node */
1128 loc_cpu_entry = t->private->entries[smp_processor_id()]; 944 loc_cpu_entry = private->entries[smp_processor_id()];
1129 ARPT_ENTRY_ITERATE(loc_cpu_entry, 945 ARPT_ENTRY_ITERATE(loc_cpu_entry,
1130 t->private->size, 946 private->size,
1131 add_counter_to_entry, 947 add_counter_to_entry,
1132 paddc->counters, 948 paddc->counters,
1133 &i); 949 &i);
1134 unlock_up_free: 950 unlock_up_free:
1135 write_unlock_bh(&t->lock); 951 write_unlock_bh(&t->lock);
1136 up(&arpt_mutex); 952 xt_table_unlock(t);
1137 module_put(t->me); 953 module_put(t->me);
1138 free: 954 free:
1139 vfree(paddc); 955 vfree(paddc);
@@ -1190,25 +1006,26 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1190 } 1006 }
1191 name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; 1007 name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
1192 1008
1193 t = try_then_request_module(find_table_lock(name), 1009 t = try_then_request_module(xt_find_table_lock(NF_ARP, name),
1194 "arptable_%s", name); 1010 "arptable_%s", name);
1195 if (t && !IS_ERR(t)) { 1011 if (t && !IS_ERR(t)) {
1196 struct arpt_getinfo info; 1012 struct arpt_getinfo info;
1013 struct xt_table_info *private = t->private;
1197 1014
1198 info.valid_hooks = t->valid_hooks; 1015 info.valid_hooks = t->valid_hooks;
1199 memcpy(info.hook_entry, t->private->hook_entry, 1016 memcpy(info.hook_entry, private->hook_entry,
1200 sizeof(info.hook_entry)); 1017 sizeof(info.hook_entry));
1201 memcpy(info.underflow, t->private->underflow, 1018 memcpy(info.underflow, private->underflow,
1202 sizeof(info.underflow)); 1019 sizeof(info.underflow));
1203 info.num_entries = t->private->number; 1020 info.num_entries = private->number;
1204 info.size = t->private->size; 1021 info.size = private->size;
1205 strcpy(info.name, name); 1022 strcpy(info.name, name);
1206 1023
1207 if (copy_to_user(user, &info, *len) != 0) 1024 if (copy_to_user(user, &info, *len) != 0)
1208 ret = -EFAULT; 1025 ret = -EFAULT;
1209 else 1026 else
1210 ret = 0; 1027 ret = 0;
1211 up(&arpt_mutex); 1028 xt_table_unlock(t);
1212 module_put(t->me); 1029 module_put(t->me);
1213 } else 1030 } else
1214 ret = t ? PTR_ERR(t) : -ENOENT; 1031 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1233,7 +1050,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1233 } 1050 }
1234 1051
1235 case ARPT_SO_GET_REVISION_TARGET: { 1052 case ARPT_SO_GET_REVISION_TARGET: {
1236 struct arpt_get_revision rev; 1053 struct xt_get_revision rev;
1237 1054
1238 if (*len != sizeof(rev)) { 1055 if (*len != sizeof(rev)) {
1239 ret = -EINVAL; 1056 ret = -EINVAL;
@@ -1244,8 +1061,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1244 break; 1061 break;
1245 } 1062 }
1246 1063
1247 try_then_request_module(find_revision(rev.name, rev.revision, 1064 try_then_request_module(xt_find_revision(NF_ARP, rev.name,
1248 target_revfn, &ret), 1065 rev.revision, 1, &ret),
1249 "arpt_%s", rev.name); 1066 "arpt_%s", rev.name);
1250 break; 1067 break;
1251 } 1068 }
@@ -1258,38 +1075,16 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1258 return ret; 1075 return ret;
1259} 1076}
1260 1077
1261/* Registration hooks for targets. */
1262int arpt_register_target(struct arpt_target *target)
1263{
1264 int ret;
1265
1266 ret = down_interruptible(&arpt_mutex);
1267 if (ret != 0)
1268 return ret;
1269
1270 list_add(&target->list, &arpt_target);
1271 up(&arpt_mutex);
1272
1273 return ret;
1274}
1275
1276void arpt_unregister_target(struct arpt_target *target)
1277{
1278 down(&arpt_mutex);
1279 LIST_DELETE(&arpt_target, target);
1280 up(&arpt_mutex);
1281}
1282
1283int arpt_register_table(struct arpt_table *table, 1078int arpt_register_table(struct arpt_table *table,
1284 const struct arpt_replace *repl) 1079 const struct arpt_replace *repl)
1285{ 1080{
1286 int ret; 1081 int ret;
1287 struct arpt_table_info *newinfo; 1082 struct xt_table_info *newinfo;
1288 static struct arpt_table_info bootstrap 1083 static struct xt_table_info bootstrap
1289 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1084 = { 0, 0, 0, { 0 }, { 0 }, { } };
1290 void *loc_cpu_entry; 1085 void *loc_cpu_entry;
1291 1086
1292 newinfo = alloc_table_info(repl->size); 1087 newinfo = xt_alloc_table_info(repl->size);
1293 if (!newinfo) { 1088 if (!newinfo) {
1294 ret = -ENOMEM; 1089 ret = -ENOMEM;
1295 return ret; 1090 return ret;
@@ -1304,60 +1099,33 @@ int arpt_register_table(struct arpt_table *table,
1304 repl->num_entries, 1099 repl->num_entries,
1305 repl->hook_entry, 1100 repl->hook_entry,
1306 repl->underflow); 1101 repl->underflow);
1102
1307 duprintf("arpt_register_table: translate table gives %d\n", ret); 1103 duprintf("arpt_register_table: translate table gives %d\n", ret);
1308 if (ret != 0) { 1104 if (ret != 0) {
1309 free_table_info(newinfo); 1105 xt_free_table_info(newinfo);
1310 return ret; 1106 return ret;
1311 } 1107 }
1312 1108
1313 ret = down_interruptible(&arpt_mutex); 1109 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1314 if (ret != 0) { 1110 xt_free_table_info(newinfo);
1315 free_table_info(newinfo);
1316 return ret; 1111 return ret;
1317 } 1112 }
1318 1113
1319 /* Don't autoload: we'd eat our tail... */ 1114 return 0;
1320 if (list_named_find(&arpt_tables, table->name)) {
1321 ret = -EEXIST;
1322 goto free_unlock;
1323 }
1324
1325 /* Simplifies replace_table code. */
1326 table->private = &bootstrap;
1327 if (!replace_table(table, 0, newinfo, &ret))
1328 goto free_unlock;
1329
1330 duprintf("table->private->number = %u\n",
1331 table->private->number);
1332
1333 /* save number of initial entries */
1334 table->private->initial_entries = table->private->number;
1335
1336 rwlock_init(&table->lock);
1337 list_prepend(&arpt_tables, table);
1338
1339 unlock:
1340 up(&arpt_mutex);
1341 return ret;
1342
1343 free_unlock:
1344 free_table_info(newinfo);
1345 goto unlock;
1346} 1115}
1347 1116
1348void arpt_unregister_table(struct arpt_table *table) 1117void arpt_unregister_table(struct arpt_table *table)
1349{ 1118{
1119 struct xt_table_info *private;
1350 void *loc_cpu_entry; 1120 void *loc_cpu_entry;
1351 1121
1352 down(&arpt_mutex); 1122 private = xt_unregister_table(table);
1353 LIST_DELETE(&arpt_tables, table);
1354 up(&arpt_mutex);
1355 1123
1356 /* Decrease module usage counts and free resources */ 1124 /* Decrease module usage counts and free resources */
1357 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 1125 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1358 ARPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, 1126 ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size,
1359 cleanup_entry, NULL); 1127 cleanup_entry, NULL);
1360 free_table_info(table->private); 1128 xt_free_table_info(private);
1361} 1129}
1362 1130
1363/* The built-in targets: standard (NULL) and error. */ 1131/* The built-in targets: standard (NULL) and error. */
@@ -1380,52 +1148,15 @@ static struct nf_sockopt_ops arpt_sockopts = {
1380 .get = do_arpt_get_ctl, 1148 .get = do_arpt_get_ctl,
1381}; 1149};
1382 1150
1383#ifdef CONFIG_PROC_FS
1384static inline int print_name(const struct arpt_table *t,
1385 off_t start_offset, char *buffer, int length,
1386 off_t *pos, unsigned int *count)
1387{
1388 if ((*count)++ >= start_offset) {
1389 unsigned int namelen;
1390
1391 namelen = sprintf(buffer + *pos, "%s\n", t->name);
1392 if (*pos + namelen > length) {
1393 /* Stop iterating */
1394 return 1;
1395 }
1396 *pos += namelen;
1397 }
1398 return 0;
1399}
1400
1401static int arpt_get_tables(char *buffer, char **start, off_t offset, int length)
1402{
1403 off_t pos = 0;
1404 unsigned int count = 0;
1405
1406 if (down_interruptible(&arpt_mutex) != 0)
1407 return 0;
1408
1409 LIST_FIND(&arpt_tables, print_name, struct arpt_table *,
1410 offset, buffer, length, &pos, &count);
1411
1412 up(&arpt_mutex);
1413
1414 /* `start' hack - see fs/proc/generic.c line ~105 */
1415 *start=(char *)((unsigned long)count-offset);
1416 return pos;
1417}
1418#endif /*CONFIG_PROC_FS*/
1419
1420static int __init init(void) 1151static int __init init(void)
1421{ 1152{
1422 int ret; 1153 int ret;
1423 1154
1155 xt_proto_init(NF_ARP);
1156
1424 /* Noone else will be downing sem now, so we won't sleep */ 1157 /* Noone else will be downing sem now, so we won't sleep */
1425 down(&arpt_mutex); 1158 xt_register_target(NF_ARP, &arpt_standard_target);
1426 list_append(&arpt_target, &arpt_standard_target); 1159 xt_register_target(NF_ARP, &arpt_error_target);
1427 list_append(&arpt_target, &arpt_error_target);
1428 up(&arpt_mutex);
1429 1160
1430 /* Register setsockopt */ 1161 /* Register setsockopt */
1431 ret = nf_register_sockopt(&arpt_sockopts); 1162 ret = nf_register_sockopt(&arpt_sockopts);
@@ -1434,19 +1165,6 @@ static int __init init(void)
1434 return ret; 1165 return ret;
1435 } 1166 }
1436 1167
1437#ifdef CONFIG_PROC_FS
1438 {
1439 struct proc_dir_entry *proc;
1440
1441 proc = proc_net_create("arp_tables_names", 0, arpt_get_tables);
1442 if (!proc) {
1443 nf_unregister_sockopt(&arpt_sockopts);
1444 return -ENOMEM;
1445 }
1446 proc->owner = THIS_MODULE;
1447 }
1448#endif
1449
1450 printk("arp_tables: (C) 2002 David S. Miller\n"); 1168 printk("arp_tables: (C) 2002 David S. Miller\n");
1451 return 0; 1169 return 0;
1452} 1170}
@@ -1454,16 +1172,12 @@ static int __init init(void)
1454static void __exit fini(void) 1172static void __exit fini(void)
1455{ 1173{
1456 nf_unregister_sockopt(&arpt_sockopts); 1174 nf_unregister_sockopt(&arpt_sockopts);
1457#ifdef CONFIG_PROC_FS 1175 xt_proto_fini(NF_ARP);
1458 proc_net_remove("arp_tables_names");
1459#endif
1460} 1176}
1461 1177
1462EXPORT_SYMBOL(arpt_register_table); 1178EXPORT_SYMBOL(arpt_register_table);
1463EXPORT_SYMBOL(arpt_unregister_table); 1179EXPORT_SYMBOL(arpt_unregister_table);
1464EXPORT_SYMBOL(arpt_do_table); 1180EXPORT_SYMBOL(arpt_do_table);
1465EXPORT_SYMBOL(arpt_register_target);
1466EXPORT_SYMBOL(arpt_unregister_target);
1467 1181
1468module_init(init); 1182module_init(init);
1469module_exit(fini); 1183module_exit(fini);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 3e592ec86482..c97650a16a5b 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -8,8 +8,9 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
8MODULE_DESCRIPTION("arptables arp payload mangle target"); 8MODULE_DESCRIPTION("arptables arp payload mangle target");
9 9
10static unsigned int 10static unsigned int
11target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, 11target(struct sk_buff **pskb, const struct net_device *in,
12 const struct net_device *out, const void *targinfo, void *userinfo) 12 const struct net_device *out, unsigned int hooknum, const void *targinfo,
13 void *userinfo)
13{ 14{
14 const struct arpt_mangle *mangle = targinfo; 15 const struct arpt_mangle *mangle = targinfo;
15 struct arphdr *arp; 16 struct arphdr *arp;
@@ -64,7 +65,7 @@ target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in,
64} 65}
65 66
66static int 67static int
67checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo, 68checkentry(const char *tablename, const void *e, void *targinfo,
68 unsigned int targinfosize, unsigned int hook_mask) 69 unsigned int targinfosize, unsigned int hook_mask)
69{ 70{
70 const struct arpt_mangle *mangle = targinfo; 71 const struct arpt_mangle *mangle = targinfo;
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 0d759f5a4ef0..f6ab45f48681 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -145,6 +145,7 @@ static struct arpt_table packet_filter = {
145 .lock = RW_LOCK_UNLOCKED, 145 .lock = RW_LOCK_UNLOCKED,
146 .private = NULL, 146 .private = NULL,
147 .me = THIS_MODULE, 147 .me = THIS_MODULE,
148 .af = NF_ARP,
148}; 149};
149 150
150/* The work comes in here from netfilter.c */ 151/* The work comes in here from netfilter.c */
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 9dec1293f67a..833fcb4be5e7 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -944,7 +944,7 @@ module_exit(fini);
944 944
945/* Some modules need us, but don't depend directly on any symbol. 945/* Some modules need us, but don't depend directly on any symbol.
946 They should call this. */ 946 They should call this. */
947void need_ip_conntrack(void) 947void need_conntrack(void)
948{ 948{
949} 949}
950 950
@@ -962,7 +962,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple);
962EXPORT_SYMBOL(invert_tuplepr); 962EXPORT_SYMBOL(invert_tuplepr);
963EXPORT_SYMBOL(ip_conntrack_alter_reply); 963EXPORT_SYMBOL(ip_conntrack_alter_reply);
964EXPORT_SYMBOL(ip_conntrack_destroyed); 964EXPORT_SYMBOL(ip_conntrack_destroyed);
965EXPORT_SYMBOL(need_ip_conntrack); 965EXPORT_SYMBOL(need_conntrack);
966EXPORT_SYMBOL(ip_conntrack_helper_register); 966EXPORT_SYMBOL(ip_conntrack_helper_register);
967EXPORT_SYMBOL(ip_conntrack_helper_unregister); 967EXPORT_SYMBOL(ip_conntrack_helper_unregister);
968EXPORT_SYMBOL(ip_ct_iterate_cleanup); 968EXPORT_SYMBOL(ip_ct_iterate_cleanup);
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index cb66b8bddeb3..1de86282d232 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -95,6 +95,7 @@ static struct ipt_table nat_table = {
95 .valid_hooks = NAT_VALID_HOOKS, 95 .valid_hooks = NAT_VALID_HOOKS,
96 .lock = RW_LOCK_UNLOCKED, 96 .lock = RW_LOCK_UNLOCKED,
97 .me = THIS_MODULE, 97 .me = THIS_MODULE,
98 .af = AF_INET,
98}; 99};
99 100
100/* Source NAT */ 101/* Source NAT */
@@ -168,7 +169,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
168} 169}
169 170
170static int ipt_snat_checkentry(const char *tablename, 171static int ipt_snat_checkentry(const char *tablename,
171 const struct ipt_entry *e, 172 const void *entry,
172 void *targinfo, 173 void *targinfo,
173 unsigned int targinfosize, 174 unsigned int targinfosize,
174 unsigned int hook_mask) 175 unsigned int hook_mask)
@@ -201,7 +202,7 @@ static int ipt_snat_checkentry(const char *tablename,
201} 202}
202 203
203static int ipt_dnat_checkentry(const char *tablename, 204static int ipt_dnat_checkentry(const char *tablename,
204 const struct ipt_entry *e, 205 const void *entry,
205 void *targinfo, 206 void *targinfo,
206 unsigned int targinfosize, 207 unsigned int targinfosize,
207 unsigned int hook_mask) 208 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 8b8a1f00bbf4..ad438fb185b8 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -364,7 +364,7 @@ static int init_or_cleanup(int init)
364{ 364{
365 int ret = 0; 365 int ret = 0;
366 366
367 need_ip_conntrack(); 367 need_conntrack();
368 368
369 if (!init) goto cleanup; 369 if (!init) goto cleanup;
370 370
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 877bc96d3336..2371b2062c2d 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -2,7 +2,7 @@
2 * Packet matching code. 2 * Packet matching code.
3 * 3 *
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org> 5 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -11,6 +11,8 @@
11 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> 11 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
12 * - increase module usage count as soon as we have rules inside 12 * - increase module usage count as soon as we have rules inside
13 * a table 13 * a table
14 * 08 Oct 2005 Harald Welte <lafore@netfilter.org>
15 * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables"
14 */ 16 */
15#include <linux/config.h> 17#include <linux/config.h>
16#include <linux/cache.h> 18#include <linux/cache.h>
@@ -20,8 +22,6 @@
20#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
21#include <linux/netdevice.h> 23#include <linux/netdevice.h>
22#include <linux/module.h> 24#include <linux/module.h>
23#include <linux/tcp.h>
24#include <linux/udp.h>
25#include <linux/icmp.h> 25#include <linux/icmp.h>
26#include <net/ip.h> 26#include <net/ip.h>
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
@@ -30,6 +30,7 @@
30#include <linux/err.h> 30#include <linux/err.h>
31#include <linux/cpumask.h> 31#include <linux/cpumask.h>
32 32
33#include <linux/netfilter/x_tables.h>
33#include <linux/netfilter_ipv4/ip_tables.h> 34#include <linux/netfilter_ipv4/ip_tables.h>
34 35
35MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
@@ -62,14 +63,6 @@ do { \
62#else 63#else
63#define IP_NF_ASSERT(x) 64#define IP_NF_ASSERT(x)
64#endif 65#endif
65#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
66
67static DECLARE_MUTEX(ipt_mutex);
68
69/* Must have mutex */
70#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
71#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
72#include <linux/netfilter_ipv4/listhelp.h>
73 66
74#if 0 67#if 0
75/* All the better to debug you with... */ 68/* All the better to debug you with... */
@@ -86,36 +79,6 @@ static DECLARE_MUTEX(ipt_mutex);
86 79
87 Hence the start of any table is given by get_table() below. */ 80 Hence the start of any table is given by get_table() below. */
88 81
89/* The table itself */
90struct ipt_table_info
91{
92 /* Size per table */
93 unsigned int size;
94 /* Number of entries: FIXME. --RR */
95 unsigned int number;
96 /* Initial number of entries. Needed for module usage count */
97 unsigned int initial_entries;
98
99 /* Entry points and underflows */
100 unsigned int hook_entry[NF_IP_NUMHOOKS];
101 unsigned int underflow[NF_IP_NUMHOOKS];
102
103 /* ipt_entry tables: one per CPU */
104 void *entries[NR_CPUS];
105};
106
107static LIST_HEAD(ipt_target);
108static LIST_HEAD(ipt_match);
109static LIST_HEAD(ipt_tables);
110#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
111#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
112
113#if 0
114#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
115#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
116#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
117#endif
118
119/* Returns whether matches rule or not. */ 82/* Returns whether matches rule or not. */
120static inline int 83static inline int
121ip_packet_match(const struct iphdr *ip, 84ip_packet_match(const struct iphdr *ip,
@@ -234,7 +197,8 @@ int do_match(struct ipt_entry_match *m,
234 int *hotdrop) 197 int *hotdrop)
235{ 198{
236 /* Stop iteration if it doesn't match */ 199 /* Stop iteration if it doesn't match */
237 if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop)) 200 if (!m->u.kernel.match->match(skb, in, out, m->data, offset,
201 skb->nh.iph->ihl*4, hotdrop))
238 return 1; 202 return 1;
239 else 203 else
240 return 0; 204 return 0;
@@ -265,6 +229,7 @@ ipt_do_table(struct sk_buff **pskb,
265 const char *indev, *outdev; 229 const char *indev, *outdev;
266 void *table_base; 230 void *table_base;
267 struct ipt_entry *e, *back; 231 struct ipt_entry *e, *back;
232 struct xt_table_info *private = table->private;
268 233
269 /* Initialization */ 234 /* Initialization */
270 ip = (*pskb)->nh.iph; 235 ip = (*pskb)->nh.iph;
@@ -281,24 +246,11 @@ ipt_do_table(struct sk_buff **pskb,
281 246
282 read_lock_bh(&table->lock); 247 read_lock_bh(&table->lock);
283 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 248 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
284 table_base = (void *)table->private->entries[smp_processor_id()]; 249 table_base = (void *)private->entries[smp_processor_id()];
285 e = get_entry(table_base, table->private->hook_entry[hook]); 250 e = get_entry(table_base, private->hook_entry[hook]);
286
287#ifdef CONFIG_NETFILTER_DEBUG
288 /* Check noone else using our table */
289 if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac
290 && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) {
291 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
292 smp_processor_id(),
293 table->name,
294 &((struct ipt_entry *)table_base)->comefrom,
295 ((struct ipt_entry *)table_base)->comefrom);
296 }
297 ((struct ipt_entry *)table_base)->comefrom = 0x57acc001;
298#endif
299 251
300 /* For return from builtin chain */ 252 /* For return from builtin chain */
301 back = get_entry(table_base, table->private->underflow[hook]); 253 back = get_entry(table_base, private->underflow[hook]);
302 254
303 do { 255 do {
304 IP_NF_ASSERT(e); 256 IP_NF_ASSERT(e);
@@ -384,9 +336,6 @@ ipt_do_table(struct sk_buff **pskb,
384 } 336 }
385 } while (!hotdrop); 337 } while (!hotdrop);
386 338
387#ifdef CONFIG_NETFILTER_DEBUG
388 ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac;
389#endif
390 read_unlock_bh(&table->lock); 339 read_unlock_bh(&table->lock);
391 340
392#ifdef DEBUG_ALLOW_ALL 341#ifdef DEBUG_ALLOW_ALL
@@ -398,145 +347,6 @@ ipt_do_table(struct sk_buff **pskb,
398#endif 347#endif
399} 348}
400 349
401/*
402 * These are weird, but module loading must not be done with mutex
403 * held (since they will register), and we have to have a single
404 * function to use try_then_request_module().
405 */
406
407/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
408static inline struct ipt_table *find_table_lock(const char *name)
409{
410 struct ipt_table *t;
411
412 if (down_interruptible(&ipt_mutex) != 0)
413 return ERR_PTR(-EINTR);
414
415 list_for_each_entry(t, &ipt_tables, list)
416 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
417 return t;
418 up(&ipt_mutex);
419 return NULL;
420}
421
422/* Find match, grabs ref. Returns ERR_PTR() on error. */
423static inline struct ipt_match *find_match(const char *name, u8 revision)
424{
425 struct ipt_match *m;
426 int err = 0;
427
428 if (down_interruptible(&ipt_mutex) != 0)
429 return ERR_PTR(-EINTR);
430
431 list_for_each_entry(m, &ipt_match, list) {
432 if (strcmp(m->name, name) == 0) {
433 if (m->revision == revision) {
434 if (try_module_get(m->me)) {
435 up(&ipt_mutex);
436 return m;
437 }
438 } else
439 err = -EPROTOTYPE; /* Found something. */
440 }
441 }
442 up(&ipt_mutex);
443 return ERR_PTR(err);
444}
445
446/* Find target, grabs ref. Returns ERR_PTR() on error. */
447static inline struct ipt_target *find_target(const char *name, u8 revision)
448{
449 struct ipt_target *t;
450 int err = 0;
451
452 if (down_interruptible(&ipt_mutex) != 0)
453 return ERR_PTR(-EINTR);
454
455 list_for_each_entry(t, &ipt_target, list) {
456 if (strcmp(t->name, name) == 0) {
457 if (t->revision == revision) {
458 if (try_module_get(t->me)) {
459 up(&ipt_mutex);
460 return t;
461 }
462 } else
463 err = -EPROTOTYPE; /* Found something. */
464 }
465 }
466 up(&ipt_mutex);
467 return ERR_PTR(err);
468}
469
470struct ipt_target *ipt_find_target(const char *name, u8 revision)
471{
472 struct ipt_target *target;
473
474 target = try_then_request_module(find_target(name, revision),
475 "ipt_%s", name);
476 if (IS_ERR(target) || !target)
477 return NULL;
478 return target;
479}
480
481static int match_revfn(const char *name, u8 revision, int *bestp)
482{
483 struct ipt_match *m;
484 int have_rev = 0;
485
486 list_for_each_entry(m, &ipt_match, list) {
487 if (strcmp(m->name, name) == 0) {
488 if (m->revision > *bestp)
489 *bestp = m->revision;
490 if (m->revision == revision)
491 have_rev = 1;
492 }
493 }
494 return have_rev;
495}
496
497static int target_revfn(const char *name, u8 revision, int *bestp)
498{
499 struct ipt_target *t;
500 int have_rev = 0;
501
502 list_for_each_entry(t, &ipt_target, list) {
503 if (strcmp(t->name, name) == 0) {
504 if (t->revision > *bestp)
505 *bestp = t->revision;
506 if (t->revision == revision)
507 have_rev = 1;
508 }
509 }
510 return have_rev;
511}
512
513/* Returns true or false (if no such extension at all) */
514static inline int find_revision(const char *name, u8 revision,
515 int (*revfn)(const char *, u8, int *),
516 int *err)
517{
518 int have_rev, best = -1;
519
520 if (down_interruptible(&ipt_mutex) != 0) {
521 *err = -EINTR;
522 return 1;
523 }
524 have_rev = revfn(name, revision, &best);
525 up(&ipt_mutex);
526
527 /* Nothing at all? Return 0 to try loading module. */
528 if (best == -1) {
529 *err = -ENOENT;
530 return 0;
531 }
532
533 *err = best;
534 if (!have_rev)
535 *err = -EPROTONOSUPPORT;
536 return 1;
537}
538
539
540/* All zeroes == unconditional rule. */ 350/* All zeroes == unconditional rule. */
541static inline int 351static inline int
542unconditional(const struct ipt_ip *ip) 352unconditional(const struct ipt_ip *ip)
@@ -553,7 +363,7 @@ unconditional(const struct ipt_ip *ip)
553/* Figures out from what hook each rule can be called: returns 0 if 363/* Figures out from what hook each rule can be called: returns 0 if
554 there are loops. Puts hook bitmask in comefrom. */ 364 there are loops. Puts hook bitmask in comefrom. */
555static int 365static int
556mark_source_chains(struct ipt_table_info *newinfo, 366mark_source_chains(struct xt_table_info *newinfo,
557 unsigned int valid_hooks, void *entry0) 367 unsigned int valid_hooks, void *entry0)
558{ 368{
559 unsigned int hook; 369 unsigned int hook;
@@ -699,7 +509,7 @@ check_match(struct ipt_entry_match *m,
699{ 509{
700 struct ipt_match *match; 510 struct ipt_match *match;
701 511
702 match = try_then_request_module(find_match(m->u.user.name, 512 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
703 m->u.user.revision), 513 m->u.user.revision),
704 "ipt_%s", m->u.user.name); 514 "ipt_%s", m->u.user.name);
705 if (IS_ERR(match) || !match) { 515 if (IS_ERR(match) || !match) {
@@ -744,7 +554,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
744 goto cleanup_matches; 554 goto cleanup_matches;
745 555
746 t = ipt_get_target(e); 556 t = ipt_get_target(e);
747 target = try_then_request_module(find_target(t->u.user.name, 557 target = try_then_request_module(xt_find_target(AF_INET,
558 t->u.user.name,
748 t->u.user.revision), 559 t->u.user.revision),
749 "ipt_%s", t->u.user.name); 560 "ipt_%s", t->u.user.name);
750 if (IS_ERR(target) || !target) { 561 if (IS_ERR(target) || !target) {
@@ -781,7 +592,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
781 592
782static inline int 593static inline int
783check_entry_size_and_hooks(struct ipt_entry *e, 594check_entry_size_and_hooks(struct ipt_entry *e,
784 struct ipt_table_info *newinfo, 595 struct xt_table_info *newinfo,
785 unsigned char *base, 596 unsigned char *base,
786 unsigned char *limit, 597 unsigned char *limit,
787 const unsigned int *hook_entries, 598 const unsigned int *hook_entries,
@@ -815,7 +626,7 @@ check_entry_size_and_hooks(struct ipt_entry *e,
815 < 0 (not IPT_RETURN). --RR */ 626 < 0 (not IPT_RETURN). --RR */
816 627
817 /* Clear counters and comefrom */ 628 /* Clear counters and comefrom */
818 e->counters = ((struct ipt_counters) { 0, 0 }); 629 e->counters = ((struct xt_counters) { 0, 0 });
819 e->comefrom = 0; 630 e->comefrom = 0;
820 631
821 (*i)++; 632 (*i)++;
@@ -845,7 +656,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
845static int 656static int
846translate_table(const char *name, 657translate_table(const char *name,
847 unsigned int valid_hooks, 658 unsigned int valid_hooks,
848 struct ipt_table_info *newinfo, 659 struct xt_table_info *newinfo,
849 void *entry0, 660 void *entry0,
850 unsigned int size, 661 unsigned int size,
851 unsigned int number, 662 unsigned int number,
@@ -922,48 +733,10 @@ translate_table(const char *name,
922 return ret; 733 return ret;
923} 734}
924 735
925static struct ipt_table_info *
926replace_table(struct ipt_table *table,
927 unsigned int num_counters,
928 struct ipt_table_info *newinfo,
929 int *error)
930{
931 struct ipt_table_info *oldinfo;
932
933#ifdef CONFIG_NETFILTER_DEBUG
934 {
935 int cpu;
936
937 for_each_cpu(cpu) {
938 struct ipt_entry *table_base = newinfo->entries[cpu];
939 if (table_base)
940 table_base->comefrom = 0xdead57ac;
941 }
942 }
943#endif
944
945 /* Do the substitution. */
946 write_lock_bh(&table->lock);
947 /* Check inside lock: is the old number correct? */
948 if (num_counters != table->private->number) {
949 duprintf("num_counters != table->private->number (%u/%u)\n",
950 num_counters, table->private->number);
951 write_unlock_bh(&table->lock);
952 *error = -EAGAIN;
953 return NULL;
954 }
955 oldinfo = table->private;
956 table->private = newinfo;
957 newinfo->initial_entries = oldinfo->initial_entries;
958 write_unlock_bh(&table->lock);
959
960 return oldinfo;
961}
962
963/* Gets counters. */ 736/* Gets counters. */
964static inline int 737static inline int
965add_entry_to_counter(const struct ipt_entry *e, 738add_entry_to_counter(const struct ipt_entry *e,
966 struct ipt_counters total[], 739 struct xt_counters total[],
967 unsigned int *i) 740 unsigned int *i)
968{ 741{
969 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 742 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -984,8 +757,8 @@ set_entry_to_counter(const struct ipt_entry *e,
984} 757}
985 758
986static void 759static void
987get_counters(const struct ipt_table_info *t, 760get_counters(const struct xt_table_info *t,
988 struct ipt_counters counters[]) 761 struct xt_counters counters[])
989{ 762{
990 unsigned int cpu; 763 unsigned int cpu;
991 unsigned int i; 764 unsigned int i;
@@ -1024,14 +797,15 @@ copy_entries_to_user(unsigned int total_size,
1024{ 797{
1025 unsigned int off, num, countersize; 798 unsigned int off, num, countersize;
1026 struct ipt_entry *e; 799 struct ipt_entry *e;
1027 struct ipt_counters *counters; 800 struct xt_counters *counters;
801 struct xt_table_info *private = table->private;
1028 int ret = 0; 802 int ret = 0;
1029 void *loc_cpu_entry; 803 void *loc_cpu_entry;
1030 804
1031 /* We need atomic snapshot of counters: rest doesn't change 805 /* We need atomic snapshot of counters: rest doesn't change
1032 (other than comefrom, which userspace doesn't care 806 (other than comefrom, which userspace doesn't care
1033 about). */ 807 about). */
1034 countersize = sizeof(struct ipt_counters) * table->private->number; 808 countersize = sizeof(struct xt_counters) * private->number;
1035 counters = vmalloc_node(countersize, numa_node_id()); 809 counters = vmalloc_node(countersize, numa_node_id());
1036 810
1037 if (counters == NULL) 811 if (counters == NULL)
@@ -1039,14 +813,14 @@ copy_entries_to_user(unsigned int total_size,
1039 813
1040 /* First, sum counters... */ 814 /* First, sum counters... */
1041 write_lock_bh(&table->lock); 815 write_lock_bh(&table->lock);
1042 get_counters(table->private, counters); 816 get_counters(private, counters);
1043 write_unlock_bh(&table->lock); 817 write_unlock_bh(&table->lock);
1044 818
1045 /* choose the copy that is on our node/cpu, ... 819 /* choose the copy that is on our node/cpu, ...
1046 * This choice is lazy (because current thread is 820 * This choice is lazy (because current thread is
1047 * allowed to migrate to another cpu) 821 * allowed to migrate to another cpu)
1048 */ 822 */
1049 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 823 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1050 /* ... then copy entire thing ... */ 824 /* ... then copy entire thing ... */
1051 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { 825 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
1052 ret = -EFAULT; 826 ret = -EFAULT;
@@ -1108,74 +882,36 @@ get_entries(const struct ipt_get_entries *entries,
1108 int ret; 882 int ret;
1109 struct ipt_table *t; 883 struct ipt_table *t;
1110 884
1111 t = find_table_lock(entries->name); 885 t = xt_find_table_lock(AF_INET, entries->name);
1112 if (t && !IS_ERR(t)) { 886 if (t && !IS_ERR(t)) {
887 struct xt_table_info *private = t->private;
1113 duprintf("t->private->number = %u\n", 888 duprintf("t->private->number = %u\n",
1114 t->private->number); 889 private->number);
1115 if (entries->size == t->private->size) 890 if (entries->size == private->size)
1116 ret = copy_entries_to_user(t->private->size, 891 ret = copy_entries_to_user(private->size,
1117 t, uptr->entrytable); 892 t, uptr->entrytable);
1118 else { 893 else {
1119 duprintf("get_entries: I've got %u not %u!\n", 894 duprintf("get_entries: I've got %u not %u!\n",
1120 t->private->size, 895 private->size,
1121 entries->size); 896 entries->size);
1122 ret = -EINVAL; 897 ret = -EINVAL;
1123 } 898 }
1124 module_put(t->me); 899 module_put(t->me);
1125 up(&ipt_mutex); 900 xt_table_unlock(t);
1126 } else 901 } else
1127 ret = t ? PTR_ERR(t) : -ENOENT; 902 ret = t ? PTR_ERR(t) : -ENOENT;
1128 903
1129 return ret; 904 return ret;
1130} 905}
1131 906
1132static void free_table_info(struct ipt_table_info *info)
1133{
1134 int cpu;
1135 for_each_cpu(cpu) {
1136 if (info->size <= PAGE_SIZE)
1137 kfree(info->entries[cpu]);
1138 else
1139 vfree(info->entries[cpu]);
1140 }
1141 kfree(info);
1142}
1143
1144static struct ipt_table_info *alloc_table_info(unsigned int size)
1145{
1146 struct ipt_table_info *newinfo;
1147 int cpu;
1148
1149 newinfo = kzalloc(sizeof(struct ipt_table_info), GFP_KERNEL);
1150 if (!newinfo)
1151 return NULL;
1152
1153 newinfo->size = size;
1154
1155 for_each_cpu(cpu) {
1156 if (size <= PAGE_SIZE)
1157 newinfo->entries[cpu] = kmalloc_node(size,
1158 GFP_KERNEL,
1159 cpu_to_node(cpu));
1160 else
1161 newinfo->entries[cpu] = vmalloc_node(size, cpu_to_node(cpu));
1162 if (newinfo->entries[cpu] == 0) {
1163 free_table_info(newinfo);
1164 return NULL;
1165 }
1166 }
1167
1168 return newinfo;
1169}
1170
1171static int 907static int
1172do_replace(void __user *user, unsigned int len) 908do_replace(void __user *user, unsigned int len)
1173{ 909{
1174 int ret; 910 int ret;
1175 struct ipt_replace tmp; 911 struct ipt_replace tmp;
1176 struct ipt_table *t; 912 struct ipt_table *t;
1177 struct ipt_table_info *newinfo, *oldinfo; 913 struct xt_table_info *newinfo, *oldinfo;
1178 struct ipt_counters *counters; 914 struct xt_counters *counters;
1179 void *loc_cpu_entry, *loc_cpu_old_entry; 915 void *loc_cpu_entry, *loc_cpu_old_entry;
1180 916
1181 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 917 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
@@ -1185,11 +921,7 @@ do_replace(void __user *user, unsigned int len)
1185 if (len != sizeof(tmp) + tmp.size) 921 if (len != sizeof(tmp) + tmp.size)
1186 return -ENOPROTOOPT; 922 return -ENOPROTOOPT;
1187 923
1188 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 924 newinfo = xt_alloc_table_info(tmp.size);
1189 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
1190 return -ENOMEM;
1191
1192 newinfo = alloc_table_info(tmp.size);
1193 if (!newinfo) 925 if (!newinfo)
1194 return -ENOMEM; 926 return -ENOMEM;
1195 927
@@ -1201,7 +933,7 @@ do_replace(void __user *user, unsigned int len)
1201 goto free_newinfo; 933 goto free_newinfo;
1202 } 934 }
1203 935
1204 counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters)); 936 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1205 if (!counters) { 937 if (!counters) {
1206 ret = -ENOMEM; 938 ret = -ENOMEM;
1207 goto free_newinfo; 939 goto free_newinfo;
@@ -1215,7 +947,7 @@ do_replace(void __user *user, unsigned int len)
1215 947
1216 duprintf("ip_tables: Translated table\n"); 948 duprintf("ip_tables: Translated table\n");
1217 949
1218 t = try_then_request_module(find_table_lock(tmp.name), 950 t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
1219 "iptable_%s", tmp.name); 951 "iptable_%s", tmp.name);
1220 if (!t || IS_ERR(t)) { 952 if (!t || IS_ERR(t)) {
1221 ret = t ? PTR_ERR(t) : -ENOENT; 953 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1230,7 +962,7 @@ do_replace(void __user *user, unsigned int len)
1230 goto put_module; 962 goto put_module;
1231 } 963 }
1232 964
1233 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 965 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1234 if (!oldinfo) 966 if (!oldinfo)
1235 goto put_module; 967 goto put_module;
1236 968
@@ -1249,23 +981,23 @@ do_replace(void __user *user, unsigned int len)
1249 /* Decrease module usage counts and free resource */ 981 /* Decrease module usage counts and free resource */
1250 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 982 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1251 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); 983 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1252 free_table_info(oldinfo); 984 xt_free_table_info(oldinfo);
1253 if (copy_to_user(tmp.counters, counters, 985 if (copy_to_user(tmp.counters, counters,
1254 sizeof(struct ipt_counters) * tmp.num_counters) != 0) 986 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1255 ret = -EFAULT; 987 ret = -EFAULT;
1256 vfree(counters); 988 vfree(counters);
1257 up(&ipt_mutex); 989 xt_table_unlock(t);
1258 return ret; 990 return ret;
1259 991
1260 put_module: 992 put_module:
1261 module_put(t->me); 993 module_put(t->me);
1262 up(&ipt_mutex); 994 xt_table_unlock(t);
1263 free_newinfo_counters_untrans: 995 free_newinfo_counters_untrans:
1264 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); 996 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1265 free_newinfo_counters: 997 free_newinfo_counters:
1266 vfree(counters); 998 vfree(counters);
1267 free_newinfo: 999 free_newinfo:
1268 free_table_info(newinfo); 1000 xt_free_table_info(newinfo);
1269 return ret; 1001 return ret;
1270} 1002}
1271 1003
@@ -1273,7 +1005,7 @@ do_replace(void __user *user, unsigned int len)
1273 * and everything is OK. */ 1005 * and everything is OK. */
1274static inline int 1006static inline int
1275add_counter_to_entry(struct ipt_entry *e, 1007add_counter_to_entry(struct ipt_entry *e,
1276 const struct ipt_counters addme[], 1008 const struct xt_counters addme[],
1277 unsigned int *i) 1009 unsigned int *i)
1278{ 1010{
1279#if 0 1011#if 0
@@ -1295,15 +1027,16 @@ static int
1295do_add_counters(void __user *user, unsigned int len) 1027do_add_counters(void __user *user, unsigned int len)
1296{ 1028{
1297 unsigned int i; 1029 unsigned int i;
1298 struct ipt_counters_info tmp, *paddc; 1030 struct xt_counters_info tmp, *paddc;
1299 struct ipt_table *t; 1031 struct ipt_table *t;
1032 struct xt_table_info *private;
1300 int ret = 0; 1033 int ret = 0;
1301 void *loc_cpu_entry; 1034 void *loc_cpu_entry;
1302 1035
1303 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1036 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1304 return -EFAULT; 1037 return -EFAULT;
1305 1038
1306 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters)) 1039 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1307 return -EINVAL; 1040 return -EINVAL;
1308 1041
1309 paddc = vmalloc_node(len, numa_node_id()); 1042 paddc = vmalloc_node(len, numa_node_id());
@@ -1315,29 +1048,30 @@ do_add_counters(void __user *user, unsigned int len)
1315 goto free; 1048 goto free;
1316 } 1049 }
1317 1050
1318 t = find_table_lock(tmp.name); 1051 t = xt_find_table_lock(AF_INET, tmp.name);
1319 if (!t || IS_ERR(t)) { 1052 if (!t || IS_ERR(t)) {
1320 ret = t ? PTR_ERR(t) : -ENOENT; 1053 ret = t ? PTR_ERR(t) : -ENOENT;
1321 goto free; 1054 goto free;
1322 } 1055 }
1323 1056
1324 write_lock_bh(&t->lock); 1057 write_lock_bh(&t->lock);
1325 if (t->private->number != paddc->num_counters) { 1058 private = t->private;
1059 if (private->number != paddc->num_counters) {
1326 ret = -EINVAL; 1060 ret = -EINVAL;
1327 goto unlock_up_free; 1061 goto unlock_up_free;
1328 } 1062 }
1329 1063
1330 i = 0; 1064 i = 0;
1331 /* Choose the copy that is on our node */ 1065 /* Choose the copy that is on our node */
1332 loc_cpu_entry = t->private->entries[raw_smp_processor_id()]; 1066 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1333 IPT_ENTRY_ITERATE(loc_cpu_entry, 1067 IPT_ENTRY_ITERATE(loc_cpu_entry,
1334 t->private->size, 1068 private->size,
1335 add_counter_to_entry, 1069 add_counter_to_entry,
1336 paddc->counters, 1070 paddc->counters,
1337 &i); 1071 &i);
1338 unlock_up_free: 1072 unlock_up_free:
1339 write_unlock_bh(&t->lock); 1073 write_unlock_bh(&t->lock);
1340 up(&ipt_mutex); 1074 xt_table_unlock(t);
1341 module_put(t->me); 1075 module_put(t->me);
1342 free: 1076 free:
1343 vfree(paddc); 1077 vfree(paddc);
@@ -1396,25 +1130,26 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1396 } 1130 }
1397 name[IPT_TABLE_MAXNAMELEN-1] = '\0'; 1131 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1398 1132
1399 t = try_then_request_module(find_table_lock(name), 1133 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1400 "iptable_%s", name); 1134 "iptable_%s", name);
1401 if (t && !IS_ERR(t)) { 1135 if (t && !IS_ERR(t)) {
1402 struct ipt_getinfo info; 1136 struct ipt_getinfo info;
1137 struct xt_table_info *private = t->private;
1403 1138
1404 info.valid_hooks = t->valid_hooks; 1139 info.valid_hooks = t->valid_hooks;
1405 memcpy(info.hook_entry, t->private->hook_entry, 1140 memcpy(info.hook_entry, private->hook_entry,
1406 sizeof(info.hook_entry)); 1141 sizeof(info.hook_entry));
1407 memcpy(info.underflow, t->private->underflow, 1142 memcpy(info.underflow, private->underflow,
1408 sizeof(info.underflow)); 1143 sizeof(info.underflow));
1409 info.num_entries = t->private->number; 1144 info.num_entries = private->number;
1410 info.size = t->private->size; 1145 info.size = private->size;
1411 memcpy(info.name, name, sizeof(info.name)); 1146 memcpy(info.name, name, sizeof(info.name));
1412 1147
1413 if (copy_to_user(user, &info, *len) != 0) 1148 if (copy_to_user(user, &info, *len) != 0)
1414 ret = -EFAULT; 1149 ret = -EFAULT;
1415 else 1150 else
1416 ret = 0; 1151 ret = 0;
1417 up(&ipt_mutex); 1152 xt_table_unlock(t);
1418 module_put(t->me); 1153 module_put(t->me);
1419 } else 1154 } else
1420 ret = t ? PTR_ERR(t) : -ENOENT; 1155 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1441,7 +1176,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1441 case IPT_SO_GET_REVISION_MATCH: 1176 case IPT_SO_GET_REVISION_MATCH:
1442 case IPT_SO_GET_REVISION_TARGET: { 1177 case IPT_SO_GET_REVISION_TARGET: {
1443 struct ipt_get_revision rev; 1178 struct ipt_get_revision rev;
1444 int (*revfn)(const char *, u8, int *); 1179 int target;
1445 1180
1446 if (*len != sizeof(rev)) { 1181 if (*len != sizeof(rev)) {
1447 ret = -EINVAL; 1182 ret = -EINVAL;
@@ -1453,12 +1188,13 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1453 } 1188 }
1454 1189
1455 if (cmd == IPT_SO_GET_REVISION_TARGET) 1190 if (cmd == IPT_SO_GET_REVISION_TARGET)
1456 revfn = target_revfn; 1191 target = 1;
1457 else 1192 else
1458 revfn = match_revfn; 1193 target = 0;
1459 1194
1460 try_then_request_module(find_revision(rev.name, rev.revision, 1195 try_then_request_module(xt_find_revision(AF_INET, rev.name,
1461 revfn, &ret), 1196 rev.revision,
1197 target, &ret),
1462 "ipt_%s", rev.name); 1198 "ipt_%s", rev.name);
1463 break; 1199 break;
1464 } 1200 }
@@ -1471,60 +1207,15 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1471 return ret; 1207 return ret;
1472} 1208}
1473 1209
1474/* Registration hooks for targets. */ 1210int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
1475int
1476ipt_register_target(struct ipt_target *target)
1477{ 1211{
1478 int ret; 1212 int ret;
1479 1213 struct xt_table_info *newinfo;
1480 ret = down_interruptible(&ipt_mutex); 1214 static struct xt_table_info bootstrap
1481 if (ret != 0)
1482 return ret;
1483 list_add(&target->list, &ipt_target);
1484 up(&ipt_mutex);
1485 return ret;
1486}
1487
1488void
1489ipt_unregister_target(struct ipt_target *target)
1490{
1491 down(&ipt_mutex);
1492 LIST_DELETE(&ipt_target, target);
1493 up(&ipt_mutex);
1494}
1495
1496int
1497ipt_register_match(struct ipt_match *match)
1498{
1499 int ret;
1500
1501 ret = down_interruptible(&ipt_mutex);
1502 if (ret != 0)
1503 return ret;
1504
1505 list_add(&match->list, &ipt_match);
1506 up(&ipt_mutex);
1507
1508 return ret;
1509}
1510
1511void
1512ipt_unregister_match(struct ipt_match *match)
1513{
1514 down(&ipt_mutex);
1515 LIST_DELETE(&ipt_match, match);
1516 up(&ipt_mutex);
1517}
1518
1519int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
1520{
1521 int ret;
1522 struct ipt_table_info *newinfo;
1523 static struct ipt_table_info bootstrap
1524 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1215 = { 0, 0, 0, { 0 }, { 0 }, { } };
1525 void *loc_cpu_entry; 1216 void *loc_cpu_entry;
1526 1217
1527 newinfo = alloc_table_info(repl->size); 1218 newinfo = xt_alloc_table_info(repl->size);
1528 if (!newinfo) 1219 if (!newinfo)
1529 return -ENOMEM; 1220 return -ENOMEM;
1530 1221
@@ -1540,246 +1231,29 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
1540 repl->hook_entry, 1231 repl->hook_entry,
1541 repl->underflow); 1232 repl->underflow);
1542 if (ret != 0) { 1233 if (ret != 0) {
1543 free_table_info(newinfo); 1234 xt_free_table_info(newinfo);
1544 return ret; 1235 return ret;
1545 } 1236 }
1546 1237
1547 ret = down_interruptible(&ipt_mutex); 1238 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1548 if (ret != 0) { 1239 xt_free_table_info(newinfo);
1549 free_table_info(newinfo);
1550 return ret; 1240 return ret;
1551 } 1241 }
1552 1242
1553 /* Don't autoload: we'd eat our tail... */ 1243 return 0;
1554 if (list_named_find(&ipt_tables, table->name)) {
1555 ret = -EEXIST;
1556 goto free_unlock;
1557 }
1558
1559 /* Simplifies replace_table code. */
1560 table->private = &bootstrap;
1561 if (!replace_table(table, 0, newinfo, &ret))
1562 goto free_unlock;
1563
1564 duprintf("table->private->number = %u\n",
1565 table->private->number);
1566
1567 /* save number of initial entries */
1568 table->private->initial_entries = table->private->number;
1569
1570 rwlock_init(&table->lock);
1571 list_prepend(&ipt_tables, table);
1572
1573 unlock:
1574 up(&ipt_mutex);
1575 return ret;
1576
1577 free_unlock:
1578 free_table_info(newinfo);
1579 goto unlock;
1580} 1244}
1581 1245
1582void ipt_unregister_table(struct ipt_table *table) 1246void ipt_unregister_table(struct ipt_table *table)
1583{ 1247{
1248 struct xt_table_info *private;
1584 void *loc_cpu_entry; 1249 void *loc_cpu_entry;
1585 1250
1586 down(&ipt_mutex); 1251 private = xt_unregister_table(table);
1587 LIST_DELETE(&ipt_tables, table);
1588 up(&ipt_mutex);
1589 1252
1590 /* Decrease module usage counts and free resources */ 1253 /* Decrease module usage counts and free resources */
1591 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 1254 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1592 IPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, 1255 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
1593 cleanup_entry, NULL); 1256 xt_free_table_info(private);
1594 free_table_info(table->private);
1595}
1596
1597/* Returns 1 if the port is matched by the range, 0 otherwise */
1598static inline int
1599port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
1600{
1601 int ret;
1602
1603 ret = (port >= min && port <= max) ^ invert;
1604 return ret;
1605}
1606
1607static int
1608tcp_find_option(u_int8_t option,
1609 const struct sk_buff *skb,
1610 unsigned int optlen,
1611 int invert,
1612 int *hotdrop)
1613{
1614 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
1615 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
1616 unsigned int i;
1617
1618 duprintf("tcp_match: finding option\n");
1619
1620 if (!optlen)
1621 return invert;
1622
1623 /* If we don't have the whole header, drop packet. */
1624 op = skb_header_pointer(skb,
1625 skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
1626 optlen, _opt);
1627 if (op == NULL) {
1628 *hotdrop = 1;
1629 return 0;
1630 }
1631
1632 for (i = 0; i < optlen; ) {
1633 if (op[i] == option) return !invert;
1634 if (op[i] < 2) i++;
1635 else i += op[i+1]?:1;
1636 }
1637
1638 return invert;
1639}
1640
1641static int
1642tcp_match(const struct sk_buff *skb,
1643 const struct net_device *in,
1644 const struct net_device *out,
1645 const void *matchinfo,
1646 int offset,
1647 int *hotdrop)
1648{
1649 struct tcphdr _tcph, *th;
1650 const struct ipt_tcp *tcpinfo = matchinfo;
1651
1652 if (offset) {
1653 /* To quote Alan:
1654
1655 Don't allow a fragment of TCP 8 bytes in. Nobody normal
1656 causes this. Its a cracker trying to break in by doing a
1657 flag overwrite to pass the direction checks.
1658 */
1659 if (offset == 1) {
1660 duprintf("Dropping evil TCP offset=1 frag.\n");
1661 *hotdrop = 1;
1662 }
1663 /* Must not be a fragment. */
1664 return 0;
1665 }
1666
1667#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
1668
1669 th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
1670 sizeof(_tcph), &_tcph);
1671 if (th == NULL) {
1672 /* We've been asked to examine this packet, and we
1673 can't. Hence, no choice but to drop. */
1674 duprintf("Dropping evil TCP offset=0 tinygram.\n");
1675 *hotdrop = 1;
1676 return 0;
1677 }
1678
1679 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
1680 ntohs(th->source),
1681 !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT)))
1682 return 0;
1683 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
1684 ntohs(th->dest),
1685 !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT)))
1686 return 0;
1687 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
1688 == tcpinfo->flg_cmp,
1689 IPT_TCP_INV_FLAGS))
1690 return 0;
1691 if (tcpinfo->option) {
1692 if (th->doff * 4 < sizeof(_tcph)) {
1693 *hotdrop = 1;
1694 return 0;
1695 }
1696 if (!tcp_find_option(tcpinfo->option, skb,
1697 th->doff*4 - sizeof(_tcph),
1698 tcpinfo->invflags & IPT_TCP_INV_OPTION,
1699 hotdrop))
1700 return 0;
1701 }
1702 return 1;
1703}
1704
1705/* Called when user tries to insert an entry of this type. */
1706static int
1707tcp_checkentry(const char *tablename,
1708 const struct ipt_ip *ip,
1709 void *matchinfo,
1710 unsigned int matchsize,
1711 unsigned int hook_mask)
1712{
1713 const struct ipt_tcp *tcpinfo = matchinfo;
1714
1715 /* Must specify proto == TCP, and no unknown invflags */
1716 return ip->proto == IPPROTO_TCP
1717 && !(ip->invflags & IPT_INV_PROTO)
1718 && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp))
1719 && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK);
1720}
1721
1722static int
1723udp_match(const struct sk_buff *skb,
1724 const struct net_device *in,
1725 const struct net_device *out,
1726 const void *matchinfo,
1727 int offset,
1728 int *hotdrop)
1729{
1730 struct udphdr _udph, *uh;
1731 const struct ipt_udp *udpinfo = matchinfo;
1732
1733 /* Must not be a fragment. */
1734 if (offset)
1735 return 0;
1736
1737 uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
1738 sizeof(_udph), &_udph);
1739 if (uh == NULL) {
1740 /* We've been asked to examine this packet, and we
1741 can't. Hence, no choice but to drop. */
1742 duprintf("Dropping evil UDP tinygram.\n");
1743 *hotdrop = 1;
1744 return 0;
1745 }
1746
1747 return port_match(udpinfo->spts[0], udpinfo->spts[1],
1748 ntohs(uh->source),
1749 !!(udpinfo->invflags & IPT_UDP_INV_SRCPT))
1750 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
1751 ntohs(uh->dest),
1752 !!(udpinfo->invflags & IPT_UDP_INV_DSTPT));
1753}
1754
1755/* Called when user tries to insert an entry of this type. */
1756static int
1757udp_checkentry(const char *tablename,
1758 const struct ipt_ip *ip,
1759 void *matchinfo,
1760 unsigned int matchinfosize,
1761 unsigned int hook_mask)
1762{
1763 const struct ipt_udp *udpinfo = matchinfo;
1764
1765 /* Must specify proto == UDP, and no unknown invflags */
1766 if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) {
1767 duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
1768 IPPROTO_UDP);
1769 return 0;
1770 }
1771 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) {
1772 duprintf("ipt_udp: matchsize %u != %u\n",
1773 matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp)));
1774 return 0;
1775 }
1776 if (udpinfo->invflags & ~IPT_UDP_INV_MASK) {
1777 duprintf("ipt_udp: unknown flags %X\n",
1778 udpinfo->invflags);
1779 return 0;
1780 }
1781
1782 return 1;
1783} 1257}
1784 1258
1785/* Returns 1 if the type and code is matched by the range, 0 otherwise */ 1259/* Returns 1 if the type and code is matched by the range, 0 otherwise */
@@ -1798,6 +1272,7 @@ icmp_match(const struct sk_buff *skb,
1798 const struct net_device *out, 1272 const struct net_device *out,
1799 const void *matchinfo, 1273 const void *matchinfo,
1800 int offset, 1274 int offset,
1275 unsigned int protoff,
1801 int *hotdrop) 1276 int *hotdrop)
1802{ 1277{
1803 struct icmphdr _icmph, *ic; 1278 struct icmphdr _icmph, *ic;
@@ -1807,8 +1282,7 @@ icmp_match(const struct sk_buff *skb,
1807 if (offset) 1282 if (offset)
1808 return 0; 1283 return 0;
1809 1284
1810 ic = skb_header_pointer(skb, skb->nh.iph->ihl*4, 1285 ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
1811 sizeof(_icmph), &_icmph);
1812 if (ic == NULL) { 1286 if (ic == NULL) {
1813 /* We've been asked to examine this packet, and we 1287 /* We've been asked to examine this packet, and we
1814 * can't. Hence, no choice but to drop. 1288 * can't. Hence, no choice but to drop.
@@ -1828,11 +1302,12 @@ icmp_match(const struct sk_buff *skb,
1828/* Called when user tries to insert an entry of this type. */ 1302/* Called when user tries to insert an entry of this type. */
1829static int 1303static int
1830icmp_checkentry(const char *tablename, 1304icmp_checkentry(const char *tablename,
1831 const struct ipt_ip *ip, 1305 const void *info,
1832 void *matchinfo, 1306 void *matchinfo,
1833 unsigned int matchsize, 1307 unsigned int matchsize,
1834 unsigned int hook_mask) 1308 unsigned int hook_mask)
1835{ 1309{
1310 const struct ipt_ip *ip = info;
1836 const struct ipt_icmp *icmpinfo = matchinfo; 1311 const struct ipt_icmp *icmpinfo = matchinfo;
1837 1312
1838 /* Must specify proto == ICMP, and no unknown invflags */ 1313 /* Must specify proto == ICMP, and no unknown invflags */
@@ -1862,123 +1337,22 @@ static struct nf_sockopt_ops ipt_sockopts = {
1862 .get = do_ipt_get_ctl, 1337 .get = do_ipt_get_ctl,
1863}; 1338};
1864 1339
1865static struct ipt_match tcp_matchstruct = {
1866 .name = "tcp",
1867 .match = &tcp_match,
1868 .checkentry = &tcp_checkentry,
1869};
1870
1871static struct ipt_match udp_matchstruct = {
1872 .name = "udp",
1873 .match = &udp_match,
1874 .checkentry = &udp_checkentry,
1875};
1876
1877static struct ipt_match icmp_matchstruct = { 1340static struct ipt_match icmp_matchstruct = {
1878 .name = "icmp", 1341 .name = "icmp",
1879 .match = &icmp_match, 1342 .match = &icmp_match,
1880 .checkentry = &icmp_checkentry, 1343 .checkentry = &icmp_checkentry,
1881}; 1344};
1882 1345
1883#ifdef CONFIG_PROC_FS
1884static inline int print_name(const char *i,
1885 off_t start_offset, char *buffer, int length,
1886 off_t *pos, unsigned int *count)
1887{
1888 if ((*count)++ >= start_offset) {
1889 unsigned int namelen;
1890
1891 namelen = sprintf(buffer + *pos, "%s\n",
1892 i + sizeof(struct list_head));
1893 if (*pos + namelen > length) {
1894 /* Stop iterating */
1895 return 1;
1896 }
1897 *pos += namelen;
1898 }
1899 return 0;
1900}
1901
1902static inline int print_target(const struct ipt_target *t,
1903 off_t start_offset, char *buffer, int length,
1904 off_t *pos, unsigned int *count)
1905{
1906 if (t == &ipt_standard_target || t == &ipt_error_target)
1907 return 0;
1908 return print_name((char *)t, start_offset, buffer, length, pos, count);
1909}
1910
1911static int ipt_get_tables(char *buffer, char **start, off_t offset, int length)
1912{
1913 off_t pos = 0;
1914 unsigned int count = 0;
1915
1916 if (down_interruptible(&ipt_mutex) != 0)
1917 return 0;
1918
1919 LIST_FIND(&ipt_tables, print_name, void *,
1920 offset, buffer, length, &pos, &count);
1921
1922 up(&ipt_mutex);
1923
1924 /* `start' hack - see fs/proc/generic.c line ~105 */
1925 *start=(char *)((unsigned long)count-offset);
1926 return pos;
1927}
1928
1929static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
1930{
1931 off_t pos = 0;
1932 unsigned int count = 0;
1933
1934 if (down_interruptible(&ipt_mutex) != 0)
1935 return 0;
1936
1937 LIST_FIND(&ipt_target, print_target, struct ipt_target *,
1938 offset, buffer, length, &pos, &count);
1939
1940 up(&ipt_mutex);
1941
1942 *start = (char *)((unsigned long)count - offset);
1943 return pos;
1944}
1945
1946static int ipt_get_matches(char *buffer, char **start, off_t offset, int length)
1947{
1948 off_t pos = 0;
1949 unsigned int count = 0;
1950
1951 if (down_interruptible(&ipt_mutex) != 0)
1952 return 0;
1953
1954 LIST_FIND(&ipt_match, print_name, void *,
1955 offset, buffer, length, &pos, &count);
1956
1957 up(&ipt_mutex);
1958
1959 *start = (char *)((unsigned long)count - offset);
1960 return pos;
1961}
1962
1963static const struct { char *name; get_info_t *get_info; } ipt_proc_entry[] =
1964{ { "ip_tables_names", ipt_get_tables },
1965 { "ip_tables_targets", ipt_get_targets },
1966 { "ip_tables_matches", ipt_get_matches },
1967 { NULL, NULL} };
1968#endif /*CONFIG_PROC_FS*/
1969
1970static int __init init(void) 1346static int __init init(void)
1971{ 1347{
1972 int ret; 1348 int ret;
1973 1349
1350 xt_proto_init(AF_INET);
1351
1974 /* Noone else will be downing sem now, so we won't sleep */ 1352 /* Noone else will be downing sem now, so we won't sleep */
1975 down(&ipt_mutex); 1353 xt_register_target(AF_INET, &ipt_standard_target);
1976 list_append(&ipt_target, &ipt_standard_target); 1354 xt_register_target(AF_INET, &ipt_error_target);
1977 list_append(&ipt_target, &ipt_error_target); 1355 xt_register_match(AF_INET, &icmp_matchstruct);
1978 list_append(&ipt_match, &tcp_matchstruct);
1979 list_append(&ipt_match, &udp_matchstruct);
1980 list_append(&ipt_match, &icmp_matchstruct);
1981 up(&ipt_mutex);
1982 1356
1983 /* Register setsockopt */ 1357 /* Register setsockopt */
1984 ret = nf_register_sockopt(&ipt_sockopts); 1358 ret = nf_register_sockopt(&ipt_sockopts);
@@ -1987,49 +1361,23 @@ static int __init init(void)
1987 return ret; 1361 return ret;
1988 } 1362 }
1989 1363
1990#ifdef CONFIG_PROC_FS 1364 printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
1991 {
1992 struct proc_dir_entry *proc;
1993 int i;
1994
1995 for (i = 0; ipt_proc_entry[i].name; i++) {
1996 proc = proc_net_create(ipt_proc_entry[i].name, 0,
1997 ipt_proc_entry[i].get_info);
1998 if (!proc) {
1999 while (--i >= 0)
2000 proc_net_remove(ipt_proc_entry[i].name);
2001 nf_unregister_sockopt(&ipt_sockopts);
2002 return -ENOMEM;
2003 }
2004 proc->owner = THIS_MODULE;
2005 }
2006 }
2007#endif
2008
2009 printk("ip_tables: (C) 2000-2002 Netfilter core team\n");
2010 return 0; 1365 return 0;
2011} 1366}
2012 1367
2013static void __exit fini(void) 1368static void __exit fini(void)
2014{ 1369{
2015 nf_unregister_sockopt(&ipt_sockopts); 1370 nf_unregister_sockopt(&ipt_sockopts);
2016#ifdef CONFIG_PROC_FS 1371
2017 { 1372 xt_unregister_match(AF_INET, &icmp_matchstruct);
2018 int i; 1373 xt_unregister_target(AF_INET, &ipt_error_target);
2019 for (i = 0; ipt_proc_entry[i].name; i++) 1374 xt_unregister_target(AF_INET, &ipt_standard_target);
2020 proc_net_remove(ipt_proc_entry[i].name); 1375
2021 } 1376 xt_proto_fini(AF_INET);
2022#endif
2023} 1377}
2024 1378
2025EXPORT_SYMBOL(ipt_register_table); 1379EXPORT_SYMBOL(ipt_register_table);
2026EXPORT_SYMBOL(ipt_unregister_table); 1380EXPORT_SYMBOL(ipt_unregister_table);
2027EXPORT_SYMBOL(ipt_register_match);
2028EXPORT_SYMBOL(ipt_unregister_match);
2029EXPORT_SYMBOL(ipt_do_table); 1381EXPORT_SYMBOL(ipt_do_table);
2030EXPORT_SYMBOL(ipt_register_target);
2031EXPORT_SYMBOL(ipt_unregister_target);
2032EXPORT_SYMBOL(ipt_find_target);
2033
2034module_init(init); 1382module_init(init);
2035module_exit(fini); 1383module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 45c52d8f4d99..d9bc971f03af 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -379,12 +379,13 @@ target(struct sk_buff **pskb,
379 379
380static int 380static int
381checkentry(const char *tablename, 381checkentry(const char *tablename,
382 const struct ipt_entry *e, 382 const void *e_void,
383 void *targinfo, 383 void *targinfo,
384 unsigned int targinfosize, 384 unsigned int targinfosize,
385 unsigned int hook_mask) 385 unsigned int hook_mask)
386{ 386{
387 struct ipt_clusterip_tgt_info *cipinfo = targinfo; 387 struct ipt_clusterip_tgt_info *cipinfo = targinfo;
388 const struct ipt_entry *e = e_void;
388 389
389 struct clusterip_config *config; 390 struct clusterip_config *config;
390 391
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index 6e319570a28c..898cdf79ce18 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -57,7 +57,7 @@ target(struct sk_buff **pskb,
57 57
58static int 58static int
59checkentry(const char *tablename, 59checkentry(const char *tablename,
60 const struct ipt_entry *e, 60 const void *e_void,
61 void *targinfo, 61 void *targinfo,
62 unsigned int targinfosize, 62 unsigned int targinfosize,
63 unsigned int hook_mask) 63 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index a1319693f648..706445426a6d 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -113,12 +113,13 @@ target(struct sk_buff **pskb,
113 113
114static int 114static int
115checkentry(const char *tablename, 115checkentry(const char *tablename,
116 const struct ipt_entry *e, 116 const void *e_void,
117 void *targinfo, 117 void *targinfo,
118 unsigned int targinfosize, 118 unsigned int targinfosize,
119 unsigned int hook_mask) 119 unsigned int hook_mask)
120{ 120{
121 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; 121 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
122 const struct ipt_entry *e = e_void;
122 123
123 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { 124 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) {
124 printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", 125 printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n",
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 30be0f1dae37..6606ddb66a29 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -431,7 +431,7 @@ ipt_log_target(struct sk_buff **pskb,
431} 431}
432 432
433static int ipt_log_checkentry(const char *tablename, 433static int ipt_log_checkentry(const char *tablename,
434 const struct ipt_entry *e, 434 const void *e,
435 void *targinfo, 435 void *targinfo,
436 unsigned int targinfosize, 436 unsigned int targinfosize,
437 unsigned int hook_mask) 437 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 27860510ca6d..12c56d3343ca 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -40,7 +40,7 @@ static DEFINE_RWLOCK(masq_lock);
40/* FIXME: Multiple targets. --RR */ 40/* FIXME: Multiple targets. --RR */
41static int 41static int
42masquerade_check(const char *tablename, 42masquerade_check(const char *tablename,
43 const struct ipt_entry *e, 43 const void *e,
44 void *targinfo, 44 void *targinfo,
45 unsigned int targinfosize, 45 unsigned int targinfosize,
46 unsigned int hook_mask) 46 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index e6e7b6095363..b074467fe67b 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -31,7 +31,7 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
31 31
32static int 32static int
33check(const char *tablename, 33check(const char *tablename,
34 const struct ipt_entry *e, 34 const void *e,
35 void *targinfo, 35 void *targinfo,
36 unsigned int targinfosize, 36 unsigned int targinfosize,
37 unsigned int hook_mask) 37 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_NFQUEUE.c b/net/ipv4/netfilter/ipt_NFQUEUE.c
deleted file mode 100644
index 3cedc9be8807..000000000000
--- a/net/ipv4/netfilter/ipt_NFQUEUE.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* iptables module for using new netfilter netlink queue
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter_ipv4/ip_tables.h>
16#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
17
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("iptables NFQUEUE target");
20MODULE_LICENSE("GPL");
21
22static unsigned int
23target(struct sk_buff **pskb,
24 const struct net_device *in,
25 const struct net_device *out,
26 unsigned int hooknum,
27 const void *targinfo,
28 void *userinfo)
29{
30 const struct ipt_NFQ_info *tinfo = targinfo;
31
32 return NF_QUEUE_NR(tinfo->queuenum);
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ipt_entry *e,
38 void *targinfo,
39 unsigned int targinfosize,
40 unsigned int hook_mask)
41{
42 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_NFQ_info))) {
43 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
44 targinfosize,
45 IPT_ALIGN(sizeof(struct ipt_NFQ_info)));
46 return 0;
47 }
48
49 return 1;
50}
51
52static struct ipt_target ipt_NFQ_reg = {
53 .name = "NFQUEUE",
54 .target = target,
55 .checkentry = checkentry,
56 .me = THIS_MODULE,
57};
58
59static int __init init(void)
60{
61 return ipt_register_target(&ipt_NFQ_reg);
62}
63
64static void __exit fini(void)
65{
66 ipt_unregister_target(&ipt_NFQ_reg);
67}
68
69module_init(init);
70module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 5245bfd33d52..140be51f2f01 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables REDIRECT target module");
33/* FIXME: Take multiple ranges --RR */ 33/* FIXME: Take multiple ranges --RR */
34static int 34static int
35redirect_check(const char *tablename, 35redirect_check(const char *tablename,
36 const struct ipt_entry *e, 36 const void *e,
37 void *targinfo, 37 void *targinfo,
38 unsigned int targinfosize, 38 unsigned int targinfosize,
39 unsigned int hook_mask) 39 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 6693526ae128..3eb47aae78c5 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -282,12 +282,13 @@ static unsigned int reject(struct sk_buff **pskb,
282} 282}
283 283
284static int check(const char *tablename, 284static int check(const char *tablename,
285 const struct ipt_entry *e, 285 const void *e_void,
286 void *targinfo, 286 void *targinfo,
287 unsigned int targinfosize, 287 unsigned int targinfosize,
288 unsigned int hook_mask) 288 unsigned int hook_mask)
289{ 289{
290 const struct ipt_reject_info *rejinfo = targinfo; 290 const struct ipt_reject_info *rejinfo = targinfo;
291 const struct ipt_entry *e = e_void;
291 292
292 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { 293 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) {
293 DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); 294 DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 7a0536d864ac..a22de59bba0e 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -49,7 +49,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
49 49
50static int 50static int
51same_check(const char *tablename, 51same_check(const char *tablename,
52 const struct ipt_entry *e, 52 const void *e,
53 void *targinfo, 53 void *targinfo,
54 unsigned int targinfosize, 54 unsigned int targinfosize,
55 unsigned int hook_mask) 55 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index 8db70d6908c3..c122841e182c 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -210,12 +210,13 @@ static inline int find_syn_match(const struct ipt_entry_match *m)
210/* Must specify -p tcp --syn/--tcp-flags SYN */ 210/* Must specify -p tcp --syn/--tcp-flags SYN */
211static int 211static int
212ipt_tcpmss_checkentry(const char *tablename, 212ipt_tcpmss_checkentry(const char *tablename,
213 const struct ipt_entry *e, 213 const void *e_void,
214 void *targinfo, 214 void *targinfo,
215 unsigned int targinfosize, 215 unsigned int targinfosize,
216 unsigned int hook_mask) 216 unsigned int hook_mask)
217{ 217{
218 const struct ipt_tcpmss_info *tcpmssinfo = targinfo; 218 const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
219 const struct ipt_entry *e = e_void;
219 220
220 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { 221 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) {
221 DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", 222 DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n",
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index deadb36d4428..3a44a56db239 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -52,7 +52,7 @@ target(struct sk_buff **pskb,
52 52
53static int 53static int
54checkentry(const char *tablename, 54checkentry(const char *tablename,
55 const struct ipt_entry *e, 55 const void *e_void,
56 void *targinfo, 56 void *targinfo,
57 unsigned int targinfosize, 57 unsigned int targinfosize,
58 unsigned int hook_mask) 58 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index b9ae6a9382f3..b769eb231970 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -66,7 +66,7 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
66} 66}
67 67
68static int ipt_ttl_checkentry(const char *tablename, 68static int ipt_ttl_checkentry(const char *tablename,
69 const struct ipt_entry *e, 69 const void *e,
70 void *targinfo, 70 void *targinfo,
71 unsigned int targinfosize, 71 unsigned int targinfosize,
72 unsigned int hook_mask) 72 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 38641cd06123..641dbc477650 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -330,7 +330,7 @@ static void ipt_logfn(unsigned int pf,
330} 330}
331 331
332static int ipt_ulog_checkentry(const char *tablename, 332static int ipt_ulog_checkentry(const char *tablename,
333 const struct ipt_entry *e, 333 const void *e,
334 void *targinfo, 334 void *targinfo,
335 unsigned int targinfosize, 335 unsigned int targinfosize,
336 unsigned int hookmask) 336 unsigned int hookmask)
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index e19c2a52d00c..d6b83a976518 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -29,7 +29,7 @@ static inline int match_type(u_int32_t addr, u_int16_t mask)
29 29
30static int match(const struct sk_buff *skb, const struct net_device *in, 30static int match(const struct sk_buff *skb, const struct net_device *in,
31 const struct net_device *out, const void *matchinfo, 31 const struct net_device *out, const void *matchinfo,
32 int offset, int *hotdrop) 32 int offset, unsigned int protoff, int *hotdrop)
33{ 33{
34 const struct ipt_addrtype_info *info = matchinfo; 34 const struct ipt_addrtype_info *info = matchinfo;
35 const struct iphdr *iph = skb->nh.iph; 35 const struct iphdr *iph = skb->nh.iph;
@@ -43,7 +43,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
43 return ret; 43 return ret;
44} 44}
45 45
46static int checkentry(const char *tablename, const struct ipt_ip *ip, 46static int checkentry(const char *tablename, const void *ip,
47 void *matchinfo, unsigned int matchsize, 47 void *matchinfo, unsigned int matchsize,
48 unsigned int hook_mask) 48 unsigned int hook_mask)
49{ 49{
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index a0fea847cb72..144adfec13cc 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -41,6 +41,7 @@ match(const struct sk_buff *skb,
41 const struct net_device *out, 41 const struct net_device *out,
42 const void *matchinfo, 42 const void *matchinfo,
43 int offset, 43 int offset,
44 unsigned int protoff,
44 int *hotdrop) 45 int *hotdrop)
45{ 46{
46 struct ip_auth_hdr _ahdr, *ah; 47 struct ip_auth_hdr _ahdr, *ah;
@@ -50,7 +51,7 @@ match(const struct sk_buff *skb,
50 if (offset) 51 if (offset)
51 return 0; 52 return 0;
52 53
53 ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 54 ah = skb_header_pointer(skb, protoff,
54 sizeof(_ahdr), &_ahdr); 55 sizeof(_ahdr), &_ahdr);
55 if (ah == NULL) { 56 if (ah == NULL) {
56 /* We've been asked to examine this packet, and we 57 /* We've been asked to examine this packet, and we
@@ -69,12 +70,13 @@ match(const struct sk_buff *skb,
69/* Called when user tries to insert an entry of this type. */ 70/* Called when user tries to insert an entry of this type. */
70static int 71static int
71checkentry(const char *tablename, 72checkentry(const char *tablename,
72 const struct ipt_ip *ip, 73 const void *ip_void,
73 void *matchinfo, 74 void *matchinfo,
74 unsigned int matchinfosize, 75 unsigned int matchinfosize,
75 unsigned int hook_mask) 76 unsigned int hook_mask)
76{ 77{
77 const struct ipt_ah *ahinfo = matchinfo; 78 const struct ipt_ah *ahinfo = matchinfo;
79 const struct ipt_ip *ip = ip_void;
78 80
79 /* Must specify proto == AH, and no unknown invflags */ 81 /* Must specify proto == AH, and no unknown invflags */
80 if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { 82 if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) {
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c
index 5df52a64a5d4..92063b4f8602 100644
--- a/net/ipv4/netfilter/ipt_dscp.c
+++ b/net/ipv4/netfilter/ipt_dscp.c
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL");
21 21
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static int match(const struct sk_buff *skb, const struct net_device *in,
23 const struct net_device *out, const void *matchinfo, 23 const struct net_device *out, const void *matchinfo,
24 int offset, int *hotdrop) 24 int offset, unsigned int protoff, int *hotdrop)
25{ 25{
26 const struct ipt_dscp_info *info = matchinfo; 26 const struct ipt_dscp_info *info = matchinfo;
27 const struct iphdr *iph = skb->nh.iph; 27 const struct iphdr *iph = skb->nh.iph;
@@ -31,7 +31,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
31 return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; 31 return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert;
32} 32}
33 33
34static int checkentry(const char *tablename, const struct ipt_ip *ip, 34static int checkentry(const char *tablename, const void *ip,
35 void *matchinfo, unsigned int matchsize, 35 void *matchinfo, unsigned int matchsize,
36 unsigned int hook_mask) 36 unsigned int hook_mask)
37{ 37{
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index b6f7181e89cc..e68b0c7981f0 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -67,7 +67,7 @@ static inline int match_tcp(const struct sk_buff *skb,
67 67
68static int match(const struct sk_buff *skb, const struct net_device *in, 68static int match(const struct sk_buff *skb, const struct net_device *in,
69 const struct net_device *out, const void *matchinfo, 69 const struct net_device *out, const void *matchinfo,
70 int offset, int *hotdrop) 70 int offset, unsigned int protoff, int *hotdrop)
71{ 71{
72 const struct ipt_ecn_info *info = matchinfo; 72 const struct ipt_ecn_info *info = matchinfo;
73 73
@@ -85,11 +85,12 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
85 return 1; 85 return 1;
86} 86}
87 87
88static int checkentry(const char *tablename, const struct ipt_ip *ip, 88static int checkentry(const char *tablename, const void *ip_void,
89 void *matchinfo, unsigned int matchsize, 89 void *matchinfo, unsigned int matchsize,
90 unsigned int hook_mask) 90 unsigned int hook_mask)
91{ 91{
92 const struct ipt_ecn_info *info = matchinfo; 92 const struct ipt_ecn_info *info = matchinfo;
93 const struct ipt_ip *ip = ip_void;
93 94
94 if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) 95 if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info)))
95 return 0; 96 return 0;
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
index e1d0dd31e117..9de191a8162d 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/ipv4/netfilter/ipt_esp.c
@@ -42,6 +42,7 @@ match(const struct sk_buff *skb,
42 const struct net_device *out, 42 const struct net_device *out,
43 const void *matchinfo, 43 const void *matchinfo,
44 int offset, 44 int offset,
45 unsigned int protoff,
45 int *hotdrop) 46 int *hotdrop)
46{ 47{
47 struct ip_esp_hdr _esp, *eh; 48 struct ip_esp_hdr _esp, *eh;
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb,
51 if (offset) 52 if (offset)
52 return 0; 53 return 0;
53 54
54 eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 55 eh = skb_header_pointer(skb, protoff,
55 sizeof(_esp), &_esp); 56 sizeof(_esp), &_esp);
56 if (eh == NULL) { 57 if (eh == NULL) {
57 /* We've been asked to examine this packet, and we 58 /* We've been asked to examine this packet, and we
@@ -70,12 +71,13 @@ match(const struct sk_buff *skb,
70/* Called when user tries to insert an entry of this type. */ 71/* Called when user tries to insert an entry of this type. */
71static int 72static int
72checkentry(const char *tablename, 73checkentry(const char *tablename,
73 const struct ipt_ip *ip, 74 const void *ip_void,
74 void *matchinfo, 75 void *matchinfo,
75 unsigned int matchinfosize, 76 unsigned int matchinfosize,
76 unsigned int hook_mask) 77 unsigned int hook_mask)
77{ 78{
78 const struct ipt_esp *espinfo = matchinfo; 79 const struct ipt_esp *espinfo = matchinfo;
80 const struct ipt_ip *ip = ip_void;
79 81
80 /* Must specify proto == ESP, and no unknown invflags */ 82 /* Must specify proto == ESP, and no unknown invflags */
81 if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) { 83 if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) {
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 2dd1cccbdab9..4fe48c1bd5f3 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -429,6 +429,7 @@ hashlimit_match(const struct sk_buff *skb,
429 const struct net_device *out, 429 const struct net_device *out,
430 const void *matchinfo, 430 const void *matchinfo,
431 int offset, 431 int offset,
432 unsigned int protoff,
432 int *hotdrop) 433 int *hotdrop)
433{ 434{
434 struct ipt_hashlimit_info *r = 435 struct ipt_hashlimit_info *r =
@@ -504,7 +505,7 @@ hashlimit_match(const struct sk_buff *skb,
504 505
505static int 506static int
506hashlimit_checkentry(const char *tablename, 507hashlimit_checkentry(const char *tablename,
507 const struct ipt_ip *ip, 508 const void *inf,
508 void *matchinfo, 509 void *matchinfo,
509 unsigned int matchsize, 510 unsigned int matchsize,
510 unsigned int hook_mask) 511 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index b835b7b2e560..13fb16fb7892 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb,
28 const struct net_device *in, 28 const struct net_device *in,
29 const struct net_device *out, 29 const struct net_device *out,
30 const void *matchinfo, 30 const void *matchinfo,
31 int offset, int *hotdrop) 31 int offset, unsigned int protoff, int *hotdrop)
32{ 32{
33 const struct ipt_iprange_info *info = matchinfo; 33 const struct ipt_iprange_info *info = matchinfo;
34 const struct iphdr *iph = skb->nh.iph; 34 const struct iphdr *iph = skb->nh.iph;
@@ -63,7 +63,7 @@ match(const struct sk_buff *skb,
63} 63}
64 64
65static int check(const char *tablename, 65static int check(const char *tablename,
66 const struct ipt_ip *ip, 66 const void *inf,
67 void *matchinfo, 67 void *matchinfo,
68 unsigned int matchsize, 68 unsigned int matchsize,
69 unsigned int hook_mask) 69 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_length.c b/net/ipv4/netfilter/ipt_length.c
deleted file mode 100644
index 4eabcfbda9d1..000000000000
--- a/net/ipv4/netfilter/ipt_length.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/* Kernel module to match packet length. */
2/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
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/module.h>
10#include <linux/skbuff.h>
11
12#include <linux/netfilter_ipv4/ipt_length.h>
13#include <linux/netfilter_ipv4/ip_tables.h>
14
15MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
16MODULE_DESCRIPTION("IP tables packet length matching module");
17MODULE_LICENSE("GPL");
18
19static int
20match(const struct sk_buff *skb,
21 const struct net_device *in,
22 const struct net_device *out,
23 const void *matchinfo,
24 int offset,
25 int *hotdrop)
26{
27 const struct ipt_length_info *info = matchinfo;
28 u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
29
30 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
31}
32
33static int
34checkentry(const char *tablename,
35 const struct ipt_ip *ip,
36 void *matchinfo,
37 unsigned int matchsize,
38 unsigned int hook_mask)
39{
40 if (matchsize != IPT_ALIGN(sizeof(struct ipt_length_info)))
41 return 0;
42
43 return 1;
44}
45
46static struct ipt_match length_match = {
47 .name = "length",
48 .match = &match,
49 .checkentry = &checkentry,
50 .me = THIS_MODULE,
51};
52
53static int __init init(void)
54{
55 return ipt_register_match(&length_match);
56}
57
58static void __exit fini(void)
59{
60 ipt_unregister_match(&length_match);
61}
62
63module_init(init);
64module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
index 99e8188162e2..2d52326553f1 100644
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ b/net/ipv4/netfilter/ipt_multiport.c
@@ -97,6 +97,7 @@ match(const struct sk_buff *skb,
97 const struct net_device *out, 97 const struct net_device *out,
98 const void *matchinfo, 98 const void *matchinfo,
99 int offset, 99 int offset,
100 unsigned int protoff,
100 int *hotdrop) 101 int *hotdrop)
101{ 102{
102 u16 _ports[2], *pptr; 103 u16 _ports[2], *pptr;
@@ -105,7 +106,7 @@ match(const struct sk_buff *skb,
105 if (offset) 106 if (offset)
106 return 0; 107 return 0;
107 108
108 pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 109 pptr = skb_header_pointer(skb, protoff,
109 sizeof(_ports), _ports); 110 sizeof(_ports), _ports);
110 if (pptr == NULL) { 111 if (pptr == NULL) {
111 /* We've been asked to examine this packet, and we 112 /* We've been asked to examine this packet, and we
@@ -128,6 +129,7 @@ match_v1(const struct sk_buff *skb,
128 const struct net_device *out, 129 const struct net_device *out,
129 const void *matchinfo, 130 const void *matchinfo,
130 int offset, 131 int offset,
132 unsigned int protoff,
131 int *hotdrop) 133 int *hotdrop)
132{ 134{
133 u16 _ports[2], *pptr; 135 u16 _ports[2], *pptr;
@@ -136,7 +138,7 @@ match_v1(const struct sk_buff *skb,
136 if (offset) 138 if (offset)
137 return 0; 139 return 0;
138 140
139 pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 141 pptr = skb_header_pointer(skb, protoff,
140 sizeof(_ports), _ports); 142 sizeof(_ports), _ports);
141 if (pptr == NULL) { 143 if (pptr == NULL) {
142 /* We've been asked to examine this packet, and we 144 /* We've been asked to examine this packet, and we
@@ -154,7 +156,7 @@ match_v1(const struct sk_buff *skb,
154/* Called when user tries to insert an entry of this type. */ 156/* Called when user tries to insert an entry of this type. */
155static int 157static int
156checkentry(const char *tablename, 158checkentry(const char *tablename,
157 const struct ipt_ip *ip, 159 const void *ip,
158 void *matchinfo, 160 void *matchinfo,
159 unsigned int matchsize, 161 unsigned int matchsize,
160 unsigned int hook_mask) 162 unsigned int hook_mask)
@@ -164,7 +166,7 @@ checkentry(const char *tablename,
164 166
165static int 167static int
166checkentry_v1(const char *tablename, 168checkentry_v1(const char *tablename,
167 const struct ipt_ip *ip, 169 const void *ip,
168 void *matchinfo, 170 void *matchinfo,
169 unsigned int matchsize, 171 unsigned int matchsize,
170 unsigned int hook_mask) 172 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 0cee2862ed85..4843d0c9734f 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -27,6 +27,7 @@ match(const struct sk_buff *skb,
27 const struct net_device *out, 27 const struct net_device *out,
28 const void *matchinfo, 28 const void *matchinfo,
29 int offset, 29 int offset,
30 unsigned int protoff,
30 int *hotdrop) 31 int *hotdrop)
31{ 32{
32 const struct ipt_owner_info *info = matchinfo; 33 const struct ipt_owner_info *info = matchinfo;
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb,
51 52
52static int 53static int
53checkentry(const char *tablename, 54checkentry(const char *tablename,
54 const struct ipt_ip *ip, 55 const void *ip,
55 void *matchinfo, 56 void *matchinfo,
56 unsigned int matchsize, 57 unsigned int matchsize,
57 unsigned int hook_mask) 58 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_physdev.c b/net/ipv4/netfilter/ipt_physdev.c
deleted file mode 100644
index 03f554857a4d..000000000000
--- a/net/ipv4/netfilter/ipt_physdev.c
+++ /dev/null
@@ -1,135 +0,0 @@
1/* Kernel module to match the bridge port in and
2 * out device for IP packets coming into contact with a bridge. */
3
4/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/netdevice.h>
13#include <linux/skbuff.h>
14#include <linux/netfilter_ipv4/ipt_physdev.h>
15#include <linux/netfilter_ipv4/ip_tables.h>
16#include <linux/netfilter_bridge.h>
17#define MATCH 1
18#define NOMATCH 0
19
20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
22MODULE_DESCRIPTION("iptables bridge physical device match module");
23
24static int
25match(const struct sk_buff *skb,
26 const struct net_device *in,
27 const struct net_device *out,
28 const void *matchinfo,
29 int offset,
30 int *hotdrop)
31{
32 int i;
33 static const char nulldevname[IFNAMSIZ];
34 const struct ipt_physdev_info *info = matchinfo;
35 unsigned int ret;
36 const char *indev, *outdev;
37 struct nf_bridge_info *nf_bridge;
38
39 /* Not a bridged IP packet or no info available yet:
40 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
41 * the destination device will be a bridge. */
42 if (!(nf_bridge = skb->nf_bridge)) {
43 /* Return MATCH if the invert flags of the used options are on */
44 if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
45 !(info->invert & IPT_PHYSDEV_OP_BRIDGED))
46 return NOMATCH;
47 if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) &&
48 !(info->invert & IPT_PHYSDEV_OP_ISIN))
49 return NOMATCH;
50 if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) &&
51 !(info->invert & IPT_PHYSDEV_OP_ISOUT))
52 return NOMATCH;
53 if ((info->bitmask & IPT_PHYSDEV_OP_IN) &&
54 !(info->invert & IPT_PHYSDEV_OP_IN))
55 return NOMATCH;
56 if ((info->bitmask & IPT_PHYSDEV_OP_OUT) &&
57 !(info->invert & IPT_PHYSDEV_OP_OUT))
58 return NOMATCH;
59 return MATCH;
60 }
61
62 /* This only makes sense in the FORWARD and POSTROUTING chains */
63 if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
64 (!!(nf_bridge->mask & BRNF_BRIDGED) ^
65 !(info->invert & IPT_PHYSDEV_OP_BRIDGED)))
66 return NOMATCH;
67
68 if ((info->bitmask & IPT_PHYSDEV_OP_ISIN &&
69 (!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) ||
70 (info->bitmask & IPT_PHYSDEV_OP_ISOUT &&
71 (!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT))))
72 return NOMATCH;
73
74 if (!(info->bitmask & IPT_PHYSDEV_OP_IN))
75 goto match_outdev;
76 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
77 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
78 ret |= (((const unsigned int *)indev)[i]
79 ^ ((const unsigned int *)info->physindev)[i])
80 & ((const unsigned int *)info->in_mask)[i];
81 }
82
83 if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN))
84 return NOMATCH;
85
86match_outdev:
87 if (!(info->bitmask & IPT_PHYSDEV_OP_OUT))
88 return MATCH;
89 outdev = nf_bridge->physoutdev ?
90 nf_bridge->physoutdev->name : nulldevname;
91 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
92 ret |= (((const unsigned int *)outdev)[i]
93 ^ ((const unsigned int *)info->physoutdev)[i])
94 & ((const unsigned int *)info->out_mask)[i];
95 }
96
97 return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT);
98}
99
100static int
101checkentry(const char *tablename,
102 const struct ipt_ip *ip,
103 void *matchinfo,
104 unsigned int matchsize,
105 unsigned int hook_mask)
106{
107 const struct ipt_physdev_info *info = matchinfo;
108
109 if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info)))
110 return 0;
111 if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) ||
112 info->bitmask & ~IPT_PHYSDEV_OP_MASK)
113 return 0;
114 return 1;
115}
116
117static struct ipt_match physdev_match = {
118 .name = "physdev",
119 .match = &match,
120 .checkentry = &checkentry,
121 .me = THIS_MODULE,
122};
123
124static int __init init(void)
125{
126 return ipt_register_match(&physdev_match);
127}
128
129static void __exit fini(void)
130{
131 ipt_unregister_match(&physdev_match);
132}
133
134module_init(init);
135module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 5ddccb18c65e..44611d6d14f5 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -104,6 +104,7 @@ match(const struct sk_buff *skb,
104 const struct net_device *out, 104 const struct net_device *out,
105 const void *matchinfo, 105 const void *matchinfo,
106 int offset, 106 int offset,
107 unsigned int protoff,
107 int *hotdrop); 108 int *hotdrop);
108 109
109/* Function to hash a given address into the hash table of table_size size */ 110/* Function to hash a given address into the hash table of table_size size */
@@ -317,7 +318,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned
317 skb->nh.iph->daddr = 0; 318 skb->nh.iph->daddr = 0;
318 /* Clear ttl since we have no way of knowing it */ 319 /* Clear ttl since we have no way of knowing it */
319 skb->nh.iph->ttl = 0; 320 skb->nh.iph->ttl = 0;
320 match(skb,NULL,NULL,info,0,NULL); 321 match(skb,NULL,NULL,info,0,0,NULL);
321 322
322 kfree(skb->nh.iph); 323 kfree(skb->nh.iph);
323out_free_skb: 324out_free_skb:
@@ -357,6 +358,7 @@ match(const struct sk_buff *skb,
357 const struct net_device *out, 358 const struct net_device *out,
358 const void *matchinfo, 359 const void *matchinfo,
359 int offset, 360 int offset,
361 unsigned int protoff,
360 int *hotdrop) 362 int *hotdrop)
361{ 363{
362 int pkt_count, hits_found, ans; 364 int pkt_count, hits_found, ans;
@@ -654,7 +656,7 @@ match(const struct sk_buff *skb,
654 */ 656 */
655static int 657static int
656checkentry(const char *tablename, 658checkentry(const char *tablename,
657 const struct ipt_ip *ip, 659 const void *ip,
658 void *matchinfo, 660 void *matchinfo,
659 unsigned int matchsize, 661 unsigned int matchsize,
660 unsigned int hook_mask) 662 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index 086a1bb61e3e..9ab765e126f2 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -23,6 +23,7 @@ match(const struct sk_buff *skb,
23 const struct net_device *out, 23 const struct net_device *out,
24 const void *matchinfo, 24 const void *matchinfo,
25 int offset, 25 int offset,
26 unsigned int protoff,
26 int *hotdrop) 27 int *hotdrop)
27{ 28{
28 const struct ipt_tos_info *info = matchinfo; 29 const struct ipt_tos_info *info = matchinfo;
@@ -32,7 +33,7 @@ match(const struct sk_buff *skb,
32 33
33static int 34static int
34checkentry(const char *tablename, 35checkentry(const char *tablename,
35 const struct ipt_ip *ip, 36 const void *ip,
36 void *matchinfo, 37 void *matchinfo,
37 unsigned int matchsize, 38 unsigned int matchsize,
38 unsigned int hook_mask) 39 unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index 219aa9de88cc..82da53f430ab 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL");
21 21
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static int match(const struct sk_buff *skb, const struct net_device *in,
23 const struct net_device *out, const void *matchinfo, 23 const struct net_device *out, const void *matchinfo,
24 int offset, int *hotdrop) 24 int offset, unsigned int protoff, int *hotdrop)
25{ 25{
26 const struct ipt_ttl_info *info = matchinfo; 26 const struct ipt_ttl_info *info = matchinfo;
27 27
@@ -47,7 +47,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
47 return 0; 47 return 0;
48} 48}
49 49
50static int checkentry(const char *tablename, const struct ipt_ip *ip, 50static int checkentry(const char *tablename, const void *ip,
51 void *matchinfo, unsigned int matchsize, 51 void *matchinfo, unsigned int matchsize,
52 unsigned int hook_mask) 52 unsigned int hook_mask)
53{ 53{
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 260a4f0a2a90..212a3079085b 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -78,7 +78,8 @@ static struct ipt_table packet_filter = {
78 .name = "filter", 78 .name = "filter",
79 .valid_hooks = FILTER_VALID_HOOKS, 79 .valid_hooks = FILTER_VALID_HOOKS,
80 .lock = RW_LOCK_UNLOCKED, 80 .lock = RW_LOCK_UNLOCKED,
81 .me = THIS_MODULE 81 .me = THIS_MODULE,
82 .af = AF_INET,
82}; 83};
83 84
84/* The work comes in here from netfilter.c. */ 85/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 160eb11b6e2f..3212a5cc4b6b 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -109,6 +109,7 @@ static struct ipt_table packet_mangler = {
109 .valid_hooks = MANGLE_VALID_HOOKS, 109 .valid_hooks = MANGLE_VALID_HOOKS,
110 .lock = RW_LOCK_UNLOCKED, 110 .lock = RW_LOCK_UNLOCKED,
111 .me = THIS_MODULE, 111 .me = THIS_MODULE,
112 .af = AF_INET,
112}; 113};
113 114
114/* The work comes in here from netfilter.c. */ 115/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 47449ba83eb9..fdb9e9c81e81 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -83,7 +83,8 @@ static struct ipt_table packet_raw = {
83 .name = "raw", 83 .name = "raw",
84 .valid_hooks = RAW_VALID_HOOKS, 84 .valid_hooks = RAW_VALID_HOOKS,
85 .lock = RW_LOCK_UNLOCKED, 85 .lock = RW_LOCK_UNLOCKED,
86 .me = THIS_MODULE 86 .me = THIS_MODULE,
87 .af = AF_INET,
87}; 88};
88 89
89/* The work comes in here from netfilter.c. */ 90/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 0c56c52a3831..167619f638c6 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -575,7 +575,7 @@ MODULE_LICENSE("GPL");
575 575
576static int __init init(void) 576static int __init init(void)
577{ 577{
578 need_nf_conntrack(); 578 need_conntrack();
579 return init_or_cleanup(1); 579 return init_or_cleanup(1);
580} 580}
581 581
@@ -587,9 +587,4 @@ static void __exit fini(void)
587module_init(init); 587module_init(init);
588module_exit(fini); 588module_exit(fini);
589 589
590void need_ip_conntrack(void)
591{
592}
593
594EXPORT_SYMBOL(need_ip_conntrack);
595EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); 590EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 105dd69ee9fb..2d6f8ecbc27b 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -41,6 +41,7 @@ config IP6_NF_QUEUE
41 41
42config IP6_NF_IPTABLES 42config IP6_NF_IPTABLES
43 tristate "IP6 tables support (required for filtering/masq/NAT)" 43 tristate "IP6 tables support (required for filtering/masq/NAT)"
44 depends on NETFILTER_XTABLES
44 help 45 help
45 ip6tables is a general, extensible packet identification framework. 46 ip6tables is a general, extensible packet identification framework.
46 Currently only the packet filtering and packet mangling subsystem 47 Currently only the packet filtering and packet mangling subsystem
@@ -50,25 +51,6 @@ config IP6_NF_IPTABLES
50 To compile it as a module, choose M here. If unsure, say N. 51 To compile it as a module, choose M here. If unsure, say N.
51 52
52# The simple matches. 53# The simple matches.
53config IP6_NF_MATCH_LIMIT
54 tristate "limit match support"
55 depends on IP6_NF_IPTABLES
56 help
57 limit matching allows you to control the rate at which a rule can be
58 matched: mainly useful in combination with the LOG target ("LOG
59 target support", below) and to avoid some Denial of Service attacks.
60
61 To compile it as a module, choose M here. If unsure, say N.
62
63config IP6_NF_MATCH_MAC
64 tristate "MAC address match support"
65 depends on IP6_NF_IPTABLES
66 help
67 mac matching allows you to match packets based on the source
68 Ethernet address of the packet.
69
70 To compile it as a module, choose M here. If unsure, say N.
71
72config IP6_NF_MATCH_RT 54config IP6_NF_MATCH_RT
73 tristate "Routing header match support" 55 tristate "Routing header match support"
74 depends on IP6_NF_IPTABLES 56 depends on IP6_NF_IPTABLES
@@ -124,16 +106,6 @@ config IP6_NF_MATCH_OWNER
124 106
125 To compile it as a module, choose M here. If unsure, say N. 107 To compile it as a module, choose M here. If unsure, say N.
126 108
127config IP6_NF_MATCH_MARK
128 tristate "netfilter MARK match support"
129 depends on IP6_NF_IPTABLES
130 help
131 Netfilter mark matching allows you to match packets based on the
132 `nfmark' value in the packet. This can be set by the MARK target
133 (see below).
134
135 To compile it as a module, choose M here. If unsure, say N.
136
137config IP6_NF_MATCH_IPV6HEADER 109config IP6_NF_MATCH_IPV6HEADER
138 tristate "IPv6 Extension Headers Match" 110 tristate "IPv6 Extension Headers Match"
139 depends on IP6_NF_IPTABLES 111 depends on IP6_NF_IPTABLES
@@ -151,15 +123,6 @@ config IP6_NF_MATCH_AHESP
151 123
152 To compile it as a module, choose M here. If unsure, say N. 124 To compile it as a module, choose M here. If unsure, say N.
153 125
154config IP6_NF_MATCH_LENGTH
155 tristate "Packet Length match support"
156 depends on IP6_NF_IPTABLES
157 help
158 This option allows you to match the length of a packet against a
159 specific value or range of values.
160
161 To compile it as a module, choose M here. If unsure, say N.
162
163config IP6_NF_MATCH_EUI64 126config IP6_NF_MATCH_EUI64
164 tristate "EUI64 address check" 127 tristate "EUI64 address check"
165 depends on IP6_NF_IPTABLES 128 depends on IP6_NF_IPTABLES
@@ -170,15 +133,6 @@ config IP6_NF_MATCH_EUI64
170 133
171 To compile it as a module, choose M here. If unsure, say N. 134 To compile it as a module, choose M here. If unsure, say N.
172 135
173config IP6_NF_MATCH_PHYSDEV
174 tristate "Physdev match support"
175 depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER
176 help
177 Physdev packet matching matches against the physical bridge ports
178 the IP packet arrived on or will leave by.
179
180 To compile it as a module, choose M here. If unsure, say N.
181
182config IP6_NF_MATCH_POLICY 136config IP6_NF_MATCH_POLICY
183 tristate "IPsec policy match support" 137 tristate "IPsec policy match support"
184 depends on IP6_NF_IPTABLES && XFRM 138 depends on IP6_NF_IPTABLES && XFRM
@@ -219,17 +173,6 @@ config IP6_NF_TARGET_REJECT
219 173
220 To compile it as a module, choose M here. If unsure, say N. 174 To compile it as a module, choose M here. If unsure, say N.
221 175
222config IP6_NF_TARGET_NFQUEUE
223 tristate "NFQUEUE Target Support"
224 depends on IP6_NF_IPTABLES
225 help
226 This Target replaced the old obsolete QUEUE target.
227
228 As opposed to QUEUE, it supports 65535 different queues,
229 not just one.
230
231 To compile it as a module, choose M here. If unsure, say N.
232
233config IP6_NF_MANGLE 176config IP6_NF_MANGLE
234 tristate "Packet mangling" 177 tristate "Packet mangling"
235 depends on IP6_NF_IPTABLES 178 depends on IP6_NF_IPTABLES
@@ -240,19 +183,6 @@ config IP6_NF_MANGLE
240 183
241 To compile it as a module, choose M here. If unsure, say N. 184 To compile it as a module, choose M here. If unsure, say N.
242 185
243config IP6_NF_TARGET_MARK
244 tristate "MARK target support"
245 depends on IP6_NF_MANGLE
246 help
247 This option adds a `MARK' target, which allows you to create rules
248 in the `mangle' table which alter the netfilter mark (nfmark) field
249 associated with the packet packet prior to routing. This can change
250 the routing method (see `Use netfilter MARK value as routing
251 key') and can also be used by other subsystems to change their
252 behavior.
253
254 To compile it as a module, choose M here. If unsure, say N.
255
256config IP6_NF_TARGET_HL 186config IP6_NF_TARGET_HL
257 tristate 'HL (hoplimit) target support' 187 tristate 'HL (hoplimit) target support'
258 depends on IP6_NF_MANGLE 188 depends on IP6_NF_MANGLE
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index c0c809b426e8..663b4749820d 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -4,10 +4,7 @@
4 4
5# Link order matters here. 5# Link order matters here.
6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
7obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
8obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
9obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o 7obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
10obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
11obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 8obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
12obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o 9obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
13obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 10obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
@@ -17,12 +14,9 @@ obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
17obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o 14obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
18obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o 15obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
19obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o 16obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
20obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
21obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 17obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
22obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 18obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
23obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
24obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o 19obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
25obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o
26obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 20obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
27obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o 21obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
28obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 22obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 1390370186d9..847068fd3367 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -13,6 +13,9 @@
13 * a table 13 * a table
14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> 14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu>
15 * - new extension header parser code 15 * - new extension header parser code
16 * 15 Oct 2005 Harald Welte <laforge@netfilter.org>
17 * - Unification of {ip,ip6}_tables into x_tables
18 * - Removed tcp and udp code, since it's not ipv6 specific
16 */ 19 */
17 20
18#include <linux/capability.h> 21#include <linux/capability.h>
@@ -23,8 +26,6 @@
23#include <linux/vmalloc.h> 26#include <linux/vmalloc.h>
24#include <linux/netdevice.h> 27#include <linux/netdevice.h>
25#include <linux/module.h> 28#include <linux/module.h>
26#include <linux/tcp.h>
27#include <linux/udp.h>
28#include <linux/icmpv6.h> 29#include <linux/icmpv6.h>
29#include <net/ipv6.h> 30#include <net/ipv6.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
@@ -33,6 +34,7 @@
33#include <linux/cpumask.h> 34#include <linux/cpumask.h>
34 35
35#include <linux/netfilter_ipv6/ip6_tables.h> 36#include <linux/netfilter_ipv6/ip6_tables.h>
37#include <linux/netfilter/x_tables.h>
36 38
37MODULE_LICENSE("GPL"); 39MODULE_LICENSE("GPL");
38MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 40MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -67,13 +69,8 @@ do { \
67#else 69#else
68#define IP_NF_ASSERT(x) 70#define IP_NF_ASSERT(x)
69#endif 71#endif
70#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
71 72
72static DECLARE_MUTEX(ip6t_mutex);
73 73
74/* Must have mutex */
75#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
76#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
77#include <linux/netfilter_ipv4/listhelp.h> 74#include <linux/netfilter_ipv4/listhelp.h>
78 75
79#if 0 76#if 0
@@ -91,30 +88,6 @@ static DECLARE_MUTEX(ip6t_mutex);
91 88
92 Hence the start of any table is given by get_table() below. */ 89 Hence the start of any table is given by get_table() below. */
93 90
94/* The table itself */
95struct ip6t_table_info
96{
97 /* Size per table */
98 unsigned int size;
99 /* Number of entries: FIXME. --RR */
100 unsigned int number;
101 /* Initial number of entries. Needed for module usage count */
102 unsigned int initial_entries;
103
104 /* Entry points and underflows */
105 unsigned int hook_entry[NF_IP6_NUMHOOKS];
106 unsigned int underflow[NF_IP6_NUMHOOKS];
107
108 /* ip6t_entry tables: one per CPU */
109 void *entries[NR_CPUS];
110};
111
112static LIST_HEAD(ip6t_target);
113static LIST_HEAD(ip6t_match);
114static LIST_HEAD(ip6t_tables);
115#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
116#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
117
118#if 0 91#if 0
119#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) 92#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
120#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) 93#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
@@ -297,7 +270,7 @@ ip6t_do_table(struct sk_buff **pskb,
297 unsigned int hook, 270 unsigned int hook,
298 const struct net_device *in, 271 const struct net_device *in,
299 const struct net_device *out, 272 const struct net_device *out,
300 struct ip6t_table *table, 273 struct xt_table *table,
301 void *userdata) 274 void *userdata)
302{ 275{
303 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 276 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
@@ -309,6 +282,7 @@ ip6t_do_table(struct sk_buff **pskb,
309 const char *indev, *outdev; 282 const char *indev, *outdev;
310 void *table_base; 283 void *table_base;
311 struct ip6t_entry *e, *back; 284 struct ip6t_entry *e, *back;
285 struct xt_table_info *private;
312 286
313 /* Initialization */ 287 /* Initialization */
314 indev = in ? in->name : nulldevname; 288 indev = in ? in->name : nulldevname;
@@ -321,9 +295,10 @@ ip6t_do_table(struct sk_buff **pskb,
321 * match it. */ 295 * match it. */
322 296
323 read_lock_bh(&table->lock); 297 read_lock_bh(&table->lock);
298 private = table->private;
324 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 299 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
325 table_base = (void *)table->private->entries[smp_processor_id()]; 300 table_base = (void *)private->entries[smp_processor_id()];
326 e = get_entry(table_base, table->private->hook_entry[hook]); 301 e = get_entry(table_base, private->hook_entry[hook]);
327 302
328#ifdef CONFIG_NETFILTER_DEBUG 303#ifdef CONFIG_NETFILTER_DEBUG
329 /* Check noone else using our table */ 304 /* Check noone else using our table */
@@ -339,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb,
339#endif 314#endif
340 315
341 /* For return from builtin chain */ 316 /* For return from builtin chain */
342 back = get_entry(table_base, table->private->underflow[hook]); 317 back = get_entry(table_base, private->underflow[hook]);
343 318
344 do { 319 do {
345 IP_NF_ASSERT(e); 320 IP_NF_ASSERT(e);
@@ -439,145 +414,6 @@ ip6t_do_table(struct sk_buff **pskb,
439#endif 414#endif
440} 415}
441 416
442/*
443 * These are weird, but module loading must not be done with mutex
444 * held (since they will register), and we have to have a single
445 * function to use try_then_request_module().
446 */
447
448/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
449static inline struct ip6t_table *find_table_lock(const char *name)
450{
451 struct ip6t_table *t;
452
453 if (down_interruptible(&ip6t_mutex) != 0)
454 return ERR_PTR(-EINTR);
455
456 list_for_each_entry(t, &ip6t_tables, list)
457 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
458 return t;
459 up(&ip6t_mutex);
460 return NULL;
461}
462
463/* Find match, grabs ref. Returns ERR_PTR() on error. */
464static inline struct ip6t_match *find_match(const char *name, u8 revision)
465{
466 struct ip6t_match *m;
467 int err = 0;
468
469 if (down_interruptible(&ip6t_mutex) != 0)
470 return ERR_PTR(-EINTR);
471
472 list_for_each_entry(m, &ip6t_match, list) {
473 if (strcmp(m->name, name) == 0) {
474 if (m->revision == revision) {
475 if (try_module_get(m->me)) {
476 up(&ip6t_mutex);
477 return m;
478 }
479 } else
480 err = -EPROTOTYPE; /* Found something. */
481 }
482 }
483 up(&ip6t_mutex);
484 return ERR_PTR(err);
485}
486
487/* Find target, grabs ref. Returns ERR_PTR() on error. */
488static inline struct ip6t_target *find_target(const char *name, u8 revision)
489{
490 struct ip6t_target *t;
491 int err = 0;
492
493 if (down_interruptible(&ip6t_mutex) != 0)
494 return ERR_PTR(-EINTR);
495
496 list_for_each_entry(t, &ip6t_target, list) {
497 if (strcmp(t->name, name) == 0) {
498 if (t->revision == revision) {
499 if (try_module_get(t->me)) {
500 up(&ip6t_mutex);
501 return t;
502 }
503 } else
504 err = -EPROTOTYPE; /* Found something. */
505 }
506 }
507 up(&ip6t_mutex);
508 return ERR_PTR(err);
509}
510
511struct ip6t_target *ip6t_find_target(const char *name, u8 revision)
512{
513 struct ip6t_target *target;
514
515 target = try_then_request_module(find_target(name, revision),
516 "ip6t_%s", name);
517 if (IS_ERR(target) || !target)
518 return NULL;
519 return target;
520}
521
522static int match_revfn(const char *name, u8 revision, int *bestp)
523{
524 struct ip6t_match *m;
525 int have_rev = 0;
526
527 list_for_each_entry(m, &ip6t_match, list) {
528 if (strcmp(m->name, name) == 0) {
529 if (m->revision > *bestp)
530 *bestp = m->revision;
531 if (m->revision == revision)
532 have_rev = 1;
533 }
534 }
535 return have_rev;
536}
537
538static int target_revfn(const char *name, u8 revision, int *bestp)
539{
540 struct ip6t_target *t;
541 int have_rev = 0;
542
543 list_for_each_entry(t, &ip6t_target, list) {
544 if (strcmp(t->name, name) == 0) {
545 if (t->revision > *bestp)
546 *bestp = t->revision;
547 if (t->revision == revision)
548 have_rev = 1;
549 }
550 }
551 return have_rev;
552}
553
554/* Returns true or fals (if no such extension at all) */
555static inline int find_revision(const char *name, u8 revision,
556 int (*revfn)(const char *, u8, int *),
557 int *err)
558{
559 int have_rev, best = -1;
560
561 if (down_interruptible(&ip6t_mutex) != 0) {
562 *err = -EINTR;
563 return 1;
564 }
565 have_rev = revfn(name, revision, &best);
566 up(&ip6t_mutex);
567
568 /* Nothing at all? Return 0 to try loading module. */
569 if (best == -1) {
570 *err = -ENOENT;
571 return 0;
572 }
573
574 *err = best;
575 if (!have_rev)
576 *err = -EPROTONOSUPPORT;
577 return 1;
578}
579
580
581/* All zeroes == unconditional rule. */ 417/* All zeroes == unconditional rule. */
582static inline int 418static inline int
583unconditional(const struct ip6t_ip6 *ipv6) 419unconditional(const struct ip6t_ip6 *ipv6)
@@ -594,7 +430,7 @@ unconditional(const struct ip6t_ip6 *ipv6)
594/* Figures out from what hook each rule can be called: returns 0 if 430/* Figures out from what hook each rule can be called: returns 0 if
595 there are loops. Puts hook bitmask in comefrom. */ 431 there are loops. Puts hook bitmask in comefrom. */
596static int 432static int
597mark_source_chains(struct ip6t_table_info *newinfo, 433mark_source_chains(struct xt_table_info *newinfo,
598 unsigned int valid_hooks, void *entry0) 434 unsigned int valid_hooks, void *entry0)
599{ 435{
600 unsigned int hook; 436 unsigned int hook;
@@ -740,11 +576,11 @@ check_match(struct ip6t_entry_match *m,
740{ 576{
741 struct ip6t_match *match; 577 struct ip6t_match *match;
742 578
743 match = try_then_request_module(find_match(m->u.user.name, 579 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
744 m->u.user.revision), 580 m->u.user.revision),
745 "ip6t_%s", m->u.user.name); 581 "ip6t_%s", m->u.user.name);
746 if (IS_ERR(match) || !match) { 582 if (IS_ERR(match) || !match) {
747 duprintf("check_match: `%s' not found\n", m->u.user.name); 583 duprintf("check_match: `%s' not found\n", m->u.user.name);
748 return match ? PTR_ERR(match) : -ENOENT; 584 return match ? PTR_ERR(match) : -ENOENT;
749 } 585 }
750 m->u.kernel.match = match; 586 m->u.kernel.match = match;
@@ -785,8 +621,9 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
785 goto cleanup_matches; 621 goto cleanup_matches;
786 622
787 t = ip6t_get_target(e); 623 t = ip6t_get_target(e);
788 target = try_then_request_module(find_target(t->u.user.name, 624 target = try_then_request_module(xt_find_target(AF_INET6,
789 t->u.user.revision), 625 t->u.user.name,
626 t->u.user.revision),
790 "ip6t_%s", t->u.user.name); 627 "ip6t_%s", t->u.user.name);
791 if (IS_ERR(target) || !target) { 628 if (IS_ERR(target) || !target) {
792 duprintf("check_entry: `%s' not found\n", t->u.user.name); 629 duprintf("check_entry: `%s' not found\n", t->u.user.name);
@@ -822,7 +659,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
822 659
823static inline int 660static inline int
824check_entry_size_and_hooks(struct ip6t_entry *e, 661check_entry_size_and_hooks(struct ip6t_entry *e,
825 struct ip6t_table_info *newinfo, 662 struct xt_table_info *newinfo,
826 unsigned char *base, 663 unsigned char *base,
827 unsigned char *limit, 664 unsigned char *limit,
828 const unsigned int *hook_entries, 665 const unsigned int *hook_entries,
@@ -856,7 +693,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
856 < 0 (not IP6T_RETURN). --RR */ 693 < 0 (not IP6T_RETURN). --RR */
857 694
858 /* Clear counters and comefrom */ 695 /* Clear counters and comefrom */
859 e->counters = ((struct ip6t_counters) { 0, 0 }); 696 e->counters = ((struct xt_counters) { 0, 0 });
860 e->comefrom = 0; 697 e->comefrom = 0;
861 698
862 (*i)++; 699 (*i)++;
@@ -886,7 +723,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
886static int 723static int
887translate_table(const char *name, 724translate_table(const char *name,
888 unsigned int valid_hooks, 725 unsigned int valid_hooks,
889 struct ip6t_table_info *newinfo, 726 struct xt_table_info *newinfo,
890 void *entry0, 727 void *entry0,
891 unsigned int size, 728 unsigned int size,
892 unsigned int number, 729 unsigned int number,
@@ -963,48 +800,10 @@ translate_table(const char *name,
963 return ret; 800 return ret;
964} 801}
965 802
966static struct ip6t_table_info *
967replace_table(struct ip6t_table *table,
968 unsigned int num_counters,
969 struct ip6t_table_info *newinfo,
970 int *error)
971{
972 struct ip6t_table_info *oldinfo;
973
974#ifdef CONFIG_NETFILTER_DEBUG
975 {
976 int cpu;
977
978 for_each_cpu(cpu) {
979 struct ip6t_entry *table_base = newinfo->entries[cpu];
980 if (table_base)
981 table_base->comefrom = 0xdead57ac;
982 }
983 }
984#endif
985
986 /* Do the substitution. */
987 write_lock_bh(&table->lock);
988 /* Check inside lock: is the old number correct? */
989 if (num_counters != table->private->number) {
990 duprintf("num_counters != table->private->number (%u/%u)\n",
991 num_counters, table->private->number);
992 write_unlock_bh(&table->lock);
993 *error = -EAGAIN;
994 return NULL;
995 }
996 oldinfo = table->private;
997 table->private = newinfo;
998 newinfo->initial_entries = oldinfo->initial_entries;
999 write_unlock_bh(&table->lock);
1000
1001 return oldinfo;
1002}
1003
1004/* Gets counters. */ 803/* Gets counters. */
1005static inline int 804static inline int
1006add_entry_to_counter(const struct ip6t_entry *e, 805add_entry_to_counter(const struct ip6t_entry *e,
1007 struct ip6t_counters total[], 806 struct xt_counters total[],
1008 unsigned int *i) 807 unsigned int *i)
1009{ 808{
1010 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 809 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -1025,8 +824,8 @@ set_entry_to_counter(const struct ip6t_entry *e,
1025} 824}
1026 825
1027static void 826static void
1028get_counters(const struct ip6t_table_info *t, 827get_counters(const struct xt_table_info *t,
1029 struct ip6t_counters counters[]) 828 struct xt_counters counters[])
1030{ 829{
1031 unsigned int cpu; 830 unsigned int cpu;
1032 unsigned int i; 831 unsigned int i;
@@ -1060,19 +859,20 @@ get_counters(const struct ip6t_table_info *t,
1060 859
1061static int 860static int
1062copy_entries_to_user(unsigned int total_size, 861copy_entries_to_user(unsigned int total_size,
1063 struct ip6t_table *table, 862 struct xt_table *table,
1064 void __user *userptr) 863 void __user *userptr)
1065{ 864{
1066 unsigned int off, num, countersize; 865 unsigned int off, num, countersize;
1067 struct ip6t_entry *e; 866 struct ip6t_entry *e;
1068 struct ip6t_counters *counters; 867 struct xt_counters *counters;
868 struct xt_table_info *private = table->private;
1069 int ret = 0; 869 int ret = 0;
1070 void *loc_cpu_entry; 870 void *loc_cpu_entry;
1071 871
1072 /* We need atomic snapshot of counters: rest doesn't change 872 /* We need atomic snapshot of counters: rest doesn't change
1073 (other than comefrom, which userspace doesn't care 873 (other than comefrom, which userspace doesn't care
1074 about). */ 874 about). */
1075 countersize = sizeof(struct ip6t_counters) * table->private->number; 875 countersize = sizeof(struct xt_counters) * private->number;
1076 counters = vmalloc(countersize); 876 counters = vmalloc(countersize);
1077 877
1078 if (counters == NULL) 878 if (counters == NULL)
@@ -1080,11 +880,11 @@ copy_entries_to_user(unsigned int total_size,
1080 880
1081 /* First, sum counters... */ 881 /* First, sum counters... */
1082 write_lock_bh(&table->lock); 882 write_lock_bh(&table->lock);
1083 get_counters(table->private, counters); 883 get_counters(private, counters);
1084 write_unlock_bh(&table->lock); 884 write_unlock_bh(&table->lock);
1085 885
1086 /* choose the copy that is on ourc node/cpu */ 886 /* choose the copy that is on ourc node/cpu */
1087 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 887 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1088 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { 888 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
1089 ret = -EFAULT; 889 ret = -EFAULT;
1090 goto free_counters; 890 goto free_counters;
@@ -1143,87 +943,42 @@ get_entries(const struct ip6t_get_entries *entries,
1143 struct ip6t_get_entries __user *uptr) 943 struct ip6t_get_entries __user *uptr)
1144{ 944{
1145 int ret; 945 int ret;
1146 struct ip6t_table *t; 946 struct xt_table *t;
1147 947
1148 t = find_table_lock(entries->name); 948 t = xt_find_table_lock(AF_INET6, entries->name);
1149 if (t && !IS_ERR(t)) { 949 if (t && !IS_ERR(t)) {
1150 duprintf("t->private->number = %u\n", 950 struct xt_table_info *private = t->private;
1151 t->private->number); 951 duprintf("t->private->number = %u\n", private->number);
1152 if (entries->size == t->private->size) 952 if (entries->size == private->size)
1153 ret = copy_entries_to_user(t->private->size, 953 ret = copy_entries_to_user(private->size,
1154 t, uptr->entrytable); 954 t, uptr->entrytable);
1155 else { 955 else {
1156 duprintf("get_entries: I've got %u not %u!\n", 956 duprintf("get_entries: I've got %u not %u!\n",
1157 t->private->size, 957 private->size, entries->size);
1158 entries->size);
1159 ret = -EINVAL; 958 ret = -EINVAL;
1160 } 959 }
1161 module_put(t->me); 960 module_put(t->me);
1162 up(&ip6t_mutex); 961 xt_table_unlock(t);
1163 } else 962 } else
1164 ret = t ? PTR_ERR(t) : -ENOENT; 963 ret = t ? PTR_ERR(t) : -ENOENT;
1165 964
1166 return ret; 965 return ret;
1167} 966}
1168 967
1169static void free_table_info(struct ip6t_table_info *info)
1170{
1171 int cpu;
1172 for_each_cpu(cpu) {
1173 if (info->size <= PAGE_SIZE)
1174 kfree(info->entries[cpu]);
1175 else
1176 vfree(info->entries[cpu]);
1177 }
1178 kfree(info);
1179}
1180
1181static struct ip6t_table_info *alloc_table_info(unsigned int size)
1182{
1183 struct ip6t_table_info *newinfo;
1184 int cpu;
1185
1186 newinfo = kzalloc(sizeof(struct ip6t_table_info), GFP_KERNEL);
1187 if (!newinfo)
1188 return NULL;
1189
1190 newinfo->size = size;
1191
1192 for_each_cpu(cpu) {
1193 if (size <= PAGE_SIZE)
1194 newinfo->entries[cpu] = kmalloc_node(size,
1195 GFP_KERNEL,
1196 cpu_to_node(cpu));
1197 else
1198 newinfo->entries[cpu] = vmalloc_node(size,
1199 cpu_to_node(cpu));
1200 if (newinfo->entries[cpu] == NULL) {
1201 free_table_info(newinfo);
1202 return NULL;
1203 }
1204 }
1205
1206 return newinfo;
1207}
1208
1209static int 968static int
1210do_replace(void __user *user, unsigned int len) 969do_replace(void __user *user, unsigned int len)
1211{ 970{
1212 int ret; 971 int ret;
1213 struct ip6t_replace tmp; 972 struct ip6t_replace tmp;
1214 struct ip6t_table *t; 973 struct xt_table *t;
1215 struct ip6t_table_info *newinfo, *oldinfo; 974 struct xt_table_info *newinfo, *oldinfo;
1216 struct ip6t_counters *counters; 975 struct xt_counters *counters;
1217 void *loc_cpu_entry, *loc_cpu_old_entry; 976 void *loc_cpu_entry, *loc_cpu_old_entry;
1218 977
1219 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 978 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1220 return -EFAULT; 979 return -EFAULT;
1221 980
1222 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 981 newinfo = xt_alloc_table_info(tmp.size);
1223 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
1224 return -ENOMEM;
1225
1226 newinfo = alloc_table_info(tmp.size);
1227 if (!newinfo) 982 if (!newinfo)
1228 return -ENOMEM; 983 return -ENOMEM;
1229 984
@@ -1235,7 +990,7 @@ do_replace(void __user *user, unsigned int len)
1235 goto free_newinfo; 990 goto free_newinfo;
1236 } 991 }
1237 992
1238 counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters)); 993 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1239 if (!counters) { 994 if (!counters) {
1240 ret = -ENOMEM; 995 ret = -ENOMEM;
1241 goto free_newinfo; 996 goto free_newinfo;
@@ -1249,7 +1004,7 @@ do_replace(void __user *user, unsigned int len)
1249 1004
1250 duprintf("ip_tables: Translated table\n"); 1005 duprintf("ip_tables: Translated table\n");
1251 1006
1252 t = try_then_request_module(find_table_lock(tmp.name), 1007 t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name),
1253 "ip6table_%s", tmp.name); 1008 "ip6table_%s", tmp.name);
1254 if (!t || IS_ERR(t)) { 1009 if (!t || IS_ERR(t)) {
1255 ret = t ? PTR_ERR(t) : -ENOENT; 1010 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1264,7 +1019,7 @@ do_replace(void __user *user, unsigned int len)
1264 goto put_module; 1019 goto put_module;
1265 } 1020 }
1266 1021
1267 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 1022 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1268 if (!oldinfo) 1023 if (!oldinfo)
1269 goto put_module; 1024 goto put_module;
1270 1025
@@ -1283,23 +1038,23 @@ do_replace(void __user *user, unsigned int len)
1283 /* Decrease module usage counts and free resource */ 1038 /* Decrease module usage counts and free resource */
1284 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1039 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1285 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); 1040 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1286 free_table_info(oldinfo); 1041 xt_free_table_info(oldinfo);
1287 if (copy_to_user(tmp.counters, counters, 1042 if (copy_to_user(tmp.counters, counters,
1288 sizeof(struct ip6t_counters) * tmp.num_counters) != 0) 1043 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1289 ret = -EFAULT; 1044 ret = -EFAULT;
1290 vfree(counters); 1045 vfree(counters);
1291 up(&ip6t_mutex); 1046 xt_table_unlock(t);
1292 return ret; 1047 return ret;
1293 1048
1294 put_module: 1049 put_module:
1295 module_put(t->me); 1050 module_put(t->me);
1296 up(&ip6t_mutex); 1051 xt_table_unlock(t);
1297 free_newinfo_counters_untrans: 1052 free_newinfo_counters_untrans:
1298 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); 1053 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1299 free_newinfo_counters: 1054 free_newinfo_counters:
1300 vfree(counters); 1055 vfree(counters);
1301 free_newinfo: 1056 free_newinfo:
1302 free_table_info(newinfo); 1057 xt_free_table_info(newinfo);
1303 return ret; 1058 return ret;
1304} 1059}
1305 1060
@@ -1307,7 +1062,7 @@ do_replace(void __user *user, unsigned int len)
1307 * and everything is OK. */ 1062 * and everything is OK. */
1308static inline int 1063static inline int
1309add_counter_to_entry(struct ip6t_entry *e, 1064add_counter_to_entry(struct ip6t_entry *e,
1310 const struct ip6t_counters addme[], 1065 const struct xt_counters addme[],
1311 unsigned int *i) 1066 unsigned int *i)
1312{ 1067{
1313#if 0 1068#if 0
@@ -1329,15 +1084,16 @@ static int
1329do_add_counters(void __user *user, unsigned int len) 1084do_add_counters(void __user *user, unsigned int len)
1330{ 1085{
1331 unsigned int i; 1086 unsigned int i;
1332 struct ip6t_counters_info tmp, *paddc; 1087 struct xt_counters_info tmp, *paddc;
1333 struct ip6t_table *t; 1088 struct xt_table_info *private;
1089 struct xt_table *t;
1334 int ret = 0; 1090 int ret = 0;
1335 void *loc_cpu_entry; 1091 void *loc_cpu_entry;
1336 1092
1337 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1093 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1338 return -EFAULT; 1094 return -EFAULT;
1339 1095
1340 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters)) 1096 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1341 return -EINVAL; 1097 return -EINVAL;
1342 1098
1343 paddc = vmalloc(len); 1099 paddc = vmalloc(len);
@@ -1349,29 +1105,30 @@ do_add_counters(void __user *user, unsigned int len)
1349 goto free; 1105 goto free;
1350 } 1106 }
1351 1107
1352 t = find_table_lock(tmp.name); 1108 t = xt_find_table_lock(AF_INET6, tmp.name);
1353 if (!t || IS_ERR(t)) { 1109 if (!t || IS_ERR(t)) {
1354 ret = t ? PTR_ERR(t) : -ENOENT; 1110 ret = t ? PTR_ERR(t) : -ENOENT;
1355 goto free; 1111 goto free;
1356 } 1112 }
1357 1113
1358 write_lock_bh(&t->lock); 1114 write_lock_bh(&t->lock);
1359 if (t->private->number != paddc->num_counters) { 1115 private = t->private;
1116 if (private->number != paddc->num_counters) {
1360 ret = -EINVAL; 1117 ret = -EINVAL;
1361 goto unlock_up_free; 1118 goto unlock_up_free;
1362 } 1119 }
1363 1120
1364 i = 0; 1121 i = 0;
1365 /* Choose the copy that is on our node */ 1122 /* Choose the copy that is on our node */
1366 loc_cpu_entry = t->private->entries[smp_processor_id()]; 1123 loc_cpu_entry = private->entries[smp_processor_id()];
1367 IP6T_ENTRY_ITERATE(loc_cpu_entry, 1124 IP6T_ENTRY_ITERATE(loc_cpu_entry,
1368 t->private->size, 1125 private->size,
1369 add_counter_to_entry, 1126 add_counter_to_entry,
1370 paddc->counters, 1127 paddc->counters,
1371 &i); 1128 &i);
1372 unlock_up_free: 1129 unlock_up_free:
1373 write_unlock_bh(&t->lock); 1130 write_unlock_bh(&t->lock);
1374 up(&ip6t_mutex); 1131 xt_table_unlock(t);
1375 module_put(t->me); 1132 module_put(t->me);
1376 free: 1133 free:
1377 vfree(paddc); 1134 vfree(paddc);
@@ -1415,7 +1172,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1415 switch (cmd) { 1172 switch (cmd) {
1416 case IP6T_SO_GET_INFO: { 1173 case IP6T_SO_GET_INFO: {
1417 char name[IP6T_TABLE_MAXNAMELEN]; 1174 char name[IP6T_TABLE_MAXNAMELEN];
1418 struct ip6t_table *t; 1175 struct xt_table *t;
1419 1176
1420 if (*len != sizeof(struct ip6t_getinfo)) { 1177 if (*len != sizeof(struct ip6t_getinfo)) {
1421 duprintf("length %u != %u\n", *len, 1178 duprintf("length %u != %u\n", *len,
@@ -1430,25 +1187,26 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1430 } 1187 }
1431 name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; 1188 name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
1432 1189
1433 t = try_then_request_module(find_table_lock(name), 1190 t = try_then_request_module(xt_find_table_lock(AF_INET6, name),
1434 "ip6table_%s", name); 1191 "ip6table_%s", name);
1435 if (t && !IS_ERR(t)) { 1192 if (t && !IS_ERR(t)) {
1436 struct ip6t_getinfo info; 1193 struct ip6t_getinfo info;
1194 struct xt_table_info *private = t->private;
1437 1195
1438 info.valid_hooks = t->valid_hooks; 1196 info.valid_hooks = t->valid_hooks;
1439 memcpy(info.hook_entry, t->private->hook_entry, 1197 memcpy(info.hook_entry, private->hook_entry,
1440 sizeof(info.hook_entry)); 1198 sizeof(info.hook_entry));
1441 memcpy(info.underflow, t->private->underflow, 1199 memcpy(info.underflow, private->underflow,
1442 sizeof(info.underflow)); 1200 sizeof(info.underflow));
1443 info.num_entries = t->private->number; 1201 info.num_entries = private->number;
1444 info.size = t->private->size; 1202 info.size = private->size;
1445 memcpy(info.name, name, sizeof(info.name)); 1203 memcpy(info.name, name, sizeof(info.name));
1446 1204
1447 if (copy_to_user(user, &info, *len) != 0) 1205 if (copy_to_user(user, &info, *len) != 0)
1448 ret = -EFAULT; 1206 ret = -EFAULT;
1449 else 1207 else
1450 ret = 0; 1208 ret = 0;
1451 up(&ip6t_mutex); 1209 xt_table_unlock(t);
1452 module_put(t->me); 1210 module_put(t->me);
1453 } else 1211 } else
1454 ret = t ? PTR_ERR(t) : -ENOENT; 1212 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1475,7 +1233,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1475 case IP6T_SO_GET_REVISION_MATCH: 1233 case IP6T_SO_GET_REVISION_MATCH:
1476 case IP6T_SO_GET_REVISION_TARGET: { 1234 case IP6T_SO_GET_REVISION_TARGET: {
1477 struct ip6t_get_revision rev; 1235 struct ip6t_get_revision rev;
1478 int (*revfn)(const char *, u8, int *); 1236 int target;
1479 1237
1480 if (*len != sizeof(rev)) { 1238 if (*len != sizeof(rev)) {
1481 ret = -EINVAL; 1239 ret = -EINVAL;
@@ -1487,12 +1245,13 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1487 } 1245 }
1488 1246
1489 if (cmd == IP6T_SO_GET_REVISION_TARGET) 1247 if (cmd == IP6T_SO_GET_REVISION_TARGET)
1490 revfn = target_revfn; 1248 target = 1;
1491 else 1249 else
1492 revfn = match_revfn; 1250 target = 0;
1493 1251
1494 try_then_request_module(find_revision(rev.name, rev.revision, 1252 try_then_request_module(xt_find_revision(AF_INET6, rev.name,
1495 revfn, &ret), 1253 rev.revision,
1254 target, &ret),
1496 "ip6t_%s", rev.name); 1255 "ip6t_%s", rev.name);
1497 break; 1256 break;
1498 } 1257 }
@@ -1505,61 +1264,16 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1505 return ret; 1264 return ret;
1506} 1265}
1507 1266
1508/* Registration hooks for targets. */ 1267int ip6t_register_table(struct xt_table *table,
1509int
1510ip6t_register_target(struct ip6t_target *target)
1511{
1512 int ret;
1513
1514 ret = down_interruptible(&ip6t_mutex);
1515 if (ret != 0)
1516 return ret;
1517 list_add(&target->list, &ip6t_target);
1518 up(&ip6t_mutex);
1519 return ret;
1520}
1521
1522void
1523ip6t_unregister_target(struct ip6t_target *target)
1524{
1525 down(&ip6t_mutex);
1526 LIST_DELETE(&ip6t_target, target);
1527 up(&ip6t_mutex);
1528}
1529
1530int
1531ip6t_register_match(struct ip6t_match *match)
1532{
1533 int ret;
1534
1535 ret = down_interruptible(&ip6t_mutex);
1536 if (ret != 0)
1537 return ret;
1538
1539 list_add(&match->list, &ip6t_match);
1540 up(&ip6t_mutex);
1541
1542 return ret;
1543}
1544
1545void
1546ip6t_unregister_match(struct ip6t_match *match)
1547{
1548 down(&ip6t_mutex);
1549 LIST_DELETE(&ip6t_match, match);
1550 up(&ip6t_mutex);
1551}
1552
1553int ip6t_register_table(struct ip6t_table *table,
1554 const struct ip6t_replace *repl) 1268 const struct ip6t_replace *repl)
1555{ 1269{
1556 int ret; 1270 int ret;
1557 struct ip6t_table_info *newinfo; 1271 struct xt_table_info *newinfo;
1558 static struct ip6t_table_info bootstrap 1272 static struct xt_table_info bootstrap
1559 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1273 = { 0, 0, 0, { 0 }, { 0 }, { } };
1560 void *loc_cpu_entry; 1274 void *loc_cpu_entry;
1561 1275
1562 newinfo = alloc_table_info(repl->size); 1276 newinfo = xt_alloc_table_info(repl->size);
1563 if (!newinfo) 1277 if (!newinfo)
1564 return -ENOMEM; 1278 return -ENOMEM;
1565 1279
@@ -1573,244 +1287,29 @@ int ip6t_register_table(struct ip6t_table *table,
1573 repl->hook_entry, 1287 repl->hook_entry,
1574 repl->underflow); 1288 repl->underflow);
1575 if (ret != 0) { 1289 if (ret != 0) {
1576 free_table_info(newinfo); 1290 xt_free_table_info(newinfo);
1577 return ret; 1291 return ret;
1578 } 1292 }
1579 1293
1580 ret = down_interruptible(&ip6t_mutex); 1294 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1581 if (ret != 0) { 1295 xt_free_table_info(newinfo);
1582 free_table_info(newinfo);
1583 return ret; 1296 return ret;
1584 } 1297 }
1585 1298
1586 /* Don't autoload: we'd eat our tail... */ 1299 return 0;
1587 if (list_named_find(&ip6t_tables, table->name)) {
1588 ret = -EEXIST;
1589 goto free_unlock;
1590 }
1591
1592 /* Simplifies replace_table code. */
1593 table->private = &bootstrap;
1594 if (!replace_table(table, 0, newinfo, &ret))
1595 goto free_unlock;
1596
1597 duprintf("table->private->number = %u\n",
1598 table->private->number);
1599
1600 /* save number of initial entries */
1601 table->private->initial_entries = table->private->number;
1602
1603 rwlock_init(&table->lock);
1604 list_prepend(&ip6t_tables, table);
1605
1606 unlock:
1607 up(&ip6t_mutex);
1608 return ret;
1609
1610 free_unlock:
1611 free_table_info(newinfo);
1612 goto unlock;
1613} 1300}
1614 1301
1615void ip6t_unregister_table(struct ip6t_table *table) 1302void ip6t_unregister_table(struct xt_table *table)
1616{ 1303{
1304 struct xt_table_info *private;
1617 void *loc_cpu_entry; 1305 void *loc_cpu_entry;
1618 1306
1619 down(&ip6t_mutex); 1307 private = xt_unregister_table(table);
1620 LIST_DELETE(&ip6t_tables, table);
1621 up(&ip6t_mutex);
1622 1308
1623 /* Decrease module usage counts and free resources */ 1309 /* Decrease module usage counts and free resources */
1624 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 1310 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1625 IP6T_ENTRY_ITERATE(loc_cpu_entry, table->private->size, 1311 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
1626 cleanup_entry, NULL); 1312 xt_free_table_info(private);
1627 free_table_info(table->private);
1628}
1629
1630/* Returns 1 if the port is matched by the range, 0 otherwise */
1631static inline int
1632port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
1633{
1634 int ret;
1635
1636 ret = (port >= min && port <= max) ^ invert;
1637 return ret;
1638}
1639
1640static int
1641tcp_find_option(u_int8_t option,
1642 const struct sk_buff *skb,
1643 unsigned int tcpoff,
1644 unsigned int optlen,
1645 int invert,
1646 int *hotdrop)
1647{
1648 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
1649 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
1650 unsigned int i;
1651
1652 duprintf("tcp_match: finding option\n");
1653 if (!optlen)
1654 return invert;
1655 /* If we don't have the whole header, drop packet. */
1656 op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen,
1657 _opt);
1658 if (op == NULL) {
1659 *hotdrop = 1;
1660 return 0;
1661 }
1662
1663 for (i = 0; i < optlen; ) {
1664 if (op[i] == option) return !invert;
1665 if (op[i] < 2) i++;
1666 else i += op[i+1]?:1;
1667 }
1668
1669 return invert;
1670}
1671
1672static int
1673tcp_match(const struct sk_buff *skb,
1674 const struct net_device *in,
1675 const struct net_device *out,
1676 const void *matchinfo,
1677 int offset,
1678 unsigned int protoff,
1679 int *hotdrop)
1680{
1681 struct tcphdr _tcph, *th;
1682 const struct ip6t_tcp *tcpinfo = matchinfo;
1683
1684 if (offset) {
1685 /* To quote Alan:
1686
1687 Don't allow a fragment of TCP 8 bytes in. Nobody normal
1688 causes this. Its a cracker trying to break in by doing a
1689 flag overwrite to pass the direction checks.
1690 */
1691 if (offset == 1) {
1692 duprintf("Dropping evil TCP offset=1 frag.\n");
1693 *hotdrop = 1;
1694 }
1695 /* Must not be a fragment. */
1696 return 0;
1697 }
1698
1699#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
1700
1701 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
1702 if (th == NULL) {
1703 /* We've been asked to examine this packet, and we
1704 can't. Hence, no choice but to drop. */
1705 duprintf("Dropping evil TCP offset=0 tinygram.\n");
1706 *hotdrop = 1;
1707 return 0;
1708 }
1709
1710 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
1711 ntohs(th->source),
1712 !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT)))
1713 return 0;
1714 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
1715 ntohs(th->dest),
1716 !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT)))
1717 return 0;
1718 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
1719 == tcpinfo->flg_cmp,
1720 IP6T_TCP_INV_FLAGS))
1721 return 0;
1722 if (tcpinfo->option) {
1723 if (th->doff * 4 < sizeof(_tcph)) {
1724 *hotdrop = 1;
1725 return 0;
1726 }
1727 if (!tcp_find_option(tcpinfo->option, skb, protoff,
1728 th->doff*4 - sizeof(*th),
1729 tcpinfo->invflags & IP6T_TCP_INV_OPTION,
1730 hotdrop))
1731 return 0;
1732 }
1733 return 1;
1734}
1735
1736/* Called when user tries to insert an entry of this type. */
1737static int
1738tcp_checkentry(const char *tablename,
1739 const struct ip6t_ip6 *ipv6,
1740 void *matchinfo,
1741 unsigned int matchsize,
1742 unsigned int hook_mask)
1743{
1744 const struct ip6t_tcp *tcpinfo = matchinfo;
1745
1746 /* Must specify proto == TCP, and no unknown invflags */
1747 return ipv6->proto == IPPROTO_TCP
1748 && !(ipv6->invflags & IP6T_INV_PROTO)
1749 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp))
1750 && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK);
1751}
1752
1753static int
1754udp_match(const struct sk_buff *skb,
1755 const struct net_device *in,
1756 const struct net_device *out,
1757 const void *matchinfo,
1758 int offset,
1759 unsigned int protoff,
1760 int *hotdrop)
1761{
1762 struct udphdr _udph, *uh;
1763 const struct ip6t_udp *udpinfo = matchinfo;
1764
1765 /* Must not be a fragment. */
1766 if (offset)
1767 return 0;
1768
1769 uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
1770 if (uh == NULL) {
1771 /* We've been asked to examine this packet, and we
1772 can't. Hence, no choice but to drop. */
1773 duprintf("Dropping evil UDP tinygram.\n");
1774 *hotdrop = 1;
1775 return 0;
1776 }
1777
1778 return port_match(udpinfo->spts[0], udpinfo->spts[1],
1779 ntohs(uh->source),
1780 !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
1781 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
1782 ntohs(uh->dest),
1783 !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
1784}
1785
1786/* Called when user tries to insert an entry of this type. */
1787static int
1788udp_checkentry(const char *tablename,
1789 const struct ip6t_ip6 *ipv6,
1790 void *matchinfo,
1791 unsigned int matchinfosize,
1792 unsigned int hook_mask)
1793{
1794 const struct ip6t_udp *udpinfo = matchinfo;
1795
1796 /* Must specify proto == UDP, and no unknown invflags */
1797 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) {
1798 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
1799 IPPROTO_UDP);
1800 return 0;
1801 }
1802 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) {
1803 duprintf("ip6t_udp: matchsize %u != %u\n",
1804 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp)));
1805 return 0;
1806 }
1807 if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) {
1808 duprintf("ip6t_udp: unknown flags %X\n",
1809 udpinfo->invflags);
1810 return 0;
1811 }
1812
1813 return 1;
1814} 1313}
1815 1314
1816/* Returns 1 if the type and code is matched by the range, 0 otherwise */ 1315/* Returns 1 if the type and code is matched by the range, 0 otherwise */
@@ -1858,11 +1357,12 @@ icmp6_match(const struct sk_buff *skb,
1858/* Called when user tries to insert an entry of this type. */ 1357/* Called when user tries to insert an entry of this type. */
1859static int 1358static int
1860icmp6_checkentry(const char *tablename, 1359icmp6_checkentry(const char *tablename,
1861 const struct ip6t_ip6 *ipv6, 1360 const void *entry,
1862 void *matchinfo, 1361 void *matchinfo,
1863 unsigned int matchsize, 1362 unsigned int matchsize,
1864 unsigned int hook_mask) 1363 unsigned int hook_mask)
1865{ 1364{
1365 const struct ip6t_ip6 *ipv6 = entry;
1866 const struct ip6t_icmp *icmpinfo = matchinfo; 1366 const struct ip6t_icmp *icmpinfo = matchinfo;
1867 1367
1868 /* Must specify proto == ICMP, and no unknown invflags */ 1368 /* Must specify proto == ICMP, and no unknown invflags */
@@ -1892,164 +1392,42 @@ static struct nf_sockopt_ops ip6t_sockopts = {
1892 .get = do_ip6t_get_ctl, 1392 .get = do_ip6t_get_ctl,
1893}; 1393};
1894 1394
1895static struct ip6t_match tcp_matchstruct = {
1896 .name = "tcp",
1897 .match = &tcp_match,
1898 .checkentry = &tcp_checkentry,
1899};
1900
1901static struct ip6t_match udp_matchstruct = {
1902 .name = "udp",
1903 .match = &udp_match,
1904 .checkentry = &udp_checkentry,
1905};
1906
1907static struct ip6t_match icmp6_matchstruct = { 1395static struct ip6t_match icmp6_matchstruct = {
1908 .name = "icmp6", 1396 .name = "icmp6",
1909 .match = &icmp6_match, 1397 .match = &icmp6_match,
1910 .checkentry = &icmp6_checkentry, 1398 .checkentry = &icmp6_checkentry,
1911}; 1399};
1912 1400
1913#ifdef CONFIG_PROC_FS
1914static inline int print_name(const char *i,
1915 off_t start_offset, char *buffer, int length,
1916 off_t *pos, unsigned int *count)
1917{
1918 if ((*count)++ >= start_offset) {
1919 unsigned int namelen;
1920
1921 namelen = sprintf(buffer + *pos, "%s\n",
1922 i + sizeof(struct list_head));
1923 if (*pos + namelen > length) {
1924 /* Stop iterating */
1925 return 1;
1926 }
1927 *pos += namelen;
1928 }
1929 return 0;
1930}
1931
1932static inline int print_target(const struct ip6t_target *t,
1933 off_t start_offset, char *buffer, int length,
1934 off_t *pos, unsigned int *count)
1935{
1936 if (t == &ip6t_standard_target || t == &ip6t_error_target)
1937 return 0;
1938 return print_name((char *)t, start_offset, buffer, length, pos, count);
1939}
1940
1941static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length)
1942{
1943 off_t pos = 0;
1944 unsigned int count = 0;
1945
1946 if (down_interruptible(&ip6t_mutex) != 0)
1947 return 0;
1948
1949 LIST_FIND(&ip6t_tables, print_name, char *,
1950 offset, buffer, length, &pos, &count);
1951
1952 up(&ip6t_mutex);
1953
1954 /* `start' hack - see fs/proc/generic.c line ~105 */
1955 *start=(char *)((unsigned long)count-offset);
1956 return pos;
1957}
1958
1959static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length)
1960{
1961 off_t pos = 0;
1962 unsigned int count = 0;
1963
1964 if (down_interruptible(&ip6t_mutex) != 0)
1965 return 0;
1966
1967 LIST_FIND(&ip6t_target, print_target, struct ip6t_target *,
1968 offset, buffer, length, &pos, &count);
1969
1970 up(&ip6t_mutex);
1971
1972 *start = (char *)((unsigned long)count - offset);
1973 return pos;
1974}
1975
1976static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length)
1977{
1978 off_t pos = 0;
1979 unsigned int count = 0;
1980
1981 if (down_interruptible(&ip6t_mutex) != 0)
1982 return 0;
1983
1984 LIST_FIND(&ip6t_match, print_name, char *,
1985 offset, buffer, length, &pos, &count);
1986
1987 up(&ip6t_mutex);
1988
1989 *start = (char *)((unsigned long)count - offset);
1990 return pos;
1991}
1992
1993static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] =
1994{ { "ip6_tables_names", ip6t_get_tables },
1995 { "ip6_tables_targets", ip6t_get_targets },
1996 { "ip6_tables_matches", ip6t_get_matches },
1997 { NULL, NULL} };
1998#endif /*CONFIG_PROC_FS*/
1999
2000static int __init init(void) 1401static int __init init(void)
2001{ 1402{
2002 int ret; 1403 int ret;
2003 1404
1405 xt_proto_init(AF_INET6);
1406
2004 /* Noone else will be downing sem now, so we won't sleep */ 1407 /* Noone else will be downing sem now, so we won't sleep */
2005 down(&ip6t_mutex); 1408 xt_register_target(AF_INET6, &ip6t_standard_target);
2006 list_append(&ip6t_target, &ip6t_standard_target); 1409 xt_register_target(AF_INET6, &ip6t_error_target);
2007 list_append(&ip6t_target, &ip6t_error_target); 1410 xt_register_match(AF_INET6, &icmp6_matchstruct);
2008 list_append(&ip6t_match, &tcp_matchstruct);
2009 list_append(&ip6t_match, &udp_matchstruct);
2010 list_append(&ip6t_match, &icmp6_matchstruct);
2011 up(&ip6t_mutex);
2012 1411
2013 /* Register setsockopt */ 1412 /* Register setsockopt */
2014 ret = nf_register_sockopt(&ip6t_sockopts); 1413 ret = nf_register_sockopt(&ip6t_sockopts);
2015 if (ret < 0) { 1414 if (ret < 0) {
2016 duprintf("Unable to register sockopts.\n"); 1415 duprintf("Unable to register sockopts.\n");
1416 xt_proto_fini(AF_INET6);
2017 return ret; 1417 return ret;
2018 } 1418 }
2019 1419
2020#ifdef CONFIG_PROC_FS 1420 printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
2021 {
2022 struct proc_dir_entry *proc;
2023 int i;
2024
2025 for (i = 0; ip6t_proc_entry[i].name; i++) {
2026 proc = proc_net_create(ip6t_proc_entry[i].name, 0,
2027 ip6t_proc_entry[i].get_info);
2028 if (!proc) {
2029 while (--i >= 0)
2030 proc_net_remove(ip6t_proc_entry[i].name);
2031 nf_unregister_sockopt(&ip6t_sockopts);
2032 return -ENOMEM;
2033 }
2034 proc->owner = THIS_MODULE;
2035 }
2036 }
2037#endif
2038
2039 printk("ip6_tables: (C) 2000-2002 Netfilter core team\n");
2040 return 0; 1421 return 0;
2041} 1422}
2042 1423
2043static void __exit fini(void) 1424static void __exit fini(void)
2044{ 1425{
2045 nf_unregister_sockopt(&ip6t_sockopts); 1426 nf_unregister_sockopt(&ip6t_sockopts);
2046#ifdef CONFIG_PROC_FS 1427 xt_unregister_match(AF_INET6, &icmp6_matchstruct);
2047 { 1428 xt_unregister_target(AF_INET6, &ip6t_error_target);
2048 int i; 1429 xt_unregister_target(AF_INET6, &ip6t_standard_target);
2049 for (i = 0; ip6t_proc_entry[i].name; i++) 1430 xt_proto_fini(AF_INET6);
2050 proc_net_remove(ip6t_proc_entry[i].name);
2051 }
2052#endif
2053} 1431}
2054 1432
2055/* 1433/*
@@ -2128,10 +1506,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2128EXPORT_SYMBOL(ip6t_register_table); 1506EXPORT_SYMBOL(ip6t_register_table);
2129EXPORT_SYMBOL(ip6t_unregister_table); 1507EXPORT_SYMBOL(ip6t_unregister_table);
2130EXPORT_SYMBOL(ip6t_do_table); 1508EXPORT_SYMBOL(ip6t_do_table);
2131EXPORT_SYMBOL(ip6t_register_match);
2132EXPORT_SYMBOL(ip6t_unregister_match);
2133EXPORT_SYMBOL(ip6t_register_target);
2134EXPORT_SYMBOL(ip6t_unregister_target);
2135EXPORT_SYMBOL(ip6t_ext_hdr); 1509EXPORT_SYMBOL(ip6t_ext_hdr);
2136EXPORT_SYMBOL(ipv6_find_hdr); 1510EXPORT_SYMBOL(ipv6_find_hdr);
2137EXPORT_SYMBOL(ip6_masked_addrcmp); 1511EXPORT_SYMBOL(ip6_masked_addrcmp);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 8f5549b72720..306200c35057 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -62,7 +62,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
62} 62}
63 63
64static int ip6t_hl_checkentry(const char *tablename, 64static int ip6t_hl_checkentry(const char *tablename,
65 const struct ip6t_entry *e, 65 const void *entry,
66 void *targinfo, 66 void *targinfo,
67 unsigned int targinfosize, 67 unsigned int targinfosize,
68 unsigned int hook_mask) 68 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index ae4653bfd654..fc19d8a4ca68 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -444,7 +444,7 @@ ip6t_log_target(struct sk_buff **pskb,
444 444
445 445
446static int ip6t_log_checkentry(const char *tablename, 446static int ip6t_log_checkentry(const char *tablename,
447 const struct ip6t_entry *e, 447 const void *entry,
448 void *targinfo, 448 void *targinfo,
449 unsigned int targinfosize, 449 unsigned int targinfosize,
450 unsigned int hook_mask) 450 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
deleted file mode 100644
index eab8fb864ee0..000000000000
--- a/net/ipv6/netfilter/ip6t_MARK.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/* This is a module which is used for setting the NFMARK field of an skb. */
2
3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/skbuff.h>
12#include <linux/ip.h>
13#include <net/checksum.h>
14
15#include <linux/netfilter_ipv6/ip6_tables.h>
16#include <linux/netfilter_ipv6/ip6t_MARK.h>
17
18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
20
21static unsigned int
22target(struct sk_buff **pskb,
23 const struct net_device *in,
24 const struct net_device *out,
25 unsigned int hooknum,
26 const void *targinfo,
27 void *userinfo)
28{
29 const struct ip6t_mark_target_info *markinfo = targinfo;
30
31 if((*pskb)->nfmark != markinfo->mark)
32 (*pskb)->nfmark = markinfo->mark;
33
34 return IP6T_CONTINUE;
35}
36
37static int
38checkentry(const char *tablename,
39 const struct ip6t_entry *e,
40 void *targinfo,
41 unsigned int targinfosize,
42 unsigned int hook_mask)
43{
44 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) {
45 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
46 targinfosize,
47 IP6T_ALIGN(sizeof(struct ip6t_mark_target_info)));
48 return 0;
49 }
50
51 if (strcmp(tablename, "mangle") != 0) {
52 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
53 return 0;
54 }
55
56 return 1;
57}
58
59static struct ip6t_target ip6t_mark_reg = {
60 .name = "MARK",
61 .target = target,
62 .checkentry = checkentry,
63 .me = THIS_MODULE
64};
65
66static int __init init(void)
67{
68 printk(KERN_DEBUG "registering ipv6 mark target\n");
69 if (ip6t_register_target(&ip6t_mark_reg))
70 return -EINVAL;
71
72 return 0;
73}
74
75static void __exit fini(void)
76{
77 ip6t_unregister_target(&ip6t_mark_reg);
78}
79
80module_init(init);
81module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c
deleted file mode 100644
index c6e3730e7409..000000000000
--- a/net/ipv6/netfilter/ip6t_NFQUEUE.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* ip6tables module for using new netfilter netlink queue
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter_ipv6/ip6_tables.h>
16#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
17
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("ip6tables NFQUEUE target");
20MODULE_LICENSE("GPL");
21
22static unsigned int
23target(struct sk_buff **pskb,
24 const struct net_device *in,
25 const struct net_device *out,
26 unsigned int hooknum,
27 const void *targinfo,
28 void *userinfo)
29{
30 const struct ipt_NFQ_info *tinfo = targinfo;
31
32 return NF_QUEUE_NR(tinfo->queuenum);
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_entry *e,
38 void *targinfo,
39 unsigned int targinfosize,
40 unsigned int hook_mask)
41{
42 if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) {
43 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
44 targinfosize,
45 IP6T_ALIGN(sizeof(struct ipt_NFQ_info)));
46 return 0;
47 }
48
49 return 1;
50}
51
52static struct ip6t_target ipt_NFQ_reg = {
53 .name = "NFQUEUE",
54 .target = target,
55 .checkentry = checkentry,
56 .me = THIS_MODULE,
57};
58
59static int __init init(void)
60{
61 return ip6t_register_target(&ipt_NFQ_reg);
62}
63
64static void __exit fini(void)
65{
66 ip6t_unregister_target(&ipt_NFQ_reg);
67}
68
69module_init(init);
70module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index b03e87adca93..c745717b4ce2 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -218,12 +218,13 @@ static unsigned int reject6_target(struct sk_buff **pskb,
218} 218}
219 219
220static int check(const char *tablename, 220static int check(const char *tablename,
221 const struct ip6t_entry *e, 221 const void *entry,
222 void *targinfo, 222 void *targinfo,
223 unsigned int targinfosize, 223 unsigned int targinfosize,
224 unsigned int hook_mask) 224 unsigned int hook_mask)
225{ 225{
226 const struct ip6t_reject_info *rejinfo = targinfo; 226 const struct ip6t_reject_info *rejinfo = targinfo;
227 const struct ip6t_entry *e = entry;
227 228
228 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { 229 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
229 DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); 230 DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index f5c1a7ff4a1f..219a30365dff 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -98,7 +98,7 @@ match(const struct sk_buff *skb,
98/* Called when user tries to insert an entry of this type. */ 98/* Called when user tries to insert an entry of this type. */
99static int 99static int
100checkentry(const char *tablename, 100checkentry(const char *tablename,
101 const struct ip6t_ip6 *ip, 101 const void *entry,
102 void *matchinfo, 102 void *matchinfo,
103 unsigned int matchinfosize, 103 unsigned int matchinfosize,
104 unsigned int hook_mask) 104 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index 48cf5f9efc95..80fe82669ce2 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb,
178/* Called when user tries to insert an entry of this type. */ 178/* Called when user tries to insert an entry of this type. */
179static int 179static int
180checkentry(const char *tablename, 180checkentry(const char *tablename,
181 const struct ip6t_ip6 *ip, 181 const void *info,
182 void *matchinfo, 182 void *matchinfo,
183 unsigned int matchinfosize, 183 unsigned int matchinfosize,
184 unsigned int hook_mask) 184 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index e1828f6d0a40..724285df8711 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -76,7 +76,7 @@ match(const struct sk_buff *skb,
76/* Called when user tries to insert an entry of this type. */ 76/* Called when user tries to insert an entry of this type. */
77static int 77static int
78checkentry(const char *tablename, 78checkentry(const char *tablename,
79 const struct ip6t_ip6 *ip, 79 const void *ip,
80 void *matchinfo, 80 void *matchinfo,
81 unsigned int matchinfosize, 81 unsigned int matchinfosize,
82 unsigned int hook_mask) 82 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 616c2cbcd54d..ddf5f571909c 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -62,7 +62,7 @@ match(const struct sk_buff *skb,
62 62
63static int 63static int
64ip6t_eui64_checkentry(const char *tablename, 64ip6t_eui64_checkentry(const char *tablename,
65 const struct ip6t_ip6 *ip, 65 const void *ip,
66 void *matchinfo, 66 void *matchinfo,
67 unsigned int matchsize, 67 unsigned int matchsize,
68 unsigned int hook_mask) 68 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index d1549b268669..a9964b946ed5 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -115,7 +115,7 @@ match(const struct sk_buff *skb,
115/* Called when user tries to insert an entry of this type. */ 115/* Called when user tries to insert an entry of this type. */
116static int 116static int
117checkentry(const char *tablename, 117checkentry(const char *tablename,
118 const struct ip6t_ip6 *ip, 118 const void *ip,
119 void *matchinfo, 119 void *matchinfo,
120 unsigned int matchinfosize, 120 unsigned int matchinfosize,
121 unsigned int hook_mask) 121 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index e3bc8e2700e7..ed8ded18bbd4 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb,
178/* Called when user tries to insert an entry of this type. */ 178/* Called when user tries to insert an entry of this type. */
179static int 179static int
180checkentry(const char *tablename, 180checkentry(const char *tablename,
181 const struct ip6t_ip6 *ip, 181 const void *entry,
182 void *matchinfo, 182 void *matchinfo,
183 unsigned int matchinfosize, 183 unsigned int matchinfosize,
184 unsigned int hook_mask) 184 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 0beaff5471dd..c5d9079f2d9d 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -48,7 +48,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
48 return 0; 48 return 0;
49} 49}
50 50
51static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, 51static int checkentry(const char *tablename, const void *entry,
52 void *matchinfo, unsigned int matchsize, 52 void *matchinfo, unsigned int matchsize,
53 unsigned int hook_mask) 53 unsigned int hook_mask)
54{ 54{
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 32e67f05845b..fda1ceaf5a29 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb,
124 124
125static int 125static int
126ipv6header_checkentry(const char *tablename, 126ipv6header_checkentry(const char *tablename,
127 const struct ip6t_ip6 *ip, 127 const void *ip,
128 void *matchinfo, 128 void *matchinfo,
129 unsigned int matchsize, 129 unsigned int matchsize,
130 unsigned int hook_mask) 130 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c
deleted file mode 100644
index e0537d3811d5..000000000000
--- a/net/ipv6/netfilter/ip6t_length.c
+++ /dev/null
@@ -1,66 +0,0 @@
1/* Length Match - IPv6 Port */
2
3/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/netfilter_ipv6/ip6t_length.h>
14#include <linux/netfilter_ipv6/ip6_tables.h>
15
16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
18MODULE_DESCRIPTION("IPv6 packet length match");
19
20static int
21match(const struct sk_buff *skb,
22 const struct net_device *in,
23 const struct net_device *out,
24 const void *matchinfo,
25 int offset,
26 unsigned int protoff,
27 int *hotdrop)
28{
29 const struct ip6t_length_info *info = matchinfo;
30 u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
31
32 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_ip6 *ip,
38 void *matchinfo,
39 unsigned int matchsize,
40 unsigned int hook_mask)
41{
42 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info)))
43 return 0;
44
45 return 1;
46}
47
48static struct ip6t_match length_match = {
49 .name = "length",
50 .match = &match,
51 .checkentry = &checkentry,
52 .me = THIS_MODULE,
53};
54
55static int __init init(void)
56{
57 return ip6t_register_match(&length_match);
58}
59
60static void __exit fini(void)
61{
62 ip6t_unregister_match(&length_match);
63}
64
65module_init(init);
66module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c
deleted file mode 100644
index fb782f610be2..000000000000
--- a/net/ipv6/netfilter/ip6t_limit.c
+++ /dev/null
@@ -1,147 +0,0 @@
1/* Kernel module to control the rate
2 *
3 * 2 September 1999: Changed from the target RATE to the match
4 * `limit', removed logging. Did I mention that
5 * Alexey is a fucking genius?
6 * Rusty Russell (rusty@rustcorp.com.au). */
7
8/* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
9 * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/module.h>
17#include <linux/skbuff.h>
18#include <linux/spinlock.h>
19#include <linux/interrupt.h>
20
21#include <linux/netfilter_ipv6/ip6_tables.h>
22#include <linux/netfilter_ipv6/ip6t_limit.h>
23
24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
26MODULE_DESCRIPTION("rate limiting within ip6tables");
27
28/* The algorithm used is the Simple Token Bucket Filter (TBF)
29 * see net/sched/sch_tbf.c in the linux source tree
30 */
31
32static DEFINE_SPINLOCK(limit_lock);
33
34/* Rusty: This is my (non-mathematically-inclined) understanding of
35 this algorithm. The `average rate' in jiffies becomes your initial
36 amount of credit `credit' and the most credit you can ever have
37 `credit_cap'. The `peak rate' becomes the cost of passing the
38 test, `cost'.
39
40 `prev' tracks the last packet hit: you gain one credit per jiffy.
41 If you get credit balance more than this, the extra credit is
42 discarded. Every time the match passes, you lose `cost' credits;
43 if you don't have that many, the test fails.
44
45 See Alexey's formal explanation in net/sched/sch_tbf.c.
46
47 To avoid underflow, we multiply by 128 (ie. you get 128 credits per
48 jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds
49 at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes
50 per second at 100HZ. */
51
52#define CREDITS_PER_JIFFY 128
53
54static int
55ip6t_limit_match(const struct sk_buff *skb,
56 const struct net_device *in,
57 const struct net_device *out,
58 const void *matchinfo,
59 int offset,
60 unsigned int protoff,
61 int *hotdrop)
62{
63 struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master;
64 unsigned long now = jiffies;
65
66 spin_lock_bh(&limit_lock);
67 r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY;
68 if (r->credit > r->credit_cap)
69 r->credit = r->credit_cap;
70
71 if (r->credit >= r->cost) {
72 /* We're not limited. */
73 r->credit -= r->cost;
74 spin_unlock_bh(&limit_lock);
75 return 1;
76 }
77
78 spin_unlock_bh(&limit_lock);
79 return 0;
80}
81
82/* Precision saver. */
83static u_int32_t
84user2credits(u_int32_t user)
85{
86 /* If multiplying would overflow... */
87 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
88 /* Divide first. */
89 return (user / IP6T_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
90
91 return (user * HZ * CREDITS_PER_JIFFY) / IP6T_LIMIT_SCALE;
92}
93
94static int
95ip6t_limit_checkentry(const char *tablename,
96 const struct ip6t_ip6 *ip,
97 void *matchinfo,
98 unsigned int matchsize,
99 unsigned int hook_mask)
100{
101 struct ip6t_rateinfo *r = matchinfo;
102
103 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rateinfo)))
104 return 0;
105
106 /* Check for overflow. */
107 if (r->burst == 0
108 || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
109 printk("Call rusty: overflow in ip6t_limit: %u/%u\n",
110 r->avg, r->burst);
111 return 0;
112 }
113
114 /* User avg in seconds * IP6T_LIMIT_SCALE: convert to jiffies *
115 128. */
116 r->prev = jiffies;
117 r->credit = user2credits(r->avg * r->burst); /* Credits full. */
118 r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
119 r->cost = user2credits(r->avg);
120
121 /* For SMP, we only want to use one set of counters. */
122 r->master = r;
123
124 return 1;
125}
126
127static struct ip6t_match ip6t_limit_reg = {
128 .name = "limit",
129 .match = ip6t_limit_match,
130 .checkentry = ip6t_limit_checkentry,
131 .me = THIS_MODULE,
132};
133
134static int __init init(void)
135{
136 if (ip6t_register_match(&ip6t_limit_reg))
137 return -EINVAL;
138 return 0;
139}
140
141static void __exit fini(void)
142{
143 ip6t_unregister_match(&ip6t_limit_reg);
144}
145
146module_init(init);
147module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
deleted file mode 100644
index c848152315bc..000000000000
--- a/net/ipv6/netfilter/ip6t_mac.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/* Kernel module to match MAC address parameters. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/if_ether.h>
14#include <linux/etherdevice.h>
15
16#include <linux/netfilter_ipv6/ip6t_mac.h>
17#include <linux/netfilter_ipv6/ip6_tables.h>
18
19MODULE_LICENSE("GPL");
20MODULE_DESCRIPTION("MAC address matching module for IPv6");
21MODULE_AUTHOR("Netfilter Core Teaam <coreteam@netfilter.org>");
22
23static int
24match(const struct sk_buff *skb,
25 const struct net_device *in,
26 const struct net_device *out,
27 const void *matchinfo,
28 int offset,
29 unsigned int protoff,
30 int *hotdrop)
31{
32 const struct ip6t_mac_info *info = matchinfo;
33
34 /* Is mac pointer valid? */
35 return (skb->mac.raw >= skb->head
36 && (skb->mac.raw + ETH_HLEN) <= skb->data
37 /* If so, compare... */
38 && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
39 ^ info->invert));
40}
41
42static int
43ip6t_mac_checkentry(const char *tablename,
44 const struct ip6t_ip6 *ip,
45 void *matchinfo,
46 unsigned int matchsize,
47 unsigned int hook_mask)
48{
49 if (hook_mask
50 & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN)
51 | (1 << NF_IP6_FORWARD))) {
52 printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or"
53 " FORWARD\n");
54 return 0;
55 }
56
57 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info)))
58 return 0;
59
60 return 1;
61}
62
63static struct ip6t_match mac_match = {
64 .name = "mac",
65 .match = &match,
66 .checkentry = &ip6t_mac_checkentry,
67 .me = THIS_MODULE,
68};
69
70static int __init init(void)
71{
72 return ip6t_register_match(&mac_match);
73}
74
75static void __exit fini(void)
76{
77 ip6t_unregister_match(&mac_match);
78}
79
80module_init(init);
81module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c
deleted file mode 100644
index affc3de364fc..000000000000
--- a/net/ipv6/netfilter/ip6t_mark.c
+++ /dev/null
@@ -1,66 +0,0 @@
1/* Kernel module to match NFMARK values. */
2
3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter_ipv6/ip6t_mark.h>
15#include <linux/netfilter_ipv6/ip6_tables.h>
16
17MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19MODULE_DESCRIPTION("ip6tables mark match");
20
21static int
22match(const struct sk_buff *skb,
23 const struct net_device *in,
24 const struct net_device *out,
25 const void *matchinfo,
26 int offset,
27 unsigned int protoff,
28 int *hotdrop)
29{
30 const struct ip6t_mark_info *info = matchinfo;
31
32 return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_ip6 *ip,
38 void *matchinfo,
39 unsigned int matchsize,
40 unsigned int hook_mask)
41{
42 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info)))
43 return 0;
44
45 return 1;
46}
47
48static struct ip6t_match mark_match = {
49 .name = "mark",
50 .match = &match,
51 .checkentry = &checkentry,
52 .me = THIS_MODULE,
53};
54
55static int __init init(void)
56{
57 return ip6t_register_match(&mark_match);
58}
59
60static void __exit fini(void)
61{
62 ip6t_unregister_match(&mark_match);
63}
64
65module_init(init);
66module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
index 6e3246153fa3..49f7829dfbc2 100644
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -84,11 +84,12 @@ match(const struct sk_buff *skb,
84/* Called when user tries to insert an entry of this type. */ 84/* Called when user tries to insert an entry of this type. */
85static int 85static int
86checkentry(const char *tablename, 86checkentry(const char *tablename,
87 const struct ip6t_ip6 *ip, 87 const void *info,
88 void *matchinfo, 88 void *matchinfo,
89 unsigned int matchsize, 89 unsigned int matchsize,
90 unsigned int hook_mask) 90 unsigned int hook_mask)
91{ 91{
92 const struct ip6t_ip6 *ip = info;
92 const struct ip6t_multiport *multiinfo = matchinfo; 93 const struct ip6t_multiport *multiinfo = matchinfo;
93 94
94 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) 95 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport)))
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 4de4cdad4b7d..5409b375b512 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -53,7 +53,7 @@ match(const struct sk_buff *skb,
53 53
54static int 54static int
55checkentry(const char *tablename, 55checkentry(const char *tablename,
56 const struct ip6t_ip6 *ip, 56 const void *ip,
57 void *matchinfo, 57 void *matchinfo,
58 unsigned int matchsize, 58 unsigned int matchsize,
59 unsigned int hook_mask) 59 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index c1e770e45543..8465b4375855 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -183,7 +183,7 @@ match(const struct sk_buff *skb,
183/* Called when user tries to insert an entry of this type. */ 183/* Called when user tries to insert an entry of this type. */
184static int 184static int
185checkentry(const char *tablename, 185checkentry(const char *tablename,
186 const struct ip6t_ip6 *ip, 186 const void *entry,
187 void *matchinfo, 187 void *matchinfo,
188 unsigned int matchinfosize, 188 unsigned int matchinfosize,
189 unsigned int hook_mask) 189 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 4c0028671c20..ce4a968e1f70 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -97,6 +97,7 @@ static struct ip6t_table packet_filter = {
97 .valid_hooks = FILTER_VALID_HOOKS, 97 .valid_hooks = FILTER_VALID_HOOKS,
98 .lock = RW_LOCK_UNLOCKED, 98 .lock = RW_LOCK_UNLOCKED,
99 .me = THIS_MODULE, 99 .me = THIS_MODULE,
100 .af = AF_INET6,
100}; 101};
101 102
102/* The work comes in here from netfilter.c. */ 103/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 85c1e6eada19..30a4627e000d 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -127,6 +127,7 @@ static struct ip6t_table packet_mangler = {
127 .valid_hooks = MANGLE_VALID_HOOKS, 127 .valid_hooks = MANGLE_VALID_HOOKS,
128 .lock = RW_LOCK_UNLOCKED, 128 .lock = RW_LOCK_UNLOCKED,
129 .me = THIS_MODULE, 129 .me = THIS_MODULE,
130 .af = AF_INET6,
130}; 131};
131 132
132/* The work comes in here from netfilter.c. */ 133/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index c2982efd14af..db28ba3855e2 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -106,11 +106,12 @@ static struct
106 } 106 }
107}; 107};
108 108
109static struct ip6t_table packet_raw = { 109static struct xt_table packet_raw = {
110 .name = "raw", 110 .name = "raw",
111 .valid_hooks = RAW_VALID_HOOKS, 111 .valid_hooks = RAW_VALID_HOOKS,
112 .lock = RW_LOCK_UNLOCKED, 112 .lock = RW_LOCK_UNLOCKED,
113 .me = THIS_MODULE 113 .me = THIS_MODULE,
114 .af = AF_INET6,
114}; 115};
115 116
116/* The work comes in here from netfilter.c. */ 117/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index e57d6fc9957a..92ad53d8f8c3 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -584,7 +584,7 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
584 584
585static int __init init(void) 585static int __init init(void)
586{ 586{
587 need_nf_conntrack(); 587 need_conntrack();
588 return init_or_cleanup(1); 588 return init_or_cleanup(1);
589} 589}
590 590
@@ -595,9 +595,3 @@ static void __exit fini(void)
595 595
596module_init(init); 596module_init(init);
597module_exit(fini); 597module_exit(fini);
598
599void need_ip6_conntrack(void)
600{
601}
602
603EXPORT_SYMBOL(need_ip6_conntrack);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index f3e5ffbd592f..84ef9a13108d 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -70,8 +70,8 @@ struct nf_ct_frag6_skb_cb
70 70
71struct nf_ct_frag6_queue 71struct nf_ct_frag6_queue
72{ 72{
73 struct nf_ct_frag6_queue *next; 73 struct hlist_node list;
74 struct list_head lru_list; /* lru list member */ 74 struct list_head lru_list; /* lru list member */
75 75
76 __u32 id; /* fragment id */ 76 __u32 id; /* fragment id */
77 struct in6_addr saddr; 77 struct in6_addr saddr;
@@ -90,14 +90,13 @@ struct nf_ct_frag6_queue
90#define FIRST_IN 2 90#define FIRST_IN 2
91#define LAST_IN 1 91#define LAST_IN 1
92 __u16 nhoffset; 92 __u16 nhoffset;
93 struct nf_ct_frag6_queue **pprev;
94}; 93};
95 94
96/* Hash table. */ 95/* Hash table. */
97 96
98#define FRAG6Q_HASHSZ 64 97#define FRAG6Q_HASHSZ 64
99 98
100static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ]; 99static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ];
101static DEFINE_RWLOCK(nf_ct_frag6_lock); 100static DEFINE_RWLOCK(nf_ct_frag6_lock);
102static u32 nf_ct_frag6_hash_rnd; 101static u32 nf_ct_frag6_hash_rnd;
103static LIST_HEAD(nf_ct_frag6_lru_list); 102static LIST_HEAD(nf_ct_frag6_lru_list);
@@ -105,9 +104,7 @@ int nf_ct_frag6_nqueues = 0;
105 104
106static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) 105static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq)
107{ 106{
108 if (fq->next) 107 hlist_del(&fq->list);
109 fq->next->pprev = fq->pprev;
110 *fq->pprev = fq->next;
111 list_del(&fq->lru_list); 108 list_del(&fq->lru_list);
112 nf_ct_frag6_nqueues--; 109 nf_ct_frag6_nqueues--;
113} 110}
@@ -158,28 +155,18 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy)
158 get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); 155 get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32));
159 for (i = 0; i < FRAG6Q_HASHSZ; i++) { 156 for (i = 0; i < FRAG6Q_HASHSZ; i++) {
160 struct nf_ct_frag6_queue *q; 157 struct nf_ct_frag6_queue *q;
158 struct hlist_node *p, *n;
161 159
162 q = nf_ct_frag6_hash[i]; 160 hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) {
163 while (q) {
164 struct nf_ct_frag6_queue *next = q->next;
165 unsigned int hval = ip6qhashfn(q->id, 161 unsigned int hval = ip6qhashfn(q->id,
166 &q->saddr, 162 &q->saddr,
167 &q->daddr); 163 &q->daddr);
168
169 if (hval != i) { 164 if (hval != i) {
170 /* Unlink. */ 165 hlist_del(&q->list);
171 if (q->next)
172 q->next->pprev = q->pprev;
173 *q->pprev = q->next;
174
175 /* Relink to new hash chain. */ 166 /* Relink to new hash chain. */
176 if ((q->next = nf_ct_frag6_hash[hval]) != NULL) 167 hlist_add_head(&q->list,
177 q->next->pprev = &q->next; 168 &nf_ct_frag6_hash[hval]);
178 nf_ct_frag6_hash[hval] = q;
179 q->pprev = &nf_ct_frag6_hash[hval];
180 } 169 }
181
182 q = next;
183 } 170 }
184 } 171 }
185 write_unlock(&nf_ct_frag6_lock); 172 write_unlock(&nf_ct_frag6_lock);
@@ -314,15 +301,17 @@ out:
314 301
315/* Creation primitives. */ 302/* Creation primitives. */
316 303
317
318static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, 304static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
319 struct nf_ct_frag6_queue *fq_in) 305 struct nf_ct_frag6_queue *fq_in)
320{ 306{
321 struct nf_ct_frag6_queue *fq; 307 struct nf_ct_frag6_queue *fq;
308#ifdef CONFIG_SMP
309 struct hlist_node *n;
310#endif
322 311
323 write_lock(&nf_ct_frag6_lock); 312 write_lock(&nf_ct_frag6_lock);
324#ifdef CONFIG_SMP 313#ifdef CONFIG_SMP
325 for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { 314 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
326 if (fq->id == fq_in->id && 315 if (fq->id == fq_in->id &&
327 !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && 316 !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) &&
328 !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { 317 !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) {
@@ -340,10 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
340 atomic_inc(&fq->refcnt); 329 atomic_inc(&fq->refcnt);
341 330
342 atomic_inc(&fq->refcnt); 331 atomic_inc(&fq->refcnt);
343 if ((fq->next = nf_ct_frag6_hash[hash]) != NULL) 332 hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]);
344 fq->next->pprev = &fq->next;
345 nf_ct_frag6_hash[hash] = fq;
346 fq->pprev = &nf_ct_frag6_hash[hash];
347 INIT_LIST_HEAD(&fq->lru_list); 333 INIT_LIST_HEAD(&fq->lru_list);
348 list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); 334 list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list);
349 nf_ct_frag6_nqueues++; 335 nf_ct_frag6_nqueues++;
@@ -384,10 +370,11 @@ static __inline__ struct nf_ct_frag6_queue *
384fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) 370fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
385{ 371{
386 struct nf_ct_frag6_queue *fq; 372 struct nf_ct_frag6_queue *fq;
373 struct hlist_node *n;
387 unsigned int hash = ip6qhashfn(id, src, dst); 374 unsigned int hash = ip6qhashfn(id, src, dst);
388 375
389 read_lock(&nf_ct_frag6_lock); 376 read_lock(&nf_ct_frag6_lock);
390 for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { 377 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
391 if (fq->id == id && 378 if (fq->id == id &&
392 !ipv6_addr_cmp(src, &fq->saddr) && 379 !ipv6_addr_cmp(src, &fq->saddr) &&
393 !ipv6_addr_cmp(dst, &fq->daddr)) { 380 !ipv6_addr_cmp(dst, &fq->daddr)) {
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 7d55f9cbd853..99c0a0fa4a97 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -103,3 +103,261 @@ config NF_CT_NETLINK
103 This option enables support for a netlink-based userspace interface 103 This option enables support for a netlink-based userspace interface
104 104
105endmenu 105endmenu
106
107config NETFILTER_XTABLES
108 tristate "Netfilter Xtables support (required for ip_tables)"
109 help
110 This is required if you intend to use any of ip_tables,
111 ip6_tables or arp_tables.
112
113# alphabetically ordered list of targets
114
115config NETFILTER_XT_TARGET_CLASSIFY
116 tristate '"CLASSIFY" target support'
117 depends on NETFILTER_XTABLES
118 help
119 This option adds a `CLASSIFY' target, which enables the user to set
120 the priority of a packet. Some qdiscs can use this value for
121 classification, among these are:
122
123 atm, cbq, dsmark, pfifo_fast, htb, prio
124
125 To compile it as a module, choose M here. If unsure, say N.
126
127config NETFILTER_XT_TARGET_CONNMARK
128 tristate '"CONNMARK" target support'
129 depends on NETFILTER_XTABLES
130 depends on IP_NF_MANGLE || IP6_NF_MANGLE
131 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
132 help
133 This option adds a `CONNMARK' target, which allows one to manipulate
134 the connection mark value. Similar to the MARK target, but
135 affects the connection mark value rather than the packet mark value.
136
137 If you want to compile it as a module, say M here and read
138 <file:Documentation/modules.txt>. The module will be called
139 ipt_CONNMARK.o. If unsure, say `N'.
140
141config NETFILTER_XT_TARGET_MARK
142 tristate '"MARK" target support'
143 depends on NETFILTER_XTABLES
144 help
145 This option adds a `MARK' target, which allows you to create rules
146 in the `mangle' table which alter the netfilter mark (nfmark) field
147 associated with the packet prior to routing. This can change
148 the routing method (see `Use netfilter MARK value as routing
149 key') and can also be used by other subsystems to change their
150 behavior.
151
152 To compile it as a module, choose M here. If unsure, say N.
153
154config NETFILTER_XT_TARGET_NFQUEUE
155 tristate '"NFQUEUE" target Support'
156 depends on NETFILTER_XTABLES
157 help
158 This Target replaced the old obsolete QUEUE target.
159
160 As opposed to QUEUE, it supports 65535 different queues,
161 not just one.
162
163 To compile it as a module, choose M here. If unsure, say N.
164
165config NETFILTER_XT_TARGET_NOTRACK
166 tristate '"NOTRACK" target support'
167 depends on NETFILTER_XTABLES
168 depends on IP_NF_RAW || IP6_NF_RAW
169 depends on IP_NF_CONNTRACK || NF_CONNTRACK
170 help
171 The NOTRACK target allows a select rule to specify
172 which packets *not* to enter the conntrack/NAT
173 subsystem with all the consequences (no ICMP error tracking,
174 no protocol helpers for the selected packets).
175
176 If you want to compile it as a module, say M here and read
177 <file:Documentation/modules.txt>. If unsure, say `N'.
178
179config NETFILTER_XT_MATCH_COMMENT
180 tristate '"comment" match support'
181 depends on NETFILTER_XTABLES
182 help
183 This option adds a `comment' dummy-match, which allows you to put
184 comments in your iptables ruleset.
185
186 If you want to compile it as a module, say M here and read
187 <file:Documentation/modules.txt>. If unsure, say `N'.
188
189config NETFILTER_XT_MATCH_CONNBYTES
190 tristate '"connbytes" per-connection counter match support'
191 depends on NETFILTER_XTABLES
192 depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT
193 help
194 This option adds a `connbytes' match, which allows you to match the
195 number of bytes and/or packets for each direction within a connection.
196
197 If you want to compile it as a module, say M here and read
198 <file:Documentation/modules.txt>. If unsure, say `N'.
199
200config NETFILTER_XT_MATCH_CONNMARK
201 tristate '"connmark" connection mark match support'
202 depends on NETFILTER_XTABLES
203 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK
204 help
205 This option adds a `connmark' match, which allows you to match the
206 connection mark value previously set for the session by `CONNMARK'.
207
208 If you want to compile it as a module, say M here and read
209 <file:Documentation/modules.txt>. The module will be called
210 ipt_connmark.o. If unsure, say `N'.
211
212config NETFILTER_XT_MATCH_CONNTRACK
213 tristate '"conntrack" connection tracking match support'
214 depends on NETFILTER_XTABLES
215 depends on IP_NF_CONNTRACK || NF_CONNTRACK
216 help
217 This is a general conntrack match module, a superset of the state match.
218
219 It allows matching on additional conntrack information, which is
220 useful in complex configurations, such as NAT gateways with multiple
221 internet links or tunnels.
222
223 To compile it as a module, choose M here. If unsure, say N.
224
225config NETFILTER_XT_MATCH_DCCP
226 tristate '"DCCP" protocol match support'
227 depends on NETFILTER_XTABLES
228 help
229 With this option enabled, you will be able to use the iptables
230 `dccp' match in order to match on DCCP source/destination ports
231 and DCCP flags.
232
233 If you want to compile it as a module, say M here and read
234 <file:Documentation/modules.txt>. If unsure, say `N'.
235
236config NETFILTER_XT_MATCH_HELPER
237 tristate '"helper" match support'
238 depends on NETFILTER_XTABLES
239 depends on IP_NF_CONNTRACK || NF_CONNTRACK
240 help
241 Helper matching allows you to match packets in dynamic connections
242 tracked by a conntrack-helper, ie. ip_conntrack_ftp
243
244 To compile it as a module, choose M here. If unsure, say Y.
245
246config NETFILTER_XT_MATCH_LENGTH
247 tristate '"length" match support'
248 depends on NETFILTER_XTABLES
249 help
250 This option allows you to match the length of a packet against a
251 specific value or range of values.
252
253 To compile it as a module, choose M here. If unsure, say N.
254
255config NETFILTER_XT_MATCH_LIMIT
256 tristate '"limit" match support'
257 depends on NETFILTER_XTABLES
258 help
259 limit matching allows you to control the rate at which a rule can be
260 matched: mainly useful in combination with the LOG target ("LOG
261 target support", below) and to avoid some Denial of Service attacks.
262
263 To compile it as a module, choose M here. If unsure, say N.
264
265config NETFILTER_XT_MATCH_MAC
266 tristate '"mac" address match support'
267 depends on NETFILTER_XTABLES
268 help
269 MAC matching allows you to match packets based on the source
270 Ethernet address of the packet.
271
272 To compile it as a module, choose M here. If unsure, say N.
273
274config NETFILTER_XT_MATCH_MARK
275 tristate '"mark" match support'
276 depends on NETFILTER_XTABLES
277 help
278 Netfilter mark matching allows you to match packets based on the
279 `nfmark' value in the packet. This can be set by the MARK target
280 (see below).
281
282 To compile it as a module, choose M here. If unsure, say N.
283
284config NETFILTER_XT_MATCH_PHYSDEV
285 tristate '"physdev" match support'
286 depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
287 help
288 Physdev packet matching matches against the physical bridge ports
289 the IP packet arrived on or will leave by.
290
291 To compile it as a module, choose M here. If unsure, say N.
292
293config NETFILTER_XT_MATCH_PKTTYPE
294 tristate '"pkttype" packet type match support'
295 depends on NETFILTER_XTABLES
296 help
297 Packet type matching allows you to match a packet by
298 its "class", eg. BROADCAST, MULTICAST, ...
299
300 Typical usage:
301 iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
302
303 To compile it as a module, choose M here. If unsure, say N.
304
305config NETFILTER_XT_MATCH_REALM
306 tristate '"realm" match support'
307 depends on NETFILTER_XTABLES
308 select NET_CLS_ROUTE
309 help
310 This option adds a `realm' match, which allows you to use the realm
311 key from the routing subsystem inside iptables.
312
313 This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
314 in tc world.
315
316 If you want to compile it as a module, say M here and read
317 <file:Documentation/modules.txt>. If unsure, say `N'.
318
319config NETFILTER_XT_MATCH_SCTP
320 tristate '"sctp" protocol match support'
321 depends on NETFILTER_XTABLES
322 help
323 With this option enabled, you will be able to use the
324 `sctp' match in order to match on SCTP source/destination ports
325 and SCTP chunk types.
326
327 If you want to compile it as a module, say M here and read
328 <file:Documentation/modules.txt>. If unsure, say `N'.
329
330config NETFILTER_XT_MATCH_STATE
331 tristate '"state" match support'
332 depends on NETFILTER_XTABLES
333 depends on IP_NF_CONNTRACK || NF_CONNTRACK
334 help
335 Connection state matching allows you to match packets based on their
336 relationship to a tracked connection (ie. previous packets). This
337 is a powerful tool for packet classification.
338
339 To compile it as a module, choose M here. If unsure, say N.
340
341config NETFILTER_XT_MATCH_STRING
342 tristate '"string" match support'
343 depends on NETFILTER_XTABLES
344 select TEXTSEARCH
345 select TEXTSEARCH_KMP
346 select TEXTSEARCH_BM
347 select TEXTSEARCH_FSM
348 help
349 This option adds a `string' match, which allows you to look for
350 pattern matchings in packets.
351
352 To compile it as a module, choose M here. If unsure, say N.
353
354config NETFILTER_XT_MATCH_TCPMSS
355 tristate '"tcpmss" match support'
356 depends on NETFILTER_XTABLES
357 help
358 This option adds a `tcpmss' match, which allows you to examine the
359 MSS value of TCP SYN packets, which control the maximum packet size
360 for that connection.
361
362 To compile it as a module, choose M here. If unsure, say N.
363
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index cb2183145c37..746172ebc91b 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,4 +1,5 @@
1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
2nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
2 3
3obj-$(CONFIG_NETFILTER) = netfilter.o 4obj-$(CONFIG_NETFILTER) = netfilter.o
4 5
@@ -6,13 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
6obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o 7obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
7obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o 8obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
8 9
9nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o 10# connection tracking
10
11obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o 11obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
12obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
13 12
14# SCTP protocol connection tracking 13# SCTP protocol connection tracking
15obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o 14obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
16 15
17# netlink interface for nf_conntrack 16# netlink interface for nf_conntrack
18obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o 17obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
18
19# connection tracking helpers
20obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
21
22# generic X tables
23obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
24
25# targets
26obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
27obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
28obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
29obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
30obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
31
32# matches
33obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
34obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
35obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
36obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
37obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
38obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
39obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
40obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
41obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
42obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
43obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
44obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
45obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
46obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
47obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
48obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
49obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 3531d142f693..617599aeeead 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -821,7 +821,7 @@ module_exit(fini);
821 821
822/* Some modules need us, but don't depend directly on any symbol. 822/* Some modules need us, but don't depend directly on any symbol.
823 They should call this. */ 823 They should call this. */
824void need_nf_conntrack(void) 824void need_conntrack(void)
825{ 825{
826} 826}
827 827
@@ -841,7 +841,7 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
841EXPORT_SYMBOL(nf_ct_invert_tuplepr); 841EXPORT_SYMBOL(nf_ct_invert_tuplepr);
842EXPORT_SYMBOL(nf_conntrack_alter_reply); 842EXPORT_SYMBOL(nf_conntrack_alter_reply);
843EXPORT_SYMBOL(nf_conntrack_destroyed); 843EXPORT_SYMBOL(nf_conntrack_destroyed);
844EXPORT_SYMBOL(need_nf_conntrack); 844EXPORT_SYMBOL(need_conntrack);
845EXPORT_SYMBOL(nf_conntrack_helper_register); 845EXPORT_SYMBOL(nf_conntrack_helper_register);
846EXPORT_SYMBOL(nf_conntrack_helper_unregister); 846EXPORT_SYMBOL(nf_conntrack_helper_unregister);
847EXPORT_SYMBOL(nf_ct_iterate_cleanup); 847EXPORT_SYMBOL(nf_ct_iterate_cleanup);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
new file mode 100644
index 000000000000..d7817afc6b96
--- /dev/null
+++ b/net/netfilter/x_tables.c
@@ -0,0 +1,624 @@
1/*
2 * x_tables core - Backend for {ip,ip6,arp}_tables
3 *
4 * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
5 *
6 * Based on existing ip_tables code which is
7 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
8 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 */
15
16#include <linux/config.h>
17#include <linux/kernel.h>
18#include <linux/socket.h>
19#include <linux/net.h>
20#include <linux/proc_fs.h>
21#include <linux/seq_file.h>
22#include <linux/string.h>
23#include <linux/vmalloc.h>
24
25#include <linux/netfilter/x_tables.h>
26#include <linux/netfilter_arp.h>
27
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
30MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
31
32#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
33
34struct xt_af {
35 struct semaphore mutex;
36 struct list_head match;
37 struct list_head target;
38 struct list_head tables;
39};
40
41static struct xt_af *xt;
42
43#ifdef DEBUG_IP_FIREWALL_USER
44#define duprintf(format, args...) printk(format , ## args)
45#else
46#define duprintf(format, args...)
47#endif
48
49enum {
50 TABLE,
51 TARGET,
52 MATCH,
53};
54
55/* Registration hooks for targets. */
56int
57xt_register_target(int af, struct xt_target *target)
58{
59 int ret;
60
61 ret = down_interruptible(&xt[af].mutex);
62 if (ret != 0)
63 return ret;
64 list_add(&target->list, &xt[af].target);
65 up(&xt[af].mutex);
66 return ret;
67}
68EXPORT_SYMBOL(xt_register_target);
69
70void
71xt_unregister_target(int af, struct xt_target *target)
72{
73 down(&xt[af].mutex);
74 LIST_DELETE(&xt[af].target, target);
75 up(&xt[af].mutex);
76}
77EXPORT_SYMBOL(xt_unregister_target);
78
79int
80xt_register_match(int af, struct xt_match *match)
81{
82 int ret;
83
84 ret = down_interruptible(&xt[af].mutex);
85 if (ret != 0)
86 return ret;
87
88 list_add(&match->list, &xt[af].match);
89 up(&xt[af].mutex);
90
91 return ret;
92}
93EXPORT_SYMBOL(xt_register_match);
94
95void
96xt_unregister_match(int af, struct xt_match *match)
97{
98 down(&xt[af].mutex);
99 LIST_DELETE(&xt[af].match, match);
100 up(&xt[af].mutex);
101}
102EXPORT_SYMBOL(xt_unregister_match);
103
104
105/*
106 * These are weird, but module loading must not be done with mutex
107 * held (since they will register), and we have to have a single
108 * function to use try_then_request_module().
109 */
110
111/* Find match, grabs ref. Returns ERR_PTR() on error. */
112struct xt_match *xt_find_match(int af, const char *name, u8 revision)
113{
114 struct xt_match *m;
115 int err = 0;
116
117 if (down_interruptible(&xt[af].mutex) != 0)
118 return ERR_PTR(-EINTR);
119
120 list_for_each_entry(m, &xt[af].match, list) {
121 if (strcmp(m->name, name) == 0) {
122 if (m->revision == revision) {
123 if (try_module_get(m->me)) {
124 up(&xt[af].mutex);
125 return m;
126 }
127 } else
128 err = -EPROTOTYPE; /* Found something. */
129 }
130 }
131 up(&xt[af].mutex);
132 return ERR_PTR(err);
133}
134EXPORT_SYMBOL(xt_find_match);
135
136/* Find target, grabs ref. Returns ERR_PTR() on error. */
137struct xt_target *xt_find_target(int af, const char *name, u8 revision)
138{
139 struct xt_target *t;
140 int err = 0;
141
142 if (down_interruptible(&xt[af].mutex) != 0)
143 return ERR_PTR(-EINTR);
144
145 list_for_each_entry(t, &xt[af].target, list) {
146 if (strcmp(t->name, name) == 0) {
147 if (t->revision == revision) {
148 if (try_module_get(t->me)) {
149 up(&xt[af].mutex);
150 return t;
151 }
152 } else
153 err = -EPROTOTYPE; /* Found something. */
154 }
155 }
156 up(&xt[af].mutex);
157 return ERR_PTR(err);
158}
159EXPORT_SYMBOL(xt_find_target);
160
161static const char *xt_prefix[NPROTO] = {
162 [AF_INET] = "ipt_%s",
163 [AF_INET6] = "ip6t_%s",
164 [NF_ARP] = "arpt_%s",
165};
166
167struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
168{
169 struct xt_target *target;
170
171 target = try_then_request_module(xt_find_target(af, name, revision),
172 xt_prefix[af], name);
173 if (IS_ERR(target) || !target)
174 return NULL;
175 return target;
176}
177EXPORT_SYMBOL_GPL(xt_request_find_target);
178
179static int match_revfn(int af, const char *name, u8 revision, int *bestp)
180{
181 struct xt_match *m;
182 int have_rev = 0;
183
184 list_for_each_entry(m, &xt[af].match, list) {
185 if (strcmp(m->name, name) == 0) {
186 if (m->revision > *bestp)
187 *bestp = m->revision;
188 if (m->revision == revision)
189 have_rev = 1;
190 }
191 }
192 return have_rev;
193}
194
195static int target_revfn(int af, const char *name, u8 revision, int *bestp)
196{
197 struct xt_target *t;
198 int have_rev = 0;
199
200 list_for_each_entry(t, &xt[af].target, list) {
201 if (strcmp(t->name, name) == 0) {
202 if (t->revision > *bestp)
203 *bestp = t->revision;
204 if (t->revision == revision)
205 have_rev = 1;
206 }
207 }
208 return have_rev;
209}
210
211/* Returns true or false (if no such extension at all) */
212int xt_find_revision(int af, const char *name, u8 revision, int target,
213 int *err)
214{
215 int have_rev, best = -1;
216
217 if (down_interruptible(&xt[af].mutex) != 0) {
218 *err = -EINTR;
219 return 1;
220 }
221 if (target == 1)
222 have_rev = target_revfn(af, name, revision, &best);
223 else
224 have_rev = match_revfn(af, name, revision, &best);
225 up(&xt[af].mutex);
226
227 /* Nothing at all? Return 0 to try loading module. */
228 if (best == -1) {
229 *err = -ENOENT;
230 return 0;
231 }
232
233 *err = best;
234 if (!have_rev)
235 *err = -EPROTONOSUPPORT;
236 return 1;
237}
238EXPORT_SYMBOL_GPL(xt_find_revision);
239
240struct xt_table_info *xt_alloc_table_info(unsigned int size)
241{
242 struct xt_table_info *newinfo;
243 int cpu;
244
245 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
246 if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
247 return NULL;
248
249 newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL);
250 if (!newinfo)
251 return NULL;
252
253 newinfo->size = size;
254
255 for_each_cpu(cpu) {
256 if (size <= PAGE_SIZE)
257 newinfo->entries[cpu] = kmalloc_node(size,
258 GFP_KERNEL,
259 cpu_to_node(cpu));
260 else
261 newinfo->entries[cpu] = vmalloc_node(size,
262 cpu_to_node(cpu));
263
264 if (newinfo->entries[cpu] == NULL) {
265 xt_free_table_info(newinfo);
266 return NULL;
267 }
268 }
269
270 return newinfo;
271}
272EXPORT_SYMBOL(xt_alloc_table_info);
273
274void xt_free_table_info(struct xt_table_info *info)
275{
276 int cpu;
277
278 for_each_cpu(cpu) {
279 if (info->size <= PAGE_SIZE)
280 kfree(info->entries[cpu]);
281 else
282 vfree(info->entries[cpu]);
283 }
284 kfree(info);
285}
286EXPORT_SYMBOL(xt_free_table_info);
287
288/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
289struct xt_table *xt_find_table_lock(int af, const char *name)
290{
291 struct xt_table *t;
292
293 if (down_interruptible(&xt[af].mutex) != 0)
294 return ERR_PTR(-EINTR);
295
296 list_for_each_entry(t, &xt[af].tables, list)
297 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
298 return t;
299 up(&xt[af].mutex);
300 return NULL;
301}
302EXPORT_SYMBOL_GPL(xt_find_table_lock);
303
304void xt_table_unlock(struct xt_table *table)
305{
306 up(&xt[table->af].mutex);
307}
308EXPORT_SYMBOL_GPL(xt_table_unlock);
309
310
311struct xt_table_info *
312xt_replace_table(struct xt_table *table,
313 unsigned int num_counters,
314 struct xt_table_info *newinfo,
315 int *error)
316{
317 struct xt_table_info *oldinfo, *private;
318
319 /* Do the substitution. */
320 write_lock_bh(&table->lock);
321 private = table->private;
322 /* Check inside lock: is the old number correct? */
323 if (num_counters != private->number) {
324 duprintf("num_counters != table->private->number (%u/%u)\n",
325 num_counters, private->number);
326 write_unlock_bh(&table->lock);
327 *error = -EAGAIN;
328 return NULL;
329 }
330 oldinfo = private;
331 table->private = newinfo;
332 newinfo->initial_entries = oldinfo->initial_entries;
333 write_unlock_bh(&table->lock);
334
335 return oldinfo;
336}
337EXPORT_SYMBOL_GPL(xt_replace_table);
338
339int xt_register_table(struct xt_table *table,
340 struct xt_table_info *bootstrap,
341 struct xt_table_info *newinfo)
342{
343 int ret;
344 struct xt_table_info *private;
345
346 ret = down_interruptible(&xt[table->af].mutex);
347 if (ret != 0)
348 return ret;
349
350 /* Don't autoload: we'd eat our tail... */
351 if (list_named_find(&xt[table->af].tables, table->name)) {
352 ret = -EEXIST;
353 goto unlock;
354 }
355
356 /* Simplifies replace_table code. */
357 table->private = bootstrap;
358 if (!xt_replace_table(table, 0, newinfo, &ret))
359 goto unlock;
360
361 private = table->private;
362 duprintf("table->private->number = %u\n", private->number);
363
364 /* save number of initial entries */
365 private->initial_entries = private->number;
366
367 rwlock_init(&table->lock);
368 list_prepend(&xt[table->af].tables, table);
369
370 ret = 0;
371 unlock:
372 up(&xt[table->af].mutex);
373 return ret;
374}
375EXPORT_SYMBOL_GPL(xt_register_table);
376
377void *xt_unregister_table(struct xt_table *table)
378{
379 struct xt_table_info *private;
380
381 down(&xt[table->af].mutex);
382 private = table->private;
383 LIST_DELETE(&xt[table->af].tables, table);
384 up(&xt[table->af].mutex);
385
386 return private;
387}
388EXPORT_SYMBOL_GPL(xt_unregister_table);
389
390#ifdef CONFIG_PROC_FS
391static char *xt_proto_prefix[NPROTO] = {
392 [AF_INET] = "ip",
393 [AF_INET6] = "ip6",
394 [NF_ARP] = "arp",
395};
396
397static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos)
398{
399 struct list_head *head = list->next;
400
401 if (!head || list_empty(list))
402 return NULL;
403
404 while (pos && (head = head->next)) {
405 if (head == list)
406 return NULL;
407 pos--;
408 }
409 return pos ? NULL : head;
410}
411
412static struct list_head *type2list(u_int16_t af, u_int16_t type)
413{
414 struct list_head *list;
415
416 switch (type) {
417 case TARGET:
418 list = &xt[af].target;
419 break;
420 case MATCH:
421 list = &xt[af].match;
422 break;
423 case TABLE:
424 list = &xt[af].tables;
425 break;
426 default:
427 list = NULL;
428 break;
429 }
430
431 return list;
432}
433
434static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
435{
436 struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
437 u_int16_t af = (unsigned long)pde->data & 0xffff;
438 u_int16_t type = (unsigned long)pde->data >> 16;
439 struct list_head *list;
440
441 if (af >= NPROTO)
442 return NULL;
443
444 list = type2list(af, type);
445 if (!list)
446 return NULL;
447
448 if (down_interruptible(&xt[af].mutex) != 0)
449 return NULL;
450
451 return xt_get_idx(list, seq, *pos);
452}
453
454static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
455{
456 struct proc_dir_entry *pde = seq->private;
457 u_int16_t af = (unsigned long)pde->data & 0xffff;
458 u_int16_t type = (unsigned long)pde->data >> 16;
459 struct list_head *list;
460
461 if (af >= NPROTO)
462 return NULL;
463
464 list = type2list(af, type);
465 if (!list)
466 return NULL;
467
468 (*pos)++;
469 return xt_get_idx(list, seq, *pos);
470}
471
472static void xt_tgt_seq_stop(struct seq_file *seq, void *v)
473{
474 struct proc_dir_entry *pde = seq->private;
475 u_int16_t af = (unsigned long)pde->data & 0xffff;
476
477 up(&xt[af].mutex);
478}
479
480static int xt_name_seq_show(struct seq_file *seq, void *v)
481{
482 char *name = (char *)v + sizeof(struct list_head);
483
484 if (strlen(name))
485 return seq_printf(seq, "%s\n", name);
486 else
487 return 0;
488}
489
490static struct seq_operations xt_tgt_seq_ops = {
491 .start = xt_tgt_seq_start,
492 .next = xt_tgt_seq_next,
493 .stop = xt_tgt_seq_stop,
494 .show = xt_name_seq_show,
495};
496
497static int xt_tgt_open(struct inode *inode, struct file *file)
498{
499 int ret;
500
501 ret = seq_open(file, &xt_tgt_seq_ops);
502 if (!ret) {
503 struct seq_file *seq = file->private_data;
504 struct proc_dir_entry *pde = PDE(inode);
505
506 seq->private = pde;
507 }
508
509 return ret;
510}
511
512static struct file_operations xt_file_ops = {
513 .owner = THIS_MODULE,
514 .open = xt_tgt_open,
515 .read = seq_read,
516 .llseek = seq_lseek,
517 .release = seq_release,
518};
519
520#define FORMAT_TABLES "_tables_names"
521#define FORMAT_MATCHES "_tables_matches"
522#define FORMAT_TARGETS "_tables_targets"
523
524#endif /* CONFIG_PROC_FS */
525
526int xt_proto_init(int af)
527{
528#ifdef CONFIG_PROC_FS
529 char buf[XT_FUNCTION_MAXNAMELEN];
530 struct proc_dir_entry *proc;
531#endif
532
533 if (af >= NPROTO)
534 return -EINVAL;
535
536
537#ifdef CONFIG_PROC_FS
538 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
539 strlcat(buf, FORMAT_TABLES, sizeof(buf));
540 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
541 if (!proc)
542 goto out;
543 proc->data = (void *) ((unsigned long) af | (TABLE << 16));
544
545
546 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
547 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
548 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
549 if (!proc)
550 goto out_remove_tables;
551 proc->data = (void *) ((unsigned long) af | (MATCH << 16));
552
553 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
554 strlcat(buf, FORMAT_TARGETS, sizeof(buf));
555 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
556 if (!proc)
557 goto out_remove_matches;
558 proc->data = (void *) ((unsigned long) af | (TARGET << 16));
559#endif
560
561 return 0;
562
563#ifdef CONFIG_PROC_FS
564out_remove_matches:
565 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
566 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
567 proc_net_remove(buf);
568
569out_remove_tables:
570 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
571 strlcat(buf, FORMAT_TABLES, sizeof(buf));
572 proc_net_remove(buf);
573out:
574 return -1;
575#endif
576}
577EXPORT_SYMBOL_GPL(xt_proto_init);
578
579void xt_proto_fini(int af)
580{
581#ifdef CONFIG_PROC_FS
582 char buf[XT_FUNCTION_MAXNAMELEN];
583
584 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
585 strlcat(buf, FORMAT_TABLES, sizeof(buf));
586 proc_net_remove(buf);
587
588 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
589 strlcat(buf, FORMAT_TARGETS, sizeof(buf));
590 proc_net_remove(buf);
591
592 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
593 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
594 proc_net_remove(buf);
595#endif /*CONFIG_PROC_FS*/
596}
597EXPORT_SYMBOL_GPL(xt_proto_fini);
598
599
600static int __init xt_init(void)
601{
602 int i;
603
604 xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
605 if (!xt)
606 return -ENOMEM;
607
608 for (i = 0; i < NPROTO; i++) {
609 init_MUTEX(&xt[i].mutex);
610 INIT_LIST_HEAD(&xt[i].target);
611 INIT_LIST_HEAD(&xt[i].match);
612 INIT_LIST_HEAD(&xt[i].tables);
613 }
614 return 0;
615}
616
617static void __exit xt_fini(void)
618{
619 kfree(xt);
620}
621
622module_init(xt_init);
623module_exit(xt_fini);
624
diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index dab78d8bd494..78ee266a12ee 100644
--- a/net/ipv4/netfilter/ipt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -15,12 +15,13 @@
15#include <linux/ip.h> 15#include <linux/ip.h>
16#include <net/checksum.h> 16#include <net/checksum.h>
17 17
18#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter/x_tables.h>
19#include <linux/netfilter_ipv4/ipt_CLASSIFY.h> 19#include <linux/netfilter/xt_CLASSIFY.h>
20 20
21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
22MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
23MODULE_DESCRIPTION("iptables qdisc classification target module"); 23MODULE_DESCRIPTION("iptables qdisc classification target module");
24MODULE_ALIAS("ipt_CLASSIFY");
24 25
25static unsigned int 26static unsigned int
26target(struct sk_buff **pskb, 27target(struct sk_buff **pskb,
@@ -30,25 +31,25 @@ target(struct sk_buff **pskb,
30 const void *targinfo, 31 const void *targinfo,
31 void *userinfo) 32 void *userinfo)
32{ 33{
33 const struct ipt_classify_target_info *clinfo = targinfo; 34 const struct xt_classify_target_info *clinfo = targinfo;
34 35
35 if((*pskb)->priority != clinfo->priority) 36 if ((*pskb)->priority != clinfo->priority)
36 (*pskb)->priority = clinfo->priority; 37 (*pskb)->priority = clinfo->priority;
37 38
38 return IPT_CONTINUE; 39 return XT_CONTINUE;
39} 40}
40 41
41static int 42static int
42checkentry(const char *tablename, 43checkentry(const char *tablename,
43 const struct ipt_entry *e, 44 const void *e,
44 void *targinfo, 45 void *targinfo,
45 unsigned int targinfosize, 46 unsigned int targinfosize,
46 unsigned int hook_mask) 47 unsigned int hook_mask)
47{ 48{
48 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){ 49 if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){
49 printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n", 50 printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n",
50 targinfosize, 51 targinfosize,
51 IPT_ALIGN(sizeof(struct ipt_classify_target_info))); 52 XT_ALIGN(sizeof(struct xt_classify_target_info)));
52 return 0; 53 return 0;
53 } 54 }
54 55
@@ -69,21 +70,39 @@ checkentry(const char *tablename,
69 return 1; 70 return 1;
70} 71}
71 72
72static struct ipt_target ipt_classify_reg = { 73static struct xt_target classify_reg = {
74 .name = "CLASSIFY",
75 .target = target,
76 .checkentry = checkentry,
77 .me = THIS_MODULE,
78};
79static struct xt_target classify6_reg = {
73 .name = "CLASSIFY", 80 .name = "CLASSIFY",
74 .target = target, 81 .target = target,
75 .checkentry = checkentry, 82 .checkentry = checkentry,
76 .me = THIS_MODULE, 83 .me = THIS_MODULE,
77}; 84};
78 85
86
79static int __init init(void) 87static int __init init(void)
80{ 88{
81 return ipt_register_target(&ipt_classify_reg); 89 int ret;
90
91 ret = xt_register_target(AF_INET, &classify_reg);
92 if (ret)
93 return ret;
94
95 ret = xt_register_target(AF_INET6, &classify6_reg);
96 if (ret)
97 xt_unregister_target(AF_INET, &classify_reg);
98
99 return ret;
82} 100}
83 101
84static void __exit fini(void) 102static void __exit fini(void)
85{ 103{
86 ipt_unregister_target(&ipt_classify_reg); 104 xt_unregister_target(AF_INET, &classify_reg);
105 xt_unregister_target(AF_INET6, &classify6_reg);
87} 106}
88 107
89module_init(init); 108module_init(init);
diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 8acac5a40a92..22506e376be5 100644
--- a/net/ipv4/netfilter/ipt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -26,9 +26,10 @@
26MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 26MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
27MODULE_DESCRIPTION("IP tables CONNMARK matching module"); 27MODULE_DESCRIPTION("IP tables CONNMARK matching module");
28MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
29MODULE_ALIAS("ipt_CONNMARK");
29 30
30#include <linux/netfilter_ipv4/ip_tables.h> 31#include <linux/netfilter/x_tables.h>
31#include <linux/netfilter_ipv4/ipt_CONNMARK.h> 32#include <linux/netfilter/xt_CONNMARK.h>
32#include <net/netfilter/nf_conntrack_compat.h> 33#include <net/netfilter/nf_conntrack_compat.h>
33 34
34static unsigned int 35static unsigned int
@@ -39,7 +40,7 @@ target(struct sk_buff **pskb,
39 const void *targinfo, 40 const void *targinfo,
40 void *userinfo) 41 void *userinfo)
41{ 42{
42 const struct ipt_connmark_target_info *markinfo = targinfo; 43 const struct xt_connmark_target_info *markinfo = targinfo;
43 u_int32_t diff; 44 u_int32_t diff;
44 u_int32_t nfmark; 45 u_int32_t nfmark;
45 u_int32_t newmark; 46 u_int32_t newmark;
@@ -48,17 +49,17 @@ target(struct sk_buff **pskb,
48 49
49 if (ctmark) { 50 if (ctmark) {
50 switch(markinfo->mode) { 51 switch(markinfo->mode) {
51 case IPT_CONNMARK_SET: 52 case XT_CONNMARK_SET:
52 newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; 53 newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
53 if (newmark != *ctmark) 54 if (newmark != *ctmark)
54 *ctmark = newmark; 55 *ctmark = newmark;
55 break; 56 break;
56 case IPT_CONNMARK_SAVE: 57 case XT_CONNMARK_SAVE:
57 newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); 58 newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
58 if (*ctmark != newmark) 59 if (*ctmark != newmark)
59 *ctmark = newmark; 60 *ctmark = newmark;
60 break; 61 break;
61 case IPT_CONNMARK_RESTORE: 62 case XT_CONNMARK_RESTORE:
62 nfmark = (*pskb)->nfmark; 63 nfmark = (*pskb)->nfmark;
63 diff = (*ctmark ^ nfmark) & markinfo->mask; 64 diff = (*ctmark ^ nfmark) & markinfo->mask;
64 if (diff != 0) 65 if (diff != 0)
@@ -67,25 +68,25 @@ target(struct sk_buff **pskb,
67 } 68 }
68 } 69 }
69 70
70 return IPT_CONTINUE; 71 return XT_CONTINUE;
71} 72}
72 73
73static int 74static int
74checkentry(const char *tablename, 75checkentry(const char *tablename,
75 const struct ipt_entry *e, 76 const void *entry,
76 void *targinfo, 77 void *targinfo,
77 unsigned int targinfosize, 78 unsigned int targinfosize,
78 unsigned int hook_mask) 79 unsigned int hook_mask)
79{ 80{
80 struct ipt_connmark_target_info *matchinfo = targinfo; 81 struct xt_connmark_target_info *matchinfo = targinfo;
81 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) { 82 if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) {
82 printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", 83 printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
83 targinfosize, 84 targinfosize,
84 IPT_ALIGN(sizeof(struct ipt_connmark_target_info))); 85 XT_ALIGN(sizeof(struct xt_connmark_target_info)));
85 return 0; 86 return 0;
86 } 87 }
87 88
88 if (matchinfo->mode == IPT_CONNMARK_RESTORE) { 89 if (matchinfo->mode == XT_CONNMARK_RESTORE) {
89 if (strcmp(tablename, "mangle") != 0) { 90 if (strcmp(tablename, "mangle") != 0) {
90 printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); 91 printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
91 return 0; 92 return 0;
@@ -100,7 +101,13 @@ checkentry(const char *tablename,
100 return 1; 101 return 1;
101} 102}
102 103
103static struct ipt_target ipt_connmark_reg = { 104static struct xt_target connmark_reg = {
105 .name = "CONNMARK",
106 .target = &target,
107 .checkentry = &checkentry,
108 .me = THIS_MODULE
109};
110static struct xt_target connmark6_reg = {
104 .name = "CONNMARK", 111 .name = "CONNMARK",
105 .target = &target, 112 .target = &target,
106 .checkentry = &checkentry, 113 .checkentry = &checkentry,
@@ -109,13 +116,25 @@ static struct ipt_target ipt_connmark_reg = {
109 116
110static int __init init(void) 117static int __init init(void)
111{ 118{
112 need_ip_conntrack(); 119 int ret;
113 return ipt_register_target(&ipt_connmark_reg); 120
121 need_conntrack();
122
123 ret = xt_register_target(AF_INET, &connmark_reg);
124 if (ret)
125 return ret;
126
127 ret = xt_register_target(AF_INET6, &connmark6_reg);
128 if (ret)
129 xt_unregister_target(AF_INET, &connmark_reg);
130
131 return ret;
114} 132}
115 133
116static void __exit fini(void) 134static void __exit fini(void)
117{ 135{
118 ipt_unregister_target(&ipt_connmark_reg); 136 xt_unregister_target(AF_INET, &connmark_reg);
137 xt_unregister_target(AF_INET6, &connmark6_reg);
119} 138}
120 139
121module_init(init); 140module_init(init);
diff --git a/net/ipv4/netfilter/ipt_MARK.c b/net/netfilter/xt_MARK.c
index 52b4f2c296bf..0c11ee9550f3 100644
--- a/net/ipv4/netfilter/ipt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -12,12 +12,14 @@
12#include <linux/ip.h> 12#include <linux/ip.h>
13#include <net/checksum.h> 13#include <net/checksum.h>
14 14
15#include <linux/netfilter_ipv4/ip_tables.h> 15#include <linux/netfilter/x_tables.h>
16#include <linux/netfilter_ipv4/ipt_MARK.h> 16#include <linux/netfilter/xt_MARK.h>
17 17
18MODULE_LICENSE("GPL"); 18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 19MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
20MODULE_DESCRIPTION("iptables MARK modification module"); 20MODULE_DESCRIPTION("ip[6]tables MARK modification module");
21MODULE_ALIAS("ipt_MARK");
22MODULE_ALIAS("ip6t_MARK");
21 23
22static unsigned int 24static unsigned int
23target_v0(struct sk_buff **pskb, 25target_v0(struct sk_buff **pskb,
@@ -27,12 +29,12 @@ target_v0(struct sk_buff **pskb,
27 const void *targinfo, 29 const void *targinfo,
28 void *userinfo) 30 void *userinfo)
29{ 31{
30 const struct ipt_mark_target_info *markinfo = targinfo; 32 const struct xt_mark_target_info *markinfo = targinfo;
31 33
32 if((*pskb)->nfmark != markinfo->mark) 34 if((*pskb)->nfmark != markinfo->mark)
33 (*pskb)->nfmark = markinfo->mark; 35 (*pskb)->nfmark = markinfo->mark;
34 36
35 return IPT_CONTINUE; 37 return XT_CONTINUE;
36} 38}
37 39
38static unsigned int 40static unsigned int
@@ -43,19 +45,19 @@ target_v1(struct sk_buff **pskb,
43 const void *targinfo, 45 const void *targinfo,
44 void *userinfo) 46 void *userinfo)
45{ 47{
46 const struct ipt_mark_target_info_v1 *markinfo = targinfo; 48 const struct xt_mark_target_info_v1 *markinfo = targinfo;
47 int mark = 0; 49 int mark = 0;
48 50
49 switch (markinfo->mode) { 51 switch (markinfo->mode) {
50 case IPT_MARK_SET: 52 case XT_MARK_SET:
51 mark = markinfo->mark; 53 mark = markinfo->mark;
52 break; 54 break;
53 55
54 case IPT_MARK_AND: 56 case XT_MARK_AND:
55 mark = (*pskb)->nfmark & markinfo->mark; 57 mark = (*pskb)->nfmark & markinfo->mark;
56 break; 58 break;
57 59
58 case IPT_MARK_OR: 60 case XT_MARK_OR:
59 mark = (*pskb)->nfmark | markinfo->mark; 61 mark = (*pskb)->nfmark | markinfo->mark;
60 break; 62 break;
61 } 63 }
@@ -63,23 +65,23 @@ target_v1(struct sk_buff **pskb,
63 if((*pskb)->nfmark != mark) 65 if((*pskb)->nfmark != mark)
64 (*pskb)->nfmark = mark; 66 (*pskb)->nfmark = mark;
65 67
66 return IPT_CONTINUE; 68 return XT_CONTINUE;
67} 69}
68 70
69 71
70static int 72static int
71checkentry_v0(const char *tablename, 73checkentry_v0(const char *tablename,
72 const struct ipt_entry *e, 74 const void *entry,
73 void *targinfo, 75 void *targinfo,
74 unsigned int targinfosize, 76 unsigned int targinfosize,
75 unsigned int hook_mask) 77 unsigned int hook_mask)
76{ 78{
77 struct ipt_mark_target_info *markinfo = targinfo; 79 struct xt_mark_target_info *markinfo = targinfo;
78 80
79 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { 81 if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) {
80 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", 82 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
81 targinfosize, 83 targinfosize,
82 IPT_ALIGN(sizeof(struct ipt_mark_target_info))); 84 XT_ALIGN(sizeof(struct xt_mark_target_info)));
83 return 0; 85 return 0;
84 } 86 }
85 87
@@ -98,17 +100,17 @@ checkentry_v0(const char *tablename,
98 100
99static int 101static int
100checkentry_v1(const char *tablename, 102checkentry_v1(const char *tablename,
101 const struct ipt_entry *e, 103 const void *entry,
102 void *targinfo, 104 void *targinfo,
103 unsigned int targinfosize, 105 unsigned int targinfosize,
104 unsigned int hook_mask) 106 unsigned int hook_mask)
105{ 107{
106 struct ipt_mark_target_info_v1 *markinfo = targinfo; 108 struct xt_mark_target_info_v1 *markinfo = targinfo;
107 109
108 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){ 110 if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){
109 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", 111 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
110 targinfosize, 112 targinfosize,
111 IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))); 113 XT_ALIGN(sizeof(struct xt_mark_target_info_v1)));
112 return 0; 114 return 0;
113 } 115 }
114 116
@@ -117,9 +119,9 @@ checkentry_v1(const char *tablename,
117 return 0; 119 return 0;
118 } 120 }
119 121
120 if (markinfo->mode != IPT_MARK_SET 122 if (markinfo->mode != XT_MARK_SET
121 && markinfo->mode != IPT_MARK_AND 123 && markinfo->mode != XT_MARK_AND
122 && markinfo->mode != IPT_MARK_OR) { 124 && markinfo->mode != XT_MARK_OR) {
123 printk(KERN_WARNING "MARK: unknown mode %u\n", 125 printk(KERN_WARNING "MARK: unknown mode %u\n",
124 markinfo->mode); 126 markinfo->mode);
125 return 0; 127 return 0;
@@ -133,7 +135,7 @@ checkentry_v1(const char *tablename,
133 return 1; 135 return 1;
134} 136}
135 137
136static struct ipt_target ipt_mark_reg_v0 = { 138static struct xt_target ipt_mark_reg_v0 = {
137 .name = "MARK", 139 .name = "MARK",
138 .target = target_v0, 140 .target = target_v0,
139 .checkentry = checkentry_v0, 141 .checkentry = checkentry_v0,
@@ -141,7 +143,7 @@ static struct ipt_target ipt_mark_reg_v0 = {
141 .revision = 0, 143 .revision = 0,
142}; 144};
143 145
144static struct ipt_target ipt_mark_reg_v1 = { 146static struct xt_target ipt_mark_reg_v1 = {
145 .name = "MARK", 147 .name = "MARK",
146 .target = target_v1, 148 .target = target_v1,
147 .checkentry = checkentry_v1, 149 .checkentry = checkentry_v1,
@@ -149,23 +151,40 @@ static struct ipt_target ipt_mark_reg_v1 = {
149 .revision = 1, 151 .revision = 1,
150}; 152};
151 153
154static struct xt_target ip6t_mark_reg_v0 = {
155 .name = "MARK",
156 .target = target_v0,
157 .checkentry = checkentry_v0,
158 .me = THIS_MODULE,
159 .revision = 0,
160};
161
152static int __init init(void) 162static int __init init(void)
153{ 163{
154 int err; 164 int err;
155 165
156 err = ipt_register_target(&ipt_mark_reg_v0); 166 err = xt_register_target(AF_INET, &ipt_mark_reg_v0);
157 if (!err) { 167 if (err)
158 err = ipt_register_target(&ipt_mark_reg_v1); 168 return err;
159 if (err) 169
160 ipt_unregister_target(&ipt_mark_reg_v0); 170 err = xt_register_target(AF_INET, &ipt_mark_reg_v1);
171 if (err)
172 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
173
174 err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0);
175 if (err) {
176 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
177 xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
161 } 178 }
179
162 return err; 180 return err;
163} 181}
164 182
165static void __exit fini(void) 183static void __exit fini(void)
166{ 184{
167 ipt_unregister_target(&ipt_mark_reg_v0); 185 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
168 ipt_unregister_target(&ipt_mark_reg_v1); 186 xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
187 xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0);
169} 188}
170 189
171module_init(init); 190module_init(init);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
new file mode 100644
index 000000000000..8b76b6f8d1e4
--- /dev/null
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -0,0 +1,107 @@
1/* iptables module for using new netfilter netlink queue
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter_arp.h>
16#include <linux/netfilter/x_tables.h>
17#include <linux/netfilter/xt_NFQUEUE.h>
18
19MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
20MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target");
21MODULE_LICENSE("GPL");
22MODULE_ALIAS("ipt_NFQUEUE");
23MODULE_ALIAS("ip6t_NFQUEUE");
24MODULE_ALIAS("arpt_NFQUEUE");
25
26static unsigned int
27target(struct sk_buff **pskb,
28 const struct net_device *in,
29 const struct net_device *out,
30 unsigned int hooknum,
31 const void *targinfo,
32 void *userinfo)
33{
34 const struct xt_NFQ_info *tinfo = targinfo;
35
36 return NF_QUEUE_NR(tinfo->queuenum);
37}
38
39static int
40checkentry(const char *tablename,
41 const void *entry,
42 void *targinfo,
43 unsigned int targinfosize,
44 unsigned int hook_mask)
45{
46 if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) {
47 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
48 targinfosize,
49 XT_ALIGN(sizeof(struct xt_NFQ_info)));
50 return 0;
51 }
52
53 return 1;
54}
55
56static struct xt_target ipt_NFQ_reg = {
57 .name = "NFQUEUE",
58 .target = target,
59 .checkentry = checkentry,
60 .me = THIS_MODULE,
61};
62
63static struct xt_target ip6t_NFQ_reg = {
64 .name = "NFQUEUE",
65 .target = target,
66 .checkentry = checkentry,
67 .me = THIS_MODULE,
68};
69
70static struct xt_target arpt_NFQ_reg = {
71 .name = "NFQUEUE",
72 .target = target,
73 .checkentry = checkentry,
74 .me = THIS_MODULE,
75};
76
77static int __init init(void)
78{
79 int ret;
80 ret = xt_register_target(AF_INET, &ipt_NFQ_reg);
81 if (ret)
82 return ret;
83 ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg);
84 if (ret)
85 goto out_ip;
86 ret = xt_register_target(NF_ARP, &arpt_NFQ_reg);
87 if (ret)
88 goto out_ip6;
89
90 return ret;
91out_ip6:
92 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
93out_ip:
94 xt_unregister_target(AF_INET, &ipt_NFQ_reg);
95
96 return ret;
97}
98
99static void __exit fini(void)
100{
101 xt_unregister_target(NF_ARP, &arpt_NFQ_reg);
102 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
103 xt_unregister_target(AF_INET, &ipt_NFQ_reg);
104}
105
106module_init(init);
107module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index e3c69d072c6e..24d477afa939 100644
--- a/net/ipv4/netfilter/ipt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -4,9 +4,12 @@
4#include <linux/module.h> 4#include <linux/module.h>
5#include <linux/skbuff.h> 5#include <linux/skbuff.h>
6 6
7#include <linux/netfilter_ipv4/ip_tables.h> 7#include <linux/netfilter/x_tables.h>
8#include <net/netfilter/nf_conntrack_compat.h> 8#include <net/netfilter/nf_conntrack_compat.h>
9 9
10MODULE_LICENSE("GPL");
11MODULE_ALIAS("ipt_NOTRACK");
12
10static unsigned int 13static unsigned int
11target(struct sk_buff **pskb, 14target(struct sk_buff **pskb,
12 const struct net_device *in, 15 const struct net_device *in,
@@ -17,7 +20,7 @@ target(struct sk_buff **pskb,
17{ 20{
18 /* Previously seen (loopback)? Ignore. */ 21 /* Previously seen (loopback)? Ignore. */
19 if ((*pskb)->nfct != NULL) 22 if ((*pskb)->nfct != NULL)
20 return IPT_CONTINUE; 23 return XT_CONTINUE;
21 24
22 /* Attach fake conntrack entry. 25 /* Attach fake conntrack entry.
23 If there is a real ct entry correspondig to this packet, 26 If there is a real ct entry correspondig to this packet,
@@ -27,12 +30,12 @@ target(struct sk_buff **pskb,
27 (*pskb)->nfctinfo = IP_CT_NEW; 30 (*pskb)->nfctinfo = IP_CT_NEW;
28 nf_conntrack_get((*pskb)->nfct); 31 nf_conntrack_get((*pskb)->nfct);
29 32
30 return IPT_CONTINUE; 33 return XT_CONTINUE;
31} 34}
32 35
33static int 36static int
34checkentry(const char *tablename, 37checkentry(const char *tablename,
35 const struct ipt_entry *e, 38 const void *entry,
36 void *targinfo, 39 void *targinfo,
37 unsigned int targinfosize, 40 unsigned int targinfosize,
38 unsigned int hook_mask) 41 unsigned int hook_mask)
@@ -51,26 +54,39 @@ checkentry(const char *tablename,
51 return 1; 54 return 1;
52} 55}
53 56
54static struct ipt_target ipt_notrack_reg = { 57static struct xt_target notrack_reg = {
55 .name = "NOTRACK", 58 .name = "NOTRACK",
56 .target = target, 59 .target = target,
57 .checkentry = checkentry, 60 .checkentry = checkentry,
58 .me = THIS_MODULE 61 .me = THIS_MODULE,
62};
63static struct xt_target notrack6_reg = {
64 .name = "NOTRACK",
65 .target = target,
66 .checkentry = checkentry,
67 .me = THIS_MODULE,
59}; 68};
60 69
61static int __init init(void) 70static int __init init(void)
62{ 71{
63 if (ipt_register_target(&ipt_notrack_reg)) 72 int ret;
64 return -EINVAL; 73
74 ret = xt_register_target(AF_INET, &notrack_reg);
75 if (ret)
76 return ret;
65 77
66 return 0; 78 ret = xt_register_target(AF_INET6, &notrack6_reg);
79 if (ret)
80 xt_unregister_target(AF_INET, &notrack_reg);
81
82 return ret;
67} 83}
68 84
69static void __exit fini(void) 85static void __exit fini(void)
70{ 86{
71 ipt_unregister_target(&ipt_notrack_reg); 87 xt_unregister_target(AF_INET6, &notrack6_reg);
88 xt_unregister_target(AF_INET, &notrack_reg);
72} 89}
73 90
74module_init(init); 91module_init(init);
75module_exit(fini); 92module_exit(fini);
76MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ipt_comment.c b/net/netfilter/xt_comment.c
index 6b76a1ea5245..4ba6fd65c6e9 100644
--- a/net/ipv4/netfilter/ipt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -6,12 +6,14 @@
6 6
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/skbuff.h> 8#include <linux/skbuff.h>
9#include <linux/netfilter_ipv4/ip_tables.h> 9#include <linux/netfilter/x_tables.h>
10#include <linux/netfilter_ipv4/ipt_comment.h> 10#include <linux/netfilter/xt_comment.h>
11 11
12MODULE_AUTHOR("Brad Fisher <brad@info-link.net>"); 12MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
13MODULE_DESCRIPTION("iptables comment match module"); 13MODULE_DESCRIPTION("iptables comment match module");
14MODULE_LICENSE("GPL"); 14MODULE_LICENSE("GPL");
15MODULE_ALIAS("ipt_comment");
16MODULE_ALIAS("ip6t_comment");
15 17
16static int 18static int
17match(const struct sk_buff *skb, 19match(const struct sk_buff *skb,
@@ -19,6 +21,7 @@ match(const struct sk_buff *skb,
19 const struct net_device *out, 21 const struct net_device *out,
20 const void *matchinfo, 22 const void *matchinfo,
21 int offset, 23 int offset,
24 unsigned int protooff,
22 int *hotdrop) 25 int *hotdrop)
23{ 26{
24 /* We always match */ 27 /* We always match */
@@ -27,18 +30,25 @@ match(const struct sk_buff *skb,
27 30
28static int 31static int
29checkentry(const char *tablename, 32checkentry(const char *tablename,
30 const struct ipt_ip *ip, 33 const void *ip,
31 void *matchinfo, 34 void *matchinfo,
32 unsigned int matchsize, 35 unsigned int matchsize,
33 unsigned int hook_mask) 36 unsigned int hook_mask)
34{ 37{
35 /* Check the size */ 38 /* Check the size */
36 if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info))) 39 if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info)))
37 return 0; 40 return 0;
38 return 1; 41 return 1;
39} 42}
40 43
41static struct ipt_match comment_match = { 44static struct xt_match comment_match = {
45 .name = "comment",
46 .match = match,
47 .checkentry = checkentry,
48 .me = THIS_MODULE
49};
50
51static struct xt_match comment6_match = {
42 .name = "comment", 52 .name = "comment",
43 .match = match, 53 .match = match,
44 .checkentry = checkentry, 54 .checkentry = checkentry,
@@ -47,12 +57,23 @@ static struct ipt_match comment_match = {
47 57
48static int __init init(void) 58static int __init init(void)
49{ 59{
50 return ipt_register_match(&comment_match); 60 int ret;
61
62 ret = xt_register_match(AF_INET, &comment_match);
63 if (ret)
64 return ret;
65
66 ret = xt_register_match(AF_INET6, &comment6_match);
67 if (ret)
68 xt_unregister_match(AF_INET, &comment_match);
69
70 return ret;
51} 71}
52 72
53static void __exit fini(void) 73static void __exit fini(void)
54{ 74{
55 ipt_unregister_match(&comment_match); 75 xt_unregister_match(AF_INET, &comment_match);
76 xt_unregister_match(AF_INET6, &comment6_match);
56} 77}
57 78
58module_init(init); 79module_init(init);
diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/netfilter/xt_connbytes.c
index d68a048b7176..150d2a4b0f71 100644
--- a/net/ipv4/netfilter/ipt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -6,13 +6,15 @@
6 * - add functionality to match number of packets 6 * - add functionality to match number of packets
7 * - add functionality to match average packet size 7 * - add functionality to match average packet size
8 * - add support to match directions seperately 8 * - add support to match directions seperately
9 * 2005-10-16 Harald Welte <laforge@netfilter.org>
10 * - Port to x_tables
9 * 11 *
10 */ 12 */
11#include <linux/module.h> 13#include <linux/module.h>
12#include <linux/skbuff.h> 14#include <linux/skbuff.h>
13#include <net/netfilter/nf_conntrack_compat.h> 15#include <net/netfilter/nf_conntrack_compat.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 16#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_ipv4/ipt_connbytes.h> 17#include <linux/netfilter/xt_connbytes.h>
16 18
17#include <asm/div64.h> 19#include <asm/div64.h>
18#include <asm/bitops.h> 20#include <asm/bitops.h>
@@ -20,6 +22,7 @@
20MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 23MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
22MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); 24MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
25MODULE_ALIAS("ipt_connbytes");
23 26
24/* 64bit divisor, dividend and result. dynamic precision */ 27/* 64bit divisor, dividend and result. dynamic precision */
25static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) 28static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor)
@@ -43,9 +46,10 @@ match(const struct sk_buff *skb,
43 const struct net_device *out, 46 const struct net_device *out,
44 const void *matchinfo, 47 const void *matchinfo,
45 int offset, 48 int offset,
49 unsigned int protoff,
46 int *hotdrop) 50 int *hotdrop)
47{ 51{
48 const struct ipt_connbytes_info *sinfo = matchinfo; 52 const struct xt_connbytes_info *sinfo = matchinfo;
49 u_int64_t what = 0; /* initialize to make gcc happy */ 53 u_int64_t what = 0; /* initialize to make gcc happy */
50 const struct ip_conntrack_counter *counters; 54 const struct ip_conntrack_counter *counters;
51 55
@@ -53,45 +57,45 @@ match(const struct sk_buff *skb,
53 return 0; /* no match */ 57 return 0; /* no match */
54 58
55 switch (sinfo->what) { 59 switch (sinfo->what) {
56 case IPT_CONNBYTES_PKTS: 60 case XT_CONNBYTES_PKTS:
57 switch (sinfo->direction) { 61 switch (sinfo->direction) {
58 case IPT_CONNBYTES_DIR_ORIGINAL: 62 case XT_CONNBYTES_DIR_ORIGINAL:
59 what = counters[IP_CT_DIR_ORIGINAL].packets; 63 what = counters[IP_CT_DIR_ORIGINAL].packets;
60 break; 64 break;
61 case IPT_CONNBYTES_DIR_REPLY: 65 case XT_CONNBYTES_DIR_REPLY:
62 what = counters[IP_CT_DIR_REPLY].packets; 66 what = counters[IP_CT_DIR_REPLY].packets;
63 break; 67 break;
64 case IPT_CONNBYTES_DIR_BOTH: 68 case XT_CONNBYTES_DIR_BOTH:
65 what = counters[IP_CT_DIR_ORIGINAL].packets; 69 what = counters[IP_CT_DIR_ORIGINAL].packets;
66 what += counters[IP_CT_DIR_REPLY].packets; 70 what += counters[IP_CT_DIR_REPLY].packets;
67 break; 71 break;
68 } 72 }
69 break; 73 break;
70 case IPT_CONNBYTES_BYTES: 74 case XT_CONNBYTES_BYTES:
71 switch (sinfo->direction) { 75 switch (sinfo->direction) {
72 case IPT_CONNBYTES_DIR_ORIGINAL: 76 case XT_CONNBYTES_DIR_ORIGINAL:
73 what = counters[IP_CT_DIR_ORIGINAL].bytes; 77 what = counters[IP_CT_DIR_ORIGINAL].bytes;
74 break; 78 break;
75 case IPT_CONNBYTES_DIR_REPLY: 79 case XT_CONNBYTES_DIR_REPLY:
76 what = counters[IP_CT_DIR_REPLY].bytes; 80 what = counters[IP_CT_DIR_REPLY].bytes;
77 break; 81 break;
78 case IPT_CONNBYTES_DIR_BOTH: 82 case XT_CONNBYTES_DIR_BOTH:
79 what = counters[IP_CT_DIR_ORIGINAL].bytes; 83 what = counters[IP_CT_DIR_ORIGINAL].bytes;
80 what += counters[IP_CT_DIR_REPLY].bytes; 84 what += counters[IP_CT_DIR_REPLY].bytes;
81 break; 85 break;
82 } 86 }
83 break; 87 break;
84 case IPT_CONNBYTES_AVGPKT: 88 case XT_CONNBYTES_AVGPKT:
85 switch (sinfo->direction) { 89 switch (sinfo->direction) {
86 case IPT_CONNBYTES_DIR_ORIGINAL: 90 case XT_CONNBYTES_DIR_ORIGINAL:
87 what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, 91 what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes,
88 counters[IP_CT_DIR_ORIGINAL].packets); 92 counters[IP_CT_DIR_ORIGINAL].packets);
89 break; 93 break;
90 case IPT_CONNBYTES_DIR_REPLY: 94 case XT_CONNBYTES_DIR_REPLY:
91 what = div64_64(counters[IP_CT_DIR_REPLY].bytes, 95 what = div64_64(counters[IP_CT_DIR_REPLY].bytes,
92 counters[IP_CT_DIR_REPLY].packets); 96 counters[IP_CT_DIR_REPLY].packets);
93 break; 97 break;
94 case IPT_CONNBYTES_DIR_BOTH: 98 case XT_CONNBYTES_DIR_BOTH:
95 { 99 {
96 u_int64_t bytes; 100 u_int64_t bytes;
97 u_int64_t pkts; 101 u_int64_t pkts;
@@ -117,30 +121,36 @@ match(const struct sk_buff *skb,
117} 121}
118 122
119static int check(const char *tablename, 123static int check(const char *tablename,
120 const struct ipt_ip *ip, 124 const void *ip,
121 void *matchinfo, 125 void *matchinfo,
122 unsigned int matchsize, 126 unsigned int matchsize,
123 unsigned int hook_mask) 127 unsigned int hook_mask)
124{ 128{
125 const struct ipt_connbytes_info *sinfo = matchinfo; 129 const struct xt_connbytes_info *sinfo = matchinfo;
126 130
127 if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info))) 131 if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info)))
128 return 0; 132 return 0;
129 133
130 if (sinfo->what != IPT_CONNBYTES_PKTS && 134 if (sinfo->what != XT_CONNBYTES_PKTS &&
131 sinfo->what != IPT_CONNBYTES_BYTES && 135 sinfo->what != XT_CONNBYTES_BYTES &&
132 sinfo->what != IPT_CONNBYTES_AVGPKT) 136 sinfo->what != XT_CONNBYTES_AVGPKT)
133 return 0; 137 return 0;
134 138
135 if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL && 139 if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
136 sinfo->direction != IPT_CONNBYTES_DIR_REPLY && 140 sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
137 sinfo->direction != IPT_CONNBYTES_DIR_BOTH) 141 sinfo->direction != XT_CONNBYTES_DIR_BOTH)
138 return 0; 142 return 0;
139 143
140 return 1; 144 return 1;
141} 145}
142 146
143static struct ipt_match state_match = { 147static struct xt_match connbytes_match = {
148 .name = "connbytes",
149 .match = &match,
150 .checkentry = &check,
151 .me = THIS_MODULE
152};
153static struct xt_match connbytes6_match = {
144 .name = "connbytes", 154 .name = "connbytes",
145 .match = &match, 155 .match = &match,
146 .checkentry = &check, 156 .checkentry = &check,
@@ -149,12 +159,21 @@ static struct ipt_match state_match = {
149 159
150static int __init init(void) 160static int __init init(void)
151{ 161{
152 return ipt_register_match(&state_match); 162 int ret;
163 ret = xt_register_match(AF_INET, &connbytes_match);
164 if (ret)
165 return ret;
166
167 ret = xt_register_match(AF_INET6, &connbytes6_match);
168 if (ret)
169 xt_unregister_match(AF_INET, &connbytes_match);
170 return ret;
153} 171}
154 172
155static void __exit fini(void) 173static void __exit fini(void)
156{ 174{
157 ipt_unregister_match(&state_match); 175 xt_unregister_match(AF_INET, &connbytes_match);
176 xt_unregister_match(AF_INET6, &connbytes6_match);
158} 177}
159 178
160module_init(init); 179module_init(init);
diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/netfilter/xt_connmark.c
index 5306ef293b92..d06e925032da 100644
--- a/net/ipv4/netfilter/ipt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -25,9 +25,10 @@
25MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 25MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
26MODULE_DESCRIPTION("IP tables connmark match module"); 26MODULE_DESCRIPTION("IP tables connmark match module");
27MODULE_LICENSE("GPL"); 27MODULE_LICENSE("GPL");
28MODULE_ALIAS("ipt_connmark");
28 29
29#include <linux/netfilter_ipv4/ip_tables.h> 30#include <linux/netfilter/x_tables.h>
30#include <linux/netfilter_ipv4/ipt_connmark.h> 31#include <linux/netfilter/xt_connmark.h>
31#include <net/netfilter/nf_conntrack_compat.h> 32#include <net/netfilter/nf_conntrack_compat.h>
32 33
33static int 34static int
@@ -36,9 +37,10 @@ match(const struct sk_buff *skb,
36 const struct net_device *out, 37 const struct net_device *out,
37 const void *matchinfo, 38 const void *matchinfo,
38 int offset, 39 int offset,
40 unsigned int protoff,
39 int *hotdrop) 41 int *hotdrop)
40{ 42{
41 const struct ipt_connmark_info *info = matchinfo; 43 const struct xt_connmark_info *info = matchinfo;
42 u_int32_t ctinfo; 44 u_int32_t ctinfo;
43 const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); 45 const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo);
44 if (!ctmark) 46 if (!ctmark)
@@ -49,14 +51,14 @@ match(const struct sk_buff *skb,
49 51
50static int 52static int
51checkentry(const char *tablename, 53checkentry(const char *tablename,
52 const struct ipt_ip *ip, 54 const void *ip,
53 void *matchinfo, 55 void *matchinfo,
54 unsigned int matchsize, 56 unsigned int matchsize,
55 unsigned int hook_mask) 57 unsigned int hook_mask)
56{ 58{
57 struct ipt_connmark_info *cm = 59 struct xt_connmark_info *cm =
58 (struct ipt_connmark_info *)matchinfo; 60 (struct xt_connmark_info *)matchinfo;
59 if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info))) 61 if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info)))
60 return 0; 62 return 0;
61 63
62 if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { 64 if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
@@ -67,21 +69,40 @@ checkentry(const char *tablename,
67 return 1; 69 return 1;
68} 70}
69 71
70static struct ipt_match connmark_match = { 72static struct xt_match connmark_match = {
73 .name = "connmark",
74 .match = &match,
75 .checkentry = &checkentry,
76 .me = THIS_MODULE
77};
78static struct xt_match connmark6_match = {
71 .name = "connmark", 79 .name = "connmark",
72 .match = &match, 80 .match = &match,
73 .checkentry = &checkentry, 81 .checkentry = &checkentry,
74 .me = THIS_MODULE 82 .me = THIS_MODULE
75}; 83};
76 84
85
77static int __init init(void) 86static int __init init(void)
78{ 87{
79 return ipt_register_match(&connmark_match); 88 int ret;
89
90 need_conntrack();
91
92 ret = xt_register_match(AF_INET, &connmark_match);
93 if (ret)
94 return ret;
95
96 ret = xt_register_match(AF_INET6, &connmark6_match);
97 if (ret)
98 xt_unregister_match(AF_INET, &connmark_match);
99 return ret;
80} 100}
81 101
82static void __exit fini(void) 102static void __exit fini(void)
83{ 103{
84 ipt_unregister_match(&connmark_match); 104 xt_unregister_match(AF_INET6, &connmark6_match);
105 xt_unregister_match(AF_INET, &connmark_match);
85} 106}
86 107
87module_init(init); 108module_init(init);
diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/netfilter/xt_conntrack.c
index c8d18705469b..ffdebc95eb95 100644
--- a/net/ipv4/netfilter/ipt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -18,12 +18,13 @@
18#include <net/netfilter/nf_conntrack.h> 18#include <net/netfilter/nf_conntrack.h>
19#endif 19#endif
20 20
21#include <linux/netfilter_ipv4/ip_tables.h> 21#include <linux/netfilter/x_tables.h>
22#include <linux/netfilter_ipv4/ipt_conntrack.h> 22#include <linux/netfilter/xt_conntrack.h>
23 23
24MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 25MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
26MODULE_DESCRIPTION("iptables connection tracking match module"); 26MODULE_DESCRIPTION("iptables connection tracking match module");
27MODULE_ALIAS("ipt_conntrack");
27 28
28#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) 29#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
29 30
@@ -33,9 +34,10 @@ match(const struct sk_buff *skb,
33 const struct net_device *out, 34 const struct net_device *out,
34 const void *matchinfo, 35 const void *matchinfo,
35 int offset, 36 int offset,
37 unsigned int protoff,
36 int *hotdrop) 38 int *hotdrop)
37{ 39{
38 const struct ipt_conntrack_info *sinfo = matchinfo; 40 const struct xt_conntrack_info *sinfo = matchinfo;
39 struct ip_conntrack *ct; 41 struct ip_conntrack *ct;
40 enum ip_conntrack_info ctinfo; 42 enum ip_conntrack_info ctinfo;
41 unsigned int statebit; 43 unsigned int statebit;
@@ -45,58 +47,58 @@ match(const struct sk_buff *skb,
45#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) 47#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
46 48
47 if (ct == &ip_conntrack_untracked) 49 if (ct == &ip_conntrack_untracked)
48 statebit = IPT_CONNTRACK_STATE_UNTRACKED; 50 statebit = XT_CONNTRACK_STATE_UNTRACKED;
49 else if (ct) 51 else if (ct)
50 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); 52 statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
51 else 53 else
52 statebit = IPT_CONNTRACK_STATE_INVALID; 54 statebit = XT_CONNTRACK_STATE_INVALID;
53 55
54 if(sinfo->flags & IPT_CONNTRACK_STATE) { 56 if(sinfo->flags & XT_CONNTRACK_STATE) {
55 if (ct) { 57 if (ct) {
56 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != 58 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
57 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) 59 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip)
58 statebit |= IPT_CONNTRACK_STATE_SNAT; 60 statebit |= XT_CONNTRACK_STATE_SNAT;
59 61
60 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != 62 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip !=
61 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) 63 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip)
62 statebit |= IPT_CONNTRACK_STATE_DNAT; 64 statebit |= XT_CONNTRACK_STATE_DNAT;
63 } 65 }
64 66
65 if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) 67 if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
66 return 0; 68 return 0;
67 } 69 }
68 70
69 if(sinfo->flags & IPT_CONNTRACK_PROTO) { 71 if(sinfo->flags & XT_CONNTRACK_PROTO) {
70 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) 72 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
71 return 0; 73 return 0;
72 } 74 }
73 75
74 if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { 76 if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
75 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) 77 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
76 return 0; 78 return 0;
77 } 79 }
78 80
79 if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { 81 if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
80 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) 82 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
81 return 0; 83 return 0;
82 } 84 }
83 85
84 if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { 86 if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
85 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) 87 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
86 return 0; 88 return 0;
87 } 89 }
88 90
89 if(sinfo->flags & IPT_CONNTRACK_REPLDST) { 91 if(sinfo->flags & XT_CONNTRACK_REPLDST) {
90 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) 92 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
91 return 0; 93 return 0;
92 } 94 }
93 95
94 if(sinfo->flags & IPT_CONNTRACK_STATUS) { 96 if(sinfo->flags & XT_CONNTRACK_STATUS) {
95 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) 97 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
96 return 0; 98 return 0;
97 } 99 }
98 100
99 if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { 101 if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
100 unsigned long expires; 102 unsigned long expires;
101 103
102 if(!ct) 104 if(!ct)
@@ -104,7 +106,7 @@ match(const struct sk_buff *skb,
104 106
105 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; 107 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
106 108
107 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) 109 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
108 return 0; 110 return 0;
109 } 111 }
110 112
@@ -118,9 +120,10 @@ match(const struct sk_buff *skb,
118 const struct net_device *out, 120 const struct net_device *out,
119 const void *matchinfo, 121 const void *matchinfo,
120 int offset, 122 int offset,
123 unsigned int protoff,
121 int *hotdrop) 124 int *hotdrop)
122{ 125{
123 const struct ipt_conntrack_info *sinfo = matchinfo; 126 const struct xt_conntrack_info *sinfo = matchinfo;
124 struct nf_conn *ct; 127 struct nf_conn *ct;
125 enum ip_conntrack_info ctinfo; 128 enum ip_conntrack_info ctinfo;
126 unsigned int statebit; 129 unsigned int statebit;
@@ -130,58 +133,58 @@ match(const struct sk_buff *skb,
130#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) 133#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
131 134
132 if (ct == &nf_conntrack_untracked) 135 if (ct == &nf_conntrack_untracked)
133 statebit = IPT_CONNTRACK_STATE_UNTRACKED; 136 statebit = XT_CONNTRACK_STATE_UNTRACKED;
134 else if (ct) 137 else if (ct)
135 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); 138 statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
136 else 139 else
137 statebit = IPT_CONNTRACK_STATE_INVALID; 140 statebit = XT_CONNTRACK_STATE_INVALID;
138 141
139 if(sinfo->flags & IPT_CONNTRACK_STATE) { 142 if(sinfo->flags & XT_CONNTRACK_STATE) {
140 if (ct) { 143 if (ct) {
141 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != 144 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip !=
142 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) 145 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip)
143 statebit |= IPT_CONNTRACK_STATE_SNAT; 146 statebit |= XT_CONNTRACK_STATE_SNAT;
144 147
145 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != 148 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip !=
146 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) 149 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip)
147 statebit |= IPT_CONNTRACK_STATE_DNAT; 150 statebit |= XT_CONNTRACK_STATE_DNAT;
148 } 151 }
149 152
150 if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) 153 if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
151 return 0; 154 return 0;
152 } 155 }
153 156
154 if(sinfo->flags & IPT_CONNTRACK_PROTO) { 157 if(sinfo->flags & XT_CONNTRACK_PROTO) {
155 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) 158 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
156 return 0; 159 return 0;
157 } 160 }
158 161
159 if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { 162 if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
160 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) 163 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
161 return 0; 164 return 0;
162 } 165 }
163 166
164 if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { 167 if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
165 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) 168 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
166 return 0; 169 return 0;
167 } 170 }
168 171
169 if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { 172 if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
170 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) 173 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
171 return 0; 174 return 0;
172 } 175 }
173 176
174 if(sinfo->flags & IPT_CONNTRACK_REPLDST) { 177 if(sinfo->flags & XT_CONNTRACK_REPLDST) {
175 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) 178 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
176 return 0; 179 return 0;
177 } 180 }
178 181
179 if(sinfo->flags & IPT_CONNTRACK_STATUS) { 182 if(sinfo->flags & XT_CONNTRACK_STATUS) {
180 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) 183 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
181 return 0; 184 return 0;
182 } 185 }
183 186
184 if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { 187 if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
185 unsigned long expires; 188 unsigned long expires;
186 189
187 if(!ct) 190 if(!ct)
@@ -189,7 +192,7 @@ match(const struct sk_buff *skb,
189 192
190 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; 193 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
191 194
192 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) 195 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
193 return 0; 196 return 0;
194 } 197 }
195 198
@@ -199,18 +202,18 @@ match(const struct sk_buff *skb,
199#endif /* CONFIG_NF_IP_CONNTRACK */ 202#endif /* CONFIG_NF_IP_CONNTRACK */
200 203
201static int check(const char *tablename, 204static int check(const char *tablename,
202 const struct ipt_ip *ip, 205 const void *ip,
203 void *matchinfo, 206 void *matchinfo,
204 unsigned int matchsize, 207 unsigned int matchsize,
205 unsigned int hook_mask) 208 unsigned int hook_mask)
206{ 209{
207 if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info))) 210 if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info)))
208 return 0; 211 return 0;
209 212
210 return 1; 213 return 1;
211} 214}
212 215
213static struct ipt_match conntrack_match = { 216static struct xt_match conntrack_match = {
214 .name = "conntrack", 217 .name = "conntrack",
215 .match = &match, 218 .match = &match,
216 .checkentry = &check, 219 .checkentry = &check,
@@ -219,13 +222,16 @@ static struct ipt_match conntrack_match = {
219 222
220static int __init init(void) 223static int __init init(void)
221{ 224{
222 need_ip_conntrack(); 225 int ret;
223 return ipt_register_match(&conntrack_match); 226 need_conntrack();
227 ret = xt_register_match(AF_INET, &conntrack_match);
228
229 return ret;
224} 230}
225 231
226static void __exit fini(void) 232static void __exit fini(void)
227{ 233{
228 ipt_unregister_match(&conntrack_match); 234 xt_unregister_match(AF_INET, &conntrack_match);
229} 235}
230 236
231module_init(init); 237module_init(init);
diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/netfilter/xt_dccp.c
index ad3278bba6c1..779f42fc9524 100644
--- a/net/ipv4/netfilter/ipt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -14,8 +14,16 @@
14#include <net/ip.h> 14#include <net/ip.h>
15#include <linux/dccp.h> 15#include <linux/dccp.h>
16 16
17#include <linux/netfilter/x_tables.h>
18#include <linux/netfilter/xt_dccp.h>
19
17#include <linux/netfilter_ipv4/ip_tables.h> 20#include <linux/netfilter_ipv4/ip_tables.h>
18#include <linux/netfilter_ipv4/ipt_dccp.h> 21#include <linux/netfilter_ipv6/ip6_tables.h>
22
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
25MODULE_DESCRIPTION("Match for DCCP protocol packets");
26MODULE_ALIAS("ipt_dccp");
19 27
20#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ 28#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
21 || (!!((invflag) & (option)) ^ (cond))) 29 || (!!((invflag) & (option)) ^ (cond)))
@@ -26,6 +34,7 @@ static DEFINE_SPINLOCK(dccp_buflock);
26static inline int 34static inline int
27dccp_find_option(u_int8_t option, 35dccp_find_option(u_int8_t option,
28 const struct sk_buff *skb, 36 const struct sk_buff *skb,
37 unsigned int protoff,
29 const struct dccp_hdr *dh, 38 const struct dccp_hdr *dh,
30 int *hotdrop) 39 int *hotdrop)
31{ 40{
@@ -44,9 +53,7 @@ dccp_find_option(u_int8_t option,
44 return 0; 53 return 0;
45 54
46 spin_lock_bh(&dccp_buflock); 55 spin_lock_bh(&dccp_buflock);
47 op = skb_header_pointer(skb, 56 op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf);
48 skb->nh.iph->ihl*4 + optoff,
49 optlen, dccp_optbuf);
50 if (op == NULL) { 57 if (op == NULL) {
51 /* If we don't have the whole header, drop packet. */ 58 /* If we don't have the whole header, drop packet. */
52 spin_unlock_bh(&dccp_buflock); 59 spin_unlock_bh(&dccp_buflock);
@@ -78,10 +85,10 @@ match_types(const struct dccp_hdr *dh, u_int16_t typemask)
78} 85}
79 86
80static inline int 87static inline int
81match_option(u_int8_t option, const struct sk_buff *skb, 88match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
82 const struct dccp_hdr *dh, int *hotdrop) 89 const struct dccp_hdr *dh, int *hotdrop)
83{ 90{
84 return dccp_find_option(option, skb, dh, hotdrop); 91 return dccp_find_option(option, skb, protoff, dh, hotdrop);
85} 92}
86 93
87static int 94static int
@@ -90,16 +97,17 @@ match(const struct sk_buff *skb,
90 const struct net_device *out, 97 const struct net_device *out,
91 const void *matchinfo, 98 const void *matchinfo,
92 int offset, 99 int offset,
100 unsigned int protoff,
93 int *hotdrop) 101 int *hotdrop)
94{ 102{
95 const struct ipt_dccp_info *info = 103 const struct xt_dccp_info *info =
96 (const struct ipt_dccp_info *)matchinfo; 104 (const struct xt_dccp_info *)matchinfo;
97 struct dccp_hdr _dh, *dh; 105 struct dccp_hdr _dh, *dh;
98 106
99 if (offset) 107 if (offset)
100 return 0; 108 return 0;
101 109
102 dh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_dh), &_dh); 110 dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
103 if (dh == NULL) { 111 if (dh == NULL) {
104 *hotdrop = 1; 112 *hotdrop = 1;
105 return 0; 113 return 0;
@@ -107,42 +115,73 @@ match(const struct sk_buff *skb,
107 115
108 return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) 116 return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
109 && (ntohs(dh->dccph_sport) <= info->spts[1])), 117 && (ntohs(dh->dccph_sport) <= info->spts[1])),
110 IPT_DCCP_SRC_PORTS, info->flags, info->invflags) 118 XT_DCCP_SRC_PORTS, info->flags, info->invflags)
111 && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) 119 && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0])
112 && (ntohs(dh->dccph_dport) <= info->dpts[1])), 120 && (ntohs(dh->dccph_dport) <= info->dpts[1])),
113 IPT_DCCP_DEST_PORTS, info->flags, info->invflags) 121 XT_DCCP_DEST_PORTS, info->flags, info->invflags)
114 && DCCHECK(match_types(dh, info->typemask), 122 && DCCHECK(match_types(dh, info->typemask),
115 IPT_DCCP_TYPE, info->flags, info->invflags) 123 XT_DCCP_TYPE, info->flags, info->invflags)
116 && DCCHECK(match_option(info->option, skb, dh, hotdrop), 124 && DCCHECK(match_option(info->option, skb, protoff, dh,
117 IPT_DCCP_OPTION, info->flags, info->invflags); 125 hotdrop),
126 XT_DCCP_OPTION, info->flags, info->invflags);
118} 127}
119 128
120static int 129static int
121checkentry(const char *tablename, 130checkentry(const char *tablename,
122 const struct ipt_ip *ip, 131 const void *inf,
123 void *matchinfo, 132 void *matchinfo,
124 unsigned int matchsize, 133 unsigned int matchsize,
125 unsigned int hook_mask) 134 unsigned int hook_mask)
126{ 135{
127 const struct ipt_dccp_info *info; 136 const struct ipt_ip *ip = inf;
137 const struct xt_dccp_info *info;
128 138
129 info = (const struct ipt_dccp_info *)matchinfo; 139 info = (const struct xt_dccp_info *)matchinfo;
130 140
131 return ip->proto == IPPROTO_DCCP 141 return ip->proto == IPPROTO_DCCP
132 && !(ip->invflags & IPT_INV_PROTO) 142 && !(ip->invflags & XT_INV_PROTO)
133 && matchsize == IPT_ALIGN(sizeof(struct ipt_dccp_info)) 143 && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
134 && !(info->flags & ~IPT_DCCP_VALID_FLAGS) 144 && !(info->flags & ~XT_DCCP_VALID_FLAGS)
135 && !(info->invflags & ~IPT_DCCP_VALID_FLAGS) 145 && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
136 && !(info->invflags & ~info->flags); 146 && !(info->invflags & ~info->flags);
137} 147}
138 148
139static struct ipt_match dccp_match = 149static int
150checkentry6(const char *tablename,
151 const void *inf,
152 void *matchinfo,
153 unsigned int matchsize,
154 unsigned int hook_mask)
155{
156 const struct ip6t_ip6 *ip = inf;
157 const struct xt_dccp_info *info;
158
159 info = (const struct xt_dccp_info *)matchinfo;
160
161 return ip->proto == IPPROTO_DCCP
162 && !(ip->invflags & XT_INV_PROTO)
163 && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
164 && !(info->flags & ~XT_DCCP_VALID_FLAGS)
165 && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
166 && !(info->invflags & ~info->flags);
167}
168
169
170static struct xt_match dccp_match =
140{ 171{
141 .name = "dccp", 172 .name = "dccp",
142 .match = &match, 173 .match = &match,
143 .checkentry = &checkentry, 174 .checkentry = &checkentry,
144 .me = THIS_MODULE, 175 .me = THIS_MODULE,
145}; 176};
177static struct xt_match dccp6_match =
178{
179 .name = "dccp",
180 .match = &match,
181 .checkentry = &checkentry6,
182 .me = THIS_MODULE,
183};
184
146 185
147static int __init init(void) 186static int __init init(void)
148{ 187{
@@ -154,23 +193,29 @@ static int __init init(void)
154 dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); 193 dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
155 if (!dccp_optbuf) 194 if (!dccp_optbuf)
156 return -ENOMEM; 195 return -ENOMEM;
157 ret = ipt_register_match(&dccp_match); 196 ret = xt_register_match(AF_INET, &dccp_match);
158 if (ret) 197 if (ret)
159 kfree(dccp_optbuf); 198 goto out_kfree;
199 ret = xt_register_match(AF_INET6, &dccp6_match);
200 if (ret)
201 goto out_unreg;
202
203 return ret;
204
205out_unreg:
206 xt_unregister_match(AF_INET, &dccp_match);
207out_kfree:
208 kfree(dccp_optbuf);
160 209
161 return ret; 210 return ret;
162} 211}
163 212
164static void __exit fini(void) 213static void __exit fini(void)
165{ 214{
166 ipt_unregister_match(&dccp_match); 215 xt_unregister_match(AF_INET6, &dccp6_match);
216 xt_unregister_match(AF_INET, &dccp_match);
167 kfree(dccp_optbuf); 217 kfree(dccp_optbuf);
168} 218}
169 219
170module_init(init); 220module_init(init);
171module_exit(fini); 221module_exit(fini);
172
173MODULE_LICENSE("GPL");
174MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
175MODULE_DESCRIPTION("Match for DCCP protocol packets");
176
diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/netfilter/xt_helper.c
index aef649e393af..38b6715e1db4 100644
--- a/net/ipv4/netfilter/ipt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -13,7 +13,6 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/skbuff.h> 14#include <linux/skbuff.h>
15#include <linux/netfilter.h> 15#include <linux/netfilter.h>
16#include <linux/interrupt.h>
17#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) 16#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
18#include <linux/netfilter_ipv4/ip_conntrack.h> 17#include <linux/netfilter_ipv4/ip_conntrack.h>
19#include <linux/netfilter_ipv4/ip_conntrack_core.h> 18#include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -23,12 +22,14 @@
23#include <net/netfilter/nf_conntrack_core.h> 22#include <net/netfilter/nf_conntrack_core.h>
24#include <net/netfilter/nf_conntrack_helper.h> 23#include <net/netfilter/nf_conntrack_helper.h>
25#endif 24#endif
26#include <linux/netfilter_ipv4/ip_tables.h> 25#include <linux/netfilter/x_tables.h>
27#include <linux/netfilter_ipv4/ipt_helper.h> 26#include <linux/netfilter/xt_helper.h>
28 27
29MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); 29MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
31MODULE_DESCRIPTION("iptables helper match module"); 30MODULE_DESCRIPTION("iptables helper match module");
31MODULE_ALIAS("ipt_helper");
32MODULE_ALIAS("ip6t_helper");
32 33
33#if 0 34#if 0
34#define DEBUGP printk 35#define DEBUGP printk
@@ -43,27 +44,28 @@ match(const struct sk_buff *skb,
43 const struct net_device *out, 44 const struct net_device *out,
44 const void *matchinfo, 45 const void *matchinfo,
45 int offset, 46 int offset,
47 unsigned int protoff,
46 int *hotdrop) 48 int *hotdrop)
47{ 49{
48 const struct ipt_helper_info *info = matchinfo; 50 const struct xt_helper_info *info = matchinfo;
49 struct ip_conntrack *ct; 51 struct ip_conntrack *ct;
50 enum ip_conntrack_info ctinfo; 52 enum ip_conntrack_info ctinfo;
51 int ret = info->invert; 53 int ret = info->invert;
52 54
53 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); 55 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
54 if (!ct) { 56 if (!ct) {
55 DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); 57 DEBUGP("xt_helper: Eek! invalid conntrack?\n");
56 return ret; 58 return ret;
57 } 59 }
58 60
59 if (!ct->master) { 61 if (!ct->master) {
60 DEBUGP("ipt_helper: conntrack %p has no master\n", ct); 62 DEBUGP("xt_helper: conntrack %p has no master\n", ct);
61 return ret; 63 return ret;
62 } 64 }
63 65
64 read_lock_bh(&ip_conntrack_lock); 66 read_lock_bh(&ip_conntrack_lock);
65 if (!ct->master->helper) { 67 if (!ct->master->helper) {
66 DEBUGP("ipt_helper: master ct %p has no helper\n", 68 DEBUGP("xt_helper: master ct %p has no helper\n",
67 exp->expectant); 69 exp->expectant);
68 goto out_unlock; 70 goto out_unlock;
69 } 71 }
@@ -89,27 +91,28 @@ match(const struct sk_buff *skb,
89 const struct net_device *out, 91 const struct net_device *out,
90 const void *matchinfo, 92 const void *matchinfo,
91 int offset, 93 int offset,
94 unsigned int protoff,
92 int *hotdrop) 95 int *hotdrop)
93{ 96{
94 const struct ipt_helper_info *info = matchinfo; 97 const struct xt_helper_info *info = matchinfo;
95 struct nf_conn *ct; 98 struct nf_conn *ct;
96 enum ip_conntrack_info ctinfo; 99 enum ip_conntrack_info ctinfo;
97 int ret = info->invert; 100 int ret = info->invert;
98 101
99 ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); 102 ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
100 if (!ct) { 103 if (!ct) {
101 DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); 104 DEBUGP("xt_helper: Eek! invalid conntrack?\n");
102 return ret; 105 return ret;
103 } 106 }
104 107
105 if (!ct->master) { 108 if (!ct->master) {
106 DEBUGP("ipt_helper: conntrack %p has no master\n", ct); 109 DEBUGP("xt_helper: conntrack %p has no master\n", ct);
107 return ret; 110 return ret;
108 } 111 }
109 112
110 read_lock_bh(&nf_conntrack_lock); 113 read_lock_bh(&nf_conntrack_lock);
111 if (!ct->master->helper) { 114 if (!ct->master->helper) {
112 DEBUGP("ipt_helper: master ct %p has no helper\n", 115 DEBUGP("xt_helper: master ct %p has no helper\n",
113 exp->expectant); 116 exp->expectant);
114 goto out_unlock; 117 goto out_unlock;
115 } 118 }
@@ -129,23 +132,29 @@ out_unlock:
129#endif 132#endif
130 133
131static int check(const char *tablename, 134static int check(const char *tablename,
132 const struct ipt_ip *ip, 135 const void *inf,
133 void *matchinfo, 136 void *matchinfo,
134 unsigned int matchsize, 137 unsigned int matchsize,
135 unsigned int hook_mask) 138 unsigned int hook_mask)
136{ 139{
137 struct ipt_helper_info *info = matchinfo; 140 struct xt_helper_info *info = matchinfo;
138 141
139 info->name[29] = '\0'; 142 info->name[29] = '\0';
140 143
141 /* verify size */ 144 /* verify size */
142 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) 145 if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info)))
143 return 0; 146 return 0;
144 147
145 return 1; 148 return 1;
146} 149}
147 150
148static struct ipt_match helper_match = { 151static struct xt_match helper_match = {
152 .name = "helper",
153 .match = &match,
154 .checkentry = &check,
155 .me = THIS_MODULE,
156};
157static struct xt_match helper6_match = {
149 .name = "helper", 158 .name = "helper",
150 .match = &match, 159 .match = &match,
151 .checkentry = &check, 160 .checkentry = &check,
@@ -154,13 +163,24 @@ static struct ipt_match helper_match = {
154 163
155static int __init init(void) 164static int __init init(void)
156{ 165{
157 need_ip_conntrack(); 166 int ret;
158 return ipt_register_match(&helper_match); 167 need_conntrack();
168
169 ret = xt_register_match(AF_INET, &helper_match);
170 if (ret < 0)
171 return ret;
172
173 ret = xt_register_match(AF_INET6, &helper6_match);
174 if (ret < 0)
175 xt_unregister_match(AF_INET, &helper_match);
176
177 return ret;
159} 178}
160 179
161static void __exit fini(void) 180static void __exit fini(void)
162{ 181{
163 ipt_unregister_match(&helper_match); 182 xt_unregister_match(AF_INET, &helper_match);
183 xt_unregister_match(AF_INET6, &helper6_match);
164} 184}
165 185
166module_init(init); 186module_init(init);
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
new file mode 100644
index 000000000000..ab6c710cf88f
--- /dev/null
+++ b/net/netfilter/xt_length.c
@@ -0,0 +1,98 @@
1/* Kernel module to match packet length. */
2/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
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/module.h>
10#include <linux/skbuff.h>
11#include <net/ip.h>
12
13#include <linux/netfilter/xt_length.h>
14#include <linux/netfilter/x_tables.h>
15
16MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
17MODULE_DESCRIPTION("IP tables packet length matching module");
18MODULE_LICENSE("GPL");
19MODULE_ALIAS("ipt_length");
20MODULE_ALIAS("ip6t_length");
21
22static int
23match(const struct sk_buff *skb,
24 const struct net_device *in,
25 const struct net_device *out,
26 const void *matchinfo,
27 int offset,
28 unsigned int protoff,
29 int *hotdrop)
30{
31 const struct xt_length_info *info = matchinfo;
32 u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
33
34 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
35}
36
37static int
38match6(const struct sk_buff *skb,
39 const struct net_device *in,
40 const struct net_device *out,
41 const void *matchinfo,
42 int offset,
43 unsigned int protoff,
44 int *hotdrop)
45{
46 const struct xt_length_info *info = matchinfo;
47 u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
48
49 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
50}
51
52static int
53checkentry(const char *tablename,
54 const void *ip,
55 void *matchinfo,
56 unsigned int matchsize,
57 unsigned int hook_mask)
58{
59 if (matchsize != XT_ALIGN(sizeof(struct xt_length_info)))
60 return 0;
61
62 return 1;
63}
64
65static struct xt_match length_match = {
66 .name = "length",
67 .match = &match,
68 .checkentry = &checkentry,
69 .me = THIS_MODULE,
70};
71static struct xt_match length6_match = {
72 .name = "length",
73 .match = &match6,
74 .checkentry = &checkentry,
75 .me = THIS_MODULE,
76};
77
78static int __init init(void)
79{
80 int ret;
81 ret = xt_register_match(AF_INET, &length_match);
82 if (ret)
83 return ret;
84 ret = xt_register_match(AF_INET6, &length6_match);
85 if (ret)
86 xt_unregister_match(AF_INET, &length_match);
87
88 return ret;
89}
90
91static void __exit fini(void)
92{
93 xt_unregister_match(AF_INET, &length_match);
94 xt_unregister_match(AF_INET6, &length6_match);
95}
96
97module_init(init);
98module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/netfilter/xt_limit.c
index 0c24dcc703a5..15e40506bc3a 100644
--- a/net/ipv4/netfilter/ipt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -18,12 +18,14 @@
18#include <linux/spinlock.h> 18#include <linux/spinlock.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20 20
21#include <linux/netfilter_ipv4/ip_tables.h> 21#include <linux/netfilter/x_tables.h>
22#include <linux/netfilter_ipv4/ipt_limit.h> 22#include <linux/netfilter/xt_limit.h>
23 23
24MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); 25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
26MODULE_DESCRIPTION("iptables rate limit match"); 26MODULE_DESCRIPTION("iptables rate limit match");
27MODULE_ALIAS("ipt_limit");
28MODULE_ALIAS("ip6t_limit");
27 29
28/* The algorithm used is the Simple Token Bucket Filter (TBF) 30/* The algorithm used is the Simple Token Bucket Filter (TBF)
29 * see net/sched/sch_tbf.c in the linux source tree 31 * see net/sched/sch_tbf.c in the linux source tree
@@ -68,9 +70,10 @@ ipt_limit_match(const struct sk_buff *skb,
68 const struct net_device *out, 70 const struct net_device *out,
69 const void *matchinfo, 71 const void *matchinfo,
70 int offset, 72 int offset,
73 unsigned int protoff,
71 int *hotdrop) 74 int *hotdrop)
72{ 75{
73 struct ipt_rateinfo *r = ((struct ipt_rateinfo *)matchinfo)->master; 76 struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master;
74 unsigned long now = jiffies; 77 unsigned long now = jiffies;
75 78
76 spin_lock_bh(&limit_lock); 79 spin_lock_bh(&limit_lock);
@@ -96,32 +99,32 @@ user2credits(u_int32_t user)
96 /* If multiplying would overflow... */ 99 /* If multiplying would overflow... */
97 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) 100 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
98 /* Divide first. */ 101 /* Divide first. */
99 return (user / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; 102 return (user / XT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
100 103
101 return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE; 104 return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
102} 105}
103 106
104static int 107static int
105ipt_limit_checkentry(const char *tablename, 108ipt_limit_checkentry(const char *tablename,
106 const struct ipt_ip *ip, 109 const void *inf,
107 void *matchinfo, 110 void *matchinfo,
108 unsigned int matchsize, 111 unsigned int matchsize,
109 unsigned int hook_mask) 112 unsigned int hook_mask)
110{ 113{
111 struct ipt_rateinfo *r = matchinfo; 114 struct xt_rateinfo *r = matchinfo;
112 115
113 if (matchsize != IPT_ALIGN(sizeof(struct ipt_rateinfo))) 116 if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo)))
114 return 0; 117 return 0;
115 118
116 /* Check for overflow. */ 119 /* Check for overflow. */
117 if (r->burst == 0 120 if (r->burst == 0
118 || user2credits(r->avg * r->burst) < user2credits(r->avg)) { 121 || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
119 printk("Overflow in ipt_limit, try lower: %u/%u\n", 122 printk("Overflow in xt_limit, try lower: %u/%u\n",
120 r->avg, r->burst); 123 r->avg, r->burst);
121 return 0; 124 return 0;
122 } 125 }
123 126
124 /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies * 127 /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
125 128. */ 128 128. */
126 r->prev = jiffies; 129 r->prev = jiffies;
127 r->credit = user2credits(r->avg * r->burst); /* Credits full. */ 130 r->credit = user2credits(r->avg * r->burst); /* Credits full. */
@@ -134,7 +137,13 @@ ipt_limit_checkentry(const char *tablename,
134 return 1; 137 return 1;
135} 138}
136 139
137static struct ipt_match ipt_limit_reg = { 140static struct xt_match ipt_limit_reg = {
141 .name = "limit",
142 .match = ipt_limit_match,
143 .checkentry = ipt_limit_checkentry,
144 .me = THIS_MODULE,
145};
146static struct xt_match limit6_reg = {
138 .name = "limit", 147 .name = "limit",
139 .match = ipt_limit_match, 148 .match = ipt_limit_match,
140 .checkentry = ipt_limit_checkentry, 149 .checkentry = ipt_limit_checkentry,
@@ -143,14 +152,23 @@ static struct ipt_match ipt_limit_reg = {
143 152
144static int __init init(void) 153static int __init init(void)
145{ 154{
146 if (ipt_register_match(&ipt_limit_reg)) 155 int ret;
147 return -EINVAL; 156
148 return 0; 157 ret = xt_register_match(AF_INET, &ipt_limit_reg);
158 if (ret)
159 return ret;
160
161 ret = xt_register_match(AF_INET6, &limit6_reg);
162 if (ret)
163 xt_unregister_match(AF_INET, &ipt_limit_reg);
164
165 return ret;
149} 166}
150 167
151static void __exit fini(void) 168static void __exit fini(void)
152{ 169{
153 ipt_unregister_match(&ipt_limit_reg); 170 xt_unregister_match(AF_INET, &ipt_limit_reg);
171 xt_unregister_match(AF_INET6, &limit6_reg);
154} 172}
155 173
156module_init(init); 174module_init(init);
diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/netfilter/xt_mac.c
index 1b9bb4559f80..0461dcb5fc7a 100644
--- a/net/ipv4/netfilter/ipt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -13,12 +13,15 @@
13#include <linux/if_ether.h> 13#include <linux/if_ether.h>
14#include <linux/etherdevice.h> 14#include <linux/etherdevice.h>
15 15
16#include <linux/netfilter_ipv4/ipt_mac.h> 16#include <linux/netfilter_ipv4.h>
17#include <linux/netfilter_ipv4/ip_tables.h> 17#include <linux/netfilter/xt_mac.h>
18#include <linux/netfilter/x_tables.h>
18 19
19MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 21MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
21MODULE_DESCRIPTION("iptables mac matching module"); 22MODULE_DESCRIPTION("iptables mac matching module");
23MODULE_ALIAS("ipt_mac");
24MODULE_ALIAS("ip6t_mac");
22 25
23static int 26static int
24match(const struct sk_buff *skb, 27match(const struct sk_buff *skb,
@@ -26,9 +29,10 @@ match(const struct sk_buff *skb,
26 const struct net_device *out, 29 const struct net_device *out,
27 const void *matchinfo, 30 const void *matchinfo,
28 int offset, 31 int offset,
32 unsigned int protoff,
29 int *hotdrop) 33 int *hotdrop)
30{ 34{
31 const struct ipt_mac_info *info = matchinfo; 35 const struct xt_mac_info *info = matchinfo;
32 36
33 /* Is mac pointer valid? */ 37 /* Is mac pointer valid? */
34 return (skb->mac.raw >= skb->head 38 return (skb->mac.raw >= skb->head
@@ -40,7 +44,7 @@ match(const struct sk_buff *skb,
40 44
41static int 45static int
42ipt_mac_checkentry(const char *tablename, 46ipt_mac_checkentry(const char *tablename,
43 const struct ipt_ip *ip, 47 const void *inf,
44 void *matchinfo, 48 void *matchinfo,
45 unsigned int matchsize, 49 unsigned int matchsize,
46 unsigned int hook_mask) 50 unsigned int hook_mask)
@@ -49,17 +53,23 @@ ipt_mac_checkentry(const char *tablename,
49 if (hook_mask 53 if (hook_mask
50 & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) 54 & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
51 | (1 << NF_IP_FORWARD))) { 55 | (1 << NF_IP_FORWARD))) {
52 printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); 56 printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
53 return 0; 57 return 0;
54 } 58 }
55 59
56 if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info))) 60 if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info)))
57 return 0; 61 return 0;
58 62
59 return 1; 63 return 1;
60} 64}
61 65
62static struct ipt_match mac_match = { 66static struct xt_match mac_match = {
67 .name = "mac",
68 .match = &match,
69 .checkentry = &ipt_mac_checkentry,
70 .me = THIS_MODULE,
71};
72static struct xt_match mac6_match = {
63 .name = "mac", 73 .name = "mac",
64 .match = &match, 74 .match = &match,
65 .checkentry = &ipt_mac_checkentry, 75 .checkentry = &ipt_mac_checkentry,
@@ -68,12 +78,22 @@ static struct ipt_match mac_match = {
68 78
69static int __init init(void) 79static int __init init(void)
70{ 80{
71 return ipt_register_match(&mac_match); 81 int ret;
82 ret = xt_register_match(AF_INET, &mac_match);
83 if (ret)
84 return ret;
85
86 ret = xt_register_match(AF_INET6, &mac6_match);
87 if (ret)
88 xt_unregister_match(AF_INET, &mac_match);
89
90 return ret;
72} 91}
73 92
74static void __exit fini(void) 93static void __exit fini(void)
75{ 94{
76 ipt_unregister_match(&mac_match); 95 xt_unregister_match(AF_INET, &mac_match);
96 xt_unregister_match(AF_INET6, &mac6_match);
77} 97}
78 98
79module_init(init); 99module_init(init);
diff --git a/net/ipv4/netfilter/ipt_mark.c b/net/netfilter/xt_mark.c
index 00bef6cdd3f8..2a0ac62b72c8 100644
--- a/net/ipv4/netfilter/ipt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -10,12 +10,14 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/skbuff.h> 11#include <linux/skbuff.h>
12 12
13#include <linux/netfilter_ipv4/ipt_mark.h> 13#include <linux/netfilter/xt_mark.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 14#include <linux/netfilter/x_tables.h>
15 15
16MODULE_LICENSE("GPL"); 16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 17MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
18MODULE_DESCRIPTION("iptables mark matching module"); 18MODULE_DESCRIPTION("iptables mark matching module");
19MODULE_ALIAS("ipt_mark");
20MODULE_ALIAS("ip6t_mark");
19 21
20static int 22static int
21match(const struct sk_buff *skb, 23match(const struct sk_buff *skb,
@@ -23,23 +25,24 @@ match(const struct sk_buff *skb,
23 const struct net_device *out, 25 const struct net_device *out,
24 const void *matchinfo, 26 const void *matchinfo,
25 int offset, 27 int offset,
28 unsigned int protoff,
26 int *hotdrop) 29 int *hotdrop)
27{ 30{
28 const struct ipt_mark_info *info = matchinfo; 31 const struct xt_mark_info *info = matchinfo;
29 32
30 return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; 33 return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
31} 34}
32 35
33static int 36static int
34checkentry(const char *tablename, 37checkentry(const char *tablename,
35 const struct ipt_ip *ip, 38 const void *entry,
36 void *matchinfo, 39 void *matchinfo,
37 unsigned int matchsize, 40 unsigned int matchsize,
38 unsigned int hook_mask) 41 unsigned int hook_mask)
39{ 42{
40 struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo; 43 struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo;
41 44
42 if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info))) 45 if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info)))
43 return 0; 46 return 0;
44 47
45 if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { 48 if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
@@ -50,7 +53,14 @@ checkentry(const char *tablename,
50 return 1; 53 return 1;
51} 54}
52 55
53static struct ipt_match mark_match = { 56static struct xt_match mark_match = {
57 .name = "mark",
58 .match = &match,
59 .checkentry = &checkentry,
60 .me = THIS_MODULE,
61};
62
63static struct xt_match mark6_match = {
54 .name = "mark", 64 .name = "mark",
55 .match = &match, 65 .match = &match,
56 .checkentry = &checkentry, 66 .checkentry = &checkentry,
@@ -59,12 +69,22 @@ static struct ipt_match mark_match = {
59 69
60static int __init init(void) 70static int __init init(void)
61{ 71{
62 return ipt_register_match(&mark_match); 72 int ret;
73 ret = xt_register_match(AF_INET, &mark_match);
74 if (ret)
75 return ret;
76
77 ret = xt_register_match(AF_INET6, &mark6_match);
78 if (ret)
79 xt_unregister_match(AF_INET, &mark_match);
80
81 return ret;
63} 82}
64 83
65static void __exit fini(void) 84static void __exit fini(void)
66{ 85{
67 ipt_unregister_match(&mark_match); 86 xt_unregister_match(AF_INET, &mark_match);
87 xt_unregister_match(AF_INET6, &mark6_match);
68} 88}
69 89
70module_init(init); 90module_init(init);
diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/netfilter/xt_physdev.c
index 71515c86ece1..19bb57c14dfe 100644
--- a/net/ipv6/netfilter/ip6t_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -10,8 +10,8 @@
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13#include <linux/netfilter_ipv6/ip6t_physdev.h> 13#include <linux/netfilter/xt_physdev.h>
14#include <linux/netfilter_ipv6/ip6_tables.h> 14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_bridge.h> 15#include <linux/netfilter_bridge.h>
16#define MATCH 1 16#define MATCH 1
17#define NOMATCH 0 17#define NOMATCH 0
@@ -19,6 +19,8 @@
19MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); 20MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
21MODULE_DESCRIPTION("iptables bridge physical device match module"); 21MODULE_DESCRIPTION("iptables bridge physical device match module");
22MODULE_ALIAS("ipt_physdev");
23MODULE_ALIAS("ip6t_physdev");
22 24
23static int 25static int
24match(const struct sk_buff *skb, 26match(const struct sk_buff *skb,
@@ -31,7 +33,7 @@ match(const struct sk_buff *skb,
31{ 33{
32 int i; 34 int i;
33 static const char nulldevname[IFNAMSIZ]; 35 static const char nulldevname[IFNAMSIZ];
34 const struct ip6t_physdev_info *info = matchinfo; 36 const struct xt_physdev_info *info = matchinfo;
35 unsigned int ret; 37 unsigned int ret;
36 const char *indev, *outdev; 38 const char *indev, *outdev;
37 struct nf_bridge_info *nf_bridge; 39 struct nf_bridge_info *nf_bridge;
@@ -41,37 +43,37 @@ match(const struct sk_buff *skb,
41 * the destination device will be a bridge. */ 43 * the destination device will be a bridge. */
42 if (!(nf_bridge = skb->nf_bridge)) { 44 if (!(nf_bridge = skb->nf_bridge)) {
43 /* Return MATCH if the invert flags of the used options are on */ 45 /* Return MATCH if the invert flags of the used options are on */
44 if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && 46 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
45 !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)) 47 !(info->invert & XT_PHYSDEV_OP_BRIDGED))
46 return NOMATCH; 48 return NOMATCH;
47 if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) && 49 if ((info->bitmask & XT_PHYSDEV_OP_ISIN) &&
48 !(info->invert & IP6T_PHYSDEV_OP_ISIN)) 50 !(info->invert & XT_PHYSDEV_OP_ISIN))
49 return NOMATCH; 51 return NOMATCH;
50 if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) && 52 if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) &&
51 !(info->invert & IP6T_PHYSDEV_OP_ISOUT)) 53 !(info->invert & XT_PHYSDEV_OP_ISOUT))
52 return NOMATCH; 54 return NOMATCH;
53 if ((info->bitmask & IP6T_PHYSDEV_OP_IN) && 55 if ((info->bitmask & XT_PHYSDEV_OP_IN) &&
54 !(info->invert & IP6T_PHYSDEV_OP_IN)) 56 !(info->invert & XT_PHYSDEV_OP_IN))
55 return NOMATCH; 57 return NOMATCH;
56 if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) && 58 if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
57 !(info->invert & IP6T_PHYSDEV_OP_OUT)) 59 !(info->invert & XT_PHYSDEV_OP_OUT))
58 return NOMATCH; 60 return NOMATCH;
59 return MATCH; 61 return MATCH;
60 } 62 }
61 63
62 /* This only makes sense in the FORWARD and POSTROUTING chains */ 64 /* This only makes sense in the FORWARD and POSTROUTING chains */
63 if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && 65 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
64 (!!(nf_bridge->mask & BRNF_BRIDGED) ^ 66 (!!(nf_bridge->mask & BRNF_BRIDGED) ^
65 !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))) 67 !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
66 return NOMATCH; 68 return NOMATCH;
67 69
68 if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN && 70 if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
69 (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) || 71 (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
70 (info->bitmask & IP6T_PHYSDEV_OP_ISOUT && 72 (info->bitmask & XT_PHYSDEV_OP_ISOUT &&
71 (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT)))) 73 (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
72 return NOMATCH; 74 return NOMATCH;
73 75
74 if (!(info->bitmask & IP6T_PHYSDEV_OP_IN)) 76 if (!(info->bitmask & XT_PHYSDEV_OP_IN))
75 goto match_outdev; 77 goto match_outdev;
76 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; 78 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
77 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { 79 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
@@ -80,11 +82,11 @@ match(const struct sk_buff *skb,
80 & ((const unsigned int *)info->in_mask)[i]; 82 & ((const unsigned int *)info->in_mask)[i];
81 } 83 }
82 84
83 if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN)) 85 if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN))
84 return NOMATCH; 86 return NOMATCH;
85 87
86match_outdev: 88match_outdev:
87 if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT)) 89 if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
88 return MATCH; 90 return MATCH;
89 outdev = nf_bridge->physoutdev ? 91 outdev = nf_bridge->physoutdev ?
90 nf_bridge->physoutdev->name : nulldevname; 92 nf_bridge->physoutdev->name : nulldevname;
@@ -94,27 +96,34 @@ match_outdev:
94 & ((const unsigned int *)info->out_mask)[i]; 96 & ((const unsigned int *)info->out_mask)[i];
95 } 97 }
96 98
97 return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT); 99 return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
98} 100}
99 101
100static int 102static int
101checkentry(const char *tablename, 103checkentry(const char *tablename,
102 const struct ip6t_ip6 *ip, 104 const void *ip,
103 void *matchinfo, 105 void *matchinfo,
104 unsigned int matchsize, 106 unsigned int matchsize,
105 unsigned int hook_mask) 107 unsigned int hook_mask)
106{ 108{
107 const struct ip6t_physdev_info *info = matchinfo; 109 const struct xt_physdev_info *info = matchinfo;
108 110
109 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info))) 111 if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info)))
110 return 0; 112 return 0;
111 if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) || 113 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
112 info->bitmask & ~IP6T_PHYSDEV_OP_MASK) 114 info->bitmask & ~XT_PHYSDEV_OP_MASK)
113 return 0; 115 return 0;
114 return 1; 116 return 1;
115} 117}
116 118
117static struct ip6t_match physdev_match = { 119static struct xt_match physdev_match = {
120 .name = "physdev",
121 .match = &match,
122 .checkentry = &checkentry,
123 .me = THIS_MODULE,
124};
125
126static struct xt_match physdev6_match = {
118 .name = "physdev", 127 .name = "physdev",
119 .match = &match, 128 .match = &match,
120 .checkentry = &checkentry, 129 .checkentry = &checkentry,
@@ -123,12 +132,23 @@ static struct ip6t_match physdev_match = {
123 132
124static int __init init(void) 133static int __init init(void)
125{ 134{
126 return ip6t_register_match(&physdev_match); 135 int ret;
136
137 ret = xt_register_match(AF_INET, &physdev_match);
138 if (ret < 0)
139 return ret;
140
141 ret = xt_register_match(AF_INET6, &physdev6_match);
142 if (ret < 0)
143 xt_unregister_match(AF_INET, &physdev_match);
144
145 return ret;
127} 146}
128 147
129static void __exit fini(void) 148static void __exit fini(void)
130{ 149{
131 ip6t_unregister_match(&physdev_match); 150 xt_unregister_match(AF_INET, &physdev_match);
151 xt_unregister_match(AF_INET6, &physdev6_match);
132} 152}
133 153
134module_init(init); 154module_init(init);
diff --git a/net/ipv4/netfilter/ipt_pkttype.c b/net/netfilter/xt_pkttype.c
index 8ddb1dc5e5ae..ab1b2630f97d 100644
--- a/net/ipv4/netfilter/ipt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -10,60 +10,72 @@
10#include <linux/if_ether.h> 10#include <linux/if_ether.h>
11#include <linux/if_packet.h> 11#include <linux/if_packet.h>
12 12
13#include <linux/netfilter_ipv4/ipt_pkttype.h> 13#include <linux/netfilter/xt_pkttype.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 14#include <linux/netfilter/x_tables.h>
15 15
16MODULE_LICENSE("GPL"); 16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); 17MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>");
18MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); 18MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
19MODULE_ALIAS("ipt_pkttype");
20MODULE_ALIAS("ip6t_pkttype");
19 21
20static int match(const struct sk_buff *skb, 22static int match(const struct sk_buff *skb,
21 const struct net_device *in, 23 const struct net_device *in,
22 const struct net_device *out, 24 const struct net_device *out,
23 const void *matchinfo, 25 const void *matchinfo,
24 int offset, 26 int offset,
27 unsigned int protoff,
25 int *hotdrop) 28 int *hotdrop)
26{ 29{
27 const struct ipt_pkttype_info *info = matchinfo; 30 const struct xt_pkttype_info *info = matchinfo;
28 31
29 return (skb->pkt_type == info->pkttype) ^ info->invert; 32 return (skb->pkt_type == info->pkttype) ^ info->invert;
30} 33}
31 34
32static int checkentry(const char *tablename, 35static int checkentry(const char *tablename,
33 const struct ipt_ip *ip, 36 const void *ip,
34 void *matchinfo, 37 void *matchinfo,
35 unsigned int matchsize, 38 unsigned int matchsize,
36 unsigned int hook_mask) 39 unsigned int hook_mask)
37{ 40{
38/* 41 if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info)))
39 if (hook_mask
40 & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
41 | (1 << NF_IP_FORWARD))) {
42 printk("ipt_pkttype: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
43 return 0;
44 }
45*/
46 if (matchsize != IPT_ALIGN(sizeof(struct ipt_pkttype_info)))
47 return 0; 42 return 0;
48 43
49 return 1; 44 return 1;
50} 45}
51 46
52static struct ipt_match pkttype_match = { 47static struct xt_match pkttype_match = {
53 .name = "pkttype", 48 .name = "pkttype",
54 .match = &match, 49 .match = &match,
55 .checkentry = &checkentry, 50 .checkentry = &checkentry,
56 .me = THIS_MODULE, 51 .me = THIS_MODULE,
57}; 52};
53static struct xt_match pkttype6_match = {
54 .name = "pkttype",
55 .match = &match,
56 .checkentry = &checkentry,
57 .me = THIS_MODULE,
58};
59
58 60
59static int __init init(void) 61static int __init init(void)
60{ 62{
61 return ipt_register_match(&pkttype_match); 63 int ret;
64 ret = xt_register_match(AF_INET, &pkttype_match);
65 if (ret)
66 return ret;
67
68 ret = xt_register_match(AF_INET6, &pkttype6_match);
69 if (ret)
70 xt_unregister_match(AF_INET, &pkttype_match);
71
72 return ret;
62} 73}
63 74
64static void __exit fini(void) 75static void __exit fini(void)
65{ 76{
66 ipt_unregister_match(&pkttype_match); 77 xt_unregister_match(AF_INET, &pkttype_match);
78 xt_unregister_match(AF_INET6, &pkttype6_match);
67} 79}
68 80
69module_init(init); 81module_init(init);
diff --git a/net/ipv4/netfilter/ipt_realm.c b/net/netfilter/xt_realm.c
index 54a6897ebaa6..2b7e1781d34d 100644
--- a/net/ipv4/netfilter/ipt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -14,12 +14,14 @@
14#include <linux/netdevice.h> 14#include <linux/netdevice.h>
15#include <net/route.h> 15#include <net/route.h>
16 16
17#include <linux/netfilter_ipv4/ipt_realm.h> 17#include <linux/netfilter_ipv4.h>
18#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter/xt_realm.h>
19#include <linux/netfilter/x_tables.h>
19 20
20MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); 21MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
21MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
22MODULE_DESCRIPTION("iptables realm match"); 23MODULE_DESCRIPTION("X_tables realm match");
24MODULE_ALIAS("ipt_realm");
23 25
24static int 26static int
25match(const struct sk_buff *skb, 27match(const struct sk_buff *skb,
@@ -27,16 +29,17 @@ match(const struct sk_buff *skb,
27 const struct net_device *out, 29 const struct net_device *out,
28 const void *matchinfo, 30 const void *matchinfo,
29 int offset, 31 int offset,
32 unsigned int protoff,
30 int *hotdrop) 33 int *hotdrop)
31{ 34{
32 const struct ipt_realm_info *info = matchinfo; 35 const struct xt_realm_info *info = matchinfo;
33 struct dst_entry *dst = skb->dst; 36 struct dst_entry *dst = skb->dst;
34 37
35 return (info->id == (dst->tclassid & info->mask)) ^ info->invert; 38 return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
36} 39}
37 40
38static int check(const char *tablename, 41static int check(const char *tablename,
39 const struct ipt_ip *ip, 42 const void *ip,
40 void *matchinfo, 43 void *matchinfo,
41 unsigned int matchsize, 44 unsigned int matchsize,
42 unsigned int hook_mask) 45 unsigned int hook_mask)
@@ -44,18 +47,18 @@ static int check(const char *tablename,
44 if (hook_mask 47 if (hook_mask
45 & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | 48 & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
46 (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { 49 (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) {
47 printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, " 50 printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
48 "LOCAL_IN or FORWARD.\n"); 51 "LOCAL_IN or FORWARD.\n");
49 return 0; 52 return 0;
50 } 53 }
51 if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) { 54 if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) {
52 printk("ipt_realm: invalid matchsize.\n"); 55 printk("xt_realm: invalid matchsize.\n");
53 return 0; 56 return 0;
54 } 57 }
55 return 1; 58 return 1;
56} 59}
57 60
58static struct ipt_match realm_match = { 61static struct xt_match realm_match = {
59 .name = "realm", 62 .name = "realm",
60 .match = match, 63 .match = match,
61 .checkentry = check, 64 .checkentry = check,
@@ -64,12 +67,12 @@ static struct ipt_match realm_match = {
64 67
65static int __init init(void) 68static int __init init(void)
66{ 69{
67 return ipt_register_match(&realm_match); 70 return xt_register_match(AF_INET, &realm_match);
68} 71}
69 72
70static void __exit fini(void) 73static void __exit fini(void)
71{ 74{
72 ipt_unregister_match(&realm_match); 75 xt_unregister_match(AF_INET, &realm_match);
73} 76}
74 77
75module_init(init); 78module_init(init);
diff --git a/net/ipv4/netfilter/ipt_sctp.c b/net/netfilter/xt_sctp.c
index fe2b327bcaa4..10fbfc5ba758 100644
--- a/net/ipv4/netfilter/ipt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -1,10 +1,18 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/skbuff.h> 2#include <linux/skbuff.h>
3#include <net/ip.h> 3#include <net/ip.h>
4#include <net/ipv6.h>
4#include <linux/sctp.h> 5#include <linux/sctp.h>
5 6
7#include <linux/netfilter/x_tables.h>
8#include <linux/netfilter/xt_sctp.h>
6#include <linux/netfilter_ipv4/ip_tables.h> 9#include <linux/netfilter_ipv4/ip_tables.h>
7#include <linux/netfilter_ipv4/ipt_sctp.h> 10#include <linux/netfilter_ipv6/ip6_tables.h>
11
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Kiran Kumar Immidi");
14MODULE_DESCRIPTION("Match for SCTP protocol packets");
15MODULE_ALIAS("ipt_sctp");
8 16
9#ifdef DEBUG_SCTP 17#ifdef DEBUG_SCTP
10#define duprintf(format, args...) printk(format , ## args) 18#define duprintf(format, args...) printk(format , ## args)
@@ -16,7 +24,7 @@
16 || (!!((invflag) & (option)) ^ (cond))) 24 || (!!((invflag) & (option)) ^ (cond)))
17 25
18static int 26static int
19match_flags(const struct ipt_sctp_flag_info *flag_info, 27match_flags(const struct xt_sctp_flag_info *flag_info,
20 const int flag_count, 28 const int flag_count,
21 u_int8_t chunktype, 29 u_int8_t chunktype,
22 u_int8_t chunkflags) 30 u_int8_t chunkflags)
@@ -32,15 +40,15 @@ match_flags(const struct ipt_sctp_flag_info *flag_info,
32 return 1; 40 return 1;
33} 41}
34 42
35static int 43static inline int
36match_packet(const struct sk_buff *skb, 44match_packet(const struct sk_buff *skb,
45 unsigned int offset,
37 const u_int32_t *chunkmap, 46 const u_int32_t *chunkmap,
38 int chunk_match_type, 47 int chunk_match_type,
39 const struct ipt_sctp_flag_info *flag_info, 48 const struct xt_sctp_flag_info *flag_info,
40 const int flag_count, 49 const int flag_count,
41 int *hotdrop) 50 int *hotdrop)
42{ 51{
43 int offset;
44 u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; 52 u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
45 sctp_chunkhdr_t _sch, *sch; 53 sctp_chunkhdr_t _sch, *sch;
46 54
@@ -52,7 +60,6 @@ match_packet(const struct sk_buff *skb,
52 SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); 60 SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
53 } 61 }
54 62
55 offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
56 do { 63 do {
57 sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); 64 sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
58 if (sch == NULL) { 65 if (sch == NULL) {
@@ -118,19 +125,20 @@ match(const struct sk_buff *skb,
118 const struct net_device *out, 125 const struct net_device *out,
119 const void *matchinfo, 126 const void *matchinfo,
120 int offset, 127 int offset,
128 unsigned int protoff,
121 int *hotdrop) 129 int *hotdrop)
122{ 130{
123 const struct ipt_sctp_info *info; 131 const struct xt_sctp_info *info;
124 sctp_sctphdr_t _sh, *sh; 132 sctp_sctphdr_t _sh, *sh;
125 133
126 info = (const struct ipt_sctp_info *)matchinfo; 134 info = (const struct xt_sctp_info *)matchinfo;
127 135
128 if (offset) { 136 if (offset) {
129 duprintf("Dropping non-first fragment.. FIXME\n"); 137 duprintf("Dropping non-first fragment.. FIXME\n");
130 return 0; 138 return 0;
131 } 139 }
132 140
133 sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh); 141 sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
134 if (sh == NULL) { 142 if (sh == NULL) {
135 duprintf("Dropping evil TCP offset=0 tinygram.\n"); 143 duprintf("Dropping evil TCP offset=0 tinygram.\n");
136 *hotdrop = 1; 144 *hotdrop = 1;
@@ -140,64 +148,103 @@ match(const struct sk_buff *skb,
140 148
141 return SCCHECK(((ntohs(sh->source) >= info->spts[0]) 149 return SCCHECK(((ntohs(sh->source) >= info->spts[0])
142 && (ntohs(sh->source) <= info->spts[1])), 150 && (ntohs(sh->source) <= info->spts[1])),
143 IPT_SCTP_SRC_PORTS, info->flags, info->invflags) 151 XT_SCTP_SRC_PORTS, info->flags, info->invflags)
144 && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) 152 && SCCHECK(((ntohs(sh->dest) >= info->dpts[0])
145 && (ntohs(sh->dest) <= info->dpts[1])), 153 && (ntohs(sh->dest) <= info->dpts[1])),
146 IPT_SCTP_DEST_PORTS, info->flags, info->invflags) 154 XT_SCTP_DEST_PORTS, info->flags, info->invflags)
147 && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type, 155 && SCCHECK(match_packet(skb, protoff,
156 info->chunkmap, info->chunk_match_type,
148 info->flag_info, info->flag_count, 157 info->flag_info, info->flag_count,
149 hotdrop), 158 hotdrop),
150 IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags); 159 XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
151} 160}
152 161
153static int 162static int
154checkentry(const char *tablename, 163checkentry(const char *tablename,
155 const struct ipt_ip *ip, 164 const void *inf,
165 void *matchinfo,
166 unsigned int matchsize,
167 unsigned int hook_mask)
168{
169 const struct xt_sctp_info *info;
170 const struct ipt_ip *ip = inf;
171
172 info = (const struct xt_sctp_info *)matchinfo;
173
174 return ip->proto == IPPROTO_SCTP
175 && !(ip->invflags & XT_INV_PROTO)
176 && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
177 && !(info->flags & ~XT_SCTP_VALID_FLAGS)
178 && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
179 && !(info->invflags & ~info->flags)
180 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
181 (info->chunk_match_type &
182 (SCTP_CHUNK_MATCH_ALL
183 | SCTP_CHUNK_MATCH_ANY
184 | SCTP_CHUNK_MATCH_ONLY)));
185}
186
187static int
188checkentry6(const char *tablename,
189 const void *inf,
156 void *matchinfo, 190 void *matchinfo,
157 unsigned int matchsize, 191 unsigned int matchsize,
158 unsigned int hook_mask) 192 unsigned int hook_mask)
159{ 193{
160 const struct ipt_sctp_info *info; 194 const struct xt_sctp_info *info;
195 const struct ip6t_ip6 *ip = inf;
161 196
162 info = (const struct ipt_sctp_info *)matchinfo; 197 info = (const struct xt_sctp_info *)matchinfo;
163 198
164 return ip->proto == IPPROTO_SCTP 199 return ip->proto == IPPROTO_SCTP
165 && !(ip->invflags & IPT_INV_PROTO) 200 && !(ip->invflags & XT_INV_PROTO)
166 && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info)) 201 && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
167 && !(info->flags & ~IPT_SCTP_VALID_FLAGS) 202 && !(info->flags & ~XT_SCTP_VALID_FLAGS)
168 && !(info->invflags & ~IPT_SCTP_VALID_FLAGS) 203 && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
169 && !(info->invflags & ~info->flags) 204 && !(info->invflags & ~info->flags)
170 && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 205 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
171 (info->chunk_match_type & 206 (info->chunk_match_type &
172 (SCTP_CHUNK_MATCH_ALL 207 (SCTP_CHUNK_MATCH_ALL
173 | SCTP_CHUNK_MATCH_ANY 208 | SCTP_CHUNK_MATCH_ANY
174 | SCTP_CHUNK_MATCH_ONLY))); 209 | SCTP_CHUNK_MATCH_ONLY)));
175} 210}
176 211
177static struct ipt_match sctp_match = 212
213static struct xt_match sctp_match =
178{ 214{
179 .list = { NULL, NULL},
180 .name = "sctp", 215 .name = "sctp",
181 .match = &match, 216 .match = &match,
182 .checkentry = &checkentry, 217 .checkentry = &checkentry,
183 .destroy = NULL, 218 .me = THIS_MODULE
219};
220static struct xt_match sctp6_match =
221{
222 .name = "sctp",
223 .match = &match,
224 .checkentry = &checkentry6,
184 .me = THIS_MODULE 225 .me = THIS_MODULE
185}; 226};
186 227
228
187static int __init init(void) 229static int __init init(void)
188{ 230{
189 return ipt_register_match(&sctp_match); 231 int ret;
232 ret = xt_register_match(AF_INET, &sctp_match);
233 if (ret)
234 return ret;
235
236 ret = xt_register_match(AF_INET6, &sctp6_match);
237 if (ret)
238 xt_unregister_match(AF_INET, &sctp_match);
239
240 return ret;
190} 241}
191 242
192static void __exit fini(void) 243static void __exit fini(void)
193{ 244{
194 ipt_unregister_match(&sctp_match); 245 xt_unregister_match(AF_INET6, &sctp6_match);
246 xt_unregister_match(AF_INET, &sctp_match);
195} 247}
196 248
197module_init(init); 249module_init(init);
198module_exit(fini); 250module_exit(fini);
199
200MODULE_LICENSE("GPL");
201MODULE_AUTHOR("Kiran Kumar Immidi");
202MODULE_DESCRIPTION("Match for SCTP protocol packets");
203
diff --git a/net/ipv4/netfilter/ipt_state.c b/net/netfilter/xt_state.c
index 4d7f16b70cec..39ce808d40ef 100644
--- a/net/ipv4/netfilter/ipt_state.c
+++ b/net/netfilter/xt_state.c
@@ -1,7 +1,7 @@
1/* Kernel module to match connection tracking information. */ 1/* Kernel module to match connection tracking information. */
2 2
3/* (C) 1999-2001 Paul `Rusty' Russell 3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 4 * (C) 2002-2005 Netfilter Core Team <coreteam@netfilter.org>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
@@ -11,12 +11,14 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13#include <net/netfilter/nf_conntrack_compat.h> 13#include <net/netfilter/nf_conntrack_compat.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_ipv4/ipt_state.h> 15#include <linux/netfilter/xt_state.h>
16 16
17MODULE_LICENSE("GPL"); 17MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); 18MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
19MODULE_DESCRIPTION("iptables connection tracking state match module"); 19MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module");
20MODULE_ALIAS("ipt_state");
21MODULE_ALIAS("ip6t_state");
20 22
21static int 23static int
22match(const struct sk_buff *skb, 24match(const struct sk_buff *skb,
@@ -24,35 +26,43 @@ match(const struct sk_buff *skb,
24 const struct net_device *out, 26 const struct net_device *out,
25 const void *matchinfo, 27 const void *matchinfo,
26 int offset, 28 int offset,
29 unsigned int protoff,
27 int *hotdrop) 30 int *hotdrop)
28{ 31{
29 const struct ipt_state_info *sinfo = matchinfo; 32 const struct xt_state_info *sinfo = matchinfo;
30 enum ip_conntrack_info ctinfo; 33 enum ip_conntrack_info ctinfo;
31 unsigned int statebit; 34 unsigned int statebit;
32 35
33 if (nf_ct_is_untracked(skb)) 36 if (nf_ct_is_untracked(skb))
34 statebit = IPT_STATE_UNTRACKED; 37 statebit = XT_STATE_UNTRACKED;
35 else if (!nf_ct_get_ctinfo(skb, &ctinfo)) 38 else if (!nf_ct_get_ctinfo(skb, &ctinfo))
36 statebit = IPT_STATE_INVALID; 39 statebit = XT_STATE_INVALID;
37 else 40 else
38 statebit = IPT_STATE_BIT(ctinfo); 41 statebit = XT_STATE_BIT(ctinfo);
39 42
40 return (sinfo->statemask & statebit); 43 return (sinfo->statemask & statebit);
41} 44}
42 45
43static int check(const char *tablename, 46static int check(const char *tablename,
44 const struct ipt_ip *ip, 47 const void *ip,
45 void *matchinfo, 48 void *matchinfo,
46 unsigned int matchsize, 49 unsigned int matchsize,
47 unsigned int hook_mask) 50 unsigned int hook_mask)
48{ 51{
49 if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info))) 52 if (matchsize != XT_ALIGN(sizeof(struct xt_state_info)))
50 return 0; 53 return 0;
51 54
52 return 1; 55 return 1;
53} 56}
54 57
55static struct ipt_match state_match = { 58static struct xt_match state_match = {
59 .name = "state",
60 .match = &match,
61 .checkentry = &check,
62 .me = THIS_MODULE,
63};
64
65static struct xt_match state6_match = {
56 .name = "state", 66 .name = "state",
57 .match = &match, 67 .match = &match,
58 .checkentry = &check, 68 .checkentry = &check,
@@ -61,13 +71,25 @@ static struct ipt_match state_match = {
61 71
62static int __init init(void) 72static int __init init(void)
63{ 73{
64 need_ip_conntrack(); 74 int ret;
65 return ipt_register_match(&state_match); 75
76 need_conntrack();
77
78 ret = xt_register_match(AF_INET, &state_match);
79 if (ret < 0)
80 return ret;
81
82 ret = xt_register_match(AF_INET6, &state6_match);
83 if (ret < 0)
84 xt_unregister_match(AF_INET,&state_match);
85
86 return ret;
66} 87}
67 88
68static void __exit fini(void) 89static void __exit fini(void)
69{ 90{
70 ipt_unregister_match(&state_match); 91 xt_unregister_match(AF_INET, &state_match);
92 xt_unregister_match(AF_INET6, &state6_match);
71} 93}
72 94
73module_init(init); 95module_init(init);
diff --git a/net/ipv4/netfilter/ipt_string.c b/net/netfilter/xt_string.c
index b5def204d798..7c7d5c8807d6 100644
--- a/net/ipv4/netfilter/ipt_string.c
+++ b/net/netfilter/xt_string.c
@@ -11,23 +11,26 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/skbuff.h> 13#include <linux/skbuff.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_ipv4/ipt_string.h> 15#include <linux/netfilter/xt_string.h>
16#include <linux/textsearch.h> 16#include <linux/textsearch.h>
17 17
18MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); 18MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
19MODULE_DESCRIPTION("IP tables string match module"); 19MODULE_DESCRIPTION("IP tables string match module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21MODULE_ALIAS("ipt_string");
22MODULE_ALIAS("ip6t_string");
21 23
22static int match(const struct sk_buff *skb, 24static int match(const struct sk_buff *skb,
23 const struct net_device *in, 25 const struct net_device *in,
24 const struct net_device *out, 26 const struct net_device *out,
25 const void *matchinfo, 27 const void *matchinfo,
26 int offset, 28 int offset,
29 unsigned int protoff,
27 int *hotdrop) 30 int *hotdrop)
28{ 31{
29 struct ts_state state; 32 struct ts_state state;
30 struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo; 33 struct xt_string_info *conf = (struct xt_string_info *) matchinfo;
31 34
32 memset(&state, 0, sizeof(struct ts_state)); 35 memset(&state, 0, sizeof(struct ts_state));
33 36
@@ -36,18 +39,18 @@ static int match(const struct sk_buff *skb,
36 != UINT_MAX) && !conf->invert; 39 != UINT_MAX) && !conf->invert;
37} 40}
38 41
39#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m) 42#define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
40 43
41static int checkentry(const char *tablename, 44static int checkentry(const char *tablename,
42 const struct ipt_ip *ip, 45 const void *ip,
43 void *matchinfo, 46 void *matchinfo,
44 unsigned int matchsize, 47 unsigned int matchsize,
45 unsigned int hook_mask) 48 unsigned int hook_mask)
46{ 49{
47 struct ipt_string_info *conf = matchinfo; 50 struct xt_string_info *conf = matchinfo;
48 struct ts_config *ts_conf; 51 struct ts_config *ts_conf;
49 52
50 if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info))) 53 if (matchsize != XT_ALIGN(sizeof(struct xt_string_info)))
51 return 0; 54 return 0;
52 55
53 /* Damn, can't handle this case properly with iptables... */ 56 /* Damn, can't handle this case properly with iptables... */
@@ -69,7 +72,14 @@ static void destroy(void *matchinfo, unsigned int matchsize)
69 textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); 72 textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
70} 73}
71 74
72static struct ipt_match string_match = { 75static struct xt_match string_match = {
76 .name = "string",
77 .match = match,
78 .checkentry = checkentry,
79 .destroy = destroy,
80 .me = THIS_MODULE
81};
82static struct xt_match string6_match = {
73 .name = "string", 83 .name = "string",
74 .match = match, 84 .match = match,
75 .checkentry = checkentry, 85 .checkentry = checkentry,
@@ -79,12 +89,22 @@ static struct ipt_match string_match = {
79 89
80static int __init init(void) 90static int __init init(void)
81{ 91{
82 return ipt_register_match(&string_match); 92 int ret;
93
94 ret = xt_register_match(AF_INET, &string_match);
95 if (ret)
96 return ret;
97 ret = xt_register_match(AF_INET6, &string6_match);
98 if (ret)
99 xt_unregister_match(AF_INET, &string_match);
100
101 return ret;
83} 102}
84 103
85static void __exit fini(void) 104static void __exit fini(void)
86{ 105{
87 ipt_unregister_match(&string_match); 106 xt_unregister_match(AF_INET, &string_match);
107 xt_unregister_match(AF_INET6, &string6_match);
88} 108}
89 109
90module_init(init); 110module_init(init);
diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 4dc9b16ab4a3..acf7f533e9f1 100644
--- a/net/ipv4/netfilter/ipt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -1,6 +1,7 @@
1/* Kernel module to match TCP MSS values. */ 1/* Kernel module to match TCP MSS values. */
2 2
3/* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca> 3/* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
4 * Portions (C) 2005 by Harald Welte <laforge@netfilter.org>
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
@@ -11,19 +12,24 @@
11#include <linux/skbuff.h> 12#include <linux/skbuff.h>
12#include <net/tcp.h> 13#include <net/tcp.h>
13 14
14#include <linux/netfilter_ipv4/ipt_tcpmss.h> 15#include <linux/netfilter/xt_tcpmss.h>
16#include <linux/netfilter/x_tables.h>
17
15#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter_ipv4/ip_tables.h>
19#include <linux/netfilter_ipv6/ip6_tables.h>
16 20
17#define TH_SYN 0x02 21#define TH_SYN 0x02
18 22
19MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 24MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
21MODULE_DESCRIPTION("iptables TCP MSS match module"); 25MODULE_DESCRIPTION("iptables TCP MSS match module");
26MODULE_ALIAS("ipt_tcpmss");
22 27
23/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ 28/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
24static inline int 29static inline int
25mssoption_match(u_int16_t min, u_int16_t max, 30mssoption_match(u_int16_t min, u_int16_t max,
26 const struct sk_buff *skb, 31 const struct sk_buff *skb,
32 unsigned int protoff,
27 int invert, 33 int invert,
28 int *hotdrop) 34 int *hotdrop)
29{ 35{
@@ -33,8 +39,7 @@ mssoption_match(u_int16_t min, u_int16_t max,
33 unsigned int i, optlen; 39 unsigned int i, optlen;
34 40
35 /* If we don't have the whole header, drop packet. */ 41 /* If we don't have the whole header, drop packet. */
36 th = skb_header_pointer(skb, skb->nh.iph->ihl * 4, 42 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
37 sizeof(_tcph), &_tcph);
38 if (th == NULL) 43 if (th == NULL)
39 goto dropit; 44 goto dropit;
40 45
@@ -47,8 +52,7 @@ mssoption_match(u_int16_t min, u_int16_t max,
47 goto out; 52 goto out;
48 53
49 /* Truncated options. */ 54 /* Truncated options. */
50 op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th), 55 op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt);
51 optlen, _opt);
52 if (op == NULL) 56 if (op == NULL)
53 goto dropit; 57 goto dropit;
54 58
@@ -79,22 +83,24 @@ match(const struct sk_buff *skb,
79 const struct net_device *out, 83 const struct net_device *out,
80 const void *matchinfo, 84 const void *matchinfo,
81 int offset, 85 int offset,
86 unsigned int protoff,
82 int *hotdrop) 87 int *hotdrop)
83{ 88{
84 const struct ipt_tcpmss_match_info *info = matchinfo; 89 const struct xt_tcpmss_match_info *info = matchinfo;
85 90
86 return mssoption_match(info->mss_min, info->mss_max, skb, 91 return mssoption_match(info->mss_min, info->mss_max, skb, protoff,
87 info->invert, hotdrop); 92 info->invert, hotdrop);
88} 93}
89 94
90static int 95static int
91checkentry(const char *tablename, 96checkentry(const char *tablename,
92 const struct ipt_ip *ip, 97 const void *ipinfo,
93 void *matchinfo, 98 void *matchinfo,
94 unsigned int matchsize, 99 unsigned int matchsize,
95 unsigned int hook_mask) 100 unsigned int hook_mask)
96{ 101{
97 if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info))) 102 const struct ipt_ip *ip = ipinfo;
103 if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
98 return 0; 104 return 0;
99 105
100 /* Must specify -p tcp */ 106 /* Must specify -p tcp */
@@ -106,21 +112,60 @@ checkentry(const char *tablename,
106 return 1; 112 return 1;
107} 113}
108 114
109static struct ipt_match tcpmss_match = { 115static int
116checkentry6(const char *tablename,
117 const void *ipinfo,
118 void *matchinfo,
119 unsigned int matchsize,
120 unsigned int hook_mask)
121{
122 const struct ip6t_ip6 *ip = ipinfo;
123
124 if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
125 return 0;
126
127 /* Must specify -p tcp */
128 if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) {
129 printk("tcpmss: Only works on TCP packets\n");
130 return 0;
131 }
132
133 return 1;
134}
135
136static struct xt_match tcpmss_match = {
110 .name = "tcpmss", 137 .name = "tcpmss",
111 .match = &match, 138 .match = &match,
112 .checkentry = &checkentry, 139 .checkentry = &checkentry,
113 .me = THIS_MODULE, 140 .me = THIS_MODULE,
114}; 141};
115 142
143static struct xt_match tcpmss6_match = {
144 .name = "tcpmss",
145 .match = &match,
146 .checkentry = &checkentry6,
147 .me = THIS_MODULE,
148};
149
150
116static int __init init(void) 151static int __init init(void)
117{ 152{
118 return ipt_register_match(&tcpmss_match); 153 int ret;
154 ret = xt_register_match(AF_INET, &tcpmss_match);
155 if (ret)
156 return ret;
157
158 ret = xt_register_match(AF_INET6, &tcpmss6_match);
159 if (ret)
160 xt_unregister_match(AF_INET, &tcpmss_match);
161
162 return ret;
119} 163}
120 164
121static void __exit fini(void) 165static void __exit fini(void)
122{ 166{
123 ipt_unregister_match(&tcpmss_match); 167 xt_unregister_match(AF_INET6, &tcpmss6_match);
168 xt_unregister_match(AF_INET, &tcpmss_match);
124} 169}
125 170
126module_init(init); 171module_init(init);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
new file mode 100644
index 000000000000..33f86fd6f3e6
--- /dev/null
+++ b/net/netfilter/xt_tcpudp.c
@@ -0,0 +1,333 @@
1#include <linux/types.h>
2#include <linux/module.h>
3#include <net/ip.h>
4#include <net/ipv6.h>
5#include <net/tcp.h>
6#include <net/udp.h>
7#include <linux/netfilter/x_tables.h>
8#include <linux/netfilter/xt_tcpudp.h>
9#include <linux/netfilter_ipv4/ip_tables.h>
10#include <linux/netfilter_ipv6/ip6_tables.h>
11
12MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6");
13MODULE_LICENSE("GPL");
14MODULE_ALIAS("xt_tcp");
15MODULE_ALIAS("xt_udp");
16MODULE_ALIAS("ipt_udp");
17MODULE_ALIAS("ipt_tcp");
18MODULE_ALIAS("ip6t_udp");
19MODULE_ALIAS("ip6t_tcp");
20
21#ifdef DEBUG_IP_FIREWALL_USER
22#define duprintf(format, args...) printk(format , ## args)
23#else
24#define duprintf(format, args...)
25#endif
26
27
28/* Returns 1 if the port is matched by the range, 0 otherwise */
29static inline int
30port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
31{
32 int ret;
33
34 ret = (port >= min && port <= max) ^ invert;
35 return ret;
36}
37
38static int
39tcp_find_option(u_int8_t option,
40 const struct sk_buff *skb,
41 unsigned int protoff,
42 unsigned int optlen,
43 int invert,
44 int *hotdrop)
45{
46 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
47 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
48 unsigned int i;
49
50 duprintf("tcp_match: finding option\n");
51
52 if (!optlen)
53 return invert;
54
55 /* If we don't have the whole header, drop packet. */
56 op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr),
57 optlen, _opt);
58 if (op == NULL) {
59 *hotdrop = 1;
60 return 0;
61 }
62
63 for (i = 0; i < optlen; ) {
64 if (op[i] == option) return !invert;
65 if (op[i] < 2) i++;
66 else i += op[i+1]?:1;
67 }
68
69 return invert;
70}
71
72static int
73tcp_match(const struct sk_buff *skb,
74 const struct net_device *in,
75 const struct net_device *out,
76 const void *matchinfo,
77 int offset,
78 unsigned int protoff,
79 int *hotdrop)
80{
81 struct tcphdr _tcph, *th;
82 const struct xt_tcp *tcpinfo = matchinfo;
83
84 if (offset) {
85 /* To quote Alan:
86
87 Don't allow a fragment of TCP 8 bytes in. Nobody normal
88 causes this. Its a cracker trying to break in by doing a
89 flag overwrite to pass the direction checks.
90 */
91 if (offset == 1) {
92 duprintf("Dropping evil TCP offset=1 frag.\n");
93 *hotdrop = 1;
94 }
95 /* Must not be a fragment. */
96 return 0;
97 }
98
99#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
100
101 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
102 if (th == NULL) {
103 /* We've been asked to examine this packet, and we
104 can't. Hence, no choice but to drop. */
105 duprintf("Dropping evil TCP offset=0 tinygram.\n");
106 *hotdrop = 1;
107 return 0;
108 }
109
110 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
111 ntohs(th->source),
112 !!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
113 return 0;
114 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
115 ntohs(th->dest),
116 !!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
117 return 0;
118 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
119 == tcpinfo->flg_cmp,
120 XT_TCP_INV_FLAGS))
121 return 0;
122 if (tcpinfo->option) {
123 if (th->doff * 4 < sizeof(_tcph)) {
124 *hotdrop = 1;
125 return 0;
126 }
127 if (!tcp_find_option(tcpinfo->option, skb, protoff,
128 th->doff*4 - sizeof(_tcph),
129 tcpinfo->invflags & XT_TCP_INV_OPTION,
130 hotdrop))
131 return 0;
132 }
133 return 1;
134}
135
136/* Called when user tries to insert an entry of this type. */
137static int
138tcp_checkentry(const char *tablename,
139 const void *info,
140 void *matchinfo,
141 unsigned int matchsize,
142 unsigned int hook_mask)
143{
144 const struct ipt_ip *ip = info;
145 const struct xt_tcp *tcpinfo = matchinfo;
146
147 /* Must specify proto == TCP, and no unknown invflags */
148 return ip->proto == IPPROTO_TCP
149 && !(ip->invflags & XT_INV_PROTO)
150 && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
151 && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
152}
153
154/* Called when user tries to insert an entry of this type. */
155static int
156tcp6_checkentry(const char *tablename,
157 const void *entry,
158 void *matchinfo,
159 unsigned int matchsize,
160 unsigned int hook_mask)
161{
162 const struct ip6t_ip6 *ipv6 = entry;
163 const struct xt_tcp *tcpinfo = matchinfo;
164
165 /* Must specify proto == TCP, and no unknown invflags */
166 return ipv6->proto == IPPROTO_TCP
167 && !(ipv6->invflags & XT_INV_PROTO)
168 && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
169 && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
170}
171
172
173static int
174udp_match(const struct sk_buff *skb,
175 const struct net_device *in,
176 const struct net_device *out,
177 const void *matchinfo,
178 int offset,
179 unsigned int protoff,
180 int *hotdrop)
181{
182 struct udphdr _udph, *uh;
183 const struct xt_udp *udpinfo = matchinfo;
184
185 /* Must not be a fragment. */
186 if (offset)
187 return 0;
188
189 uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
190 if (uh == NULL) {
191 /* We've been asked to examine this packet, and we
192 can't. Hence, no choice but to drop. */
193 duprintf("Dropping evil UDP tinygram.\n");
194 *hotdrop = 1;
195 return 0;
196 }
197
198 return port_match(udpinfo->spts[0], udpinfo->spts[1],
199 ntohs(uh->source),
200 !!(udpinfo->invflags & XT_UDP_INV_SRCPT))
201 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
202 ntohs(uh->dest),
203 !!(udpinfo->invflags & XT_UDP_INV_DSTPT));
204}
205
206/* Called when user tries to insert an entry of this type. */
207static int
208udp_checkentry(const char *tablename,
209 const void *info,
210 void *matchinfo,
211 unsigned int matchinfosize,
212 unsigned int hook_mask)
213{
214 const struct ipt_ip *ip = info;
215 const struct xt_udp *udpinfo = matchinfo;
216
217 /* Must specify proto == UDP, and no unknown invflags */
218 if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) {
219 duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
220 IPPROTO_UDP);
221 return 0;
222 }
223 if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
224 duprintf("ipt_udp: matchsize %u != %u\n",
225 matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
226 return 0;
227 }
228 if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
229 duprintf("ipt_udp: unknown flags %X\n",
230 udpinfo->invflags);
231 return 0;
232 }
233
234 return 1;
235}
236
237/* Called when user tries to insert an entry of this type. */
238static int
239udp6_checkentry(const char *tablename,
240 const void *entry,
241 void *matchinfo,
242 unsigned int matchinfosize,
243 unsigned int hook_mask)
244{
245 const struct ip6t_ip6 *ipv6 = entry;
246 const struct xt_udp *udpinfo = matchinfo;
247
248 /* Must specify proto == UDP, and no unknown invflags */
249 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) {
250 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
251 IPPROTO_UDP);
252 return 0;
253 }
254 if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
255 duprintf("ip6t_udp: matchsize %u != %u\n",
256 matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
257 return 0;
258 }
259 if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
260 duprintf("ip6t_udp: unknown flags %X\n",
261 udpinfo->invflags);
262 return 0;
263 }
264
265 return 1;
266}
267
268static struct xt_match tcp_matchstruct = {
269 .name = "tcp",
270 .match = &tcp_match,
271 .checkentry = &tcp_checkentry,
272 .me = THIS_MODULE,
273};
274static struct xt_match tcp6_matchstruct = {
275 .name = "tcp",
276 .match = &tcp_match,
277 .checkentry = &tcp6_checkentry,
278 .me = THIS_MODULE,
279};
280
281static struct xt_match udp_matchstruct = {
282 .name = "udp",
283 .match = &udp_match,
284 .checkentry = &udp_checkentry,
285 .me = THIS_MODULE,
286};
287static struct xt_match udp6_matchstruct = {
288 .name = "udp",
289 .match = &udp_match,
290 .checkentry = &udp6_checkentry,
291 .me = THIS_MODULE,
292};
293
294static int __init init(void)
295{
296 int ret;
297 ret = xt_register_match(AF_INET, &tcp_matchstruct);
298 if (ret)
299 return ret;
300
301 ret = xt_register_match(AF_INET6, &tcp6_matchstruct);
302 if (ret)
303 goto out_unreg_tcp;
304
305 ret = xt_register_match(AF_INET, &udp_matchstruct);
306 if (ret)
307 goto out_unreg_tcp6;
308
309 ret = xt_register_match(AF_INET6, &udp6_matchstruct);
310 if (ret)
311 goto out_unreg_udp;
312
313 return ret;
314
315out_unreg_udp:
316 xt_unregister_match(AF_INET, &tcp_matchstruct);
317out_unreg_tcp6:
318 xt_unregister_match(AF_INET6, &tcp6_matchstruct);
319out_unreg_tcp:
320 xt_unregister_match(AF_INET, &tcp_matchstruct);
321 return ret;
322}
323
324static void __exit fini(void)
325{
326 xt_unregister_match(AF_INET6, &udp6_matchstruct);
327 xt_unregister_match(AF_INET, &udp_matchstruct);
328 xt_unregister_match(AF_INET6, &tcp6_matchstruct);
329 xt_unregister_match(AF_INET, &tcp_matchstruct);
330}
331
332module_init(init);
333module_exit(fini);
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index b5001939b74b..39a22a3ffe78 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -62,7 +62,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
62 struct ipt_target *target; 62 struct ipt_target *target;
63 int ret = 0; 63 int ret = 0;
64 64
65 target = ipt_find_target(t->u.user.name, t->u.user.revision); 65 target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision);
66 if (!target) 66 if (!target)
67 return -ENOENT; 67 return -ENOENT;
68 68