aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-10-08 09:50:38 -0700
committerDavid S. Miller <davem@davemloft.net>2008-10-08 09:50:38 -0700
commit364ae953a48152be11f1aa424cbfd943b7762b0d (patch)
tree6873b352af1aa2dd6baa223b951eff4d6e74b1ae /net/netfilter
parentMerge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 (diff)
parentnetfilter: xtables: remove bogus mangle table dependency of connmark (diff)
downloadlinux-dev-364ae953a48152be11f1aa424cbfd943b7762b0d.tar.xz
linux-dev-364ae953a48152be11f1aa424cbfd943b7762b0d.zip
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/Kconfig236
-rw-r--r--net/netfilter/Makefile6
-rw-r--r--net/netfilter/core.c18
-rw-r--r--net/netfilter/nf_conntrack_acct.c100
-rw-r--r--net/netfilter/nf_conntrack_core.c344
-rw-r--r--net/netfilter/nf_conntrack_ecache.c26
-rw-r--r--net/netfilter/nf_conntrack_expect.c104
-rw-r--r--net/netfilter/nf_conntrack_ftp.c9
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c6
-rw-r--r--net/netfilter/nf_conntrack_helper.c40
-rw-r--r--net/netfilter/nf_conntrack_netlink.c31
-rw-r--r--net/netfilter/nf_conntrack_pptp.c36
-rw-r--r--net/netfilter/nf_conntrack_proto.c10
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c20
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c101
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c6
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c35
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c16
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c20
-rw-r--r--net/netfilter/nf_conntrack_sip.c3
-rw-r--r--net/netfilter/nf_conntrack_standalone.c146
-rw-r--r--net/netfilter/nf_internals.h4
-rw-r--r--net/netfilter/nf_log.c18
-rw-r--r--net/netfilter/nf_queue.c22
-rw-r--r--net/netfilter/nf_sockopt.c18
-rw-r--r--net/netfilter/nf_tproxy_core.c96
-rw-r--r--net/netfilter/nfnetlink_log.c4
-rw-r--r--net/netfilter/x_tables.c145
-rw-r--r--net/netfilter/xt_CLASSIFY.c44
-rw-r--r--net/netfilter/xt_CONNMARK.c78
-rw-r--r--net/netfilter/xt_CONNSECMARK.c63
-rw-r--r--net/netfilter/xt_DSCP.c59
-rw-r--r--net/netfilter/xt_MARK.c76
-rw-r--r--net/netfilter/xt_NFLOG.c46
-rw-r--r--net/netfilter/xt_NFQUEUE.c10
-rw-r--r--net/netfilter/xt_NOTRACK.c30
-rw-r--r--net/netfilter/xt_RATEEST.c56
-rw-r--r--net/netfilter/xt_SECMARK.c52
-rw-r--r--net/netfilter/xt_TCPMSS.c38
-rw-r--r--net/netfilter/xt_TCPOPTSTRIP.c16
-rw-r--r--net/netfilter/xt_TPROXY.c102
-rw-r--r--net/netfilter/xt_TRACE.c30
-rw-r--r--net/netfilter/xt_comment.c31
-rw-r--r--net/netfilter/xt_connbytes.c56
-rw-r--r--net/netfilter/xt_connlimit.c80
-rw-r--r--net/netfilter/xt_connmark.c68
-rw-r--r--net/netfilter/xt_conntrack.c62
-rw-r--r--net/netfilter/xt_dccp.c27
-rw-r--r--net/netfilter/xt_dscp.c51
-rw-r--r--net/netfilter/xt_esp.c25
-rw-r--r--net/netfilter/xt_hashlimit.c104
-rw-r--r--net/netfilter/xt_helper.c54
-rw-r--r--net/netfilter/xt_iprange.c27
-rw-r--r--net/netfilter/xt_length.c18
-rw-r--r--net/netfilter/xt_limit.c54
-rw-r--r--net/netfilter/xt_mac.c41
-rw-r--r--net/netfilter/xt_mark.c46
-rw-r--r--net/netfilter/xt_multiport.c71
-rw-r--r--net/netfilter/xt_owner.c51
-rw-r--r--net/netfilter/xt_physdev.c49
-rw-r--r--net/netfilter/xt_pkttype.c37
-rw-r--r--net/netfilter/xt_policy.c34
-rw-r--r--net/netfilter/xt_quota.c43
-rw-r--r--net/netfilter/xt_rateest.c58
-rw-r--r--net/netfilter/xt_realm.c9
-rw-r--r--net/netfilter/xt_recent.c689
-rw-r--r--net/netfilter/xt_sctp.c27
-rw-r--r--net/netfilter/xt_socket.c185
-rw-r--r--net/netfilter/xt_state.c24
-rw-r--r--net/netfilter/xt_statistic.c45
-rw-r--r--net/netfilter/xt_string.c53
-rw-r--r--net/netfilter/xt_tcpmss.c17
-rw-r--r--net/netfilter/xt_tcpudp.c64
-rw-r--r--net/netfilter/xt_time.c41
-rw-r--r--net/netfilter/xt_u32.c33
76 files changed, 2653 insertions, 1943 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index ee898e74808d..f70b4145ffc7 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -38,10 +38,11 @@ config NF_CONNTRACK
To compile it as a module, choose M here. If unsure, say N.
+if NF_CONNTRACK
+
config NF_CT_ACCT
bool "Connection tracking flow accounting"
depends on NETFILTER_ADVANCED
- depends on NF_CONNTRACK
help
If this option is enabled, the connection tracking code will
keep per-flow packet and byte counters.
@@ -63,7 +64,6 @@ config NF_CT_ACCT
config NF_CONNTRACK_MARK
bool 'Connection mark tracking support'
depends on NETFILTER_ADVANCED
- depends on NF_CONNTRACK
help
This option enables support for connection marks, used by the
`CONNMARK' target and `connmark' match. Similar to the mark value
@@ -72,7 +72,7 @@ config NF_CONNTRACK_MARK
config NF_CONNTRACK_SECMARK
bool 'Connection tracking security mark support'
- depends on NF_CONNTRACK && NETWORK_SECMARK
+ depends on NETWORK_SECMARK
default m if NETFILTER_ADVANCED=n
help
This option enables security markings to be applied to
@@ -85,7 +85,6 @@ config NF_CONNTRACK_SECMARK
config NF_CONNTRACK_EVENTS
bool "Connection tracking events"
- depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
help
If this option is enabled, the connection tracking code will
@@ -96,7 +95,7 @@ config NF_CONNTRACK_EVENTS
config NF_CT_PROTO_DCCP
tristate 'DCCP protocol connection tracking support (EXPERIMENTAL)'
- depends on EXPERIMENTAL && NF_CONNTRACK
+ depends on EXPERIMENTAL
depends on NETFILTER_ADVANCED
default IP_DCCP
help
@@ -107,11 +106,10 @@ config NF_CT_PROTO_DCCP
config NF_CT_PROTO_GRE
tristate
- depends on NF_CONNTRACK
config NF_CT_PROTO_SCTP
tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
- depends on EXPERIMENTAL && NF_CONNTRACK
+ depends on EXPERIMENTAL
depends on NETFILTER_ADVANCED
default IP_SCTP
help
@@ -123,7 +121,6 @@ config NF_CT_PROTO_SCTP
config NF_CT_PROTO_UDPLITE
tristate 'UDP-Lite protocol connection tracking support'
- depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
help
With this option enabled, the layer 3 independent connection
@@ -134,7 +131,6 @@ config NF_CT_PROTO_UDPLITE
config NF_CONNTRACK_AMANDA
tristate "Amanda backup protocol support"
- depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
select TEXTSEARCH
select TEXTSEARCH_KMP
@@ -150,7 +146,6 @@ config NF_CONNTRACK_AMANDA
config NF_CONNTRACK_FTP
tristate "FTP protocol support"
- depends on NF_CONNTRACK
default m if NETFILTER_ADVANCED=n
help
Tracking FTP connections is problematic: special helpers are
@@ -165,7 +160,7 @@ config NF_CONNTRACK_FTP
config NF_CONNTRACK_H323
tristate "H.323 protocol support"
- depends on NF_CONNTRACK && (IPV6 || IPV6=n)
+ depends on (IPV6 || IPV6=n)
depends on NETFILTER_ADVANCED
help
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
@@ -185,7 +180,6 @@ config NF_CONNTRACK_H323
config NF_CONNTRACK_IRC
tristate "IRC protocol support"
- depends on NF_CONNTRACK
default m if NETFILTER_ADVANCED=n
help
There is a commonly-used extension to IRC called
@@ -201,7 +195,6 @@ config NF_CONNTRACK_IRC
config NF_CONNTRACK_NETBIOS_NS
tristate "NetBIOS name service protocol support"
- depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
help
NetBIOS name service requests are sent as broadcast messages from an
@@ -221,7 +214,6 @@ config NF_CONNTRACK_NETBIOS_NS
config NF_CONNTRACK_PPTP
tristate "PPtP protocol support"
- depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
select NF_CT_PROTO_GRE
help
@@ -241,7 +233,7 @@ config NF_CONNTRACK_PPTP
config NF_CONNTRACK_SANE
tristate "SANE protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ depends on EXPERIMENTAL
depends on NETFILTER_ADVANCED
help
SANE is a protocol for remote access to scanners as implemented
@@ -255,7 +247,6 @@ config NF_CONNTRACK_SANE
config NF_CONNTRACK_SIP
tristate "SIP protocol support"
- depends on NF_CONNTRACK
default m if NETFILTER_ADVANCED=n
help
SIP is an application-layer control protocol that can establish,
@@ -268,7 +259,6 @@ config NF_CONNTRACK_SIP
config NF_CONNTRACK_TFTP
tristate "TFTP protocol support"
- depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
help
TFTP connection tracking helper, this is required depending
@@ -280,13 +270,29 @@ config NF_CONNTRACK_TFTP
config NF_CT_NETLINK
tristate 'Connection tracking netlink interface'
- depends on NF_CONNTRACK
select NETFILTER_NETLINK
depends on NF_NAT=n || NF_NAT
default m if NETFILTER_ADVANCED=n
help
This option enables support for a netlink-based userspace interface
+# transparent proxy support
+config NETFILTER_TPROXY
+ tristate "Transparent proxying support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ depends on IP_NF_MANGLE
+ depends on NETFILTER_ADVANCED
+ help
+ This option enables transparent proxying support, that is,
+ support for handling non-locally bound IPv4 TCP and UDP sockets.
+ For it to work you will have to configure certain iptables rules
+ and use policy routing. For more information on how to set it up
+ see Documentation/networking/tproxy.txt.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+endif # NF_CONNTRACK
+
config NETFILTER_XTABLES
tristate "Netfilter Xtables support (required for ip_tables)"
default m if NETFILTER_ADVANCED=n
@@ -294,11 +300,12 @@ config NETFILTER_XTABLES
This is required if you intend to use any of ip_tables,
ip6_tables or arp_tables.
+if NETFILTER_XTABLES
+
# alphabetically ordered list of targets
config NETFILTER_XT_TARGET_CLASSIFY
tristate '"CLASSIFY" target support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This option adds a `CLASSIFY' target, which enables the user to set
@@ -311,8 +318,6 @@ config NETFILTER_XT_TARGET_CLASSIFY
config NETFILTER_XT_TARGET_CONNMARK
tristate '"CONNMARK" target support'
- depends on NETFILTER_XTABLES
- depends on IP_NF_MANGLE || IP6_NF_MANGLE
depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
select NF_CONNTRACK_MARK
@@ -325,9 +330,20 @@ config NETFILTER_XT_TARGET_CONNMARK
<file:Documentation/kbuild/modules.txt>. The module will be called
ipt_CONNMARK.ko. If unsure, say `N'.
+config NETFILTER_XT_TARGET_CONNSECMARK
+ tristate '"CONNSECMARK" target support'
+ depends on NF_CONNTRACK && NF_CONNTRACK_SECMARK
+ default m if NETFILTER_ADVANCED=n
+ help
+ The CONNSECMARK target copies security markings from packets
+ to connections, and restores security markings from connections
+ to packets (if the packets are not already marked). This would
+ normally be used in conjunction with the SECMARK target.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_TARGET_DSCP
tristate '"DSCP" and "TOS" target support'
- depends on NETFILTER_XTABLES
depends on IP_NF_MANGLE || IP6_NF_MANGLE
depends on NETFILTER_ADVANCED
help
@@ -344,7 +360,6 @@ config NETFILTER_XT_TARGET_DSCP
config NETFILTER_XT_TARGET_MARK
tristate '"MARK" target support'
- depends on NETFILTER_XTABLES
default m if NETFILTER_ADVANCED=n
help
This option adds a `MARK' target, which allows you to create rules
@@ -356,21 +371,8 @@ config NETFILTER_XT_TARGET_MARK
To compile it as a module, choose M here. If unsure, say N.
-config NETFILTER_XT_TARGET_NFQUEUE
- tristate '"NFQUEUE" target Support'
- depends on NETFILTER_XTABLES
- depends on NETFILTER_ADVANCED
- help
- This target replaced the old obsolete QUEUE target.
-
- As opposed to QUEUE, it supports 65535 different queues,
- not just one.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config NETFILTER_XT_TARGET_NFLOG
tristate '"NFLOG" target support'
- depends on NETFILTER_XTABLES
default m if NETFILTER_ADVANCED=n
help
This option enables the NFLOG target, which allows to LOG
@@ -380,9 +382,19 @@ config NETFILTER_XT_TARGET_NFLOG
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_TARGET_NFQUEUE
+ tristate '"NFQUEUE" target Support'
+ depends on NETFILTER_ADVANCED
+ help
+ This target replaced the old obsolete QUEUE target.
+
+ As opposed to QUEUE, it supports 65535 different queues,
+ not just one.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_TARGET_NOTRACK
tristate '"NOTRACK" target support'
- depends on NETFILTER_XTABLES
depends on IP_NF_RAW || IP6_NF_RAW
depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
@@ -397,7 +409,6 @@ config NETFILTER_XT_TARGET_NOTRACK
config NETFILTER_XT_TARGET_RATEEST
tristate '"RATEEST" target support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This option adds a `RATEEST' target, which allows to measure
@@ -406,9 +417,23 @@ config NETFILTER_XT_TARGET_RATEEST
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_TARGET_TPROXY
+ tristate '"TPROXY" target support (EXPERIMENTAL)'
+ depends on EXPERIMENTAL
+ depends on NETFILTER_TPROXY
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_ADVANCED
+ select NF_DEFRAG_IPV4
+ help
+ This option adds a `TPROXY' target, which is somewhat similar to
+ REDIRECT. It can only be used in the mangle table and is useful
+ to redirect traffic to a transparent proxy. It does _not_ depend
+ on Netfilter connection tracking and NAT, unlike REDIRECT.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_TARGET_TRACE
tristate '"TRACE" target support'
- depends on NETFILTER_XTABLES
depends on IP_NF_RAW || IP6_NF_RAW
depends on NETFILTER_ADVANCED
help
@@ -421,7 +446,7 @@ config NETFILTER_XT_TARGET_TRACE
config NETFILTER_XT_TARGET_SECMARK
tristate '"SECMARK" target support'
- depends on NETFILTER_XTABLES && NETWORK_SECMARK
+ depends on NETWORK_SECMARK
default m if NETFILTER_ADVANCED=n
help
The SECMARK target allows security marking of network
@@ -429,21 +454,9 @@ config NETFILTER_XT_TARGET_SECMARK
To compile it as a module, choose M here. If unsure, say N.
-config NETFILTER_XT_TARGET_CONNSECMARK
- tristate '"CONNSECMARK" target support'
- depends on NETFILTER_XTABLES && NF_CONNTRACK && NF_CONNTRACK_SECMARK
- default m if NETFILTER_ADVANCED=n
- help
- The CONNSECMARK target copies security markings from packets
- to connections, and restores security markings from connections
- to packets (if the packets are not already marked). This would
- normally be used in conjunction with the SECMARK target.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config NETFILTER_XT_TARGET_TCPMSS
tristate '"TCPMSS" target support'
- depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
+ depends on (IPV6 || IPV6=n)
default m if NETFILTER_ADVANCED=n
---help---
This option adds a `TCPMSS' target, which allows you to alter the
@@ -470,7 +483,7 @@ config NETFILTER_XT_TARGET_TCPMSS
config NETFILTER_XT_TARGET_TCPOPTSTRIP
tristate '"TCPOPTSTRIP" target support (EXPERIMENTAL)'
- depends on EXPERIMENTAL && NETFILTER_XTABLES
+ depends on EXPERIMENTAL
depends on IP_NF_MANGLE || IP6_NF_MANGLE
depends on NETFILTER_ADVANCED
help
@@ -479,7 +492,6 @@ config NETFILTER_XT_TARGET_TCPOPTSTRIP
config NETFILTER_XT_MATCH_COMMENT
tristate '"comment" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This option adds a `comment' dummy-match, which allows you to put
@@ -490,7 +502,6 @@ config NETFILTER_XT_MATCH_COMMENT
config NETFILTER_XT_MATCH_CONNBYTES
tristate '"connbytes" per-connection counter match support'
- depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
select NF_CT_ACCT
@@ -503,7 +514,6 @@ config NETFILTER_XT_MATCH_CONNBYTES
config NETFILTER_XT_MATCH_CONNLIMIT
tristate '"connlimit" match support"'
- depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
---help---
@@ -512,7 +522,6 @@ config NETFILTER_XT_MATCH_CONNLIMIT
config NETFILTER_XT_MATCH_CONNMARK
tristate '"connmark" connection mark match support'
- depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
select NF_CONNTRACK_MARK
@@ -526,7 +535,6 @@ config NETFILTER_XT_MATCH_CONNMARK
config NETFILTER_XT_MATCH_CONNTRACK
tristate '"conntrack" connection tracking match support'
- depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
default m if NETFILTER_ADVANCED=n
help
@@ -540,7 +548,6 @@ config NETFILTER_XT_MATCH_CONNTRACK
config NETFILTER_XT_MATCH_DCCP
tristate '"dccp" protocol match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
default IP_DCCP
help
@@ -553,7 +560,6 @@ config NETFILTER_XT_MATCH_DCCP
config NETFILTER_XT_MATCH_DSCP
tristate '"dscp" and "tos" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This option adds a `DSCP' match, which allows you to match against
@@ -569,7 +575,6 @@ config NETFILTER_XT_MATCH_DSCP
config NETFILTER_XT_MATCH_ESP
tristate '"esp" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This match extension allows you to match a range of SPIs
@@ -577,9 +582,23 @@ config NETFILTER_XT_MATCH_ESP
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_HASHLIMIT
+ tristate '"hashlimit" match support'
+ depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
+ depends on NETFILTER_ADVANCED
+ help
+ This option adds a `hashlimit' match.
+
+ As opposed to `limit', this match dynamically creates a hash table
+ of limit buckets, based on your selection of source/destination
+ addresses and/or ports.
+
+ It enables you to express policies like `10kpps for any given
+ destination address' or `500pps from any given source address'
+ with a single rule.
+
config NETFILTER_XT_MATCH_HELPER
tristate '"helper" match support'
- depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED
help
@@ -590,7 +609,6 @@ config NETFILTER_XT_MATCH_HELPER
config NETFILTER_XT_MATCH_IPRANGE
tristate '"iprange" address range match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
---help---
This option adds a "iprange" match, which allows you to match based on
@@ -601,7 +619,6 @@ config NETFILTER_XT_MATCH_IPRANGE
config NETFILTER_XT_MATCH_LENGTH
tristate '"length" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This option allows you to match the length of a packet against a
@@ -611,7 +628,6 @@ config NETFILTER_XT_MATCH_LENGTH
config NETFILTER_XT_MATCH_LIMIT
tristate '"limit" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
limit matching allows you to control the rate at which a rule can be
@@ -622,7 +638,6 @@ config NETFILTER_XT_MATCH_LIMIT
config NETFILTER_XT_MATCH_MAC
tristate '"mac" address match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
MAC matching allows you to match packets based on the source
@@ -632,7 +647,6 @@ config NETFILTER_XT_MATCH_MAC
config NETFILTER_XT_MATCH_MARK
tristate '"mark" match support'
- depends on NETFILTER_XTABLES
default m if NETFILTER_ADVANCED=n
help
Netfilter mark matching allows you to match packets based on the
@@ -641,9 +655,18 @@ config NETFILTER_XT_MATCH_MARK
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_MULTIPORT
+ tristate '"multiport" Multiple port match support'
+ depends on NETFILTER_ADVANCED
+ help
+ Multiport matching allows you to match TCP or UDP packets based on
+ a series of source or destination ports: normally a rule can only
+ match a single range of ports.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_OWNER
tristate '"owner" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
---help---
Socket owner matching allows you to match locally-generated packets
@@ -652,7 +675,7 @@ config NETFILTER_XT_MATCH_OWNER
config NETFILTER_XT_MATCH_POLICY
tristate 'IPsec "policy" match support'
- depends on NETFILTER_XTABLES && XFRM
+ depends on XFRM
default m if NETFILTER_ADVANCED=n
help
Policy matching allows you to match packets based on the
@@ -661,20 +684,9 @@ config NETFILTER_XT_MATCH_POLICY
To compile it as a module, choose M here. If unsure, say N.
-config NETFILTER_XT_MATCH_MULTIPORT
- tristate '"multiport" Multiple port match support'
- depends on NETFILTER_XTABLES
- depends on NETFILTER_ADVANCED
- help
- Multiport matching allows you to match TCP or UDP packets based on
- a series of source or destination ports: normally a rule can only
- match a single range of ports.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config NETFILTER_XT_MATCH_PHYSDEV
tristate '"physdev" match support'
- depends on NETFILTER_XTABLES && BRIDGE && BRIDGE_NETFILTER
+ depends on BRIDGE && BRIDGE_NETFILTER
depends on NETFILTER_ADVANCED
help
Physdev packet matching matches against the physical bridge ports
@@ -684,7 +696,6 @@ config NETFILTER_XT_MATCH_PHYSDEV
config NETFILTER_XT_MATCH_PKTTYPE
tristate '"pkttype" packet type match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
Packet type matching allows you to match a packet by
@@ -697,7 +708,6 @@ config NETFILTER_XT_MATCH_PKTTYPE
config NETFILTER_XT_MATCH_QUOTA
tristate '"quota" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This option adds a `quota' match, which allows to match on a
@@ -708,7 +718,6 @@ config NETFILTER_XT_MATCH_QUOTA
config NETFILTER_XT_MATCH_RATEEST
tristate '"rateest" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
select NETFILTER_XT_TARGET_RATEEST
help
@@ -719,7 +728,6 @@ config NETFILTER_XT_MATCH_RATEEST
config NETFILTER_XT_MATCH_REALM
tristate '"realm" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
select NET_CLS_ROUTE
help
@@ -732,9 +740,26 @@ config NETFILTER_XT_MATCH_REALM
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+config NETFILTER_XT_MATCH_RECENT
+ tristate '"recent" match support'
+ depends on NETFILTER_ADVANCED
+ ---help---
+ This match is used for creating one or many lists of recently
+ used addresses and then matching against that/those list(s).
+
+ Short options are available by using 'iptables -m recent -h'
+ Official Website: <http://snowman.net/projects/ipt_recent/>
+
+config NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
+ bool 'Enable obsolete /proc/net/ipt_recent'
+ depends on NETFILTER_XT_MATCH_RECENT && PROC_FS
+ ---help---
+ This option enables the old /proc/net/ipt_recent interface,
+ which has been obsoleted by /proc/net/xt_recent.
+
config NETFILTER_XT_MATCH_SCTP
tristate '"sctp" protocol match support (EXPERIMENTAL)'
- depends on NETFILTER_XTABLES && EXPERIMENTAL
+ depends on EXPERIMENTAL
depends on NETFILTER_ADVANCED
default IP_SCTP
help
@@ -745,9 +770,23 @@ config NETFILTER_XT_MATCH_SCTP
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+config NETFILTER_XT_MATCH_SOCKET
+ tristate '"socket" match support (EXPERIMENTAL)'
+ depends on EXPERIMENTAL
+ depends on NETFILTER_TPROXY
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_ADVANCED
+ select NF_DEFRAG_IPV4
+ help
+ This option adds a `socket' match, which can be used to match
+ packets for which a TCP or UDP socket lookup finds a valid socket.
+ It can be used in combination with the MARK target and policy
+ routing to implement full featured non-locally bound sockets.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_STATE
tristate '"state" match support'
- depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
default m if NETFILTER_ADVANCED=n
help
@@ -759,7 +798,6 @@ config NETFILTER_XT_MATCH_STATE
config NETFILTER_XT_MATCH_STATISTIC
tristate '"statistic" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This option adds a `statistic' match, which allows you to match
@@ -769,7 +807,6 @@ config NETFILTER_XT_MATCH_STATISTIC
config NETFILTER_XT_MATCH_STRING
tristate '"string" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
select TEXTSEARCH
select TEXTSEARCH_KMP
@@ -783,7 +820,6 @@ config NETFILTER_XT_MATCH_STRING
config NETFILTER_XT_MATCH_TCPMSS
tristate '"tcpmss" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
help
This option adds a `tcpmss' match, which allows you to examine the
@@ -794,7 +830,6 @@ config NETFILTER_XT_MATCH_TCPMSS
config NETFILTER_XT_MATCH_TIME
tristate '"time" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
---help---
This option adds a "time" match, which allows you to match based on
@@ -809,7 +844,6 @@ config NETFILTER_XT_MATCH_TIME
config NETFILTER_XT_MATCH_U32
tristate '"u32" match support'
- depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
---help---
u32 allows you to extract quantities of up to 4 bytes from a packet,
@@ -821,20 +855,6 @@ config NETFILTER_XT_MATCH_U32
Details and examples are in the kernel module source.
-config NETFILTER_XT_MATCH_HASHLIMIT
- tristate '"hashlimit" match support'
- depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
- depends on NETFILTER_ADVANCED
- help
- This option adds a `hashlimit' match.
-
- As opposed to `limit', this match dynamically creates a hash table
- of limit buckets, based on your selection of source/destination
- addresses and/or ports.
-
- It enables you to express policies like `10kpps for any given
- destination address' or `500pps from any given source address'
- with a single rule.
+endif # NETFILTER_XTABLES
endmenu
-
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 3bd2cc556aea..8ce67665882d 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -34,6 +34,9 @@ obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o
obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
+# transparent proxy support
+obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o
+
# generic X tables
obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
@@ -48,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o
obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o
obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
@@ -76,7 +80,9 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
obj-$(CONFIG_NETFILTER_XT_MATCH_RATEEST) += xt_rateest.o
obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) += xt_recent.o
obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 292fa28146fb..a90ac83c5918 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -26,7 +26,7 @@
static DEFINE_MUTEX(afinfo_mutex);
-const struct nf_afinfo *nf_afinfo[NPROTO] __read_mostly;
+const struct nf_afinfo *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
EXPORT_SYMBOL(nf_afinfo);
int nf_register_afinfo(const struct nf_afinfo *afinfo)
@@ -51,7 +51,7 @@ void nf_unregister_afinfo(const struct nf_afinfo *afinfo)
}
EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
-struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly;
+struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;
EXPORT_SYMBOL(nf_hooks);
static DEFINE_MUTEX(nf_hook_mutex);
@@ -113,7 +113,7 @@ EXPORT_SYMBOL(nf_unregister_hooks);
unsigned int nf_iterate(struct list_head *head,
struct sk_buff *skb,
- int hook,
+ unsigned int hook,
const struct net_device *indev,
const struct net_device *outdev,
struct list_head **i,
@@ -155,7 +155,7 @@ unsigned int nf_iterate(struct list_head *head,
/* Returns 1 if okfn() needs to be executed by the caller,
* -EPERM for NF_DROP, 0 otherwise. */
-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
+int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *),
@@ -165,14 +165,6 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
unsigned int verdict;
int ret = 0;
-#ifdef CONFIG_NET_NS
- struct net *net;
-
- net = indev == NULL ? dev_net(outdev) : dev_net(indev);
- if (net != &init_net)
- return 1;
-#endif
-
/* We may already have this, but read-locks nest anyway */
rcu_read_lock();
@@ -264,7 +256,7 @@ EXPORT_SYMBOL(proc_net_netfilter);
void __init netfilter_init(void)
{
int i, h;
- for (i = 0; i < NPROTO; i++) {
+ for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
for (h = 0; h < NF_MAX_HOOKS; h++)
INIT_LIST_HEAD(&nf_hooks[i][h]);
}
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index 59bd8b903a19..03591d37b9cc 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -22,19 +22,17 @@
#define NF_CT_ACCT_DEFAULT 0
#endif
-int nf_ct_acct __read_mostly = NF_CT_ACCT_DEFAULT;
-EXPORT_SYMBOL_GPL(nf_ct_acct);
+static int nf_ct_acct __read_mostly = NF_CT_ACCT_DEFAULT;
module_param_named(acct, nf_ct_acct, bool, 0644);
MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");
#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *acct_sysctl_header;
static struct ctl_table acct_sysctl_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "nf_conntrack_acct",
- .data = &nf_ct_acct,
+ .data = &init_net.ct.sysctl_acct,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec,
@@ -64,41 +62,87 @@ static struct nf_ct_ext_type acct_extend __read_mostly = {
.id = NF_CT_EXT_ACCT,
};
-int nf_conntrack_acct_init(void)
+#ifdef CONFIG_SYSCTL
+static int nf_conntrack_acct_init_sysctl(struct net *net)
{
- int ret;
+ struct ctl_table *table;
-#ifdef CONFIG_NF_CT_ACCT
- printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Plase use\n");
- printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
- printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
-#endif
+ table = kmemdup(acct_sysctl_table, sizeof(acct_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ goto out;
+
+ table[0].data = &net->ct.sysctl_acct;
- ret = nf_ct_extend_register(&acct_extend);
- if (ret < 0) {
- printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
- return ret;
+ net->ct.acct_sysctl_header = register_net_sysctl_table(net,
+ nf_net_netfilter_sysctl_path, table);
+ if (!net->ct.acct_sysctl_header) {
+ printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
+ goto out_register;
}
+ return 0;
-#ifdef CONFIG_SYSCTL
- acct_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
- acct_sysctl_table);
+out_register:
+ kfree(table);
+out:
+ return -ENOMEM;
+}
- if (!acct_sysctl_header) {
- nf_ct_extend_unregister(&acct_extend);
+static void nf_conntrack_acct_fini_sysctl(struct net *net)
+{
+ struct ctl_table *table;
- printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
- return -ENOMEM;
- }
+ table = net->ct.acct_sysctl_header->ctl_table_arg;
+ unregister_net_sysctl_table(net->ct.acct_sysctl_header);
+ kfree(table);
+}
+#else
+static int nf_conntrack_acct_init_sysctl(struct net *net)
+{
+ return 0;
+}
+
+static void nf_conntrack_acct_fini_sysctl(struct net *net)
+{
+}
+#endif
+
+int nf_conntrack_acct_init(struct net *net)
+{
+ int ret;
+
+ net->ct.sysctl_acct = nf_ct_acct;
+
+ if (net_eq(net, &init_net)) {
+#ifdef CONFIG_NF_CT_ACCT
+ printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Plase use\n");
+ printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
+ printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
#endif
+ ret = nf_ct_extend_register(&acct_extend);
+ if (ret < 0) {
+ printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
+ goto out_extend_register;
+ }
+ }
+
+ ret = nf_conntrack_acct_init_sysctl(net);
+ if (ret < 0)
+ goto out_sysctl;
+
return 0;
+
+out_sysctl:
+ if (net_eq(net, &init_net))
+ nf_ct_extend_unregister(&acct_extend);
+out_extend_register:
+ return ret;
}
-void nf_conntrack_acct_fini(void)
+void nf_conntrack_acct_fini(struct net *net)
{
-#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(acct_sysctl_header);
-#endif
- nf_ct_extend_unregister(&acct_extend);
+ nf_conntrack_acct_fini_sysctl(net);
+ if (net_eq(net, &init_net))
+ nf_ct_extend_unregister(&acct_extend);
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 9d1830da8e84..27de3c7b006e 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -44,30 +44,17 @@
DEFINE_SPINLOCK(nf_conntrack_lock);
EXPORT_SYMBOL_GPL(nf_conntrack_lock);
-/* nf_conntrack_standalone needs this */
-atomic_t nf_conntrack_count = ATOMIC_INIT(0);
-EXPORT_SYMBOL_GPL(nf_conntrack_count);
-
unsigned int nf_conntrack_htable_size __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
int nf_conntrack_max __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_max);
-struct hlist_head *nf_conntrack_hash __read_mostly;
-EXPORT_SYMBOL_GPL(nf_conntrack_hash);
-
struct nf_conn nf_conntrack_untracked __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_untracked);
-unsigned int nf_ct_log_invalid __read_mostly;
-HLIST_HEAD(unconfirmed);
-static int nf_conntrack_vmalloc __read_mostly;
static struct kmem_cache *nf_conntrack_cachep __read_mostly;
-DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
-EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat);
-
static int nf_conntrack_hash_rnd_initted;
static unsigned int nf_conntrack_hash_rnd;
@@ -180,6 +167,7 @@ static void
destroy_conntrack(struct nf_conntrack *nfct)
{
struct nf_conn *ct = (struct nf_conn *)nfct;
+ struct net *net = nf_ct_net(ct);
struct nf_conntrack_l4proto *l4proto;
pr_debug("destroy_conntrack(%p)\n", ct);
@@ -212,7 +200,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
}
- NF_CT_STAT_INC(delete);
+ NF_CT_STAT_INC(net, delete);
spin_unlock_bh(&nf_conntrack_lock);
if (ct->master)
@@ -225,6 +213,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
static void death_by_timeout(unsigned long ul_conntrack)
{
struct nf_conn *ct = (void *)ul_conntrack;
+ struct net *net = nf_ct_net(ct);
struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_helper *helper;
@@ -239,14 +228,14 @@ static void death_by_timeout(unsigned long ul_conntrack)
spin_lock_bh(&nf_conntrack_lock);
/* Inside lock so preempt is disabled on module removal path.
* Otherwise we can get spurious warnings. */
- NF_CT_STAT_INC(delete_list);
+ NF_CT_STAT_INC(net, delete_list);
clean_from_lists(ct);
spin_unlock_bh(&nf_conntrack_lock);
nf_ct_put(ct);
}
struct nf_conntrack_tuple_hash *
-__nf_conntrack_find(const struct nf_conntrack_tuple *tuple)
+__nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_tuple_hash *h;
struct hlist_node *n;
@@ -256,13 +245,13 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple)
* at least once for the stats anyway.
*/
local_bh_disable();
- hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnode) {
+ hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) {
if (nf_ct_tuple_equal(tuple, &h->tuple)) {
- NF_CT_STAT_INC(found);
+ NF_CT_STAT_INC(net, found);
local_bh_enable();
return h;
}
- NF_CT_STAT_INC(searched);
+ NF_CT_STAT_INC(net, searched);
}
local_bh_enable();
@@ -272,13 +261,13 @@ EXPORT_SYMBOL_GPL(__nf_conntrack_find);
/* Find a connection corresponding to a tuple. */
struct nf_conntrack_tuple_hash *
-nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple)
+nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_tuple_hash *h;
struct nf_conn *ct;
rcu_read_lock();
- h = __nf_conntrack_find(tuple);
+ h = __nf_conntrack_find(net, tuple);
if (h) {
ct = nf_ct_tuplehash_to_ctrack(h);
if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use)))
@@ -294,10 +283,12 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct,
unsigned int hash,
unsigned int repl_hash)
{
+ struct net *net = nf_ct_net(ct);
+
hlist_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
- &nf_conntrack_hash[hash]);
+ &net->ct.hash[hash]);
hlist_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnode,
- &nf_conntrack_hash[repl_hash]);
+ &net->ct.hash[repl_hash]);
}
void nf_conntrack_hash_insert(struct nf_conn *ct)
@@ -323,8 +314,10 @@ __nf_conntrack_confirm(struct sk_buff *skb)
struct nf_conn_help *help;
struct hlist_node *n;
enum ip_conntrack_info ctinfo;
+ struct net *net;
ct = nf_ct_get(skb, &ctinfo);
+ net = nf_ct_net(ct);
/* ipt_REJECT uses nf_conntrack_attach to attach related
ICMP/TCP RST packets in other direction. Actual packet
@@ -351,11 +344,11 @@ __nf_conntrack_confirm(struct sk_buff *skb)
/* See if there's one in the list already, including reverse:
NAT could have grabbed it without realizing, since we're
not in the hash. If there is, we lost race. */
- hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode)
+ hlist_for_each_entry(h, n, &net->ct.hash[hash], hnode)
if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
&h->tuple))
goto out;
- hlist_for_each_entry(h, n, &nf_conntrack_hash[repl_hash], hnode)
+ hlist_for_each_entry(h, n, &net->ct.hash[repl_hash], hnode)
if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
&h->tuple))
goto out;
@@ -371,22 +364,22 @@ __nf_conntrack_confirm(struct sk_buff *skb)
add_timer(&ct->timeout);
atomic_inc(&ct->ct_general.use);
set_bit(IPS_CONFIRMED_BIT, &ct->status);
- NF_CT_STAT_INC(insert);
+ NF_CT_STAT_INC(net, insert);
spin_unlock_bh(&nf_conntrack_lock);
help = nfct_help(ct);
if (help && help->helper)
- nf_conntrack_event_cache(IPCT_HELPER, skb);
+ nf_conntrack_event_cache(IPCT_HELPER, ct);
#ifdef CONFIG_NF_NAT_NEEDED
if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
- nf_conntrack_event_cache(IPCT_NATINFO, skb);
+ nf_conntrack_event_cache(IPCT_NATINFO, ct);
#endif
nf_conntrack_event_cache(master_ct(ct) ?
- IPCT_RELATED : IPCT_NEW, skb);
+ IPCT_RELATED : IPCT_NEW, ct);
return NF_ACCEPT;
out:
- NF_CT_STAT_INC(insert_failed);
+ NF_CT_STAT_INC(net, insert_failed);
spin_unlock_bh(&nf_conntrack_lock);
return NF_DROP;
}
@@ -398,6 +391,7 @@ int
nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack)
{
+ struct net *net = nf_ct_net(ignored_conntrack);
struct nf_conntrack_tuple_hash *h;
struct hlist_node *n;
unsigned int hash = hash_conntrack(tuple);
@@ -406,14 +400,14 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
* least once for the stats anyway.
*/
rcu_read_lock_bh();
- hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnode) {
+ hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) {
if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
nf_ct_tuple_equal(tuple, &h->tuple)) {
- NF_CT_STAT_INC(found);
+ NF_CT_STAT_INC(net, found);
rcu_read_unlock_bh();
return 1;
}
- NF_CT_STAT_INC(searched);
+ NF_CT_STAT_INC(net, searched);
}
rcu_read_unlock_bh();
@@ -425,7 +419,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken);
/* There's a small race here where we may free a just-assured
connection. Too bad: we're in trouble anyway. */
-static noinline int early_drop(unsigned int hash)
+static noinline int early_drop(struct net *net, unsigned int hash)
{
/* Use oldest entry, which is roughly LRU */
struct nf_conntrack_tuple_hash *h;
@@ -436,7 +430,7 @@ static noinline int early_drop(unsigned int hash)
rcu_read_lock();
for (i = 0; i < nf_conntrack_htable_size; i++) {
- hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash],
+ hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash],
hnode) {
tmp = nf_ct_tuplehash_to_ctrack(h);
if (!test_bit(IPS_ASSURED_BIT, &tmp->status))
@@ -458,13 +452,14 @@ static noinline int early_drop(unsigned int hash)
if (del_timer(&ct->timeout)) {
death_by_timeout((unsigned long)ct);
dropped = 1;
- NF_CT_STAT_INC_ATOMIC(early_drop);
+ NF_CT_STAT_INC_ATOMIC(net, early_drop);
}
nf_ct_put(ct);
return dropped;
}
-struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
+struct nf_conn *nf_conntrack_alloc(struct net *net,
+ const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_tuple *repl,
gfp_t gfp)
{
@@ -476,13 +471,13 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
}
/* We don't want any race condition at early drop stage */
- atomic_inc(&nf_conntrack_count);
+ atomic_inc(&net->ct.count);
if (nf_conntrack_max &&
- unlikely(atomic_read(&nf_conntrack_count) > nf_conntrack_max)) {
+ unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) {
unsigned int hash = hash_conntrack(orig);
- if (!early_drop(hash)) {
- atomic_dec(&nf_conntrack_count);
+ if (!early_drop(net, hash)) {
+ atomic_dec(&net->ct.count);
if (net_ratelimit())
printk(KERN_WARNING
"nf_conntrack: table full, dropping"
@@ -494,7 +489,7 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
ct = kmem_cache_zalloc(nf_conntrack_cachep, gfp);
if (ct == NULL) {
pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
- atomic_dec(&nf_conntrack_count);
+ atomic_dec(&net->ct.count);
return ERR_PTR(-ENOMEM);
}
@@ -503,6 +498,9 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
/* Don't set timer yet: wait for confirmation */
setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct);
+#ifdef CONFIG_NET_NS
+ ct->ct_net = net;
+#endif
INIT_RCU_HEAD(&ct->rcu);
return ct;
@@ -512,10 +510,11 @@ EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
static void nf_conntrack_free_rcu(struct rcu_head *head)
{
struct nf_conn *ct = container_of(head, struct nf_conn, rcu);
+ struct net *net = nf_ct_net(ct);
nf_ct_ext_free(ct);
kmem_cache_free(nf_conntrack_cachep, ct);
- atomic_dec(&nf_conntrack_count);
+ atomic_dec(&net->ct.count);
}
void nf_conntrack_free(struct nf_conn *ct)
@@ -528,7 +527,8 @@ EXPORT_SYMBOL_GPL(nf_conntrack_free);
/* Allocate a new conntrack: we return -ENOMEM if classification
failed due to stress. Otherwise it really is unclassifiable. */
static struct nf_conntrack_tuple_hash *
-init_conntrack(const struct nf_conntrack_tuple *tuple,
+init_conntrack(struct net *net,
+ const struct nf_conntrack_tuple *tuple,
struct nf_conntrack_l3proto *l3proto,
struct nf_conntrack_l4proto *l4proto,
struct sk_buff *skb,
@@ -544,7 +544,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
return NULL;
}
- ct = nf_conntrack_alloc(tuple, &repl_tuple, GFP_ATOMIC);
+ ct = nf_conntrack_alloc(net, tuple, &repl_tuple, GFP_ATOMIC);
if (ct == NULL || IS_ERR(ct)) {
pr_debug("Can't allocate conntrack.\n");
return (struct nf_conntrack_tuple_hash *)ct;
@@ -559,7 +559,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
spin_lock_bh(&nf_conntrack_lock);
- exp = nf_ct_find_expectation(tuple);
+ exp = nf_ct_find_expectation(net, tuple);
if (exp) {
pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
ct, exp);
@@ -579,7 +579,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
ct->secmark = exp->master->secmark;
#endif
nf_conntrack_get(&ct->master->ct_general);
- NF_CT_STAT_INC(expect_new);
+ NF_CT_STAT_INC(net, expect_new);
} else {
struct nf_conntrack_helper *helper;
@@ -589,11 +589,12 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
if (help)
rcu_assign_pointer(help->helper, helper);
}
- NF_CT_STAT_INC(new);
+ NF_CT_STAT_INC(net, new);
}
/* Overload tuple linked list to put us in unconfirmed list. */
- hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, &unconfirmed);
+ hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
+ &net->ct.unconfirmed);
spin_unlock_bh(&nf_conntrack_lock);
@@ -608,7 +609,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
/* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
static inline struct nf_conn *
-resolve_normal_ct(struct sk_buff *skb,
+resolve_normal_ct(struct net *net,
+ struct sk_buff *skb,
unsigned int dataoff,
u_int16_t l3num,
u_int8_t protonum,
@@ -629,9 +631,9 @@ resolve_normal_ct(struct sk_buff *skb,
}
/* look for tuple match */
- h = nf_conntrack_find_get(&tuple);
+ h = nf_conntrack_find_get(net, &tuple);
if (!h) {
- h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff);
+ h = init_conntrack(net, &tuple, l3proto, l4proto, skb, dataoff);
if (!h)
return NULL;
if (IS_ERR(h))
@@ -665,7 +667,8 @@ resolve_normal_ct(struct sk_buff *skb,
}
unsigned int
-nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb)
+nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
+ struct sk_buff *skb)
{
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
@@ -678,44 +681,46 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb)
/* Previously seen (loopback or untracked)? Ignore. */
if (skb->nfct) {
- NF_CT_STAT_INC_ATOMIC(ignore);
+ NF_CT_STAT_INC_ATOMIC(net, ignore);
return NF_ACCEPT;
}
/* rcu_read_lock()ed by nf_hook_slow */
- l3proto = __nf_ct_l3proto_find((u_int16_t)pf);
+ l3proto = __nf_ct_l3proto_find(pf);
ret = l3proto->get_l4proto(skb, skb_network_offset(skb),
&dataoff, &protonum);
if (ret <= 0) {
pr_debug("not prepared to track yet or error occured\n");
- NF_CT_STAT_INC_ATOMIC(error);
- NF_CT_STAT_INC_ATOMIC(invalid);
+ NF_CT_STAT_INC_ATOMIC(net, error);
+ NF_CT_STAT_INC_ATOMIC(net, invalid);
return -ret;
}
- l4proto = __nf_ct_l4proto_find((u_int16_t)pf, protonum);
+ l4proto = __nf_ct_l4proto_find(pf, protonum);
/* It may be an special packet, error, unclean...
* inverse of the return code tells to the netfilter
* core what to do with the packet. */
- if (l4proto->error != NULL &&
- (ret = l4proto->error(skb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
- NF_CT_STAT_INC_ATOMIC(error);
- NF_CT_STAT_INC_ATOMIC(invalid);
- return -ret;
+ if (l4proto->error != NULL) {
+ ret = l4proto->error(net, skb, dataoff, &ctinfo, pf, hooknum);
+ if (ret <= 0) {
+ NF_CT_STAT_INC_ATOMIC(net, error);
+ NF_CT_STAT_INC_ATOMIC(net, invalid);
+ return -ret;
+ }
}
- ct = resolve_normal_ct(skb, dataoff, pf, protonum, l3proto, l4proto,
- &set_reply, &ctinfo);
+ ct = resolve_normal_ct(net, skb, dataoff, pf, protonum,
+ l3proto, l4proto, &set_reply, &ctinfo);
if (!ct) {
/* Not valid part of a connection */
- NF_CT_STAT_INC_ATOMIC(invalid);
+ NF_CT_STAT_INC_ATOMIC(net, invalid);
return NF_ACCEPT;
}
if (IS_ERR(ct)) {
/* Too stressed to deal. */
- NF_CT_STAT_INC_ATOMIC(drop);
+ NF_CT_STAT_INC_ATOMIC(net, drop);
return NF_DROP;
}
@@ -728,12 +733,12 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb)
pr_debug("nf_conntrack_in: Can't track with proto module\n");
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
- NF_CT_STAT_INC_ATOMIC(invalid);
+ NF_CT_STAT_INC_ATOMIC(net, invalid);
return -ret;
}
if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
- nf_conntrack_event_cache(IPCT_STATUS, skb);
+ nf_conntrack_event_cache(IPCT_STATUS, ct);
return ret;
}
@@ -846,7 +851,7 @@ acct:
/* must be unlocked when calling event cache */
if (event)
- nf_conntrack_event_cache(event, skb);
+ nf_conntrack_event_cache(event, ct);
}
EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
@@ -938,7 +943,7 @@ static void nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
/* Bring out ya dead! */
static struct nf_conn *
-get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
+get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
void *data, unsigned int *bucket)
{
struct nf_conntrack_tuple_hash *h;
@@ -947,13 +952,13 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
spin_lock_bh(&nf_conntrack_lock);
for (; *bucket < nf_conntrack_htable_size; (*bucket)++) {
- hlist_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnode) {
+ hlist_for_each_entry(h, n, &net->ct.hash[*bucket], hnode) {
ct = nf_ct_tuplehash_to_ctrack(h);
if (iter(ct, data))
goto found;
}
}
- hlist_for_each_entry(h, n, &unconfirmed, hnode) {
+ hlist_for_each_entry(h, n, &net->ct.unconfirmed, hnode) {
ct = nf_ct_tuplehash_to_ctrack(h);
if (iter(ct, data))
set_bit(IPS_DYING_BIT, &ct->status);
@@ -966,13 +971,14 @@ found:
return ct;
}
-void
-nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), void *data)
+void nf_ct_iterate_cleanup(struct net *net,
+ int (*iter)(struct nf_conn *i, void *data),
+ void *data)
{
struct nf_conn *ct;
unsigned int bucket = 0;
- while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) {
+ while ((ct = get_next_corpse(net, iter, data, &bucket)) != NULL) {
/* Time to push up daises... */
if (del_timer(&ct->timeout))
death_by_timeout((unsigned long)ct);
@@ -998,27 +1004,26 @@ void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, unsigned int s
}
EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
-void nf_conntrack_flush(void)
+void nf_conntrack_flush(struct net *net)
{
- nf_ct_iterate_cleanup(kill_all, NULL);
+ nf_ct_iterate_cleanup(net, kill_all, NULL);
}
EXPORT_SYMBOL_GPL(nf_conntrack_flush);
-/* Mishearing the voices in his head, our hero wonders how he's
- supposed to kill the mall. */
-void nf_conntrack_cleanup(void)
+static void nf_conntrack_cleanup_init_net(void)
{
- rcu_assign_pointer(ip_ct_attach, NULL);
-
- /* This makes sure all current packets have passed through
- netfilter framework. Roll on, two-stage module
- delete... */
- synchronize_net();
+ nf_conntrack_helper_fini();
+ nf_conntrack_proto_fini();
+ kmem_cache_destroy(nf_conntrack_cachep);
+}
- nf_ct_event_cache_flush();
+static void nf_conntrack_cleanup_net(struct net *net)
+{
+ nf_ct_event_cache_flush(net);
+ nf_conntrack_ecache_fini(net);
i_see_dead_people:
- nf_conntrack_flush();
- if (atomic_read(&nf_conntrack_count) != 0) {
+ nf_conntrack_flush(net);
+ if (atomic_read(&net->ct.count) != 0) {
schedule();
goto i_see_dead_people;
}
@@ -1026,16 +1031,31 @@ void nf_conntrack_cleanup(void)
while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1)
schedule();
- rcu_assign_pointer(nf_ct_destroy, NULL);
-
- kmem_cache_destroy(nf_conntrack_cachep);
- nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
+ nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
nf_conntrack_htable_size);
+ nf_conntrack_acct_fini(net);
+ nf_conntrack_expect_fini(net);
+ free_percpu(net->ct.stat);
+}
- nf_conntrack_acct_fini();
- nf_conntrack_expect_fini();
- nf_conntrack_helper_fini();
- nf_conntrack_proto_fini();
+/* Mishearing the voices in his head, our hero wonders how he's
+ supposed to kill the mall. */
+void nf_conntrack_cleanup(struct net *net)
+{
+ if (net_eq(net, &init_net))
+ rcu_assign_pointer(ip_ct_attach, NULL);
+
+ /* This makes sure all current packets have passed through
+ netfilter framework. Roll on, two-stage module
+ delete... */
+ synchronize_net();
+
+ nf_conntrack_cleanup_net(net);
+
+ if (net_eq(net, &init_net)) {
+ rcu_assign_pointer(nf_ct_destroy, NULL);
+ nf_conntrack_cleanup_init_net();
+ }
}
struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced)
@@ -1094,8 +1114,8 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
*/
spin_lock_bh(&nf_conntrack_lock);
for (i = 0; i < nf_conntrack_htable_size; i++) {
- while (!hlist_empty(&nf_conntrack_hash[i])) {
- h = hlist_entry(nf_conntrack_hash[i].first,
+ while (!hlist_empty(&init_net.ct.hash[i])) {
+ h = hlist_entry(init_net.ct.hash[i].first,
struct nf_conntrack_tuple_hash, hnode);
hlist_del_rcu(&h->hnode);
bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
@@ -1103,12 +1123,12 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
}
}
old_size = nf_conntrack_htable_size;
- old_vmalloced = nf_conntrack_vmalloc;
- old_hash = nf_conntrack_hash;
+ old_vmalloced = init_net.ct.hash_vmalloc;
+ old_hash = init_net.ct.hash;
nf_conntrack_htable_size = hashsize;
- nf_conntrack_vmalloc = vmalloced;
- nf_conntrack_hash = hash;
+ init_net.ct.hash_vmalloc = vmalloced;
+ init_net.ct.hash = hash;
nf_conntrack_hash_rnd = rnd;
spin_unlock_bh(&nf_conntrack_lock);
@@ -1120,7 +1140,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize);
module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint,
&nf_conntrack_htable_size, 0600);
-int __init nf_conntrack_init(void)
+static int nf_conntrack_init_init_net(void)
{
int max_factor = 8;
int ret;
@@ -1142,13 +1162,6 @@ int __init nf_conntrack_init(void)
* entries. */
max_factor = 4;
}
- nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
- &nf_conntrack_vmalloc);
- if (!nf_conntrack_hash) {
- printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
- goto err_out;
- }
-
nf_conntrack_max = max_factor * nf_conntrack_htable_size;
printk("nf_conntrack version %s (%u buckets, %d max)\n",
@@ -1160,48 +1173,103 @@ int __init nf_conntrack_init(void)
0, 0, NULL);
if (!nf_conntrack_cachep) {
printk(KERN_ERR "Unable to create nf_conn slab cache\n");
- goto err_free_hash;
+ ret = -ENOMEM;
+ goto err_cache;
}
ret = nf_conntrack_proto_init();
if (ret < 0)
- goto err_free_conntrack_slab;
-
- ret = nf_conntrack_expect_init();
- if (ret < 0)
- goto out_fini_proto;
+ goto err_proto;
ret = nf_conntrack_helper_init();
if (ret < 0)
- goto out_fini_expect;
+ goto err_helper;
- ret = nf_conntrack_acct_init();
- if (ret < 0)
- goto out_fini_helper;
+ return 0;
- /* For use by REJECT target */
- rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
- rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
+err_helper:
+ nf_conntrack_proto_fini();
+err_proto:
+ kmem_cache_destroy(nf_conntrack_cachep);
+err_cache:
+ return ret;
+}
+
+static int nf_conntrack_init_net(struct net *net)
+{
+ int ret;
+
+ atomic_set(&net->ct.count, 0);
+ INIT_HLIST_HEAD(&net->ct.unconfirmed);
+ net->ct.stat = alloc_percpu(struct ip_conntrack_stat);
+ if (!net->ct.stat) {
+ ret = -ENOMEM;
+ goto err_stat;
+ }
+ ret = nf_conntrack_ecache_init(net);
+ if (ret < 0)
+ goto err_ecache;
+ net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
+ &net->ct.hash_vmalloc);
+ if (!net->ct.hash) {
+ ret = -ENOMEM;
+ printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
+ goto err_hash;
+ }
+ ret = nf_conntrack_expect_init(net);
+ if (ret < 0)
+ goto err_expect;
+ ret = nf_conntrack_acct_init(net);
+ if (ret < 0)
+ goto err_acct;
/* Set up fake conntrack:
- to never be deleted, not in any hashes */
+#ifdef CONFIG_NET_NS
+ nf_conntrack_untracked.ct_net = &init_net;
+#endif
atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
/* - and look it like as a confirmed connection */
set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);
- return ret;
+ return 0;
-out_fini_helper:
- nf_conntrack_helper_fini();
-out_fini_expect:
- nf_conntrack_expect_fini();
-out_fini_proto:
- nf_conntrack_proto_fini();
-err_free_conntrack_slab:
- kmem_cache_destroy(nf_conntrack_cachep);
-err_free_hash:
- nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
+err_acct:
+ nf_conntrack_expect_fini(net);
+err_expect:
+ nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
nf_conntrack_htable_size);
-err_out:
- return -ENOMEM;
+err_hash:
+ nf_conntrack_ecache_fini(net);
+err_ecache:
+ free_percpu(net->ct.stat);
+err_stat:
+ return ret;
+}
+
+int nf_conntrack_init(struct net *net)
+{
+ int ret;
+
+ if (net_eq(net, &init_net)) {
+ ret = nf_conntrack_init_init_net();
+ if (ret < 0)
+ goto out_init_net;
+ }
+ ret = nf_conntrack_init_net(net);
+ if (ret < 0)
+ goto out_net;
+
+ if (net_eq(net, &init_net)) {
+ /* For use by REJECT target */
+ rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
+ rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
+ }
+ return 0;
+
+out_net:
+ if (net_eq(net, &init_net))
+ nf_conntrack_cleanup_init_net();
+out_init_net:
+ return ret;
}
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 83c41ac3505b..a5f5e2e65d13 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -29,9 +29,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_chain);
ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain);
EXPORT_SYMBOL_GPL(nf_ct_expect_chain);
-DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
-EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
-
/* deliver cached events and clear cache entry - must be called with locally
* disabled softirqs */
static inline void
@@ -51,10 +48,11 @@ __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
* by code prior to async packet handling for freeing the skb */
void nf_ct_deliver_cached_events(const struct nf_conn *ct)
{
+ struct net *net = nf_ct_net(ct);
struct nf_conntrack_ecache *ecache;
local_bh_disable();
- ecache = &__get_cpu_var(nf_conntrack_ecache);
+ ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id());
if (ecache->ct == ct)
__nf_ct_deliver_cached_events(ecache);
local_bh_enable();
@@ -64,10 +62,11 @@ EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
/* Deliver cached events for old pending events, if current conntrack != old */
void __nf_ct_event_cache_init(struct nf_conn *ct)
{
+ struct net *net = nf_ct_net(ct);
struct nf_conntrack_ecache *ecache;
/* take care of delivering potentially old events */
- ecache = &__get_cpu_var(nf_conntrack_ecache);
+ ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id());
BUG_ON(ecache->ct == ct);
if (ecache->ct)
__nf_ct_deliver_cached_events(ecache);
@@ -79,18 +78,31 @@ EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init);
/* flush the event cache - touches other CPU's data and must not be called
* while packets are still passing through the code */
-void nf_ct_event_cache_flush(void)
+void nf_ct_event_cache_flush(struct net *net)
{
struct nf_conntrack_ecache *ecache;
int cpu;
for_each_possible_cpu(cpu) {
- ecache = &per_cpu(nf_conntrack_ecache, cpu);
+ ecache = per_cpu_ptr(net->ct.ecache, cpu);
if (ecache->ct)
nf_ct_put(ecache->ct);
}
}
+int nf_conntrack_ecache_init(struct net *net)
+{
+ net->ct.ecache = alloc_percpu(struct nf_conntrack_ecache);
+ if (!net->ct.ecache)
+ return -ENOMEM;
+ return 0;
+}
+
+void nf_conntrack_ecache_fini(struct net *net)
+{
+ free_percpu(net->ct.ecache);
+}
+
int nf_conntrack_register_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index e8f0dead267f..37a703bc3b8e 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -28,17 +28,12 @@
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_tuple.h>
-struct hlist_head *nf_ct_expect_hash __read_mostly;
-EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
-
unsigned int nf_ct_expect_hsize __read_mostly;
EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
static unsigned int nf_ct_expect_hash_rnd __read_mostly;
-static unsigned int nf_ct_expect_count;
unsigned int nf_ct_expect_max __read_mostly;
static int nf_ct_expect_hash_rnd_initted __read_mostly;
-static int nf_ct_expect_vmalloc;
static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
@@ -46,18 +41,19 @@ static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
{
struct nf_conn_help *master_help = nfct_help(exp->master);
+ struct net *net = nf_ct_exp_net(exp);
NF_CT_ASSERT(master_help);
NF_CT_ASSERT(!timer_pending(&exp->timeout));
hlist_del_rcu(&exp->hnode);
- nf_ct_expect_count--;
+ net->ct.expect_count--;
hlist_del(&exp->lnode);
master_help->expecting[exp->class]--;
nf_ct_expect_put(exp);
- NF_CT_STAT_INC(expect_delete);
+ NF_CT_STAT_INC(net, expect_delete);
}
EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);
@@ -87,17 +83,17 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple
}
struct nf_conntrack_expect *
-__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple)
+__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *i;
struct hlist_node *n;
unsigned int h;
- if (!nf_ct_expect_count)
+ if (!net->ct.expect_count)
return NULL;
h = nf_ct_expect_dst_hash(tuple);
- hlist_for_each_entry_rcu(i, n, &nf_ct_expect_hash[h], hnode) {
+ hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) {
if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
return i;
}
@@ -107,12 +103,12 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
/* Just find a expectation corresponding to a tuple. */
struct nf_conntrack_expect *
-nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple)
+nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *i;
rcu_read_lock();
- i = __nf_ct_expect_find(tuple);
+ i = __nf_ct_expect_find(net, tuple);
if (i && !atomic_inc_not_zero(&i->use))
i = NULL;
rcu_read_unlock();
@@ -124,17 +120,17 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
/* If an expectation for this connection is found, it gets delete from
* global list then returned. */
struct nf_conntrack_expect *
-nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
+nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *i, *exp = NULL;
struct hlist_node *n;
unsigned int h;
- if (!nf_ct_expect_count)
+ if (!net->ct.expect_count)
return NULL;
h = nf_ct_expect_dst_hash(tuple);
- hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
+ hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
exp = i;
@@ -241,7 +237,7 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
- int family,
+ u_int8_t family,
const union nf_inet_addr *saddr,
const union nf_inet_addr *daddr,
u_int8_t proto, const __be16 *src, const __be16 *dst)
@@ -311,6 +307,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_put);
static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
{
struct nf_conn_help *master_help = nfct_help(exp->master);
+ struct net *net = nf_ct_exp_net(exp);
const struct nf_conntrack_expect_policy *p;
unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
@@ -319,8 +316,8 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
hlist_add_head(&exp->lnode, &master_help->expectations);
master_help->expecting[exp->class]++;
- hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]);
- nf_ct_expect_count++;
+ hlist_add_head_rcu(&exp->hnode, &net->ct.expect_hash[h]);
+ net->ct.expect_count++;
setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
(unsigned long)exp);
@@ -329,7 +326,7 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
add_timer(&exp->timeout);
atomic_inc(&exp->use);
- NF_CT_STAT_INC(expect_create);
+ NF_CT_STAT_INC(net, expect_create);
}
/* Race with expectations being used means we could have none to find; OK. */
@@ -371,6 +368,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
struct nf_conntrack_expect *i;
struct nf_conn *master = expect->master;
struct nf_conn_help *master_help = nfct_help(master);
+ struct net *net = nf_ct_exp_net(expect);
struct hlist_node *n;
unsigned int h;
int ret;
@@ -383,7 +381,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
goto out;
}
h = nf_ct_expect_dst_hash(&expect->tuple);
- hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
+ hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
if (expect_matches(i, expect)) {
/* Refresh timer: if it's dying, ignore.. */
if (refresh_timer(i)) {
@@ -406,7 +404,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
}
}
- if (nf_ct_expect_count >= nf_ct_expect_max) {
+ if (net->ct.expect_count >= nf_ct_expect_max) {
if (net_ratelimit())
printk(KERN_WARNING
"nf_conntrack: expectation table full\n");
@@ -425,16 +423,18 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_related);
#ifdef CONFIG_PROC_FS
struct ct_expect_iter_state {
+ struct seq_net_private p;
unsigned int bucket;
};
static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
{
+ struct net *net = seq_file_net(seq);
struct ct_expect_iter_state *st = seq->private;
struct hlist_node *n;
for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
- n = rcu_dereference(nf_ct_expect_hash[st->bucket].first);
+ n = rcu_dereference(net->ct.expect_hash[st->bucket].first);
if (n)
return n;
}
@@ -444,13 +444,14 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
struct hlist_node *head)
{
+ struct net *net = seq_file_net(seq);
struct ct_expect_iter_state *st = seq->private;
head = rcu_dereference(head->next);
while (head == NULL) {
if (++st->bucket >= nf_ct_expect_hsize)
return NULL;
- head = rcu_dereference(nf_ct_expect_hash[st->bucket].first);
+ head = rcu_dereference(net->ct.expect_hash[st->bucket].first);
}
return head;
}
@@ -524,7 +525,7 @@ static const struct seq_operations exp_seq_ops = {
static int exp_open(struct inode *inode, struct file *file)
{
- return seq_open_private(file, &exp_seq_ops,
+ return seq_open_net(inode, file, &exp_seq_ops,
sizeof(struct ct_expect_iter_state));
}
@@ -533,72 +534,79 @@ static const struct file_operations exp_file_ops = {
.open = exp_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release_private,
+ .release = seq_release_net,
};
#endif /* CONFIG_PROC_FS */
-static int __init exp_proc_init(void)
+static int exp_proc_init(struct net *net)
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
- proc = proc_net_fops_create(&init_net, "nf_conntrack_expect", 0440, &exp_file_ops);
+ proc = proc_net_fops_create(net, "nf_conntrack_expect", 0440, &exp_file_ops);
if (!proc)
return -ENOMEM;
#endif /* CONFIG_PROC_FS */
return 0;
}
-static void exp_proc_remove(void)
+static void exp_proc_remove(struct net *net)
{
#ifdef CONFIG_PROC_FS
- proc_net_remove(&init_net, "nf_conntrack_expect");
+ proc_net_remove(net, "nf_conntrack_expect");
#endif /* CONFIG_PROC_FS */
}
module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
-int __init nf_conntrack_expect_init(void)
+int nf_conntrack_expect_init(struct net *net)
{
int err = -ENOMEM;
- if (!nf_ct_expect_hsize) {
- nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
- if (!nf_ct_expect_hsize)
- nf_ct_expect_hsize = 1;
+ if (net_eq(net, &init_net)) {
+ if (!nf_ct_expect_hsize) {
+ nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
+ if (!nf_ct_expect_hsize)
+ nf_ct_expect_hsize = 1;
+ }
+ nf_ct_expect_max = nf_ct_expect_hsize * 4;
}
- nf_ct_expect_max = nf_ct_expect_hsize * 4;
- nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
- &nf_ct_expect_vmalloc);
- if (nf_ct_expect_hash == NULL)
+ net->ct.expect_count = 0;
+ net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
+ &net->ct.expect_vmalloc);
+ if (net->ct.expect_hash == NULL)
goto err1;
- nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
+ if (net_eq(net, &init_net)) {
+ nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
sizeof(struct nf_conntrack_expect),
0, 0, NULL);
- if (!nf_ct_expect_cachep)
- goto err2;
+ if (!nf_ct_expect_cachep)
+ goto err2;
+ }
- err = exp_proc_init();
+ err = exp_proc_init(net);
if (err < 0)
goto err3;
return 0;
err3:
- kmem_cache_destroy(nf_ct_expect_cachep);
+ if (net_eq(net, &init_net))
+ kmem_cache_destroy(nf_ct_expect_cachep);
err2:
- nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
+ nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
nf_ct_expect_hsize);
err1:
return err;
}
-void nf_conntrack_expect_fini(void)
+void nf_conntrack_expect_fini(struct net *net)
{
- exp_proc_remove();
- kmem_cache_destroy(nf_ct_expect_cachep);
- nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
+ exp_proc_remove(net);
+ if (net_eq(net, &init_net))
+ kmem_cache_destroy(nf_ct_expect_cachep);
+ nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
nf_ct_expect_hsize);
}
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index bb20672fe036..4f7107107e99 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -318,7 +318,8 @@ static int find_nl_seq(u32 seq, const struct nf_ct_ftp_master *info, int dir)
}
/* We don't update if it's older than what we have. */
-static void update_nl_seq(u32 nl_seq, struct nf_ct_ftp_master *info, int dir,
+static void update_nl_seq(struct nf_conn *ct, u32 nl_seq,
+ struct nf_ct_ftp_master *info, int dir,
struct sk_buff *skb)
{
unsigned int i, oldest = NUM_SEQ_TO_REMEMBER;
@@ -336,11 +337,11 @@ static void update_nl_seq(u32 nl_seq, struct nf_ct_ftp_master *info, int dir,
if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) {
info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq;
- nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
+ nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, ct);
} else if (oldest != NUM_SEQ_TO_REMEMBER &&
after(nl_seq, info->seq_aft_nl[dir][oldest])) {
info->seq_aft_nl[dir][oldest] = nl_seq;
- nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
+ nf_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, ct);
}
}
@@ -509,7 +510,7 @@ out_update_nl:
/* Now if this ends in \n, update ftp info. Seq may have been
* adjusted by NAT code. */
if (ends_in_nl)
- update_nl_seq(seq, ct_ftp_info, dir, skb);
+ update_nl_seq(ct, seq, ct_ftp_info, dir, skb);
out:
spin_unlock_bh(&nf_ftp_lock);
return ret;
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 2f83c158934d..c1504f71cdff 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -709,7 +709,8 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
/* If the calling party is on the same side of the forward-to party,
* we don't need to track the second call */
static int callforward_do_filter(const union nf_inet_addr *src,
- const union nf_inet_addr *dst, int family)
+ const union nf_inet_addr *dst,
+ u_int8_t family)
{
const struct nf_afinfo *afinfo;
struct flowi fl1, fl2;
@@ -1209,6 +1210,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
union nf_inet_addr *addr,
__be16 port)
{
+ struct net *net = nf_ct_net(ct);
struct nf_conntrack_expect *exp;
struct nf_conntrack_tuple tuple;
@@ -1218,7 +1220,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
tuple.dst.u.tcp.port = port;
tuple.dst.protonum = IPPROTO_TCP;
- exp = __nf_ct_expect_find(&tuple);
+ exp = __nf_ct_expect_find(net, &tuple);
if (exp && exp->master == ct)
return exp;
return NULL;
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 8e0b4c8f62a8..9c06b9f86ad4 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -123,29 +123,18 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
}
EXPORT_SYMBOL_GPL(nf_conntrack_helper_register);
-void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
+static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me,
+ struct net *net)
{
struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_expect *exp;
const struct hlist_node *n, *next;
unsigned int i;
- mutex_lock(&nf_ct_helper_mutex);
- hlist_del_rcu(&me->hnode);
- nf_ct_helper_count--;
- mutex_unlock(&nf_ct_helper_mutex);
-
- /* Make sure every nothing is still using the helper unless its a
- * connection in the hash.
- */
- synchronize_rcu();
-
- spin_lock_bh(&nf_conntrack_lock);
-
/* Get rid of expectations */
for (i = 0; i < nf_ct_expect_hsize; i++) {
hlist_for_each_entry_safe(exp, n, next,
- &nf_ct_expect_hash[i], hnode) {
+ &net->ct.expect_hash[i], hnode) {
struct nf_conn_help *help = nfct_help(exp->master);
if ((help->helper == me || exp->helper == me) &&
del_timer(&exp->timeout)) {
@@ -156,12 +145,31 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
}
/* Get rid of expecteds, set helpers to NULL. */
- hlist_for_each_entry(h, n, &unconfirmed, hnode)
+ hlist_for_each_entry(h, n, &net->ct.unconfirmed, hnode)
unhelp(h, me);
for (i = 0; i < nf_conntrack_htable_size; i++) {
- hlist_for_each_entry(h, n, &nf_conntrack_hash[i], hnode)
+ hlist_for_each_entry(h, n, &net->ct.hash[i], hnode)
unhelp(h, me);
}
+}
+
+void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
+{
+ struct net *net;
+
+ mutex_lock(&nf_ct_helper_mutex);
+ hlist_del_rcu(&me->hnode);
+ nf_ct_helper_count--;
+ mutex_unlock(&nf_ct_helper_mutex);
+
+ /* Make sure every nothing is still using the helper unless its a
+ * connection in the hash.
+ */
+ synchronize_rcu();
+
+ spin_lock_bh(&nf_conntrack_lock);
+ for_each_net(net)
+ __nf_conntrack_helper_unregister(me, net);
spin_unlock_bh(&nf_conntrack_lock);
}
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index a8752031adcb..cadfd15b44f6 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -549,7 +549,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
last = (struct nf_conn *)cb->args[1];
for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
restart:
- hlist_for_each_entry_rcu(h, n, &nf_conntrack_hash[cb->args[0]],
+ hlist_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]],
hnode) {
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
continue;
@@ -794,14 +794,14 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
else {
/* Flush the whole table */
- nf_conntrack_flush();
+ nf_conntrack_flush(&init_net);
return 0;
}
if (err < 0)
return err;
- h = nf_conntrack_find_get(&tuple);
+ h = nf_conntrack_find_get(&init_net, &tuple);
if (!h)
return -ENOENT;
@@ -847,7 +847,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
- h = nf_conntrack_find_get(&tuple);
+ h = nf_conntrack_find_get(&init_net, &tuple);
if (!h)
return -ENOENT;
@@ -1125,7 +1125,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
struct nf_conn_help *help;
struct nf_conntrack_helper *helper;
- ct = nf_conntrack_alloc(otuple, rtuple, GFP_KERNEL);
+ ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_KERNEL);
if (ct == NULL || IS_ERR(ct))
return -ENOMEM;
@@ -1213,9 +1213,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
spin_lock_bh(&nf_conntrack_lock);
if (cda[CTA_TUPLE_ORIG])
- h = __nf_conntrack_find(&otuple);
+ h = __nf_conntrack_find(&init_net, &otuple);
else if (cda[CTA_TUPLE_REPLY])
- h = __nf_conntrack_find(&rtuple);
+ h = __nf_conntrack_find(&init_net, &rtuple);
if (h == NULL) {
struct nf_conntrack_tuple master;
@@ -1230,7 +1230,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
goto out_unlock;
- master_h = __nf_conntrack_find(&master);
+ master_h = __nf_conntrack_find(&init_net, &master);
if (master_h == NULL) {
err = -ENOENT;
goto out_unlock;
@@ -1458,6 +1458,7 @@ static int ctnetlink_exp_done(struct netlink_callback *cb)
static int
ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct net *net = &init_net;
struct nf_conntrack_expect *exp, *last;
struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
struct hlist_node *n;
@@ -1467,7 +1468,7 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
last = (struct nf_conntrack_expect *)cb->args[1];
for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) {
restart:
- hlist_for_each_entry(exp, n, &nf_ct_expect_hash[cb->args[0]],
+ hlist_for_each_entry(exp, n, &net->ct.expect_hash[cb->args[0]],
hnode) {
if (l3proto && exp->tuple.src.l3num != l3proto)
continue;
@@ -1529,7 +1530,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
- exp = nf_ct_expect_find_get(&tuple);
+ exp = nf_ct_expect_find_get(&init_net, &tuple);
if (!exp)
return -ENOENT;
@@ -1583,7 +1584,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return err;
/* bump usage count to 2 */
- exp = nf_ct_expect_find_get(&tuple);
+ exp = nf_ct_expect_find_get(&init_net, &tuple);
if (!exp)
return -ENOENT;
@@ -1613,7 +1614,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
}
for (i = 0; i < nf_ct_expect_hsize; i++) {
hlist_for_each_entry_safe(exp, n, next,
- &nf_ct_expect_hash[i],
+ &init_net.ct.expect_hash[i],
hnode) {
m_help = nfct_help(exp->master);
if (m_help->helper == h
@@ -1629,7 +1630,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
spin_lock_bh(&nf_conntrack_lock);
for (i = 0; i < nf_ct_expect_hsize; i++) {
hlist_for_each_entry_safe(exp, n, next,
- &nf_ct_expect_hash[i],
+ &init_net.ct.expect_hash[i],
hnode) {
if (del_timer(&exp->timeout)) {
nf_ct_unlink_expect(exp);
@@ -1670,7 +1671,7 @@ ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3)
return err;
/* Look for master conntrack of this expectation */
- h = nf_conntrack_find_get(&master_tuple);
+ h = nf_conntrack_find_get(&init_net, &master_tuple);
if (!h)
return -ENOENT;
ct = nf_ct_tuplehash_to_ctrack(h);
@@ -1724,7 +1725,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
return err;
spin_lock_bh(&nf_conntrack_lock);
- exp = __nf_ct_expect_find(&tuple);
+ exp = __nf_ct_expect_find(&init_net, &tuple);
if (!exp) {
spin_unlock_bh(&nf_conntrack_lock);
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 97e54b0e43a3..373e51e91ce5 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -98,6 +98,7 @@ EXPORT_SYMBOL(pptp_msg_name);
static void pptp_expectfn(struct nf_conn *ct,
struct nf_conntrack_expect *exp)
{
+ struct net *net = nf_ct_net(ct);
typeof(nf_nat_pptp_hook_expectfn) nf_nat_pptp_expectfn;
pr_debug("increasing timeouts\n");
@@ -121,7 +122,7 @@ static void pptp_expectfn(struct nf_conn *ct,
pr_debug("trying to unexpect other dir: ");
nf_ct_dump_tuple(&inv_t);
- exp_other = nf_ct_expect_find_get(&inv_t);
+ exp_other = nf_ct_expect_find_get(net, &inv_t);
if (exp_other) {
/* delete other expectation. */
pr_debug("found\n");
@@ -134,7 +135,8 @@ static void pptp_expectfn(struct nf_conn *ct,
rcu_read_unlock();
}
-static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
+static int destroy_sibling_or_exp(struct net *net,
+ const struct nf_conntrack_tuple *t)
{
const struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_expect *exp;
@@ -143,7 +145,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
pr_debug("trying to timeout ct or exp for tuple ");
nf_ct_dump_tuple(t);
- h = nf_conntrack_find_get(t);
+ h = nf_conntrack_find_get(net, t);
if (h) {
sibling = nf_ct_tuplehash_to_ctrack(h);
pr_debug("setting timeout of conntrack %p to 0\n", sibling);
@@ -154,7 +156,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
nf_ct_put(sibling);
return 1;
} else {
- exp = nf_ct_expect_find_get(t);
+ exp = nf_ct_expect_find_get(net, t);
if (exp) {
pr_debug("unexpect_related of expect %p\n", exp);
nf_ct_unexpect_related(exp);
@@ -168,6 +170,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
/* timeout GRE data connections */
static void pptp_destroy_siblings(struct nf_conn *ct)
{
+ struct net *net = nf_ct_net(ct);
const struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_tuple t;
@@ -178,7 +181,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
- if (!destroy_sibling_or_exp(&t))
+ if (!destroy_sibling_or_exp(net, &t))
pr_debug("failed to timeout original pns->pac ct/exp\n");
/* try reply (pac->pns) tuple */
@@ -186,7 +189,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id;
- if (!destroy_sibling_or_exp(&t))
+ if (!destroy_sibling_or_exp(net, &t))
pr_debug("failed to timeout reply pac->pns ct/exp\n");
}
@@ -594,15 +597,32 @@ static struct nf_conntrack_helper pptp __read_mostly = {
.expect_policy = &pptp_exp_policy,
};
+static void nf_conntrack_pptp_net_exit(struct net *net)
+{
+ nf_ct_gre_keymap_flush(net);
+}
+
+static struct pernet_operations nf_conntrack_pptp_net_ops = {
+ .exit = nf_conntrack_pptp_net_exit,
+};
+
static int __init nf_conntrack_pptp_init(void)
{
- return nf_conntrack_helper_register(&pptp);
+ int rv;
+
+ rv = nf_conntrack_helper_register(&pptp);
+ if (rv < 0)
+ return rv;
+ rv = register_pernet_subsys(&nf_conntrack_pptp_net_ops);
+ if (rv < 0)
+ nf_conntrack_helper_unregister(&pptp);
+ return rv;
}
static void __exit nf_conntrack_pptp_fini(void)
{
nf_conntrack_helper_unregister(&pptp);
- nf_ct_gre_keymap_flush();
+ unregister_pernet_subsys(&nf_conntrack_pptp_net_ops);
}
module_init(nf_conntrack_pptp_init);
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index a49fc932629b..a59a307e685d 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -207,6 +207,8 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register);
void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
{
+ struct net *net;
+
BUG_ON(proto->l3proto >= AF_MAX);
mutex_lock(&nf_ct_proto_mutex);
@@ -219,7 +221,8 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
synchronize_rcu();
/* Remove all contrack entries for this protocol */
- nf_ct_iterate_cleanup(kill_l3proto, proto);
+ for_each_net(net)
+ nf_ct_iterate_cleanup(net, kill_l3proto, proto);
}
EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
@@ -316,6 +319,8 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register);
void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
{
+ struct net *net;
+
BUG_ON(l4proto->l3proto >= PF_MAX);
mutex_lock(&nf_ct_proto_mutex);
@@ -328,7 +333,8 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
synchronize_rcu();
/* Remove all contrack entries for this protocol */
- nf_ct_iterate_cleanup(kill_l4proto, l4proto);
+ for_each_net(net)
+ nf_ct_iterate_cleanup(net, kill_l4proto, l4proto);
}
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index e7866dd3cde6..8fcf1762fabf 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -418,6 +418,7 @@ static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv,
static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff)
{
+ struct net *net = nf_ct_net(ct);
struct dccp_hdr _dh, *dh;
const char *msg;
u_int8_t state;
@@ -445,7 +446,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
return true;
out_invalid:
- if (LOG_INVALID(IPPROTO_DCCP))
+ if (LOG_INVALID(net, IPPROTO_DCCP))
nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, msg);
return false;
}
@@ -461,8 +462,9 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh)
static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff, enum ip_conntrack_info ctinfo,
- int pf, unsigned int hooknum)
+ u_int8_t pf, unsigned int hooknum)
{
+ struct net *net = nf_ct_net(ct);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
struct dccp_hdr _dh, *dh;
u_int8_t type, old_state, new_state;
@@ -524,13 +526,13 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
ct->proto.dccp.last_pkt = type;
write_unlock_bh(&dccp_lock);
- if (LOG_INVALID(IPPROTO_DCCP))
+ if (LOG_INVALID(net, IPPROTO_DCCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_dccp: invalid packet ignored ");
return NF_ACCEPT;
case CT_DCCP_INVALID:
write_unlock_bh(&dccp_lock);
- if (LOG_INVALID(IPPROTO_DCCP))
+ if (LOG_INVALID(net, IPPROTO_DCCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_dccp: invalid state transition ");
return -NF_ACCEPT;
@@ -545,9 +547,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
return NF_ACCEPT;
}
-static int dccp_error(struct sk_buff *skb, unsigned int dataoff,
- enum ip_conntrack_info *ctinfo, int pf,
- unsigned int hooknum)
+static int dccp_error(struct net *net, struct sk_buff *skb,
+ unsigned int dataoff, enum ip_conntrack_info *ctinfo,
+ u_int8_t pf, unsigned int hooknum)
{
struct dccp_hdr _dh, *dh;
unsigned int dccp_len = skb->len - dataoff;
@@ -575,7 +577,7 @@ static int dccp_error(struct sk_buff *skb, unsigned int dataoff,
}
}
- if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
+ if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP,
pf)) {
msg = "nf_ct_dccp: bad checksum ";
@@ -590,7 +592,7 @@ static int dccp_error(struct sk_buff *skb, unsigned int dataoff,
return NF_ACCEPT;
out_invalid:
- if (LOG_INVALID(IPPROTO_DCCP))
+ if (LOG_INVALID(net, IPPROTO_DCCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL, msg);
return -NF_ACCEPT;
}
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index e31b0e7bd0b1..dbe680af85d2 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -45,7 +45,7 @@ static int packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_generic_timeout);
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 9bd03967fea4..a2cdbcbf64c4 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -29,8 +29,11 @@
#include <linux/list.h>
#include <linux/seq_file.h>
#include <linux/in.h>
+#include <linux/netdevice.h>
#include <linux/skbuff.h>
-
+#include <net/dst.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h>
@@ -40,19 +43,23 @@
#define GRE_TIMEOUT (30 * HZ)
#define GRE_STREAM_TIMEOUT (180 * HZ)
-static DEFINE_RWLOCK(nf_ct_gre_lock);
-static LIST_HEAD(gre_keymap_list);
+static int proto_gre_net_id;
+struct netns_proto_gre {
+ rwlock_t keymap_lock;
+ struct list_head keymap_list;
+};
-void nf_ct_gre_keymap_flush(void)
+void nf_ct_gre_keymap_flush(struct net *net)
{
+ struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
struct nf_ct_gre_keymap *km, *tmp;
- write_lock_bh(&nf_ct_gre_lock);
- list_for_each_entry_safe(km, tmp, &gre_keymap_list, list) {
+ write_lock_bh(&net_gre->keymap_lock);
+ list_for_each_entry_safe(km, tmp, &net_gre->keymap_list, list) {
list_del(&km->list);
kfree(km);
}
- write_unlock_bh(&nf_ct_gre_lock);
+ write_unlock_bh(&net_gre->keymap_lock);
}
EXPORT_SYMBOL(nf_ct_gre_keymap_flush);
@@ -67,19 +74,20 @@ static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km,
}
/* look up the source key for a given tuple */
-static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t)
+static __be16 gre_keymap_lookup(struct net *net, struct nf_conntrack_tuple *t)
{
+ struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
struct nf_ct_gre_keymap *km;
__be16 key = 0;
- read_lock_bh(&nf_ct_gre_lock);
- list_for_each_entry(km, &gre_keymap_list, list) {
+ read_lock_bh(&net_gre->keymap_lock);
+ list_for_each_entry(km, &net_gre->keymap_list, list) {
if (gre_key_cmpfn(km, t)) {
key = km->tuple.src.u.gre.key;
break;
}
}
- read_unlock_bh(&nf_ct_gre_lock);
+ read_unlock_bh(&net_gre->keymap_lock);
pr_debug("lookup src key 0x%x for ", key);
nf_ct_dump_tuple(t);
@@ -91,20 +99,22 @@ static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t)
int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
struct nf_conntrack_tuple *t)
{
+ struct net *net = nf_ct_net(ct);
+ struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
struct nf_conn_help *help = nfct_help(ct);
struct nf_ct_gre_keymap **kmp, *km;
kmp = &help->help.ct_pptp_info.keymap[dir];
if (*kmp) {
/* check whether it's a retransmission */
- read_lock_bh(&nf_ct_gre_lock);
- list_for_each_entry(km, &gre_keymap_list, list) {
+ read_lock_bh(&net_gre->keymap_lock);
+ list_for_each_entry(km, &net_gre->keymap_list, list) {
if (gre_key_cmpfn(km, t) && km == *kmp) {
- read_unlock_bh(&nf_ct_gre_lock);
+ read_unlock_bh(&net_gre->keymap_lock);
return 0;
}
}
- read_unlock_bh(&nf_ct_gre_lock);
+ read_unlock_bh(&net_gre->keymap_lock);
pr_debug("trying to override keymap_%s for ct %p\n",
dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
return -EEXIST;
@@ -119,9 +129,9 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
pr_debug("adding new entry %p: ", km);
nf_ct_dump_tuple(&km->tuple);
- write_lock_bh(&nf_ct_gre_lock);
- list_add_tail(&km->list, &gre_keymap_list);
- write_unlock_bh(&nf_ct_gre_lock);
+ write_lock_bh(&net_gre->keymap_lock);
+ list_add_tail(&km->list, &net_gre->keymap_list);
+ write_unlock_bh(&net_gre->keymap_lock);
return 0;
}
@@ -130,12 +140,14 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add);
/* destroy the keymap entries associated with specified master ct */
void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
{
+ struct net *net = nf_ct_net(ct);
+ struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
struct nf_conn_help *help = nfct_help(ct);
enum ip_conntrack_dir dir;
pr_debug("entering for ct %p\n", ct);
- write_lock_bh(&nf_ct_gre_lock);
+ write_lock_bh(&net_gre->keymap_lock);
for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
if (help->help.ct_pptp_info.keymap[dir]) {
pr_debug("removing %p from list\n",
@@ -145,7 +157,7 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
help->help.ct_pptp_info.keymap[dir] = NULL;
}
}
- write_unlock_bh(&nf_ct_gre_lock);
+ write_unlock_bh(&net_gre->keymap_lock);
}
EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);
@@ -164,6 +176,7 @@ static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple,
static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
{
+ struct net *net = dev_net(skb->dev ? skb->dev : skb->dst->dev);
const struct gre_hdr_pptp *pgrehdr;
struct gre_hdr_pptp _pgrehdr;
__be16 srckey;
@@ -190,7 +203,7 @@ static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
}
tuple->dst.u.gre.key = pgrehdr->call_id;
- srckey = gre_keymap_lookup(tuple);
+ srckey = gre_keymap_lookup(net, tuple);
tuple->src.u.gre.key = srckey;
return true;
@@ -219,7 +232,7 @@ static int gre_packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
/* If we've seen traffic both ways, this is a GRE connection.
@@ -229,7 +242,7 @@ static int gre_packet(struct nf_conn *ct,
ct->proto.gre.stream_timeout);
/* Also, more likely to be important, and not a probe. */
set_bit(IPS_ASSURED_BIT, &ct->status);
- nf_conntrack_event_cache(IPCT_STATUS, skb);
+ nf_conntrack_event_cache(IPCT_STATUS, ct);
} else
nf_ct_refresh_acct(ct, ctinfo, skb,
ct->proto.gre.timeout);
@@ -285,15 +298,53 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
#endif
};
+static int proto_gre_net_init(struct net *net)
+{
+ struct netns_proto_gre *net_gre;
+ int rv;
+
+ net_gre = kmalloc(sizeof(struct netns_proto_gre), GFP_KERNEL);
+ if (!net_gre)
+ return -ENOMEM;
+ rwlock_init(&net_gre->keymap_lock);
+ INIT_LIST_HEAD(&net_gre->keymap_list);
+
+ rv = net_assign_generic(net, proto_gre_net_id, net_gre);
+ if (rv < 0)
+ kfree(net_gre);
+ return rv;
+}
+
+static void proto_gre_net_exit(struct net *net)
+{
+ struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
+
+ nf_ct_gre_keymap_flush(net);
+ kfree(net_gre);
+}
+
+static struct pernet_operations proto_gre_net_ops = {
+ .init = proto_gre_net_init,
+ .exit = proto_gre_net_exit,
+};
+
static int __init nf_ct_proto_gre_init(void)
{
- return nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4);
+ int rv;
+
+ rv = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4);
+ if (rv < 0)
+ return rv;
+ rv = register_pernet_gen_device(&proto_gre_net_id, &proto_gre_net_ops);
+ if (rv < 0)
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
+ return rv;
}
static void nf_ct_proto_gre_fini(void)
{
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
- nf_ct_gre_keymap_flush();
+ unregister_pernet_gen_device(proto_gre_net_id, &proto_gre_net_ops);
}
module_init(nf_ct_proto_gre_init);
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 30aa5b94a771..ae8c2609e230 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -287,7 +287,7 @@ static int sctp_packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
enum sctp_conntrack new_state, old_state;
@@ -369,7 +369,7 @@ static int sctp_packet(struct nf_conn *ct,
ct->proto.sctp.state = new_state;
if (old_state != new_state)
- nf_conntrack_event_cache(IPCT_PROTOINFO, skb);
+ nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
}
write_unlock_bh(&sctp_lock);
@@ -380,7 +380,7 @@ static int sctp_packet(struct nf_conn *ct,
new_state == SCTP_CONNTRACK_ESTABLISHED) {
pr_debug("Setting assured bit\n");
set_bit(IPS_ASSURED_BIT, &ct->status);
- nf_conntrack_event_cache(IPCT_STATUS, skb);
+ nf_conntrack_event_cache(IPCT_STATUS, ct);
}
return NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6f61261888ef..f947ec41e391 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -486,8 +486,9 @@ static bool tcp_in_window(const struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
const struct tcphdr *tcph,
- int pf)
+ u_int8_t pf)
{
+ struct net *net = nf_ct_net(ct);
struct ip_ct_tcp_state *sender = &state->seen[dir];
struct ip_ct_tcp_state *receiver = &state->seen[!dir];
const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
@@ -668,7 +669,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
nf_ct_tcp_be_liberal)
res = true;
- if (!res && LOG_INVALID(IPPROTO_TCP))
+ if (!res && LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: %s ",
before(seq, sender->td_maxend + 1) ?
@@ -746,10 +747,11 @@ static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) + 1] =
};
/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */
-static int tcp_error(struct sk_buff *skb,
+static int tcp_error(struct net *net,
+ struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
const struct tcphdr *th;
@@ -760,7 +762,7 @@ static int tcp_error(struct sk_buff *skb,
/* Smaller that minimal TCP header? */
th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
if (th == NULL) {
- if (LOG_INVALID(IPPROTO_TCP))
+ if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: short packet ");
return -NF_ACCEPT;
@@ -768,7 +770,7 @@ static int tcp_error(struct sk_buff *skb,
/* Not whole TCP header or malformed packet */
if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
- if (LOG_INVALID(IPPROTO_TCP))
+ if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: truncated/malformed packet ");
return -NF_ACCEPT;
@@ -779,9 +781,9 @@ static int tcp_error(struct sk_buff *skb,
* because the checksum is assumed to be correct.
*/
/* FIXME: Source route IP option packets --RR */
- if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
+ if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
- if (LOG_INVALID(IPPROTO_TCP))
+ if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: bad TCP checksum ");
return -NF_ACCEPT;
@@ -790,7 +792,7 @@ static int tcp_error(struct sk_buff *skb,
/* Check TCP flags. */
tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR|TH_PUSH));
if (!tcp_valid_flags[tcpflags]) {
- if (LOG_INVALID(IPPROTO_TCP))
+ if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: invalid TCP flag combination ");
return -NF_ACCEPT;
@@ -804,9 +806,10 @@ static int tcp_packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
+ struct net *net = nf_ct_net(ct);
struct nf_conntrack_tuple *tuple;
enum tcp_conntrack new_state, old_state;
enum ip_conntrack_dir dir;
@@ -885,7 +888,7 @@ static int tcp_packet(struct nf_conn *ct,
* thus initiate a clean new session.
*/
write_unlock_bh(&tcp_lock);
- if (LOG_INVALID(IPPROTO_TCP))
+ if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: killing out of sync session ");
nf_ct_kill(ct);
@@ -898,7 +901,7 @@ static int tcp_packet(struct nf_conn *ct,
segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th);
write_unlock_bh(&tcp_lock);
- if (LOG_INVALID(IPPROTO_TCP))
+ if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: invalid packet ignored ");
return NF_ACCEPT;
@@ -907,7 +910,7 @@ static int tcp_packet(struct nf_conn *ct,
pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
dir, get_conntrack_index(th), old_state);
write_unlock_bh(&tcp_lock);
- if (LOG_INVALID(IPPROTO_TCP))
+ if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: invalid state ");
return -NF_ACCEPT;
@@ -968,9 +971,9 @@ static int tcp_packet(struct nf_conn *ct,
timeout = tcp_timeouts[new_state];
write_unlock_bh(&tcp_lock);
- nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
+ nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
if (new_state != old_state)
- nf_conntrack_event_cache(IPCT_PROTOINFO, skb);
+ nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
if (!test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
/* If only reply is a RST, we can consider ourselves not to
@@ -989,7 +992,7 @@ static int tcp_packet(struct nf_conn *ct,
after SYN_RECV or a valid answer for a picked up
connection. */
set_bit(IPS_ASSURED_BIT, &ct->status);
- nf_conntrack_event_cache(IPCT_STATUS, skb);
+ nf_conntrack_event_cache(IPCT_STATUS, ct);
}
nf_ct_refresh_acct(ct, ctinfo, skb, timeout);
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 8b21762e65de..7c2ca48698be 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -66,7 +66,7 @@ static int udp_packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
/* If we've seen traffic both ways, this is some kind of UDP
@@ -75,7 +75,7 @@ static int udp_packet(struct nf_conn *ct,
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream);
/* Also, more likely to be important, and not a probe */
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
- nf_conntrack_event_cache(IPCT_STATUS, skb);
+ nf_conntrack_event_cache(IPCT_STATUS, ct);
} else
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout);
@@ -89,9 +89,9 @@ static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
return true;
}
-static int udp_error(struct sk_buff *skb, unsigned int dataoff,
+static int udp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
unsigned int udplen = skb->len - dataoff;
@@ -101,7 +101,7 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
/* Header is too small? */
hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
if (hdr == NULL) {
- if (LOG_INVALID(IPPROTO_UDP))
+ if (LOG_INVALID(net, IPPROTO_UDP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udp: short packet ");
return -NF_ACCEPT;
@@ -109,7 +109,7 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
/* Truncated/malformed packets */
if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
- if (LOG_INVALID(IPPROTO_UDP))
+ if (LOG_INVALID(net, IPPROTO_UDP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udp: truncated/malformed packet ");
return -NF_ACCEPT;
@@ -123,9 +123,9 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
* We skip checking packets on the outgoing path
* because the checksum is assumed to be correct.
* FIXME: Source route IP option packets --RR */
- if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
+ if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
- if (LOG_INVALID(IPPROTO_UDP))
+ if (LOG_INVALID(net, IPPROTO_UDP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udp: bad UDP checksum ");
return -NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 1fa62f3c24f1..d22d839e4f94 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -65,7 +65,7 @@ static int udplite_packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
/* If we've seen traffic both ways, this is some kind of UDP
@@ -75,7 +75,7 @@ static int udplite_packet(struct nf_conn *ct,
nf_ct_udplite_timeout_stream);
/* Also, more likely to be important, and not a probe */
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
- nf_conntrack_event_cache(IPCT_STATUS, skb);
+ nf_conntrack_event_cache(IPCT_STATUS, ct);
} else
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout);
@@ -89,9 +89,11 @@ static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
return true;
}
-static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
+static int udplite_error(struct net *net,
+ struct sk_buff *skb,
+ unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
- int pf,
+ u_int8_t pf,
unsigned int hooknum)
{
unsigned int udplen = skb->len - dataoff;
@@ -102,7 +104,7 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
/* Header is too small? */
hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
if (hdr == NULL) {
- if (LOG_INVALID(IPPROTO_UDPLITE))
+ if (LOG_INVALID(net, IPPROTO_UDPLITE))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udplite: short packet ");
return -NF_ACCEPT;
@@ -112,7 +114,7 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
if (cscov == 0)
cscov = udplen;
else if (cscov < sizeof(*hdr) || cscov > udplen) {
- if (LOG_INVALID(IPPROTO_UDPLITE))
+ if (LOG_INVALID(net, IPPROTO_UDPLITE))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udplite: invalid checksum coverage ");
return -NF_ACCEPT;
@@ -120,17 +122,17 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
/* UDPLITE mandates checksums */
if (!hdr->check) {
- if (LOG_INVALID(IPPROTO_UDPLITE))
+ if (LOG_INVALID(net, IPPROTO_UDPLITE))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udplite: checksum missing ");
return -NF_ACCEPT;
}
/* Checksum invalid? Ignore. */
- if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
+ if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
pf)) {
- if (LOG_INVALID(IPPROTO_UDPLITE))
+ if (LOG_INVALID(net, IPPROTO_UDPLITE))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udplite: bad UDPLite checksum ");
return -NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 1fa306be60fb..6813f1c8863f 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -736,6 +736,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
struct nf_conntrack_expect *exp, *rtp_exp, *rtcp_exp;
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ struct net *net = nf_ct_net(ct);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
union nf_inet_addr *saddr;
struct nf_conntrack_tuple tuple;
@@ -775,7 +776,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
rcu_read_lock();
do {
- exp = __nf_ct_expect_find(&tuple);
+ exp = __nf_ct_expect_find(net, &tuple);
if (!exp || exp->master == ct ||
nfct_help(exp->master)->helper != nfct_help(ct)->helper ||
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 8509db14670b..98106d4e89f0 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -40,18 +40,20 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
EXPORT_SYMBOL_GPL(print_tuple);
struct ct_iter_state {
+ struct seq_net_private p;
unsigned int bucket;
};
static struct hlist_node *ct_get_first(struct seq_file *seq)
{
+ struct net *net = seq_file_net(seq);
struct ct_iter_state *st = seq->private;
struct hlist_node *n;
for (st->bucket = 0;
st->bucket < nf_conntrack_htable_size;
st->bucket++) {
- n = rcu_dereference(nf_conntrack_hash[st->bucket].first);
+ n = rcu_dereference(net->ct.hash[st->bucket].first);
if (n)
return n;
}
@@ -61,13 +63,14 @@ static struct hlist_node *ct_get_first(struct seq_file *seq)
static struct hlist_node *ct_get_next(struct seq_file *seq,
struct hlist_node *head)
{
+ struct net *net = seq_file_net(seq);
struct ct_iter_state *st = seq->private;
head = rcu_dereference(head->next);
while (head == NULL) {
if (++st->bucket >= nf_conntrack_htable_size)
return NULL;
- head = rcu_dereference(nf_conntrack_hash[st->bucket].first);
+ head = rcu_dereference(net->ct.hash[st->bucket].first);
}
return head;
}
@@ -177,7 +180,7 @@ static const struct seq_operations ct_seq_ops = {
static int ct_open(struct inode *inode, struct file *file)
{
- return seq_open_private(file, &ct_seq_ops,
+ return seq_open_net(inode, file, &ct_seq_ops,
sizeof(struct ct_iter_state));
}
@@ -186,11 +189,12 @@ static const struct file_operations ct_file_ops = {
.open = ct_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release_private,
+ .release = seq_release_net,
};
static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
{
+ struct net *net = seq_file_net(seq);
int cpu;
if (*pos == 0)
@@ -200,7 +204,7 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
if (!cpu_possible(cpu))
continue;
*pos = cpu + 1;
- return &per_cpu(nf_conntrack_stat, cpu);
+ return per_cpu_ptr(net->ct.stat, cpu);
}
return NULL;
@@ -208,13 +212,14 @@ static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
+ struct net *net = seq_file_net(seq);
int cpu;
for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
if (!cpu_possible(cpu))
continue;
*pos = cpu + 1;
- return &per_cpu(nf_conntrack_stat, cpu);
+ return per_cpu_ptr(net->ct.stat, cpu);
}
return NULL;
@@ -226,7 +231,8 @@ static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
static int ct_cpu_seq_show(struct seq_file *seq, void *v)
{
- unsigned int nr_conntracks = atomic_read(&nf_conntrack_count);
+ struct net *net = seq_file_net(seq);
+ unsigned int nr_conntracks = atomic_read(&net->ct.count);
const struct ip_conntrack_stat *st = v;
if (v == SEQ_START_TOKEN) {
@@ -266,7 +272,8 @@ static const struct seq_operations ct_cpu_seq_ops = {
static int ct_cpu_seq_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &ct_cpu_seq_ops);
+ return seq_open_net(inode, file, &ct_cpu_seq_ops,
+ sizeof(struct seq_net_private));
}
static const struct file_operations ct_cpu_seq_fops = {
@@ -274,56 +281,52 @@ static const struct file_operations ct_cpu_seq_fops = {
.open = ct_cpu_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_net,
};
-static int nf_conntrack_standalone_init_proc(void)
+static int nf_conntrack_standalone_init_proc(struct net *net)
{
struct proc_dir_entry *pde;
- pde = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
+ pde = proc_net_fops_create(net, "nf_conntrack", 0440, &ct_file_ops);
if (!pde)
goto out_nf_conntrack;
- pde = proc_create("nf_conntrack", S_IRUGO, init_net.proc_net_stat,
+ pde = proc_create("nf_conntrack", S_IRUGO, net->proc_net_stat,
&ct_cpu_seq_fops);
if (!pde)
goto out_stat_nf_conntrack;
return 0;
out_stat_nf_conntrack:
- proc_net_remove(&init_net, "nf_conntrack");
+ proc_net_remove(net, "nf_conntrack");
out_nf_conntrack:
return -ENOMEM;
}
-static void nf_conntrack_standalone_fini_proc(void)
+static void nf_conntrack_standalone_fini_proc(struct net *net)
{
- remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
- proc_net_remove(&init_net, "nf_conntrack");
+ remove_proc_entry("nf_conntrack", net->proc_net_stat);
+ proc_net_remove(net, "nf_conntrack");
}
#else
-static int nf_conntrack_standalone_init_proc(void)
+static int nf_conntrack_standalone_init_proc(struct net *net)
{
return 0;
}
-static void nf_conntrack_standalone_fini_proc(void)
+static void nf_conntrack_standalone_fini_proc(struct net *net)
{
}
#endif /* CONFIG_PROC_FS */
/* Sysctl support */
-int nf_conntrack_checksum __read_mostly = 1;
-EXPORT_SYMBOL_GPL(nf_conntrack_checksum);
-
#ifdef CONFIG_SYSCTL
/* Log invalid packets of a given protocol */
static int log_invalid_proto_min = 0;
static int log_invalid_proto_max = 255;
-static struct ctl_table_header *nf_ct_sysctl_header;
static struct ctl_table_header *nf_ct_netfilter_header;
static ctl_table nf_ct_sysctl_table[] = {
@@ -338,7 +341,7 @@ static ctl_table nf_ct_sysctl_table[] = {
{
.ctl_name = NET_NF_CONNTRACK_COUNT,
.procname = "nf_conntrack_count",
- .data = &nf_conntrack_count,
+ .data = &init_net.ct.count,
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = &proc_dointvec,
@@ -354,7 +357,7 @@ static ctl_table nf_ct_sysctl_table[] = {
{
.ctl_name = NET_NF_CONNTRACK_CHECKSUM,
.procname = "nf_conntrack_checksum",
- .data = &nf_conntrack_checksum,
+ .data = &init_net.ct.sysctl_checksum,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec,
@@ -362,7 +365,7 @@ static ctl_table nf_ct_sysctl_table[] = {
{
.ctl_name = NET_NF_CONNTRACK_LOG_INVALID,
.procname = "nf_conntrack_log_invalid",
- .data = &nf_ct_log_invalid,
+ .data = &init_net.ct.sysctl_log_invalid,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
@@ -400,74 +403,109 @@ static struct ctl_path nf_ct_path[] = {
{ }
};
-EXPORT_SYMBOL_GPL(nf_ct_log_invalid);
-
-static int nf_conntrack_standalone_init_sysctl(void)
+static int nf_conntrack_standalone_init_sysctl(struct net *net)
{
- nf_ct_netfilter_header =
- register_sysctl_paths(nf_ct_path, nf_ct_netfilter_table);
- if (!nf_ct_netfilter_header)
- goto out;
-
- nf_ct_sysctl_header =
- register_sysctl_paths(nf_net_netfilter_sysctl_path,
- nf_ct_sysctl_table);
- if (!nf_ct_sysctl_header)
+ struct ctl_table *table;
+
+ if (net_eq(net, &init_net)) {
+ nf_ct_netfilter_header =
+ register_sysctl_paths(nf_ct_path, nf_ct_netfilter_table);
+ if (!nf_ct_netfilter_header)
+ goto out;
+ }
+
+ table = kmemdup(nf_ct_sysctl_table, sizeof(nf_ct_sysctl_table),
+ GFP_KERNEL);
+ if (!table)
+ goto out_kmemdup;
+
+ table[1].data = &net->ct.count;
+ table[3].data = &net->ct.sysctl_checksum;
+ table[4].data = &net->ct.sysctl_log_invalid;
+
+ net->ct.sysctl_header = register_net_sysctl_table(net,
+ nf_net_netfilter_sysctl_path, table);
+ if (!net->ct.sysctl_header)
goto out_unregister_netfilter;
return 0;
out_unregister_netfilter:
- unregister_sysctl_table(nf_ct_netfilter_header);
+ kfree(table);
+out_kmemdup:
+ if (net_eq(net, &init_net))
+ unregister_sysctl_table(nf_ct_netfilter_header);
out:
printk("nf_conntrack: can't register to sysctl.\n");
return -ENOMEM;
}
-static void nf_conntrack_standalone_fini_sysctl(void)
+static void nf_conntrack_standalone_fini_sysctl(struct net *net)
{
- unregister_sysctl_table(nf_ct_netfilter_header);
- unregister_sysctl_table(nf_ct_sysctl_header);
+ struct ctl_table *table;
+
+ if (net_eq(net, &init_net))
+ unregister_sysctl_table(nf_ct_netfilter_header);
+ table = net->ct.sysctl_header->ctl_table_arg;
+ unregister_net_sysctl_table(net->ct.sysctl_header);
+ kfree(table);
}
#else
-static int nf_conntrack_standalone_init_sysctl(void)
+static int nf_conntrack_standalone_init_sysctl(struct net *net)
{
return 0;
}
-static void nf_conntrack_standalone_fini_sysctl(void)
+static void nf_conntrack_standalone_fini_sysctl(struct net *net)
{
}
#endif /* CONFIG_SYSCTL */
-static int __init nf_conntrack_standalone_init(void)
+static int nf_conntrack_net_init(struct net *net)
{
int ret;
- ret = nf_conntrack_init();
+ ret = nf_conntrack_init(net);
if (ret < 0)
- goto out;
- ret = nf_conntrack_standalone_init_proc();
+ goto out_init;
+ ret = nf_conntrack_standalone_init_proc(net);
if (ret < 0)
goto out_proc;
- ret = nf_conntrack_standalone_init_sysctl();
+ net->ct.sysctl_checksum = 1;
+ net->ct.sysctl_log_invalid = 0;
+ ret = nf_conntrack_standalone_init_sysctl(net);
if (ret < 0)
goto out_sysctl;
return 0;
out_sysctl:
- nf_conntrack_standalone_fini_proc();
+ nf_conntrack_standalone_fini_proc(net);
out_proc:
- nf_conntrack_cleanup();
-out:
+ nf_conntrack_cleanup(net);
+out_init:
return ret;
}
+static void nf_conntrack_net_exit(struct net *net)
+{
+ nf_conntrack_standalone_fini_sysctl(net);
+ nf_conntrack_standalone_fini_proc(net);
+ nf_conntrack_cleanup(net);
+}
+
+static struct pernet_operations nf_conntrack_net_ops = {
+ .init = nf_conntrack_net_init,
+ .exit = nf_conntrack_net_exit,
+};
+
+static int __init nf_conntrack_standalone_init(void)
+{
+ return register_pernet_subsys(&nf_conntrack_net_ops);
+}
+
static void __exit nf_conntrack_standalone_fini(void)
{
- nf_conntrack_standalone_fini_sysctl();
- nf_conntrack_standalone_fini_proc();
- nf_conntrack_cleanup();
+ unregister_pernet_subsys(&nf_conntrack_net_ops);
}
module_init(nf_conntrack_standalone_init);
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index 196269c1e586..bf6609978af7 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -15,7 +15,7 @@
/* core.c */
extern unsigned int nf_iterate(struct list_head *head,
struct sk_buff *skb,
- int hook,
+ unsigned int hook,
const struct net_device *indev,
const struct net_device *outdev,
struct list_head **i,
@@ -25,7 +25,7 @@ extern unsigned int nf_iterate(struct list_head *head,
/* nf_queue.c */
extern int nf_queue(struct sk_buff *skb,
struct list_head *elem,
- int pf, unsigned int hook,
+ u_int8_t pf, unsigned int hook,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *),
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 9fda6ee95a31..fa8ae5d2659c 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -15,16 +15,16 @@
#define NF_LOG_PREFIXLEN 128
-static const struct nf_logger *nf_loggers[NPROTO] __read_mostly;
+static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
static DEFINE_MUTEX(nf_log_mutex);
/* return EBUSY if somebody else is registered, EEXIST if the same logger
* is registred, 0 on success. */
-int nf_log_register(int pf, const struct nf_logger *logger)
+int nf_log_register(u_int8_t pf, const struct nf_logger *logger)
{
int ret;
- if (pf >= NPROTO)
+ if (pf >= ARRAY_SIZE(nf_loggers))
return -EINVAL;
/* Any setup of logging members must be done before
@@ -45,9 +45,9 @@ int nf_log_register(int pf, const struct nf_logger *logger)
}
EXPORT_SYMBOL(nf_log_register);
-void nf_log_unregister_pf(int pf)
+void nf_log_unregister_pf(u_int8_t pf)
{
- if (pf >= NPROTO)
+ if (pf >= ARRAY_SIZE(nf_loggers))
return;
mutex_lock(&nf_log_mutex);
rcu_assign_pointer(nf_loggers[pf], NULL);
@@ -63,7 +63,7 @@ void nf_log_unregister(const struct nf_logger *logger)
int i;
mutex_lock(&nf_log_mutex);
- for (i = 0; i < NPROTO; i++) {
+ for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) {
if (nf_loggers[i] == logger)
rcu_assign_pointer(nf_loggers[i], NULL);
}
@@ -73,7 +73,7 @@ void nf_log_unregister(const struct nf_logger *logger)
}
EXPORT_SYMBOL(nf_log_unregister);
-void nf_log_packet(int pf,
+void nf_log_packet(u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
@@ -103,7 +103,7 @@ static void *seq_start(struct seq_file *seq, loff_t *pos)
{
rcu_read_lock();
- if (*pos >= NPROTO)
+ if (*pos >= ARRAY_SIZE(nf_loggers))
return NULL;
return pos;
@@ -113,7 +113,7 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
{
(*pos)++;
- if (*pos >= NPROTO)
+ if (*pos >= ARRAY_SIZE(nf_loggers))
return NULL;
return pos;
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 582ec3efc8a5..4f2310c93e01 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -16,17 +16,17 @@
* long term mutex. The handler must provide an an outfn() to accept packets
* for queueing and must reinject all packets it receives, no matter what.
*/
-static const struct nf_queue_handler *queue_handler[NPROTO];
+static const struct nf_queue_handler *queue_handler[NFPROTO_NUMPROTO] __read_mostly;
static DEFINE_MUTEX(queue_handler_mutex);
/* return EBUSY when somebody else is registered, return EEXIST if the
* same handler is registered, return 0 in case of success. */
-int nf_register_queue_handler(int pf, const struct nf_queue_handler *qh)
+int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
{
int ret;
- if (pf >= NPROTO)
+ if (pf >= ARRAY_SIZE(queue_handler))
return -EINVAL;
mutex_lock(&queue_handler_mutex);
@@ -45,9 +45,9 @@ int nf_register_queue_handler(int pf, const struct nf_queue_handler *qh)
EXPORT_SYMBOL(nf_register_queue_handler);
/* The caller must flush their queue before this */
-int nf_unregister_queue_handler(int pf, const struct nf_queue_handler *qh)
+int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
{
- if (pf >= NPROTO)
+ if (pf >= ARRAY_SIZE(queue_handler))
return -EINVAL;
mutex_lock(&queue_handler_mutex);
@@ -67,10 +67,10 @@ EXPORT_SYMBOL(nf_unregister_queue_handler);
void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
{
- int pf;
+ u_int8_t pf;
mutex_lock(&queue_handler_mutex);
- for (pf = 0; pf < NPROTO; pf++) {
+ for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++) {
if (queue_handler[pf] == qh)
rcu_assign_pointer(queue_handler[pf], NULL);
}
@@ -107,7 +107,7 @@ static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
*/
static int __nf_queue(struct sk_buff *skb,
struct list_head *elem,
- int pf, unsigned int hook,
+ u_int8_t pf, unsigned int hook,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *),
@@ -191,7 +191,7 @@ err:
int nf_queue(struct sk_buff *skb,
struct list_head *elem,
- int pf, unsigned int hook,
+ u_int8_t pf, unsigned int hook,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *),
@@ -285,7 +285,7 @@ EXPORT_SYMBOL(nf_reinject);
#ifdef CONFIG_PROC_FS
static void *seq_start(struct seq_file *seq, loff_t *pos)
{
- if (*pos >= NPROTO)
+ if (*pos >= ARRAY_SIZE(queue_handler))
return NULL;
return pos;
@@ -295,7 +295,7 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
{
(*pos)++;
- if (*pos >= NPROTO)
+ if (*pos >= ARRAY_SIZE(queue_handler))
return NULL;
return pos;
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index 01489681fa96..8ab829f86574 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -60,14 +60,11 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
}
EXPORT_SYMBOL(nf_unregister_sockopt);
-static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, int pf,
+static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, u_int8_t pf,
int val, int get)
{
struct nf_sockopt_ops *ops;
- if (!net_eq(sock_net(sk), &init_net))
- return ERR_PTR(-ENOPROTOOPT);
-
if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
return ERR_PTR(-EINTR);
@@ -96,7 +93,7 @@ out:
}
/* Call get/setsockopt() */
-static int nf_sockopt(struct sock *sk, int pf, int val,
+static int nf_sockopt(struct sock *sk, u_int8_t pf, int val,
char __user *opt, int *len, int get)
{
struct nf_sockopt_ops *ops;
@@ -115,21 +112,22 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
return ret;
}
-int nf_setsockopt(struct sock *sk, int pf, int val, char __user *opt,
+int nf_setsockopt(struct sock *sk, u_int8_t pf, int val, char __user *opt,
int len)
{
return nf_sockopt(sk, pf, val, opt, &len, 0);
}
EXPORT_SYMBOL(nf_setsockopt);
-int nf_getsockopt(struct sock *sk, int pf, int val, char __user *opt, int *len)
+int nf_getsockopt(struct sock *sk, u_int8_t pf, int val, char __user *opt,
+ int *len)
{
return nf_sockopt(sk, pf, val, opt, len, 1);
}
EXPORT_SYMBOL(nf_getsockopt);
#ifdef CONFIG_COMPAT
-static int compat_nf_sockopt(struct sock *sk, int pf, int val,
+static int compat_nf_sockopt(struct sock *sk, u_int8_t pf, int val,
char __user *opt, int *len, int get)
{
struct nf_sockopt_ops *ops;
@@ -155,14 +153,14 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val,
return ret;
}
-int compat_nf_setsockopt(struct sock *sk, int pf,
+int compat_nf_setsockopt(struct sock *sk, u_int8_t pf,
int val, char __user *opt, int len)
{
return compat_nf_sockopt(sk, pf, val, opt, &len, 0);
}
EXPORT_SYMBOL(compat_nf_setsockopt);
-int compat_nf_getsockopt(struct sock *sk, int pf,
+int compat_nf_getsockopt(struct sock *sk, u_int8_t pf,
int val, char __user *opt, int *len)
{
return compat_nf_sockopt(sk, pf, val, opt, len, 1);
diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c
new file mode 100644
index 000000000000..fe34f4bf74cc
--- /dev/null
+++ b/net/netfilter/nf_tproxy_core.c
@@ -0,0 +1,96 @@
+/*
+ * Transparent proxy support for Linux/iptables
+ *
+ * Copyright (c) 2006-2007 BalaBit IT Ltd.
+ * Author: Balazs Scheidler, Krisztian Kovacs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/net.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <net/udp.h>
+#include <net/netfilter/nf_tproxy_core.h>
+
+struct sock *
+nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
+ const __be32 saddr, const __be32 daddr,
+ const __be16 sport, const __be16 dport,
+ const struct net_device *in, bool listening_only)
+{
+ struct sock *sk;
+
+ /* look up socket */
+ switch (protocol) {
+ case IPPROTO_TCP:
+ if (listening_only)
+ sk = __inet_lookup_listener(net, &tcp_hashinfo,
+ daddr, ntohs(dport),
+ in->ifindex);
+ else
+ sk = __inet_lookup(net, &tcp_hashinfo,
+ saddr, sport, daddr, dport,
+ in->ifindex);
+ break;
+ case IPPROTO_UDP:
+ sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
+ in->ifindex);
+ break;
+ default:
+ WARN_ON(1);
+ sk = NULL;
+ }
+
+ pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, listener only: %d, sock %p\n",
+ protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), listening_only, sk);
+
+ return sk;
+}
+EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v4);
+
+static void
+nf_tproxy_destructor(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+
+ skb->sk = NULL;
+ skb->destructor = NULL;
+
+ if (sk)
+ nf_tproxy_put_sock(sk);
+}
+
+/* consumes sk */
+int
+nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
+{
+ if (inet_sk(sk)->transparent) {
+ skb->sk = sk;
+ skb->destructor = nf_tproxy_destructor;
+ return 1;
+ } else
+ nf_tproxy_put_sock(sk);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_tproxy_assign_sock);
+
+static int __init nf_tproxy_init(void)
+{
+ pr_info("NF_TPROXY: Transparent proxy support initialized, version 4.1.0\n");
+ pr_info("NF_TPROXY: Copyright (c) 2006-2007 BalaBit IT Ltd.\n");
+ return 0;
+}
+
+module_init(nf_tproxy_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Krisztian Kovacs");
+MODULE_DESCRIPTION("Transparent proxy support core routines");
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 9a35b57ab76d..41e0105d3828 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -359,7 +359,7 @@ static inline int
__build_packet_message(struct nfulnl_instance *inst,
const struct sk_buff *skb,
unsigned int data_len,
- unsigned int pf,
+ u_int8_t pf,
unsigned int hooknum,
const struct net_device *indev,
const struct net_device *outdev,
@@ -534,7 +534,7 @@ static struct nf_loginfo default_loginfo = {
/* log handler for internal netfilter logging api */
static void
-nfulnl_log_packet(unsigned int pf,
+nfulnl_log_packet(u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 5d75cd86ebb3..89837a4eef76 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -30,7 +30,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
+MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
@@ -58,17 +58,20 @@ static struct xt_af *xt;
#define duprintf(format, args...)
#endif
-static const char *const xt_prefix[NPROTO] = {
- [AF_INET] = "ip",
- [AF_INET6] = "ip6",
- [NF_ARP] = "arp",
+static const char *const xt_prefix[NFPROTO_NUMPROTO] = {
+ [NFPROTO_UNSPEC] = "x",
+ [NFPROTO_IPV4] = "ip",
+ [NFPROTO_ARP] = "arp",
+ [NFPROTO_BRIDGE] = "eb",
+ [NFPROTO_IPV6] = "ip6",
};
/* Registration hooks for targets. */
int
xt_register_target(struct xt_target *target)
{
- int ret, af = target->family;
+ u_int8_t af = target->family;
+ int ret;
ret = mutex_lock_interruptible(&xt[af].mutex);
if (ret != 0)
@@ -82,7 +85,7 @@ EXPORT_SYMBOL(xt_register_target);
void
xt_unregister_target(struct xt_target *target)
{
- int af = target->family;
+ u_int8_t af = target->family;
mutex_lock(&xt[af].mutex);
list_del(&target->list);
@@ -123,7 +126,8 @@ EXPORT_SYMBOL(xt_unregister_targets);
int
xt_register_match(struct xt_match *match)
{
- int ret, af = match->family;
+ u_int8_t af = match->family;
+ int ret;
ret = mutex_lock_interruptible(&xt[af].mutex);
if (ret != 0)
@@ -139,7 +143,7 @@ EXPORT_SYMBOL(xt_register_match);
void
xt_unregister_match(struct xt_match *match)
{
- int af = match->family;
+ u_int8_t af = match->family;
mutex_lock(&xt[af].mutex);
list_del(&match->list);
@@ -185,7 +189,7 @@ EXPORT_SYMBOL(xt_unregister_matches);
*/
/* Find match, grabs ref. Returns ERR_PTR() on error. */
-struct xt_match *xt_find_match(int af, const char *name, u8 revision)
+struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
{
struct xt_match *m;
int err = 0;
@@ -205,12 +209,17 @@ struct xt_match *xt_find_match(int af, const char *name, u8 revision)
}
}
mutex_unlock(&xt[af].mutex);
+
+ if (af != NFPROTO_UNSPEC)
+ /* Try searching again in the family-independent list */
+ return xt_find_match(NFPROTO_UNSPEC, name, revision);
+
return ERR_PTR(err);
}
EXPORT_SYMBOL(xt_find_match);
/* Find target, grabs ref. Returns ERR_PTR() on error. */
-struct xt_target *xt_find_target(int af, const char *name, u8 revision)
+struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
{
struct xt_target *t;
int err = 0;
@@ -230,11 +239,16 @@ struct xt_target *xt_find_target(int af, const char *name, u8 revision)
}
}
mutex_unlock(&xt[af].mutex);
+
+ if (af != NFPROTO_UNSPEC)
+ /* Try searching again in the family-independent list */
+ return xt_find_target(NFPROTO_UNSPEC, name, revision);
+
return ERR_PTR(err);
}
EXPORT_SYMBOL(xt_find_target);
-struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
+struct xt_target *xt_request_find_target(u8 af, const char *name, u8 revision)
{
struct xt_target *target;
@@ -246,7 +260,7 @@ struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
}
EXPORT_SYMBOL_GPL(xt_request_find_target);
-static int match_revfn(int af, const char *name, u8 revision, int *bestp)
+static int match_revfn(u8 af, const char *name, u8 revision, int *bestp)
{
const struct xt_match *m;
int have_rev = 0;
@@ -262,7 +276,7 @@ static int match_revfn(int af, const char *name, u8 revision, int *bestp)
return have_rev;
}
-static int target_revfn(int af, const char *name, u8 revision, int *bestp)
+static int target_revfn(u8 af, const char *name, u8 revision, int *bestp)
{
const struct xt_target *t;
int have_rev = 0;
@@ -279,7 +293,7 @@ static int target_revfn(int af, const char *name, u8 revision, int *bestp)
}
/* Returns true or false (if no such extension at all) */
-int xt_find_revision(int af, const char *name, u8 revision, int target,
+int xt_find_revision(u8 af, const char *name, u8 revision, int target,
int *err)
{
int have_rev, best = -1;
@@ -307,37 +321,47 @@ int xt_find_revision(int af, const char *name, u8 revision, int target,
}
EXPORT_SYMBOL_GPL(xt_find_revision);
-int xt_check_match(const struct xt_match *match, unsigned short family,
- unsigned int size, const char *table, unsigned int hook_mask,
- unsigned short proto, int inv_proto)
+int xt_check_match(struct xt_mtchk_param *par,
+ unsigned int size, u_int8_t proto, bool inv_proto)
{
- if (XT_ALIGN(match->matchsize) != size) {
+ if (XT_ALIGN(par->match->matchsize) != size &&
+ par->match->matchsize != -1) {
+ /*
+ * ebt_among is exempt from centralized matchsize checking
+ * because it uses a dynamic-size data set.
+ */
printk("%s_tables: %s match: invalid size %Zu != %u\n",
- xt_prefix[family], match->name,
- XT_ALIGN(match->matchsize), size);
+ xt_prefix[par->family], par->match->name,
+ XT_ALIGN(par->match->matchsize), size);
return -EINVAL;
}
- if (match->table && strcmp(match->table, table)) {
+ if (par->match->table != NULL &&
+ strcmp(par->match->table, par->table) != 0) {
printk("%s_tables: %s match: only valid in %s table, not %s\n",
- xt_prefix[family], match->name, match->table, table);
+ xt_prefix[par->family], par->match->name,
+ par->match->table, par->table);
return -EINVAL;
}
- if (match->hooks && (hook_mask & ~match->hooks) != 0) {
- printk("%s_tables: %s match: bad hook_mask %u/%u\n",
- xt_prefix[family], match->name, hook_mask, match->hooks);
+ if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) {
+ printk("%s_tables: %s match: bad hook_mask %#x/%#x\n",
+ xt_prefix[par->family], par->match->name,
+ par->hook_mask, par->match->hooks);
return -EINVAL;
}
- if (match->proto && (match->proto != proto || inv_proto)) {
+ if (par->match->proto && (par->match->proto != proto || inv_proto)) {
printk("%s_tables: %s match: only valid for protocol %u\n",
- xt_prefix[family], match->name, match->proto);
+ xt_prefix[par->family], par->match->name,
+ par->match->proto);
return -EINVAL;
}
+ if (par->match->checkentry != NULL && !par->match->checkentry(par))
+ return -EINVAL;
return 0;
}
EXPORT_SYMBOL_GPL(xt_check_match);
#ifdef CONFIG_COMPAT
-int xt_compat_add_offset(int af, unsigned int offset, short delta)
+int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta)
{
struct compat_delta *tmp;
@@ -359,7 +383,7 @@ int xt_compat_add_offset(int af, unsigned int offset, short delta)
}
EXPORT_SYMBOL_GPL(xt_compat_add_offset);
-void xt_compat_flush_offsets(int af)
+void xt_compat_flush_offsets(u_int8_t af)
{
struct compat_delta *tmp, *next;
@@ -373,7 +397,7 @@ void xt_compat_flush_offsets(int af)
}
EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
-short xt_compat_calc_jump(int af, unsigned int offset)
+short xt_compat_calc_jump(u_int8_t af, unsigned int offset)
{
struct compat_delta *tmp;
short delta;
@@ -448,32 +472,36 @@ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
#endif /* CONFIG_COMPAT */
-int xt_check_target(const struct xt_target *target, unsigned short family,
- unsigned int size, const char *table, unsigned int hook_mask,
- unsigned short proto, int inv_proto)
+int xt_check_target(struct xt_tgchk_param *par,
+ unsigned int size, u_int8_t proto, bool inv_proto)
{
- if (XT_ALIGN(target->targetsize) != size) {
+ if (XT_ALIGN(par->target->targetsize) != size) {
printk("%s_tables: %s target: invalid size %Zu != %u\n",
- xt_prefix[family], target->name,
- XT_ALIGN(target->targetsize), size);
+ xt_prefix[par->family], par->target->name,
+ XT_ALIGN(par->target->targetsize), size);
return -EINVAL;
}
- if (target->table && strcmp(target->table, table)) {
+ if (par->target->table != NULL &&
+ strcmp(par->target->table, par->table) != 0) {
printk("%s_tables: %s target: only valid in %s table, not %s\n",
- xt_prefix[family], target->name, target->table, table);
+ xt_prefix[par->family], par->target->name,
+ par->target->table, par->table);
return -EINVAL;
}
- if (target->hooks && (hook_mask & ~target->hooks) != 0) {
- printk("%s_tables: %s target: bad hook_mask %u/%u\n",
- xt_prefix[family], target->name, hook_mask,
- target->hooks);
+ if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
+ printk("%s_tables: %s target: bad hook_mask %#x/%#x\n",
+ xt_prefix[par->family], par->target->name,
+ par->hook_mask, par->target->hooks);
return -EINVAL;
}
- if (target->proto && (target->proto != proto || inv_proto)) {
+ if (par->target->proto && (par->target->proto != proto || inv_proto)) {
printk("%s_tables: %s target: only valid for protocol %u\n",
- xt_prefix[family], target->name, target->proto);
+ xt_prefix[par->family], par->target->name,
+ par->target->proto);
return -EINVAL;
}
+ if (par->target->checkentry != NULL && !par->target->checkentry(par))
+ return -EINVAL;
return 0;
}
EXPORT_SYMBOL_GPL(xt_check_target);
@@ -590,7 +618,8 @@ void xt_free_table_info(struct xt_table_info *info)
EXPORT_SYMBOL(xt_free_table_info);
/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
-struct xt_table *xt_find_table_lock(struct net *net, int af, const char *name)
+struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
+ const char *name)
{
struct xt_table *t;
@@ -612,13 +641,13 @@ void xt_table_unlock(struct xt_table *table)
EXPORT_SYMBOL_GPL(xt_table_unlock);
#ifdef CONFIG_COMPAT
-void xt_compat_lock(int af)
+void xt_compat_lock(u_int8_t af)
{
mutex_lock(&xt[af].compat_mutex);
}
EXPORT_SYMBOL_GPL(xt_compat_lock);
-void xt_compat_unlock(int af)
+void xt_compat_unlock(u_int8_t af)
{
mutex_unlock(&xt[af].compat_mutex);
}
@@ -722,13 +751,13 @@ EXPORT_SYMBOL_GPL(xt_unregister_table);
#ifdef CONFIG_PROC_FS
struct xt_names_priv {
struct seq_net_private p;
- int af;
+ u_int8_t af;
};
static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
{
struct xt_names_priv *priv = seq->private;
struct net *net = seq_file_net(seq);
- int af = priv->af;
+ u_int8_t af = priv->af;
mutex_lock(&xt[af].mutex);
return seq_list_start(&net->xt.tables[af], *pos);
@@ -738,7 +767,7 @@ static void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct xt_names_priv *priv = seq->private;
struct net *net = seq_file_net(seq);
- int af = priv->af;
+ u_int8_t af = priv->af;
return seq_list_next(v, &net->xt.tables[af], pos);
}
@@ -746,7 +775,7 @@ static void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos)
static void xt_table_seq_stop(struct seq_file *seq, void *v)
{
struct xt_names_priv *priv = seq->private;
- int af = priv->af;
+ u_int8_t af = priv->af;
mutex_unlock(&xt[af].mutex);
}
@@ -922,14 +951,14 @@ static const struct file_operations xt_target_ops = {
#endif /* CONFIG_PROC_FS */
-int xt_proto_init(struct net *net, int af)
+int xt_proto_init(struct net *net, u_int8_t af)
{
#ifdef CONFIG_PROC_FS
char buf[XT_FUNCTION_MAXNAMELEN];
struct proc_dir_entry *proc;
#endif
- if (af >= NPROTO)
+ if (af >= ARRAY_SIZE(xt_prefix))
return -EINVAL;
@@ -974,7 +1003,7 @@ out:
}
EXPORT_SYMBOL_GPL(xt_proto_init);
-void xt_proto_fini(struct net *net, int af)
+void xt_proto_fini(struct net *net, u_int8_t af)
{
#ifdef CONFIG_PROC_FS
char buf[XT_FUNCTION_MAXNAMELEN];
@@ -998,7 +1027,7 @@ static int __net_init xt_net_init(struct net *net)
{
int i;
- for (i = 0; i < NPROTO; i++)
+ for (i = 0; i < NFPROTO_NUMPROTO; i++)
INIT_LIST_HEAD(&net->xt.tables[i]);
return 0;
}
@@ -1011,11 +1040,11 @@ static int __init xt_init(void)
{
int i, rv;
- xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
+ xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL);
if (!xt)
return -ENOMEM;
- for (i = 0; i < NPROTO; i++) {
+ for (i = 0; i < NFPROTO_NUMPROTO; i++) {
mutex_init(&xt[i].mutex);
#ifdef CONFIG_COMPAT
mutex_init(&xt[i].compat_mutex);
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 77a52bf83225..011bc80dd2a1 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -27,50 +27,34 @@ MODULE_ALIAS("ipt_CLASSIFY");
MODULE_ALIAS("ip6t_CLASSIFY");
static unsigned int
-classify_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+classify_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_classify_target_info *clinfo = targinfo;
+ const struct xt_classify_target_info *clinfo = par->targinfo;
skb->priority = clinfo->priority;
return XT_CONTINUE;
}
-static struct xt_target classify_tg_reg[] __read_mostly = {
- {
- .family = AF_INET,
- .name = "CLASSIFY",
- .target = classify_tg,
- .targetsize = sizeof(struct xt_classify_target_info),
- .table = "mangle",
- .hooks = (1 << NF_INET_LOCAL_OUT) |
- (1 << NF_INET_FORWARD) |
- (1 << NF_INET_POST_ROUTING),
- .me = THIS_MODULE,
- },
- {
- .name = "CLASSIFY",
- .family = AF_INET6,
- .target = classify_tg,
- .targetsize = sizeof(struct xt_classify_target_info),
- .table = "mangle",
- .hooks = (1 << NF_INET_LOCAL_OUT) |
- (1 << NF_INET_FORWARD) |
- (1 << NF_INET_POST_ROUTING),
- .me = THIS_MODULE,
- },
+static struct xt_target classify_tg_reg __read_mostly = {
+ .name = "CLASSIFY",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .table = "mangle",
+ .hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
+ (1 << NF_INET_POST_ROUTING),
+ .target = classify_tg,
+ .targetsize = sizeof(struct xt_classify_target_info),
+ .me = THIS_MODULE,
};
static int __init classify_tg_init(void)
{
- return xt_register_targets(classify_tg_reg,
- ARRAY_SIZE(classify_tg_reg));
+ return xt_register_target(&classify_tg_reg);
}
static void __exit classify_tg_exit(void)
{
- xt_unregister_targets(classify_tg_reg, ARRAY_SIZE(classify_tg_reg));
+ xt_unregister_target(&classify_tg_reg);
}
module_init(classify_tg_init);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 5fecfb4794b1..d6e5ab463277 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -36,11 +36,9 @@ MODULE_ALIAS("ip6t_CONNMARK");
#include <net/netfilter/nf_conntrack_ecache.h>
static unsigned int
-connmark_tg_v0(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+connmark_tg_v0(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_connmark_target_info *markinfo = targinfo;
+ const struct xt_connmark_target_info *markinfo = par->targinfo;
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
u_int32_t diff;
@@ -54,7 +52,7 @@ connmark_tg_v0(struct sk_buff *skb, const struct net_device *in,
newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
if (newmark != ct->mark) {
ct->mark = newmark;
- nf_conntrack_event_cache(IPCT_MARK, skb);
+ nf_conntrack_event_cache(IPCT_MARK, ct);
}
break;
case XT_CONNMARK_SAVE:
@@ -62,7 +60,7 @@ connmark_tg_v0(struct sk_buff *skb, const struct net_device *in,
(skb->mark & markinfo->mask);
if (ct->mark != newmark) {
ct->mark = newmark;
- nf_conntrack_event_cache(IPCT_MARK, skb);
+ nf_conntrack_event_cache(IPCT_MARK, ct);
}
break;
case XT_CONNMARK_RESTORE:
@@ -77,11 +75,9 @@ connmark_tg_v0(struct sk_buff *skb, const struct net_device *in,
}
static unsigned int
-connmark_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+connmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_connmark_tginfo1 *info = targinfo;
+ const struct xt_connmark_tginfo1 *info = par->targinfo;
enum ip_conntrack_info ctinfo;
struct nf_conn *ct;
u_int32_t newmark;
@@ -95,7 +91,7 @@ connmark_tg(struct sk_buff *skb, const struct net_device *in,
newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
if (ct->mark != newmark) {
ct->mark = newmark;
- nf_conntrack_event_cache(IPCT_MARK, skb);
+ nf_conntrack_event_cache(IPCT_MARK, ct);
}
break;
case XT_CONNMARK_SAVE:
@@ -103,7 +99,7 @@ connmark_tg(struct sk_buff *skb, const struct net_device *in,
(skb->mark & info->nfmask);
if (ct->mark != newmark) {
ct->mark = newmark;
- nf_conntrack_event_cache(IPCT_MARK, skb);
+ nf_conntrack_event_cache(IPCT_MARK, ct);
}
break;
case XT_CONNMARK_RESTORE:
@@ -116,18 +112,15 @@ connmark_tg(struct sk_buff *skb, const struct net_device *in,
return XT_CONTINUE;
}
-static bool
-connmark_tg_check_v0(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool connmark_tg_check_v0(const struct xt_tgchk_param *par)
{
- const struct xt_connmark_target_info *matchinfo = targinfo;
+ const struct xt_connmark_target_info *matchinfo = par->targinfo;
if (matchinfo->mode == XT_CONNMARK_RESTORE) {
- if (strcmp(tablename, "mangle") != 0) {
+ if (strcmp(par->table, "mangle") != 0) {
printk(KERN_WARNING "CONNMARK: restore can only be "
"called from \"mangle\" table, not \"%s\"\n",
- tablename);
+ par->table);
return false;
}
}
@@ -135,31 +128,27 @@ connmark_tg_check_v0(const char *tablename, const void *entry,
printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
return false;
}
- if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%u\n", target->family);
+ "proto=%u\n", par->family);
return false;
}
return true;
}
-static bool
-connmark_tg_check(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool connmark_tg_check(const struct xt_tgchk_param *par)
{
- if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "cannot load conntrack support for "
- "proto=%u\n", target->family);
+ "proto=%u\n", par->family);
return false;
}
return true;
}
-static void
-connmark_tg_destroy(const struct xt_target *target, void *targinfo)
+static void connmark_tg_destroy(const struct xt_tgdtor_param *par)
{
- nf_ct_l3proto_module_put(target->family);
+ nf_ct_l3proto_module_put(par->family);
}
#ifdef CONFIG_COMPAT
@@ -197,7 +186,7 @@ static struct xt_target connmark_tg_reg[] __read_mostly = {
{
.name = "CONNMARK",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_UNSPEC,
.checkentry = connmark_tg_check_v0,
.destroy = connmark_tg_destroy,
.target = connmark_tg_v0,
@@ -210,34 +199,9 @@ static struct xt_target connmark_tg_reg[] __read_mostly = {
.me = THIS_MODULE
},
{
- .name = "CONNMARK",
- .revision = 0,
- .family = AF_INET6,
- .checkentry = connmark_tg_check_v0,
- .destroy = connmark_tg_destroy,
- .target = connmark_tg_v0,
- .targetsize = sizeof(struct xt_connmark_target_info),
-#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_xt_connmark_target_info),
- .compat_from_user = connmark_tg_compat_from_user_v0,
- .compat_to_user = connmark_tg_compat_to_user_v0,
-#endif
- .me = THIS_MODULE
- },
- {
- .name = "CONNMARK",
- .revision = 1,
- .family = AF_INET,
- .checkentry = connmark_tg_check,
- .target = connmark_tg,
- .targetsize = sizeof(struct xt_connmark_tginfo1),
- .destroy = connmark_tg_destroy,
- .me = THIS_MODULE,
- },
- {
.name = "CONNMARK",
.revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_UNSPEC,
.checkentry = connmark_tg_check,
.target = connmark_tg,
.targetsize = sizeof(struct xt_connmark_tginfo1),
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 76ca1f2421eb..b54c3756fdc3 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -43,7 +43,7 @@ static void secmark_save(const struct sk_buff *skb)
ct = nf_ct_get(skb, &ctinfo);
if (ct && !ct->secmark) {
ct->secmark = skb->secmark;
- nf_conntrack_event_cache(IPCT_SECMARK, skb);
+ nf_conntrack_event_cache(IPCT_SECMARK, ct);
}
}
}
@@ -65,11 +65,9 @@ static void secmark_restore(struct sk_buff *skb)
}
static unsigned int
-connsecmark_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+connsecmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_connsecmark_target_info *info = targinfo;
+ const struct xt_connsecmark_target_info *info = par->targinfo;
switch (info->mode) {
case CONNSECMARK_SAVE:
@@ -87,16 +85,14 @@ connsecmark_tg(struct sk_buff *skb, const struct net_device *in,
return XT_CONTINUE;
}
-static bool
-connsecmark_tg_check(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool connsecmark_tg_check(const struct xt_tgchk_param *par)
{
- const struct xt_connsecmark_target_info *info = targinfo;
+ const struct xt_connsecmark_target_info *info = par->targinfo;
- if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) {
+ if (strcmp(par->table, "mangle") != 0 &&
+ strcmp(par->table, "security") != 0) {
printk(KERN_INFO PFX "target only valid in the \'mangle\' "
- "or \'security\' tables, not \'%s\'.\n", tablename);
+ "or \'security\' tables, not \'%s\'.\n", par->table);
return false;
}
@@ -110,51 +106,38 @@ connsecmark_tg_check(const char *tablename, const void *entry,
return false;
}
- if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%u\n", target->family);
+ "proto=%u\n", par->family);
return false;
}
return true;
}
-static void
-connsecmark_tg_destroy(const struct xt_target *target, void *targinfo)
+static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
{
- nf_ct_l3proto_module_put(target->family);
+ nf_ct_l3proto_module_put(par->family);
}
-static struct xt_target connsecmark_tg_reg[] __read_mostly = {
- {
- .name = "CONNSECMARK",
- .family = AF_INET,
- .checkentry = connsecmark_tg_check,
- .destroy = connsecmark_tg_destroy,
- .target = connsecmark_tg,
- .targetsize = sizeof(struct xt_connsecmark_target_info),
- .me = THIS_MODULE,
- },
- {
- .name = "CONNSECMARK",
- .family = AF_INET6,
- .checkentry = connsecmark_tg_check,
- .destroy = connsecmark_tg_destroy,
- .target = connsecmark_tg,
- .targetsize = sizeof(struct xt_connsecmark_target_info),
- .me = THIS_MODULE,
- },
+static struct xt_target connsecmark_tg_reg __read_mostly = {
+ .name = "CONNSECMARK",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = connsecmark_tg_check,
+ .destroy = connsecmark_tg_destroy,
+ .target = connsecmark_tg,
+ .targetsize = sizeof(struct xt_connsecmark_target_info),
+ .me = THIS_MODULE,
};
static int __init connsecmark_tg_init(void)
{
- return xt_register_targets(connsecmark_tg_reg,
- ARRAY_SIZE(connsecmark_tg_reg));
+ return xt_register_target(&connsecmark_tg_reg);
}
static void __exit connsecmark_tg_exit(void)
{
- xt_unregister_targets(connsecmark_tg_reg,
- ARRAY_SIZE(connsecmark_tg_reg));
+ xt_unregister_target(&connsecmark_tg_reg);
}
module_init(connsecmark_tg_init);
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 97efd74c04fe..6a347e768f86 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -29,11 +29,9 @@ MODULE_ALIAS("ipt_TOS");
MODULE_ALIAS("ip6t_TOS");
static unsigned int
-dscp_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+dscp_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_DSCP_info *dinfo = targinfo;
+ const struct xt_DSCP_info *dinfo = par->targinfo;
u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
if (dscp != dinfo->dscp) {
@@ -48,11 +46,9 @@ dscp_tg(struct sk_buff *skb, const struct net_device *in,
}
static unsigned int
-dscp_tg6(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_DSCP_info *dinfo = targinfo;
+ const struct xt_DSCP_info *dinfo = par->targinfo;
u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
if (dscp != dinfo->dscp) {
@@ -65,26 +61,21 @@ dscp_tg6(struct sk_buff *skb, const struct net_device *in,
return XT_CONTINUE;
}
-static bool
-dscp_tg_check(const char *tablename, const void *e_void,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool dscp_tg_check(const struct xt_tgchk_param *par)
{
- const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp;
+ const struct xt_DSCP_info *info = par->targinfo;
- if (dscp > XT_DSCP_MAX) {
- printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
+ if (info->dscp > XT_DSCP_MAX) {
+ printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp);
return false;
}
return true;
}
static unsigned int
-tos_tg_v0(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+tos_tg_v0(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct ipt_tos_target_info *info = targinfo;
+ const struct ipt_tos_target_info *info = par->targinfo;
struct iphdr *iph = ip_hdr(skb);
u_int8_t oldtos;
@@ -101,12 +92,10 @@ tos_tg_v0(struct sk_buff *skb, const struct net_device *in,
return XT_CONTINUE;
}
-static bool
-tos_tg_check_v0(const char *tablename, const void *e_void,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool tos_tg_check_v0(const struct xt_tgchk_param *par)
{
- const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos;
+ const struct ipt_tos_target_info *info = par->targinfo;
+ const uint8_t tos = info->tos;
if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT &&
tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST &&
@@ -119,11 +108,9 @@ tos_tg_check_v0(const char *tablename, const void *e_void,
}
static unsigned int
-tos_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+tos_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_tos_target_info *info = targinfo;
+ const struct xt_tos_target_info *info = par->targinfo;
struct iphdr *iph = ip_hdr(skb);
u_int8_t orig, nv;
@@ -141,11 +128,9 @@ tos_tg(struct sk_buff *skb, const struct net_device *in,
}
static unsigned int
-tos_tg6(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+tos_tg6(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_tos_target_info *info = targinfo;
+ const struct xt_tos_target_info *info = par->targinfo;
struct ipv6hdr *iph = ipv6_hdr(skb);
u_int8_t orig, nv;
@@ -165,7 +150,7 @@ tos_tg6(struct sk_buff *skb, const struct net_device *in,
static struct xt_target dscp_tg_reg[] __read_mostly = {
{
.name = "DSCP",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = dscp_tg_check,
.target = dscp_tg,
.targetsize = sizeof(struct xt_DSCP_info),
@@ -174,7 +159,7 @@ static struct xt_target dscp_tg_reg[] __read_mostly = {
},
{
.name = "DSCP",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = dscp_tg_check,
.target = dscp_tg6,
.targetsize = sizeof(struct xt_DSCP_info),
@@ -184,7 +169,7 @@ static struct xt_target dscp_tg_reg[] __read_mostly = {
{
.name = "TOS",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.table = "mangle",
.target = tos_tg_v0,
.targetsize = sizeof(struct ipt_tos_target_info),
@@ -194,7 +179,7 @@ static struct xt_target dscp_tg_reg[] __read_mostly = {
{
.name = "TOS",
.revision = 1,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.table = "mangle",
.target = tos_tg,
.targetsize = sizeof(struct xt_tos_target_info),
@@ -203,7 +188,7 @@ static struct xt_target dscp_tg_reg[] __read_mostly = {
{
.name = "TOS",
.revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.table = "mangle",
.target = tos_tg6,
.targetsize = sizeof(struct xt_tos_target_info),
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index f9ce20b58981..67574bcfb8ac 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -25,22 +25,18 @@ MODULE_ALIAS("ipt_MARK");
MODULE_ALIAS("ip6t_MARK");
static unsigned int
-mark_tg_v0(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+mark_tg_v0(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_mark_target_info *markinfo = targinfo;
+ const struct xt_mark_target_info *markinfo = par->targinfo;
skb->mark = markinfo->mark;
return XT_CONTINUE;
}
static unsigned int
-mark_tg_v1(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+mark_tg_v1(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_mark_target_info_v1 *markinfo = targinfo;
+ const struct xt_mark_target_info_v1 *markinfo = par->targinfo;
int mark = 0;
switch (markinfo->mode) {
@@ -62,22 +58,17 @@ mark_tg_v1(struct sk_buff *skb, const struct net_device *in,
}
static unsigned int
-mark_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+mark_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_mark_tginfo2 *info = targinfo;
+ const struct xt_mark_tginfo2 *info = par->targinfo;
skb->mark = (skb->mark & ~info->mask) ^ info->mark;
return XT_CONTINUE;
}
-static bool
-mark_tg_check_v0(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool mark_tg_check_v0(const struct xt_tgchk_param *par)
{
- const struct xt_mark_target_info *markinfo = targinfo;
+ const struct xt_mark_target_info *markinfo = par->targinfo;
if (markinfo->mark > 0xffffffff) {
printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
@@ -86,12 +77,9 @@ mark_tg_check_v0(const char *tablename, const void *entry,
return true;
}
-static bool
-mark_tg_check_v1(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool mark_tg_check_v1(const struct xt_tgchk_param *par)
{
- const struct xt_mark_target_info_v1 *markinfo = targinfo;
+ const struct xt_mark_target_info_v1 *markinfo = par->targinfo;
if (markinfo->mode != XT_MARK_SET
&& markinfo->mode != XT_MARK_AND
@@ -161,7 +149,7 @@ static int mark_tg_compat_to_user_v1(void __user *dst, void *src)
static struct xt_target mark_tg_reg[] __read_mostly = {
{
.name = "MARK",
- .family = AF_INET,
+ .family = NFPROTO_UNSPEC,
.revision = 0,
.checkentry = mark_tg_check_v0,
.target = mark_tg_v0,
@@ -176,7 +164,7 @@ static struct xt_target mark_tg_reg[] __read_mostly = {
},
{
.name = "MARK",
- .family = AF_INET,
+ .family = NFPROTO_UNSPEC,
.revision = 1,
.checkentry = mark_tg_check_v1,
.target = mark_tg_v1,
@@ -190,47 +178,9 @@ static struct xt_target mark_tg_reg[] __read_mostly = {
.me = THIS_MODULE,
},
{
- .name = "MARK",
- .family = AF_INET6,
- .revision = 0,
- .checkentry = mark_tg_check_v0,
- .target = mark_tg_v0,
- .targetsize = sizeof(struct xt_mark_target_info),
-#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_xt_mark_target_info),
- .compat_from_user = mark_tg_compat_from_user_v0,
- .compat_to_user = mark_tg_compat_to_user_v0,
-#endif
- .table = "mangle",
- .me = THIS_MODULE,
- },
- {
- .name = "MARK",
- .family = AF_INET6,
- .revision = 1,
- .checkentry = mark_tg_check_v1,
- .target = mark_tg_v1,
- .targetsize = sizeof(struct xt_mark_target_info_v1),
-#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_xt_mark_target_info_v1),
- .compat_from_user = mark_tg_compat_from_user_v1,
- .compat_to_user = mark_tg_compat_to_user_v1,
-#endif
- .table = "mangle",
- .me = THIS_MODULE,
- },
- {
- .name = "MARK",
- .revision = 2,
- .family = AF_INET,
- .target = mark_tg,
- .targetsize = sizeof(struct xt_mark_tginfo2),
- .me = THIS_MODULE,
- },
- {
.name = "MARK",
.revision = 2,
- .family = AF_INET6,
+ .family = NFPROTO_UNSPEC,
.target = mark_tg,
.targetsize = sizeof(struct xt_mark_tginfo2),
.me = THIS_MODULE,
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index 19ae8efae655..50e3a52d3b31 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -21,11 +21,9 @@ MODULE_ALIAS("ipt_NFLOG");
MODULE_ALIAS("ip6t_NFLOG");
static unsigned int
-nflog_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+nflog_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_nflog_info *info = targinfo;
+ const struct xt_nflog_info *info = par->targinfo;
struct nf_loginfo li;
li.type = NF_LOG_TYPE_ULOG;
@@ -33,17 +31,14 @@ nflog_tg(struct sk_buff *skb, const struct net_device *in,
li.u.ulog.group = info->group;
li.u.ulog.qthreshold = info->threshold;
- nf_log_packet(target->family, hooknum, skb, in, out, &li,
- "%s", info->prefix);
+ nf_log_packet(par->family, par->hooknum, skb, par->in,
+ par->out, &li, "%s", info->prefix);
return XT_CONTINUE;
}
-static bool
-nflog_tg_check(const char *tablename, const void *entry,
- const struct xt_target *target, void *targetinfo,
- unsigned int hookmask)
+static bool nflog_tg_check(const struct xt_tgchk_param *par)
{
- const struct xt_nflog_info *info = targetinfo;
+ const struct xt_nflog_info *info = par->targinfo;
if (info->flags & ~XT_NFLOG_MASK)
return false;
@@ -52,33 +47,24 @@ nflog_tg_check(const char *tablename, const void *entry,
return true;
}
-static struct xt_target nflog_tg_reg[] __read_mostly = {
- {
- .name = "NFLOG",
- .family = AF_INET,
- .checkentry = nflog_tg_check,
- .target = nflog_tg,
- .targetsize = sizeof(struct xt_nflog_info),
- .me = THIS_MODULE,
- },
- {
- .name = "NFLOG",
- .family = AF_INET6,
- .checkentry = nflog_tg_check,
- .target = nflog_tg,
- .targetsize = sizeof(struct xt_nflog_info),
- .me = THIS_MODULE,
- },
+static struct xt_target nflog_tg_reg __read_mostly = {
+ .name = "NFLOG",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = nflog_tg_check,
+ .target = nflog_tg,
+ .targetsize = sizeof(struct xt_nflog_info),
+ .me = THIS_MODULE,
};
static int __init nflog_tg_init(void)
{
- return xt_register_targets(nflog_tg_reg, ARRAY_SIZE(nflog_tg_reg));
+ return xt_register_target(&nflog_tg_reg);
}
static void __exit nflog_tg_exit(void)
{
- xt_unregister_targets(nflog_tg_reg, ARRAY_SIZE(nflog_tg_reg));
+ xt_unregister_target(&nflog_tg_reg);
}
module_init(nflog_tg_init);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index beb24d19a56f..2cc1fff49307 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -24,11 +24,9 @@ MODULE_ALIAS("ip6t_NFQUEUE");
MODULE_ALIAS("arpt_NFQUEUE");
static unsigned int
-nfqueue_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_NFQ_info *tinfo = targinfo;
+ const struct xt_NFQ_info *tinfo = par->targinfo;
return NF_QUEUE_NR(tinfo->queuenum);
}
@@ -36,14 +34,14 @@ nfqueue_tg(struct sk_buff *skb, const struct net_device *in,
static struct xt_target nfqueue_tg_reg[] __read_mostly = {
{
.name = "NFQUEUE",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.target = nfqueue_tg,
.targetsize = sizeof(struct xt_NFQ_info),
.me = THIS_MODULE,
},
{
.name = "NFQUEUE",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.target = nfqueue_tg,
.targetsize = sizeof(struct xt_NFQ_info),
.me = THIS_MODULE,
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 6c9de611eb8d..e7a0a54fd4ea 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -13,9 +13,7 @@ MODULE_ALIAS("ipt_NOTRACK");
MODULE_ALIAS("ip6t_NOTRACK");
static unsigned int
-notrack_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+notrack_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
/* Previously seen (loopback)? Ignore. */
if (skb->nfct != NULL)
@@ -32,31 +30,23 @@ notrack_tg(struct sk_buff *skb, const struct net_device *in,
return XT_CONTINUE;
}
-static struct xt_target notrack_tg_reg[] __read_mostly = {
- {
- .name = "NOTRACK",
- .family = AF_INET,
- .target = notrack_tg,
- .table = "raw",
- .me = THIS_MODULE,
- },
- {
- .name = "NOTRACK",
- .family = AF_INET6,
- .target = notrack_tg,
- .table = "raw",
- .me = THIS_MODULE,
- },
+static struct xt_target notrack_tg_reg __read_mostly = {
+ .name = "NOTRACK",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .target = notrack_tg,
+ .table = "raw",
+ .me = THIS_MODULE,
};
static int __init notrack_tg_init(void)
{
- return xt_register_targets(notrack_tg_reg, ARRAY_SIZE(notrack_tg_reg));
+ return xt_register_target(&notrack_tg_reg);
}
static void __exit notrack_tg_exit(void)
{
- xt_unregister_targets(notrack_tg_reg, ARRAY_SIZE(notrack_tg_reg));
+ xt_unregister_target(&notrack_tg_reg);
}
module_init(notrack_tg_init);
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
index 64d6ad380293..43f5676b1af4 100644
--- a/net/netfilter/xt_RATEEST.c
+++ b/net/netfilter/xt_RATEEST.c
@@ -71,14 +71,9 @@ void xt_rateest_put(struct xt_rateest *est)
EXPORT_SYMBOL_GPL(xt_rateest_put);
static unsigned int
-xt_rateest_tg(struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- unsigned int hooknum,
- const struct xt_target *target,
- const void *targinfo)
+xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
- const struct xt_rateest_target_info *info = targinfo;
+ const struct xt_rateest_target_info *info = par->targinfo;
struct gnet_stats_basic *stats = &info->est->bstats;
spin_lock_bh(&info->est->lock);
@@ -89,14 +84,9 @@ xt_rateest_tg(struct sk_buff *skb,
return XT_CONTINUE;
}
-static bool
-xt_rateest_tg_checkentry(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
{
- struct xt_rateest_target_info *info = targinfo;
+ struct xt_rateest_target_info *info = par->targinfo;
struct xt_rateest *est;
struct {
struct nlattr opt;
@@ -149,33 +139,22 @@ err1:
return false;
}
-static void xt_rateest_tg_destroy(const struct xt_target *target,
- void *targinfo)
+static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par)
{
- struct xt_rateest_target_info *info = targinfo;
+ struct xt_rateest_target_info *info = par->targinfo;
xt_rateest_put(info->est);
}
-static struct xt_target xt_rateest_target[] __read_mostly = {
- {
- .family = AF_INET,
- .name = "RATEEST",
- .target = xt_rateest_tg,
- .checkentry = xt_rateest_tg_checkentry,
- .destroy = xt_rateest_tg_destroy,
- .targetsize = sizeof(struct xt_rateest_target_info),
- .me = THIS_MODULE,
- },
- {
- .family = AF_INET6,
- .name = "RATEEST",
- .target = xt_rateest_tg,
- .checkentry = xt_rateest_tg_checkentry,
- .destroy = xt_rateest_tg_destroy,
- .targetsize = sizeof(struct xt_rateest_target_info),
- .me = THIS_MODULE,
- },
+static struct xt_target xt_rateest_tg_reg __read_mostly = {
+ .name = "RATEEST",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .target = xt_rateest_tg,
+ .checkentry = xt_rateest_tg_checkentry,
+ .destroy = xt_rateest_tg_destroy,
+ .targetsize = sizeof(struct xt_rateest_target_info),
+ .me = THIS_MODULE,
};
static int __init xt_rateest_tg_init(void)
@@ -186,13 +165,12 @@ static int __init xt_rateest_tg_init(void)
INIT_HLIST_HEAD(&rateest_hash[i]);
get_random_bytes(&jhash_rnd, sizeof(jhash_rnd));
- return xt_register_targets(xt_rateest_target,
- ARRAY_SIZE(xt_rateest_target));
+ return xt_register_target(&xt_rateest_tg_reg);
}
static void __exit xt_rateest_tg_fini(void)
{
- xt_unregister_targets(xt_rateest_target, ARRAY_SIZE(xt_rateest_target));
+ xt_unregister_target(&xt_rateest_tg_reg);
}
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 94f87ee7552b..7a6f9e6f5dfa 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -29,12 +29,10 @@ MODULE_ALIAS("ip6t_SECMARK");
static u8 mode;
static unsigned int
-secmark_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+secmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
u32 secmark = 0;
- const struct xt_secmark_target_info *info = targinfo;
+ const struct xt_secmark_target_info *info = par->targinfo;
BUG_ON(info->mode != mode);
@@ -82,16 +80,14 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
return true;
}
-static bool
-secmark_tg_check(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool secmark_tg_check(const struct xt_tgchk_param *par)
{
- struct xt_secmark_target_info *info = targinfo;
+ struct xt_secmark_target_info *info = par->targinfo;
- if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) {
+ if (strcmp(par->table, "mangle") != 0 &&
+ strcmp(par->table, "security") != 0) {
printk(KERN_INFO PFX "target only valid in the \'mangle\' "
- "or \'security\' tables, not \'%s\'.\n", tablename);
+ "or \'security\' tables, not \'%s\'.\n", par->table);
return false;
}
@@ -117,7 +113,7 @@ secmark_tg_check(const char *tablename, const void *entry,
return true;
}
-static void secmark_tg_destroy(const struct xt_target *target, void *targinfo)
+static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
{
switch (mode) {
case SECMARK_MODE_SEL:
@@ -125,35 +121,25 @@ static void secmark_tg_destroy(const struct xt_target *target, void *targinfo)
}
}
-static struct xt_target secmark_tg_reg[] __read_mostly = {
- {
- .name = "SECMARK",
- .family = AF_INET,
- .checkentry = secmark_tg_check,
- .destroy = secmark_tg_destroy,
- .target = secmark_tg,
- .targetsize = sizeof(struct xt_secmark_target_info),
- .me = THIS_MODULE,
- },
- {
- .name = "SECMARK",
- .family = AF_INET6,
- .checkentry = secmark_tg_check,
- .destroy = secmark_tg_destroy,
- .target = secmark_tg,
- .targetsize = sizeof(struct xt_secmark_target_info),
- .me = THIS_MODULE,
- },
+static struct xt_target secmark_tg_reg __read_mostly = {
+ .name = "SECMARK",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = secmark_tg_check,
+ .destroy = secmark_tg_destroy,
+ .target = secmark_tg,
+ .targetsize = sizeof(struct xt_secmark_target_info),
+ .me = THIS_MODULE,
};
static int __init secmark_tg_init(void)
{
- return xt_register_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
+ return xt_register_target(&secmark_tg_reg);
}
static void __exit secmark_tg_exit(void)
{
- xt_unregister_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
+ xt_unregister_target(&secmark_tg_reg);
}
module_init(secmark_tg_init);
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index beb5094703cb..4f3b1f808795 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -174,15 +174,13 @@ static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
}
static unsigned int
-tcpmss_tg4(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+tcpmss_tg4(struct sk_buff *skb, const struct xt_target_param *par)
{
struct iphdr *iph = ip_hdr(skb);
__be16 newlen;
int ret;
- ret = tcpmss_mangle_packet(skb, targinfo,
+ ret = tcpmss_mangle_packet(skb, par->targinfo,
tcpmss_reverse_mtu(skb, PF_INET),
iph->ihl * 4,
sizeof(*iph) + sizeof(struct tcphdr));
@@ -199,9 +197,7 @@ tcpmss_tg4(struct sk_buff *skb, const struct net_device *in,
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
static unsigned int
-tcpmss_tg6(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+tcpmss_tg6(struct sk_buff *skb, const struct xt_target_param *par)
{
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
u8 nexthdr;
@@ -212,7 +208,7 @@ tcpmss_tg6(struct sk_buff *skb, const struct net_device *in,
tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr);
if (tcphoff < 0)
return NF_DROP;
- ret = tcpmss_mangle_packet(skb, targinfo,
+ ret = tcpmss_mangle_packet(skb, par->targinfo,
tcpmss_reverse_mtu(skb, PF_INET6),
tcphoff,
sizeof(*ipv6h) + sizeof(struct tcphdr));
@@ -241,16 +237,13 @@ static inline bool find_syn_match(const struct xt_entry_match *m)
return false;
}
-static bool
-tcpmss_tg4_check(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
{
- const struct xt_tcpmss_info *info = targinfo;
- const struct ipt_entry *e = entry;
+ const struct xt_tcpmss_info *info = par->targinfo;
+ const struct ipt_entry *e = par->entryinfo;
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
- (hook_mask & ~((1 << NF_INET_FORWARD) |
+ (par->hook_mask & ~((1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING))) != 0) {
printk("xt_TCPMSS: path-MTU clamping only supported in "
@@ -264,16 +257,13 @@ tcpmss_tg4_check(const char *tablename, const void *entry,
}
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
-static bool
-tcpmss_tg6_check(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
{
- const struct xt_tcpmss_info *info = targinfo;
- const struct ip6t_entry *e = entry;
+ const struct xt_tcpmss_info *info = par->targinfo;
+ const struct ip6t_entry *e = par->entryinfo;
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
- (hook_mask & ~((1 << NF_INET_FORWARD) |
+ (par->hook_mask & ~((1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING))) != 0) {
printk("xt_TCPMSS: path-MTU clamping only supported in "
@@ -289,7 +279,7 @@ tcpmss_tg6_check(const char *tablename, const void *entry,
static struct xt_target tcpmss_tg_reg[] __read_mostly = {
{
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.name = "TCPMSS",
.checkentry = tcpmss_tg4_check,
.target = tcpmss_tg4,
@@ -299,7 +289,7 @@ static struct xt_target tcpmss_tg_reg[] __read_mostly = {
},
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
{
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.name = "TCPMSS",
.checkentry = tcpmss_tg6_check,
.target = tcpmss_tg6,
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
index 9685b6fcbc81..9dd8c8ef63eb 100644
--- a/net/netfilter/xt_TCPOPTSTRIP.c
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -75,19 +75,15 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
}
static unsigned int
-tcpoptstrip_tg4(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_target_param *par)
{
- return tcpoptstrip_mangle_packet(skb, targinfo, ip_hdrlen(skb),
+ return tcpoptstrip_mangle_packet(skb, par->targinfo, ip_hdrlen(skb),
sizeof(struct iphdr) + sizeof(struct tcphdr));
}
#if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE)
static unsigned int
-tcpoptstrip_tg6(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_target_param *par)
{
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
int tcphoff;
@@ -98,7 +94,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct net_device *in,
if (tcphoff < 0)
return NF_DROP;
- return tcpoptstrip_mangle_packet(skb, targinfo, tcphoff,
+ return tcpoptstrip_mangle_packet(skb, par->targinfo, tcphoff,
sizeof(*ipv6h) + sizeof(struct tcphdr));
}
#endif
@@ -106,7 +102,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct net_device *in,
static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = {
{
.name = "TCPOPTSTRIP",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.table = "mangle",
.proto = IPPROTO_TCP,
.target = tcpoptstrip_tg4,
@@ -116,7 +112,7 @@ static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = {
#if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE)
{
.name = "TCPOPTSTRIP",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.table = "mangle",
.proto = IPPROTO_TCP,
.target = tcpoptstrip_tg6,
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
new file mode 100644
index 000000000000..1340c2fa3621
--- /dev/null
+++ b/net/netfilter/xt_TPROXY.c
@@ -0,0 +1,102 @@
+/*
+ * Transparent proxy support for Linux/iptables
+ *
+ * Copyright (c) 2006-2007 BalaBit IT Ltd.
+ * Author: Balazs Scheidler, Krisztian Kovacs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+#include <net/inet_sock.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/xt_TPROXY.h>
+
+#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
+#include <net/netfilter/nf_tproxy_core.h>
+
+static unsigned int
+tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+ const struct xt_tproxy_target_info *tgi = par->targinfo;
+ struct udphdr _hdr, *hp;
+ struct sock *sk;
+
+ hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+ return NF_DROP;
+
+ sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
+ iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr,
+ hp->source, tgi->lport ? tgi->lport : hp->dest,
+ par->in, true);
+
+ /* NOTE: assign_sock consumes our sk reference */
+ if (sk && nf_tproxy_assign_sock(skb, sk)) {
+ /* This should be in a separate target, but we don't do multiple
+ targets on the same rule yet */
+ skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
+
+ pr_debug("redirecting: proto %u %08x:%u -> %08x:%u, mark: %x\n",
+ iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
+ ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
+ return NF_ACCEPT;
+ }
+
+ pr_debug("no socket, dropping: proto %u %08x:%u -> %08x:%u, mark: %x\n",
+ iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
+ ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
+ return NF_DROP;
+}
+
+static bool tproxy_tg_check(const struct xt_tgchk_param *par)
+{
+ const struct ipt_ip *i = par->entryinfo;
+
+ if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
+ && !(i->invflags & IPT_INV_PROTO))
+ return true;
+
+ pr_info("xt_TPROXY: Can be used only in combination with "
+ "either -p tcp or -p udp\n");
+ return false;
+}
+
+static struct xt_target tproxy_tg_reg __read_mostly = {
+ .name = "TPROXY",
+ .family = AF_INET,
+ .table = "mangle",
+ .target = tproxy_tg,
+ .targetsize = sizeof(struct xt_tproxy_target_info),
+ .checkentry = tproxy_tg_check,
+ .hooks = 1 << NF_INET_PRE_ROUTING,
+ .me = THIS_MODULE,
+};
+
+static int __init tproxy_tg_init(void)
+{
+ nf_defrag_ipv4_enable();
+ return xt_register_target(&tproxy_tg_reg);
+}
+
+static void __exit tproxy_tg_exit(void)
+{
+ xt_unregister_target(&tproxy_tg_reg);
+}
+
+module_init(tproxy_tg_init);
+module_exit(tproxy_tg_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Krisztian Kovacs");
+MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) target module.");
+MODULE_ALIAS("ipt_TPROXY");
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
index 30dab79a3438..fbb04b86c46b 100644
--- a/net/netfilter/xt_TRACE.c
+++ b/net/netfilter/xt_TRACE.c
@@ -11,39 +11,29 @@ MODULE_ALIAS("ipt_TRACE");
MODULE_ALIAS("ip6t_TRACE");
static unsigned int
-trace_tg(struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, unsigned int hooknum,
- const struct xt_target *target, const void *targinfo)
+trace_tg(struct sk_buff *skb, const struct xt_target_param *par)
{
skb->nf_trace = 1;
return XT_CONTINUE;
}
-static struct xt_target trace_tg_reg[] __read_mostly = {
- {
- .name = "TRACE",
- .family = AF_INET,
- .target = trace_tg,
- .table = "raw",
- .me = THIS_MODULE,
- },
- {
- .name = "TRACE",
- .family = AF_INET6,
- .target = trace_tg,
- .table = "raw",
- .me = THIS_MODULE,
- },
+static struct xt_target trace_tg_reg __read_mostly = {
+ .name = "TRACE",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .table = "raw",
+ .target = trace_tg,
+ .me = THIS_MODULE,
};
static int __init trace_tg_init(void)
{
- return xt_register_targets(trace_tg_reg, ARRAY_SIZE(trace_tg_reg));
+ return xt_register_target(&trace_tg_reg);
}
static void __exit trace_tg_exit(void)
{
- xt_unregister_targets(trace_tg_reg, ARRAY_SIZE(trace_tg_reg));
+ xt_unregister_target(&trace_tg_reg);
}
module_init(trace_tg_init);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 89f47364e848..e82179832acd 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -16,40 +16,29 @@ MODULE_ALIAS("ipt_comment");
MODULE_ALIAS("ip6t_comment");
static bool
-comment_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protooff,
- bool *hotdrop)
+comment_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
/* We always match */
return true;
}
-static struct xt_match comment_mt_reg[] __read_mostly = {
- {
- .name = "comment",
- .family = AF_INET,
- .match = comment_mt,
- .matchsize = sizeof(struct xt_comment_info),
- .me = THIS_MODULE
- },
- {
- .name = "comment",
- .family = AF_INET6,
- .match = comment_mt,
- .matchsize = sizeof(struct xt_comment_info),
- .me = THIS_MODULE
- },
+static struct xt_match comment_mt_reg __read_mostly = {
+ .name = "comment",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = comment_mt,
+ .matchsize = sizeof(struct xt_comment_info),
+ .me = THIS_MODULE,
};
static int __init comment_mt_init(void)
{
- return xt_register_matches(comment_mt_reg, ARRAY_SIZE(comment_mt_reg));
+ return xt_register_match(&comment_mt_reg);
}
static void __exit comment_mt_exit(void)
{
- xt_unregister_matches(comment_mt_reg, ARRAY_SIZE(comment_mt_reg));
+ xt_unregister_match(&comment_mt_reg);
}
module_init(comment_mt_init);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 3e39c4fe1931..955e6598a7f0 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -17,12 +17,9 @@ MODULE_ALIAS("ipt_connbytes");
MODULE_ALIAS("ip6t_connbytes");
static bool
-connbytes_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+connbytes_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_connbytes_info *sinfo = matchinfo;
+ const struct xt_connbytes_info *sinfo = par->matchinfo;
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
u_int64_t what = 0; /* initialize to make gcc happy */
@@ -95,12 +92,9 @@ connbytes_mt(const struct sk_buff *skb, const struct net_device *in,
return what >= sinfo->count.from;
}
-static bool
-connbytes_mt_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool connbytes_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_connbytes_info *sinfo = matchinfo;
+ const struct xt_connbytes_info *sinfo = par->matchinfo;
if (sinfo->what != XT_CONNBYTES_PKTS &&
sinfo->what != XT_CONNBYTES_BYTES &&
@@ -112,51 +106,39 @@ connbytes_mt_check(const char *tablename, const void *ip,
sinfo->direction != XT_CONNBYTES_DIR_BOTH)
return false;
- if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%u\n", match->family);
+ "proto=%u\n", par->family);
return false;
}
return true;
}
-static void
-connbytes_mt_destroy(const struct xt_match *match, void *matchinfo)
+static void connbytes_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(match->family);
+ nf_ct_l3proto_module_put(par->family);
}
-static struct xt_match connbytes_mt_reg[] __read_mostly = {
- {
- .name = "connbytes",
- .family = AF_INET,
- .checkentry = connbytes_mt_check,
- .match = connbytes_mt,
- .destroy = connbytes_mt_destroy,
- .matchsize = sizeof(struct xt_connbytes_info),
- .me = THIS_MODULE
- },
- {
- .name = "connbytes",
- .family = AF_INET6,
- .checkentry = connbytes_mt_check,
- .match = connbytes_mt,
- .destroy = connbytes_mt_destroy,
- .matchsize = sizeof(struct xt_connbytes_info),
- .me = THIS_MODULE
- },
+static struct xt_match connbytes_mt_reg __read_mostly = {
+ .name = "connbytes",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = connbytes_mt_check,
+ .match = connbytes_mt,
+ .destroy = connbytes_mt_destroy,
+ .matchsize = sizeof(struct xt_connbytes_info),
+ .me = THIS_MODULE,
};
static int __init connbytes_mt_init(void)
{
- return xt_register_matches(connbytes_mt_reg,
- ARRAY_SIZE(connbytes_mt_reg));
+ return xt_register_match(&connbytes_mt_reg);
}
static void __exit connbytes_mt_exit(void)
{
- xt_unregister_matches(connbytes_mt_reg, ARRAY_SIZE(connbytes_mt_reg));
+ xt_unregister_match(&connbytes_mt_reg);
}
module_init(connbytes_mt_init);
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 70907f6baac3..7f404cc64c83 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -82,9 +82,9 @@ static inline bool already_closed(const struct nf_conn *conn)
static inline unsigned int
same_source_net(const union nf_inet_addr *addr,
const union nf_inet_addr *mask,
- const union nf_inet_addr *u3, unsigned int family)
+ const union nf_inet_addr *u3, u_int8_t family)
{
- if (family == AF_INET) {
+ if (family == NFPROTO_IPV4) {
return (addr->ip & mask->ip) == (u3->ip & mask->ip);
} else {
union nf_inet_addr lh, rh;
@@ -114,7 +114,7 @@ static int count_them(struct xt_connlimit_data *data,
int matches = 0;
- if (match->family == AF_INET6)
+ if (match->family == NFPROTO_IPV6)
hash = &data->iphash[connlimit_iphash6(addr, mask)];
else
hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)];
@@ -123,7 +123,7 @@ static int count_them(struct xt_connlimit_data *data,
/* check the saved connections */
list_for_each_entry_safe(conn, tmp, hash, list) {
- found = __nf_conntrack_find(&conn->tuple);
+ found = __nf_conntrack_find(&init_net, &conn->tuple);
found_ct = NULL;
if (found != NULL)
@@ -178,12 +178,9 @@ static int count_them(struct xt_connlimit_data *data,
}
static bool
-connlimit_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_connlimit_info *info = matchinfo;
+ const struct xt_connlimit_info *info = par->matchinfo;
union nf_inet_addr addr;
struct nf_conntrack_tuple tuple;
const struct nf_conntrack_tuple *tuple_ptr = &tuple;
@@ -195,10 +192,10 @@ connlimit_mt(const struct sk_buff *skb, const struct net_device *in,
if (ct != NULL)
tuple_ptr = &ct->tuplehash[0].tuple;
else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
- match->family, &tuple))
+ par->family, &tuple))
goto hotdrop;
- if (match->family == AF_INET6) {
+ if (par->family == NFPROTO_IPV6) {
const struct ipv6hdr *iph = ipv6_hdr(skb);
memcpy(&addr.ip6, &iph->saddr, sizeof(iph->saddr));
} else {
@@ -208,40 +205,37 @@ connlimit_mt(const struct sk_buff *skb, const struct net_device *in,
spin_lock_bh(&info->data->lock);
connections = count_them(info->data, tuple_ptr, &addr,
- &info->mask, match);
+ &info->mask, par->match);
spin_unlock_bh(&info->data->lock);
if (connections < 0) {
/* kmalloc failed, drop it entirely */
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
return (connections > info->limit) ^ info->inverse;
hotdrop:
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
-static bool
-connlimit_mt_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool connlimit_mt_check(const struct xt_mtchk_param *par)
{
- struct xt_connlimit_info *info = matchinfo;
+ struct xt_connlimit_info *info = par->matchinfo;
unsigned int i;
- if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "cannot load conntrack support for "
- "address family %u\n", match->family);
+ "address family %u\n", par->family);
return false;
}
/* init private data */
info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
if (info->data == NULL) {
- nf_ct_l3proto_module_put(match->family);
+ nf_ct_l3proto_module_put(par->family);
return false;
}
@@ -252,16 +246,15 @@ connlimit_mt_check(const char *tablename, const void *ip,
return true;
}
-static void
-connlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
+static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
{
- const struct xt_connlimit_info *info = matchinfo;
+ const struct xt_connlimit_info *info = par->matchinfo;
struct xt_connlimit_conn *conn;
struct xt_connlimit_conn *tmp;
struct list_head *hash = info->data->iphash;
unsigned int i;
- nf_ct_l3proto_module_put(match->family);
+ nf_ct_l3proto_module_put(par->family);
for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) {
list_for_each_entry_safe(conn, tmp, &hash[i], list) {
@@ -273,41 +266,30 @@ connlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
kfree(info->data);
}
-static struct xt_match connlimit_mt_reg[] __read_mostly = {
- {
- .name = "connlimit",
- .family = AF_INET,
- .checkentry = connlimit_mt_check,
- .match = connlimit_mt,
- .matchsize = sizeof(struct xt_connlimit_info),
- .destroy = connlimit_mt_destroy,
- .me = THIS_MODULE,
- },
- {
- .name = "connlimit",
- .family = AF_INET6,
- .checkentry = connlimit_mt_check,
- .match = connlimit_mt,
- .matchsize = sizeof(struct xt_connlimit_info),
- .destroy = connlimit_mt_destroy,
- .me = THIS_MODULE,
- },
+static struct xt_match connlimit_mt_reg __read_mostly = {
+ .name = "connlimit",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = connlimit_mt_check,
+ .match = connlimit_mt,
+ .matchsize = sizeof(struct xt_connlimit_info),
+ .destroy = connlimit_mt_destroy,
+ .me = THIS_MODULE,
};
static int __init connlimit_mt_init(void)
{
- return xt_register_matches(connlimit_mt_reg,
- ARRAY_SIZE(connlimit_mt_reg));
+ return xt_register_match(&connlimit_mt_reg);
}
static void __exit connlimit_mt_exit(void)
{
- xt_unregister_matches(connlimit_mt_reg, ARRAY_SIZE(connlimit_mt_reg));
+ xt_unregister_match(&connlimit_mt_reg);
}
module_init(connlimit_mt_init);
module_exit(connlimit_mt_exit);
-MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
+MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_DESCRIPTION("Xtables: Number of connections matching");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_connlimit");
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index aaa1b96691f9..86cacab7a4a3 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -34,12 +34,9 @@ MODULE_ALIAS("ipt_connmark");
MODULE_ALIAS("ip6t_connmark");
static bool
-connmark_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_connmark_mtinfo1 *info = matchinfo;
+ const struct xt_connmark_mtinfo1 *info = par->matchinfo;
enum ip_conntrack_info ctinfo;
const struct nf_conn *ct;
@@ -51,12 +48,9 @@ connmark_mt(const struct sk_buff *skb, const struct net_device *in,
}
static bool
-connmark_mt_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+connmark_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_connmark_info *info = matchinfo;
+ const struct xt_connmark_info *info = par->matchinfo;
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
@@ -67,42 +61,35 @@ connmark_mt_v0(const struct sk_buff *skb, const struct net_device *in,
return ((ct->mark & info->mask) == info->mark) ^ info->invert;
}
-static bool
-connmark_mt_check_v0(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool connmark_mt_check_v0(const struct xt_mtchk_param *par)
{
- const struct xt_connmark_info *cm = matchinfo;
+ const struct xt_connmark_info *cm = par->matchinfo;
if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
printk(KERN_WARNING "connmark: only support 32bit mark\n");
return false;
}
- if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%u\n", match->family);
+ "proto=%u\n", par->family);
return false;
}
return true;
}
-static bool
-connmark_mt_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool connmark_mt_check(const struct xt_mtchk_param *par)
{
- if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "cannot load conntrack support for "
- "proto=%u\n", match->family);
+ "proto=%u\n", par->family);
return false;
}
return true;
}
-static void
-connmark_mt_destroy(const struct xt_match *match, void *matchinfo)
+static void connmark_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(match->family);
+ nf_ct_l3proto_module_put(par->family);
}
#ifdef CONFIG_COMPAT
@@ -140,7 +127,7 @@ static struct xt_match connmark_mt_reg[] __read_mostly = {
{
.name = "connmark",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_UNSPEC,
.checkentry = connmark_mt_check_v0,
.match = connmark_mt_v0,
.destroy = connmark_mt_destroy,
@@ -153,34 +140,9 @@ static struct xt_match connmark_mt_reg[] __read_mostly = {
.me = THIS_MODULE
},
{
- .name = "connmark",
- .revision = 0,
- .family = AF_INET6,
- .checkentry = connmark_mt_check_v0,
- .match = connmark_mt_v0,
- .destroy = connmark_mt_destroy,
- .matchsize = sizeof(struct xt_connmark_info),
-#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_xt_connmark_info),
- .compat_from_user = connmark_mt_compat_from_user_v0,
- .compat_to_user = connmark_mt_compat_to_user_v0,
-#endif
- .me = THIS_MODULE
- },
- {
- .name = "connmark",
- .revision = 1,
- .family = AF_INET,
- .checkentry = connmark_mt_check,
- .match = connmark_mt,
- .matchsize = sizeof(struct xt_connmark_mtinfo1),
- .destroy = connmark_mt_destroy,
- .me = THIS_MODULE,
- },
- {
.name = "connmark",
.revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_UNSPEC,
.checkentry = connmark_mt_check,
.match = connmark_mt,
.matchsize = sizeof(struct xt_connmark_mtinfo1),
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index d61412f58ef7..0b7139f3dd78 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -25,12 +25,9 @@ MODULE_ALIAS("ipt_conntrack");
MODULE_ALIAS("ip6t_conntrack");
static bool
-conntrack_mt_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+conntrack_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_conntrack_info *sinfo = matchinfo;
+ const struct xt_conntrack_info *sinfo = par->matchinfo;
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
unsigned int statebit;
@@ -121,9 +118,9 @@ conntrack_addrcmp(const union nf_inet_addr *kaddr,
const union nf_inet_addr *uaddr,
const union nf_inet_addr *umask, unsigned int l3proto)
{
- if (l3proto == AF_INET)
+ if (l3proto == NFPROTO_IPV4)
return ((kaddr->ip ^ uaddr->ip) & umask->ip) == 0;
- else if (l3proto == AF_INET6)
+ else if (l3proto == NFPROTO_IPV6)
return ipv6_masked_addr_cmp(&kaddr->in6, &umask->in6,
&uaddr->in6) == 0;
else
@@ -133,7 +130,7 @@ conntrack_addrcmp(const union nf_inet_addr *kaddr,
static inline bool
conntrack_mt_origsrc(const struct nf_conn *ct,
const struct xt_conntrack_mtinfo1 *info,
- unsigned int family)
+ u_int8_t family)
{
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
&info->origsrc_addr, &info->origsrc_mask, family);
@@ -142,7 +139,7 @@ conntrack_mt_origsrc(const struct nf_conn *ct,
static inline bool
conntrack_mt_origdst(const struct nf_conn *ct,
const struct xt_conntrack_mtinfo1 *info,
- unsigned int family)
+ u_int8_t family)
{
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3,
&info->origdst_addr, &info->origdst_mask, family);
@@ -151,7 +148,7 @@ conntrack_mt_origdst(const struct nf_conn *ct,
static inline bool
conntrack_mt_replsrc(const struct nf_conn *ct,
const struct xt_conntrack_mtinfo1 *info,
- unsigned int family)
+ u_int8_t family)
{
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3,
&info->replsrc_addr, &info->replsrc_mask, family);
@@ -160,7 +157,7 @@ conntrack_mt_replsrc(const struct nf_conn *ct,
static inline bool
conntrack_mt_repldst(const struct nf_conn *ct,
const struct xt_conntrack_mtinfo1 *info,
- unsigned int family)
+ u_int8_t family)
{
return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3,
&info->repldst_addr, &info->repldst_mask, family);
@@ -205,12 +202,9 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
}
static bool
-conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_conntrack_mtinfo1 *info = matchinfo;
+ const struct xt_conntrack_mtinfo1 *info = par->matchinfo;
enum ip_conntrack_info ctinfo;
const struct nf_conn *ct;
unsigned int statebit;
@@ -244,22 +238,22 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
return false;
if (info->match_flags & XT_CONNTRACK_ORIGSRC)
- if (conntrack_mt_origsrc(ct, info, match->family) ^
+ if (conntrack_mt_origsrc(ct, info, par->family) ^
!(info->invert_flags & XT_CONNTRACK_ORIGSRC))
return false;
if (info->match_flags & XT_CONNTRACK_ORIGDST)
- if (conntrack_mt_origdst(ct, info, match->family) ^
+ if (conntrack_mt_origdst(ct, info, par->family) ^
!(info->invert_flags & XT_CONNTRACK_ORIGDST))
return false;
if (info->match_flags & XT_CONNTRACK_REPLSRC)
- if (conntrack_mt_replsrc(ct, info, match->family) ^
+ if (conntrack_mt_replsrc(ct, info, par->family) ^
!(info->invert_flags & XT_CONNTRACK_REPLSRC))
return false;
if (info->match_flags & XT_CONNTRACK_REPLDST)
- if (conntrack_mt_repldst(ct, info, match->family) ^
+ if (conntrack_mt_repldst(ct, info, par->family) ^
!(info->invert_flags & XT_CONNTRACK_REPLDST))
return false;
@@ -284,23 +278,19 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
return true;
}
-static bool
-conntrack_mt_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool conntrack_mt_check(const struct xt_mtchk_param *par)
{
- if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%u\n", match->family);
+ "proto=%u\n", par->family);
return false;
}
return true;
}
-static void
-conntrack_mt_destroy(const struct xt_match *match, void *matchinfo)
+static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(match->family);
+ nf_ct_l3proto_module_put(par->family);
}
#ifdef CONFIG_COMPAT
@@ -356,7 +346,7 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = {
{
.name = "conntrack",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = conntrack_mt_v0,
.checkentry = conntrack_mt_check,
.destroy = conntrack_mt_destroy,
@@ -371,17 +361,7 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = {
{
.name = "conntrack",
.revision = 1,
- .family = AF_INET,
- .matchsize = sizeof(struct xt_conntrack_mtinfo1),
- .match = conntrack_mt,
- .checkentry = conntrack_mt_check,
- .destroy = conntrack_mt_destroy,
- .me = THIS_MODULE,
- },
- {
- .name = "conntrack",
- .revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_UNSPEC,
.matchsize = sizeof(struct xt_conntrack_mtinfo1),
.match = conntrack_mt,
.checkentry = conntrack_mt_check,
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 8b6522186d9f..e5d3e8673287 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -93,20 +93,18 @@ match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
}
static bool
-dccp_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+dccp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_dccp_info *info = matchinfo;
+ const struct xt_dccp_info *info = par->matchinfo;
const struct dccp_hdr *dh;
struct dccp_hdr _dh;
- if (offset)
+ if (par->fragoff != 0)
return false;
- dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
+ dh = skb_header_pointer(skb, par->thoff, sizeof(_dh), &_dh);
if (dh == NULL) {
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
@@ -118,17 +116,14 @@ dccp_mt(const struct sk_buff *skb, const struct net_device *in,
XT_DCCP_DEST_PORTS, info->flags, info->invflags)
&& DCCHECK(match_types(dh, info->typemask),
XT_DCCP_TYPE, info->flags, info->invflags)
- && DCCHECK(match_option(info->option, skb, protoff, dh,
- hotdrop),
+ && DCCHECK(match_option(info->option, skb, par->thoff, dh,
+ par->hotdrop),
XT_DCCP_OPTION, info->flags, info->invflags);
}
-static bool
-dccp_mt_check(const char *tablename, const void *inf,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool dccp_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_dccp_info *info = matchinfo;
+ const struct xt_dccp_info *info = par->matchinfo;
return !(info->flags & ~XT_DCCP_VALID_FLAGS)
&& !(info->invflags & ~XT_DCCP_VALID_FLAGS)
@@ -138,7 +133,7 @@ dccp_mt_check(const char *tablename, const void *inf,
static struct xt_match dccp_mt_reg[] __read_mostly = {
{
.name = "dccp",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = dccp_mt_check,
.match = dccp_mt,
.matchsize = sizeof(struct xt_dccp_info),
@@ -147,7 +142,7 @@ static struct xt_match dccp_mt_reg[] __read_mostly = {
},
{
.name = "dccp",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = dccp_mt_check,
.match = dccp_mt,
.matchsize = sizeof(struct xt_dccp_info),
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index 26f4aab9c429..c3f8085460d7 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -26,61 +26,48 @@ MODULE_ALIAS("ipt_tos");
MODULE_ALIAS("ip6t_tos");
static bool
-dscp_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+dscp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_dscp_info *info = matchinfo;
+ const struct xt_dscp_info *info = par->matchinfo;
u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
return (dscp == info->dscp) ^ !!info->invert;
}
static bool
-dscp_mt6(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+dscp_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_dscp_info *info = matchinfo;
+ const struct xt_dscp_info *info = par->matchinfo;
u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
return (dscp == info->dscp) ^ !!info->invert;
}
-static bool
-dscp_mt_check(const char *tablename, const void *info,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool dscp_mt_check(const struct xt_mtchk_param *par)
{
- const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp;
+ const struct xt_dscp_info *info = par->matchinfo;
- if (dscp > XT_DSCP_MAX) {
- printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp);
+ if (info->dscp > XT_DSCP_MAX) {
+ printk(KERN_ERR "xt_dscp: dscp %x out of range\n", info->dscp);
return false;
}
return true;
}
-static bool tos_mt_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, bool *hotdrop)
+static bool
+tos_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ipt_tos_info *info = matchinfo;
+ const struct ipt_tos_info *info = par->matchinfo;
return (ip_hdr(skb)->tos == info->tos) ^ info->invert;
}
-static bool tos_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+static bool tos_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_tos_match_info *info = matchinfo;
+ const struct xt_tos_match_info *info = par->matchinfo;
- if (match->family == AF_INET)
+ if (par->match->family == NFPROTO_IPV4)
return ((ip_hdr(skb)->tos & info->tos_mask) ==
info->tos_value) ^ !!info->invert;
else
@@ -91,7 +78,7 @@ static bool tos_mt(const struct sk_buff *skb, const struct net_device *in,
static struct xt_match dscp_mt_reg[] __read_mostly = {
{
.name = "dscp",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = dscp_mt_check,
.match = dscp_mt,
.matchsize = sizeof(struct xt_dscp_info),
@@ -99,7 +86,7 @@ static struct xt_match dscp_mt_reg[] __read_mostly = {
},
{
.name = "dscp",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = dscp_mt_check,
.match = dscp_mt6,
.matchsize = sizeof(struct xt_dscp_info),
@@ -108,7 +95,7 @@ static struct xt_match dscp_mt_reg[] __read_mostly = {
{
.name = "tos",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = tos_mt_v0,
.matchsize = sizeof(struct ipt_tos_info),
.me = THIS_MODULE,
@@ -116,7 +103,7 @@ static struct xt_match dscp_mt_reg[] __read_mostly = {
{
.name = "tos",
.revision = 1,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = tos_mt,
.matchsize = sizeof(struct xt_tos_match_info),
.me = THIS_MODULE,
@@ -124,7 +111,7 @@ static struct xt_match dscp_mt_reg[] __read_mostly = {
{
.name = "tos",
.revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.match = tos_mt,
.matchsize = sizeof(struct xt_tos_match_info),
.me = THIS_MODULE,
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
index a133eb9b23e1..609439967c2c 100644
--- a/net/netfilter/xt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -42,26 +42,23 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
return r;
}
-static bool
-esp_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+static bool esp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct ip_esp_hdr *eh;
struct ip_esp_hdr _esp;
- const struct xt_esp *espinfo = matchinfo;
+ const struct xt_esp *espinfo = par->matchinfo;
/* Must not be a fragment. */
- if (offset)
+ if (par->fragoff != 0)
return false;
- eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
+ eh = skb_header_pointer(skb, par->thoff, sizeof(_esp), &_esp);
if (eh == NULL) {
/* We've been asked to examine this packet, and we
* can't. Hence, no choice but to drop.
*/
duprintf("Dropping evil ESP tinygram.\n");
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
@@ -69,13 +66,9 @@ esp_mt(const struct sk_buff *skb, const struct net_device *in,
!!(espinfo->invflags & XT_ESP_INV_SPI));
}
-/* Called when user tries to insert an entry of this type. */
-static bool
-esp_mt_check(const char *tablename, const void *ip_void,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool esp_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_esp *espinfo = matchinfo;
+ const struct xt_esp *espinfo = par->matchinfo;
if (espinfo->invflags & ~XT_ESP_INV_MASK) {
duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
@@ -88,7 +81,7 @@ esp_mt_check(const char *tablename, const void *ip_void,
static struct xt_match esp_mt_reg[] __read_mostly = {
{
.name = "esp",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = esp_mt_check,
.match = esp_mt,
.matchsize = sizeof(struct xt_esp),
@@ -97,7 +90,7 @@ static struct xt_match esp_mt_reg[] __read_mostly = {
},
{
.name = "esp",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = esp_mt_check,
.match = esp_mt,
.matchsize = sizeof(struct xt_esp),
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index d9418a267812..6fc4292d46e6 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -80,7 +80,7 @@ struct dsthash_ent {
struct xt_hashlimit_htable {
struct hlist_node node; /* global list of all htables */
atomic_t use;
- int family;
+ u_int8_t family;
struct hashlimit_cfg1 cfg; /* config */
@@ -185,7 +185,7 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent)
}
static void htable_gc(unsigned long htlong);
-static int htable_create_v0(struct xt_hashlimit_info *minfo, int family)
+static int htable_create_v0(struct xt_hashlimit_info *minfo, u_int8_t family)
{
struct xt_hashlimit_htable *hinfo;
unsigned int size;
@@ -218,7 +218,7 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, int family)
hinfo->cfg.gc_interval = minfo->cfg.gc_interval;
hinfo->cfg.expire = minfo->cfg.expire;
- if (family == AF_INET)
+ if (family == NFPROTO_IPV4)
hinfo->cfg.srcmask = hinfo->cfg.dstmask = 32;
else
hinfo->cfg.srcmask = hinfo->cfg.dstmask = 128;
@@ -237,11 +237,10 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, int family)
hinfo->family = family;
hinfo->rnd_initialized = 0;
spin_lock_init(&hinfo->lock);
- hinfo->pde =
- proc_create_data(minfo->name, 0,
- family == AF_INET ? hashlimit_procdir4 :
- hashlimit_procdir6,
- &dl_file_ops, hinfo);
+ hinfo->pde = proc_create_data(minfo->name, 0,
+ (family == NFPROTO_IPV4) ?
+ hashlimit_procdir4 : hashlimit_procdir6,
+ &dl_file_ops, hinfo);
if (!hinfo->pde) {
vfree(hinfo);
return -1;
@@ -258,8 +257,7 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, int family)
return 0;
}
-static int htable_create(struct xt_hashlimit_mtinfo1 *minfo,
- unsigned int family)
+static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, u_int8_t family)
{
struct xt_hashlimit_htable *hinfo;
unsigned int size;
@@ -301,11 +299,10 @@ static int htable_create(struct xt_hashlimit_mtinfo1 *minfo,
hinfo->rnd_initialized = 0;
spin_lock_init(&hinfo->lock);
- hinfo->pde =
- proc_create_data(minfo->name, 0,
- family == AF_INET ? hashlimit_procdir4 :
- hashlimit_procdir6,
- &dl_file_ops, hinfo);
+ hinfo->pde = proc_create_data(minfo->name, 0,
+ (family == NFPROTO_IPV4) ?
+ hashlimit_procdir4 : hashlimit_procdir6,
+ &dl_file_ops, hinfo);
if (hinfo->pde == NULL) {
vfree(hinfo);
return -1;
@@ -371,14 +368,14 @@ static void htable_destroy(struct xt_hashlimit_htable *hinfo)
/* remove proc entry */
remove_proc_entry(hinfo->pde->name,
- hinfo->family == AF_INET ? hashlimit_procdir4 :
+ hinfo->family == NFPROTO_IPV4 ? hashlimit_procdir4 :
hashlimit_procdir6);
htable_selective_cleanup(hinfo, select_all);
vfree(hinfo);
}
static struct xt_hashlimit_htable *htable_find_get(const char *name,
- int family)
+ u_int8_t family)
{
struct xt_hashlimit_htable *hinfo;
struct hlist_node *pos;
@@ -502,7 +499,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
memset(dst, 0, sizeof(*dst));
switch (hinfo->family) {
- case AF_INET:
+ case NFPROTO_IPV4:
if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP)
dst->ip.dst = maskl(ip_hdr(skb)->daddr,
hinfo->cfg.dstmask);
@@ -516,7 +513,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
nexthdr = ip_hdr(skb)->protocol;
break;
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
- case AF_INET6:
+ case NFPROTO_IPV6:
if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) {
memcpy(&dst->ip6.dst, &ipv6_hdr(skb)->daddr,
sizeof(dst->ip6.dst));
@@ -566,19 +563,16 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
}
static bool
-hashlimit_mt_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+hashlimit_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct xt_hashlimit_info *r =
- ((const struct xt_hashlimit_info *)matchinfo)->u.master;
+ ((const struct xt_hashlimit_info *)par->matchinfo)->u.master;
struct xt_hashlimit_htable *hinfo = r->hinfo;
unsigned long now = jiffies;
struct dsthash_ent *dh;
struct dsthash_dst dst;
- if (hashlimit_init_dst(hinfo, &dst, skb, protoff) < 0)
+ if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0)
goto hotdrop;
spin_lock_bh(&hinfo->lock);
@@ -616,23 +610,20 @@ hashlimit_mt_v0(const struct sk_buff *skb, const struct net_device *in,
return false;
hotdrop:
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
static bool
-hashlimit_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+hashlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_hashlimit_mtinfo1 *info = matchinfo;
+ const struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
struct xt_hashlimit_htable *hinfo = info->hinfo;
unsigned long now = jiffies;
struct dsthash_ent *dh;
struct dsthash_dst dst;
- if (hashlimit_init_dst(hinfo, &dst, skb, protoff) < 0)
+ if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0)
goto hotdrop;
spin_lock_bh(&hinfo->lock);
@@ -669,16 +660,13 @@ hashlimit_mt(const struct sk_buff *skb, const struct net_device *in,
return info->cfg.mode & XT_HASHLIMIT_INVERT;
hotdrop:
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
-static bool
-hashlimit_mt_check_v0(const char *tablename, const void *inf,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
{
- struct xt_hashlimit_info *r = matchinfo;
+ struct xt_hashlimit_info *r = par->matchinfo;
/* Check for overflow. */
if (r->cfg.burst == 0 ||
@@ -707,8 +695,8 @@ hashlimit_mt_check_v0(const char *tablename, const void *inf,
* the list of htable's in htable_create(), since then we would
* create duplicate proc files. -HW */
mutex_lock(&hlimit_mutex);
- r->hinfo = htable_find_get(r->name, match->family);
- if (!r->hinfo && htable_create_v0(r, match->family) != 0) {
+ r->hinfo = htable_find_get(r->name, par->match->family);
+ if (!r->hinfo && htable_create_v0(r, par->match->family) != 0) {
mutex_unlock(&hlimit_mutex);
return false;
}
@@ -719,12 +707,9 @@ hashlimit_mt_check_v0(const char *tablename, const void *inf,
return true;
}
-static bool
-hashlimit_mt_check(const char *tablename, const void *inf,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool hashlimit_mt_check(const struct xt_mtchk_param *par)
{
- struct xt_hashlimit_mtinfo1 *info = matchinfo;
+ struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
/* Check for overflow. */
if (info->cfg.burst == 0 ||
@@ -738,7 +723,7 @@ hashlimit_mt_check(const char *tablename, const void *inf,
return false;
if (info->name[sizeof(info->name)-1] != '\0')
return false;
- if (match->family == AF_INET) {
+ if (par->match->family == NFPROTO_IPV4) {
if (info->cfg.srcmask > 32 || info->cfg.dstmask > 32)
return false;
} else {
@@ -753,8 +738,8 @@ hashlimit_mt_check(const char *tablename, const void *inf,
* the list of htable's in htable_create(), since then we would
* create duplicate proc files. -HW */
mutex_lock(&hlimit_mutex);
- info->hinfo = htable_find_get(info->name, match->family);
- if (!info->hinfo && htable_create(info, match->family) != 0) {
+ info->hinfo = htable_find_get(info->name, par->match->family);
+ if (!info->hinfo && htable_create(info, par->match->family) != 0) {
mutex_unlock(&hlimit_mutex);
return false;
}
@@ -763,17 +748,16 @@ hashlimit_mt_check(const char *tablename, const void *inf,
}
static void
-hashlimit_mt_destroy_v0(const struct xt_match *match, void *matchinfo)
+hashlimit_mt_destroy_v0(const struct xt_mtdtor_param *par)
{
- const struct xt_hashlimit_info *r = matchinfo;
+ const struct xt_hashlimit_info *r = par->matchinfo;
htable_put(r->hinfo);
}
-static void
-hashlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
+static void hashlimit_mt_destroy(const struct xt_mtdtor_param *par)
{
- const struct xt_hashlimit_mtinfo1 *info = matchinfo;
+ const struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
htable_put(info->hinfo);
}
@@ -806,7 +790,7 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = {
{
.name = "hashlimit",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = hashlimit_mt_v0,
.matchsize = sizeof(struct xt_hashlimit_info),
#ifdef CONFIG_COMPAT
@@ -821,7 +805,7 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = {
{
.name = "hashlimit",
.revision = 1,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = hashlimit_mt,
.matchsize = sizeof(struct xt_hashlimit_mtinfo1),
.checkentry = hashlimit_mt_check,
@@ -831,7 +815,7 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = {
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
{
.name = "hashlimit",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.match = hashlimit_mt_v0,
.matchsize = sizeof(struct xt_hashlimit_info),
#ifdef CONFIG_COMPAT
@@ -846,7 +830,7 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = {
{
.name = "hashlimit",
.revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.match = hashlimit_mt,
.matchsize = sizeof(struct xt_hashlimit_mtinfo1),
.checkentry = hashlimit_mt_check,
@@ -901,14 +885,14 @@ static void dl_seq_stop(struct seq_file *s, void *v)
spin_unlock_bh(&htable->lock);
}
-static int dl_seq_real_show(struct dsthash_ent *ent, int family,
+static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family,
struct seq_file *s)
{
/* recalculate to show accurate numbers */
rateinfo_recalc(ent, jiffies);
switch (family) {
- case AF_INET:
+ case NFPROTO_IPV4:
return seq_printf(s, "%ld %u.%u.%u.%u:%u->"
"%u.%u.%u.%u:%u %u %u %u\n",
(long)(ent->expires - jiffies)/HZ,
@@ -919,7 +903,7 @@ static int dl_seq_real_show(struct dsthash_ent *ent, int family,
ent->rateinfo.credit, ent->rateinfo.credit_cap,
ent->rateinfo.cost);
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
- case AF_INET6:
+ case NFPROTO_IPV6:
return seq_printf(s, "%ld " NIP6_FMT ":%u->"
NIP6_FMT ":%u %u %u %u\n",
(long)(ent->expires - jiffies)/HZ,
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index dada2905d66e..64fc7f277221 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -24,12 +24,9 @@ MODULE_ALIAS("ip6t_helper");
static bool
-helper_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+helper_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_helper_info *info = matchinfo;
+ const struct xt_helper_info *info = par->matchinfo;
const struct nf_conn *ct;
const struct nf_conn_help *master_help;
const struct nf_conntrack_helper *helper;
@@ -57,56 +54,43 @@ helper_mt(const struct sk_buff *skb, const struct net_device *in,
return ret;
}
-static bool
-helper_mt_check(const char *tablename, const void *inf,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool helper_mt_check(const struct xt_mtchk_param *par)
{
- struct xt_helper_info *info = matchinfo;
+ struct xt_helper_info *info = par->matchinfo;
- if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%u\n", match->family);
+ "proto=%u\n", par->family);
return false;
}
info->name[29] = '\0';
return true;
}
-static void helper_mt_destroy(const struct xt_match *match, void *matchinfo)
+static void helper_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(match->family);
+ nf_ct_l3proto_module_put(par->family);
}
-static struct xt_match helper_mt_reg[] __read_mostly = {
- {
- .name = "helper",
- .family = AF_INET,
- .checkentry = helper_mt_check,
- .match = helper_mt,
- .destroy = helper_mt_destroy,
- .matchsize = sizeof(struct xt_helper_info),
- .me = THIS_MODULE,
- },
- {
- .name = "helper",
- .family = AF_INET6,
- .checkentry = helper_mt_check,
- .match = helper_mt,
- .destroy = helper_mt_destroy,
- .matchsize = sizeof(struct xt_helper_info),
- .me = THIS_MODULE,
- },
+static struct xt_match helper_mt_reg __read_mostly = {
+ .name = "helper",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = helper_mt_check,
+ .match = helper_mt,
+ .destroy = helper_mt_destroy,
+ .matchsize = sizeof(struct xt_helper_info),
+ .me = THIS_MODULE,
};
static int __init helper_mt_init(void)
{
- return xt_register_matches(helper_mt_reg, ARRAY_SIZE(helper_mt_reg));
+ return xt_register_match(&helper_mt_reg);
}
static void __exit helper_mt_exit(void)
{
- xt_unregister_matches(helper_mt_reg, ARRAY_SIZE(helper_mt_reg));
+ xt_unregister_match(&helper_mt_reg);
}
module_init(helper_mt_init);
diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c
index c63e9333c755..6f62c36948d9 100644
--- a/net/netfilter/xt_iprange.c
+++ b/net/netfilter/xt_iprange.c
@@ -17,12 +17,9 @@
#include <linux/netfilter_ipv4/ipt_iprange.h>
static bool
-iprange_mt_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+iprange_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ipt_iprange_info *info = matchinfo;
+ const struct ipt_iprange_info *info = par->matchinfo;
const struct iphdr *iph = ip_hdr(skb);
if (info->flags & IPRANGE_SRC) {
@@ -55,12 +52,9 @@ iprange_mt_v0(const struct sk_buff *skb, const struct net_device *in,
}
static bool
-iprange_mt4(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+iprange_mt4(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_iprange_mtinfo *info = matchinfo;
+ const struct xt_iprange_mtinfo *info = par->matchinfo;
const struct iphdr *iph = ip_hdr(skb);
bool m;
@@ -111,12 +105,9 @@ iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b)
}
static bool
-iprange_mt6(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+iprange_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_iprange_mtinfo *info = matchinfo;
+ const struct xt_iprange_mtinfo *info = par->matchinfo;
const struct ipv6hdr *iph = ipv6_hdr(skb);
bool m;
@@ -141,7 +132,7 @@ static struct xt_match iprange_mt_reg[] __read_mostly = {
{
.name = "iprange",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = iprange_mt_v0,
.matchsize = sizeof(struct ipt_iprange_info),
.me = THIS_MODULE,
@@ -149,7 +140,7 @@ static struct xt_match iprange_mt_reg[] __read_mostly = {
{
.name = "iprange",
.revision = 1,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = iprange_mt4,
.matchsize = sizeof(struct xt_iprange_mtinfo),
.me = THIS_MODULE,
@@ -157,7 +148,7 @@ static struct xt_match iprange_mt_reg[] __read_mostly = {
{
.name = "iprange",
.revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.match = iprange_mt6,
.matchsize = sizeof(struct xt_iprange_mtinfo),
.me = THIS_MODULE,
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index b8640f972950..c4871ca6c86d 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -21,24 +21,18 @@ MODULE_ALIAS("ipt_length");
MODULE_ALIAS("ip6t_length");
static bool
-length_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+length_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_length_info *info = matchinfo;
+ const struct xt_length_info *info = par->matchinfo;
u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len);
return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
}
static bool
-length_mt6(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+length_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_length_info *info = matchinfo;
+ const struct xt_length_info *info = par->matchinfo;
const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) +
sizeof(struct ipv6hdr);
@@ -48,14 +42,14 @@ length_mt6(const struct sk_buff *skb, const struct net_device *in,
static struct xt_match length_mt_reg[] __read_mostly = {
{
.name = "length",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = length_mt,
.matchsize = sizeof(struct xt_length_info),
.me = THIS_MODULE,
},
{
.name = "length",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.match = length_mt6,
.matchsize = sizeof(struct xt_length_info),
.me = THIS_MODULE,
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index aad9ab8d2046..c908d69a5595 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -58,13 +58,10 @@ static DEFINE_SPINLOCK(limit_lock);
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
static bool
-limit_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+limit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
struct xt_rateinfo *r =
- ((const struct xt_rateinfo *)matchinfo)->master;
+ ((const struct xt_rateinfo *)par->matchinfo)->master;
unsigned long now = jiffies;
spin_lock_bh(&limit_lock);
@@ -95,12 +92,9 @@ user2credits(u_int32_t user)
return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
}
-static bool
-limit_mt_check(const char *tablename, const void *inf,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool limit_mt_check(const struct xt_mtchk_param *par)
{
- struct xt_rateinfo *r = matchinfo;
+ struct xt_rateinfo *r = par->matchinfo;
/* Check for overflow. */
if (r->burst == 0
@@ -167,43 +161,29 @@ static int limit_mt_compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_match limit_mt_reg[] __read_mostly = {
- {
- .name = "limit",
- .family = AF_INET,
- .checkentry = limit_mt_check,
- .match = limit_mt,
- .matchsize = sizeof(struct xt_rateinfo),
-#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_xt_rateinfo),
- .compat_from_user = limit_mt_compat_from_user,
- .compat_to_user = limit_mt_compat_to_user,
-#endif
- .me = THIS_MODULE,
- },
- {
- .name = "limit",
- .family = AF_INET6,
- .checkentry = limit_mt_check,
- .match = limit_mt,
- .matchsize = sizeof(struct xt_rateinfo),
+static struct xt_match limit_mt_reg __read_mostly = {
+ .name = "limit",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = limit_mt,
+ .checkentry = limit_mt_check,
+ .matchsize = sizeof(struct xt_rateinfo),
#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_xt_rateinfo),
- .compat_from_user = limit_mt_compat_from_user,
- .compat_to_user = limit_mt_compat_to_user,
+ .compatsize = sizeof(struct compat_xt_rateinfo),
+ .compat_from_user = limit_mt_compat_from_user,
+ .compat_to_user = limit_mt_compat_to_user,
#endif
- .me = THIS_MODULE,
- },
+ .me = THIS_MODULE,
};
static int __init limit_mt_init(void)
{
- return xt_register_matches(limit_mt_reg, ARRAY_SIZE(limit_mt_reg));
+ return xt_register_match(&limit_mt_reg);
}
static void __exit limit_mt_exit(void)
{
- xt_unregister_matches(limit_mt_reg, ARRAY_SIZE(limit_mt_reg));
+ xt_unregister_match(&limit_mt_reg);
}
module_init(limit_mt_init);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index b3e96a0ec176..c2007116ce5b 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -24,12 +24,9 @@ MODULE_DESCRIPTION("Xtables: MAC address match");
MODULE_ALIAS("ipt_mac");
MODULE_ALIAS("ip6t_mac");
-static bool
-mac_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+static bool mac_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_mac_info *info = matchinfo;
+ const struct xt_mac_info *info = par->matchinfo;
/* Is mac pointer valid? */
return skb_mac_header(skb) >= skb->head &&
@@ -39,37 +36,25 @@ mac_mt(const struct sk_buff *skb, const struct net_device *in,
^ info->invert);
}
-static struct xt_match mac_mt_reg[] __read_mostly = {
- {
- .name = "mac",
- .family = AF_INET,
- .match = mac_mt,
- .matchsize = sizeof(struct xt_mac_info),
- .hooks = (1 << NF_INET_PRE_ROUTING) |
- (1 << NF_INET_LOCAL_IN) |
- (1 << NF_INET_FORWARD),
- .me = THIS_MODULE,
- },
- {
- .name = "mac",
- .family = AF_INET6,
- .match = mac_mt,
- .matchsize = sizeof(struct xt_mac_info),
- .hooks = (1 << NF_INET_PRE_ROUTING) |
- (1 << NF_INET_LOCAL_IN) |
- (1 << NF_INET_FORWARD),
- .me = THIS_MODULE,
- },
+static struct xt_match mac_mt_reg __read_mostly = {
+ .name = "mac",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = mac_mt,
+ .matchsize = sizeof(struct xt_mac_info),
+ .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
+ (1 << NF_INET_FORWARD),
+ .me = THIS_MODULE,
};
static int __init mac_mt_init(void)
{
- return xt_register_matches(mac_mt_reg, ARRAY_SIZE(mac_mt_reg));
+ return xt_register_match(&mac_mt_reg);
}
static void __exit mac_mt_exit(void)
{
- xt_unregister_matches(mac_mt_reg, ARRAY_SIZE(mac_mt_reg));
+ xt_unregister_match(&mac_mt_reg);
}
module_init(mac_mt_init);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 9f78f6120fbd..10b9e34bbc5b 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -23,32 +23,24 @@ MODULE_ALIAS("ipt_mark");
MODULE_ALIAS("ip6t_mark");
static bool
-mark_mt_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+mark_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_mark_info *info = matchinfo;
+ const struct xt_mark_info *info = par->matchinfo;
return ((skb->mark & info->mask) == info->mark) ^ info->invert;
}
static bool
-mark_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+mark_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_mark_mtinfo1 *info = matchinfo;
+ const struct xt_mark_mtinfo1 *info = par->matchinfo;
return ((skb->mark & info->mask) == info->mark) ^ info->invert;
}
-static bool
-mark_mt_check_v0(const char *tablename, const void *entry,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool mark_mt_check_v0(const struct xt_mtchk_param *par)
{
- const struct xt_mark_info *minfo = matchinfo;
+ const struct xt_mark_info *minfo = par->matchinfo;
if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
printk(KERN_WARNING "mark: only supports 32bit mark\n");
@@ -92,7 +84,7 @@ static struct xt_match mark_mt_reg[] __read_mostly = {
{
.name = "mark",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_UNSPEC,
.checkentry = mark_mt_check_v0,
.match = mark_mt_v0,
.matchsize = sizeof(struct xt_mark_info),
@@ -104,31 +96,9 @@ static struct xt_match mark_mt_reg[] __read_mostly = {
.me = THIS_MODULE,
},
{
- .name = "mark",
- .revision = 0,
- .family = AF_INET6,
- .checkentry = mark_mt_check_v0,
- .match = mark_mt_v0,
- .matchsize = sizeof(struct xt_mark_info),
-#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_xt_mark_info),
- .compat_from_user = mark_mt_compat_from_user_v0,
- .compat_to_user = mark_mt_compat_to_user_v0,
-#endif
- .me = THIS_MODULE,
- },
- {
- .name = "mark",
- .revision = 1,
- .family = AF_INET,
- .match = mark_mt,
- .matchsize = sizeof(struct xt_mark_mtinfo1),
- .me = THIS_MODULE,
- },
- {
.name = "mark",
.revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_UNSPEC,
.match = mark_mt,
.matchsize = sizeof(struct xt_mark_mtinfo1),
.me = THIS_MODULE,
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index fd88c489b70e..d06bb2dd3900 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -95,25 +95,22 @@ ports_match_v1(const struct xt_multiport_v1 *minfo,
}
static bool
-multiport_mt_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+multiport_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
const __be16 *pptr;
__be16 _ports[2];
- const struct xt_multiport *multiinfo = matchinfo;
+ const struct xt_multiport *multiinfo = par->matchinfo;
- if (offset)
+ if (par->fragoff != 0)
return false;
- pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+ pptr = skb_header_pointer(skb, par->thoff, sizeof(_ports), _ports);
if (pptr == NULL) {
/* We've been asked to examine this packet, and we
* can't. Hence, no choice but to drop.
*/
duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
@@ -122,25 +119,22 @@ multiport_mt_v0(const struct sk_buff *skb, const struct net_device *in,
}
static bool
-multiport_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+multiport_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const __be16 *pptr;
__be16 _ports[2];
- const struct xt_multiport_v1 *multiinfo = matchinfo;
+ const struct xt_multiport_v1 *multiinfo = par->matchinfo;
- if (offset)
+ if (par->fragoff != 0)
return false;
- pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+ pptr = skb_header_pointer(skb, par->thoff, sizeof(_ports), _ports);
if (pptr == NULL) {
/* We've been asked to examine this packet, and we
* can't. Hence, no choice but to drop.
*/
duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
@@ -164,50 +158,37 @@ check(u_int16_t proto,
&& count <= XT_MULTI_PORTS;
}
-/* Called when user tries to insert an entry of this type. */
-static bool
-multiport_mt_check_v0(const char *tablename, const void *info,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool multiport_mt_check_v0(const struct xt_mtchk_param *par)
{
- const struct ipt_ip *ip = info;
- const struct xt_multiport *multiinfo = matchinfo;
+ const struct ipt_ip *ip = par->entryinfo;
+ const struct xt_multiport *multiinfo = par->matchinfo;
return check(ip->proto, ip->invflags, multiinfo->flags,
multiinfo->count);
}
-static bool
-multiport_mt_check(const char *tablename, const void *info,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool multiport_mt_check(const struct xt_mtchk_param *par)
{
- const struct ipt_ip *ip = info;
- const struct xt_multiport_v1 *multiinfo = matchinfo;
+ const struct ipt_ip *ip = par->entryinfo;
+ const struct xt_multiport_v1 *multiinfo = par->matchinfo;
return check(ip->proto, ip->invflags, multiinfo->flags,
multiinfo->count);
}
-static bool
-multiport_mt6_check_v0(const char *tablename, const void *info,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool multiport_mt6_check_v0(const struct xt_mtchk_param *par)
{
- const struct ip6t_ip6 *ip = info;
- const struct xt_multiport *multiinfo = matchinfo;
+ const struct ip6t_ip6 *ip = par->entryinfo;
+ const struct xt_multiport *multiinfo = par->matchinfo;
return check(ip->proto, ip->invflags, multiinfo->flags,
multiinfo->count);
}
-static bool
-multiport_mt6_check(const char *tablename, const void *info,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool multiport_mt6_check(const struct xt_mtchk_param *par)
{
- const struct ip6t_ip6 *ip = info;
- const struct xt_multiport_v1 *multiinfo = matchinfo;
+ const struct ip6t_ip6 *ip = par->entryinfo;
+ const struct xt_multiport_v1 *multiinfo = par->matchinfo;
return check(ip->proto, ip->invflags, multiinfo->flags,
multiinfo->count);
@@ -216,7 +197,7 @@ multiport_mt6_check(const char *tablename, const void *info,
static struct xt_match multiport_mt_reg[] __read_mostly = {
{
.name = "multiport",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.revision = 0,
.checkentry = multiport_mt_check_v0,
.match = multiport_mt_v0,
@@ -225,7 +206,7 @@ static struct xt_match multiport_mt_reg[] __read_mostly = {
},
{
.name = "multiport",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.revision = 1,
.checkentry = multiport_mt_check,
.match = multiport_mt,
@@ -234,7 +215,7 @@ static struct xt_match multiport_mt_reg[] __read_mostly = {
},
{
.name = "multiport",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.revision = 0,
.checkentry = multiport_mt6_check_v0,
.match = multiport_mt_v0,
@@ -243,7 +224,7 @@ static struct xt_match multiport_mt_reg[] __read_mostly = {
},
{
.name = "multiport",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.revision = 1,
.checkentry = multiport_mt6_check,
.match = multiport_mt,
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c
index 9059c16144c3..f19ebd9b78f5 100644
--- a/net/netfilter/xt_owner.c
+++ b/net/netfilter/xt_owner.c
@@ -21,12 +21,9 @@
#include <linux/netfilter_ipv6/ip6t_owner.h>
static bool
-owner_mt_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+owner_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ipt_owner_info *info = matchinfo;
+ const struct ipt_owner_info *info = par->matchinfo;
const struct file *filp;
if (skb->sk == NULL || skb->sk->sk_socket == NULL)
@@ -50,12 +47,9 @@ owner_mt_v0(const struct sk_buff *skb, const struct net_device *in,
}
static bool
-owner_mt6_v0(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+owner_mt6_v0(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct ip6t_owner_info *info = matchinfo;
+ const struct ip6t_owner_info *info = par->matchinfo;
const struct file *filp;
if (skb->sk == NULL || skb->sk->sk_socket == NULL)
@@ -79,12 +73,9 @@ owner_mt6_v0(const struct sk_buff *skb, const struct net_device *in,
}
static bool
-owner_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+owner_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_owner_match_info *info = matchinfo;
+ const struct xt_owner_match_info *info = par->matchinfo;
const struct file *filp;
if (skb->sk == NULL || skb->sk->sk_socket == NULL)
@@ -116,12 +107,9 @@ owner_mt(const struct sk_buff *skb, const struct net_device *in,
return true;
}
-static bool
-owner_mt_check_v0(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool owner_mt_check_v0(const struct xt_mtchk_param *par)
{
- const struct ipt_owner_info *info = matchinfo;
+ const struct ipt_owner_info *info = par->matchinfo;
if (info->match & (IPT_OWNER_PID | IPT_OWNER_SID | IPT_OWNER_COMM)) {
printk(KERN_WARNING KBUILD_MODNAME
@@ -133,12 +121,9 @@ owner_mt_check_v0(const char *tablename, const void *ip,
return true;
}
-static bool
-owner_mt6_check_v0(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool owner_mt6_check_v0(const struct xt_mtchk_param *par)
{
- const struct ip6t_owner_info *info = matchinfo;
+ const struct ip6t_owner_info *info = par->matchinfo;
if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
printk(KERN_WARNING KBUILD_MODNAME
@@ -153,7 +138,7 @@ static struct xt_match owner_mt_reg[] __read_mostly = {
{
.name = "owner",
.revision = 0,
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = owner_mt_v0,
.matchsize = sizeof(struct ipt_owner_info),
.checkentry = owner_mt_check_v0,
@@ -164,7 +149,7 @@ static struct xt_match owner_mt_reg[] __read_mostly = {
{
.name = "owner",
.revision = 0,
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.match = owner_mt6_v0,
.matchsize = sizeof(struct ip6t_owner_info),
.checkentry = owner_mt6_check_v0,
@@ -175,17 +160,7 @@ static struct xt_match owner_mt_reg[] __read_mostly = {
{
.name = "owner",
.revision = 1,
- .family = AF_INET,
- .match = owner_mt,
- .matchsize = sizeof(struct xt_owner_match_info),
- .hooks = (1 << NF_INET_LOCAL_OUT) |
- (1 << NF_INET_POST_ROUTING),
- .me = THIS_MODULE,
- },
- {
- .name = "owner",
- .revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_UNSPEC,
.match = owner_mt,
.matchsize = sizeof(struct xt_owner_match_info),
.hooks = (1 << NF_INET_LOCAL_OUT) |
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 4ec1094bda92..1bcdfc12cf59 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -21,14 +21,11 @@ MODULE_ALIAS("ipt_physdev");
MODULE_ALIAS("ip6t_physdev");
static bool
-physdev_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+physdev_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
int i;
static const char nulldevname[IFNAMSIZ];
- const struct xt_physdev_info *info = matchinfo;
+ const struct xt_physdev_info *info = par->matchinfo;
bool ret;
const char *indev, *outdev;
const struct nf_bridge_info *nf_bridge;
@@ -94,12 +91,9 @@ match_outdev:
return ret ^ !(info->invert & XT_PHYSDEV_OP_OUT);
}
-static bool
-physdev_mt_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool physdev_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_physdev_info *info = matchinfo;
+ const struct xt_physdev_info *info = par->matchinfo;
if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
info->bitmask & ~XT_PHYSDEV_OP_MASK)
@@ -107,44 +101,35 @@ physdev_mt_check(const char *tablename, const void *ip,
if (info->bitmask & XT_PHYSDEV_OP_OUT &&
(!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
info->invert & XT_PHYSDEV_OP_BRIDGED) &&
- hook_mask & ((1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
- (1 << NF_INET_POST_ROUTING))) {
+ par->hook_mask & ((1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) {
printk(KERN_WARNING "physdev match: using --physdev-out in the "
"OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
"traffic is not supported anymore.\n");
- if (hook_mask & (1 << NF_INET_LOCAL_OUT))
+ if (par->hook_mask & (1 << NF_INET_LOCAL_OUT))
return false;
}
return true;
}
-static struct xt_match physdev_mt_reg[] __read_mostly = {
- {
- .name = "physdev",
- .family = AF_INET,
- .checkentry = physdev_mt_check,
- .match = physdev_mt,
- .matchsize = sizeof(struct xt_physdev_info),
- .me = THIS_MODULE,
- },
- {
- .name = "physdev",
- .family = AF_INET6,
- .checkentry = physdev_mt_check,
- .match = physdev_mt,
- .matchsize = sizeof(struct xt_physdev_info),
- .me = THIS_MODULE,
- },
+static struct xt_match physdev_mt_reg __read_mostly = {
+ .name = "physdev",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = physdev_mt_check,
+ .match = physdev_mt,
+ .matchsize = sizeof(struct xt_physdev_info),
+ .me = THIS_MODULE,
};
static int __init physdev_mt_init(void)
{
- return xt_register_matches(physdev_mt_reg, ARRAY_SIZE(physdev_mt_reg));
+ return xt_register_match(&physdev_mt_reg);
}
static void __exit physdev_mt_exit(void)
{
- xt_unregister_matches(physdev_mt_reg, ARRAY_SIZE(physdev_mt_reg));
+ xt_unregister_match(&physdev_mt_reg);
}
module_init(physdev_mt_init);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index 7936f7e23254..69da1d3a1d85 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -23,20 +23,17 @@ MODULE_ALIAS("ipt_pkttype");
MODULE_ALIAS("ip6t_pkttype");
static bool
-pkttype_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+pkttype_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_pkttype_info *info = matchinfo;
+ const struct xt_pkttype_info *info = par->matchinfo;
u_int8_t type;
if (skb->pkt_type != PACKET_LOOPBACK)
type = skb->pkt_type;
- else if (match->family == AF_INET &&
+ else if (par->family == NFPROTO_IPV4 &&
ipv4_is_multicast(ip_hdr(skb)->daddr))
type = PACKET_MULTICAST;
- else if (match->family == AF_INET6 &&
+ else if (par->family == NFPROTO_IPV6 &&
ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF)
type = PACKET_MULTICAST;
else
@@ -45,31 +42,23 @@ pkttype_mt(const struct sk_buff *skb, const struct net_device *in,
return (type == info->pkttype) ^ info->invert;
}
-static struct xt_match pkttype_mt_reg[] __read_mostly = {
- {
- .name = "pkttype",
- .family = AF_INET,
- .match = pkttype_mt,
- .matchsize = sizeof(struct xt_pkttype_info),
- .me = THIS_MODULE,
- },
- {
- .name = "pkttype",
- .family = AF_INET6,
- .match = pkttype_mt,
- .matchsize = sizeof(struct xt_pkttype_info),
- .me = THIS_MODULE,
- },
+static struct xt_match pkttype_mt_reg __read_mostly = {
+ .name = "pkttype",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = pkttype_mt,
+ .matchsize = sizeof(struct xt_pkttype_info),
+ .me = THIS_MODULE,
};
static int __init pkttype_mt_init(void)
{
- return xt_register_matches(pkttype_mt_reg, ARRAY_SIZE(pkttype_mt_reg));
+ return xt_register_match(&pkttype_mt_reg);
}
static void __exit pkttype_mt_exit(void)
{
- xt_unregister_matches(pkttype_mt_reg, ARRAY_SIZE(pkttype_mt_reg));
+ xt_unregister_match(&pkttype_mt_reg);
}
module_init(pkttype_mt_init);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index d351582b2a3d..328bd20ddd25 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -26,9 +26,9 @@ xt_addr_cmp(const union nf_inet_addr *a1, const union nf_inet_addr *m,
const union nf_inet_addr *a2, unsigned short family)
{
switch (family) {
- case AF_INET:
+ case NFPROTO_IPV4:
return ((a1->ip ^ a2->ip) & m->ip) == 0;
- case AF_INET6:
+ case NFPROTO_IPV6:
return ipv6_masked_addr_cmp(&a1->in6, &m->in6, &a2->in6) == 0;
}
return false;
@@ -110,18 +110,15 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info,
}
static bool
-policy_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+policy_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_policy_info *info = matchinfo;
+ const struct xt_policy_info *info = par->matchinfo;
int ret;
if (info->flags & XT_POLICY_MATCH_IN)
- ret = match_policy_in(skb, info, match->family);
+ ret = match_policy_in(skb, info, par->match->family);
else
- ret = match_policy_out(skb, info, match->family);
+ ret = match_policy_out(skb, info, par->match->family);
if (ret < 0)
ret = info->flags & XT_POLICY_MATCH_NONE ? true : false;
@@ -131,26 +128,23 @@ policy_mt(const struct sk_buff *skb, const struct net_device *in,
return ret;
}
-static bool
-policy_mt_check(const char *tablename, const void *ip_void,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool policy_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_policy_info *info = matchinfo;
+ const struct xt_policy_info *info = par->matchinfo;
if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
printk(KERN_ERR "xt_policy: neither incoming nor "
"outgoing policy selected\n");
return false;
}
- if (hook_mask & (1 << NF_INET_PRE_ROUTING | 1 << NF_INET_LOCAL_IN)
- && info->flags & XT_POLICY_MATCH_OUT) {
+ if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
+ (1 << NF_INET_LOCAL_IN)) && info->flags & XT_POLICY_MATCH_OUT) {
printk(KERN_ERR "xt_policy: output policy not valid in "
"PRE_ROUTING and INPUT\n");
return false;
}
- if (hook_mask & (1 << NF_INET_POST_ROUTING | 1 << NF_INET_LOCAL_OUT)
- && info->flags & XT_POLICY_MATCH_IN) {
+ if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
+ (1 << NF_INET_LOCAL_OUT)) && info->flags & XT_POLICY_MATCH_IN) {
printk(KERN_ERR "xt_policy: input policy not valid in "
"POST_ROUTING and OUTPUT\n");
return false;
@@ -165,7 +159,7 @@ policy_mt_check(const char *tablename, const void *ip_void,
static struct xt_match policy_mt_reg[] __read_mostly = {
{
.name = "policy",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = policy_mt_check,
.match = policy_mt,
.matchsize = sizeof(struct xt_policy_info),
@@ -173,7 +167,7 @@ static struct xt_match policy_mt_reg[] __read_mostly = {
},
{
.name = "policy",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = policy_mt_check,
.match = policy_mt,
.matchsize = sizeof(struct xt_policy_info),
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index 3b021d0c522a..c84fce5e0f3e 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -18,13 +18,10 @@ MODULE_ALIAS("ip6t_quota");
static DEFINE_SPINLOCK(quota_lock);
static bool
-quota_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+quota_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
struct xt_quota_info *q =
- ((const struct xt_quota_info *)matchinfo)->master;
+ ((const struct xt_quota_info *)par->matchinfo)->master;
bool ret = q->flags & XT_QUOTA_INVERT;
spin_lock_bh(&quota_lock);
@@ -40,12 +37,9 @@ quota_mt(const struct sk_buff *skb, const struct net_device *in,
return ret;
}
-static bool
-quota_mt_check(const char *tablename, const void *entry,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool quota_mt_check(const struct xt_mtchk_param *par)
{
- struct xt_quota_info *q = matchinfo;
+ struct xt_quota_info *q = par->matchinfo;
if (q->flags & ~XT_QUOTA_MASK)
return false;
@@ -54,33 +48,24 @@ quota_mt_check(const char *tablename, const void *entry,
return true;
}
-static struct xt_match quota_mt_reg[] __read_mostly = {
- {
- .name = "quota",
- .family = AF_INET,
- .checkentry = quota_mt_check,
- .match = quota_mt,
- .matchsize = sizeof(struct xt_quota_info),
- .me = THIS_MODULE
- },
- {
- .name = "quota",
- .family = AF_INET6,
- .checkentry = quota_mt_check,
- .match = quota_mt,
- .matchsize = sizeof(struct xt_quota_info),
- .me = THIS_MODULE
- },
+static struct xt_match quota_mt_reg __read_mostly = {
+ .name = "quota",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = quota_mt,
+ .checkentry = quota_mt_check,
+ .matchsize = sizeof(struct xt_quota_info),
+ .me = THIS_MODULE,
};
static int __init quota_mt_init(void)
{
- return xt_register_matches(quota_mt_reg, ARRAY_SIZE(quota_mt_reg));
+ return xt_register_match(&quota_mt_reg);
}
static void __exit quota_mt_exit(void)
{
- xt_unregister_matches(quota_mt_reg, ARRAY_SIZE(quota_mt_reg));
+ xt_unregister_match(&quota_mt_reg);
}
module_init(quota_mt_init);
diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c
index ebd84f1b4f62..220a1d588ee0 100644
--- a/net/netfilter/xt_rateest.c
+++ b/net/netfilter/xt_rateest.c
@@ -14,16 +14,10 @@
#include <net/netfilter/xt_rateest.h>
-static bool xt_rateest_mt(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- bool *hotdrop)
+static bool
+xt_rateest_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_rateest_match_info *info = matchinfo;
+ const struct xt_rateest_match_info *info = par->matchinfo;
struct gnet_stats_rate_est *r;
u_int32_t bps1, bps2, pps1, pps2;
bool ret = true;
@@ -80,13 +74,9 @@ static bool xt_rateest_mt(const struct sk_buff *skb,
return ret;
}
-static bool xt_rateest_mt_checkentry(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool xt_rateest_mt_checkentry(const struct xt_mtchk_param *par)
{
- struct xt_rateest_match_info *info = matchinfo;
+ struct xt_rateest_match_info *info = par->matchinfo;
struct xt_rateest *est1, *est2;
if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
@@ -127,46 +117,34 @@ err1:
return false;
}
-static void xt_rateest_mt_destroy(const struct xt_match *match,
- void *matchinfo)
+static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par)
{
- struct xt_rateest_match_info *info = matchinfo;
+ struct xt_rateest_match_info *info = par->matchinfo;
xt_rateest_put(info->est1);
if (info->est2)
xt_rateest_put(info->est2);
}
-static struct xt_match xt_rateest_match[] __read_mostly = {
- {
- .family = AF_INET,
- .name = "rateest",
- .match = xt_rateest_mt,
- .checkentry = xt_rateest_mt_checkentry,
- .destroy = xt_rateest_mt_destroy,
- .matchsize = sizeof(struct xt_rateest_match_info),
- .me = THIS_MODULE,
- },
- {
- .family = AF_INET6,
- .name = "rateest",
- .match = xt_rateest_mt,
- .checkentry = xt_rateest_mt_checkentry,
- .destroy = xt_rateest_mt_destroy,
- .matchsize = sizeof(struct xt_rateest_match_info),
- .me = THIS_MODULE,
- },
+static struct xt_match xt_rateest_mt_reg __read_mostly = {
+ .name = "rateest",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = xt_rateest_mt,
+ .checkentry = xt_rateest_mt_checkentry,
+ .destroy = xt_rateest_mt_destroy,
+ .matchsize = sizeof(struct xt_rateest_match_info),
+ .me = THIS_MODULE,
};
static int __init xt_rateest_mt_init(void)
{
- return xt_register_matches(xt_rateest_match,
- ARRAY_SIZE(xt_rateest_match));
+ return xt_register_match(&xt_rateest_mt_reg);
}
static void __exit xt_rateest_mt_fini(void)
{
- xt_unregister_matches(xt_rateest_match, ARRAY_SIZE(xt_rateest_match));
+ xt_unregister_match(&xt_rateest_mt_reg);
}
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index 7df1627c536f..67419287bc7e 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -22,12 +22,9 @@ MODULE_DESCRIPTION("Xtables: Routing realm match");
MODULE_ALIAS("ipt_realm");
static bool
-realm_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+realm_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_realm_info *info = matchinfo;
+ const struct xt_realm_info *info = par->matchinfo;
const struct dst_entry *dst = skb->dst;
return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
@@ -39,7 +36,7 @@ static struct xt_match realm_mt_reg __read_mostly = {
.matchsize = sizeof(struct xt_realm_info),
.hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_LOCAL_IN),
- .family = AF_INET,
+ .family = NFPROTO_UNSPEC,
.me = THIS_MODULE
};
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
new file mode 100644
index 000000000000..4ebd4ca9a991
--- /dev/null
+++ b/net/netfilter/xt_recent.c
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ * Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is a replacement of the old ipt_recent module, which carried the
+ * following copyright notice:
+ *
+ * Author: Stephen Frost <sfrost@snowman.net>
+ * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org
+ */
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/random.h>
+#include <linux/jhash.h>
+#include <linux/bitops.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <net/net_namespace.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_recent.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
+MODULE_DESCRIPTION("Xtables: \"recently-seen\" host matching for IPv4");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_recent");
+MODULE_ALIAS("ip6t_recent");
+
+static unsigned int ip_list_tot = 100;
+static unsigned int ip_pkt_list_tot = 20;
+static unsigned int ip_list_hash_size = 0;
+static unsigned int ip_list_perms = 0644;
+static unsigned int ip_list_uid = 0;
+static unsigned int ip_list_gid = 0;
+module_param(ip_list_tot, uint, 0400);
+module_param(ip_pkt_list_tot, uint, 0400);
+module_param(ip_list_hash_size, uint, 0400);
+module_param(ip_list_perms, uint, 0400);
+module_param(ip_list_uid, uint, 0400);
+module_param(ip_list_gid, uint, 0400);
+MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list");
+MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)");
+MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs");
+MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files");
+MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/xt_recent/* files");
+MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/xt_recent/* files");
+
+struct recent_entry {
+ struct list_head list;
+ struct list_head lru_list;
+ union nf_inet_addr addr;
+ u_int16_t family;
+ u_int8_t ttl;
+ u_int8_t index;
+ u_int16_t nstamps;
+ unsigned long stamps[0];
+};
+
+struct recent_table {
+ struct list_head list;
+ char name[XT_RECENT_NAME_LEN];
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc_old, *proc;
+#endif
+ unsigned int refcnt;
+ unsigned int entries;
+ struct list_head lru_list;
+ struct list_head iphash[0];
+};
+
+static LIST_HEAD(tables);
+static DEFINE_SPINLOCK(recent_lock);
+static DEFINE_MUTEX(recent_mutex);
+
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
+static struct proc_dir_entry *proc_old_dir;
+#endif
+static struct proc_dir_entry *recent_proc_dir;
+static const struct file_operations recent_old_fops, recent_mt_fops;
+#endif
+
+static u_int32_t hash_rnd;
+static bool hash_rnd_initted;
+
+static unsigned int recent_entry_hash4(const union nf_inet_addr *addr)
+{
+ if (!hash_rnd_initted) {
+ get_random_bytes(&hash_rnd, sizeof(hash_rnd));
+ hash_rnd_initted = true;
+ }
+ return jhash_1word((__force u32)addr->ip, hash_rnd) &
+ (ip_list_hash_size - 1);
+}
+
+static unsigned int recent_entry_hash6(const union nf_inet_addr *addr)
+{
+ if (!hash_rnd_initted) {
+ get_random_bytes(&hash_rnd, sizeof(hash_rnd));
+ hash_rnd_initted = true;
+ }
+ return jhash2((u32 *)addr->ip6, ARRAY_SIZE(addr->ip6), hash_rnd) &
+ (ip_list_hash_size - 1);
+}
+
+static struct recent_entry *
+recent_entry_lookup(const struct recent_table *table,
+ const union nf_inet_addr *addrp, u_int16_t family,
+ u_int8_t ttl)
+{
+ struct recent_entry *e;
+ unsigned int h;
+
+ if (family == NFPROTO_IPV4)
+ h = recent_entry_hash4(addrp);
+ else
+ h = recent_entry_hash6(addrp);
+
+ list_for_each_entry(e, &table->iphash[h], list)
+ if (e->family == family &&
+ memcmp(&e->addr, addrp, sizeof(e->addr)) == 0 &&
+ (ttl == e->ttl || ttl == 0 || e->ttl == 0))
+ return e;
+ return NULL;
+}
+
+static void recent_entry_remove(struct recent_table *t, struct recent_entry *e)
+{
+ list_del(&e->list);
+ list_del(&e->lru_list);
+ kfree(e);
+ t->entries--;
+}
+
+static struct recent_entry *
+recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr,
+ u_int16_t family, u_int8_t ttl)
+{
+ struct recent_entry *e;
+
+ if (t->entries >= ip_list_tot) {
+ e = list_entry(t->lru_list.next, struct recent_entry, lru_list);
+ recent_entry_remove(t, e);
+ }
+ e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * ip_pkt_list_tot,
+ GFP_ATOMIC);
+ if (e == NULL)
+ return NULL;
+ memcpy(&e->addr, addr, sizeof(e->addr));
+ e->ttl = ttl;
+ e->stamps[0] = jiffies;
+ e->nstamps = 1;
+ e->index = 1;
+ e->family = family;
+ if (family == NFPROTO_IPV4)
+ list_add_tail(&e->list, &t->iphash[recent_entry_hash4(addr)]);
+ else
+ list_add_tail(&e->list, &t->iphash[recent_entry_hash6(addr)]);
+ list_add_tail(&e->lru_list, &t->lru_list);
+ t->entries++;
+ return e;
+}
+
+static void recent_entry_update(struct recent_table *t, struct recent_entry *e)
+{
+ e->stamps[e->index++] = jiffies;
+ if (e->index > e->nstamps)
+ e->nstamps = e->index;
+ e->index %= ip_pkt_list_tot;
+ list_move_tail(&e->lru_list, &t->lru_list);
+}
+
+static struct recent_table *recent_table_lookup(const char *name)
+{
+ struct recent_table *t;
+
+ list_for_each_entry(t, &tables, list)
+ if (!strcmp(t->name, name))
+ return t;
+ return NULL;
+}
+
+static void recent_table_flush(struct recent_table *t)
+{
+ struct recent_entry *e, *next;
+ unsigned int i;
+
+ for (i = 0; i < ip_list_hash_size; i++)
+ list_for_each_entry_safe(e, next, &t->iphash[i], list)
+ recent_entry_remove(t, e);
+}
+
+static bool
+recent_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+ const struct xt_recent_mtinfo *info = par->matchinfo;
+ struct recent_table *t;
+ struct recent_entry *e;
+ union nf_inet_addr addr = {};
+ u_int8_t ttl;
+ bool ret = info->invert;
+
+ if (par->match->family == NFPROTO_IPV4) {
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (info->side == XT_RECENT_DEST)
+ addr.ip = iph->daddr;
+ else
+ addr.ip = iph->saddr;
+
+ ttl = iph->ttl;
+ } else {
+ const struct ipv6hdr *iph = ipv6_hdr(skb);
+
+ if (info->side == XT_RECENT_DEST)
+ memcpy(&addr.in6, &iph->daddr, sizeof(addr.in6));
+ else
+ memcpy(&addr.in6, &iph->saddr, sizeof(addr.in6));
+
+ ttl = iph->hop_limit;
+ }
+
+ /* use TTL as seen before forwarding */
+ if (par->out != NULL && skb->sk == NULL)
+ ttl++;
+
+ spin_lock_bh(&recent_lock);
+ t = recent_table_lookup(info->name);
+ e = recent_entry_lookup(t, &addr, par->match->family,
+ (info->check_set & XT_RECENT_TTL) ? ttl : 0);
+ if (e == NULL) {
+ if (!(info->check_set & XT_RECENT_SET))
+ goto out;
+ e = recent_entry_init(t, &addr, par->match->family, ttl);
+ if (e == NULL)
+ *par->hotdrop = true;
+ ret = !ret;
+ goto out;
+ }
+
+ if (info->check_set & XT_RECENT_SET)
+ ret = !ret;
+ else if (info->check_set & XT_RECENT_REMOVE) {
+ recent_entry_remove(t, e);
+ ret = !ret;
+ } else if (info->check_set & (XT_RECENT_CHECK | XT_RECENT_UPDATE)) {
+ unsigned long time = jiffies - info->seconds * HZ;
+ unsigned int i, hits = 0;
+
+ for (i = 0; i < e->nstamps; i++) {
+ if (info->seconds && time_after(time, e->stamps[i]))
+ continue;
+ if (++hits >= info->hit_count) {
+ ret = !ret;
+ break;
+ }
+ }
+ }
+
+ if (info->check_set & XT_RECENT_SET ||
+ (info->check_set & XT_RECENT_UPDATE && ret)) {
+ recent_entry_update(t, e);
+ e->ttl = ttl;
+ }
+out:
+ spin_unlock_bh(&recent_lock);
+ return ret;
+}
+
+static bool recent_mt_check(const struct xt_mtchk_param *par)
+{
+ const struct xt_recent_mtinfo *info = par->matchinfo;
+ struct recent_table *t;
+ unsigned i;
+ bool ret = false;
+
+ if (hweight8(info->check_set &
+ (XT_RECENT_SET | XT_RECENT_REMOVE |
+ XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1)
+ return false;
+ if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) &&
+ (info->seconds || info->hit_count))
+ return false;
+ if (info->hit_count > ip_pkt_list_tot)
+ return false;
+ if (info->name[0] == '\0' ||
+ strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN)
+ return false;
+
+ mutex_lock(&recent_mutex);
+ t = recent_table_lookup(info->name);
+ if (t != NULL) {
+ t->refcnt++;
+ ret = true;
+ goto out;
+ }
+
+ t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
+ GFP_KERNEL);
+ if (t == NULL)
+ goto out;
+ t->refcnt = 1;
+ strcpy(t->name, info->name);
+ INIT_LIST_HEAD(&t->lru_list);
+ for (i = 0; i < ip_list_hash_size; i++)
+ INIT_LIST_HEAD(&t->iphash[i]);
+#ifdef CONFIG_PROC_FS
+ t->proc = proc_create(t->name, ip_list_perms, recent_proc_dir,
+ &recent_mt_fops);
+ if (t->proc == NULL) {
+ kfree(t);
+ goto out;
+ }
+#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
+ t->proc_old = proc_create(t->name, ip_list_perms, proc_old_dir,
+ &recent_old_fops);
+ if (t->proc_old == NULL) {
+ remove_proc_entry(t->name, proc_old_dir);
+ kfree(t);
+ goto out;
+ }
+ t->proc_old->uid = ip_list_uid;
+ t->proc_old->gid = ip_list_gid;
+ t->proc_old->data = t;
+#endif
+ t->proc->uid = ip_list_uid;
+ t->proc->gid = ip_list_gid;
+ t->proc->data = t;
+#endif
+ spin_lock_bh(&recent_lock);
+ list_add_tail(&t->list, &tables);
+ spin_unlock_bh(&recent_lock);
+ ret = true;
+out:
+ mutex_unlock(&recent_mutex);
+ return ret;
+}
+
+static void recent_mt_destroy(const struct xt_mtdtor_param *par)
+{
+ const struct xt_recent_mtinfo *info = par->matchinfo;
+ struct recent_table *t;
+
+ mutex_lock(&recent_mutex);
+ t = recent_table_lookup(info->name);
+ if (--t->refcnt == 0) {
+ spin_lock_bh(&recent_lock);
+ list_del(&t->list);
+ spin_unlock_bh(&recent_lock);
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
+ remove_proc_entry(t->name, proc_old_dir);
+#endif
+ remove_proc_entry(t->name, recent_proc_dir);
+#endif
+ recent_table_flush(t);
+ kfree(t);
+ }
+ mutex_unlock(&recent_mutex);
+}
+
+#ifdef CONFIG_PROC_FS
+struct recent_iter_state {
+ const struct recent_table *table;
+ unsigned int bucket;
+};
+
+static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(recent_lock)
+{
+ struct recent_iter_state *st = seq->private;
+ const struct recent_table *t = st->table;
+ struct recent_entry *e;
+ loff_t p = *pos;
+
+ spin_lock_bh(&recent_lock);
+
+ for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++)
+ list_for_each_entry(e, &t->iphash[st->bucket], list)
+ if (p-- == 0)
+ return e;
+ return NULL;
+}
+
+static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct recent_iter_state *st = seq->private;
+ const struct recent_table *t = st->table;
+ const struct recent_entry *e = v;
+ const struct list_head *head = e->list.next;
+
+ while (head == &t->iphash[st->bucket]) {
+ if (++st->bucket >= ip_list_hash_size)
+ return NULL;
+ head = t->iphash[st->bucket].next;
+ }
+ (*pos)++;
+ return list_entry(head, struct recent_entry, list);
+}
+
+static void recent_seq_stop(struct seq_file *s, void *v)
+ __releases(recent_lock)
+{
+ spin_unlock_bh(&recent_lock);
+}
+
+static int recent_seq_show(struct seq_file *seq, void *v)
+{
+ const struct recent_entry *e = v;
+ unsigned int i;
+
+ i = (e->index - 1) % ip_pkt_list_tot;
+ if (e->family == NFPROTO_IPV4)
+ seq_printf(seq, "src=" NIPQUAD_FMT " ttl: %u last_seen: %lu "
+ "oldest_pkt: %u", NIPQUAD(e->addr.ip), e->ttl,
+ e->stamps[i], e->index);
+ else
+ seq_printf(seq, "src=" NIP6_FMT " ttl: %u last_seen: %lu "
+ "oldest_pkt: %u", NIP6(e->addr.in6), e->ttl,
+ e->stamps[i], e->index);
+ for (i = 0; i < e->nstamps; i++)
+ seq_printf(seq, "%s %lu", i ? "," : "", e->stamps[i]);
+ seq_printf(seq, "\n");
+ return 0;
+}
+
+static const struct seq_operations recent_seq_ops = {
+ .start = recent_seq_start,
+ .next = recent_seq_next,
+ .stop = recent_seq_stop,
+ .show = recent_seq_show,
+};
+
+static int recent_seq_open(struct inode *inode, struct file *file)
+{
+ struct proc_dir_entry *pde = PDE(inode);
+ struct recent_iter_state *st;
+
+ st = __seq_open_private(file, &recent_seq_ops, sizeof(*st));
+ if (st == NULL)
+ return -ENOMEM;
+
+ st->table = pde->data;
+ return 0;
+}
+
+#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
+static int recent_old_seq_open(struct inode *inode, struct file *filp)
+{
+ static bool warned_of_old;
+
+ if (unlikely(!warned_of_old)) {
+ printk(KERN_INFO KBUILD_MODNAME ": Use of /proc/net/ipt_recent"
+ " is deprecated; use /proc/net/xt_recent.\n");
+ warned_of_old = true;
+ }
+ return recent_seq_open(inode, filp);
+}
+
+static ssize_t recent_old_proc_write(struct file *file,
+ const char __user *input,
+ size_t size, loff_t *loff)
+{
+ const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ struct recent_table *t = pde->data;
+ struct recent_entry *e;
+ char buf[sizeof("+255.255.255.255")], *c = buf;
+ __be32 addr;
+ int add;
+
+ if (size > sizeof(buf))
+ size = sizeof(buf);
+ if (copy_from_user(buf, input, size))
+ return -EFAULT;
+
+ while (isspace(*c))
+ c++;
+
+ if (size - (c - buf) < 5)
+ return c - buf;
+ if (!strncmp(c, "clear", 5)) {
+ c += 5;
+ spin_lock_bh(&recent_lock);
+ recent_table_flush(t);
+ spin_unlock_bh(&recent_lock);
+ return c - buf;
+ }
+
+ switch (*c) {
+ case '-':
+ add = 0;
+ c++;
+ break;
+ case '+':
+ c++;
+ default:
+ add = 1;
+ break;
+ }
+ addr = in_aton(c);
+
+ spin_lock_bh(&recent_lock);
+ e = recent_entry_lookup(t, (const void *)&addr, NFPROTO_IPV4, 0);
+ if (e == NULL) {
+ if (add)
+ recent_entry_init(t, (const void *)&addr,
+ NFPROTO_IPV4, 0);
+ } else {
+ if (add)
+ recent_entry_update(t, e);
+ else
+ recent_entry_remove(t, e);
+ }
+ spin_unlock_bh(&recent_lock);
+ return size;
+}
+
+static const struct file_operations recent_old_fops = {
+ .open = recent_old_seq_open,
+ .read = seq_read,
+ .write = recent_old_proc_write,
+ .release = seq_release_private,
+ .owner = THIS_MODULE,
+};
+#endif
+
+static ssize_t
+recent_mt_proc_write(struct file *file, const char __user *input,
+ size_t size, loff_t *loff)
+{
+ const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ struct recent_table *t = pde->data;
+ struct recent_entry *e;
+ char buf[sizeof("+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")];
+ const char *c = buf;
+ union nf_inet_addr addr;
+ u_int16_t family;
+ bool add, succ;
+
+ if (size == 0)
+ return 0;
+ if (size > sizeof(buf))
+ size = sizeof(buf);
+ if (copy_from_user(buf, input, size) != 0)
+ return -EFAULT;
+
+ /* Strict protocol! */
+ if (*loff != 0)
+ return -ESPIPE;
+ switch (*c) {
+ case '/': /* flush table */
+ spin_lock_bh(&recent_lock);
+ recent_table_flush(t);
+ spin_unlock_bh(&recent_lock);
+ return size;
+ case '-': /* remove address */
+ add = false;
+ break;
+ case '+': /* add address */
+ add = true;
+ break;
+ default:
+ printk(KERN_INFO KBUILD_MODNAME ": Need +ip, -ip or /\n");
+ return -EINVAL;
+ }
+
+ ++c;
+ --size;
+ if (strnchr(c, size, ':') != NULL) {
+ family = NFPROTO_IPV6;
+ succ = in6_pton(c, size, (void *)&addr, '\n', NULL);
+ } else {
+ family = NFPROTO_IPV4;
+ succ = in4_pton(c, size, (void *)&addr, '\n', NULL);
+ }
+
+ if (!succ) {
+ printk(KERN_INFO KBUILD_MODNAME ": illegal address written "
+ "to procfs\n");
+ return -EINVAL;
+ }
+
+ spin_lock_bh(&recent_lock);
+ e = recent_entry_lookup(t, &addr, family, 0);
+ if (e == NULL) {
+ if (add)
+ recent_entry_init(t, &addr, family, 0);
+ } else {
+ if (add)
+ recent_entry_update(t, e);
+ else
+ recent_entry_remove(t, e);
+ }
+ spin_unlock_bh(&recent_lock);
+ /* Note we removed one above */
+ *loff += size + 1;
+ return size + 1;
+}
+
+static const struct file_operations recent_mt_fops = {
+ .open = recent_seq_open,
+ .read = seq_read,
+ .write = recent_mt_proc_write,
+ .release = seq_release_private,
+ .owner = THIS_MODULE,
+};
+#endif /* CONFIG_PROC_FS */
+
+static struct xt_match recent_mt_reg[] __read_mostly = {
+ {
+ .name = "recent",
+ .revision = 0,
+ .family = NFPROTO_IPV4,
+ .match = recent_mt,
+ .matchsize = sizeof(struct xt_recent_mtinfo),
+ .checkentry = recent_mt_check,
+ .destroy = recent_mt_destroy,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "recent",
+ .revision = 0,
+ .family = NFPROTO_IPV6,
+ .match = recent_mt,
+ .matchsize = sizeof(struct xt_recent_mtinfo),
+ .checkentry = recent_mt_check,
+ .destroy = recent_mt_destroy,
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init recent_mt_init(void)
+{
+ int err;
+
+ if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255)
+ return -EINVAL;
+ ip_list_hash_size = 1 << fls(ip_list_tot);
+
+ err = xt_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
+#ifdef CONFIG_PROC_FS
+ if (err)
+ return err;
+ recent_proc_dir = proc_mkdir("xt_recent", init_net.proc_net);
+ if (recent_proc_dir == NULL) {
+ xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
+ err = -ENOMEM;
+ }
+#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
+ if (err < 0)
+ return err;
+ proc_old_dir = proc_mkdir("ipt_recent", init_net.proc_net);
+ if (proc_old_dir == NULL) {
+ remove_proc_entry("xt_recent", init_net.proc_net);
+ xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
+ err = -ENOMEM;
+ }
+#endif
+#endif
+ return err;
+}
+
+static void __exit recent_mt_exit(void)
+{
+ BUG_ON(!list_empty(&tables));
+ xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
+ remove_proc_entry("ipt_recent", init_net.proc_net);
+#endif
+ remove_proc_entry("xt_recent", init_net.proc_net);
+#endif
+}
+
+module_init(recent_mt_init);
+module_exit(recent_mt_exit);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index e6e4681fa047..e223cb43ae8e 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -117,23 +117,21 @@ match_packet(const struct sk_buff *skb,
}
static bool
-sctp_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+sctp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_sctp_info *info = matchinfo;
+ const struct xt_sctp_info *info = par->matchinfo;
const sctp_sctphdr_t *sh;
sctp_sctphdr_t _sh;
- if (offset) {
+ if (par->fragoff != 0) {
duprintf("Dropping non-first fragment.. FIXME\n");
return false;
}
- sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
+ sh = skb_header_pointer(skb, par->thoff, sizeof(_sh), &_sh);
if (sh == NULL) {
duprintf("Dropping evil TCP offset=0 tinygram.\n");
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
@@ -144,17 +142,14 @@ sctp_mt(const struct sk_buff *skb, const struct net_device *in,
&& SCCHECK(ntohs(sh->dest) >= info->dpts[0]
&& ntohs(sh->dest) <= info->dpts[1],
XT_SCTP_DEST_PORTS, info->flags, info->invflags)
- && SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t),
- info, hotdrop),
+ && SCCHECK(match_packet(skb, par->thoff + sizeof(sctp_sctphdr_t),
+ info, par->hotdrop),
XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
}
-static bool
-sctp_mt_check(const char *tablename, const void *inf,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool sctp_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_sctp_info *info = matchinfo;
+ const struct xt_sctp_info *info = par->matchinfo;
return !(info->flags & ~XT_SCTP_VALID_FLAGS)
&& !(info->invflags & ~XT_SCTP_VALID_FLAGS)
@@ -169,7 +164,7 @@ sctp_mt_check(const char *tablename, const void *inf,
static struct xt_match sctp_mt_reg[] __read_mostly = {
{
.name = "sctp",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = sctp_mt_check,
.match = sctp_mt,
.matchsize = sizeof(struct xt_sctp_info),
@@ -178,7 +173,7 @@ static struct xt_match sctp_mt_reg[] __read_mostly = {
},
{
.name = "sctp",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = sctp_mt_check,
.match = sctp_mt,
.matchsize = sizeof(struct xt_sctp_info),
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
new file mode 100644
index 000000000000..02a8fed21082
--- /dev/null
+++ b/net/netfilter/xt_socket.c
@@ -0,0 +1,185 @@
+/*
+ * Transparent proxy support for Linux/iptables
+ *
+ * Copyright (C) 2007-2008 BalaBit IT Ltd.
+ * Author: Krisztian Kovacs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/icmp.h>
+#include <net/sock.h>
+#include <net/inet_sock.h>
+#include <net/netfilter/nf_tproxy_core.h>
+#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
+
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#define XT_SOCKET_HAVE_CONNTRACK 1
+#include <net/netfilter/nf_conntrack.h>
+#endif
+
+static int
+extract_icmp_fields(const struct sk_buff *skb,
+ u8 *protocol,
+ __be32 *raddr,
+ __be32 *laddr,
+ __be16 *rport,
+ __be16 *lport)
+{
+ unsigned int outside_hdrlen = ip_hdrlen(skb);
+ struct iphdr *inside_iph, _inside_iph;
+ struct icmphdr *icmph, _icmph;
+ __be16 *ports, _ports[2];
+
+ icmph = skb_header_pointer(skb, outside_hdrlen,
+ sizeof(_icmph), &_icmph);
+ if (icmph == NULL)
+ return 1;
+
+ switch (icmph->type) {
+ case ICMP_DEST_UNREACH:
+ case ICMP_SOURCE_QUENCH:
+ case ICMP_REDIRECT:
+ case ICMP_TIME_EXCEEDED:
+ case ICMP_PARAMETERPROB:
+ break;
+ default:
+ return 1;
+ }
+
+ inside_iph = skb_header_pointer(skb, outside_hdrlen +
+ sizeof(struct icmphdr),
+ sizeof(_inside_iph), &_inside_iph);
+ if (inside_iph == NULL)
+ return 1;
+
+ if (inside_iph->protocol != IPPROTO_TCP &&
+ inside_iph->protocol != IPPROTO_UDP)
+ return 1;
+
+ ports = skb_header_pointer(skb, outside_hdrlen +
+ sizeof(struct icmphdr) +
+ (inside_iph->ihl << 2),
+ sizeof(_ports), &_ports);
+ if (ports == NULL)
+ return 1;
+
+ /* the inside IP packet is the one quoted from our side, thus
+ * its saddr is the local address */
+ *protocol = inside_iph->protocol;
+ *laddr = inside_iph->saddr;
+ *lport = ports[0];
+ *raddr = inside_iph->daddr;
+ *rport = ports[1];
+
+ return 0;
+}
+
+
+static bool
+socket_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+ struct udphdr _hdr, *hp = NULL;
+ struct sock *sk;
+ __be32 daddr, saddr;
+ __be16 dport, sport;
+ u8 protocol;
+#ifdef XT_SOCKET_HAVE_CONNTRACK
+ struct nf_conn const *ct;
+ enum ip_conntrack_info ctinfo;
+#endif
+
+ if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) {
+ hp = skb_header_pointer(skb, ip_hdrlen(skb),
+ sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+ return false;
+
+ protocol = iph->protocol;
+ saddr = iph->saddr;
+ sport = hp->source;
+ daddr = iph->daddr;
+ dport = hp->dest;
+
+ } else if (iph->protocol == IPPROTO_ICMP) {
+ if (extract_icmp_fields(skb, &protocol, &saddr, &daddr,
+ &sport, &dport))
+ return false;
+ } else {
+ return false;
+ }
+
+#ifdef XT_SOCKET_HAVE_CONNTRACK
+ /* Do the lookup with the original socket address in case this is a
+ * reply packet of an established SNAT-ted connection. */
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct && (ct != &nf_conntrack_untracked) &&
+ ((iph->protocol != IPPROTO_ICMP &&
+ ctinfo == IP_CT_IS_REPLY + IP_CT_ESTABLISHED) ||
+ (iph->protocol == IPPROTO_ICMP &&
+ ctinfo == IP_CT_IS_REPLY + IP_CT_RELATED)) &&
+ (ct->status & IPS_SRC_NAT_DONE)) {
+
+ daddr = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
+ dport = (iph->protocol == IPPROTO_TCP) ?
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port :
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
+ }
+#endif
+
+ sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
+ saddr, daddr, sport, dport, par->in, false);
+ if (sk != NULL) {
+ bool wildcard = (inet_sk(sk)->rcv_saddr == 0);
+
+ nf_tproxy_put_sock(sk);
+ if (wildcard)
+ sk = NULL;
+ }
+
+ pr_debug("socket match: proto %u %08x:%u -> %08x:%u "
+ "(orig %08x:%u) sock %p\n",
+ protocol, ntohl(saddr), ntohs(sport),
+ ntohl(daddr), ntohs(dport),
+ ntohl(iph->daddr), hp ? ntohs(hp->dest) : 0, sk);
+
+ return (sk != NULL);
+}
+
+static struct xt_match socket_mt_reg __read_mostly = {
+ .name = "socket",
+ .family = AF_INET,
+ .match = socket_mt,
+ .hooks = 1 << NF_INET_PRE_ROUTING,
+ .me = THIS_MODULE,
+};
+
+static int __init socket_mt_init(void)
+{
+ nf_defrag_ipv4_enable();
+ return xt_register_match(&socket_mt_reg);
+}
+
+static void __exit socket_mt_exit(void)
+{
+ xt_unregister_match(&socket_mt_reg);
+}
+
+module_init(socket_mt_init);
+module_exit(socket_mt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
+MODULE_DESCRIPTION("x_tables socket match module");
+MODULE_ALIAS("ipt_socket");
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index a776dc36a193..4c946cbd731f 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -21,12 +21,9 @@ MODULE_ALIAS("ipt_state");
MODULE_ALIAS("ip6t_state");
static bool
-state_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+state_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_state_info *sinfo = matchinfo;
+ const struct xt_state_info *sinfo = par->matchinfo;
enum ip_conntrack_info ctinfo;
unsigned int statebit;
@@ -40,28 +37,25 @@ state_mt(const struct sk_buff *skb, const struct net_device *in,
return (sinfo->statemask & statebit);
}
-static bool
-state_mt_check(const char *tablename, const void *inf,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool state_mt_check(const struct xt_mtchk_param *par)
{
- if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%u\n", match->family);
+ "proto=%u\n", par->match->family);
return false;
}
return true;
}
-static void state_mt_destroy(const struct xt_match *match, void *matchinfo)
+static void state_mt_destroy(const struct xt_mtdtor_param *par)
{
- nf_ct_l3proto_module_put(match->family);
+ nf_ct_l3proto_module_put(par->match->family);
}
static struct xt_match state_mt_reg[] __read_mostly = {
{
.name = "state",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = state_mt_check,
.match = state_mt,
.destroy = state_mt_destroy,
@@ -70,7 +64,7 @@ static struct xt_match state_mt_reg[] __read_mostly = {
},
{
.name = "state",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = state_mt_check,
.match = state_mt,
.destroy = state_mt_destroy,
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
index 43133080da7d..0d75141139d5 100644
--- a/net/netfilter/xt_statistic.c
+++ b/net/netfilter/xt_statistic.c
@@ -25,12 +25,9 @@ MODULE_ALIAS("ip6t_statistic");
static DEFINE_SPINLOCK(nth_lock);
static bool
-statistic_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+statistic_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+ struct xt_statistic_info *info = (void *)par->matchinfo;
bool ret = info->flags & XT_STATISTIC_INVERT;
switch (info->mode) {
@@ -52,12 +49,9 @@ statistic_mt(const struct sk_buff *skb, const struct net_device *in,
return ret;
}
-static bool
-statistic_mt_check(const char *tablename, const void *entry,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool statistic_mt_check(const struct xt_mtchk_param *par)
{
- struct xt_statistic_info *info = matchinfo;
+ struct xt_statistic_info *info = par->matchinfo;
if (info->mode > XT_STATISTIC_MODE_MAX ||
info->flags & ~XT_STATISTIC_MASK)
@@ -66,35 +60,24 @@ statistic_mt_check(const char *tablename, const void *entry,
return true;
}
-static struct xt_match statistic_mt_reg[] __read_mostly = {
- {
- .name = "statistic",
- .family = AF_INET,
- .checkentry = statistic_mt_check,
- .match = statistic_mt,
- .matchsize = sizeof(struct xt_statistic_info),
- .me = THIS_MODULE,
- },
- {
- .name = "statistic",
- .family = AF_INET6,
- .checkentry = statistic_mt_check,
- .match = statistic_mt,
- .matchsize = sizeof(struct xt_statistic_info),
- .me = THIS_MODULE,
- },
+static struct xt_match xt_statistic_mt_reg __read_mostly = {
+ .name = "statistic",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = statistic_mt,
+ .checkentry = statistic_mt_check,
+ .matchsize = sizeof(struct xt_statistic_info),
+ .me = THIS_MODULE,
};
static int __init statistic_mt_init(void)
{
- return xt_register_matches(statistic_mt_reg,
- ARRAY_SIZE(statistic_mt_reg));
+ return xt_register_match(&xt_statistic_mt_reg);
}
static void __exit statistic_mt_exit(void)
{
- xt_unregister_matches(statistic_mt_reg,
- ARRAY_SIZE(statistic_mt_reg));
+ xt_unregister_match(&xt_statistic_mt_reg);
}
module_init(statistic_mt_init);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 4903182a062b..b4d774111311 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -22,18 +22,15 @@ MODULE_ALIAS("ipt_string");
MODULE_ALIAS("ip6t_string");
static bool
-string_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+string_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_string_info *conf = matchinfo;
+ const struct xt_string_info *conf = par->matchinfo;
struct ts_state state;
int invert;
memset(&state, 0, sizeof(struct ts_state));
- invert = (match->revision == 0 ? conf->u.v0.invert :
+ invert = (par->match->revision == 0 ? conf->u.v0.invert :
conf->u.v1.flags & XT_STRING_FLAG_INVERT);
return (skb_find_text((struct sk_buff *)skb, conf->from_offset,
@@ -43,12 +40,9 @@ string_mt(const struct sk_buff *skb, const struct net_device *in,
#define STRING_TEXT_PRIV(m) ((struct xt_string_info *)(m))
-static bool
-string_mt_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool string_mt_check(const struct xt_mtchk_param *par)
{
- struct xt_string_info *conf = matchinfo;
+ struct xt_string_info *conf = par->matchinfo;
struct ts_config *ts_conf;
int flags = TS_AUTOLOAD;
@@ -59,7 +53,7 @@ string_mt_check(const char *tablename, const void *ip,
return false;
if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE)
return false;
- if (match->revision == 1) {
+ if (par->match->revision == 1) {
if (conf->u.v1.flags &
~(XT_STRING_FLAG_IGNORECASE | XT_STRING_FLAG_INVERT))
return false;
@@ -76,36 +70,16 @@ string_mt_check(const char *tablename, const void *ip,
return true;
}
-static void string_mt_destroy(const struct xt_match *match, void *matchinfo)
+static void string_mt_destroy(const struct xt_mtdtor_param *par)
{
- textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
+ textsearch_destroy(STRING_TEXT_PRIV(par->matchinfo)->config);
}
-static struct xt_match string_mt_reg[] __read_mostly = {
- {
- .name = "string",
- .revision = 0,
- .family = AF_INET,
- .checkentry = string_mt_check,
- .match = string_mt,
- .destroy = string_mt_destroy,
- .matchsize = sizeof(struct xt_string_info),
- .me = THIS_MODULE
- },
- {
- .name = "string",
- .revision = 1,
- .family = AF_INET,
- .checkentry = string_mt_check,
- .match = string_mt,
- .destroy = string_mt_destroy,
- .matchsize = sizeof(struct xt_string_info),
- .me = THIS_MODULE
- },
+static struct xt_match xt_string_mt_reg[] __read_mostly = {
{
.name = "string",
.revision = 0,
- .family = AF_INET6,
+ .family = NFPROTO_UNSPEC,
.checkentry = string_mt_check,
.match = string_mt,
.destroy = string_mt_destroy,
@@ -115,7 +89,7 @@ static struct xt_match string_mt_reg[] __read_mostly = {
{
.name = "string",
.revision = 1,
- .family = AF_INET6,
+ .family = NFPROTO_UNSPEC,
.checkentry = string_mt_check,
.match = string_mt,
.destroy = string_mt_destroy,
@@ -126,12 +100,13 @@ static struct xt_match string_mt_reg[] __read_mostly = {
static int __init string_mt_init(void)
{
- return xt_register_matches(string_mt_reg, ARRAY_SIZE(string_mt_reg));
+ return xt_register_matches(xt_string_mt_reg,
+ ARRAY_SIZE(xt_string_mt_reg));
}
static void __exit string_mt_exit(void)
{
- xt_unregister_matches(string_mt_reg, ARRAY_SIZE(string_mt_reg));
+ xt_unregister_matches(xt_string_mt_reg, ARRAY_SIZE(xt_string_mt_reg));
}
module_init(string_mt_init);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 6771bf01275b..4809b34b10f8 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -25,12 +25,9 @@ MODULE_ALIAS("ipt_tcpmss");
MODULE_ALIAS("ip6t_tcpmss");
static bool
-tcpmss_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff,
- bool *hotdrop)
+tcpmss_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_tcpmss_match_info *info = matchinfo;
+ const struct xt_tcpmss_match_info *info = par->matchinfo;
const struct tcphdr *th;
struct tcphdr _tcph;
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
@@ -39,7 +36,7 @@ tcpmss_mt(const struct sk_buff *skb, const struct net_device *in,
unsigned int i, optlen;
/* If we don't have the whole header, drop packet. */
- th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
+ th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph);
if (th == NULL)
goto dropit;
@@ -52,7 +49,7 @@ tcpmss_mt(const struct sk_buff *skb, const struct net_device *in,
goto out;
/* Truncated options. */
- op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt);
+ op = skb_header_pointer(skb, par->thoff + sizeof(*th), optlen, _opt);
if (op == NULL)
goto dropit;
@@ -76,14 +73,14 @@ out:
return info->invert;
dropit:
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
static struct xt_match tcpmss_mt_reg[] __read_mostly = {
{
.name = "tcpmss",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.match = tcpmss_mt,
.matchsize = sizeof(struct xt_tcpmss_match_info),
.proto = IPPROTO_TCP,
@@ -91,7 +88,7 @@ static struct xt_match tcpmss_mt_reg[] __read_mostly = {
},
{
.name = "tcpmss",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.match = tcpmss_mt,
.matchsize = sizeof(struct xt_tcpmss_match_info),
.proto = IPPROTO_TCP,
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 951b06b8d701..1ebdc4934eed 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -68,25 +68,22 @@ tcp_find_option(u_int8_t option,
return invert;
}
-static bool
-tcp_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+static bool tcp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct tcphdr *th;
struct tcphdr _tcph;
- const struct xt_tcp *tcpinfo = matchinfo;
+ const struct xt_tcp *tcpinfo = par->matchinfo;
- if (offset) {
+ if (par->fragoff != 0) {
/* To quote Alan:
Don't allow a fragment of TCP 8 bytes in. Nobody normal
causes this. Its a cracker trying to break in by doing a
flag overwrite to pass the direction checks.
*/
- if (offset == 1) {
+ if (par->fragoff == 1) {
duprintf("Dropping evil TCP offset=1 frag.\n");
- *hotdrop = true;
+ *par->hotdrop = true;
}
/* Must not be a fragment. */
return false;
@@ -94,12 +91,12 @@ tcp_mt(const struct sk_buff *skb, const struct net_device *in,
#define FWINVTCP(bool, invflg) ((bool) ^ !!(tcpinfo->invflags & (invflg)))
- th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
+ th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph);
if (th == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil TCP offset=0 tinygram.\n");
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
@@ -117,49 +114,42 @@ tcp_mt(const struct sk_buff *skb, const struct net_device *in,
return false;
if (tcpinfo->option) {
if (th->doff * 4 < sizeof(_tcph)) {
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
- if (!tcp_find_option(tcpinfo->option, skb, protoff,
+ if (!tcp_find_option(tcpinfo->option, skb, par->thoff,
th->doff*4 - sizeof(_tcph),
tcpinfo->invflags & XT_TCP_INV_OPTION,
- hotdrop))
+ par->hotdrop))
return false;
}
return true;
}
-/* Called when user tries to insert an entry of this type. */
-static bool
-tcp_mt_check(const char *tablename, const void *info,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool tcp_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_tcp *tcpinfo = matchinfo;
+ const struct xt_tcp *tcpinfo = par->matchinfo;
/* Must specify no unknown invflags */
return !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
}
-static bool
-udp_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+static bool udp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
const struct udphdr *uh;
struct udphdr _udph;
- const struct xt_udp *udpinfo = matchinfo;
+ const struct xt_udp *udpinfo = par->matchinfo;
/* Must not be a fragment. */
- if (offset)
+ if (par->fragoff != 0)
return false;
- uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
+ uh = skb_header_pointer(skb, par->thoff, sizeof(_udph), &_udph);
if (uh == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil UDP tinygram.\n");
- *hotdrop = true;
+ *par->hotdrop = true;
return false;
}
@@ -171,13 +161,9 @@ udp_mt(const struct sk_buff *skb, const struct net_device *in,
!!(udpinfo->invflags & XT_UDP_INV_DSTPT));
}
-/* Called when user tries to insert an entry of this type. */
-static bool
-udp_mt_check(const char *tablename, const void *info,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool udp_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_udp *udpinfo = matchinfo;
+ const struct xt_udp *udpinfo = par->matchinfo;
/* Must specify no unknown invflags */
return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
@@ -186,7 +172,7 @@ udp_mt_check(const char *tablename, const void *info,
static struct xt_match tcpudp_mt_reg[] __read_mostly = {
{
.name = "tcp",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = tcp_mt_check,
.match = tcp_mt,
.matchsize = sizeof(struct xt_tcp),
@@ -195,7 +181,7 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
},
{
.name = "tcp",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = tcp_mt_check,
.match = tcp_mt,
.matchsize = sizeof(struct xt_tcp),
@@ -204,7 +190,7 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
},
{
.name = "udp",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = udp_mt_check,
.match = udp_mt,
.matchsize = sizeof(struct xt_udp),
@@ -213,7 +199,7 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
},
{
.name = "udp",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = udp_mt_check,
.match = udp_mt,
.matchsize = sizeof(struct xt_udp),
@@ -222,7 +208,7 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
},
{
.name = "udplite",
- .family = AF_INET,
+ .family = NFPROTO_IPV4,
.checkentry = udp_mt_check,
.match = udp_mt,
.matchsize = sizeof(struct xt_udp),
@@ -231,7 +217,7 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
},
{
.name = "udplite",
- .family = AF_INET6,
+ .family = NFPROTO_IPV6,
.checkentry = udp_mt_check,
.match = udp_mt,
.matchsize = sizeof(struct xt_udp),
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index 307a2c3c2df4..29375ba8db73 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -153,11 +153,9 @@ static void localtime_3(struct xtm *r, time_t time)
}
static bool
-time_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+time_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_time_info *info = matchinfo;
+ const struct xt_time_info *info = par->matchinfo;
unsigned int packet_time;
struct xtm current_time;
s64 stamp;
@@ -220,12 +218,9 @@ time_mt(const struct sk_buff *skb, const struct net_device *in,
return true;
}
-static bool
-time_mt_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool time_mt_check(const struct xt_mtchk_param *par)
{
- const struct xt_time_info *info = matchinfo;
+ const struct xt_time_info *info = par->matchinfo;
if (info->daytime_start > XT_TIME_MAX_DAYTIME ||
info->daytime_stop > XT_TIME_MAX_DAYTIME) {
@@ -237,33 +232,23 @@ time_mt_check(const char *tablename, const void *ip,
return true;
}
-static struct xt_match time_mt_reg[] __read_mostly = {
- {
- .name = "time",
- .family = AF_INET,
- .match = time_mt,
- .matchsize = sizeof(struct xt_time_info),
- .checkentry = time_mt_check,
- .me = THIS_MODULE,
- },
- {
- .name = "time",
- .family = AF_INET6,
- .match = time_mt,
- .matchsize = sizeof(struct xt_time_info),
- .checkentry = time_mt_check,
- .me = THIS_MODULE,
- },
+static struct xt_match xt_time_mt_reg __read_mostly = {
+ .name = "time",
+ .family = NFPROTO_UNSPEC,
+ .match = time_mt,
+ .checkentry = time_mt_check,
+ .matchsize = sizeof(struct xt_time_info),
+ .me = THIS_MODULE,
};
static int __init time_mt_init(void)
{
- return xt_register_matches(time_mt_reg, ARRAY_SIZE(time_mt_reg));
+ return xt_register_match(&xt_time_mt_reg);
}
static void __exit time_mt_exit(void)
{
- xt_unregister_matches(time_mt_reg, ARRAY_SIZE(time_mt_reg));
+ xt_unregister_match(&xt_time_mt_reg);
}
module_init(time_mt_init);
diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c
index 627e0f336d54..24a527624500 100644
--- a/net/netfilter/xt_u32.c
+++ b/net/netfilter/xt_u32.c
@@ -87,43 +87,32 @@ static bool u32_match_it(const struct xt_u32 *data,
return true;
}
-static bool
-u32_mt(const struct sk_buff *skb, const struct net_device *in,
- const struct net_device *out, const struct xt_match *match,
- const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+static bool u32_mt(const struct sk_buff *skb, const struct xt_match_param *par)
{
- const struct xt_u32 *data = matchinfo;
+ const struct xt_u32 *data = par->matchinfo;
bool ret;
ret = u32_match_it(data, skb);
return ret ^ data->invert;
}
-static struct xt_match u32_mt_reg[] __read_mostly = {
- {
- .name = "u32",
- .family = AF_INET,
- .match = u32_mt,
- .matchsize = sizeof(struct xt_u32),
- .me = THIS_MODULE,
- },
- {
- .name = "u32",
- .family = AF_INET6,
- .match = u32_mt,
- .matchsize = sizeof(struct xt_u32),
- .me = THIS_MODULE,
- },
+static struct xt_match xt_u32_mt_reg __read_mostly = {
+ .name = "u32",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = u32_mt,
+ .matchsize = sizeof(struct xt_u32),
+ .me = THIS_MODULE,
};
static int __init u32_mt_init(void)
{
- return xt_register_matches(u32_mt_reg, ARRAY_SIZE(u32_mt_reg));
+ return xt_register_match(&xt_u32_mt_reg);
}
static void __exit u32_mt_exit(void)
{
- xt_unregister_matches(u32_mt_reg, ARRAY_SIZE(u32_mt_reg));
+ xt_unregister_match(&xt_u32_mt_reg);
}
module_init(u32_mt_init);