aboutsummaryrefslogtreecommitdiff
path: root/net/netfilter
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 22:54:01 +1100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 22:54:01 +1100
commit0ba6c33bcddc64a54b5f1c25a696c4767dc76292 (patch)
tree62e616f97a4762d8e75bf732e4827af2d15d52c5 /net/netfilter
parent21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (diff)
parent85040bcb4643cba578839e953f25e2d1965d83d0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25: (1470 commits) [IPV6] ADDRLABEL: Fix double free on label deletion. [PPP]: Sparse warning fixes. [IPV4] fib_trie: remove unneeded NULL check [IPV4] fib_trie: More whitespace cleanup. [NET_SCHED]: Use nla_policy for attribute validation in ematches [NET_SCHED]: Use nla_policy for attribute validation in actions [NET_SCHED]: Use nla_policy for attribute validation in classifiers [NET_SCHED]: Use nla_policy for attribute validation in packet schedulers [NET_SCHED]: sch_api: introduce constant for rate table size [NET_SCHED]: Use typeful attribute parsing helpers [NET_SCHED]: Use typeful attribute construction helpers [NET_SCHED]: Use NLA_PUT_STRING for string dumping [NET_SCHED]: Use nla_nest_start/nla_nest_end [NET_SCHED]: Propagate nla_parse return value [NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get [NET_SCHED]: act_api: use nlmsg_parse [NET_SCHED]: act_api: fix netlink API conversion bug [NET_SCHED]: sch_netem: use nla_parse_nested_compat [NET_SCHED]: sch_atm: fix format string warning [NETNS]: Add namespace for ICMP replying code. ...
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/Kconfig180
-rw-r--r--net/netfilter/Makefile6
-rw-r--r--net/netfilter/core.c47
-rw-r--r--net/netfilter/nf_conntrack_core.c17
-rw-r--r--net/netfilter/nf_conntrack_expect.c12
-rw-r--r--net/netfilter/nf_conntrack_ftp.c2
-rw-r--r--net/netfilter/nf_conntrack_h323_asn1.c8
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c53
-rw-r--r--net/netfilter/nf_conntrack_l3proto_generic.c7
-rw-r--r--net/netfilter/nf_conntrack_netlink.c264
-rw-r--r--net/netfilter/nf_conntrack_proto.c7
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c8
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c328
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c96
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c14
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c13
-rw-r--r--net/netfilter/nf_conntrack_sip.c8
-rw-r--r--net/netfilter/nf_conntrack_standalone.c20
-rw-r--r--net/netfilter/nf_log.c12
-rw-r--r--net/netfilter/nf_queue.c183
-rw-r--r--net/netfilter/nf_sysctl.c134
-rw-r--r--net/netfilter/nfnetlink.c2
-rw-r--r--net/netfilter/nfnetlink_log.c203
-rw-r--r--net/netfilter/nfnetlink_queue.c595
-rw-r--r--net/netfilter/x_tables.c65
-rw-r--r--net/netfilter/xt_CLASSIFY.c44
-rw-r--r--net/netfilter/xt_CONNMARK.c150
-rw-r--r--net/netfilter/xt_CONNSECMARK.c56
-rw-r--r--net/netfilter/xt_DSCP.c167
-rw-r--r--net/netfilter/xt_MARK.c158
-rw-r--r--net/netfilter/xt_NFLOG.c39
-rw-r--r--net/netfilter/xt_NFQUEUE.c32
-rw-r--r--net/netfilter/xt_NOTRACK.c29
-rw-r--r--net/netfilter/xt_RATEEST.c205
-rw-r--r--net/netfilter/xt_SECMARK.c40
-rw-r--r--net/netfilter/xt_TCPMSS.c94
-rw-r--r--net/netfilter/xt_TCPOPTSTRIP.c147
-rw-r--r--net/netfilter/xt_TRACE.c29
-rw-r--r--net/netfilter/xt_comment.c33
-rw-r--r--net/netfilter/xt_connbytes.c56
-rw-r--r--net/netfilter/xt_connlimit.c75
-rw-r--r--net/netfilter/xt_connmark.c129
-rw-r--r--net/netfilter/xt_conntrack.c237
-rw-r--r--net/netfilter/xt_dccp.c43
-rw-r--r--net/netfilter/xt_dscp.c112
-rw-r--r--net/netfilter/xt_esp.c43
-rw-r--r--net/netfilter/xt_hashlimit.c104
-rw-r--r--net/netfilter/xt_helper.c56
-rw-r--r--net/netfilter/xt_iprange.c180
-rw-r--r--net/netfilter/xt_length.c45
-rw-r--r--net/netfilter/xt_limit.c57
-rw-r--r--net/netfilter/xt_mac.c43
-rw-r--r--net/netfilter/xt_mark.c100
-rw-r--r--net/netfilter/xt_multiport.c100
-rw-r--r--net/netfilter/xt_owner.c211
-rw-r--r--net/netfilter/xt_physdev.c51
-rw-r--r--net/netfilter/xt_pkttype.c51
-rw-r--r--net/netfilter/xt_policy.c67
-rw-r--r--net/netfilter/xt_quota.c37
-rw-r--r--net/netfilter/xt_rateest.c178
-rw-r--r--net/netfilter/xt_realm.c34
-rw-r--r--net/netfilter/xt_sctp.c43
-rw-r--r--net/netfilter/xt_state.c52
-rw-r--r--net/netfilter/xt_statistic.c42
-rw-r--r--net/netfilter/xt_string.c54
-rw-r--r--net/netfilter/xt_tcpmss.c33
-rw-r--r--net/netfilter/xt_tcpudp.c79
-rw-r--r--net/netfilter/xt_time.c40
-rw-r--r--net/netfilter/xt_u32.c29
69 files changed, 3570 insertions, 2318 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 21a9fcc0379..daf5b881064 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -2,21 +2,20 @@ menu "Core Netfilter Configuration"
depends on NET && INET && NETFILTER
config NETFILTER_NETLINK
- tristate "Netfilter netlink interface"
- help
- If this option is enabled, the kernel will include support
- for the new netfilter netlink interface.
+ tristate
config NETFILTER_NETLINK_QUEUE
tristate "Netfilter NFQUEUE over NFNETLINK interface"
- depends on NETFILTER_NETLINK
+ depends on NETFILTER_ADVANCED
+ select NETFILTER_NETLINK
help
If this option is enabled, the kernel will include support
for queueing packets via NFNETLINK.
config NETFILTER_NETLINK_LOG
tristate "Netfilter LOG over NFNETLINK interface"
- depends on NETFILTER_NETLINK
+ default m if NETFILTER_ADVANCED=n
+ select NETFILTER_NETLINK
help
If this option is enabled, the kernel will include support
for logging packets via NFNETLINK.
@@ -25,9 +24,9 @@ config NETFILTER_NETLINK_LOG
and is also scheduled to replace the old syslog-based ipt_LOG
and ip6t_LOG modules.
-# Rename this to NF_CONNTRACK in a 2.6.25
-config NF_CONNTRACK_ENABLED
+config NF_CONNTRACK
tristate "Netfilter connection tracking support"
+ default m if NETFILTER_ADVANCED=n
help
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
@@ -40,12 +39,9 @@ config NF_CONNTRACK_ENABLED
To compile it as a module, choose M here. If unsure, say N.
-config NF_CONNTRACK
- tristate
- default NF_CONNTRACK_ENABLED
-
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
@@ -58,6 +54,7 @@ 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
@@ -68,6 +65,7 @@ config NF_CONNTRACK_MARK
config NF_CONNTRACK_SECMARK
bool 'Connection tracking security mark support'
depends on NF_CONNTRACK && NETWORK_SECMARK
+ default m if NETFILTER_ADVANCED=n
help
This option enables security markings to be applied to
connections. Typically they are copied to connections from
@@ -78,8 +76,9 @@ config NF_CONNTRACK_SECMARK
If unsure, say 'N'.
config NF_CONNTRACK_EVENTS
- bool "Connection tracking events (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ bool "Connection tracking events"
+ depends on NF_CONNTRACK
+ depends on NETFILTER_ADVANCED
help
If this option is enabled, the connection tracking code will
provide a notifier chain that can be used by other kernel code
@@ -94,7 +93,7 @@ config NF_CT_PROTO_GRE
config NF_CT_PROTO_SCTP
tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
depends on EXPERIMENTAL && NF_CONNTRACK
- default n
+ depends on NETFILTER_ADVANCED
help
With this option enabled, the layer 3 independent connection
tracking code will be able to do state tracking on SCTP connections.
@@ -103,8 +102,9 @@ config NF_CT_PROTO_SCTP
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
config NF_CT_PROTO_UDPLITE
- tristate 'UDP-Lite protocol connection tracking support (EXPERIMENTAL)'
- depends on EXPERIMENTAL && NF_CONNTRACK
+ 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
tracking code will be able to do state tracking on UDP-Lite
@@ -115,6 +115,7 @@ 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
help
@@ -130,6 +131,7 @@ 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
required for tracking them, and doing masquerading and other forms
@@ -142,8 +144,9 @@ config NF_CONNTRACK_FTP
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_H323
- tristate "H.323 protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK && (IPV6 || IPV6=n)
+ tristate "H.323 protocol support"
+ depends on NF_CONNTRACK && (IPV6 || IPV6=n)
+ depends on NETFILTER_ADVANCED
help
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
important VoIP protocols, it is widely used by voice hardware and
@@ -163,6 +166,7 @@ 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
Direct Client-to-Client Protocol (DCC). This enables users to send
@@ -176,8 +180,9 @@ config NF_CONNTRACK_IRC
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_NETBIOS_NS
- tristate "NetBIOS name service protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ 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
unprivileged port and responded to with unicast messages to the
@@ -197,6 +202,7 @@ 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
This module adds support for PPTP (Point to Point Tunnelling
@@ -216,6 +222,7 @@ config NF_CONNTRACK_PPTP
config NF_CONNTRACK_SANE
tristate "SANE protocol support (EXPERIMENTAL)"
depends on EXPERIMENTAL && NF_CONNTRACK
+ depends on NETFILTER_ADVANCED
help
SANE is a protocol for remote access to scanners as implemented
by the 'saned' daemon. Like FTP, it uses separate control and
@@ -227,8 +234,9 @@ config NF_CONNTRACK_SANE
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_SIP
- tristate "SIP protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ 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,
modify, and terminate multimedia sessions (conferences) such as
@@ -241,6 +249,7 @@ 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
on how restrictive your ruleset is.
@@ -250,15 +259,17 @@ config NF_CONNTRACK_TFTP
To compile it as a module, choose M here. If unsure, say N.
config NF_CT_NETLINK
- tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
- depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
- depends on NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+ 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
config NETFILTER_XTABLES
tristate "Netfilter Xtables support (required for ip_tables)"
+ default m if NETFILTER_ADVANCED=n
help
This is required if you intend to use any of ip_tables,
ip6_tables or arp_tables.
@@ -268,6 +279,7 @@ config NETFILTER_XTABLES
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
the priority of a packet. Some qdiscs can use this value for
@@ -282,31 +294,38 @@ config NETFILTER_XT_TARGET_CONNMARK
depends on NETFILTER_XTABLES
depends on IP_NF_MANGLE || IP6_NF_MANGLE
depends on NF_CONNTRACK
+ depends on NETFILTER_ADVANCED
select NF_CONNTRACK_MARK
help
This option adds a `CONNMARK' target, which allows one to manipulate
the connection mark value. Similar to the MARK target, but
affects the connection mark value rather than the packet mark value.
-
+
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. The module will be called
ipt_CONNMARK.ko. If unsure, say `N'.
config NETFILTER_XT_TARGET_DSCP
- tristate '"DSCP" target support'
+ tristate '"DSCP" and "TOS" target support'
depends on NETFILTER_XTABLES
depends on IP_NF_MANGLE || IP6_NF_MANGLE
+ depends on NETFILTER_ADVANCED
help
This option adds a `DSCP' target, which allows you to manipulate
the IPv4/IPv6 header DSCP field (differentiated services codepoint).
The DSCP field can have any value between 0x0 and 0x3f inclusive.
+ It also adds the "TOS" target, which allows you to create rules in
+ the "mangle" table which alter the Type Of Service field of an IPv4
+ or the Priority field of an IPv6 packet, prior to routing.
+
To compile it as a module, choose M here. If unsure, say N.
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
in the `mangle' table which alter the netfilter mark (nfmark) field
@@ -320,6 +339,7 @@ config NETFILTER_XT_TARGET_MARK
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.
@@ -331,6 +351,7 @@ config NETFILTER_XT_TARGET_NFQUEUE
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
messages through the netfilter logging API, which can use
@@ -344,19 +365,32 @@ config NETFILTER_XT_TARGET_NOTRACK
depends on NETFILTER_XTABLES
depends on IP_NF_RAW || IP6_NF_RAW
depends on NF_CONNTRACK
+ depends on NETFILTER_ADVANCED
help
The NOTRACK target allows a select rule to specify
which packets *not* to enter the conntrack/NAT
subsystem with all the consequences (no ICMP error tracking,
no protocol helpers for the selected packets).
-
+
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_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
+ rates similar to TC estimators. The `rateest' match can be
+ used to match on the measured rates.
+
+ 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
The TRACE target allows you to mark packets so that the kernel
will log every rule which match the packets as those traverse
@@ -368,6 +402,7 @@ config NETFILTER_XT_TARGET_TRACE
config NETFILTER_XT_TARGET_SECMARK
tristate '"SECMARK" target support'
depends on NETFILTER_XTABLES && NETWORK_SECMARK
+ default m if NETFILTER_ADVANCED=n
help
The SECMARK target allows security marking of network
packets, for use with security subsystems.
@@ -377,6 +412,7 @@ config NETFILTER_XT_TARGET_SECMARK
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
@@ -388,6 +424,7 @@ config NETFILTER_XT_TARGET_CONNSECMARK
config NETFILTER_XT_TARGET_TCPMSS
tristate '"TCPMSS" target support'
depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
+ default m if NETFILTER_ADVANCED=n
---help---
This option adds a `TCPMSS' target, which allows you to alter the
MSS value of TCP SYN packets, to control the maximum size for that
@@ -411,9 +448,19 @@ config NETFILTER_XT_TARGET_TCPMSS
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_TARGET_TCPOPTSTRIP
+ tristate '"TCPOPTSTRIP" target support (EXPERIMENTAL)'
+ depends on EXPERIMENTAL && NETFILTER_XTABLES
+ depends on IP_NF_MANGLE || IP6_NF_MANGLE
+ depends on NETFILTER_ADVANCED
+ help
+ This option adds a "TCPOPTSTRIP" target, which allows you to strip
+ TCP options from TCP packets.
+
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
comments in your iptables ruleset.
@@ -425,6 +472,7 @@ 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
help
This option adds a `connbytes' match, which allows you to match the
@@ -437,6 +485,7 @@ config NETFILTER_XT_MATCH_CONNLIMIT
tristate '"connlimit" match support"'
depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
+ depends on NETFILTER_ADVANCED
---help---
This match allows you to match against the number of parallel
connections to a server per client IP address (or address block).
@@ -445,11 +494,12 @@ 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
help
This option adds a `connmark' match, which allows you to match the
connection mark value previously set for the session by `CONNMARK'.
-
+
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. The module will be called
ipt_connmark.ko. If unsure, say `N'.
@@ -458,6 +508,7 @@ 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
This is a general conntrack match module, a superset of the state match.
@@ -468,8 +519,9 @@ config NETFILTER_XT_MATCH_CONNTRACK
To compile it as a module, choose M here. If unsure, say N.
config NETFILTER_XT_MATCH_DCCP
- tristate '"DCCP" protocol match support'
+ tristate '"dccp" protocol match support'
depends on NETFILTER_XTABLES
+ depends on NETFILTER_ADVANCED
help
With this option enabled, you will be able to use the iptables
`dccp' match in order to match on DCCP source/destination ports
@@ -479,19 +531,25 @@ config NETFILTER_XT_MATCH_DCCP
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
config NETFILTER_XT_MATCH_DSCP
- tristate '"DSCP" match support'
+ 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
the IPv4/IPv6 header DSCP field (differentiated services codepoint).
The DSCP field can have any value between 0x0 and 0x3f inclusive.
+ It will also add a "tos" match, which allows you to match packets
+ based on the Type Of Service fields of the IPv4 packet (which share
+ the same bits as DSCP).
+
To compile it as a module, choose M here. If unsure, say N.
config NETFILTER_XT_MATCH_ESP
- tristate '"ESP" match support'
+ tristate '"esp" match support'
depends on NETFILTER_XTABLES
+ depends on NETFILTER_ADVANCED
help
This match extension allows you to match a range of SPIs
inside ESP header of IPSec packets.
@@ -502,15 +560,28 @@ config NETFILTER_XT_MATCH_HELPER
tristate '"helper" match support'
depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
+ depends on NETFILTER_ADVANCED
help
Helper matching allows you to match packets in dynamic connections
tracked by a conntrack-helper, ie. ip_conntrack_ftp
To compile it as a module, choose M here. If unsure, say Y.
+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
+ an IP address range. (Normal iptables only matches on single addresses
+ with an optional mask.)
+
+ If unsure, say M.
+
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
specific value or range of values.
@@ -520,6 +591,7 @@ 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
matched: mainly useful in combination with the LOG target ("LOG
@@ -530,6 +602,7 @@ 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
Ethernet address of the packet.
@@ -539,6 +612,7 @@ 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
`nfmark' value in the packet. This can be set by the MARK target
@@ -546,9 +620,19 @@ config NETFILTER_XT_MATCH_MARK
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
+ based on who created the socket: the user or group. It is also
+ possible to check whether a socket actually exists.
+
config NETFILTER_XT_MATCH_POLICY
tristate 'IPsec "policy" match support'
depends on NETFILTER_XTABLES && XFRM
+ default m if NETFILTER_ADVANCED=n
help
Policy matching allows you to match packets based on the
IPsec policy that was used during decapsulation/will
@@ -557,8 +641,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 "Multiple port match support"
+ 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
@@ -569,6 +654,7 @@ config NETFILTER_XT_MATCH_MULTIPORT
config NETFILTER_XT_MATCH_PHYSDEV
tristate '"physdev" match support'
depends on NETFILTER_XTABLES && BRIDGE && BRIDGE_NETFILTER
+ depends on NETFILTER_ADVANCED
help
Physdev packet matching matches against the physical bridge ports
the IP packet arrived on or will leave by.
@@ -578,6 +664,7 @@ 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
its "class", eg. BROADCAST, MULTICAST, ...
@@ -590,6 +677,7 @@ 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
byte counter.
@@ -597,23 +685,36 @@ config NETFILTER_XT_MATCH_QUOTA
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_RATEEST
+ tristate '"rateest" match support'
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_ADVANCED
+ select NETFILTER_XT_TARGET_RATEEST
+ help
+ This option adds a `rateest' match, which allows to match on the
+ rate estimated by the RATEEST target.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_REALM
tristate '"realm" match support'
depends on NETFILTER_XTABLES
+ depends on NETFILTER_ADVANCED
select NET_CLS_ROUTE
help
This option adds a `realm' match, which allows you to use the realm
key from the routing subsystem inside iptables.
-
+
This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
in tc world.
-
+
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_SCTP
tristate '"sctp" protocol match support (EXPERIMENTAL)'
depends on NETFILTER_XTABLES && EXPERIMENTAL
+ depends on NETFILTER_ADVANCED
help
With this option enabled, you will be able to use the
`sctp' match in order to match on SCTP source/destination ports
@@ -626,6 +727,7 @@ config NETFILTER_XT_MATCH_STATE
tristate '"state" match support'
depends on NETFILTER_XTABLES
depends on NF_CONNTRACK
+ default m if NETFILTER_ADVANCED=n
help
Connection state matching allows you to match packets based on their
relationship to a tracked connection (ie. previous packets). This
@@ -636,6 +738,7 @@ 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
on packets periodically or randomly with a given percentage.
@@ -645,6 +748,7 @@ 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
select TEXTSEARCH_BM
@@ -658,6 +762,7 @@ 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
MSS value of TCP SYN packets, which control the maximum packet size
@@ -668,6 +773,7 @@ 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
the packet arrival time (at the machine which netfilter is running)
@@ -682,6 +788,7 @@ 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,
AND them with specified masks, shift them by specified amounts and
@@ -695,6 +802,7 @@ config NETFILTER_XT_MATCH_U32
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.
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index ad0e36ebea3..ea7508387f9 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -4,7 +4,6 @@ nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_exp
nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
obj-$(CONFIG_NETFILTER) = netfilter.o
-obj-$(CONFIG_SYSCTL) += nf_sysctl.o
obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
@@ -46,8 +45,10 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
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_TCPMSS) += xt_TCPMSS.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o
obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
# matches
@@ -61,15 +62,18 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
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_SCTP) += xt_sctp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index bed9ba01e8e..c4065b8f9a9 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -26,10 +26,10 @@
static DEFINE_MUTEX(afinfo_mutex);
-struct nf_afinfo *nf_afinfo[NPROTO] __read_mostly;
+const struct nf_afinfo *nf_afinfo[NPROTO] __read_mostly;
EXPORT_SYMBOL(nf_afinfo);
-int nf_register_afinfo(struct nf_afinfo *afinfo)
+int nf_register_afinfo(const struct nf_afinfo *afinfo)
{
int err;
@@ -42,7 +42,7 @@ int nf_register_afinfo(struct nf_afinfo *afinfo)
}
EXPORT_SYMBOL_GPL(nf_register_afinfo);
-void nf_unregister_afinfo(struct nf_afinfo *afinfo)
+void nf_unregister_afinfo(const struct nf_afinfo *afinfo)
{
mutex_lock(&afinfo_mutex);
rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
@@ -51,28 +51,23 @@ void nf_unregister_afinfo(struct nf_afinfo *afinfo)
}
EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
-/* In this code, we can be waiting indefinitely for userspace to
- * service a packet if a hook returns NF_QUEUE. We could keep a count
- * of skbuffs queued for userspace, and not deregister a hook unless
- * this is zero, but that sucks. Now, we simply check when the
- * packets come back: if the hook is gone, the packet is discarded. */
struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly;
EXPORT_SYMBOL(nf_hooks);
static DEFINE_MUTEX(nf_hook_mutex);
int nf_register_hook(struct nf_hook_ops *reg)
{
- struct list_head *i;
+ struct nf_hook_ops *elem;
int err;
err = mutex_lock_interruptible(&nf_hook_mutex);
if (err < 0)
return err;
- list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
- if (reg->priority < ((struct nf_hook_ops *)i)->priority)
+ list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
+ if (reg->priority < elem->priority)
break;
}
- list_add_rcu(&reg->list, i->prev);
+ list_add_rcu(&reg->list, elem->list.prev);
mutex_unlock(&nf_hook_mutex);
return 0;
}
@@ -183,8 +178,7 @@ next_hook:
} else if (verdict == NF_DROP) {
kfree_skb(skb);
ret = -EPERM;
- } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
- NFDEBUG("nf_hook: Verdict = QUEUE.\n");
+ } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
verdict >> NF_VERDICT_BITS))
goto next_hook;
@@ -217,22 +211,6 @@ int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
}
EXPORT_SYMBOL(skb_make_writable);
-void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
- __be32 from, __be32 to, int pseudohdr)
-{
- __be32 diff[] = { ~from, to };
- if (skb->ip_summed != CHECKSUM_PARTIAL) {
- *sum = csum_fold(csum_partial(diff, sizeof(diff),
- ~csum_unfold(*sum)));
- if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
- skb->csum = ~csum_partial(diff, sizeof(diff),
- ~skb->csum);
- } else if (pseudohdr)
- *sum = ~csum_fold(csum_partial(diff, sizeof(diff),
- csum_unfold(*sum)));
-}
-EXPORT_SYMBOL(nf_proto_csum_replace4);
-
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
/* This does not belong here, but locally generated errors need it if connection
tracking in use: without this, connection may not be in hash table, and hence
@@ -294,3 +272,12 @@ void __init netfilter_init(void)
if (netfilter_log_init() < 0)
panic("cannot initialize nf_log");
}
+
+#ifdef CONFIG_SYSCTL
+struct ctl_path nf_net_netfilter_sysctl_path[] = {
+ { .procname = "net", .ctl_name = CTL_NET, },
+ { .procname = "netfilter", .ctl_name = NET_NETFILTER, },
+ { }
+};
+EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path);
+#endif /* CONFIG_SYSCTL */
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index a4d5cdeb011..078fff0335a 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -81,7 +81,7 @@ static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple,
((__force __u16)tuple->src.u.all << 16) |
(__force __u16)tuple->dst.u.all);
- return jhash_2words(a, b, rnd) % size;
+ return ((u64)jhash_2words(a, b, rnd) * size) >> 32;
}
static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
@@ -831,10 +831,8 @@ EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple)
{
- NLA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(u_int16_t),
- &tuple->src.u.tcp.port);
- NLA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(u_int16_t),
- &tuple->dst.u.tcp.port);
+ NLA_PUT_BE16(skb, CTA_PROTO_SRC_PORT, tuple->src.u.tcp.port);
+ NLA_PUT_BE16(skb, CTA_PROTO_DST_PORT, tuple->dst.u.tcp.port);
return 0;
nla_put_failure:
@@ -854,8 +852,8 @@ int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[],
if (!tb[CTA_PROTO_SRC_PORT] || !tb[CTA_PROTO_DST_PORT])
return -EINVAL;
- t->src.u.tcp.port = *(__be16 *)nla_data(tb[CTA_PROTO_SRC_PORT]);
- t->dst.u.tcp.port = *(__be16 *)nla_data(tb[CTA_PROTO_DST_PORT]);
+ t->src.u.tcp.port = nla_get_be16(tb[CTA_PROTO_SRC_PORT]);
+ t->dst.u.tcp.port = nla_get_be16(tb[CTA_PROTO_DST_PORT]);
return 0;
}
@@ -863,7 +861,7 @@ EXPORT_SYMBOL_GPL(nf_ct_port_nlattr_to_tuple);
#endif
/* Used by ipt_REJECT and ip6t_REJECT. */
-void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
+static void nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
{
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
@@ -880,7 +878,6 @@ void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
nskb->nfctinfo = ctinfo;
nf_conntrack_get(nskb->nfct);
}
-EXPORT_SYMBOL_GPL(__nf_conntrack_attach);
static inline int
do_iter(const struct nf_conntrack_tuple_hash *i,
@@ -1124,7 +1121,7 @@ int __init nf_conntrack_init(void)
goto out_fini_expect;
/* For use by REJECT target */
- rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach);
+ rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
/* Set up fake conntrack:
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 175c8d1a199..e0cd9d00aa6 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -73,15 +73,17 @@ static void nf_ct_expectation_timed_out(unsigned long ul_expect)
static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple)
{
+ unsigned int hash;
+
if (unlikely(!nf_ct_expect_hash_rnd_initted)) {
get_random_bytes(&nf_ct_expect_hash_rnd, 4);
nf_ct_expect_hash_rnd_initted = 1;
}
- return jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all),
+ hash = jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all),
(((tuple->dst.protonum ^ tuple->src.l3num) << 16) |
- (__force __u16)tuple->dst.u.all) ^ nf_ct_expect_hash_rnd) %
- nf_ct_expect_hsize;
+ (__force __u16)tuple->dst.u.all) ^ nf_ct_expect_hash_rnd);
+ return ((u64)hash * nf_ct_expect_hsize) >> 32;
}
struct nf_conntrack_expect *
@@ -226,8 +228,8 @@ 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, int family,
- union nf_conntrack_address *saddr,
- union nf_conntrack_address *daddr,
+ union nf_inet_addr *saddr,
+ union nf_inet_addr *daddr,
u_int8_t proto, __be16 *src, __be16 *dst)
{
int len;
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 6df259067f7..6770baf2e84 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -358,7 +358,7 @@ static int help(struct sk_buff *skb,
unsigned int matchlen, matchoff;
struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
struct nf_conntrack_expect *exp;
- union nf_conntrack_address *daddr;
+ union nf_inet_addr *daddr;
struct nf_conntrack_man cmd = {};
unsigned int i;
int found = 0, ends_in_nl;
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
index a869403b229..ff66fba514f 100644
--- a/net/netfilter/nf_conntrack_h323_asn1.c
+++ b/net/netfilter/nf_conntrack_h323_asn1.c
@@ -100,10 +100,10 @@ typedef struct {
} bitstr_t;
/* Tool Functions */
-#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;}
-#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;}
-#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;}
-#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND)
+#define INC_BIT(bs) if((++(bs)->bit)>7){(bs)->cur++;(bs)->bit=0;}
+#define INC_BITS(bs,b) if(((bs)->bit+=(b))>7){(bs)->cur+=(bs)->bit>>3;(bs)->bit&=7;}
+#define BYTE_ALIGN(bs) if((bs)->bit){(bs)->cur++;(bs)->bit=0;}
+#define CHECK_BOUND(bs,n) if((bs)->cur+(n)>(bs)->end)return(H323_ERROR_BOUND)
static unsigned get_len(bitstr_t * bs);
static unsigned get_bit(bitstr_t * bs);
static unsigned get_bits(bitstr_t * bs, unsigned b);
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index f23fd9598e1..872c1aa3124 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -50,12 +50,12 @@ MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
int (*set_h245_addr_hook) (struct sk_buff *skb,
unsigned char **data, int dataoff,
H245_TransportAddress *taddr,
- union nf_conntrack_address *addr, __be16 port)
+ union nf_inet_addr *addr, __be16 port)
__read_mostly;
int (*set_h225_addr_hook) (struct sk_buff *skb,
unsigned char **data, int dataoff,
TransportAddress *taddr,
- union nf_conntrack_address *addr, __be16 port)
+ union nf_inet_addr *addr, __be16 port)
__read_mostly;
int (*set_sig_addr_hook) (struct sk_buff *skb,
struct nf_conn *ct,
@@ -214,7 +214,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
/****************************************************************************/
static int get_h245_addr(struct nf_conn *ct, unsigned char *data,
H245_TransportAddress *taddr,
- union nf_conntrack_address *addr, __be16 *port)
+ union nf_inet_addr *addr, __be16 *port)
{
unsigned char *p;
int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
@@ -257,7 +257,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
int ret = 0;
__be16 port;
__be16 rtp_port, rtcp_port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
struct nf_conntrack_expect *rtp_exp;
struct nf_conntrack_expect *rtcp_exp;
typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
@@ -330,7 +330,7 @@ static int expect_t120(struct sk_buff *skb,
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
struct nf_conntrack_expect *exp;
typeof(nat_t120_hook) nat_t120;
@@ -623,7 +623,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
/****************************************************************************/
int get_h225_addr(struct nf_conn *ct, unsigned char *data,
TransportAddress *taddr,
- union nf_conntrack_address *addr, __be16 *port)
+ union nf_inet_addr *addr, __be16 *port)
{
unsigned char *p;
int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
@@ -662,7 +662,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
struct nf_conntrack_expect *exp;
typeof(nat_h245_hook) nat_h245;
@@ -704,13 +704,19 @@ 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(union nf_conntrack_address *src,
- union nf_conntrack_address *dst,
+static int callforward_do_filter(union nf_inet_addr *src,
+ union nf_inet_addr *dst,
int family)
{
+ const struct nf_afinfo *afinfo;
struct flowi fl1, fl2;
int ret = 0;
+ /* rcu_read_lock()ed by nf_hook_slow() */
+ afinfo = nf_get_afinfo(family);
+ if (!afinfo)
+ return 0;
+
memset(&fl1, 0, sizeof(fl1));
memset(&fl2, 0, sizeof(fl2));
@@ -720,8 +726,8 @@ static int callforward_do_filter(union nf_conntrack_address *src,
fl1.fl4_dst = src->ip;
fl2.fl4_dst = dst->ip;
- if (ip_route_output_key(&rt1, &fl1) == 0) {
- if (ip_route_output_key(&rt2, &fl2) == 0) {
+ if (!afinfo->route((struct dst_entry **)&rt1, &fl1)) {
+ if (!afinfo->route((struct dst_entry **)&rt2, &fl2)) {
if (rt1->rt_gateway == rt2->rt_gateway &&
rt1->u.dst.dev == rt2->u.dst.dev)
ret = 1;
@@ -731,16 +737,15 @@ static int callforward_do_filter(union nf_conntrack_address *src,
}
break;
}
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if defined(CONFIG_NF_CONNTRACK_IPV6) || \
+ defined(CONFIG_NF_CONNTRACK_IPV6_MODULE)
case AF_INET6: {
struct rt6_info *rt1, *rt2;
memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst));
memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst));
- rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1);
- if (rt1) {
- rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2);
- if (rt2) {
+ if (!afinfo->route((struct dst_entry **)&rt1, &fl1)) {
+ if (!afinfo->route((struct dst_entry **)&rt2, &fl2)) {
if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
sizeof(rt1->rt6i_gateway)) &&
rt1->u.dst.dev == rt2->u.dst.dev)
@@ -767,7 +772,7 @@ static int expect_callforwarding(struct sk_buff *skb,
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
struct nf_conntrack_expect *exp;
typeof(nat_callforwarding_hook) nat_callforwarding;
@@ -823,7 +828,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
int ret;
int i;
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
typeof(set_h225_addr_hook) set_h225_addr;
pr_debug("nf_ct_q931: Setup\n");
@@ -1195,7 +1200,7 @@ static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff,
/****************************************************************************/
static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
- union nf_conntrack_address *addr,
+ union nf_inet_addr *addr,
__be16 port)
{
struct nf_conntrack_expect *exp;
@@ -1237,7 +1242,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
int ret = 0;
int i;
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
struct nf_conntrack_expect *exp;
typeof(nat_q931_hook) nat_q931;
@@ -1306,7 +1311,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
struct nf_conntrack_expect *exp;
pr_debug("nf_ct_ras: GCF\n");
@@ -1466,7 +1471,7 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
int dir = CTINFO2DIR(ctinfo);
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
typeof(set_h225_addr_hook) set_h225_addr;
pr_debug("nf_ct_ras: ARQ\n");
@@ -1508,7 +1513,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
struct nf_conntrack_expect *exp;
typeof(set_sig_addr_hook) set_sig_addr;
@@ -1571,7 +1576,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
__be16 port;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
struct nf_conntrack_expect *exp;
pr_debug("nf_ct_ras: LCF\n");
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 991c52c9a28..8e914e5ffea 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -55,12 +55,6 @@ static int generic_print_tuple(struct seq_file *s,
return 0;
}
-static int generic_print_conntrack(struct seq_file *s,
- const struct nf_conn *conntrack)
-{
- return 0;
-}
-
static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
unsigned int *dataoff, u_int8_t *protonum)
{
@@ -75,7 +69,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_generic __read_mostly = {
.pkt_to_tuple = generic_pkt_to_tuple,
.invert_tuple = generic_invert_tuple,
.print_tuple = generic_print_tuple,
- .print_conntrack = generic_print_conntrack,
.get_l4proto = generic_get_l4proto,
};
EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 7d231243754..38141f104db 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -59,7 +59,7 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb,
nest_parms = nla_nest_start(skb, CTA_TUPLE_PROTO | NLA_F_NESTED);
if (!nest_parms)
goto nla_put_failure;
- NLA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
+ NLA_PUT_U8(skb, CTA_PROTO_NUM, tuple->dst.protonum);
if (likely(l4proto->tuple_to_nlattr))
ret = l4proto->tuple_to_nlattr(skb, tuple);
@@ -95,7 +95,7 @@ nla_put_failure:
return -1;
}
-static inline int
+static int
ctnetlink_dump_tuples(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple)
{
@@ -120,8 +120,7 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
static inline int
ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
{
- __be32 status = htonl((u_int32_t) ct->status);
- NLA_PUT(skb, CTA_STATUS, sizeof(status), &status);
+ NLA_PUT_BE32(skb, CTA_STATUS, htonl(ct->status));
return 0;
nla_put_failure:
@@ -131,15 +130,12 @@ nla_put_failure:
static inline int
ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct)
{
- long timeout_l = ct->timeout.expires - jiffies;
- __be32 timeout;
+ long timeout = (ct->timeout.expires - jiffies) / HZ;
- if (timeout_l < 0)
+ if (timeout < 0)
timeout = 0;
- else
- timeout = htonl(timeout_l / HZ);
- NLA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
+ NLA_PUT_BE32(skb, CTA_TIMEOUT, htonl(timeout));
return 0;
nla_put_failure:
@@ -193,7 +189,7 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
nest_helper = nla_nest_start(skb, CTA_HELP | NLA_F_NESTED);
if (!nest_helper)
goto nla_put_failure;
- NLA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);
+ NLA_PUT_STRING(skb, CTA_HELP_NAME, helper->name);
if (helper->to_nlattr)
helper->to_nlattr(skb, ct);
@@ -209,23 +205,21 @@ nla_put_failure:
}
#ifdef CONFIG_NF_CT_ACCT
-static inline int
+static int
ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
enum ip_conntrack_dir dir)
{
enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
struct nlattr *nest_count;
- __be32 tmp;
nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
if (!nest_count)
goto nla_put_failure;
- tmp = htonl(ct->counters[dir].packets);
- NLA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
-
- tmp = htonl(ct->counters[dir].bytes);
- NLA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
+ NLA_PUT_BE32(skb, CTA_COUNTERS32_PACKETS,
+ htonl(ct->counters[dir].packets));
+ NLA_PUT_BE32(skb, CTA_COUNTERS32_BYTES,
+ htonl(ct->counters[dir].bytes));
nla_nest_end(skb, nest_count);
@@ -242,9 +236,7 @@ nla_put_failure:
static inline int
ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
{
- __be32 mark = htonl(ct->mark);
-
- NLA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
+ NLA_PUT_BE32(skb, CTA_MARK, htonl(ct->mark));
return 0;
nla_put_failure:
@@ -254,11 +246,95 @@ nla_put_failure:
#define ctnetlink_dump_mark(a, b) (0)
#endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static inline int
+ctnetlink_dump_secmark(struct sk_buff *skb, const struct nf_conn *ct)
+{
+ NLA_PUT_BE32(skb, CTA_SECMARK, htonl(ct->secmark));
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+#else
+#define ctnetlink_dump_secmark(a, b) (0)
+#endif
+
+#define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple)
+
+static inline int
+ctnetlink_dump_master(struct sk_buff *skb, const struct nf_conn *ct)
+{
+ struct nlattr *nest_parms;
+
+ if (!(ct->status & IPS_EXPECTED))
+ return 0;
+
+ nest_parms = nla_nest_start(skb, CTA_TUPLE_MASTER | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
+ if (ctnetlink_dump_tuples(skb, master_tuple(ct)) < 0)
+ goto nla_put_failure;
+ nla_nest_end(skb, nest_parms);
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+#ifdef CONFIG_NF_NAT_NEEDED
+static int
+dump_nat_seq_adj(struct sk_buff *skb, const struct nf_nat_seq *natseq, int type)
+{
+ struct nlattr *nest_parms;
+
+ nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
+
+ NLA_PUT_BE32(skb, CTA_NAT_SEQ_CORRECTION_POS,
+ htonl(natseq->correction_pos));
+ NLA_PUT_BE32(skb, CTA_NAT_SEQ_OFFSET_BEFORE,
+ htonl(natseq->offset_before));
+ NLA_PUT_BE32(skb, CTA_NAT_SEQ_OFFSET_AFTER,
+ htonl(natseq->offset_after));
+
+ nla_nest_end(skb, nest_parms);
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_nat_seq_adj(struct sk_buff *skb, const struct nf_conn *ct)
+{
+ struct nf_nat_seq *natseq;
+ struct nf_conn_nat *nat = nfct_nat(ct);
+
+ if (!(ct->status & IPS_SEQ_ADJUST) || !nat)
+ return 0;
+
+ natseq = &nat->seq[IP_CT_DIR_ORIGINAL];
+ if (dump_nat_seq_adj(skb, natseq, CTA_NAT_SEQ_ADJ_ORIG) == -1)
+ return -1;
+
+ natseq = &nat->seq[IP_CT_DIR_REPLY];
+ if (dump_nat_seq_adj(skb, natseq, CTA_NAT_SEQ_ADJ_REPLY) == -1)
+ return -1;
+
+ return 0;
+}
+#else
+#define ctnetlink_dump_nat_seq_adj(a, b) (0)
+#endif
+
static inline int
ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
{
- __be32 id = htonl((unsigned long)ct);
- NLA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
+ NLA_PUT_BE32(skb, CTA_ID, htonl((unsigned long)ct));
return 0;
nla_put_failure:
@@ -268,9 +344,7 @@ nla_put_failure:
static inline int
ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
{
- __be32 use = htonl(atomic_read(&ct->ct_general.use));
-
- NLA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
+ NLA_PUT_BE32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use)));
return 0;
nla_put_failure:
@@ -320,8 +394,11 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
ctnetlink_dump_protoinfo(skb, ct) < 0 ||
ctnetlink_dump_helpinfo(skb, ct) < 0 ||
ctnetlink_dump_mark(skb, ct) < 0 ||
+ ctnetlink_dump_secmark(skb, ct) < 0 ||
ctnetlink_dump_id(skb, ct) < 0 ||
- ctnetlink_dump_use(skb, ct) < 0)
+ ctnetlink_dump_use(skb, ct) < 0 ||
+ ctnetlink_dump_master(skb, ct) < 0 ||
+ ctnetlink_dump_nat_seq_adj(skb, ct) < 0)
goto nla_put_failure;
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
@@ -419,11 +496,24 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
&& ctnetlink_dump_mark(skb, ct) < 0)
goto nla_put_failure;
#endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+ if ((events & IPCT_SECMARK || ct->secmark)
+ && ctnetlink_dump_secmark(skb, ct) < 0)
+ goto nla_put_failure;
+#endif
if (events & IPCT_COUNTER_FILLING &&
(ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
goto nla_put_failure;
+
+ if (events & IPCT_RELATED &&
+ ctnetlink_dump_master(skb, ct) < 0)
+ goto nla_put_failure;
+
+ if (events & IPCT_NATSEQADJ &&
+ ctnetlink_dump_nat_seq_adj(skb, ct) < 0)
+ goto nla_put_failure;
}
nlh->nlmsg_len = skb->tail - b;
@@ -444,7 +534,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
return 0;
}
-#define L3PROTO(ct) ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
+#define L3PROTO(ct) (ct)->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
static int
ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
@@ -542,7 +632,7 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr,
if (!tb[CTA_PROTO_NUM])
return -EINVAL;
- tuple->dst.protonum = *(u_int8_t *)nla_data(tb[CTA_PROTO_NUM]);
+ tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]);
l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
@@ -558,7 +648,7 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr,
return ret;
}
-static inline int
+static int
ctnetlink_parse_tuple(struct nlattr *cda[], struct nf_conntrack_tuple *tuple,
enum ctattr_tuple type, u_int8_t l3num)
{
@@ -605,7 +695,7 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr,
struct nf_nat_range *range)
{
struct nlattr *tb[CTA_PROTONAT_MAX+1];
- struct nf_nat_protocol *npt;
+ const struct nf_nat_protocol *npt;
int err;
err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy);
@@ -647,12 +737,12 @@ nfnetlink_parse_nat(struct nlattr *nat,
return err;
if (tb[CTA_NAT_MINIP])
- range->min_ip = *(__be32 *)nla_data(tb[CTA_NAT_MINIP]);
+ range->min_ip = nla_get_be32(tb[CTA_NAT_MINIP]);
if (!tb[CTA_NAT_MAXIP])
range->max_ip = range->min_ip;
else
- range->max_ip = *(__be32 *)nla_data(tb[CTA_NAT_MAXIP]);
+ range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]);
if (range->min_ip)
range->flags |= IP_NAT_RANGE_MAP_IPS;
@@ -722,7 +812,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
ct = nf_ct_tuplehash_to_ctrack(h);
if (cda[CTA_ID]) {
- u_int32_t id = ntohl(*(__be32 *)nla_data(cda[CTA_ID]));
+ u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID]));
if (id != (u32)(unsigned long)ct) {
nf_ct_put(ct);
return -ENOENT;
@@ -798,11 +888,11 @@ out:
return err;
}
-static inline int
+static int
ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
{
unsigned long d;
- unsigned int status = ntohl(*(__be32 *)nla_data(cda[CTA_STATUS]));
+ unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
d = ct->status ^ status;
if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
@@ -828,19 +918,17 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
if (nfnetlink_parse_nat(cda[CTA_NAT_DST], ct,
&range) < 0)
return -EINVAL;
- if (nf_nat_initialized(ct,
- HOOK2MANIP(NF_IP_PRE_ROUTING)))
+ if (nf_nat_initialized(ct, IP_NAT_MANIP_DST))
return -EEXIST;
- nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
}
if (cda[CTA_NAT_SRC]) {
if (nfnetlink_parse_nat(cda[CTA_NAT_SRC], ct,
&range) < 0)
return -EINVAL;
- if (nf_nat_initialized(ct,
- HOOK2MANIP(NF_IP_POST_ROUTING)))
+ if (nf_nat_initialized(ct, IP_NAT_MANIP_SRC))
return -EEXIST;
- nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
}
#endif
}
@@ -904,7 +992,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[])
static inline int
ctnetlink_change_timeout(struct nf_conn *ct, struct nlattr *cda[])
{
- u_int32_t timeout = ntohl(*(__be32 *)nla_data(cda[CTA_TIMEOUT]));
+ u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
if (!del_timer(&ct->timeout))
return -ETIME;
@@ -935,6 +1023,66 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[])
return err;
}
+#ifdef CONFIG_NF_NAT_NEEDED
+static inline int
+change_nat_seq_adj(struct nf_nat_seq *natseq, struct nlattr *attr)
+{
+ struct nlattr *cda[CTA_NAT_SEQ_MAX+1];
+
+ nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, NULL);
+
+ if (!cda[CTA_NAT_SEQ_CORRECTION_POS])
+ return -EINVAL;
+
+ natseq->correction_pos =
+ ntohl(nla_get_be32(cda[CTA_NAT_SEQ_CORRECTION_POS]));
+
+ if (!cda[CTA_NAT_SEQ_OFFSET_BEFORE])
+ return -EINVAL;
+
+ natseq->offset_before =
+ ntohl(nla_get_be32(cda[CTA_NAT_SEQ_OFFSET_BEFORE]));
+
+ if (!cda[CTA_NAT_SEQ_OFFSET_AFTER])
+ return -EINVAL;
+
+ natseq->offset_after =
+ ntohl(nla_get_be32(cda[CTA_NAT_SEQ_OFFSET_AFTER]));
+
+ return 0;
+}
+
+static int
+ctnetlink_change_nat_seq_adj(struct nf_conn *ct, struct nlattr *cda[])
+{
+ int ret = 0;
+ struct nf_conn_nat *nat = nfct_nat(ct);
+
+ if (!nat)
+ return 0;
+
+ if (cda[CTA_NAT_SEQ_ADJ_ORIG]) {
+ ret = change_nat_seq_adj(&nat->seq[IP_CT_DIR_ORIGINAL],
+ cda[CTA_NAT_SEQ_ADJ_ORIG]);
+ if (ret < 0)
+ return ret;
+
+ ct->status |= IPS_SEQ_ADJUST;
+ }
+
+ if (cda[CTA_NAT_SEQ_ADJ_REPLY]) {
+ ret = change_nat_seq_adj(&nat->seq[IP_CT_DIR_REPLY],
+ cda[CTA_NAT_SEQ_ADJ_REPLY]);
+ if (ret < 0)
+ return ret;
+
+ ct->status |= IPS_SEQ_ADJUST;
+ }
+
+ return 0;
+}
+#endif
+
static int
ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[])
{
@@ -966,7 +1114,15 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[])
#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK])
- ct->mark = ntohl(*(__be32 *)nla_data(cda[CTA_MARK]));
+ ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
+#endif
+
+#ifdef CONFIG_NF_NAT_NEEDED
+ if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) {
+ err = ctnetlink_change_nat_seq_adj(ct, cda);
+ if (err < 0)
+ return err;
+ }
#endif
return 0;
@@ -989,7 +1145,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
if (!cda[CTA_TIMEOUT])
goto err;
- ct->timeout.expires = ntohl(*(__be32 *)nla_data(cda[CTA_TIMEOUT]));
+ ct->timeout.expires = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
ct->status |= IPS_CONFIRMED;
@@ -1008,7 +1164,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK])
- ct->mark = ntohl(*(__be32 *)nla_data(cda[CTA_MARK]));
+ ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
#endif
helper = nf_ct_helper_find_get(rtuple);
@@ -1193,13 +1349,15 @@ nla_put_failure:
return -1;
}
-static inline int
+static int
ctnetlink_exp_dump_expect(struct sk_buff *skb,
const struct nf_conntrack_expect *exp)
{
struct nf_conn *master = exp->master;
- __be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
- __be32 id = htonl((unsigned long)exp);
+ long timeout = (exp->timeout.expires - jiffies) / HZ;
+
+ if (timeout < 0)
+ timeout = 0;
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
goto nla_put_failure;
@@ -1210,8 +1368,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
CTA_EXPECT_MASTER) < 0)
goto nla_put_failure;
- NLA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
- NLA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
+ NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout));
+ NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp));
return 0;
@@ -1384,7 +1542,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
return -ENOENT;
if (cda[CTA_EXPECT_ID]) {
- __be32 id = *(__be32 *)nla_data(cda[CTA_EXPECT_ID]);
+ __be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
if (ntohl(id) != (u32)(unsigned long)exp) {
nf_ct_expect_put(exp);
return -ENOENT;
@@ -1438,7 +1596,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return -ENOENT;
if (cda[CTA_EXPECT_ID]) {
- __be32 id = *(__be32 *)nla_data(cda[CTA_EXPECT_ID]);
+ __be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
if (ntohl(id) != (u32)(unsigned long)exp) {
nf_ct_expect_put(exp);
return -ENOENT;
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 6d947068c58..8595b5946ac 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -36,11 +36,11 @@ static DEFINE_MUTEX(nf_ct_proto_mutex);
#ifdef CONFIG_SYSCTL
static int
-nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_table *path,
+nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_path *path,
struct ctl_table *table, unsigned int *users)
{
if (*header == NULL) {
- *header = nf_register_sysctl_table(path, table);
+ *header = register_sysctl_paths(path, table);
if (*header == NULL)
return -ENOMEM;
}
@@ -55,7 +55,8 @@ nf_ct_unregister_sysctl(struct ctl_table_header **header,
{
if (users != NULL && --*users > 0)
return;
- nf_unregister_sysctl_table(*header, table);
+
+ unregister_sysctl_table(*header);
*header = NULL;
}
#endif
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 13f81917964..22c5dcb6306 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -40,13 +40,6 @@ static int generic_print_tuple(struct seq_file *s,
return 0;
}
-/* Print out the private part of the conntrack. */
-static int generic_print_conntrack(struct seq_file *s,
- const struct nf_conn *state)
-{
- return 0;
-}
-
/* Returns verdict for packet, or -1 for invalid. */
static int packet(struct nf_conn *conntrack,
const struct sk_buff *skb,
@@ -104,7 +97,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
.pkt_to_tuple = generic_pkt_to_tuple,
.invert_tuple = generic_invert_tuple,
.print_tuple = generic_print_tuple,
- .print_conntrack = generic_print_conntrack,
.packet = packet,
.new = new,
#ifdef CONFIG_SYSCTL
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index cb046751059..21d29e782ba 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -49,24 +49,15 @@ static const char *sctp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-static unsigned int nf_ct_sctp_timeout_closed __read_mostly = 10 SECS;
-static unsigned int nf_ct_sctp_timeout_cookie_wait __read_mostly = 3 SECS;
-static unsigned int nf_ct_sctp_timeout_cookie_echoed __read_mostly = 3 SECS;
-static unsigned int nf_ct_sctp_timeout_established __read_mostly = 5 DAYS;
-static unsigned int nf_ct_sctp_timeout_shutdown_sent __read_mostly = 300 SECS / 1000;
-static unsigned int nf_ct_sctp_timeout_shutdown_recd __read_mostly = 300 SECS / 1000;
-static unsigned int nf_ct_sctp_timeout_shutdown_ack_sent __read_mostly = 3 SECS;
-
-static unsigned int * sctp_timeouts[]
-= { NULL, /* SCTP_CONNTRACK_NONE */
- &nf_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
- &nf_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
- &nf_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
- &nf_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
- &nf_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
- &nf_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
- &nf_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
- };
+static unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] __read_mostly = {
+ [SCTP_CONNTRACK_CLOSED] = 10 SECS,
+ [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS,
+ [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS,
+ [SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS,
+ [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000,
+ [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000,
+ [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS,
+};
#define sNO SCTP_CONNTRACK_NONE
#define sCL SCTP_CONNTRACK_CLOSED
@@ -110,7 +101,7 @@ cookie echoed to closed.
*/
/* SCTP conntrack state transitions */
-static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
+static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
{
/* ORIGINAL */
/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
@@ -173,29 +164,28 @@ static int sctp_print_tuple(struct seq_file *s,
}
/* Print out the private part of the conntrack. */
-static int sctp_print_conntrack(struct seq_file *s,
- const struct nf_conn *conntrack)
+static int sctp_print_conntrack(struct seq_file *s, const struct nf_conn *ct)
{
enum sctp_conntrack state;
read_lock_bh(&sctp_lock);
- state = conntrack->proto.sctp.state;
+ state = ct->proto.sctp.state;
read_unlock_bh(&sctp_lock);
return seq_printf(s, "%s ", sctp_conntrack_names[state]);
}
#define for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) \
-for (offset = dataoff + sizeof(sctp_sctphdr_t), count = 0; \
- offset < skb->len && \
- (sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch)); \
- offset += (ntohs(sch->length) + 3) & ~3, count++)
+for ((offset) = (dataoff) + sizeof(sctp_sctphdr_t), (count) = 0; \
+ (offset) < (skb)->len && \
+ ((sch) = skb_header_pointer((skb), (offset), sizeof(_sch), &(_sch))); \
+ (offset) += (ntohs((sch)->length) + 3) & ~3, (count)++)
/* Some validity checks to make sure the chunks are fine */
-static int do_basic_checks(struct nf_conn *conntrack,
+static int do_basic_checks(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
- char *map)
+ unsigned long *map)
{
u_int32_t offset, count;
sctp_chunkhdr_t _sch, *sch;
@@ -206,76 +196,83 @@ static int do_basic_checks(struct nf_conn *conntrack,
for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
pr_debug("Chunk Num: %d Type: %d\n", count, sch->type);
- if (sch->type == SCTP_CID_INIT
- || sch->type == SCTP_CID_INIT_ACK
- || sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
+ if (sch->type == SCTP_CID_INIT ||
+ sch->type == SCTP_CID_INIT_ACK ||
+ sch->type == SCTP_CID_SHUTDOWN_COMPLETE)
flag = 1;
- }
/*
* Cookie Ack/Echo chunks not the first OR
* Init / Init Ack / Shutdown compl chunks not the only chunks
* OR zero-length.
*/
- if (((sch->type == SCTP_CID_COOKIE_ACK
- || sch->type == SCTP_CID_COOKIE_ECHO
- || flag)
- && count !=0) || !sch->length) {
+ if (((sch->type == SCTP_CID_COOKIE_ACK ||
+ sch->type == SCTP_CID_COOKIE_ECHO ||
+ flag) &&
+ count != 0) || !sch->length) {
pr_debug("Basic checks failed\n");
return 1;
}
- if (map) {
- set_bit(sch->type, (void *)map);
- }
+ if (map)
+ set_bit(sch->type, map);
}
pr_debug("Basic checks passed\n");
return count == 0;
}
-static int new_state(enum ip_conntrack_dir dir,
- enum sctp_conntrack cur_state,
- int chunk_type)
+static int sctp_new_state(enum ip_conntrack_dir dir,
+ enum sctp_conntrack cur_state,
+ int chunk_type)
{
int i;
pr_debug("Chunk type: %d\n", chunk_type);
switch (chunk_type) {
- case SCTP_CID_INIT:
- pr_debug("SCTP_CID_INIT\n");
- i = 0; break;
- case SCTP_CID_INIT_ACK:
- pr_debug("SCTP_CID_INIT_ACK\n");
- i = 1; break;
- case SCTP_CID_ABORT:
- pr_debug("SCTP_CID_ABORT\n");
- i = 2; break;
- case SCTP_CID_SHUTDOWN:
- pr_debug("SCTP_CID_SHUTDOWN\n");
- i = 3; break;
- case SCTP_CID_SHUTDOWN_ACK:
- pr_debug("SCTP_CID_SHUTDOWN_ACK\n");
- i = 4; break;
- case SCTP_CID_ERROR:
- pr_debug("SCTP_CID_ERROR\n");
- i = 5; break;
- case SCTP_CID_COOKIE_ECHO:
- pr_debug("SCTP_CID_COOKIE_ECHO\n");
- i = 6; break;
- case SCTP_CID_COOKIE_ACK:
- pr_debug("SCTP_CID_COOKIE_ACK\n");
- i = 7; break;
- case SCTP_CID_SHUTDOWN_COMPLETE:
- pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n");
- i = 8; break;
- default:
- /* Other chunks like DATA, SACK, HEARTBEAT and
- its ACK do not cause a change in state */
- pr_debug("Unknown chunk type, Will stay in %s\n",
- sctp_conntrack_names[cur_state]);
- return cur_state;
+ case SCTP_CID_INIT:
+ pr_debug("SCTP_CID_INIT\n");
+ i = 0;
+ break;
+ case SCTP_CID_INIT_ACK:
+ pr_debug("SCTP_CID_INIT_ACK\n");
+ i = 1;
+ break;
+ case SCTP_CID_ABORT:
+ pr_debug("SCTP_CID_ABORT\n");
+ i = 2;
+ break;
+ case SCTP_CID_SHUTDOWN:
+ pr_debug("SCTP_CID_SHUTDOWN\n");
+ i = 3;
+ break;
+ case SCTP_CID_SHUTDOWN_ACK:
+ pr_debug("SCTP_CID_SHUTDOWN_ACK\n");
+ i = 4;
+ break;
+ case SCTP_CID_ERROR:
+ pr_debug("SCTP_CID_ERROR\n");
+ i = 5;
+ break;
+ case SCTP_CID_COOKIE_ECHO:
+ pr_debug("SCTP_CID_COOKIE_ECHO\n");
+ i = 6;
+ break;
+ case SCTP_CID_COOKIE_ACK:
+ pr_debug("SCTP_CID_COOKIE_ACK\n");
+ i = 7;
+ break;
+ case SCTP_CID_SHUTDOWN_COMPLETE:
+ pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n");
+ i = 8;
+ break;
+ default:
+ /* Other chunks like DATA, SACK, HEARTBEAT and
+ its ACK do not cause a change in state */
+ pr_debug("Unknown chunk type, Will stay in %s\n",
+ sctp_conntrack_names[cur_state]);
+ return cur_state;
}
pr_debug("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
@@ -285,154 +282,145 @@ static int new_state(enum ip_conntrack_dir dir,
return sctp_conntracks[dir][i][cur_state];
}
-/* Returns verdict for packet, or -1 for invalid. */
-static int sctp_packet(struct nf_conn *conntrack,
+/* Returns verdict for packet, or -NF_ACCEPT for invalid. */
+static int sctp_packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
int pf,
unsigned int hooknum)
{
- enum sctp_conntrack newconntrack, oldsctpstate;
+ enum sctp_conntrack new_state, old_state;
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
sctp_sctphdr_t _sctph, *sh;
sctp_chunkhdr_t _sch, *sch;
u_int32_t offset, count;
- char map[256 / sizeof (char)] = {0};
+ unsigned long map[256 / sizeof(unsigned long)] = { 0 };
sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
if (sh == NULL)
- return -1;
+ goto out;
- if (do_basic_checks(conntrack, skb, dataoff, map) != 0)
- return -1;
+ if (do_basic_checks(ct, skb, dataoff, map) != 0)
+ goto out;
/* Check the verification tag (Sec 8.5) */
- if (!test_bit(SCTP_CID_INIT, (void *)map)
- && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
- && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
- && !test_bit(SCTP_CID_ABORT, (void *)map)
- && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
- && (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
+ if (!test_bit(SCTP_CID_INIT, map) &&
+ !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) &&
+ !test_bit(SCTP_CID_COOKIE_ECHO, map) &&
+ !test_bit(SCTP_CID_ABORT, map) &&
+ !test_bit(SCTP_CID_SHUTDOWN_ACK, map) &&
+ sh->vtag != ct->proto.sctp.vtag[dir]) {
pr_debug("Verification tag check failed\n");
- return -1;
+ goto out;
}
- oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
+ old_state = new_state = SCTP_CONNTRACK_MAX;
+ write_lock_bh(&sctp_lock);
for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
- write_lock_bh(&sctp_lock);
-
/* Special cases of Verification tag check (Sec 8.5.1) */
if (sch->type == SCTP_CID_INIT) {
/* Sec 8.5.1 (A) */
- if (sh->vtag != 0) {
- write_unlock_bh(&sctp_lock);
- return -1;
- }
+ if (sh->vtag != 0)
+ goto out_unlock;
} else if (sch->type == SCTP_CID_ABORT) {
/* Sec 8.5.1 (B) */
- if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
- && !(sh->vtag == conntrack->proto.sctp.vtag
- [1 - CTINFO2DIR(ctinfo)])) {
- write_unlock_bh(&sctp_lock);
- return -1;
- }
+ if (sh->vtag != ct->proto.sctp.vtag[dir] &&
+ sh->vtag != ct->proto.sctp.vtag[!dir])
+ goto out_unlock;
} else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
/* Sec 8.5.1 (C) */
- if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
- && !(sh->vtag == conntrack->proto.sctp.vtag
- [1 - CTINFO2DIR(ctinfo)]
- && (sch->flags & 1))) {
- write_unlock_bh(&sctp_lock);
- return -1;
- }
+ if (sh->vtag != ct->proto.sctp.vtag[dir] &&
+ sh->vtag != ct->proto.sctp.vtag[!dir] &&
+ sch->flags & SCTP_CHUNK_FLAG_T)
+ goto out_unlock;
} else if (sch->type == SCTP_CID_COOKIE_ECHO) {
/* Sec 8.5.1 (D) */
- if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
- write_unlock_bh(&sctp_lock);
- return -1;
- }
+ if (sh->vtag != ct->proto.sctp.vtag[dir])
+ goto out_unlock;
}
- oldsctpstate = conntrack->proto.sctp.state;
- newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch->type);
+ old_state = ct->proto.sctp.state;
+ new_state = sctp_new_state(dir, old_state, sch->type);
/* Invalid */
- if (newconntrack == SCTP_CONNTRACK_MAX) {
+ if (new_state == SCTP_CONNTRACK_MAX) {
pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
"conntrack=%u\n",
- CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
- write_unlock_bh(&sctp_lock);
- return -1;
+ dir, sch->type, old_state);
+ goto out_unlock;
}
/* If it is an INIT or an INIT ACK note down the vtag */
- if (sch->type == SCTP_CID_INIT
- || sch->type == SCTP_CID_INIT_ACK) {
+ if (sch->type == SCTP_CID_INIT ||
+ sch->type == SCTP_CID_INIT_ACK) {
sctp_inithdr_t _inithdr, *ih;
ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
sizeof(_inithdr), &_inithdr);
- if (ih == NULL) {
- write_unlock_bh(&sctp_lock);
- return -1;
- }
+ if (ih == NULL)
+ goto out_unlock;
pr_debug("Setting vtag %x for dir %d\n",
- ih->init_tag, !CTINFO2DIR(ctinfo));
- conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
+ ih->init_tag, !dir);
+ ct->proto.sctp.vtag[!dir] = ih->init_tag;
}
- conntrack->proto.sctp.state = newconntrack;
- if (oldsctpstate != newconntrack)
+ ct->proto.sctp.state = new_state;
+ if (old_state != new_state)
nf_conntrack_event_cache(IPCT_PROTOINFO, skb);
- write_unlock_bh(&sctp_lock);
}
+ write_unlock_bh(&sctp_lock);
- nf_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]);
+ nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]);
- if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
- && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
- && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
+ if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
+ dir == IP_CT_DIR_REPLY &&
+ new_state == SCTP_CONNTRACK_ESTABLISHED) {
pr_debug("Setting assured bit\n");
- set_bit(IPS_ASSURED_BIT, &conntrack->status);
+ set_bit(IPS_ASSURED_BIT, &ct->status);
nf_conntrack_event_cache(IPCT_STATUS, skb);
}
return NF_ACCEPT;
+
+out_unlock:
+ write_unlock_bh(&sctp_lock);
+out:
+ return -NF_ACCEPT;
}
/* Called when a new connection for this protocol found. */
-static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
+static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff)
{
- enum sctp_conntrack newconntrack;
+ enum sctp_conntrack new_state;
sctp_sctphdr_t _sctph, *sh;
sctp_chunkhdr_t _sch, *sch;
u_int32_t offset, count;
- char map[256 / sizeof (char)] = {0};
+ unsigned long map[256 / sizeof(unsigned long)] = { 0 };
sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
if (sh == NULL)
return 0;
- if (do_basic_checks(conntrack, skb, dataoff, map) != 0)
+ if (do_basic_checks(ct, skb, dataoff, map) != 0)
return 0;
/* If an OOTB packet has any of these chunks discard (Sec 8.4) */
- if ((test_bit (SCTP_CID_ABORT, (void *)map))
- || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
- || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
+ if (test_bit(SCTP_CID_ABORT, map) ||
+ test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) ||
+ test_bit(SCTP_CID_COOKIE_ACK, map))
return 0;
- }
- newconntrack = SCTP_CONNTRACK_MAX;
+ new_state = SCTP_CONNTRACK_MAX;
for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
/* Don't need lock here: this conntrack not in circulation yet */
- newconntrack = new_state(IP_CT_DIR_ORIGINAL,
- SCTP_CONNTRACK_NONE, sch->type);
+ new_state = sctp_new_state(IP_CT_DIR_ORIGINAL,
+ SCTP_CONNTRACK_NONE, sch->type);
/* Invalid: delete conntrack */
- if (newconntrack == SCTP_CONNTRACK_NONE ||
- newconntrack == SCTP_CONNTRACK_MAX) {
+ if (new_state == SCTP_CONNTRACK_NONE ||
+ new_state == SCTP_CONNTRACK_MAX) {
pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
return 0;
}
@@ -450,7 +438,7 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
pr_debug("Setting vtag %x for new conn\n",
ih->init_tag);
- conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
+ ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
ih->init_tag;
} else {
/* Sec 8.5.1 (A) */
@@ -462,10 +450,10 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
else {
pr_debug("Setting vtag %x for new conn OOTB\n",
sh->vtag);
- conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
+ ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
}
- conntrack->proto.sctp.state = newconntrack;
+ ct->proto.sctp.state = new_state;
}
return 1;
@@ -477,49 +465,49 @@ static struct ctl_table_header *sctp_sysctl_header;
static struct ctl_table sctp_sysctl_table[] = {
{
.procname = "nf_conntrack_sctp_timeout_closed",
- .data = &nf_ct_sctp_timeout_closed,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_cookie_wait",
- .data = &nf_ct_sctp_timeout_cookie_wait,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_cookie_echoed",
- .data = &nf_ct_sctp_timeout_cookie_echoed,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_established",
- .data = &nf_ct_sctp_timeout_established,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_sent",
- .data = &nf_ct_sctp_timeout_shutdown_sent,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_recd",
- .data = &nf_ct_sctp_timeout_shutdown_recd,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
- .data = &nf_ct_sctp_timeout_shutdown_ack_sent,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
@@ -533,49 +521,49 @@ static struct ctl_table sctp_sysctl_table[] = {
static struct ctl_table sctp_compat_sysctl_table[] = {
{
.procname = "ip_conntrack_sctp_timeout_closed",
- .data = &nf_ct_sctp_timeout_closed,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_cookie_wait",
- .data = &nf_ct_sctp_timeout_cookie_wait,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_cookie_echoed",
- .data = &nf_ct_sctp_timeout_cookie_echoed,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_established",
- .data = &nf_ct_sctp_timeout_established,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_shutdown_sent",
- .data = &nf_ct_sctp_timeout_shutdown_sent,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_shutdown_recd",
- .data = &nf_ct_sctp_timeout_shutdown_recd,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
- .data = &nf_ct_sctp_timeout_shutdown_ack_sent,
+ .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
@@ -598,6 +586,11 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
.packet = sctp_packet,
.new = sctp_new,
.me = THIS_MODULE,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
+#endif
#ifdef CONFIG_SYSCTL
.ctl_table_users = &sctp_sysctl_table_users,
.ctl_table_header = &sctp_sysctl_header,
@@ -619,6 +612,11 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
.packet = sctp_packet,
.new = sctp_new,
.me = THIS_MODULE,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
+#endif
#ifdef CONFIG_SYSCTL
.ctl_table_users = &sctp_sysctl_table_users,
.ctl_table_header = &sctp_sysctl_header,
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 7a3f64c1aca..64c9b910419 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -24,6 +24,7 @@
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
+#include <net/netfilter/nf_log.h>
/* Protects conntrack->proto.tcp */
static DEFINE_RWLOCK(tcp_lock);
@@ -63,32 +64,21 @@ static const char *tcp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-static unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS;
-static unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS;
-static unsigned int nf_ct_tcp_timeout_established __read_mostly = 5 DAYS;
-static unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS;
-static unsigned int nf_ct_tcp_timeout_close_wait __read_mostly = 60 SECS;
-static unsigned int nf_ct_tcp_timeout_last_ack __read_mostly = 30 SECS;
-static unsigned int nf_ct_tcp_timeout_time_wait __read_mostly = 2 MINS;
-static unsigned int nf_ct_tcp_timeout_close __read_mostly = 10 SECS;
-
/* RFC1122 says the R2 limit should be at least 100 seconds.
Linux uses 15 packets as limit, which corresponds
to ~13-30min depending on RTO. */
static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS;
-static unsigned int * tcp_timeouts[] = {
- NULL, /* TCP_CONNTRACK_NONE */
- &nf_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */
- &nf_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */
- &nf_ct_tcp_timeout_established, /* TCP_CONNTRACK_ESTABLISHED, */
- &nf_ct_tcp_timeout_fin_wait, /* TCP_CONNTRACK_FIN_WAIT, */
- &nf_ct_tcp_timeout_close_wait, /* TCP_CONNTRACK_CLOSE_WAIT, */
- &nf_ct_tcp_timeout_last_ack, /* TCP_CONNTRACK_LAST_ACK, */
- &nf_ct_tcp_timeout_time_wait, /* TCP_CONNTRACK_TIME_WAIT, */
- &nf_ct_tcp_timeout_close, /* TCP_CONNTRACK_CLOSE, */
- NULL, /* TCP_CONNTRACK_LISTEN */
- };
+static unsigned int tcp_timeouts[TCP_CONNTRACK_MAX] __read_mostly = {
+ [TCP_CONNTRACK_SYN_SENT] = 2 MINS,
+ [TCP_CONNTRACK_SYN_RECV] = 60 SECS,
+ [TCP_CONNTRACK_ESTABLISHED] = 5 DAYS,
+ [TCP_CONNTRACK_FIN_WAIT] = 2 MINS,
+ [TCP_CONNTRACK_CLOSE_WAIT] = 60 SECS,
+ [TCP_CONNTRACK_LAST_ACK] = 30 SECS,
+ [TCP_CONNTRACK_TIME_WAIT] = 2 MINS,
+ [TCP_CONNTRACK_CLOSE] = 10 SECS,
+};
#define sNO TCP_CONNTRACK_NONE
#define sSS TCP_CONNTRACK_SYN_SENT
@@ -148,7 +138,7 @@ enum tcp_bit_set {
* if they are invalid
* or we do not support the request (simultaneous open)
*/
-static enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
+static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
{
/* ORIGINAL */
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
@@ -783,9 +773,7 @@ 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 &&
- ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
- (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
+ if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -942,8 +930,8 @@ static int tcp_packet(struct nf_conn *conntrack,
|| new_state == TCP_CONNTRACK_CLOSE))
conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
timeout = conntrack->proto.tcp.retrans >= nf_ct_tcp_max_retrans
- && *tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans
- ? nf_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
+ && tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans
+ ? nf_ct_tcp_timeout_max_retrans : tcp_timeouts[new_state];
write_unlock_bh(&tcp_lock);
nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
@@ -1074,14 +1062,13 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
if (!nest_parms)
goto nla_put_failure;
- NLA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
- &ct->proto.tcp.state);
+ NLA_PUT_U8(skb, CTA_PROTOINFO_TCP_STATE, ct->proto.tcp.state);
- NLA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, sizeof(u_int8_t),
- &ct->proto.tcp.seen[0].td_scale);
+ NLA_PUT_U8(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
+ ct->proto.tcp.seen[0].td_scale);
- NLA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY, sizeof(u_int8_t),
- &ct->proto.tcp.seen[1].td_scale);
+ NLA_PUT_U8(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY,
+ ct->proto.tcp.seen[1].td_scale);
tmp.flags = ct->proto.tcp.seen[0].flags;
NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
@@ -1128,8 +1115,7 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
return -EINVAL;
write_lock_bh(&tcp_lock);
- ct->proto.tcp.state =
- *(u_int8_t *)nla_data(tb[CTA_PROTOINFO_TCP_STATE]);
+ ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]) {
struct nf_ct_tcp_flags *attr =
@@ -1149,10 +1135,10 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
tb[CTA_PROTOINFO_TCP_WSCALE_REPLY] &&
ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_WINDOW_SCALE &&
ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_WINDOW_SCALE) {
- ct->proto.tcp.seen[0].td_scale = *(u_int8_t *)
- nla_data(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]);
- ct->proto.tcp.seen[1].td_scale = *(u_int8_t *)
- nla_data(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]);
+ ct->proto.tcp.seen[0].td_scale =
+ nla_get_u8(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]);
+ ct->proto.tcp.seen[1].td_scale =
+ nla_get_u8(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]);
}
write_unlock_bh(&tcp_lock);
@@ -1166,56 +1152,56 @@ static struct ctl_table_header *tcp_sysctl_header;
static struct ctl_table tcp_sysctl_table[] = {
{
.procname = "nf_conntrack_tcp_timeout_syn_sent",
- .data = &nf_ct_tcp_timeout_syn_sent,
+ .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_syn_recv",
- .data = &nf_ct_tcp_timeout_syn_recv,
+ .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_established",
- .data = &nf_ct_tcp_timeout_established,
+ .data = &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_fin_wait",
- .data = &nf_ct_tcp_timeout_fin_wait,
+ .data = &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_close_wait",
- .data = &nf_ct_tcp_timeout_close_wait,
+ .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_last_ack",
- .data = &nf_ct_tcp_timeout_last_ack,
+ .data = &tcp_timeouts[TCP_CONNTRACK_LAST_ACK],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_time_wait",
- .data = &nf_ct_tcp_timeout_time_wait,
+ .data = &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_close",
- .data = &nf_ct_tcp_timeout_close,
+ .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
@@ -1260,56 +1246,56 @@ static struct ctl_table tcp_sysctl_table[] = {
static struct ctl_table tcp_compat_sysctl_table[] = {
{
.procname = "ip_conntrack_tcp_timeout_syn_sent",
- .data = &nf_ct_tcp_timeout_syn_sent,
+ .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_syn_recv",
- .data = &nf_ct_tcp_timeout_syn_recv,
+ .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_established",
- .data = &nf_ct_tcp_timeout_established,
+ .data = &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_fin_wait",
- .data = &nf_ct_tcp_timeout_fin_wait,
+ .data = &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_close_wait",
- .data = &nf_ct_tcp_timeout_close_wait,
+ .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_last_ack",
- .data = &nf_ct_tcp_timeout_last_ack,
+ .data = &tcp_timeouts[TCP_CONNTRACK_LAST_ACK],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_time_wait",
- .data = &nf_ct_tcp_timeout_time_wait,
+ .data = &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_close",
- .data = &nf_ct_tcp_timeout_close,
+ .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index b3e7ecb080e..38487541108 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -21,6 +21,7 @@
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
+#include <net/netfilter/nf_log.h>
static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
@@ -59,13 +60,6 @@ static int udp_print_tuple(struct seq_file *s,
ntohs(tuple->dst.u.udp.port));
}
-/* Print out the private part of the conntrack. */
-static int udp_print_conntrack(struct seq_file *s,
- const struct nf_conn *conntrack)
-{
- return 0;
-}
-
/* Returns verdict for packet, and may modify conntracktype */
static int udp_packet(struct nf_conn *conntrack,
const struct sk_buff *skb,
@@ -128,9 +122,7 @@ 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 &&
- ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
- (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
+ if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -194,7 +186,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
.pkt_to_tuple = udp_pkt_to_tuple,
.invert_tuple = udp_invert_tuple,
.print_tuple = udp_print_tuple,
- .print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
.error = udp_error,
@@ -222,7 +213,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
.pkt_to_tuple = udp_pkt_to_tuple,
.invert_tuple = udp_invert_tuple,
.print_tuple = udp_print_tuple,
- .print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
.error = udp_error,
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index b8981dd922b..070056d9bcd 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -22,6 +22,7 @@
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
+#include <net/netfilter/nf_log.h>
static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
@@ -58,13 +59,6 @@ static int udplite_print_tuple(struct seq_file *s,
ntohs(tuple->dst.u.udp.port));
}
-/* Print out the private part of the conntrack. */
-static int udplite_print_conntrack(struct seq_file *s,
- const struct nf_conn *conntrack)
-{
- return 0;
-}
-
/* Returns verdict for packet, and may modify conntracktype */
static int udplite_packet(struct nf_conn *conntrack,
const struct sk_buff *skb,
@@ -133,8 +127,7 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
/* Checksum invalid? Ignore. */
if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) &&
- ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
- (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))) {
+ hooknum == NF_INET_PRE_ROUTING) {
if (pf == PF_INET) {
struct iphdr *iph = ip_hdr(skb);
@@ -198,7 +191,6 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
.pkt_to_tuple = udplite_pkt_to_tuple,
.invert_tuple = udplite_invert_tuple,
.print_tuple = udplite_print_tuple,
- .print_conntrack = udplite_print_conntrack,
.packet = udplite_packet,
.new = udplite_new,
.error = udplite_error,
@@ -222,7 +214,6 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
.pkt_to_tuple = udplite_pkt_to_tuple,
.invert_tuple = udplite_invert_tuple,
.print_tuple = udplite_print_tuple,
- .print_conntrack = udplite_print_conntrack,
.packet = udplite_packet,
.new = udplite_new,
.error = udplite_error,
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 515abffc4a0..47d8947cf26 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -247,7 +247,7 @@ static int skp_digits_len(struct nf_conn *ct, const char *dptr,
}
static int parse_addr(struct nf_conn *ct, const char *cp, const char **endp,
- union nf_conntrack_address *addr, const char *limit)
+ union nf_inet_addr *addr, const char *limit)
{
const char *end;
int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
@@ -275,7 +275,7 @@ static int parse_addr(struct nf_conn *ct, const char *cp, const char **endp,
static int epaddr_len(struct nf_conn *ct, const char *dptr,
const char *limit, int *shift)
{
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
const char *aux = dptr;
if (!parse_addr(ct, dptr, &dptr, &addr, limit)) {
@@ -366,7 +366,7 @@ EXPORT_SYMBOL_GPL(ct_sip_get_info);
static int set_expected_rtp(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
- union nf_conntrack_address *addr,
+ union nf_inet_addr *addr,
__be16 port,
const char *dptr)
{
@@ -403,7 +403,7 @@ static int sip_help(struct sk_buff *skb,
enum ip_conntrack_info ctinfo)
{
int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
- union nf_conntrack_address addr;
+ union nf_inet_addr addr;
unsigned int dataoff, datalen;
const char *dptr;
int ret = NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 9efdd37fc19..696074a037c 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -142,10 +142,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
? (long)(conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
return -ENOSPC;
- if (l3proto->print_conntrack(s, conntrack))
- return -ENOSPC;
-
- if (l4proto->print_conntrack(s, conntrack))
+ if (l4proto->print_conntrack && l4proto->print_conntrack(s, conntrack))
return -ENOSPC;
if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
@@ -383,15 +380,11 @@ static ctl_table nf_ct_netfilter_table[] = {
{ .ctl_name = 0 }
};
-static ctl_table nf_ct_net_table[] = {
- {
- .ctl_name = CTL_NET,
- .procname = "net",
- .mode = 0555,
- .child = nf_ct_netfilter_table,
- },
- { .ctl_name = 0 }
+struct ctl_path nf_ct_path[] = {
+ { .procname = "net", .ctl_name = CTL_NET, },
+ { }
};
+
EXPORT_SYMBOL_GPL(nf_ct_log_invalid);
#endif /* CONFIG_SYSCTL */
@@ -418,7 +411,8 @@ static int __init nf_conntrack_standalone_init(void)
proc_stat->owner = THIS_MODULE;
#endif
#ifdef CONFIG_SYSCTL
- nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table);
+ nf_ct_sysctl_header = register_sysctl_paths(nf_ct_path,
+ nf_ct_netfilter_table);
if (nf_ct_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index d67c4fbf603..4f5f2885fca 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -6,6 +6,7 @@
#include <linux/netfilter.h>
#include <linux/seq_file.h>
#include <net/protocol.h>
+#include <net/netfilter/nf_log.h>
#include "nf_internals.h"
@@ -14,12 +15,12 @@
#define NF_LOG_PREFIXLEN 128
-static struct nf_logger *nf_loggers[NPROTO];
+static const struct nf_logger *nf_loggers[NPROTO] __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, struct nf_logger *logger)
+int nf_log_register(int pf, const struct nf_logger *logger)
{
int ret;
@@ -57,7 +58,7 @@ void nf_log_unregister_pf(int pf)
}
EXPORT_SYMBOL(nf_log_unregister_pf);
-void nf_log_unregister(struct nf_logger *logger)
+void nf_log_unregister(const struct nf_logger *logger)
{
int i;
@@ -77,12 +78,12 @@ void nf_log_packet(int pf,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
- struct nf_loginfo *loginfo,
+ const struct nf_loginfo *loginfo,
const char *fmt, ...)
{
va_list args;
char prefix[NF_LOG_PREFIXLEN];
- struct nf_logger *logger;
+ const struct nf_logger *logger;
rcu_read_lock();
logger = rcu_dereference(nf_loggers[pf]);
@@ -90,7 +91,6 @@ void nf_log_packet(int pf,
va_start(args, fmt);
vsnprintf(prefix, sizeof(prefix), fmt, args);
va_end(args);
- /* We must read logging before nf_logfn[pf] */
logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
} else if (net_ratelimit()) {
printk(KERN_WARNING "nf_log_packet: can\'t log since "
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 0cef1433d66..bfc2928c191 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -7,6 +7,7 @@
#include <linux/seq_file.h>
#include <linux/rcupdate.h>
#include <net/protocol.h>
+#include <net/netfilter/nf_queue.h>
#include "nf_internals.h"
@@ -15,13 +16,13 @@
* 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 struct nf_queue_handler *queue_handler[NPROTO];
+static const struct nf_queue_handler *queue_handler[NPROTO];
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, struct nf_queue_handler *qh)
+int nf_register_queue_handler(int pf, const struct nf_queue_handler *qh)
{
int ret;
@@ -44,7 +45,7 @@ int nf_register_queue_handler(int pf, 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, struct nf_queue_handler *qh)
+int nf_unregister_queue_handler(int pf, const struct nf_queue_handler *qh)
{
if (pf >= NPROTO)
return -EINVAL;
@@ -64,7 +65,7 @@ int nf_unregister_queue_handler(int pf, struct nf_queue_handler *qh)
}
EXPORT_SYMBOL(nf_unregister_queue_handler);
-void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
+void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
{
int pf;
@@ -79,6 +80,27 @@ void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
}
EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
+static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
+{
+ /* Release those devices we held, or Alexey will kill me. */
+ if (entry->indev)
+ dev_put(entry->indev);
+ if (entry->outdev)
+ dev_put(entry->outdev);
+#ifdef CONFIG_BRIDGE_NETFILTER
+ if (entry->skb->nf_bridge) {
+ struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
+
+ if (nf_bridge->physindev)
+ dev_put(nf_bridge->physindev);
+ if (nf_bridge->physoutdev)
+ dev_put(nf_bridge->physoutdev);
+ }
+#endif
+ /* Drop reference to owner of hook which queued us. */
+ module_put(entry->elem->owner);
+}
+
/*
* Any packet that leaves via this function must come back
* through nf_reinject().
@@ -92,84 +114,79 @@ static int __nf_queue(struct sk_buff *skb,
unsigned int queuenum)
{
int status;
- struct nf_info *info;
+ struct nf_queue_entry *entry = NULL;
#ifdef CONFIG_BRIDGE_NETFILTER
- struct net_device *physindev = NULL;
- struct net_device *physoutdev = NULL;
+ struct net_device *physindev;
+ struct net_device *physoutdev;
#endif
- struct nf_afinfo *afinfo;
- struct nf_queue_handler *qh;
+ const struct nf_afinfo *afinfo;
+ const struct nf_queue_handler *qh;
/* QUEUE == DROP if noone is waiting, to be safe. */
rcu_read_lock();
qh = rcu_dereference(queue_handler[pf]);
- if (!qh) {
- rcu_read_unlock();
- kfree_skb(skb);
- return 1;
- }
+ if (!qh)
+ goto err_unlock;
afinfo = nf_get_afinfo(pf);
- if (!afinfo) {
- rcu_read_unlock();
- kfree_skb(skb);
- return 1;
- }
-
- info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
- if (!info) {
- if (net_ratelimit())
- printk(KERN_ERR "OOM queueing packet %p\n",
- skb);
- rcu_read_unlock();
- kfree_skb(skb);
- return 1;
- }
-
- *info = (struct nf_info) {
- (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
+ if (!afinfo)
+ goto err_unlock;
+
+ entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC);
+ if (!entry)
+ goto err_unlock;
+
+ *entry = (struct nf_queue_entry) {
+ .skb = skb,
+ .elem = list_entry(elem, struct nf_hook_ops, list),
+ .pf = pf,
+ .hook = hook,
+ .indev = indev,
+ .outdev = outdev,
+ .okfn = okfn,
+ };
/* If it's going away, ignore hook. */
- if (!try_module_get(info->elem->owner)) {
+ if (!try_module_get(entry->elem->owner)) {
rcu_read_unlock();
- kfree(info);
+ kfree(entry);
return 0;
}
/* Bump dev refs so they don't vanish while packet is out */
- if (indev) dev_hold(indev);
- if (outdev) dev_hold(outdev);
-
+ if (indev)
+ dev_hold(indev);
+ if (outdev)
+ dev_hold(outdev);
#ifdef CONFIG_BRIDGE_NETFILTER
if (skb->nf_bridge) {
physindev = skb->nf_bridge->physindev;
- if (physindev) dev_hold(physindev);
+ if (physindev)
+ dev_hold(physindev);
physoutdev = skb->nf_bridge->physoutdev;
- if (physoutdev) dev_hold(physoutdev);
+ if (physoutdev)
+ dev_hold(physoutdev);
}
#endif
- afinfo->saveroute(skb, info);
- status = qh->outfn(skb, info, queuenum, qh->data);
+ afinfo->saveroute(skb, entry);
+ status = qh->outfn(entry, queuenum);
rcu_read_unlock();
if (status < 0) {
- /* James M doesn't say fuck enough. */
- if (indev) dev_put(indev);
- if (outdev) dev_put(outdev);
-#ifdef CONFIG_BRIDGE_NETFILTER
- if (physindev) dev_put(physindev);
- if (physoutdev) dev_put(physoutdev);
-#endif
- module_put(info->elem->owner);
- kfree(info);
- kfree_skb(skb);
-
- return 1;
+ nf_queue_entry_release_refs(entry);
+ goto err;
}
return 1;
+
+err_unlock:
+ rcu_read_unlock();
+err:
+ kfree_skb(skb);
+ kfree(entry);
+ return 1;
}
int nf_queue(struct sk_buff *skb,
@@ -212,41 +229,15 @@ int nf_queue(struct sk_buff *skb,
return 1;
}
-void nf_reinject(struct sk_buff *skb, struct nf_info *info,
- unsigned int verdict)
+void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
{
- struct list_head *elem = &info->elem->list;
- struct list_head *i;
- struct nf_afinfo *afinfo;
+ struct sk_buff *skb = entry->skb;
+ struct list_head *elem = &entry->elem->list;
+ const struct nf_afinfo *afinfo;
rcu_read_lock();
- /* Release those devices we held, or Alexey will kill me. */
- if (info->indev) dev_put(info->indev);
- if (info->outdev) dev_put(info->outdev);
-#ifdef CONFIG_BRIDGE_NETFILTER
- if (skb->nf_bridge) {
- if (skb->nf_bridge->physindev)
- dev_put(skb->nf_bridge->physindev);
- if (skb->nf_bridge->physoutdev)
- dev_put(skb->nf_bridge->physoutdev);
- }
-#endif
-
- /* Drop reference to owner of hook which queued us. */
- module_put(info->elem->owner);
-
- list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {
- if (i == elem)
- break;
- }
-
- if (i == &nf_hooks[info->pf][info->hook]) {
- /* The module which sent it to userspace is gone. */
- NFDEBUG("%s: module disappeared, dropping packet.\n",
- __FUNCTION__);
- verdict = NF_DROP;
- }
+ nf_queue_entry_release_refs(entry);
/* Continue traversal iff userspace said ok... */
if (verdict == NF_REPEAT) {
@@ -255,28 +246,30 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
}
if (verdict == NF_ACCEPT) {
- afinfo = nf_get_afinfo(info->pf);
- if (!afinfo || afinfo->reroute(skb, info) < 0)
+ afinfo = nf_get_afinfo(entry->pf);
+ if (!afinfo || afinfo->reroute(skb, entry) < 0)
verdict = NF_DROP;
}
if (verdict == NF_ACCEPT) {
next_hook:
- verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
- skb, info->hook,
- info->indev, info->outdev, &elem,
- info->okfn, INT_MIN);
+ verdict = nf_iterate(&nf_hooks[entry->pf][entry->hook],
+ skb, entry->hook,
+ entry->indev, entry->outdev, &elem,
+ entry->okfn, INT_MIN);
}
switch (verdict & NF_VERDICT_MASK) {
case NF_ACCEPT:
case NF_STOP:
- info->okfn(skb);
+ local_bh_disable();
+ entry->okfn(skb);
+ local_bh_enable();
case NF_STOLEN:
break;
case NF_QUEUE:
- if (!__nf_queue(skb, elem, info->pf, info->hook,
- info->indev, info->outdev, info->okfn,
+ if (!__nf_queue(skb, elem, entry->pf, entry->hook,
+ entry->indev, entry->outdev, entry->okfn,
verdict >> NF_VERDICT_BITS))
goto next_hook;
break;
@@ -284,7 +277,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
kfree_skb(skb);
}
rcu_read_unlock();
- kfree(info);
+ kfree(entry);
return;
}
EXPORT_SYMBOL(nf_reinject);
@@ -317,7 +310,7 @@ static int seq_show(struct seq_file *s, void *v)
{
int ret;
loff_t *pos = v;
- struct nf_queue_handler *qh;
+ const struct nf_queue_handler *qh;
rcu_read_lock();
qh = rcu_dereference(queue_handler[*pos]);
diff --git a/net/netfilter/nf_sysctl.c b/net/netfilter/nf_sysctl.c
deleted file mode 100644
index ee34589e48a..00000000000
--- a/net/netfilter/nf_sysctl.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* nf_sysctl.c netfilter sysctl registration/unregistation
- *
- * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
- */
-#include <linux/module.h>
-#include <linux/sysctl.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-static void
-path_free(struct ctl_table *path, struct ctl_table *table)
-{
- struct ctl_table *t, *next;
-
- for (t = path; t != NULL && t != table; t = next) {
- next = t->child;
- kfree(t);
- }
-}
-
-static struct ctl_table *
-path_dup(struct ctl_table *path, struct ctl_table *table)
-{
- struct ctl_table *t, *last = NULL, *tmp;
-
- for (t = path; t != NULL; t = t->child) {
- /* twice the size since path elements are terminated by an
- * empty element */
- tmp = kmemdup(t, 2 * sizeof(*t), GFP_KERNEL);
- if (tmp == NULL) {
- if (last != NULL)
- path_free(path, table);
- return NULL;
- }
-
- if (last != NULL)
- last->child = tmp;
- else
- path = tmp;
- last = tmp;
- }
-
- if (last != NULL)
- last->child = table;
- else
- path = table;
-
- return path;
-}
-
-struct ctl_table_header *
-nf_register_sysctl_table(struct ctl_table *path, struct ctl_table *table)
-{
- struct ctl_table_header *header;
-
- path = path_dup(path, table);
- if (path == NULL)
- return NULL;
- header = register_sysctl_table(path);
- if (header == NULL)
- path_free(path, table);
- return header;
-}
-EXPORT_SYMBOL_GPL(nf_register_sysctl_table);
-
-void
-nf_unregister_sysctl_table(struct ctl_table_header *header,
- struct ctl_table *table)
-{
- struct ctl_table *path = header->ctl_table;
-
- unregister_sysctl_table(header);
- path_free(path, table);
-}
-EXPORT_SYMBOL_GPL(nf_unregister_sysctl_table);
-
-/* net/netfilter */
-static struct ctl_table nf_net_netfilter_table[] = {
- {
- .ctl_name = NET_NETFILTER,
- .procname = "netfilter",
- .mode = 0555,
- },
- {
- .ctl_name = 0
- }
-};
-struct ctl_table nf_net_netfilter_sysctl_path[] = {
- {
- .ctl_name = CTL_NET,
- .procname = "net",
- .mode = 0555,
- .child = nf_net_netfilter_table,
- },
- {
- .ctl_name = 0
- }
-};
-EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path);
-
-/* net/ipv4/netfilter */
-static struct ctl_table nf_net_ipv4_netfilter_table[] = {
- {
- .ctl_name = NET_IPV4_NETFILTER,
- .procname = "netfilter",
- .mode = 0555,
- },
- {
- .ctl_name = 0
- }
-};
-static struct ctl_table nf_net_ipv4_table[] = {
- {
- .ctl_name = NET_IPV4,
- .procname = "ipv4",
- .mode = 0555,
- .child = nf_net_ipv4_netfilter_table,
- },
- {
- .ctl_name = 0
- }
-};
-struct ctl_table nf_net_ipv4_netfilter_sysctl_path[] = {
- {
- .ctl_name = CTL_NET,
- .procname = "net",
- .mode = 0555,
- .child = nf_net_ipv4_table,
- },
- {
- .ctl_name = 0
- }
-};
-EXPORT_SYMBOL_GPL(nf_net_ipv4_netfilter_sysctl_path);
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 2128542995f..b75c9c4a995 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -179,7 +179,7 @@ static void nfnetlink_rcv(struct sk_buff *skb)
static void __exit nfnetlink_exit(void)
{
printk("Removing netfilter NETLINK layer.\n");
- sock_release(nfnl->sk_socket);
+ netlink_kernel_release(nfnl);
return;
}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 2c7bd2eb029..5013cb97ce2 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -29,6 +29,7 @@
#include <linux/jhash.h>
#include <linux/random.h>
#include <net/sock.h>
+#include <net/netfilter/nf_log.h>
#include <asm/atomic.h>
@@ -44,14 +45,6 @@
#define PRINTR(x, args...) do { if (net_ratelimit()) \
printk(x, ## args); } while (0);
-#if 0
-#define UDEBUG(x, args ...) printk(KERN_DEBUG "%s(%d):%s(): " x, \
- __FILE__, __LINE__, __FUNCTION__, \
- ## args)
-#else
-#define UDEBUG(x, ...)
-#endif
-
struct nfulnl_instance {
struct hlist_node hlist; /* global list of instances */
spinlock_t lock;
@@ -92,8 +85,6 @@ __instance_lookup(u_int16_t group_num)
struct hlist_node *pos;
struct nfulnl_instance *inst;
- UDEBUG("entering (group_num=%u)\n", group_num);
-
head = &instance_table[instance_hashfn(group_num)];
hlist_for_each_entry(inst, pos, head, hlist) {
if (inst->group_num == group_num)
@@ -126,7 +117,6 @@ static void
instance_put(struct nfulnl_instance *inst)
{
if (inst && atomic_dec_and_test(&inst->use)) {
- UDEBUG("kfree(inst=%p)\n", inst);
kfree(inst);
module_put(THIS_MODULE);
}
@@ -138,23 +128,23 @@ static struct nfulnl_instance *
instance_create(u_int16_t group_num, int pid)
{
struct nfulnl_instance *inst;
-
- UDEBUG("entering (group_num=%u, pid=%d)\n", group_num,
- pid);
+ int err;
write_lock_bh(&instances_lock);
if (__instance_lookup(group_num)) {
- inst = NULL;
- UDEBUG("aborting, instance already exists\n");
+ err = -EEXIST;
goto out_unlock;
}
inst = kzalloc(sizeof(*inst), GFP_ATOMIC);
- if (!inst)
+ if (!inst) {
+ err = -ENOMEM;
goto out_unlock;
+ }
if (!try_module_get(THIS_MODULE)) {
kfree(inst);
+ err = -EAGAIN;
goto out_unlock;
}
@@ -177,16 +167,13 @@ instance_create(u_int16_t group_num, int pid)
hlist_add_head(&inst->hlist,
&instance_table[instance_hashfn(group_num)]);
- UDEBUG("newly added node: %p, next=%p\n", &inst->hlist,
- inst->hlist.next);
-
write_unlock_bh(&instances_lock);
return inst;
out_unlock:
write_unlock_bh(&instances_lock);
- return NULL;
+ return ERR_PTR(err);
}
static void __nfulnl_flush(struct nfulnl_instance *inst);
@@ -195,9 +182,6 @@ static void
__instance_destroy(struct nfulnl_instance *inst)
{
/* first pull it out of the global list */
- UDEBUG("removing instance %p (queuenum=%u) from hash\n",
- inst, inst->group_num);
-
hlist_del(&inst->hlist);
/* then flush all pending packets from skb */
@@ -305,8 +289,6 @@ nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size)
struct sk_buff *skb;
unsigned int n;
- UDEBUG("entered (%u, %u)\n", inst_size, pkt_size);
-
/* alloc skb which should be big enough for a whole multipart
* message. WARNING: has to be <= 128k due to slab restrictions */
@@ -341,10 +323,6 @@ __nfulnl_send(struct nfulnl_instance *inst)
sizeof(struct nfgenmsg));
status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT);
- if (status < 0) {
- UDEBUG("netlink_unicast() failed\n");
- /* FIXME: statistics */
- }
inst->qlen = 0;
inst->skb = NULL;
@@ -368,8 +346,6 @@ nfulnl_timer(unsigned long data)
{
struct nfulnl_instance *inst = (struct nfulnl_instance *)data;
- UDEBUG("timer function called, flushing buffer\n");
-
spin_lock_bh(&inst->lock);
if (inst->skb)
__nfulnl_send(inst);
@@ -396,8 +372,6 @@ __build_packet_message(struct nfulnl_instance *inst,
__be32 tmp_uint;
sk_buff_data_t old_tail = inst->skb->tail;
- UDEBUG("entered\n");
-
nlh = NLMSG_PUT(inst->skb, 0, 0,
NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
sizeof(struct nfgenmsg));
@@ -415,32 +389,27 @@ __build_packet_message(struct nfulnl_instance *inst,
NLA_PUT(inst->skb, NFULA_PREFIX, plen, prefix);
if (indev) {
- tmp_uint = htonl(indev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV, sizeof(tmp_uint),
- &tmp_uint);
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
+ htonl(indev->ifindex));
#else
if (pf == PF_BRIDGE) {
/* Case 1: outdev is physical input device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
- sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+ htonl(indev->ifindex));
/* this is the bridge group "brX" */
- tmp_uint = htonl(indev->br_port->br->dev->ifindex);
- NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
- sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
+ htonl(indev->br_port->br->dev->ifindex));
} else {
/* Case 2: indev is bridge group, we need to look for
* physical device (when called from ipv4) */
- NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
- sizeof(tmp_uint), &tmp_uint);
- if (skb->nf_bridge && skb->nf_bridge->physindev) {
- tmp_uint =
- htonl(skb->nf_bridge->physindev->ifindex);
- NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
- sizeof(tmp_uint), &tmp_uint);
- }
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
+ htonl(indev->ifindex));
+ if (skb->nf_bridge && skb->nf_bridge->physindev)
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+ htonl(skb->nf_bridge->physindev->ifindex));
}
#endif
}
@@ -448,38 +417,32 @@ __build_packet_message(struct nfulnl_instance *inst,
if (outdev) {
tmp_uint = htonl(outdev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV, sizeof(tmp_uint),
- &tmp_uint);
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
+ htonl(outdev->ifindex));
#else
if (pf == PF_BRIDGE) {
/* Case 1: outdev is physical output device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
- sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+ htonl(outdev->ifindex));
/* this is the bridge group "brX" */
- tmp_uint = htonl(outdev->br_port->br->dev->ifindex);
- NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
- sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
+ htonl(outdev->br_port->br->dev->ifindex));
} else {
/* Case 2: indev is a bridge group, we need to look
* for physical device (when called from ipv4) */
- NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
- sizeof(tmp_uint), &tmp_uint);
- if (skb->nf_bridge && skb->nf_bridge->physoutdev) {
- tmp_uint =
- htonl(skb->nf_bridge->physoutdev->ifindex);
- NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
- sizeof(tmp_uint), &tmp_uint);
- }
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
+ htonl(outdev->ifindex));
+ if (skb->nf_bridge && skb->nf_bridge->physoutdev)
+ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+ htonl(skb->nf_bridge->physoutdev->ifindex));
}
#endif
}
- if (skb->mark) {
- tmp_uint = htonl(skb->mark);
- NLA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint);
- }
+ if (skb->mark)
+ NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark));
if (indev && skb->dev) {
struct nfulnl_msg_packet_hw phw;
@@ -504,23 +467,23 @@ __build_packet_message(struct nfulnl_instance *inst,
read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
__be32 uid = htonl(skb->sk->sk_socket->file->f_uid);
+ __be32 gid = htons(skb->sk->sk_socket->file->f_gid);
/* need to unlock here since NLA_PUT may goto */
read_unlock_bh(&skb->sk->sk_callback_lock);
- NLA_PUT(inst->skb, NFULA_UID, sizeof(uid), &uid);
+ NLA_PUT_BE32(inst->skb, NFULA_UID, uid);
+ NLA_PUT_BE32(inst->skb, NFULA_GID, gid);
} else
read_unlock_bh(&skb->sk->sk_callback_lock);
}
/* local sequence number */
- if (inst->flags & NFULNL_CFG_F_SEQ) {
- tmp_uint = htonl(inst->seq++);
- NLA_PUT(inst->skb, NFULA_SEQ, sizeof(tmp_uint), &tmp_uint);
- }
+ if (inst->flags & NFULNL_CFG_F_SEQ)
+ NLA_PUT_BE32(inst->skb, NFULA_SEQ, htonl(inst->seq++));
+
/* global sequence number */
- if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) {
- tmp_uint = htonl(atomic_inc_return(&global_seq));
- NLA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint);
- }
+ if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
+ NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL,
+ htonl(atomic_inc_return(&global_seq)));
if (data_len) {
struct nlattr *nla;
@@ -543,7 +506,6 @@ __build_packet_message(struct nfulnl_instance *inst,
return 0;
nlmsg_failure:
- UDEBUG("nlmsg_failure\n");
nla_put_failure:
PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n");
return -1;
@@ -604,12 +566,11 @@ nfulnl_log_packet(unsigned int pf,
#endif
+ nla_total_size(sizeof(u_int32_t)) /* mark */
+ nla_total_size(sizeof(u_int32_t)) /* uid */
+ + nla_total_size(sizeof(u_int32_t)) /* gid */
+ nla_total_size(plen) /* prefix */
+ nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
- UDEBUG("initial size=%u\n", size);
-
spin_lock_bh(&inst->lock);
if (inst->flags & NFULNL_CFG_F_SEQ)
@@ -636,7 +597,6 @@ nfulnl_log_packet(unsigned int pf,
data_len = inst->copy_range;
size += nla_total_size(data_len);
- UDEBUG("copy_packet, therefore size now %u\n", size);
break;
default:
@@ -647,8 +607,6 @@ nfulnl_log_packet(unsigned int pf,
size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) {
/* either the queue len is too high or we don't have
* enough room in the skb left. flush to userspace. */
- UDEBUG("flushing old skb\n");
-
__nfulnl_flush(inst);
}
@@ -658,7 +616,6 @@ nfulnl_log_packet(unsigned int pf,
goto alloc_failure;
}
- UDEBUG("qlen %d, qthreshold %d\n", inst->qlen, qthreshold);
inst->qlen++;
__build_packet_message(inst, skb, data_len, pf,
@@ -680,7 +637,6 @@ unlock_and_release:
return;
alloc_failure:
- UDEBUG("error allocating skb\n");
/* FIXME: statistics */
goto unlock_and_release;
}
@@ -703,7 +659,6 @@ nfulnl_rcv_nl_event(struct notifier_block *this,
struct hlist_head *head = &instance_table[i];
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
- UDEBUG("node = %p\n", inst);
if ((n->net == &init_net) &&
(n->pid == inst->peer_pid))
__instance_destroy(inst);
@@ -725,7 +680,7 @@ nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
return -ENOTSUPP;
}
-static struct nf_logger nfulnl_logger = {
+static const struct nf_logger nfulnl_logger = {
.name = "nfnetlink_log",
.logfn = &nfulnl_log_packet,
.me = THIS_MODULE,
@@ -749,14 +704,17 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
struct nfulnl_instance *inst;
int ret = 0;
- UDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
-
inst = instance_lookup_get(group_num);
+ if (inst && inst->peer_pid != NETLINK_CB(skb).pid) {
+ ret = -EPERM;
+ goto out_put;
+ }
+
if (nfula[NFULA_CFG_CMD]) {
u_int8_t pf = nfmsg->nfgen_family;
struct nfulnl_msg_config_cmd *cmd;
+
cmd = nla_data(nfula[NFULA_CFG_CMD]);
- UDEBUG("found CFG_CMD for\n");
switch (cmd->command) {
case NFULNL_CFG_CMD_BIND:
@@ -767,8 +725,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
inst = instance_create(group_num,
NETLINK_CB(skb).pid);
- if (!inst) {
- ret = -EINVAL;
+ if (IS_ERR(inst)) {
+ ret = PTR_ERR(inst);
goto out;
}
break;
@@ -778,78 +736,71 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
goto out;
}
- if (inst->peer_pid != NETLINK_CB(skb).pid) {
- ret = -EPERM;
- goto out_put;
- }
-
instance_destroy(inst);
goto out;
case NFULNL_CFG_CMD_PF_BIND:
- UDEBUG("registering log handler for pf=%u\n", pf);
ret = nf_log_register(pf, &nfulnl_logger);
break;
case NFULNL_CFG_CMD_PF_UNBIND:
- UDEBUG("unregistering log handler for pf=%u\n", pf);
/* This is a bug and a feature. We cannot unregister
* other handlers, like nfnetlink_inst can */
nf_log_unregister_pf(pf);
break;
default:
- ret = -EINVAL;
+ ret = -ENOTSUPP;
break;
}
-
- if (!inst)
- goto out;
- } else {
- if (!inst) {
- UDEBUG("no config command, and no instance for "
- "group=%u pid=%u =>ENOENT\n",
- group_num, NETLINK_CB(skb).pid);
- ret = -ENOENT;
- goto out;
- }
-
- if (inst->peer_pid != NETLINK_CB(skb).pid) {
- UDEBUG("no config command, and wrong pid\n");
- ret = -EPERM;
- goto out_put;
- }
}
if (nfula[NFULA_CFG_MODE]) {
struct nfulnl_msg_config_mode *params;
params = nla_data(nfula[NFULA_CFG_MODE]);
+ if (!inst) {
+ ret = -ENODEV;
+ goto out;
+ }
nfulnl_set_mode(inst, params->copy_mode,
ntohl(params->copy_range));
}
if (nfula[NFULA_CFG_TIMEOUT]) {
- __be32 timeout =
- *(__be32 *)nla_data(nfula[NFULA_CFG_TIMEOUT]);
+ __be32 timeout = nla_get_be32(nfula[NFULA_CFG_TIMEOUT]);
+ if (!inst) {
+ ret = -ENODEV;
+ goto out;
+ }
nfulnl_set_timeout(inst, ntohl(timeout));
}
if (nfula[NFULA_CFG_NLBUFSIZ]) {
- __be32 nlbufsiz =
- *(__be32 *)nla_data(nfula[NFULA_CFG_NLBUFSIZ]);
+ __be32 nlbufsiz = nla_get_be32(nfula[NFULA_CFG_NLBUFSIZ]);
+ if (!inst) {
+ ret = -ENODEV;
+ goto out;
+ }
nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz));
}
if (nfula[NFULA_CFG_QTHRESH]) {
- __be32 qthresh =
- *(__be32 *)nla_data(nfula[NFULA_CFG_QTHRESH]);
+ __be32 qthresh = nla_get_be32(nfula[NFULA_CFG_QTHRESH]);
+ if (!inst) {
+ ret = -ENODEV;
+ goto out;
+ }
nfulnl_set_qthresh(inst, ntohl(qthresh));
}
if (nfula[NFULA_CFG_FLAGS]) {
- __be16 flags =
- *(__be16 *)nla_data(nfula[NFULA_CFG_FLAGS]);
+ __be16 flags = nla_get_be16(nfula[NFULA_CFG_FLAGS]);
+
+ if (!inst) {
+ ret = -ENODEV;
+ goto out;
+ }
nfulnl_set_flags(inst, ntohs(flags));
}
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 3ceeffcf6f9..51476f82bb5 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -3,6 +3,7 @@
* userspace via nfetlink.
*
* (C) 2005 by Harald Welte <laforge@netfilter.org>
+ * (C) 2007 by Patrick McHardy <kaber@trash.net>
*
* Based on the old ipv4-only ip_queue.c:
* (C) 2000-2002 James Morris <jmorris@intercode.com.au>
@@ -27,6 +28,7 @@
#include <linux/netfilter/nfnetlink_queue.h>
#include <linux/list.h>
#include <net/sock.h>
+#include <net/netfilter/nf_queue.h>
#include <asm/atomic.h>
@@ -36,24 +38,9 @@
#define NFQNL_QMAX_DEFAULT 1024
-#if 0
-#define QDEBUG(x, args ...) printk(KERN_DEBUG "%s(%d):%s(): " x, \
- __FILE__, __LINE__, __FUNCTION__, \
- ## args)
-#else
-#define QDEBUG(x, ...)
-#endif
-
-struct nfqnl_queue_entry {
- struct list_head list;
- struct nf_info *info;
- struct sk_buff *skb;
- unsigned int id;
-};
-
struct nfqnl_instance {
struct hlist_node hlist; /* global list of queues */
- atomic_t use;
+ struct rcu_head rcu;
int peer_pid;
unsigned int queue_maxlen;
@@ -62,7 +49,7 @@ struct nfqnl_instance {
unsigned int queue_dropped;
unsigned int queue_user_dropped;
- atomic_t id_sequence; /* 'sequence' of pkt ids */
+ unsigned int id_sequence; /* 'sequence' of pkt ids */
u_int16_t queue_num; /* number of this queue */
u_int8_t copy_mode;
@@ -72,12 +59,12 @@ struct nfqnl_instance {
struct list_head queue_list; /* packets in queue */
};
-typedef int (*nfqnl_cmpfn)(struct nfqnl_queue_entry *, unsigned long);
+typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
-static DEFINE_RWLOCK(instances_lock);
+static DEFINE_SPINLOCK(instances_lock);
#define INSTANCE_BUCKETS 16
-static struct hlist_head instance_table[INSTANCE_BUCKETS];
+static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly;
static inline u_int8_t instance_hashfn(u_int16_t queue_num)
{
@@ -85,14 +72,14 @@ static inline u_int8_t instance_hashfn(u_int16_t queue_num)
}
static struct nfqnl_instance *
-__instance_lookup(u_int16_t queue_num)
+instance_lookup(u_int16_t queue_num)
{
struct hlist_head *head;
struct hlist_node *pos;
struct nfqnl_instance *inst;
head = &instance_table[instance_hashfn(queue_num)];
- hlist_for_each_entry(inst, pos, head, hlist) {
+ hlist_for_each_entry_rcu(inst, pos, head, hlist) {
if (inst->queue_num == queue_num)
return inst;
}
@@ -100,243 +87,131 @@ __instance_lookup(u_int16_t queue_num)
}
static struct nfqnl_instance *
-instance_lookup_get(u_int16_t queue_num)
-{
- struct nfqnl_instance *inst;
-
- read_lock_bh(&instances_lock);
- inst = __instance_lookup(queue_num);
- if (inst)
- atomic_inc(&inst->use);
- read_unlock_bh(&instances_lock);
-
- return inst;
-}
-
-static void
-instance_put(struct nfqnl_instance *inst)
-{
- if (inst && atomic_dec_and_test(&inst->use)) {
- QDEBUG("kfree(inst=%p)\n", inst);
- kfree(inst);
- }
-}
-
-static struct nfqnl_instance *
instance_create(u_int16_t queue_num, int pid)
{
struct nfqnl_instance *inst;
+ unsigned int h;
+ int err;
- QDEBUG("entering for queue_num=%u, pid=%d\n", queue_num, pid);
-
- write_lock_bh(&instances_lock);
- if (__instance_lookup(queue_num)) {
- inst = NULL;
- QDEBUG("aborting, instance already exists\n");
+ spin_lock(&instances_lock);
+ if (instance_lookup(queue_num)) {
+ err = -EEXIST;
goto out_unlock;
}
inst = kzalloc(sizeof(*inst), GFP_ATOMIC);
- if (!inst)
+ if (!inst) {
+ err = -ENOMEM;
goto out_unlock;
+ }
inst->queue_num = queue_num;
inst->peer_pid = pid;
inst->queue_maxlen = NFQNL_QMAX_DEFAULT;
inst->copy_range = 0xfffff;
inst->copy_mode = NFQNL_COPY_NONE;
- atomic_set(&inst->id_sequence, 0);
- /* needs to be two, since we _put() after creation */
- atomic_set(&inst->use, 2);
spin_lock_init(&inst->lock);
INIT_LIST_HEAD(&inst->queue_list);
+ INIT_RCU_HEAD(&inst->rcu);
- if (!try_module_get(THIS_MODULE))
+ if (!try_module_get(THIS_MODULE)) {
+ err = -EAGAIN;
goto out_free;
+ }
- hlist_add_head(&inst->hlist,
- &instance_table[instance_hashfn(queue_num)]);
-
- write_unlock_bh(&instances_lock);
+ h = instance_hashfn(queue_num);
+ hlist_add_head_rcu(&inst->hlist, &instance_table[h]);
- QDEBUG("successfully created new instance\n");
+ spin_unlock(&instances_lock);
return inst;
out_free:
kfree(inst);
out_unlock:
- write_unlock_bh(&instances_lock);
- return NULL;
+ spin_unlock(&instances_lock);
+ return ERR_PTR(err);
}
-static void nfqnl_flush(struct nfqnl_instance *queue, int verdict);
+static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
+ unsigned long data);
static void
-_instance_destroy2(struct nfqnl_instance *inst, int lock)
+instance_destroy_rcu(struct rcu_head *head)
{
- /* first pull it out of the global list */
- if (lock)
- write_lock_bh(&instances_lock);
-
- QDEBUG("removing instance %p (queuenum=%u) from hash\n",
- inst, inst->queue_num);
- hlist_del(&inst->hlist);
-
- if (lock)
- write_unlock_bh(&instances_lock);
-
- /* then flush all pending skbs from the queue */
- nfqnl_flush(inst, NF_DROP);
-
- /* and finally put the refcount */
- instance_put(inst);
+ struct nfqnl_instance *inst = container_of(head, struct nfqnl_instance,
+ rcu);
+ nfqnl_flush(inst, NULL, 0);
+ kfree(inst);
module_put(THIS_MODULE);
}
-static inline void
+static void
__instance_destroy(struct nfqnl_instance *inst)
{
- _instance_destroy2(inst, 0);
+ hlist_del_rcu(&inst->hlist);
+ call_rcu(&inst->rcu, instance_destroy_rcu);
}
-static inline void
-instance_destroy(struct nfqnl_instance *inst)
-{
- _instance_destroy2(inst, 1);
-}
-
-
-
static void
-issue_verdict(struct nfqnl_queue_entry *entry, int verdict)
+instance_destroy(struct nfqnl_instance *inst)
{
- QDEBUG("entering for entry %p, verdict %u\n", entry, verdict);
-
- /* TCP input path (and probably other bits) assume to be called
- * from softirq context, not from syscall, like issue_verdict is
- * called. TCP input path deadlocks with locks taken from timer
- * softirq, e.g. We therefore emulate this by local_bh_disable() */
-
- local_bh_disable();
- nf_reinject(entry->skb, entry->info, verdict);
- local_bh_enable();
-
- kfree(entry);
+ spin_lock(&instances_lock);
+ __instance_destroy(inst);
+ spin_unlock(&instances_lock);
}
static inline void
-__enqueue_entry(struct nfqnl_instance *queue,
- struct nfqnl_queue_entry *entry)
+__enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
{
- list_add(&entry->list, &queue->queue_list);
+ list_add_tail(&entry->list, &queue->queue_list);
queue->queue_total++;
}
-/*
- * Find and return a queued entry matched by cmpfn, or return the last
- * entry if cmpfn is NULL.
- */
-static inline struct nfqnl_queue_entry *
-__find_entry(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
- unsigned long data)
+static struct nf_queue_entry *
+find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
{
- struct list_head *p;
+ struct nf_queue_entry *entry = NULL, *i;
- list_for_each_prev(p, &queue->queue_list) {
- struct nfqnl_queue_entry *entry = (struct nfqnl_queue_entry *)p;
+ spin_lock_bh(&queue->lock);
- if (!cmpfn || cmpfn(entry, data))
- return entry;
+ list_for_each_entry(i, &queue->queue_list, list) {
+ if (i->id == id) {
+ entry = i;
+ break;
+ }
}
- return NULL;
-}
-
-static inline void
-__dequeue_entry(struct nfqnl_instance *q, struct nfqnl_queue_entry *entry)
-{
- list_del(&entry->list);
- q->queue_total--;
-}
-
-static inline struct nfqnl_queue_entry *
-__find_dequeue_entry(struct nfqnl_instance *queue,
- nfqnl_cmpfn cmpfn, unsigned long data)
-{
- struct nfqnl_queue_entry *entry;
-
- entry = __find_entry(queue, cmpfn, data);
- if (entry == NULL)
- return NULL;
-
- __dequeue_entry(queue, entry);
- return entry;
-}
-
-
-static inline void
-__nfqnl_flush(struct nfqnl_instance *queue, int verdict)
-{
- struct nfqnl_queue_entry *entry;
-
- while ((entry = __find_dequeue_entry(queue, NULL, 0)))
- issue_verdict(entry, verdict);
-}
-
-static inline int
-__nfqnl_set_mode(struct nfqnl_instance *queue,
- unsigned char mode, unsigned int range)
-{
- int status = 0;
-
- switch (mode) {
- case NFQNL_COPY_NONE:
- case NFQNL_COPY_META:
- queue->copy_mode = mode;
- queue->copy_range = 0;
- break;
-
- case NFQNL_COPY_PACKET:
- queue->copy_mode = mode;
- /* we're using struct nlattr which has 16bit nla_len */
- if (range > 0xffff)
- queue->copy_range = 0xffff;
- else
- queue->copy_range = range;
- break;
-
- default:
- status = -EINVAL;
+ if (entry) {
+ list_del(&entry->list);
+ queue->queue_total--;
}
- return status;
-}
-static struct nfqnl_queue_entry *
-find_dequeue_entry(struct nfqnl_instance *queue,
- nfqnl_cmpfn cmpfn, unsigned long data)
-{
- struct nfqnl_queue_entry *entry;
-
- spin_lock_bh(&queue->lock);
- entry = __find_dequeue_entry(queue, cmpfn, data);
spin_unlock_bh(&queue->lock);
return entry;
}
static void
-nfqnl_flush(struct nfqnl_instance *queue, int verdict)
+nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
{
+ struct nf_queue_entry *entry, *next;
+
spin_lock_bh(&queue->lock);
- __nfqnl_flush(queue, verdict);
+ list_for_each_entry_safe(entry, next, &queue->queue_list, list) {
+ if (!cmpfn || cmpfn(entry, data)) {
+ list_del(&entry->list);
+ queue->queue_total--;
+ nf_reinject(entry, NF_DROP);
+ }
+ }
spin_unlock_bh(&queue->lock);
}
static struct sk_buff *
nfqnl_build_packet_message(struct nfqnl_instance *queue,
- struct nfqnl_queue_entry *entry, int *errp)
+ struct nf_queue_entry *entry)
{
sk_buff_data_t old_tail;
size_t size;
@@ -345,13 +220,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
struct nfqnl_msg_packet_hdr pmsg;
struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg;
- struct nf_info *entinf = entry->info;
struct sk_buff *entskb = entry->skb;
struct net_device *indev;
struct net_device *outdev;
- __be32 tmp_uint;
-
- QDEBUG("entered\n");
size = NLMSG_ALIGN(sizeof(struct nfgenmsg))
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
@@ -365,11 +236,11 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
+ nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
- outdev = entinf->outdev;
+ outdev = entry->outdev;
spin_lock_bh(&queue->lock);
- switch (queue->copy_mode) {
+ switch ((enum nfqnl_config_mode)queue->copy_mode) {
case NFQNL_COPY_META:
case NFQNL_COPY_NONE:
data_len = 0;
@@ -378,7 +249,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
case NFQNL_COPY_PACKET:
if ((entskb->ip_summed == CHECKSUM_PARTIAL ||
entskb->ip_summed == CHECKSUM_COMPLETE) &&
- (*errp = skb_checksum_help(entskb))) {
+ skb_checksum_help(entskb)) {
spin_unlock_bh(&queue->lock);
return NULL;
}
@@ -390,13 +261,10 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
size += nla_total_size(data_len);
break;
-
- default:
- *errp = -EINVAL;
- spin_unlock_bh(&queue->lock);
- return NULL;
}
+ entry->id = queue->id_sequence++;
+
spin_unlock_bh(&queue->lock);
skb = alloc_skb(size, GFP_ATOMIC);
@@ -408,81 +276,69 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
sizeof(struct nfgenmsg));
nfmsg = NLMSG_DATA(nlh);
- nfmsg->nfgen_family = entinf->pf;
+ nfmsg->nfgen_family = entry->pf;
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = htons(queue->queue_num);
pmsg.packet_id = htonl(entry->id);
pmsg.hw_protocol = entskb->protocol;
- pmsg.hook = entinf->hook;
+ pmsg.hook = entry->hook;
NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
- indev = entinf->indev;
+ indev = entry->indev;
if (indev) {
- tmp_uint = htonl(indev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex));
#else
- if (entinf->pf == PF_BRIDGE) {
+ if (entry->pf == PF_BRIDGE) {
/* Case 1: indev is physical input device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NLA_PUT(skb, NFQA_IFINDEX_PHYSINDEV, sizeof(tmp_uint),
- &tmp_uint);
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV,
+ htonl(indev->ifindex));
/* this is the bridge group "brX" */
- tmp_uint = htonl(indev->br_port->br->dev->ifindex);
- NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
- &tmp_uint);
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV,
+ htonl(indev->br_port->br->dev->ifindex));
} else {
/* Case 2: indev is bridge group, we need to look for
* physical device (when called from ipv4) */
- NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
- &tmp_uint);
- if (entskb->nf_bridge
- && entskb->nf_bridge->physindev) {
- tmp_uint = htonl(entskb->nf_bridge->physindev->ifindex);
- NLA_PUT(skb, NFQA_IFINDEX_PHYSINDEV,
- sizeof(tmp_uint), &tmp_uint);
- }
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV,
+ htonl(indev->ifindex));
+ if (entskb->nf_bridge && entskb->nf_bridge->physindev)
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV,
+ htonl(entskb->nf_bridge->physindev->ifindex));
}
#endif
}
if (outdev) {
- tmp_uint = htonl(outdev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex));
#else
- if (entinf->pf == PF_BRIDGE) {
+ if (entry->pf == PF_BRIDGE) {
/* Case 1: outdev is physical output device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NLA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV, sizeof(tmp_uint),
- &tmp_uint);
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV,
+ htonl(outdev->ifindex));
/* this is the bridge group "brX" */
- tmp_uint = htonl(outdev->br_port->br->dev->ifindex);
- NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
- &tmp_uint);
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV,
+ htonl(outdev->br_port->br->dev->ifindex));
} else {
/* Case 2: outdev is bridge group, we need to look for
* physical output device (when called from ipv4) */
- NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
- &tmp_uint);
- if (entskb->nf_bridge
- && entskb->nf_bridge->physoutdev) {
- tmp_uint = htonl(entskb->nf_bridge->physoutdev->ifindex);
- NLA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV,
- sizeof(tmp_uint), &tmp_uint);
- }
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV,
+ htonl(outdev->ifindex));
+ if (entskb->nf_bridge && entskb->nf_bridge->physoutdev)
+ NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV,
+ htonl(entskb->nf_bridge->physoutdev->ifindex));
}
#endif
}
- if (entskb->mark) {
- tmp_uint = htonl(entskb->mark);
- NLA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint);
- }
+ if (entskb->mark)
+ NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark));
if (indev && entskb->dev) {
struct nfqnl_msg_packet_hw phw;
@@ -526,51 +382,29 @@ nlmsg_failure:
nla_put_failure:
if (skb)
kfree_skb(skb);
- *errp = -EINVAL;
if (net_ratelimit())
printk(KERN_ERR "nf_queue: error creating packet message\n");
return NULL;
}
static int
-nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
- unsigned int queuenum, void *data)
+nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
{
- int status = -EINVAL;
struct sk_buff *nskb;
struct nfqnl_instance *queue;
- struct nfqnl_queue_entry *entry;
-
- QDEBUG("entered\n");
-
- queue = instance_lookup_get(queuenum);
- if (!queue) {
- QDEBUG("no queue instance matching\n");
- return -EINVAL;
- }
-
- if (queue->copy_mode == NFQNL_COPY_NONE) {
- QDEBUG("mode COPY_NONE, aborting\n");
- status = -EAGAIN;
- goto err_out_put;
- }
+ int err;
- entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
- if (entry == NULL) {
- if (net_ratelimit())
- printk(KERN_ERR
- "nf_queue: OOM in nfqnl_enqueue_packet()\n");
- status = -ENOMEM;
- goto err_out_put;
- }
+ /* rcu_read_lock()ed by nf_hook_slow() */
+ queue = instance_lookup(queuenum);
+ if (!queue)
+ goto err_out;
- entry->info = info;
- entry->skb = skb;
- entry->id = atomic_inc_return(&queue->id_sequence);
+ if (queue->copy_mode == NFQNL_COPY_NONE)
+ goto err_out;
- nskb = nfqnl_build_packet_message(queue, entry, &status);
+ nskb = nfqnl_build_packet_message(queue, entry);
if (nskb == NULL)
- goto err_out_free;
+ goto err_out;
spin_lock_bh(&queue->lock);
@@ -579,7 +413,6 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
if (queue->queue_total >= queue->queue_maxlen) {
queue->queue_dropped++;
- status = -ENOSPC;
if (net_ratelimit())
printk(KERN_WARNING "nf_queue: full at %d entries, "
"dropping packets(s). Dropped: %d\n",
@@ -588,8 +421,8 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
}
/* nfnetlink_unicast will either free the nskb or add it to a socket */
- status = nfnetlink_unicast(nskb, queue->peer_pid, MSG_DONTWAIT);
- if (status < 0) {
+ err = nfnetlink_unicast(nskb, queue->peer_pid, MSG_DONTWAIT);
+ if (err < 0) {
queue->queue_user_dropped++;
goto err_out_unlock;
}
@@ -597,24 +430,18 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
__enqueue_entry(queue, entry);
spin_unlock_bh(&queue->lock);
- instance_put(queue);
- return status;
+ return 0;
err_out_free_nskb:
kfree_skb(nskb);
-
err_out_unlock:
spin_unlock_bh(&queue->lock);
-
-err_out_free:
- kfree(entry);
-err_out_put:
- instance_put(queue);
- return status;
+err_out:
+ return -1;
}
static int
-nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
+nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e)
{
int diff;
int err;
@@ -645,35 +472,46 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
return 0;
}
-static inline int
-id_cmp(struct nfqnl_queue_entry *e, unsigned long id)
-{
- return (id == e->id);
-}
-
static int
nfqnl_set_mode(struct nfqnl_instance *queue,
unsigned char mode, unsigned int range)
{
- int status;
+ int status = 0;
spin_lock_bh(&queue->lock);
- status = __nfqnl_set_mode(queue, mode, range);
+ switch (mode) {
+ case NFQNL_COPY_NONE:
+ case NFQNL_COPY_META:
+ queue->copy_mode = mode;
+ queue->copy_range = 0;
+ break;
+
+ case NFQNL_COPY_PACKET:
+ queue->copy_mode = mode;
+ /* we're using struct nlattr which has 16bit nla_len */
+ if (range > 0xffff)
+ queue->copy_range = 0xffff;
+ else
+ queue->copy_range = range;
+ break;
+
+ default:
+ status = -EINVAL;
+
+ }
spin_unlock_bh(&queue->lock);
return status;
}
static int
-dev_cmp(struct nfqnl_queue_entry *entry, unsigned long ifindex)
+dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
{
- struct nf_info *entinf = entry->info;
-
- if (entinf->indev)
- if (entinf->indev->ifindex == ifindex)
+ if (entry->indev)
+ if (entry->indev->ifindex == ifindex)
return 1;
- if (entinf->outdev)
- if (entinf->outdev->ifindex == ifindex)
+ if (entry->outdev)
+ if (entry->outdev->ifindex == ifindex)
return 1;
#ifdef CONFIG_BRIDGE_NETFILTER
if (entry->skb->nf_bridge) {
@@ -695,27 +533,18 @@ nfqnl_dev_drop(int ifindex)
{
int i;
- QDEBUG("entering for ifindex %u\n", ifindex);
-
- /* this only looks like we have to hold the readlock for a way too long
- * time, issue_verdict(), nf_reinject(), ... - but we always only
- * issue NF_DROP, which is processed directly in nf_reinject() */
- read_lock_bh(&instances_lock);
+ rcu_read_lock();
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
+ for (i = 0; i < INSTANCE_BUCKETS; i++) {
struct hlist_node *tmp;
struct nfqnl_instance *inst;
struct hlist_head *head = &instance_table[i];
- hlist_for_each_entry(inst, tmp, head, hlist) {
- struct nfqnl_queue_entry *entry;
- while ((entry = find_dequeue_entry(inst, dev_cmp,
- ifindex)) != NULL)
- issue_verdict(entry, NF_DROP);
- }
+ hlist_for_each_entry_rcu(inst, tmp, head, hlist)
+ nfqnl_flush(inst, dev_cmp, ifindex);
}
- read_unlock_bh(&instances_lock);
+ rcu_read_unlock();
}
#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
@@ -750,8 +579,8 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
int i;
/* destroy all instances for this pid */
- write_lock_bh(&instances_lock);
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
+ spin_lock(&instances_lock);
+ for (i = 0; i < INSTANCE_BUCKETS; i++) {
struct hlist_node *tmp, *t2;
struct nfqnl_instance *inst;
struct hlist_head *head = &instance_table[i];
@@ -762,7 +591,7 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
__instance_destroy(inst);
}
}
- write_unlock_bh(&instances_lock);
+ spin_unlock(&instances_lock);
}
return NOTIFY_DONE;
}
@@ -787,21 +616,24 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
struct nfqnl_msg_verdict_hdr *vhdr;
struct nfqnl_instance *queue;
unsigned int verdict;
- struct nfqnl_queue_entry *entry;
+ struct nf_queue_entry *entry;
int err;
- queue = instance_lookup_get(queue_num);
- if (!queue)
- return -ENODEV;
+ rcu_read_lock();
+ queue = instance_lookup(queue_num);
+ if (!queue) {
+ err = -ENODEV;
+ goto err_out_unlock;
+ }
if (queue->peer_pid != NETLINK_CB(skb).pid) {
err = -EPERM;
- goto err_out_put;
+ goto err_out_unlock;
}
if (!nfqa[NFQA_VERDICT_HDR]) {
err = -EINVAL;
- goto err_out_put;
+ goto err_out_unlock;
}
vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
@@ -809,14 +641,15 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) {
err = -EINVAL;
- goto err_out_put;
+ goto err_out_unlock;
}
- entry = find_dequeue_entry(queue, id_cmp, ntohl(vhdr->id));
+ entry = find_dequeue_entry(queue, ntohl(vhdr->id));
if (entry == NULL) {
err = -ENOENT;
- goto err_out_put;
+ goto err_out_unlock;
}
+ rcu_read_unlock();
if (nfqa[NFQA_PAYLOAD]) {
if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
@@ -825,15 +658,13 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
}
if (nfqa[NFQA_MARK])
- entry->skb->mark = ntohl(*(__be32 *)
- nla_data(nfqa[NFQA_MARK]));
+ entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
- issue_verdict(entry, verdict);
- instance_put(queue);
+ nf_reinject(entry, verdict);
return 0;
-err_out_put:
- instance_put(queue);
+err_out_unlock:
+ rcu_read_unlock();
return err;
}
@@ -849,7 +680,7 @@ static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = {
[NFQA_CFG_PARAMS] = { .len = sizeof(struct nfqnl_msg_config_params) },
};
-static struct nf_queue_handler nfqh = {
+static const struct nf_queue_handler nfqh = {
.name = "nf_queue",
.outfn = &nfqnl_enqueue_packet,
};
@@ -861,70 +692,72 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
u_int16_t queue_num = ntohs(nfmsg->res_id);
struct nfqnl_instance *queue;
+ struct nfqnl_msg_config_cmd *cmd = NULL;
int ret = 0;
- QDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
-
- queue = instance_lookup_get(queue_num);
if (nfqa[NFQA_CFG_CMD]) {
- struct nfqnl_msg_config_cmd *cmd;
cmd = nla_data(nfqa[NFQA_CFG_CMD]);
- QDEBUG("found CFG_CMD\n");
+ /* Commands without queue context - might sleep */
switch (cmd->command) {
- case NFQNL_CFG_CMD_BIND:
- if (queue)
- return -EBUSY;
+ case NFQNL_CFG_CMD_PF_BIND:
+ ret = nf_register_queue_handler(ntohs(cmd->pf),
+ &nfqh);
+ break;
+ case NFQNL_CFG_CMD_PF_UNBIND:
+ ret = nf_unregister_queue_handler(ntohs(cmd->pf),
+ &nfqh);
+ break;
+ default:
+ break;
+ }
+
+ if (ret < 0)
+ return ret;
+ }
+
+ rcu_read_lock();
+ queue = instance_lookup(queue_num);
+ if (queue && queue->peer_pid != NETLINK_CB(skb).pid) {
+ ret = -EPERM;
+ goto err_out_unlock;
+ }
+ if (cmd != NULL) {
+ switch (cmd->command) {
+ case NFQNL_CFG_CMD_BIND:
+ if (queue) {
+ ret = -EBUSY;
+ goto err_out_unlock;
+ }
queue = instance_create(queue_num, NETLINK_CB(skb).pid);
- if (!queue)
- return -EINVAL;
+ if (IS_ERR(queue)) {
+ ret = PTR_ERR(queue);
+ goto err_out_unlock;
+ }
break;
case NFQNL_CFG_CMD_UNBIND:
- if (!queue)
- return -ENODEV;
-
- if (queue->peer_pid != NETLINK_CB(skb).pid) {
- ret = -EPERM;
- goto out_put;
+ if (!queue) {
+ ret = -ENODEV;
+ goto err_out_unlock;
}
-
instance_destroy(queue);
break;
case NFQNL_CFG_CMD_PF_BIND:
- QDEBUG("registering queue handler for pf=%u\n",
- ntohs(cmd->pf));
- ret = nf_register_queue_handler(ntohs(cmd->pf), &nfqh);
- break;
case NFQNL_CFG_CMD_PF_UNBIND:
- QDEBUG("unregistering queue handler for pf=%u\n",
- ntohs(cmd->pf));
- ret = nf_unregister_queue_handler(ntohs(cmd->pf), &nfqh);
break;
default:
- ret = -EINVAL;
+ ret = -ENOTSUPP;
break;
}
- } else {
- if (!queue) {
- QDEBUG("no config command, and no instance ENOENT\n");
- ret = -ENOENT;
- goto out_put;
- }
-
- if (queue->peer_pid != NETLINK_CB(skb).pid) {
- QDEBUG("no config command, and wrong pid\n");
- ret = -EPERM;
- goto out_put;
- }
}
if (nfqa[NFQA_CFG_PARAMS]) {
struct nfqnl_msg_config_params *params;
if (!queue) {
- ret = -ENOENT;
- goto out_put;
+ ret = -ENODEV;
+ goto err_out_unlock;
}
params = nla_data(nfqa[NFQA_CFG_PARAMS]);
nfqnl_set_mode(queue, params->copy_mode,
@@ -933,14 +766,19 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
if (nfqa[NFQA_CFG_QUEUE_MAXLEN]) {
__be32 *queue_maxlen;
+
+ if (!queue) {
+ ret = -ENODEV;
+ goto err_out_unlock;
+ }
queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]);
spin_lock_bh(&queue->lock);
queue->queue_maxlen = ntohl(*queue_maxlen);
spin_unlock_bh(&queue->lock);
}
-out_put:
- instance_put(queue);
+err_out_unlock:
+ rcu_read_unlock();
return ret;
}
@@ -1008,7 +846,7 @@ static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
static void *seq_start(struct seq_file *seq, loff_t *pos)
{
- read_lock_bh(&instances_lock);
+ spin_lock(&instances_lock);
return get_idx(seq, *pos);
}
@@ -1020,7 +858,7 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
static void seq_stop(struct seq_file *s, void *v)
{
- read_unlock_bh(&instances_lock);
+ spin_unlock(&instances_lock);
}
static int seq_show(struct seq_file *s, void *v)
@@ -1032,8 +870,7 @@ static int seq_show(struct seq_file *s, void *v)
inst->peer_pid, inst->queue_total,
inst->copy_mode, inst->copy_range,
inst->queue_dropped, inst->queue_user_dropped,
- atomic_read(&inst->id_sequence),
- atomic_read(&inst->use));
+ inst->id_sequence, 1);
}
static const struct seq_operations nfqnl_seq_ops = {
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index b6160e41eb1..8d4fca96a4a 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -34,12 +34,21 @@ MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
+struct compat_delta {
+ struct compat_delta *next;
+ unsigned int offset;
+ short delta;
+};
+
struct xt_af {
struct mutex mutex;
struct list_head match;
struct list_head target;
struct list_head tables;
+#ifdef CONFIG_COMPAT
struct mutex compat_mutex;
+ struct compat_delta *compat_offsets;
+#endif
};
static struct xt_af *xt;
@@ -335,6 +344,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
EXPORT_SYMBOL_GPL(xt_check_match);
#ifdef CONFIG_COMPAT
+int xt_compat_add_offset(int af, unsigned int offset, short delta)
+{
+ struct compat_delta *tmp;
+
+ tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ tmp->offset = offset;
+ tmp->delta = delta;
+
+ if (xt[af].compat_offsets) {
+ tmp->next = xt[af].compat_offsets->next;
+ xt[af].compat_offsets->next = tmp;
+ } else {
+ xt[af].compat_offsets = tmp;
+ tmp->next = NULL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(xt_compat_add_offset);
+
+void xt_compat_flush_offsets(int af)
+{
+ struct compat_delta *tmp, *next;
+
+ if (xt[af].compat_offsets) {
+ for (tmp = xt[af].compat_offsets; tmp; tmp = next) {
+ next = tmp->next;
+ kfree(tmp);
+ }
+ xt[af].compat_offsets = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
+
+short xt_compat_calc_jump(int af, unsigned int offset)
+{
+ struct compat_delta *tmp;
+ short delta;
+
+ for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
+ if (tmp->offset < offset)
+ delta += tmp->delta;
+ return delta;
+}
+EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
+
int xt_compat_match_offset(struct xt_match *match)
{
u_int16_t csize = match->compatsize ? : match->matchsize;
@@ -342,8 +399,8 @@ int xt_compat_match_offset(struct xt_match *match)
}
EXPORT_SYMBOL_GPL(xt_compat_match_offset);
-void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
- int *size)
+int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+ int *size)
{
struct xt_match *match = m->u.kernel.match;
struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
@@ -365,6 +422,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
*size += off;
*dstptr += msize;
+ return 0;
}
EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
@@ -499,7 +557,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
return NULL;
- newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL);
+ newinfo = kzalloc(XT_TABLE_INFO_SZ, GFP_KERNEL);
if (!newinfo)
return NULL;
@@ -872,6 +930,7 @@ static int __init xt_init(void)
mutex_init(&xt[i].mutex);
#ifdef CONFIG_COMPAT
mutex_init(&xt[i].compat_mutex);
+ xt[i].compat_offsets = NULL;
#endif
INIT_LIST_HEAD(&xt[i].target);
INIT_LIST_HEAD(&xt[i].match);
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 77eeae658d4..77a52bf8322 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -22,17 +22,14 @@
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("iptables qdisc classification target module");
+MODULE_DESCRIPTION("Xtables: Qdisc classification");
MODULE_ALIAS("ipt_CLASSIFY");
MODULE_ALIAS("ip6t_CLASSIFY");
static unsigned int
-target(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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
const struct xt_classify_target_info *clinfo = targinfo;
@@ -40,42 +37,41 @@ target(struct sk_buff *skb,
return XT_CONTINUE;
}
-static struct xt_target xt_classify_target[] __read_mostly = {
+static struct xt_target classify_tg_reg[] __read_mostly = {
{
.family = AF_INET,
.name = "CLASSIFY",
- .target = target,
+ .target = classify_tg,
.targetsize = sizeof(struct xt_classify_target_info),
.table = "mangle",
- .hooks = (1 << NF_IP_LOCAL_OUT) |
- (1 << NF_IP_FORWARD) |
- (1 << NF_IP_POST_ROUTING),
+ .hooks = (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_FORWARD) |
+ (1 << NF_INET_POST_ROUTING),
.me = THIS_MODULE,
},
{
.name = "CLASSIFY",
.family = AF_INET6,
- .target = target,
+ .target = classify_tg,
.targetsize = sizeof(struct xt_classify_target_info),
.table = "mangle",
- .hooks = (1 << NF_IP6_LOCAL_OUT) |
- (1 << NF_IP6_FORWARD) |
- (1 << NF_IP6_POST_ROUTING),
+ .hooks = (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_FORWARD) |
+ (1 << NF_INET_POST_ROUTING),
.me = THIS_MODULE,
},
};
-static int __init xt_classify_init(void)
+static int __init classify_tg_init(void)
{
- return xt_register_targets(xt_classify_target,
- ARRAY_SIZE(xt_classify_target));
+ return xt_register_targets(classify_tg_reg,
+ ARRAY_SIZE(classify_tg_reg));
}
-static void __exit xt_classify_fini(void)
+static void __exit classify_tg_exit(void)
{
- xt_unregister_targets(xt_classify_target,
- ARRAY_SIZE(xt_classify_target));
+ xt_unregister_targets(classify_tg_reg, ARRAY_SIZE(classify_tg_reg));
}
-module_init(xt_classify_init);
-module_exit(xt_classify_fini);
+module_init(classify_tg_init);
+module_exit(classify_tg_exit);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 0621ca7de3b..5fecfb4794b 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -1,8 +1,10 @@
-/* This kernel module is used to modify the connection mark values, or
- * to optionally restore the skb nfmark from the connection mark
+/*
+ * xt_CONNMARK - Netfilter module to modify the connection mark values
*
- * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
- * by Henrik Nordstrom <hno@marasystems.com>
+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ * Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ * Jan Engelhardt <jengelh@computergmbh.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +26,7 @@
#include <net/checksum.h>
MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
-MODULE_DESCRIPTION("IP tables CONNMARK matching module");
+MODULE_DESCRIPTION("Xtables: connection mark modification");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_CONNMARK");
MODULE_ALIAS("ip6t_CONNMARK");
@@ -34,12 +36,9 @@ MODULE_ALIAS("ip6t_CONNMARK");
#include <net/netfilter/nf_conntrack_ecache.h>
static unsigned int
-target(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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
const struct xt_connmark_target_info *markinfo = targinfo;
struct nf_conn *ct;
@@ -77,12 +76,50 @@ target(struct sk_buff *skb,
return XT_CONTINUE;
}
+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)
+{
+ const struct xt_connmark_tginfo1 *info = targinfo;
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct;
+ u_int32_t newmark;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct == NULL)
+ return XT_CONTINUE;
+
+ switch (info->mode) {
+ case XT_CONNMARK_SET:
+ newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
+ if (ct->mark != newmark) {
+ ct->mark = newmark;
+ nf_conntrack_event_cache(IPCT_MARK, skb);
+ }
+ break;
+ case XT_CONNMARK_SAVE:
+ newmark = (ct->mark & ~info->ctmask) ^
+ (skb->mark & info->nfmask);
+ if (ct->mark != newmark) {
+ ct->mark = newmark;
+ nf_conntrack_event_cache(IPCT_MARK, skb);
+ }
+ break;
+ case XT_CONNMARK_RESTORE:
+ newmark = (skb->mark & ~info->nfmask) ^
+ (ct->mark & info->ctmask);
+ skb->mark = newmark;
+ break;
+ }
+
+ return XT_CONTINUE;
+}
+
static bool
-checkentry(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+connmark_tg_check_v0(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
const struct xt_connmark_target_info *matchinfo = targinfo;
@@ -100,14 +137,27 @@ checkentry(const char *tablename,
}
if (nf_ct_l3proto_try_module_get(target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", target->family);
+ "proto=%u\n", target->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)
+{
+ if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ printk(KERN_WARNING "cannot load conntrack support for "
+ "proto=%u\n", target->family);
return false;
}
return true;
}
static void
-destroy(const struct xt_target *target, void *targinfo)
+connmark_tg_destroy(const struct xt_target *target, void *targinfo)
{
nf_ct_l3proto_module_put(target->family);
}
@@ -120,7 +170,7 @@ struct compat_xt_connmark_target_info {
u_int16_t __pad2;
};
-static void compat_from_user(void *dst, void *src)
+static void connmark_tg_compat_from_user_v0(void *dst, void *src)
{
const struct compat_xt_connmark_target_info *cm = src;
struct xt_connmark_target_info m = {
@@ -131,7 +181,7 @@ static void compat_from_user(void *dst, void *src)
memcpy(dst, &m, sizeof(m));
}
-static int compat_to_user(void __user *dst, void *src)
+static int connmark_tg_compat_to_user_v0(void __user *dst, void *src)
{
const struct xt_connmark_target_info *m = src;
struct compat_xt_connmark_target_info cm = {
@@ -143,43 +193,69 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_target xt_connmark_target[] __read_mostly = {
+static struct xt_target connmark_tg_reg[] __read_mostly = {
{
.name = "CONNMARK",
+ .revision = 0,
.family = AF_INET,
- .checkentry = checkentry,
- .destroy = destroy,
- .target = target,
+ .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 = compat_from_user,
- .compat_to_user = compat_to_user,
+ .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 = 0,
.family = AF_INET6,
- .checkentry = checkentry,
- .destroy = destroy,
- .target = target,
+ .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,
+ .checkentry = connmark_tg_check,
+ .target = connmark_tg,
+ .targetsize = sizeof(struct xt_connmark_tginfo1),
+ .destroy = connmark_tg_destroy,
+ .me = THIS_MODULE,
+ },
};
-static int __init xt_connmark_init(void)
+static int __init connmark_tg_init(void)
{
- return xt_register_targets(xt_connmark_target,
- ARRAY_SIZE(xt_connmark_target));
+ return xt_register_targets(connmark_tg_reg,
+ ARRAY_SIZE(connmark_tg_reg));
}
-static void __exit xt_connmark_fini(void)
+static void __exit connmark_tg_exit(void)
{
- xt_unregister_targets(xt_connmark_target,
- ARRAY_SIZE(xt_connmark_target));
+ xt_unregister_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
}
-module_init(xt_connmark_init);
-module_exit(xt_connmark_fini);
+module_init(connmark_tg_init);
+module_exit(connmark_tg_exit);
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index d8feba9bdb4..1faa9136195 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -20,12 +20,13 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_CONNSECMARK.h>
#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
#define PFX "CONNSECMARK: "
MODULE_LICENSE("GPL");
MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
-MODULE_DESCRIPTION("ip[6]tables CONNSECMARK module");
+MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark");
MODULE_ALIAS("ipt_CONNSECMARK");
MODULE_ALIAS("ip6t_CONNSECMARK");
@@ -40,8 +41,10 @@ static void secmark_save(const struct sk_buff *skb)
enum ip_conntrack_info ctinfo;
ct = nf_ct_get(skb, &ctinfo);
- if (ct && !ct->secmark)
+ if (ct && !ct->secmark) {
ct->secmark = skb->secmark;
+ nf_conntrack_event_cache(IPCT_SECMARK, skb);
+ }
}
}
@@ -61,10 +64,10 @@ static void secmark_restore(struct sk_buff *skb)
}
}
-static unsigned int target(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)
+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)
{
const struct xt_connsecmark_target_info *info = targinfo;
@@ -84,9 +87,10 @@ static unsigned int target(struct sk_buff *skb, const struct net_device *in,
return XT_CONTINUE;
}
-static bool checkentry(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool
+connsecmark_tg_check(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
const struct xt_connsecmark_target_info *info = targinfo;
@@ -102,25 +106,25 @@ static bool checkentry(const char *tablename, const void *entry,
if (nf_ct_l3proto_try_module_get(target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", target->family);
+ "proto=%u\n", target->family);
return false;
}
return true;
}
static void
-destroy(const struct xt_target *target, void *targinfo)
+connsecmark_tg_destroy(const struct xt_target *target, void *targinfo)
{
nf_ct_l3proto_module_put(target->family);
}
-static struct xt_target xt_connsecmark_target[] __read_mostly = {
+static struct xt_target connsecmark_tg_reg[] __read_mostly = {
{
.name = "CONNSECMARK",
.family = AF_INET,
- .checkentry = checkentry,
- .destroy = destroy,
- .target = target,
+ .checkentry = connsecmark_tg_check,
+ .destroy = connsecmark_tg_destroy,
+ .target = connsecmark_tg,
.targetsize = sizeof(struct xt_connsecmark_target_info),
.table = "mangle",
.me = THIS_MODULE,
@@ -128,26 +132,26 @@ static struct xt_target xt_connsecmark_target[] __read_mostly = {
{
.name = "CONNSECMARK",
.family = AF_INET6,
- .checkentry = checkentry,
- .destroy = destroy,
- .target = target,
+ .checkentry = connsecmark_tg_check,
+ .destroy = connsecmark_tg_destroy,
+ .target = connsecmark_tg,
.targetsize = sizeof(struct xt_connsecmark_target_info),
.table = "mangle",
.me = THIS_MODULE,
},
};
-static int __init xt_connsecmark_init(void)
+static int __init connsecmark_tg_init(void)
{
- return xt_register_targets(xt_connsecmark_target,
- ARRAY_SIZE(xt_connsecmark_target));
+ return xt_register_targets(connsecmark_tg_reg,
+ ARRAY_SIZE(connsecmark_tg_reg));
}
-static void __exit xt_connsecmark_fini(void)
+static void __exit connsecmark_tg_exit(void)
{
- xt_unregister_targets(xt_connsecmark_target,
- ARRAY_SIZE(xt_connsecmark_target));
+ xt_unregister_targets(connsecmark_tg_reg,
+ ARRAY_SIZE(connsecmark_tg_reg));
}
-module_init(xt_connsecmark_init);
-module_exit(xt_connsecmark_fini);
+module_init(connsecmark_tg_init);
+module_exit(connsecmark_tg_exit);
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 6322a933ab7..97efd74c04f 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -18,19 +18,20 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_DSCP.h>
+#include <linux/netfilter_ipv4/ipt_TOS.h>
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("x_tables DSCP modification module");
+MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_DSCP");
MODULE_ALIAS("ip6t_DSCP");
+MODULE_ALIAS("ipt_TOS");
+MODULE_ALIAS("ip6t_TOS");
-static unsigned int target(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)
+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)
{
const struct xt_DSCP_info *dinfo = targinfo;
u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -46,12 +47,10 @@ static unsigned int target(struct sk_buff *skb,
return XT_CONTINUE;
}
-static unsigned int target6(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)
+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)
{
const struct xt_DSCP_info *dinfo = targinfo;
u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -66,11 +65,10 @@ static unsigned int target6(struct sk_buff *skb,
return XT_CONTINUE;
}
-static bool checkentry(const char *tablename,
- const void *e_void,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool
+dscp_tg_check(const char *tablename, const void *e_void,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp;
@@ -81,12 +79,95 @@ static bool checkentry(const char *tablename,
return true;
}
-static struct xt_target xt_dscp_target[] __read_mostly = {
+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)
+{
+ const struct ipt_tos_target_info *info = targinfo;
+ struct iphdr *iph = ip_hdr(skb);
+ u_int8_t oldtos;
+
+ if ((iph->tos & IPTOS_TOS_MASK) != info->tos) {
+ if (!skb_make_writable(skb, sizeof(struct iphdr)))
+ return NF_DROP;
+
+ iph = ip_hdr(skb);
+ oldtos = iph->tos;
+ iph->tos = (iph->tos & IPTOS_PREC_MASK) | info->tos;
+ csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
+ }
+
+ 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)
+{
+ const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos;
+
+ if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT &&
+ tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST &&
+ tos != IPTOS_NORMALSVC) {
+ printk(KERN_WARNING "TOS: bad tos value %#x\n", tos);
+ return false;
+ }
+
+ return true;
+}
+
+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)
+{
+ const struct xt_tos_target_info *info = targinfo;
+ struct iphdr *iph = ip_hdr(skb);
+ u_int8_t orig, nv;
+
+ orig = ipv4_get_dsfield(iph);
+ nv = (orig & ~info->tos_mask) ^ info->tos_value;
+
+ if (orig != nv) {
+ if (!skb_make_writable(skb, sizeof(struct iphdr)))
+ return NF_DROP;
+ iph = ip_hdr(skb);
+ ipv4_change_dsfield(iph, 0, nv);
+ }
+
+ return XT_CONTINUE;
+}
+
+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)
+{
+ const struct xt_tos_target_info *info = targinfo;
+ struct ipv6hdr *iph = ipv6_hdr(skb);
+ u_int8_t orig, nv;
+
+ orig = ipv6_get_dsfield(iph);
+ nv = (orig & info->tos_mask) ^ info->tos_value;
+
+ if (orig != nv) {
+ if (!skb_make_writable(skb, sizeof(struct iphdr)))
+ return NF_DROP;
+ iph = ipv6_hdr(skb);
+ ipv6_change_dsfield(iph, 0, nv);
+ }
+
+ return XT_CONTINUE;
+}
+
+static struct xt_target dscp_tg_reg[] __read_mostly = {
{
.name = "DSCP",
.family = AF_INET,
- .checkentry = checkentry,
- .target = target,
+ .checkentry = dscp_tg_check,
+ .target = dscp_tg,
.targetsize = sizeof(struct xt_DSCP_info),
.table = "mangle",
.me = THIS_MODULE,
@@ -94,23 +175,51 @@ static struct xt_target xt_dscp_target[] __read_mostly = {
{
.name = "DSCP",
.family = AF_INET6,
- .checkentry = checkentry,
- .target = target6,
+ .checkentry = dscp_tg_check,
+ .target = dscp_tg6,
.targetsize = sizeof(struct xt_DSCP_info),
.table = "mangle",
.me = THIS_MODULE,
},
+ {
+ .name = "TOS",
+ .revision = 0,
+ .family = AF_INET,
+ .table = "mangle",
+ .target = tos_tg_v0,
+ .targetsize = sizeof(struct ipt_tos_target_info),
+ .checkentry = tos_tg_check_v0,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "TOS",
+ .revision = 1,
+ .family = AF_INET,
+ .table = "mangle",
+ .target = tos_tg,
+ .targetsize = sizeof(struct xt_tos_target_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "TOS",
+ .revision = 1,
+ .family = AF_INET6,
+ .table = "mangle",
+ .target = tos_tg6,
+ .targetsize = sizeof(struct xt_tos_target_info),
+ .me = THIS_MODULE,
+ },
};
-static int __init xt_dscp_target_init(void)
+static int __init dscp_tg_init(void)
{
- return xt_register_targets(xt_dscp_target, ARRAY_SIZE(xt_dscp_target));
+ return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg));
}
-static void __exit xt_dscp_target_fini(void)
+static void __exit dscp_tg_exit(void)
{
- xt_unregister_targets(xt_dscp_target, ARRAY_SIZE(xt_dscp_target));
+ xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg));
}
-module_init(xt_dscp_target_init);
-module_exit(xt_dscp_target_fini);
+module_init(dscp_tg_init);
+module_exit(dscp_tg_exit);
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index bc6503d77d7..f9ce20b5898 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -1,10 +1,13 @@
-/* This is a module which is used for setting the NFMARK field of an skb. */
-
-/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+/*
+ * xt_MARK - Netfilter module to modify the NFMARK field of an skb
+ *
+ * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+ * Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ * Jan Engelhardt <jengelh@computergmbh.de>
*
- * 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 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>
@@ -17,17 +20,14 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-MODULE_DESCRIPTION("ip[6]tables MARK modification module");
+MODULE_DESCRIPTION("Xtables: packet mark modification");
MODULE_ALIAS("ipt_MARK");
MODULE_ALIAS("ip6t_MARK");
static unsigned int
-target_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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
const struct xt_mark_target_info *markinfo = targinfo;
@@ -36,12 +36,9 @@ target_v0(struct sk_buff *skb,
}
static unsigned int
-target_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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
const struct xt_mark_target_info_v1 *markinfo = targinfo;
int mark = 0;
@@ -64,13 +61,21 @@ target_v1(struct sk_buff *skb,
return XT_CONTINUE;
}
+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)
+{
+ const struct xt_mark_tginfo2 *info = targinfo;
+
+ skb->mark = (skb->mark & ~info->mask) ^ info->mark;
+ return XT_CONTINUE;
+}
static bool
-checkentry_v0(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+mark_tg_check_v0(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
const struct xt_mark_target_info *markinfo = targinfo;
@@ -82,11 +87,9 @@ checkentry_v0(const char *tablename,
}
static bool
-checkentry_v1(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+mark_tg_check_v1(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
const struct xt_mark_target_info_v1 *markinfo = targinfo;
@@ -105,6 +108,28 @@ checkentry_v1(const char *tablename,
}
#ifdef CONFIG_COMPAT
+struct compat_xt_mark_target_info {
+ compat_ulong_t mark;
+};
+
+static void mark_tg_compat_from_user_v0(void *dst, void *src)
+{
+ const struct compat_xt_mark_target_info *cm = src;
+ struct xt_mark_target_info m = {
+ .mark = cm->mark,
+ };
+ memcpy(dst, &m, sizeof(m));
+}
+
+static int mark_tg_compat_to_user_v0(void __user *dst, void *src)
+{
+ const struct xt_mark_target_info *m = src;
+ struct compat_xt_mark_target_info cm = {
+ .mark = m->mark,
+ };
+ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+
struct compat_xt_mark_target_info_v1 {
compat_ulong_t mark;
u_int8_t mode;
@@ -112,7 +137,7 @@ struct compat_xt_mark_target_info_v1 {
u_int16_t __pad2;
};
-static void compat_from_user_v1(void *dst, void *src)
+static void mark_tg_compat_from_user_v1(void *dst, void *src)
{
const struct compat_xt_mark_target_info_v1 *cm = src;
struct xt_mark_target_info_v1 m = {
@@ -122,7 +147,7 @@ static void compat_from_user_v1(void *dst, void *src)
memcpy(dst, &m, sizeof(m));
}
-static int compat_to_user_v1(void __user *dst, void *src)
+static int mark_tg_compat_to_user_v1(void __user *dst, void *src)
{
const struct xt_mark_target_info_v1 *m = src;
struct compat_xt_mark_target_info_v1 cm = {
@@ -133,14 +158,19 @@ static int compat_to_user_v1(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_target xt_mark_target[] __read_mostly = {
+static struct xt_target mark_tg_reg[] __read_mostly = {
{
.name = "MARK",
.family = AF_INET,
.revision = 0,
- .checkentry = checkentry_v0,
- .target = target_v0,
+ .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,
},
@@ -148,13 +178,13 @@ static struct xt_target xt_mark_target[] __read_mostly = {
.name = "MARK",
.family = AF_INET,
.revision = 1,
- .checkentry = checkentry_v1,
- .target = target_v1,
+ .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 = compat_from_user_v1,
- .compat_to_user = compat_to_user_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,
@@ -163,23 +193,59 @@ static struct xt_target xt_mark_target[] __read_mostly = {
.name = "MARK",
.family = AF_INET6,
.revision = 0,
- .checkentry = checkentry_v0,
- .target = target_v0,
+ .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,
+ .target = mark_tg,
+ .targetsize = sizeof(struct xt_mark_tginfo2),
+ .me = THIS_MODULE,
+ },
};
-static int __init xt_mark_init(void)
+static int __init mark_tg_init(void)
{
- return xt_register_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
+ return xt_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
}
-static void __exit xt_mark_fini(void)
+static void __exit mark_tg_exit(void)
{
- xt_unregister_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
+ xt_unregister_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
}
-module_init(xt_mark_init);
-module_exit(xt_mark_fini);
+module_init(mark_tg_init);
+module_exit(mark_tg_exit);
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index 9fb449ffbf8..19ae8efae65 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -12,18 +12,18 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_NFLOG.h>
+#include <net/netfilter/nf_log.h>
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_DESCRIPTION("x_tables NFLOG target");
+MODULE_DESCRIPTION("Xtables: packet logging to netlink using NFLOG");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_NFLOG");
MODULE_ALIAS("ip6t_NFLOG");
static unsigned int
-nflog_target(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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
const struct xt_nflog_info *info = targinfo;
struct nf_loginfo li;
@@ -39,9 +39,9 @@ nflog_target(struct sk_buff *skb,
}
static bool
-nflog_checkentry(const char *tablename, const void *entry,
- const struct xt_target *target, void *targetinfo,
- unsigned int hookmask)
+nflog_tg_check(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targetinfo,
+ unsigned int hookmask)
{
const struct xt_nflog_info *info = targetinfo;
@@ -52,35 +52,34 @@ nflog_checkentry(const char *tablename, const void *entry,
return true;
}
-static struct xt_target xt_nflog_target[] __read_mostly = {
+static struct xt_target nflog_tg_reg[] __read_mostly = {
{
.name = "NFLOG",
.family = AF_INET,
- .checkentry = nflog_checkentry,
- .target = nflog_target,
+ .checkentry = nflog_tg_check,
+ .target = nflog_tg,
.targetsize = sizeof(struct xt_nflog_info),
.me = THIS_MODULE,
},
{
.name = "NFLOG",
.family = AF_INET6,
- .checkentry = nflog_checkentry,
- .target = nflog_target,
+ .checkentry = nflog_tg_check,
+ .target = nflog_tg,
.targetsize = sizeof(struct xt_nflog_info),
.me = THIS_MODULE,
},
};
-static int __init xt_nflog_init(void)
+static int __init nflog_tg_init(void)
{
- return xt_register_targets(xt_nflog_target,
- ARRAY_SIZE(xt_nflog_target));
+ return xt_register_targets(nflog_tg_reg, ARRAY_SIZE(nflog_tg_reg));
}
-static void __exit xt_nflog_fini(void)
+static void __exit nflog_tg_exit(void)
{
- xt_unregister_targets(xt_nflog_target, ARRAY_SIZE(xt_nflog_target));
+ xt_unregister_targets(nflog_tg_reg, ARRAY_SIZE(nflog_tg_reg));
}
-module_init(xt_nflog_init);
-module_exit(xt_nflog_fini);
+module_init(nflog_tg_init);
+module_exit(nflog_tg_exit);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index c3984e9f766..beb24d19a56 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -17,59 +17,55 @@
#include <linux/netfilter/xt_NFQUEUE.h>
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target");
+MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_NFQUEUE");
MODULE_ALIAS("ip6t_NFQUEUE");
MODULE_ALIAS("arpt_NFQUEUE");
static unsigned int
-target(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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
const struct xt_NFQ_info *tinfo = targinfo;
return NF_QUEUE_NR(tinfo->queuenum);
}
-static struct xt_target xt_nfqueue_target[] __read_mostly = {
+static struct xt_target nfqueue_tg_reg[] __read_mostly = {
{
.name = "NFQUEUE",
.family = AF_INET,
- .target = target,
+ .target = nfqueue_tg,
.targetsize = sizeof(struct xt_NFQ_info),
.me = THIS_MODULE,
},
{
.name = "NFQUEUE",
.family = AF_INET6,
- .target = target,
+ .target = nfqueue_tg,
.targetsize = sizeof(struct xt_NFQ_info),
.me = THIS_MODULE,
},
{
.name = "NFQUEUE",
.family = NF_ARP,
- .target = target,
+ .target = nfqueue_tg,
.targetsize = sizeof(struct xt_NFQ_info),
.me = THIS_MODULE,
},
};
-static int __init xt_nfqueue_init(void)
+static int __init nfqueue_tg_init(void)
{
- return xt_register_targets(xt_nfqueue_target,
- ARRAY_SIZE(xt_nfqueue_target));
+ return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
}
-static void __exit xt_nfqueue_fini(void)
+static void __exit nfqueue_tg_exit(void)
{
- xt_unregister_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target));
+ xt_unregister_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
}
-module_init(xt_nfqueue_init);
-module_exit(xt_nfqueue_fini);
+module_init(nfqueue_tg_init);
+module_exit(nfqueue_tg_exit);
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 4976ce18661..6c9de611eb8 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -7,17 +7,15 @@
#include <linux/netfilter/x_tables.h>
#include <net/netfilter/nf_conntrack.h>
+MODULE_DESCRIPTION("Xtables: Disabling connection tracking for packets");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_NOTRACK");
MODULE_ALIAS("ip6t_NOTRACK");
static unsigned int
-target(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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
/* Previously seen (loopback)? Ignore. */
if (skb->nfct != NULL)
@@ -34,33 +32,32 @@ target(struct sk_buff *skb,
return XT_CONTINUE;
}
-static struct xt_target xt_notrack_target[] __read_mostly = {
+static struct xt_target notrack_tg_reg[] __read_mostly = {
{
.name = "NOTRACK",
.family = AF_INET,
- .target = target,
+ .target = notrack_tg,
.table = "raw",
.me = THIS_MODULE,
},
{
.name = "NOTRACK",
.family = AF_INET6,
- .target = target,
+ .target = notrack_tg,
.table = "raw",
.me = THIS_MODULE,
},
};
-static int __init xt_notrack_init(void)
+static int __init notrack_tg_init(void)
{
- return xt_register_targets(xt_notrack_target,
- ARRAY_SIZE(xt_notrack_target));
+ return xt_register_targets(notrack_tg_reg, ARRAY_SIZE(notrack_tg_reg));
}
-static void __exit xt_notrack_fini(void)
+static void __exit notrack_tg_exit(void)
{
- xt_unregister_targets(xt_notrack_target, ARRAY_SIZE(xt_notrack_target));
+ xt_unregister_targets(notrack_tg_reg, ARRAY_SIZE(notrack_tg_reg));
}
-module_init(xt_notrack_init);
-module_exit(xt_notrack_fini);
+module_init(notrack_tg_init);
+module_exit(notrack_tg_exit);
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
new file mode 100644
index 00000000000..24c73ba31ea
--- /dev/null
+++ b/net/netfilter/xt_RATEEST.c
@@ -0,0 +1,205 @@
+/*
+ * (C) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * 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/gen_stats.h>
+#include <linux/jhash.h>
+#include <linux/rtnetlink.h>
+#include <linux/random.h>
+#include <net/gen_stats.h>
+#include <net/netlink.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_RATEEST.h>
+#include <net/netfilter/xt_rateest.h>
+
+static DEFINE_MUTEX(xt_rateest_mutex);
+
+#define RATEEST_HSIZE 16
+static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly;
+static unsigned int jhash_rnd __read_mostly;
+
+static unsigned int xt_rateest_hash(const char *name)
+{
+ return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) &
+ (RATEEST_HSIZE - 1);
+}
+
+static void xt_rateest_hash_insert(struct xt_rateest *est)
+{
+ unsigned int h;
+
+ h = xt_rateest_hash(est->name);
+ hlist_add_head(&est->list, &rateest_hash[h]);
+}
+
+struct xt_rateest *xt_rateest_lookup(const char *name)
+{
+ struct xt_rateest *est;
+ struct hlist_node *n;
+ unsigned int h;
+
+ h = xt_rateest_hash(name);
+ mutex_lock(&xt_rateest_mutex);
+ hlist_for_each_entry(est, n, &rateest_hash[h], list) {
+ if (strcmp(est->name, name) == 0) {
+ est->refcnt++;
+ mutex_unlock(&xt_rateest_mutex);
+ return est;
+ }
+ }
+ mutex_unlock(&xt_rateest_mutex);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(xt_rateest_lookup);
+
+void xt_rateest_put(struct xt_rateest *est)
+{
+ mutex_lock(&xt_rateest_mutex);
+ if (--est->refcnt == 0) {
+ hlist_del(&est->list);
+ gen_kill_estimator(&est->bstats, &est->rstats);
+ kfree(est);
+ }
+ mutex_unlock(&xt_rateest_mutex);
+}
+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)
+{
+ const struct xt_rateest_target_info *info = targinfo;
+ struct gnet_stats_basic *stats = &info->est->bstats;
+
+ spin_lock_bh(&info->est->lock);
+ stats->bytes += skb->len;
+ stats->packets++;
+ spin_unlock_bh(&info->est->lock);
+
+ 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)
+{
+ struct xt_rateest_target_info *info = (void *)targinfo;
+ struct xt_rateest *est;
+ struct {
+ struct nlattr opt;
+ struct gnet_estimator est;
+ } cfg;
+
+ est = xt_rateest_lookup(info->name);
+ if (est) {
+ /*
+ * If estimator parameters are specified, they must match the
+ * existing estimator.
+ */
+ if ((!info->interval && !info->ewma_log) ||
+ (info->interval != est->params.interval ||
+ info->ewma_log != est->params.ewma_log)) {
+ xt_rateest_put(est);
+ return false;
+ }
+ info->est = est;
+ return true;
+ }
+
+ est = kzalloc(sizeof(*est), GFP_KERNEL);
+ if (!est)
+ goto err1;
+
+ strlcpy(est->name, info->name, sizeof(est->name));
+ spin_lock_init(&est->lock);
+ est->refcnt = 1;
+ est->params.interval = info->interval;
+ est->params.ewma_log = info->ewma_log;
+
+ cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est));
+ cfg.opt.nla_type = TCA_STATS_RATE_EST;
+ cfg.est.interval = info->interval;
+ cfg.est.ewma_log = info->ewma_log;
+
+ if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock,
+ &cfg.opt) < 0)
+ goto err2;
+
+ info->est = est;
+ xt_rateest_hash_insert(est);
+
+ return true;
+
+err2:
+ kfree(est);
+err1:
+ return false;
+}
+
+static void xt_rateest_tg_destroy(const struct xt_target *target,
+ void *targinfo)
+{
+ struct xt_rateest_target_info *info = 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 int __init xt_rateest_tg_init(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(rateest_hash); i++)
+ 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));
+}
+
+static void __exit xt_rateest_tg_fini(void)
+{
+ xt_unregister_targets(xt_rateest_target, ARRAY_SIZE(xt_rateest_target));
+}
+
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Xtables: packet rate estimator");
+MODULE_ALIAS("ipt_RATEEST");
+MODULE_ALIAS("ip6t_RATEEST");
+module_init(xt_rateest_tg_init);
+module_exit(xt_rateest_tg_fini);
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 235806eb6ec..b11b3ecbb39 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -20,7 +20,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
-MODULE_DESCRIPTION("ip[6]tables SECMARK modification module");
+MODULE_DESCRIPTION("Xtables: packet security mark modification");
MODULE_ALIAS("ipt_SECMARK");
MODULE_ALIAS("ip6t_SECMARK");
@@ -28,10 +28,10 @@ MODULE_ALIAS("ip6t_SECMARK");
static u8 mode;
-static unsigned int target(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)
+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)
{
u32 secmark = 0;
const struct xt_secmark_target_info *info = targinfo;
@@ -81,9 +81,10 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
return true;
}
-static bool checkentry(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool
+secmark_tg_check(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
struct xt_secmark_target_info *info = targinfo;
@@ -109,12 +110,12 @@ static bool checkentry(const char *tablename, const void *entry,
return true;
}
-static struct xt_target xt_secmark_target[] __read_mostly = {
+static struct xt_target secmark_tg_reg[] __read_mostly = {
{
.name = "SECMARK",
.family = AF_INET,
- .checkentry = checkentry,
- .target = target,
+ .checkentry = secmark_tg_check,
+ .target = secmark_tg,
.targetsize = sizeof(struct xt_secmark_target_info),
.table = "mangle",
.me = THIS_MODULE,
@@ -122,24 +123,23 @@ static struct xt_target xt_secmark_target[] __read_mostly = {
{
.name = "SECMARK",
.family = AF_INET6,
- .checkentry = checkentry,
- .target = target,
+ .checkentry = secmark_tg_check,
+ .target = secmark_tg,
.targetsize = sizeof(struct xt_secmark_target_info),
.table = "mangle",
.me = THIS_MODULE,
},
};
-static int __init xt_secmark_init(void)
+static int __init secmark_tg_init(void)
{
- return xt_register_targets(xt_secmark_target,
- ARRAY_SIZE(xt_secmark_target));
+ return xt_register_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
}
-static void __exit xt_secmark_fini(void)
+static void __exit secmark_tg_exit(void)
{
- xt_unregister_targets(xt_secmark_target, ARRAY_SIZE(xt_secmark_target));
+ xt_unregister_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
}
-module_init(xt_secmark_init);
-module_exit(xt_secmark_fini);
+module_init(secmark_tg_init);
+module_exit(secmark_tg_exit);
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 8e76d1f52fb..60e3767cc71 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -24,7 +24,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-MODULE_DESCRIPTION("x_tables TCP MSS modification module");
+MODULE_DESCRIPTION("Xtables: TCP Maximum Segment Size (MSS) adjustment");
MODULE_ALIAS("ipt_TCPMSS");
MODULE_ALIAS("ip6t_TCPMSS");
@@ -88,15 +88,19 @@ tcpmss_mangle_packet(struct sk_buff *skb,
oldmss = (opt[i+2] << 8) | opt[i+3];
- if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
- oldmss <= newmss)
+ /* Never increase MSS, even when setting it, as
+ * doing so results in problems for hosts that rely
+ * on MSS being set correctly.
+ */
+ if (oldmss <= newmss)
return 0;
opt[i+2] = (newmss & 0xff00) >> 8;
opt[i+3] = newmss & 0x00ff;
- nf_proto_csum_replace2(&tcph->check, skb,
- htons(oldmss), htons(newmss), 0);
+ inet_proto_csum_replace2(&tcph->check, skb,
+ htons(oldmss), htons(newmss),
+ 0);
return 0;
}
}
@@ -117,29 +121,26 @@ tcpmss_mangle_packet(struct sk_buff *skb,
opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
- nf_proto_csum_replace2(&tcph->check, skb,
- htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
+ inet_proto_csum_replace2(&tcph->check, skb,
+ htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
opt[0] = TCPOPT_MSS;
opt[1] = TCPOLEN_MSS;
opt[2] = (newmss & 0xff00) >> 8;
opt[3] = newmss & 0x00ff;
- nf_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), 0);
+ inet_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), 0);
oldval = ((__be16 *)tcph)[6];
tcph->doff += TCPOLEN_MSS/4;
- nf_proto_csum_replace2(&tcph->check, skb,
- oldval, ((__be16 *)tcph)[6], 0);
+ inet_proto_csum_replace2(&tcph->check, skb,
+ oldval, ((__be16 *)tcph)[6], 0);
return TCPOLEN_MSS;
}
static unsigned int
-xt_tcpmss_target4(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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
struct iphdr *iph = ip_hdr(skb);
__be16 newlen;
@@ -152,7 +153,7 @@ xt_tcpmss_target4(struct sk_buff *skb,
if (ret > 0) {
iph = ip_hdr(skb);
newlen = htons(ntohs(iph->tot_len) + ret);
- nf_csum_replace2(&iph->check, iph->tot_len, newlen);
+ csum_replace2(&iph->check, iph->tot_len, newlen);
iph->tot_len = newlen;
}
return XT_CONTINUE;
@@ -160,12 +161,9 @@ xt_tcpmss_target4(struct sk_buff *skb,
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
static unsigned int
-xt_tcpmss_target6(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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
u8 nexthdr;
@@ -204,19 +202,17 @@ static inline bool find_syn_match(const struct xt_entry_match *m)
}
static bool
-xt_tcpmss_checkentry4(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+tcpmss_tg4_check(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
const struct xt_tcpmss_info *info = targinfo;
const struct ipt_entry *e = entry;
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
- (hook_mask & ~((1 << NF_IP_FORWARD) |
- (1 << NF_IP_LOCAL_OUT) |
- (1 << NF_IP_POST_ROUTING))) != 0) {
+ (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 "
"FORWARD, OUTPUT and POSTROUTING hooks\n");
return false;
@@ -229,19 +225,17 @@ xt_tcpmss_checkentry4(const char *tablename,
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
static bool
-xt_tcpmss_checkentry6(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+tcpmss_tg6_check(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
const struct xt_tcpmss_info *info = targinfo;
const struct ip6t_entry *e = entry;
if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
- (hook_mask & ~((1 << NF_IP6_FORWARD) |
- (1 << NF_IP6_LOCAL_OUT) |
- (1 << NF_IP6_POST_ROUTING))) != 0) {
+ (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 "
"FORWARD, OUTPUT and POSTROUTING hooks\n");
return false;
@@ -253,12 +247,12 @@ xt_tcpmss_checkentry6(const char *tablename,
}
#endif
-static struct xt_target xt_tcpmss_reg[] __read_mostly = {
+static struct xt_target tcpmss_tg_reg[] __read_mostly = {
{
.family = AF_INET,
.name = "TCPMSS",
- .checkentry = xt_tcpmss_checkentry4,
- .target = xt_tcpmss_target4,
+ .checkentry = tcpmss_tg4_check,
+ .target = tcpmss_tg4,
.targetsize = sizeof(struct xt_tcpmss_info),
.proto = IPPROTO_TCP,
.me = THIS_MODULE,
@@ -267,8 +261,8 @@ static struct xt_target xt_tcpmss_reg[] __read_mostly = {
{
.family = AF_INET6,
.name = "TCPMSS",
- .checkentry = xt_tcpmss_checkentry6,
- .target = xt_tcpmss_target6,
+ .checkentry = tcpmss_tg6_check,
+ .target = tcpmss_tg6,
.targetsize = sizeof(struct xt_tcpmss_info),
.proto = IPPROTO_TCP,
.me = THIS_MODULE,
@@ -276,15 +270,15 @@ static struct xt_target xt_tcpmss_reg[] __read_mostly = {
#endif
};
-static int __init xt_tcpmss_init(void)
+static int __init tcpmss_tg_init(void)
{
- return xt_register_targets(xt_tcpmss_reg, ARRAY_SIZE(xt_tcpmss_reg));
+ return xt_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg));
}
-static void __exit xt_tcpmss_fini(void)
+static void __exit tcpmss_tg_exit(void)
{
- xt_unregister_targets(xt_tcpmss_reg, ARRAY_SIZE(xt_tcpmss_reg));
+ xt_unregister_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg));
}
-module_init(xt_tcpmss_init);
-module_exit(xt_tcpmss_fini);
+module_init(tcpmss_tg_init);
+module_exit(tcpmss_tg_exit);
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
new file mode 100644
index 00000000000..3b2aa56833b
--- /dev/null
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -0,0 +1,147 @@
+/*
+ * A module for stripping a specific TCP option from TCP packets.
+ *
+ * Copyright (C) 2007 Sven Schnelle <svens@bitebene.org>
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ *
+ * 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 <linux/ipv6.h>
+#include <linux/tcp.h>
+#include <net/ipv6.h>
+#include <net/tcp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+
+static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset)
+{
+ /* Beware zero-length options: make finite progress */
+ if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
+ return 1;
+ else
+ return opt[offset+1];
+}
+
+static unsigned int
+tcpoptstrip_mangle_packet(struct sk_buff *skb,
+ const struct xt_tcpoptstrip_target_info *info,
+ unsigned int tcphoff, unsigned int minlen)
+{
+ unsigned int optl, i, j;
+ struct tcphdr *tcph;
+ u_int16_t n, o;
+ u_int8_t *opt;
+
+ if (!skb_make_writable(skb, skb->len))
+ return NF_DROP;
+
+ tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
+ opt = (u_int8_t *)tcph;
+
+ /*
+ * Walk through all TCP options - if we find some option to remove,
+ * set all octets to %TCPOPT_NOP and adjust checksum.
+ */
+ for (i = sizeof(struct tcphdr); i < tcp_hdrlen(skb); i += optl) {
+ optl = optlen(opt, i);
+
+ if (i + optl > tcp_hdrlen(skb))
+ break;
+
+ if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))
+ continue;
+
+ for (j = 0; j < optl; ++j) {
+ o = opt[i+j];
+ n = TCPOPT_NOP;
+ if ((i + j) % 2 == 0) {
+ o <<= 8;
+ n <<= 8;
+ }
+ inet_proto_csum_replace2(&tcph->check, skb, htons(o),
+ htons(n), 0);
+ }
+ memset(opt + i, TCPOPT_NOP, optl);
+ }
+
+ return XT_CONTINUE;
+}
+
+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)
+{
+ return tcpoptstrip_mangle_packet(skb, 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)
+{
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ unsigned int tcphoff;
+ u_int8_t nexthdr;
+
+ nexthdr = ipv6h->nexthdr;
+ tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr);
+ if (tcphoff < 0)
+ return NF_DROP;
+
+ return tcpoptstrip_mangle_packet(skb, targinfo, tcphoff,
+ sizeof(*ipv6h) + sizeof(struct tcphdr));
+}
+#endif
+
+static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = {
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = tcpoptstrip_tg4,
+ .targetsize = sizeof(struct xt_tcpoptstrip_target_info),
+ .me = THIS_MODULE,
+ },
+#if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE)
+ {
+ .name = "TCPOPTSTRIP",
+ .family = AF_INET6,
+ .table = "mangle",
+ .proto = IPPROTO_TCP,
+ .target = tcpoptstrip_tg6,
+ .targetsize = sizeof(struct xt_tcpoptstrip_target_info),
+ .me = THIS_MODULE,
+ },
+#endif
+};
+
+static int __init tcpoptstrip_tg_init(void)
+{
+ return xt_register_targets(tcpoptstrip_tg_reg,
+ ARRAY_SIZE(tcpoptstrip_tg_reg));
+}
+
+static void __exit tcpoptstrip_tg_exit(void)
+{
+ xt_unregister_targets(tcpoptstrip_tg_reg,
+ ARRAY_SIZE(tcpoptstrip_tg_reg));
+}
+
+module_init(tcpoptstrip_tg_init);
+module_exit(tcpoptstrip_tg_exit);
+MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>, Jan Engelhardt <jengelh@computergmbh.de>");
+MODULE_DESCRIPTION("Xtables: TCP option stripping");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TCPOPTSTRIP");
+MODULE_ALIAS("ip6t_TCPOPTSTRIP");
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
index 26c5d08ab2c..30dab79a343 100644
--- a/net/netfilter/xt_TRACE.c
+++ b/net/netfilter/xt_TRACE.c
@@ -5,49 +5,46 @@
#include <linux/netfilter/x_tables.h>
+MODULE_DESCRIPTION("Xtables: packet flow tracing");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_TRACE");
MODULE_ALIAS("ip6t_TRACE");
static unsigned int
-target(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 net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
{
skb->nf_trace = 1;
return XT_CONTINUE;
}
-static struct xt_target xt_trace_target[] __read_mostly = {
+static struct xt_target trace_tg_reg[] __read_mostly = {
{
.name = "TRACE",
.family = AF_INET,
- .target = target,
+ .target = trace_tg,
.table = "raw",
.me = THIS_MODULE,
},
{
.name = "TRACE",
.family = AF_INET6,
- .target = target,
+ .target = trace_tg,
.table = "raw",
.me = THIS_MODULE,
},
};
-static int __init xt_trace_init(void)
+static int __init trace_tg_init(void)
{
- return xt_register_targets(xt_trace_target,
- ARRAY_SIZE(xt_trace_target));
+ return xt_register_targets(trace_tg_reg, ARRAY_SIZE(trace_tg_reg));
}
-static void __exit xt_trace_fini(void)
+static void __exit trace_tg_exit(void)
{
- xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target));
+ xt_unregister_targets(trace_tg_reg, ARRAY_SIZE(trace_tg_reg));
}
-module_init(xt_trace_init);
-module_exit(xt_trace_fini);
+module_init(trace_tg_init);
+module_exit(trace_tg_exit);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 64bcdb0fe1e..89f47364e84 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -10,52 +10,47 @@
#include <linux/netfilter/xt_comment.h>
MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
-MODULE_DESCRIPTION("iptables comment match module");
+MODULE_DESCRIPTION("Xtables: No-op match which can be tagged with a comment");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_comment");
MODULE_ALIAS("ip6t_comment");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protooff,
+ bool *hotdrop)
{
/* We always match */
return true;
}
-static struct xt_match xt_comment_match[] __read_mostly = {
+static struct xt_match comment_mt_reg[] __read_mostly = {
{
.name = "comment",
.family = AF_INET,
- .match = match,
+ .match = comment_mt,
.matchsize = sizeof(struct xt_comment_info),
.me = THIS_MODULE
},
{
.name = "comment",
.family = AF_INET6,
- .match = match,
+ .match = comment_mt,
.matchsize = sizeof(struct xt_comment_info),
.me = THIS_MODULE
},
};
-static int __init xt_comment_init(void)
+static int __init comment_mt_init(void)
{
- return xt_register_matches(xt_comment_match,
- ARRAY_SIZE(xt_comment_match));
+ return xt_register_matches(comment_mt_reg, ARRAY_SIZE(comment_mt_reg));
}
-static void __exit xt_comment_fini(void)
+static void __exit comment_mt_exit(void)
{
- xt_unregister_matches(xt_comment_match, ARRAY_SIZE(xt_comment_match));
+ xt_unregister_matches(comment_mt_reg, ARRAY_SIZE(comment_mt_reg));
}
-module_init(xt_comment_init);
-module_exit(xt_comment_fini);
+module_init(comment_mt_init);
+module_exit(comment_mt_exit);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 9ec50139b9a..b15e7e2fa14 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -12,19 +12,15 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
+MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching");
MODULE_ALIAS("ipt_connbytes");
MODULE_ALIAS("ip6t_connbytes");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_connbytes_info *sinfo = matchinfo;
const struct nf_conn *ct;
@@ -96,11 +92,10 @@ match(const struct sk_buff *skb,
return what >= sinfo->count.from;
}
-static bool check(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool
+connbytes_mt_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_connbytes_info *sinfo = matchinfo;
@@ -116,7 +111,7 @@ static bool check(const char *tablename,
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", match->family);
+ "proto=%u\n", match->family);
return false;
}
@@ -124,43 +119,42 @@ static bool check(const char *tablename,
}
static void
-destroy(const struct xt_match *match, void *matchinfo)
+connbytes_mt_destroy(const struct xt_match *match, void *matchinfo)
{
nf_ct_l3proto_module_put(match->family);
}
-static struct xt_match xt_connbytes_match[] __read_mostly = {
+static struct xt_match connbytes_mt_reg[] __read_mostly = {
{
.name = "connbytes",
.family = AF_INET,
- .checkentry = check,
- .match = match,
- .destroy = destroy,
+ .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 = check,
- .match = match,
- .destroy = destroy,
+ .checkentry = connbytes_mt_check,
+ .match = connbytes_mt,
+ .destroy = connbytes_mt_destroy,
.matchsize = sizeof(struct xt_connbytes_info),
.me = THIS_MODULE
},
};
-static int __init xt_connbytes_init(void)
+static int __init connbytes_mt_init(void)
{
- return xt_register_matches(xt_connbytes_match,
- ARRAY_SIZE(xt_connbytes_match));
+ return xt_register_matches(connbytes_mt_reg,
+ ARRAY_SIZE(connbytes_mt_reg));
}
-static void __exit xt_connbytes_fini(void)
+static void __exit connbytes_mt_exit(void)
{
- xt_unregister_matches(xt_connbytes_match,
- ARRAY_SIZE(xt_connbytes_match));
+ xt_unregister_matches(connbytes_mt_reg, ARRAY_SIZE(connbytes_mt_reg));
}
-module_init(xt_connbytes_init);
-module_exit(xt_connbytes_fini);
+module_init(connbytes_mt_init);
+module_exit(connbytes_mt_exit);
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index d7becf08a93..e00ecd974fa 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -53,10 +53,10 @@ static inline unsigned int connlimit_iphash(__be32 addr)
}
static inline unsigned int
-connlimit_iphash6(const union nf_conntrack_address *addr,
- const union nf_conntrack_address *mask)
+connlimit_iphash6(const union nf_inet_addr *addr,
+ const union nf_inet_addr *mask)
{
- union nf_conntrack_address res;
+ union nf_inet_addr res;
unsigned int i;
if (unlikely(!connlimit_rnd_inited)) {
@@ -81,14 +81,14 @@ static inline bool already_closed(const struct nf_conn *conn)
}
static inline unsigned int
-same_source_net(const union nf_conntrack_address *addr,
- const union nf_conntrack_address *mask,
- const union nf_conntrack_address *u3, unsigned int family)
+same_source_net(const union nf_inet_addr *addr,
+ const union nf_inet_addr *mask,
+ const union nf_inet_addr *u3, unsigned int family)
{
if (family == AF_INET) {
return (addr->ip & mask->ip) == (u3->ip & mask->ip);
} else {
- union nf_conntrack_address lh, rh;
+ union nf_inet_addr lh, rh;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) {
@@ -102,8 +102,8 @@ same_source_net(const union nf_conntrack_address *addr,
static int count_them(struct xt_connlimit_data *data,
const struct nf_conntrack_tuple *tuple,
- const union nf_conntrack_address *addr,
- const union nf_conntrack_address *mask,
+ const union nf_inet_addr *addr,
+ const union nf_inet_addr *mask,
const struct xt_match *match)
{
struct nf_conntrack_tuple_hash *found;
@@ -178,15 +178,14 @@ static int count_them(struct xt_connlimit_data *data,
return matches;
}
-static bool connlimit_match(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
+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)
{
const struct xt_connlimit_info *info = matchinfo;
- union nf_conntrack_address addr, mask;
+ union nf_inet_addr addr;
struct nf_conntrack_tuple tuple;
const struct nf_conntrack_tuple *tuple_ptr = &tuple;
enum ip_conntrack_info ctinfo;
@@ -203,15 +202,14 @@ static bool connlimit_match(const struct sk_buff *skb,
if (match->family == AF_INET6) {
const struct ipv6hdr *iph = ipv6_hdr(skb);
memcpy(&addr.ip6, &iph->saddr, sizeof(iph->saddr));
- memcpy(&mask.ip6, info->v6_mask, sizeof(info->v6_mask));
} else {
const struct iphdr *iph = ip_hdr(skb);
addr.ip = iph->saddr;
- mask.ip = info->v4_mask;
}
spin_lock_bh(&info->data->lock);
- connections = count_them(info->data, tuple_ptr, &addr, &mask, match);
+ connections = count_them(info->data, tuple_ptr, &addr,
+ &info->mask, match);
spin_unlock_bh(&info->data->lock);
if (connections < 0) {
@@ -227,9 +225,10 @@ static bool connlimit_match(const struct sk_buff *skb,
return false;
}
-static bool connlimit_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool
+connlimit_mt_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_connlimit_info *info = matchinfo;
unsigned int i;
@@ -254,7 +253,8 @@ static bool connlimit_check(const char *tablename, const void *ip,
return true;
}
-static void connlimit_destroy(const struct xt_match *match, void *matchinfo)
+static void
+connlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
{
struct xt_connlimit_info *info = matchinfo;
struct xt_connlimit_conn *conn;
@@ -274,41 +274,42 @@ static void connlimit_destroy(const struct xt_match *match, void *matchinfo)
kfree(info->data);
}
-static struct xt_match connlimit_reg[] __read_mostly = {
+static struct xt_match connlimit_mt_reg[] __read_mostly = {
{
.name = "connlimit",
.family = AF_INET,
- .checkentry = connlimit_check,
- .match = connlimit_match,
+ .checkentry = connlimit_mt_check,
+ .match = connlimit_mt,
.matchsize = sizeof(struct xt_connlimit_info),
- .destroy = connlimit_destroy,
+ .destroy = connlimit_mt_destroy,
.me = THIS_MODULE,
},
{
.name = "connlimit",
.family = AF_INET6,
- .checkentry = connlimit_check,
- .match = connlimit_match,
+ .checkentry = connlimit_mt_check,
+ .match = connlimit_mt,
.matchsize = sizeof(struct xt_connlimit_info),
- .destroy = connlimit_destroy,
+ .destroy = connlimit_mt_destroy,
.me = THIS_MODULE,
},
};
-static int __init xt_connlimit_init(void)
+static int __init connlimit_mt_init(void)
{
- return xt_register_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg));
+ return xt_register_matches(connlimit_mt_reg,
+ ARRAY_SIZE(connlimit_mt_reg));
}
-static void __exit xt_connlimit_exit(void)
+static void __exit connlimit_mt_exit(void)
{
- xt_unregister_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg));
+ xt_unregister_matches(connlimit_mt_reg, ARRAY_SIZE(connlimit_mt_reg));
}
-module_init(xt_connlimit_init);
-module_exit(xt_connlimit_exit);
+module_init(connlimit_mt_init);
+module_exit(connlimit_mt_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
-MODULE_DESCRIPTION("netfilter xt_connlimit match module");
+MODULE_DESCRIPTION("Xtables: Number of connections matching");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_connlimit");
MODULE_ALIAS("ip6t_connlimit");
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 9f67920af41..aaa1b96691f 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -1,8 +1,10 @@
-/* This kernel module matches connection mark values set by the
- * CONNMARK target
+/*
+ * xt_connmark - Netfilter module to match connection mark values
*
- * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
- * by Henrik Nordstrom <hno@marasystems.com>
+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ * Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ * Jan Engelhardt <jengelh@computergmbh.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,20 +28,33 @@
#include <linux/netfilter/xt_connmark.h>
MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
-MODULE_DESCRIPTION("IP tables connmark match module");
+MODULE_DESCRIPTION("Xtables: connection mark match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_connmark");
MODULE_ALIAS("ip6t_connmark");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
+{
+ const struct xt_connmark_mtinfo1 *info = matchinfo;
+ enum ip_conntrack_info ctinfo;
+ const struct nf_conn *ct;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct == NULL)
+ return false;
+
+ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
+}
+
+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)
{
const struct xt_connmark_info *info = matchinfo;
const struct nf_conn *ct;
@@ -53,11 +68,9 @@ match(const struct sk_buff *skb,
}
static bool
-checkentry(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+connmark_mt_check_v0(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_connmark_info *cm = matchinfo;
@@ -67,14 +80,27 @@ checkentry(const char *tablename,
}
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", match->family);
+ "proto=%u\n", match->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)
+{
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "cannot load conntrack support for "
+ "proto=%u\n", match->family);
return false;
}
return true;
}
static void
-destroy(const struct xt_match *match, void *matchinfo)
+connmark_mt_destroy(const struct xt_match *match, void *matchinfo)
{
nf_ct_l3proto_module_put(match->family);
}
@@ -87,7 +113,7 @@ struct compat_xt_connmark_info {
u_int16_t __pad2;
};
-static void compat_from_user(void *dst, void *src)
+static void connmark_mt_compat_from_user_v0(void *dst, void *src)
{
const struct compat_xt_connmark_info *cm = src;
struct xt_connmark_info m = {
@@ -98,7 +124,7 @@ static void compat_from_user(void *dst, void *src)
memcpy(dst, &m, sizeof(m));
}
-static int compat_to_user(void __user *dst, void *src)
+static int connmark_mt_compat_to_user_v0(void __user *dst, void *src)
{
const struct xt_connmark_info *m = src;
struct compat_xt_connmark_info cm = {
@@ -110,42 +136,69 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_match xt_connmark_match[] __read_mostly = {
+static struct xt_match connmark_mt_reg[] __read_mostly = {
{
.name = "connmark",
+ .revision = 0,
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
- .destroy = destroy,
+ .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 = compat_from_user,
- .compat_to_user = compat_to_user,
+ .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 = 0,
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
- .destroy = destroy,
+ .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,
+ .checkentry = connmark_mt_check,
+ .match = connmark_mt,
+ .matchsize = sizeof(struct xt_connmark_mtinfo1),
+ .destroy = connmark_mt_destroy,
+ .me = THIS_MODULE,
+ },
};
-static int __init xt_connmark_init(void)
+static int __init connmark_mt_init(void)
{
- return xt_register_matches(xt_connmark_match,
- ARRAY_SIZE(xt_connmark_match));
+ return xt_register_matches(connmark_mt_reg,
+ ARRAY_SIZE(connmark_mt_reg));
}
-static void __exit xt_connmark_fini(void)
+static void __exit connmark_mt_exit(void)
{
- xt_unregister_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match));
+ xt_unregister_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg));
}
-module_init(xt_connmark_init);
-module_exit(xt_connmark_fini);
+module_init(connmark_mt_init);
+module_exit(connmark_mt_exit);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index ca4b69f020a..e92190eafcc 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -1,33 +1,34 @@
-/* Kernel module to match connection tracking information.
- * Superset of Rusty's minimalistic state match.
+/*
+ * xt_conntrack - Netfilter module to match connection tracking
+ * information. (Superset of Rusty's minimalistic state match.)
*
- * (C) 2001 Marc Boucher (marc@mbsi.ca).
+ * (C) 2001 Marc Boucher (marc@mbsi.ca).
+ * Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ * Jan Engelhardt <jengelh@computergmbh.de>
*
- * 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 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 <net/ipv6.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_conntrack.h>
#include <net/netfilter/nf_conntrack.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-MODULE_DESCRIPTION("iptables connection tracking match module");
+MODULE_DESCRIPTION("Xtables: connection tracking state match");
MODULE_ALIAS("ipt_conntrack");
+MODULE_ALIAS("ip6t_conntrack");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_conntrack_info *sinfo = matchinfo;
const struct nf_conn *ct;
@@ -36,7 +37,7 @@ match(const struct sk_buff *skb,
ct = nf_ct_get(skb, &ctinfo);
-#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
+#define FWINV(bool, invflg) ((bool) ^ !!(sinfo->invflags & (invflg)))
if (ct == &nf_conntrack_untracked)
statebit = XT_CONNTRACK_STATE_UNTRACKED;
@@ -112,24 +113,152 @@ match(const struct sk_buff *skb,
return false;
}
return true;
+#undef FWINV
}
static bool
-checkentry(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+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)
+ return (kaddr->ip & umask->ip) == uaddr->ip;
+ else if (l3proto == AF_INET6)
+ return ipv6_masked_addr_cmp(&kaddr->in6, &umask->in6,
+ &uaddr->in6) == 0;
+ else
+ return false;
+}
+
+static inline bool
+conntrack_mt_origsrc(const struct nf_conn *ct,
+ const struct xt_conntrack_mtinfo1 *info,
+ unsigned int family)
+{
+ return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
+ &info->origsrc_addr, &info->origsrc_mask, family);
+}
+
+static inline bool
+conntrack_mt_origdst(const struct nf_conn *ct,
+ const struct xt_conntrack_mtinfo1 *info,
+ unsigned int family)
+{
+ return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3,
+ &info->origdst_addr, &info->origdst_mask, family);
+}
+
+static inline bool
+conntrack_mt_replsrc(const struct nf_conn *ct,
+ const struct xt_conntrack_mtinfo1 *info,
+ unsigned int family)
+{
+ return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3,
+ &info->replsrc_addr, &info->replsrc_mask, family);
+}
+
+static inline bool
+conntrack_mt_repldst(const struct nf_conn *ct,
+ const struct xt_conntrack_mtinfo1 *info,
+ unsigned int family)
+{
+ return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3,
+ &info->repldst_addr, &info->repldst_mask, family);
+}
+
+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)
+{
+ const struct xt_conntrack_mtinfo1 *info = matchinfo;
+ enum ip_conntrack_info ctinfo;
+ const struct nf_conn *ct;
+ unsigned int statebit;
+
+ ct = nf_ct_get(skb, &ctinfo);
+
+ if (ct == &nf_conntrack_untracked)
+ statebit = XT_CONNTRACK_STATE_UNTRACKED;
+ else if (ct != NULL)
+ statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
+ else
+ statebit = XT_CONNTRACK_STATE_INVALID;
+
+ if (info->match_flags & XT_CONNTRACK_STATE) {
+ if (ct != NULL) {
+ if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
+ statebit |= XT_CONNTRACK_STATE_SNAT;
+ if (test_bit(IPS_DST_NAT_BIT, &ct->status))
+ statebit |= XT_CONNTRACK_STATE_DNAT;
+ }
+ if ((info->state_mask & statebit) ^
+ !(info->invert_flags & XT_CONNTRACK_STATE))
+ return false;
+ }
+
+ if (ct == NULL)
+ return info->match_flags & XT_CONNTRACK_STATE;
+
+ if ((info->match_flags & XT_CONNTRACK_PROTO) &&
+ ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
+ info->l4proto) ^ !(info->invert_flags & XT_CONNTRACK_PROTO)))
+ return false;
+
+ if (info->match_flags & XT_CONNTRACK_ORIGSRC)
+ if (conntrack_mt_origsrc(ct, info, match->family) ^
+ !(info->invert_flags & XT_CONNTRACK_ORIGSRC))
+ return false;
+
+ if (info->match_flags & XT_CONNTRACK_ORIGDST)
+ if (conntrack_mt_origdst(ct, info, match->family) ^
+ !(info->invert_flags & XT_CONNTRACK_ORIGDST))
+ return false;
+
+ if (info->match_flags & XT_CONNTRACK_REPLSRC)
+ if (conntrack_mt_replsrc(ct, info, match->family) ^
+ !(info->invert_flags & XT_CONNTRACK_REPLSRC))
+ return false;
+
+ if (info->match_flags & XT_CONNTRACK_REPLDST)
+ if (conntrack_mt_repldst(ct, info, match->family) ^
+ !(info->invert_flags & XT_CONNTRACK_REPLDST))
+ return false;
+
+ if ((info->match_flags & XT_CONNTRACK_STATUS) &&
+ (!!(info->status_mask & ct->status) ^
+ !(info->invert_flags & XT_CONNTRACK_STATUS)))
+ return false;
+
+ if (info->match_flags & XT_CONNTRACK_EXPIRES) {
+ unsigned long expires = 0;
+
+ if (timer_pending(&ct->timeout))
+ expires = (ct->timeout.expires - jiffies) / HZ;
+ if ((expires >= info->expires_min &&
+ expires <= info->expires_max) ^
+ !(info->invert_flags & XT_CONNTRACK_EXPIRES))
+ return false;
+ }
+ return true;
+}
+
+static bool
+conntrack_mt_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", match->family);
+ "proto=%u\n", match->family);
return false;
}
return true;
}
-static void destroy(const struct xt_match *match, void *matchinfo)
+static void
+conntrack_mt_destroy(const struct xt_match *match, void *matchinfo)
{
nf_ct_l3proto_module_put(match->family);
}
@@ -148,7 +277,7 @@ struct compat_xt_conntrack_info
u_int8_t invflags;
};
-static void compat_from_user(void *dst, void *src)
+static void conntrack_mt_compat_from_user_v0(void *dst, void *src)
{
const struct compat_xt_conntrack_info *cm = src;
struct xt_conntrack_info m = {
@@ -165,7 +294,7 @@ static void compat_from_user(void *dst, void *src)
memcpy(dst, &m, sizeof(m));
}
-static int compat_to_user(void __user *dst, void *src)
+static int conntrack_mt_compat_to_user_v0(void __user *dst, void *src)
{
const struct xt_conntrack_info *m = src;
struct compat_xt_conntrack_info cm = {
@@ -183,30 +312,54 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif
-static struct xt_match conntrack_match __read_mostly = {
- .name = "conntrack",
- .match = match,
- .checkentry = checkentry,
- .destroy = destroy,
- .matchsize = sizeof(struct xt_conntrack_info),
+static struct xt_match conntrack_mt_reg[] __read_mostly = {
+ {
+ .name = "conntrack",
+ .revision = 0,
+ .family = AF_INET,
+ .match = conntrack_mt_v0,
+ .checkentry = conntrack_mt_check,
+ .destroy = conntrack_mt_destroy,
+ .matchsize = sizeof(struct xt_conntrack_info),
+ .me = THIS_MODULE,
#ifdef CONFIG_COMPAT
- .compatsize = sizeof(struct compat_xt_conntrack_info),
- .compat_from_user = compat_from_user,
- .compat_to_user = compat_to_user,
+ .compatsize = sizeof(struct compat_xt_conntrack_info),
+ .compat_from_user = conntrack_mt_compat_from_user_v0,
+ .compat_to_user = conntrack_mt_compat_to_user_v0,
#endif
- .family = AF_INET,
- .me = THIS_MODULE,
+ },
+ {
+ .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,
+ .matchsize = sizeof(struct xt_conntrack_mtinfo1),
+ .match = conntrack_mt,
+ .checkentry = conntrack_mt_check,
+ .destroy = conntrack_mt_destroy,
+ .me = THIS_MODULE,
+ },
};
-static int __init xt_conntrack_init(void)
+static int __init conntrack_mt_init(void)
{
- return xt_register_match(&conntrack_match);
+ return xt_register_matches(conntrack_mt_reg,
+ ARRAY_SIZE(conntrack_mt_reg));
}
-static void __exit xt_conntrack_fini(void)
+static void __exit conntrack_mt_exit(void)
{
- xt_unregister_match(&conntrack_match);
+ xt_unregister_matches(conntrack_mt_reg, ARRAY_SIZE(conntrack_mt_reg));
}
-module_init(xt_conntrack_init);
-module_exit(xt_conntrack_fini);
+module_init(conntrack_mt_init);
+module_exit(conntrack_mt_exit);
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index c2b1b24ee33..667f45e72cd 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -22,7 +22,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("Match for DCCP protocol packets");
+MODULE_DESCRIPTION("Xtables: DCCP protocol packet match");
MODULE_ALIAS("ipt_dccp");
MODULE_ALIAS("ip6t_dccp");
@@ -93,14 +93,9 @@ match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
}
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
const struct xt_dccp_info *info = matchinfo;
struct dccp_hdr _dh, *dh;
@@ -128,11 +123,9 @@ match(const struct sk_buff *skb,
}
static bool
-checkentry(const char *tablename,
- const void *inf,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+dccp_mt_check(const char *tablename, const void *inf,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_dccp_info *info = matchinfo;
@@ -141,12 +134,12 @@ checkentry(const char *tablename,
&& !(info->invflags & ~info->flags);
}
-static struct xt_match xt_dccp_match[] __read_mostly = {
+static struct xt_match dccp_mt_reg[] __read_mostly = {
{
.name = "dccp",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = dccp_mt_check,
+ .match = dccp_mt,
.matchsize = sizeof(struct xt_dccp_info),
.proto = IPPROTO_DCCP,
.me = THIS_MODULE,
@@ -154,15 +147,15 @@ static struct xt_match xt_dccp_match[] __read_mostly = {
{
.name = "dccp",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = dccp_mt_check,
+ .match = dccp_mt,
.matchsize = sizeof(struct xt_dccp_info),
.proto = IPPROTO_DCCP,
.me = THIS_MODULE,
},
};
-static int __init xt_dccp_init(void)
+static int __init dccp_mt_init(void)
{
int ret;
@@ -172,7 +165,7 @@ static int __init xt_dccp_init(void)
dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
if (!dccp_optbuf)
return -ENOMEM;
- ret = xt_register_matches(xt_dccp_match, ARRAY_SIZE(xt_dccp_match));
+ ret = xt_register_matches(dccp_mt_reg, ARRAY_SIZE(dccp_mt_reg));
if (ret)
goto out_kfree;
return ret;
@@ -182,11 +175,11 @@ out_kfree:
return ret;
}
-static void __exit xt_dccp_fini(void)
+static void __exit dccp_mt_exit(void)
{
- xt_unregister_matches(xt_dccp_match, ARRAY_SIZE(xt_dccp_match));
+ xt_unregister_matches(dccp_mt_reg, ARRAY_SIZE(dccp_mt_reg));
kfree(dccp_optbuf);
}
-module_init(xt_dccp_init);
-module_exit(xt_dccp_fini);
+module_init(dccp_mt_init);
+module_exit(dccp_mt_exit);
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index dde6d66e0d3..26f4aab9c42 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -13,23 +13,22 @@
#include <linux/ipv6.h>
#include <net/dsfield.h>
-#include <linux/netfilter/xt_dscp.h>
#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_dscp.h>
+#include <linux/netfilter_ipv4/ipt_tos.h>
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("x_tables DSCP matching module");
+MODULE_DESCRIPTION("Xtables: DSCP/TOS field match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_dscp");
MODULE_ALIAS("ip6t_dscp");
+MODULE_ALIAS("ipt_tos");
+MODULE_ALIAS("ip6t_tos");
-static bool match(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
+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)
{
const struct xt_dscp_info *info = matchinfo;
u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -37,14 +36,11 @@ static bool match(const struct sk_buff *skb,
return (dscp == info->dscp) ^ !!info->invert;
}
-static bool match6(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
+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)
{
const struct xt_dscp_info *info = matchinfo;
u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -52,11 +48,10 @@ static bool match6(const struct sk_buff *skb,
return (dscp == info->dscp) ^ !!info->invert;
}
-static bool checkentry(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool
+dscp_mt_check(const char *tablename, const void *info,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp;
@@ -68,34 +63,83 @@ static bool checkentry(const char *tablename,
return true;
}
-static struct xt_match xt_dscp_match[] __read_mostly = {
+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)
+{
+ const struct ipt_tos_info *info = 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)
+{
+ const struct xt_tos_match_info *info = matchinfo;
+
+ if (match->family == AF_INET)
+ return ((ip_hdr(skb)->tos & info->tos_mask) ==
+ info->tos_value) ^ !!info->invert;
+ else
+ return ((ipv6_get_dsfield(ipv6_hdr(skb)) & info->tos_mask) ==
+ info->tos_value) ^ !!info->invert;
+}
+
+static struct xt_match dscp_mt_reg[] __read_mostly = {
{
.name = "dscp",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = dscp_mt_check,
+ .match = dscp_mt,
.matchsize = sizeof(struct xt_dscp_info),
.me = THIS_MODULE,
},
{
.name = "dscp",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match6,
+ .checkentry = dscp_mt_check,
+ .match = dscp_mt6,
.matchsize = sizeof(struct xt_dscp_info),
.me = THIS_MODULE,
},
+ {
+ .name = "tos",
+ .revision = 0,
+ .family = AF_INET,
+ .match = tos_mt_v0,
+ .matchsize = sizeof(struct ipt_tos_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "tos",
+ .revision = 1,
+ .family = AF_INET,
+ .match = tos_mt,
+ .matchsize = sizeof(struct xt_tos_match_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "tos",
+ .revision = 1,
+ .family = AF_INET6,
+ .match = tos_mt,
+ .matchsize = sizeof(struct xt_tos_match_info),
+ .me = THIS_MODULE,
+ },
};
-static int __init xt_dscp_match_init(void)
+static int __init dscp_mt_init(void)
{
- return xt_register_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match));
+ return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
}
-static void __exit xt_dscp_match_fini(void)
+static void __exit dscp_mt_exit(void)
{
- xt_unregister_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match));
+ xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
}
-module_init(xt_dscp_match_init);
-module_exit(xt_dscp_match_fini);
+module_init(dscp_mt_init);
+module_exit(dscp_mt_exit);
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
index b11378e001b..71c7c378526 100644
--- a/net/netfilter/xt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -20,7 +20,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
-MODULE_DESCRIPTION("x_tables ESP SPI match module");
+MODULE_DESCRIPTION("Xtables: IPsec-ESP packet match");
MODULE_ALIAS("ipt_esp");
MODULE_ALIAS("ip6t_esp");
@@ -43,14 +43,9 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
}
static bool
-match(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)
+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)
{
struct ip_esp_hdr _esp, *eh;
const struct xt_esp *espinfo = matchinfo;
@@ -75,11 +70,9 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static bool
-checkentry(const char *tablename,
- const void *ip_void,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+esp_mt_check(const char *tablename, const void *ip_void,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_esp *espinfo = matchinfo;
@@ -91,12 +84,12 @@ checkentry(const char *tablename,
return true;
}
-static struct xt_match xt_esp_match[] __read_mostly = {
+static struct xt_match esp_mt_reg[] __read_mostly = {
{
.name = "esp",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = esp_mt_check,
+ .match = esp_mt,
.matchsize = sizeof(struct xt_esp),
.proto = IPPROTO_ESP,
.me = THIS_MODULE,
@@ -104,23 +97,23 @@ static struct xt_match xt_esp_match[] __read_mostly = {
{
.name = "esp",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = esp_mt_check,
+ .match = esp_mt,
.matchsize = sizeof(struct xt_esp),
.proto = IPPROTO_ESP,
.me = THIS_MODULE,
},
};
-static int __init xt_esp_init(void)
+static int __init esp_mt_init(void)
{
- return xt_register_matches(xt_esp_match, ARRAY_SIZE(xt_esp_match));
+ return xt_register_matches(esp_mt_reg, ARRAY_SIZE(esp_mt_reg));
}
-static void __exit xt_esp_cleanup(void)
+static void __exit esp_mt_exit(void)
{
- xt_unregister_matches(xt_esp_match, ARRAY_SIZE(xt_esp_match));
+ xt_unregister_matches(esp_mt_reg, ARRAY_SIZE(esp_mt_reg));
}
-module_init(xt_esp_init);
-module_exit(xt_esp_cleanup);
+module_init(esp_mt_init);
+module_exit(esp_mt_exit);
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 2ef44d8560c..d479ca98011 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -20,7 +20,11 @@
#include <linux/mm.h>
#include <linux/in.h>
#include <linux/ip.h>
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#endif
+
#include <net/net_namespace.h>
#include <linux/netfilter/x_tables.h>
@@ -31,7 +35,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("iptables match for limiting per hash-bucket");
+MODULE_DESCRIPTION("Xtables: per hash-bucket rate-limit match");
MODULE_ALIAS("ipt_hashlimit");
MODULE_ALIAS("ip6t_hashlimit");
@@ -47,10 +51,12 @@ struct dsthash_dst {
__be32 src;
__be32 dst;
} ip;
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
struct {
__be32 src[4];
__be32 dst[4];
} ip6;
+#endif
} addr;
__be16 src_port;
__be16 dst_port;
@@ -104,7 +110,16 @@ static inline bool dst_cmp(const struct dsthash_ent *ent,
static u_int32_t
hash_dst(const struct xt_hashlimit_htable *ht, const struct dsthash_dst *dst)
{
- return jhash(dst, sizeof(*dst), ht->rnd) % ht->cfg.size;
+ u_int32_t hash = jhash2((const u32 *)dst,
+ sizeof(*dst)/sizeof(u32),
+ ht->rnd);
+ /*
+ * Instead of returning hash % ht->cfg.size (implying a divide)
+ * we return the high 32 bits of the (hash * ht->cfg.size) that will
+ * give results between [0 and cfg.size-1] and same hash distribution,
+ * but using a multiply, less expensive than a divide
+ */
+ return ((u64)hash * ht->cfg.size) >> 32;
}
static struct dsthash_ent *
@@ -379,7 +394,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
const struct sk_buff *skb, unsigned int protoff)
{
__be16 _ports[2], *ports;
- int nexthdr;
+ u8 nexthdr;
memset(dst, 0, sizeof(*dst));
@@ -407,8 +422,9 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
if (!(hinfo->cfg.mode &
(XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
return 0;
- nexthdr = ipv6_find_hdr(skb, &protoff, -1, NULL);
- if (nexthdr < 0)
+ nexthdr = ipv6_hdr(skb)->nexthdr;
+ protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
+ if ((int)protoff < 0)
return -1;
break;
#endif
@@ -441,14 +457,10 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
}
static bool
-hashlimit_match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_hashlimit_info *r =
((const struct xt_hashlimit_info *)matchinfo)->u.master;
@@ -500,11 +512,9 @@ hotdrop:
}
static bool
-hashlimit_checkentry(const char *tablename,
- const void *inf,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+hashlimit_mt_check(const char *tablename, const void *inf,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_hashlimit_info *r = matchinfo;
@@ -548,7 +558,7 @@ hashlimit_checkentry(const char *tablename,
}
static void
-hashlimit_destroy(const struct xt_match *match, void *matchinfo)
+hashlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
{
const struct xt_hashlimit_info *r = matchinfo;
@@ -563,7 +573,7 @@ struct compat_xt_hashlimit_info {
compat_uptr_t master;
};
-static void compat_from_user(void *dst, void *src)
+static void hashlimit_mt_compat_from_user(void *dst, void *src)
{
int off = offsetof(struct compat_xt_hashlimit_info, hinfo);
@@ -571,7 +581,7 @@ static void compat_from_user(void *dst, void *src)
memset(dst + off, 0, sizeof(struct compat_xt_hashlimit_info) - off);
}
-static int compat_to_user(void __user *dst, void *src)
+static int hashlimit_mt_compat_to_user(void __user *dst, void *src)
{
int off = offsetof(struct compat_xt_hashlimit_info, hinfo);
@@ -579,35 +589,37 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif
-static struct xt_match xt_hashlimit[] __read_mostly = {
+static struct xt_match hashlimit_mt_reg[] __read_mostly = {
{
.name = "hashlimit",
.family = AF_INET,
- .match = hashlimit_match,
+ .match = hashlimit_mt,
.matchsize = sizeof(struct xt_hashlimit_info),
#ifdef CONFIG_COMPAT
.compatsize = sizeof(struct compat_xt_hashlimit_info),
- .compat_from_user = compat_from_user,
- .compat_to_user = compat_to_user,
+ .compat_from_user = hashlimit_mt_compat_from_user,
+ .compat_to_user = hashlimit_mt_compat_to_user,
#endif
- .checkentry = hashlimit_checkentry,
- .destroy = hashlimit_destroy,
+ .checkentry = hashlimit_mt_check,
+ .destroy = hashlimit_mt_destroy,
.me = THIS_MODULE
},
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
{
.name = "hashlimit",
.family = AF_INET6,
- .match = hashlimit_match,
+ .match = hashlimit_mt,
.matchsize = sizeof(struct xt_hashlimit_info),
#ifdef CONFIG_COMPAT
.compatsize = sizeof(struct compat_xt_hashlimit_info),
- .compat_from_user = compat_from_user,
- .compat_to_user = compat_to_user,
+ .compat_from_user = hashlimit_mt_compat_from_user,
+ .compat_to_user = hashlimit_mt_compat_to_user,
#endif
- .checkentry = hashlimit_checkentry,
- .destroy = hashlimit_destroy,
+ .checkentry = hashlimit_mt_check,
+ .destroy = hashlimit_mt_destroy,
.me = THIS_MODULE
},
+#endif
};
/* PROC stuff */
@@ -670,6 +682,7 @@ static int dl_seq_real_show(struct dsthash_ent *ent, int family,
ntohs(ent->dst.dst_port),
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:
return seq_printf(s, "%ld " NIP6_FMT ":%u->"
NIP6_FMT ":%u %u %u %u\n",
@@ -680,6 +693,7 @@ static int dl_seq_real_show(struct dsthash_ent *ent, int family,
ntohs(ent->dst.dst_port),
ent->rateinfo.credit, ent->rateinfo.credit_cap,
ent->rateinfo.cost);
+#endif
default:
BUG();
return 0;
@@ -728,11 +742,12 @@ static const struct file_operations dl_file_ops = {
.release = seq_release
};
-static int __init xt_hashlimit_init(void)
+static int __init hashlimit_mt_init(void)
{
int err;
- err = xt_register_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+ err = xt_register_matches(hashlimit_mt_reg,
+ ARRAY_SIZE(hashlimit_mt_reg));
if (err < 0)
goto err1;
@@ -750,31 +765,36 @@ static int __init xt_hashlimit_init(void)
"entry\n");
goto err3;
}
+ err = 0;
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", init_net.proc_net);
if (!hashlimit_procdir6) {
printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
"entry\n");
- goto err4;
+ err = -ENOMEM;
}
- return 0;
-err4:
+#endif
+ if (!err)
+ return 0;
remove_proc_entry("ipt_hashlimit", init_net.proc_net);
err3:
kmem_cache_destroy(hashlimit_cachep);
err2:
- xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+ xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg));
err1:
return err;
}
-static void __exit xt_hashlimit_fini(void)
+static void __exit hashlimit_mt_exit(void)
{
remove_proc_entry("ipt_hashlimit", init_net.proc_net);
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
remove_proc_entry("ip6t_hashlimit", init_net.proc_net);
+#endif
kmem_cache_destroy(hashlimit_cachep);
- xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+ xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg));
}
-module_init(xt_hashlimit_init);
-module_exit(xt_hashlimit_fini);
+module_init(hashlimit_mt_init);
+module_exit(hashlimit_mt_exit);
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index d842c4a6d63..dada2905d66 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -18,20 +18,16 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
-MODULE_DESCRIPTION("iptables helper match module");
+MODULE_DESCRIPTION("Xtables: Related connection matching");
MODULE_ALIAS("ipt_helper");
MODULE_ALIAS("ip6t_helper");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_helper_info *info = matchinfo;
const struct nf_conn *ct;
@@ -61,61 +57,57 @@ match(const struct sk_buff *skb,
return ret;
}
-static bool check(const char *tablename,
- const void *inf,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool
+helper_mt_check(const char *tablename, const void *inf,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_helper_info *info = matchinfo;
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", match->family);
+ "proto=%u\n", match->family);
return false;
}
info->name[29] = '\0';
return true;
}
-static void
-destroy(const struct xt_match *match, void *matchinfo)
+static void helper_mt_destroy(const struct xt_match *match, void *matchinfo)
{
nf_ct_l3proto_module_put(match->family);
}
-static struct xt_match xt_helper_match[] __read_mostly = {
+static struct xt_match helper_mt_reg[] __read_mostly = {
{
.name = "helper",
.family = AF_INET,
- .checkentry = check,
- .match = match,
- .destroy = destroy,
+ .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 = check,
- .match = match,
- .destroy = destroy,
+ .checkentry = helper_mt_check,
+ .match = helper_mt,
+ .destroy = helper_mt_destroy,
.matchsize = sizeof(struct xt_helper_info),
.me = THIS_MODULE,
},
};
-static int __init xt_helper_init(void)
+static int __init helper_mt_init(void)
{
- return xt_register_matches(xt_helper_match,
- ARRAY_SIZE(xt_helper_match));
+ return xt_register_matches(helper_mt_reg, ARRAY_SIZE(helper_mt_reg));
}
-static void __exit xt_helper_fini(void)
+static void __exit helper_mt_exit(void)
{
- xt_unregister_matches(xt_helper_match, ARRAY_SIZE(xt_helper_match));
+ xt_unregister_matches(helper_mt_reg, ARRAY_SIZE(helper_mt_reg));
}
-module_init(xt_helper_init);
-module_exit(xt_helper_fini);
-
+module_init(helper_mt_init);
+module_exit(helper_mt_exit);
diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c
new file mode 100644
index 00000000000..dbea0e0893f
--- /dev/null
+++ b/net/netfilter/xt_iprange.c
@@ -0,0 +1,180 @@
+/*
+ * xt_iprange - Netfilter module to match IP address ranges
+ *
+ * (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ * (C) CC Computer Consultants GmbH, 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.
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter/x_tables.h>
+#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)
+{
+ const struct ipt_iprange_info *info = matchinfo;
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (info->flags & IPRANGE_SRC) {
+ if ((ntohl(iph->saddr) < ntohl(info->src.min_ip)
+ || ntohl(iph->saddr) > ntohl(info->src.max_ip))
+ ^ !!(info->flags & IPRANGE_SRC_INV)) {
+ pr_debug("src IP %u.%u.%u.%u NOT in range %s"
+ "%u.%u.%u.%u-%u.%u.%u.%u\n",
+ NIPQUAD(iph->saddr),
+ info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
+ NIPQUAD(info->src.min_ip),
+ NIPQUAD(info->src.max_ip));
+ return false;
+ }
+ }
+ if (info->flags & IPRANGE_DST) {
+ if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip)
+ || ntohl(iph->daddr) > ntohl(info->dst.max_ip))
+ ^ !!(info->flags & IPRANGE_DST_INV)) {
+ pr_debug("dst IP %u.%u.%u.%u NOT in range %s"
+ "%u.%u.%u.%u-%u.%u.%u.%u\n",
+ NIPQUAD(iph->daddr),
+ info->flags & IPRANGE_DST_INV ? "(INV) " : "",
+ NIPQUAD(info->dst.min_ip),
+ NIPQUAD(info->dst.max_ip));
+ return false;
+ }
+ }
+ return true;
+}
+
+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)
+{
+ const struct xt_iprange_mtinfo *info = matchinfo;
+ const struct iphdr *iph = ip_hdr(skb);
+ bool m;
+
+ if (info->flags & IPRANGE_SRC) {
+ m = ntohl(iph->saddr) < ntohl(info->src_min.ip);
+ m |= ntohl(iph->saddr) > ntohl(info->src_max.ip);
+ m ^= info->flags & IPRANGE_SRC_INV;
+ if (m) {
+ pr_debug("src IP " NIPQUAD_FMT " NOT in range %s"
+ NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
+ NIPQUAD(iph->saddr),
+ (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "",
+ NIPQUAD(info->src_max.ip),
+ NIPQUAD(info->src_max.ip));
+ return false;
+ }
+ }
+ if (info->flags & IPRANGE_DST) {
+ m = ntohl(iph->daddr) < ntohl(info->dst_min.ip);
+ m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip);
+ m ^= info->flags & IPRANGE_DST_INV;
+ if (m) {
+ pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s"
+ NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
+ NIPQUAD(iph->daddr),
+ (info->flags & IPRANGE_DST_INV) ? "(INV) " : "",
+ NIPQUAD(info->dst_min.ip),
+ NIPQUAD(info->dst_max.ip));
+ return false;
+ }
+ }
+ return true;
+}
+
+static inline int
+iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b)
+{
+ unsigned int i;
+ int r;
+
+ for (i = 0; i < 4; ++i) {
+ r = a->s6_addr32[i] - b->s6_addr32[i];
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
+
+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)
+{
+ const struct xt_iprange_mtinfo *info = matchinfo;
+ const struct ipv6hdr *iph = ipv6_hdr(skb);
+ bool m;
+
+ if (info->flags & IPRANGE_SRC) {
+ m = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0;
+ m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0;
+ m ^= info->flags & IPRANGE_SRC_INV;
+ if (m)
+ return false;
+ }
+ if (info->flags & IPRANGE_DST) {
+ m = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0;
+ m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0;
+ m ^= info->flags & IPRANGE_DST_INV;
+ if (m)
+ return false;
+ }
+ return true;
+}
+
+static struct xt_match iprange_mt_reg[] __read_mostly = {
+ {
+ .name = "iprange",
+ .revision = 0,
+ .family = AF_INET,
+ .match = iprange_mt_v0,
+ .matchsize = sizeof(struct ipt_iprange_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "iprange",
+ .revision = 1,
+ .family = AF_INET6,
+ .match = iprange_mt4,
+ .matchsize = sizeof(struct xt_iprange_mtinfo),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "iprange",
+ .revision = 1,
+ .family = AF_INET6,
+ .match = iprange_mt6,
+ .matchsize = sizeof(struct xt_iprange_mtinfo),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init iprange_mt_init(void)
+{
+ return xt_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
+}
+
+static void __exit iprange_mt_exit(void)
+{
+ xt_unregister_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
+}
+
+module_init(iprange_mt_init);
+module_exit(iprange_mt_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>, Jan Engelhardt <jengelh@computergmbh.de>");
+MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching");
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 3dad173d973..b8640f97295 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -15,20 +15,16 @@
#include <linux/netfilter/x_tables.h>
MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
-MODULE_DESCRIPTION("IP tables packet length matching module");
+MODULE_DESCRIPTION("Xtables: Packet length (Layer3,4,5) match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_length");
MODULE_ALIAS("ip6t_length");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_length_info *info = matchinfo;
u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len);
@@ -37,14 +33,10 @@ match(const struct sk_buff *skb,
}
static bool
-match6(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_length_info *info = matchinfo;
const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) +
@@ -53,33 +45,32 @@ match6(const struct sk_buff *skb,
return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
}
-static struct xt_match xt_length_match[] __read_mostly = {
+static struct xt_match length_mt_reg[] __read_mostly = {
{
.name = "length",
.family = AF_INET,
- .match = match,
+ .match = length_mt,
.matchsize = sizeof(struct xt_length_info),
.me = THIS_MODULE,
},
{
.name = "length",
.family = AF_INET6,
- .match = match6,
+ .match = length_mt6,
.matchsize = sizeof(struct xt_length_info),
.me = THIS_MODULE,
},
};
-static int __init xt_length_init(void)
+static int __init length_mt_init(void)
{
- return xt_register_matches(xt_length_match,
- ARRAY_SIZE(xt_length_match));
+ return xt_register_matches(length_mt_reg, ARRAY_SIZE(length_mt_reg));
}
-static void __exit xt_length_fini(void)
+static void __exit length_mt_exit(void)
{
- xt_unregister_matches(xt_length_match, ARRAY_SIZE(xt_length_match));
+ xt_unregister_matches(length_mt_reg, ARRAY_SIZE(length_mt_reg));
}
-module_init(xt_length_init);
-module_exit(xt_length_fini);
+module_init(length_mt_init);
+module_exit(length_mt_exit);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index f263a77e57b..aad9ab8d204 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -16,7 +16,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
-MODULE_DESCRIPTION("iptables rate limit match");
+MODULE_DESCRIPTION("Xtables: rate-limit match");
MODULE_ALIAS("ipt_limit");
MODULE_ALIAS("ip6t_limit");
@@ -58,14 +58,10 @@ static DEFINE_SPINLOCK(limit_lock);
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
static bool
-ipt_limit_match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
struct xt_rateinfo *r =
((const struct xt_rateinfo *)matchinfo)->master;
@@ -100,11 +96,9 @@ user2credits(u_int32_t user)
}
static bool
-ipt_limit_checkentry(const char *tablename,
- const void *inf,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+limit_mt_check(const char *tablename, const void *inf,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_rateinfo *r = matchinfo;
@@ -143,7 +137,7 @@ struct compat_xt_rateinfo {
/* To keep the full "prev" timestamp, the upper 32 bits are stored in the
* master pointer, which does not need to be preserved. */
-static void compat_from_user(void *dst, void *src)
+static void limit_mt_compat_from_user(void *dst, void *src)
{
const struct compat_xt_rateinfo *cm = src;
struct xt_rateinfo m = {
@@ -157,7 +151,7 @@ static void compat_from_user(void *dst, void *src)
memcpy(dst, &m, sizeof(m));
}
-static int compat_to_user(void __user *dst, void *src)
+static int limit_mt_compat_to_user(void __user *dst, void *src)
{
const struct xt_rateinfo *m = src;
struct compat_xt_rateinfo cm = {
@@ -173,39 +167,44 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_match xt_limit_match[] __read_mostly = {
+static struct xt_match limit_mt_reg[] __read_mostly = {
{
.name = "limit",
.family = AF_INET,
- .checkentry = ipt_limit_checkentry,
- .match = ipt_limit_match,
+ .checkentry = limit_mt_check,
+ .match = limit_mt,
.matchsize = sizeof(struct xt_rateinfo),
#ifdef CONFIG_COMPAT
.compatsize = sizeof(struct compat_xt_rateinfo),
- .compat_from_user = compat_from_user,
- .compat_to_user = compat_to_user,
+ .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 = ipt_limit_checkentry,
- .match = ipt_limit_match,
+ .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,
},
};
-static int __init xt_limit_init(void)
+static int __init limit_mt_init(void)
{
- return xt_register_matches(xt_limit_match, ARRAY_SIZE(xt_limit_match));
+ return xt_register_matches(limit_mt_reg, ARRAY_SIZE(limit_mt_reg));
}
-static void __exit xt_limit_fini(void)
+static void __exit limit_mt_exit(void)
{
- xt_unregister_matches(xt_limit_match, ARRAY_SIZE(xt_limit_match));
+ xt_unregister_matches(limit_mt_reg, ARRAY_SIZE(limit_mt_reg));
}
-module_init(xt_limit_init);
-module_exit(xt_limit_fini);
+module_init(limit_mt_init);
+module_exit(limit_mt_exit);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 00490d777a0..b3e96a0ec17 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -20,19 +20,14 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("iptables mac matching module");
+MODULE_DESCRIPTION("Xtables: MAC address match");
MODULE_ALIAS("ipt_mac");
MODULE_ALIAS("ip6t_mac");
static bool
-match(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)
+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)
{
const struct xt_mac_info *info = matchinfo;
@@ -44,38 +39,38 @@ match(const struct sk_buff *skb,
^ info->invert);
}
-static struct xt_match xt_mac_match[] __read_mostly = {
+static struct xt_match mac_mt_reg[] __read_mostly = {
{
.name = "mac",
.family = AF_INET,
- .match = match,
+ .match = mac_mt,
.matchsize = sizeof(struct xt_mac_info),
- .hooks = (1 << NF_IP_PRE_ROUTING) |
- (1 << NF_IP_LOCAL_IN) |
- (1 << NF_IP_FORWARD),
+ .hooks = (1 << NF_INET_PRE_ROUTING) |
+ (1 << NF_INET_LOCAL_IN) |
+ (1 << NF_INET_FORWARD),
.me = THIS_MODULE,
},
{
.name = "mac",
.family = AF_INET6,
- .match = match,
+ .match = mac_mt,
.matchsize = sizeof(struct xt_mac_info),
- .hooks = (1 << NF_IP6_PRE_ROUTING) |
- (1 << NF_IP6_LOCAL_IN) |
- (1 << NF_IP6_FORWARD),
+ .hooks = (1 << NF_INET_PRE_ROUTING) |
+ (1 << NF_INET_LOCAL_IN) |
+ (1 << NF_INET_FORWARD),
.me = THIS_MODULE,
},
};
-static int __init xt_mac_init(void)
+static int __init mac_mt_init(void)
{
- return xt_register_matches(xt_mac_match, ARRAY_SIZE(xt_mac_match));
+ return xt_register_matches(mac_mt_reg, ARRAY_SIZE(mac_mt_reg));
}
-static void __exit xt_mac_fini(void)
+static void __exit mac_mt_exit(void)
{
- xt_unregister_matches(xt_mac_match, ARRAY_SIZE(xt_mac_match));
+ xt_unregister_matches(mac_mt_reg, ARRAY_SIZE(mac_mt_reg));
}
-module_init(xt_mac_init);
-module_exit(xt_mac_fini);
+module_init(mac_mt_init);
+module_exit(mac_mt_exit);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index c02a7f8f392..9f78f6120fb 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -1,10 +1,13 @@
-/* Kernel module to match NFMARK values. */
-
-/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+/*
+ * xt_mark - Netfilter module to match NFMARK value
+ *
+ * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+ * Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ * Jan Engelhardt <jengelh@computergmbh.de>
*
- * 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 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>
@@ -15,19 +18,15 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-MODULE_DESCRIPTION("iptables mark matching module");
+MODULE_DESCRIPTION("Xtables: packet mark match");
MODULE_ALIAS("ipt_mark");
MODULE_ALIAS("ip6t_mark");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_mark_info *info = matchinfo;
@@ -35,11 +34,19 @@ match(const struct sk_buff *skb,
}
static bool
-checkentry(const char *tablename,
- const void *entry,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+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)
+{
+ const struct xt_mark_mtinfo1 *info = 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)
{
const struct xt_mark_info *minfo = matchinfo;
@@ -58,7 +65,7 @@ struct compat_xt_mark_info {
u_int16_t __pad2;
};
-static void compat_from_user(void *dst, void *src)
+static void mark_mt_compat_from_user_v0(void *dst, void *src)
{
const struct compat_xt_mark_info *cm = src;
struct xt_mark_info m = {
@@ -69,7 +76,7 @@ static void compat_from_user(void *dst, void *src)
memcpy(dst, &m, sizeof(m));
}
-static int compat_to_user(void __user *dst, void *src)
+static int mark_mt_compat_to_user_v0(void __user *dst, void *src)
{
const struct xt_mark_info *m = src;
struct compat_xt_mark_info cm = {
@@ -81,39 +88,62 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_match xt_mark_match[] __read_mostly = {
+static struct xt_match mark_mt_reg[] __read_mostly = {
{
.name = "mark",
+ .revision = 0,
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .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 = compat_from_user,
- .compat_to_user = compat_to_user,
+ .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 = 0,
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
+ .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,
+ .match = mark_mt,
+ .matchsize = sizeof(struct xt_mark_mtinfo1),
+ .me = THIS_MODULE,
+ },
};
-static int __init xt_mark_init(void)
+static int __init mark_mt_init(void)
{
- return xt_register_matches(xt_mark_match, ARRAY_SIZE(xt_mark_match));
+ return xt_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg));
}
-static void __exit xt_mark_fini(void)
+static void __exit mark_mt_exit(void)
{
- xt_unregister_matches(xt_mark_match, ARRAY_SIZE(xt_mark_match));
+ xt_unregister_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg));
}
-module_init(xt_mark_init);
-module_exit(xt_mark_fini);
+module_init(mark_mt_init);
+module_exit(mark_mt_exit);
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index e8ae10284ac..31daa819242 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -22,7 +22,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("x_tables multiple port match module");
+MODULE_DESCRIPTION("Xtables: multiple port matching for TCP, UDP, UDP-Lite, SCTP and DCCP");
MODULE_ALIAS("ipt_multiport");
MODULE_ALIAS("ip6t_multiport");
@@ -34,8 +34,8 @@ MODULE_ALIAS("ip6t_multiport");
/* Returns 1 if the port is matched by the test, 0 otherwise. */
static inline bool
-ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
- u_int8_t count, u_int16_t src, u_int16_t dst)
+ports_match_v0(const u_int16_t *portlist, enum xt_multiport_flags flags,
+ u_int8_t count, u_int16_t src, u_int16_t dst)
{
unsigned int i;
for (i = 0; i < count; i++) {
@@ -95,14 +95,10 @@ ports_match_v1(const struct xt_multiport_v1 *minfo,
}
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
__be16 _ports[2], *pptr;
const struct xt_multiport *multiinfo = matchinfo;
@@ -120,20 +116,15 @@ match(const struct sk_buff *skb,
return false;
}
- return ports_match(multiinfo->ports,
- multiinfo->flags, multiinfo->count,
- ntohs(pptr[0]), ntohs(pptr[1]));
+ return ports_match_v0(multiinfo->ports, multiinfo->flags,
+ multiinfo->count, ntohs(pptr[0]), ntohs(pptr[1]));
}
static bool
-match_v1(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
__be16 _ports[2], *pptr;
const struct xt_multiport_v1 *multiinfo = matchinfo;
@@ -173,11 +164,9 @@ check(u_int16_t proto,
/* Called when user tries to insert an entry of this type. */
static bool
-checkentry(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+multiport_mt_check_v0(const char *tablename, const void *info,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct ipt_ip *ip = info;
const struct xt_multiport *multiinfo = matchinfo;
@@ -187,11 +176,9 @@ checkentry(const char *tablename,
}
static bool
-checkentry_v1(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+multiport_mt_check(const char *tablename, const void *info,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct ipt_ip *ip = info;
const struct xt_multiport_v1 *multiinfo = matchinfo;
@@ -201,11 +188,9 @@ checkentry_v1(const char *tablename,
}
static bool
-checkentry6(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+multiport_mt6_check_v0(const char *tablename, const void *info,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct ip6t_ip6 *ip = info;
const struct xt_multiport *multiinfo = matchinfo;
@@ -215,11 +200,9 @@ checkentry6(const char *tablename,
}
static bool
-checkentry6_v1(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+multiport_mt6_check(const char *tablename, const void *info,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct ip6t_ip6 *ip = info;
const struct xt_multiport_v1 *multiinfo = matchinfo;
@@ -228,13 +211,13 @@ checkentry6_v1(const char *tablename,
multiinfo->count);
}
-static struct xt_match xt_multiport_match[] __read_mostly = {
+static struct xt_match multiport_mt_reg[] __read_mostly = {
{
.name = "multiport",
.family = AF_INET,
.revision = 0,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = multiport_mt_check_v0,
+ .match = multiport_mt_v0,
.matchsize = sizeof(struct xt_multiport),
.me = THIS_MODULE,
},
@@ -242,8 +225,8 @@ static struct xt_match xt_multiport_match[] __read_mostly = {
.name = "multiport",
.family = AF_INET,
.revision = 1,
- .checkentry = checkentry_v1,
- .match = match_v1,
+ .checkentry = multiport_mt_check,
+ .match = multiport_mt,
.matchsize = sizeof(struct xt_multiport_v1),
.me = THIS_MODULE,
},
@@ -251,8 +234,8 @@ static struct xt_match xt_multiport_match[] __read_mostly = {
.name = "multiport",
.family = AF_INET6,
.revision = 0,
- .checkentry = checkentry6,
- .match = match,
+ .checkentry = multiport_mt6_check_v0,
+ .match = multiport_mt_v0,
.matchsize = sizeof(struct xt_multiport),
.me = THIS_MODULE,
},
@@ -260,24 +243,23 @@ static struct xt_match xt_multiport_match[] __read_mostly = {
.name = "multiport",
.family = AF_INET6,
.revision = 1,
- .checkentry = checkentry6_v1,
- .match = match_v1,
+ .checkentry = multiport_mt6_check,
+ .match = multiport_mt,
.matchsize = sizeof(struct xt_multiport_v1),
.me = THIS_MODULE,
},
};
-static int __init xt_multiport_init(void)
+static int __init multiport_mt_init(void)
{
- return xt_register_matches(xt_multiport_match,
- ARRAY_SIZE(xt_multiport_match));
+ return xt_register_matches(multiport_mt_reg,
+ ARRAY_SIZE(multiport_mt_reg));
}
-static void __exit xt_multiport_fini(void)
+static void __exit multiport_mt_exit(void)
{
- xt_unregister_matches(xt_multiport_match,
- ARRAY_SIZE(xt_multiport_match));
+ xt_unregister_matches(multiport_mt_reg, ARRAY_SIZE(multiport_mt_reg));
}
-module_init(xt_multiport_init);
-module_exit(xt_multiport_fini);
+module_init(multiport_mt_init);
+module_exit(multiport_mt_exit);
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c
new file mode 100644
index 00000000000..d382f9cc38b
--- /dev/null
+++ b/net/netfilter/xt_owner.c
@@ -0,0 +1,211 @@
+/*
+ * Kernel module to match various things tied to sockets associated with
+ * locally generated outgoing packets.
+ *
+ * (C) 2000 Marc Boucher <marc@mbsi.ca>
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: <jengelh@computergmbh.de>
+ *
+ * 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/file.h>
+#include <net/sock.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_owner.h>
+#include <linux/netfilter_ipv4/ipt_owner.h>
+#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)
+{
+ const struct ipt_owner_info *info = matchinfo;
+ const struct file *filp;
+
+ if (skb->sk == NULL || skb->sk->sk_socket == NULL)
+ return false;
+
+ filp = skb->sk->sk_socket->file;
+ if (filp == NULL)
+ return false;
+
+ if (info->match & IPT_OWNER_UID)
+ if ((filp->f_uid != info->uid) ^
+ !!(info->invert & IPT_OWNER_UID))
+ return false;
+
+ if (info->match & IPT_OWNER_GID)
+ if ((filp->f_gid != info->gid) ^
+ !!(info->invert & IPT_OWNER_GID))
+ return false;
+
+ return true;
+}
+
+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)
+{
+ const struct ip6t_owner_info *info = matchinfo;
+ const struct file *filp;
+
+ if (skb->sk == NULL || skb->sk->sk_socket == NULL)
+ return false;
+
+ filp = skb->sk->sk_socket->file;
+ if (filp == NULL)
+ return false;
+
+ if (info->match & IP6T_OWNER_UID)
+ if ((filp->f_uid != info->uid) ^
+ !!(info->invert & IP6T_OWNER_UID))
+ return false;
+
+ if (info->match & IP6T_OWNER_GID)
+ if ((filp->f_gid != info->gid) ^
+ !!(info->invert & IP6T_OWNER_GID))
+ return false;
+
+ return true;
+}
+
+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)
+{
+ const struct xt_owner_match_info *info = matchinfo;
+ const struct file *filp;
+
+ if (skb->sk == NULL || skb->sk->sk_socket == NULL)
+ return (info->match ^ info->invert) == 0;
+ else if (info->match & info->invert & XT_OWNER_SOCKET)
+ /*
+ * Socket exists but user wanted ! --socket-exists.
+ * (Single ampersands intended.)
+ */
+ return false;
+
+ filp = skb->sk->sk_socket->file;
+ if (filp == NULL)
+ return ((info->match ^ info->invert) &
+ (XT_OWNER_UID | XT_OWNER_GID)) == 0;
+
+ if (info->match & XT_OWNER_UID)
+ if ((filp->f_uid != info->uid) ^
+ !!(info->invert & XT_OWNER_UID))
+ return false;
+
+ if (info->match & XT_OWNER_GID)
+ if ((filp->f_gid != info->gid) ^
+ !!(info->invert & XT_OWNER_GID))
+ return false;
+
+ 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)
+{
+ const struct ipt_owner_info *info = matchinfo;
+
+ if (info->match & (IPT_OWNER_PID | IPT_OWNER_SID | IPT_OWNER_COMM)) {
+ printk(KERN_WARNING KBUILD_MODNAME
+ ": PID, SID and command matching is not "
+ "supported anymore\n");
+ return false;
+ }
+
+ 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)
+{
+ const struct ip6t_owner_info *info = matchinfo;
+
+ if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
+ printk(KERN_WARNING KBUILD_MODNAME
+ ": PID and SID matching is not supported anymore\n");
+ return false;
+ }
+
+ return true;
+}
+
+static struct xt_match owner_mt_reg[] __read_mostly = {
+ {
+ .name = "owner",
+ .revision = 0,
+ .family = AF_INET,
+ .match = owner_mt_v0,
+ .matchsize = sizeof(struct ipt_owner_info),
+ .checkentry = owner_mt_check_v0,
+ .hooks = (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_POST_ROUTING),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "owner",
+ .revision = 0,
+ .family = AF_INET6,
+ .match = owner_mt6_v0,
+ .matchsize = sizeof(struct ip6t_owner_info),
+ .checkentry = owner_mt6_check_v0,
+ .hooks = (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_POST_ROUTING),
+ .me = THIS_MODULE,
+ },
+ {
+ .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,
+ .match = owner_mt,
+ .matchsize = sizeof(struct xt_owner_match_info),
+ .hooks = (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_POST_ROUTING),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init owner_mt_init(void)
+{
+ return xt_register_matches(owner_mt_reg, ARRAY_SIZE(owner_mt_reg));
+}
+
+static void __exit owner_mt_exit(void)
+{
+ xt_unregister_matches(owner_mt_reg, ARRAY_SIZE(owner_mt_reg));
+}
+
+module_init(owner_mt_init);
+module_exit(owner_mt_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
+MODULE_DESCRIPTION("Xtables: socket owner matching");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_owner");
+MODULE_ALIAS("ip6t_owner");
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index a4bab043a6d..4ec1094bda9 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -16,19 +16,15 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
-MODULE_DESCRIPTION("iptables bridge physical device match module");
+MODULE_DESCRIPTION("Xtables: Bridge physical device match");
MODULE_ALIAS("ipt_physdev");
MODULE_ALIAS("ip6t_physdev");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
int i;
static const char nulldevname[IFNAMSIZ];
@@ -99,11 +95,9 @@ match_outdev:
}
static bool
-checkentry(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+physdev_mt_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_physdev_info *info = matchinfo;
@@ -113,46 +107,45 @@ checkentry(const char *tablename,
if (info->bitmask & XT_PHYSDEV_OP_OUT &&
(!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
info->invert & XT_PHYSDEV_OP_BRIDGED) &&
- hook_mask & ((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
- (1 << NF_IP_POST_ROUTING))) {
+ 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_IP_LOCAL_OUT))
+ if (hook_mask & (1 << NF_INET_LOCAL_OUT))
return false;
}
return true;
}
-static struct xt_match xt_physdev_match[] __read_mostly = {
+static struct xt_match physdev_mt_reg[] __read_mostly = {
{
.name = "physdev",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = physdev_mt_check,
+ .match = physdev_mt,
.matchsize = sizeof(struct xt_physdev_info),
.me = THIS_MODULE,
},
{
.name = "physdev",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = physdev_mt_check,
+ .match = physdev_mt,
.matchsize = sizeof(struct xt_physdev_info),
.me = THIS_MODULE,
},
};
-static int __init xt_physdev_init(void)
+static int __init physdev_mt_init(void)
{
- return xt_register_matches(xt_physdev_match,
- ARRAY_SIZE(xt_physdev_match));
+ return xt_register_matches(physdev_mt_reg, ARRAY_SIZE(physdev_mt_reg));
}
-static void __exit xt_physdev_fini(void)
+static void __exit physdev_mt_exit(void)
{
- xt_unregister_matches(xt_physdev_match, ARRAY_SIZE(xt_physdev_match));
+ xt_unregister_matches(physdev_mt_reg, ARRAY_SIZE(physdev_mt_reg));
}
-module_init(xt_physdev_init);
-module_exit(xt_physdev_fini);
+module_init(physdev_mt_init);
+module_exit(physdev_mt_exit);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index a52925f12f3..7936f7e2325 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -11,65 +11,66 @@
#include <linux/if_packet.h>
#include <linux/in.h>
#include <linux/ip.h>
+#include <linux/ipv6.h>
#include <linux/netfilter/xt_pkttype.h>
#include <linux/netfilter/x_tables.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>");
-MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
+MODULE_DESCRIPTION("Xtables: link layer packet type match");
MODULE_ALIAS("ipt_pkttype");
MODULE_ALIAS("ip6t_pkttype");
-static bool match(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
+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)
{
- u_int8_t type;
const struct xt_pkttype_info *info = matchinfo;
+ u_int8_t type;
- if (skb->pkt_type == PACKET_LOOPBACK)
- type = MULTICAST(ip_hdr(skb)->daddr)
- ? PACKET_MULTICAST
- : PACKET_BROADCAST;
- else
+ if (skb->pkt_type != PACKET_LOOPBACK)
type = skb->pkt_type;
+ else if (match->family == AF_INET &&
+ ipv4_is_multicast(ip_hdr(skb)->daddr))
+ type = PACKET_MULTICAST;
+ else if (match->family == AF_INET6 &&
+ ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF)
+ type = PACKET_MULTICAST;
+ else
+ type = PACKET_BROADCAST;
return (type == info->pkttype) ^ info->invert;
}
-static struct xt_match xt_pkttype_match[] __read_mostly = {
+static struct xt_match pkttype_mt_reg[] __read_mostly = {
{
.name = "pkttype",
.family = AF_INET,
- .match = match,
+ .match = pkttype_mt,
.matchsize = sizeof(struct xt_pkttype_info),
.me = THIS_MODULE,
},
{
.name = "pkttype",
.family = AF_INET6,
- .match = match,
+ .match = pkttype_mt,
.matchsize = sizeof(struct xt_pkttype_info),
.me = THIS_MODULE,
},
};
-static int __init xt_pkttype_init(void)
+static int __init pkttype_mt_init(void)
{
- return xt_register_matches(xt_pkttype_match,
- ARRAY_SIZE(xt_pkttype_match));
+ return xt_register_matches(pkttype_mt_reg, ARRAY_SIZE(pkttype_mt_reg));
}
-static void __exit xt_pkttype_fini(void)
+static void __exit pkttype_mt_exit(void)
{
- xt_unregister_matches(xt_pkttype_match, ARRAY_SIZE(xt_pkttype_match));
+ xt_unregister_matches(pkttype_mt_reg, ARRAY_SIZE(pkttype_mt_reg));
}
-module_init(xt_pkttype_init);
-module_exit(xt_pkttype_fini);
+module_init(pkttype_mt_init);
+module_exit(pkttype_mt_exit);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 6d6d3b7fcbb..9e918add228 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -13,37 +13,38 @@
#include <linux/init.h>
#include <net/xfrm.h>
+#include <linux/netfilter.h>
#include <linux/netfilter/xt_policy.h>
#include <linux/netfilter/x_tables.h>
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_DESCRIPTION("Xtables IPsec policy matching module");
+MODULE_DESCRIPTION("Xtables: IPsec policy match");
MODULE_LICENSE("GPL");
static inline bool
-xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m,
- const union xt_policy_addr *a2, unsigned short family)
+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:
- return !((a1->a4.s_addr ^ a2->a4.s_addr) & m->a4.s_addr);
+ return ((a1->ip ^ a2->ip) & m->ip) == 0;
case AF_INET6:
- return !ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6);
+ return ipv6_masked_addr_cmp(&a1->in6, &m->in6, &a2->in6) == 0;
}
return false;
}
-static inline bool
+static bool
match_xfrm_state(const struct xfrm_state *x, const struct xt_policy_elem *e,
unsigned short family)
{
#define MATCH_ADDR(x,y,z) (!e->match.x || \
- (xt_addr_cmp(&e->x, &e->y, z, family) \
+ (xt_addr_cmp(&e->x, &e->y, (const union nf_inet_addr *)(z), family) \
^ e->invert.x))
#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
- return MATCH_ADDR(saddr, smask, (union xt_policy_addr *)&x->props.saddr) &&
- MATCH_ADDR(daddr, dmask, (union xt_policy_addr *)&x->id.daddr) &&
+ return MATCH_ADDR(saddr, smask, &x->props.saddr) &&
+ MATCH_ADDR(daddr, dmask, &x->id.daddr) &&
MATCH(proto, x->id.proto) &&
MATCH(mode, x->props.mode) &&
MATCH(spi, x->id.spi) &&
@@ -108,14 +109,11 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info,
return strict ? i == info->len : 0;
}
-static bool match(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
+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)
{
const struct xt_policy_info *info = matchinfo;
int ret;
@@ -133,9 +131,10 @@ static bool match(const struct sk_buff *skb,
return ret;
}
-static bool checkentry(const char *tablename, const void *ip_void,
- const struct xt_match *match,
- void *matchinfo, unsigned int hook_mask)
+static bool
+policy_mt_check(const char *tablename, const void *ip_void,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_policy_info *info = matchinfo;
@@ -144,14 +143,13 @@ static bool checkentry(const char *tablename, const void *ip_void,
"outgoing policy selected\n");
return false;
}
- /* hook values are equal for IPv4 and IPv6 */
- if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
+ if (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_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
+ if (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");
@@ -164,37 +162,36 @@ static bool checkentry(const char *tablename, const void *ip_void,
return true;
}
-static struct xt_match xt_policy_match[] __read_mostly = {
+static struct xt_match policy_mt_reg[] __read_mostly = {
{
.name = "policy",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = policy_mt_check,
+ .match = policy_mt,
.matchsize = sizeof(struct xt_policy_info),
.me = THIS_MODULE,
},
{
.name = "policy",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = policy_mt_check,
+ .match = policy_mt,
.matchsize = sizeof(struct xt_policy_info),
.me = THIS_MODULE,
},
};
-static int __init init(void)
+static int __init policy_mt_init(void)
{
- return xt_register_matches(xt_policy_match,
- ARRAY_SIZE(xt_policy_match));
+ return xt_register_matches(policy_mt_reg, ARRAY_SIZE(policy_mt_reg));
}
-static void __exit fini(void)
+static void __exit policy_mt_exit(void)
{
- xt_unregister_matches(xt_policy_match, ARRAY_SIZE(xt_policy_match));
+ xt_unregister_matches(policy_mt_reg, ARRAY_SIZE(policy_mt_reg));
}
-module_init(init);
-module_exit(fini);
+module_init(policy_mt_init);
+module_exit(policy_mt_exit);
MODULE_ALIAS("ipt_policy");
MODULE_ALIAS("ip6t_policy");
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index dae97445b87..3b021d0c522 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -11,16 +11,17 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
+MODULE_DESCRIPTION("Xtables: countdown quota match");
MODULE_ALIAS("ipt_quota");
MODULE_ALIAS("ip6t_quota");
static DEFINE_SPINLOCK(quota_lock);
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
struct xt_quota_info *q =
((const struct xt_quota_info *)matchinfo)->master;
@@ -40,9 +41,9 @@ match(const struct sk_buff *skb,
}
static bool
-checkentry(const char *tablename, const void *entry,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+quota_mt_check(const char *tablename, const void *entry,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_quota_info *q = matchinfo;
@@ -53,34 +54,34 @@ checkentry(const char *tablename, const void *entry,
return true;
}
-static struct xt_match xt_quota_match[] __read_mostly = {
+static struct xt_match quota_mt_reg[] __read_mostly = {
{
.name = "quota",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = quota_mt_check,
+ .match = quota_mt,
.matchsize = sizeof(struct xt_quota_info),
.me = THIS_MODULE
},
{
.name = "quota",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = quota_mt_check,
+ .match = quota_mt,
.matchsize = sizeof(struct xt_quota_info),
.me = THIS_MODULE
},
};
-static int __init xt_quota_init(void)
+static int __init quota_mt_init(void)
{
- return xt_register_matches(xt_quota_match, ARRAY_SIZE(xt_quota_match));
+ return xt_register_matches(quota_mt_reg, ARRAY_SIZE(quota_mt_reg));
}
-static void __exit xt_quota_fini(void)
+static void __exit quota_mt_exit(void)
{
- xt_unregister_matches(xt_quota_match, ARRAY_SIZE(xt_quota_match));
+ xt_unregister_matches(quota_mt_reg, ARRAY_SIZE(quota_mt_reg));
}
-module_init(xt_quota_init);
-module_exit(xt_quota_fini);
+module_init(quota_mt_init);
+module_exit(quota_mt_exit);
diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c
new file mode 100644
index 00000000000..fdb86a51514
--- /dev/null
+++ b/net/netfilter/xt_rateest.c
@@ -0,0 +1,178 @@
+/*
+ * (C) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * 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/gen_stats.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_rateest.h>
+#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)
+{
+ const struct xt_rateest_match_info *info = matchinfo;
+ struct gnet_stats_rate_est *r;
+ u_int32_t bps1, bps2, pps1, pps2;
+ bool ret = true;
+
+ spin_lock_bh(&info->est1->lock);
+ r = &info->est1->rstats;
+ if (info->flags & XT_RATEEST_MATCH_DELTA) {
+ bps1 = info->bps1 >= r->bps ? info->bps1 - r->bps : 0;
+ pps1 = info->pps1 >= r->pps ? info->pps1 - r->pps : 0;
+ } else {
+ bps1 = r->bps;
+ pps1 = r->pps;
+ }
+ spin_unlock_bh(&info->est1->lock);
+
+ if (info->flags & XT_RATEEST_MATCH_ABS) {
+ bps2 = info->bps2;
+ pps2 = info->pps2;
+ } else {
+ spin_lock_bh(&info->est2->lock);
+ r = &info->est2->rstats;
+ if (info->flags & XT_RATEEST_MATCH_DELTA) {
+ bps2 = info->bps2 >= r->bps ? info->bps2 - r->bps : 0;
+ pps2 = info->pps2 >= r->pps ? info->pps2 - r->pps : 0;
+ } else {
+ bps2 = r->bps;
+ pps2 = r->pps;
+ }
+ spin_unlock_bh(&info->est2->lock);
+ }
+
+ switch (info->mode) {
+ case XT_RATEEST_MATCH_LT:
+ if (info->flags & XT_RATEEST_MATCH_BPS)
+ ret &= bps1 < bps2;
+ if (info->flags & XT_RATEEST_MATCH_PPS)
+ ret &= pps1 < pps2;
+ break;
+ case XT_RATEEST_MATCH_GT:
+ if (info->flags & XT_RATEEST_MATCH_BPS)
+ ret &= bps1 > bps2;
+ if (info->flags & XT_RATEEST_MATCH_PPS)
+ ret &= pps1 > pps2;
+ break;
+ case XT_RATEEST_MATCH_EQ:
+ if (info->flags & XT_RATEEST_MATCH_BPS)
+ ret &= bps1 == bps2;
+ if (info->flags & XT_RATEEST_MATCH_PPS)
+ ret &= pps2 == pps2;
+ break;
+ }
+
+ ret ^= info->flags & XT_RATEEST_MATCH_INVERT ? true : false;
+ 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)
+{
+ struct xt_rateest_match_info *info = (void *)matchinfo;
+ struct xt_rateest *est1, *est2;
+
+ if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
+ XT_RATEEST_MATCH_REL)) != 1)
+ goto err1;
+
+ if (!(info->flags & (XT_RATEEST_MATCH_BPS | XT_RATEEST_MATCH_PPS)))
+ goto err1;
+
+ switch (info->mode) {
+ case XT_RATEEST_MATCH_EQ:
+ case XT_RATEEST_MATCH_LT:
+ case XT_RATEEST_MATCH_GT:
+ break;
+ default:
+ goto err1;
+ }
+
+ est1 = xt_rateest_lookup(info->name1);
+ if (!est1)
+ goto err1;
+
+ if (info->flags & XT_RATEEST_MATCH_REL) {
+ est2 = xt_rateest_lookup(info->name2);
+ if (!est2)
+ goto err2;
+ } else
+ est2 = NULL;
+
+
+ info->est1 = est1;
+ info->est2 = est2;
+ return true;
+
+err2:
+ xt_rateest_put(est1);
+err1:
+ return false;
+}
+
+static void xt_rateest_mt_destroy(const struct xt_match *match,
+ void *matchinfo)
+{
+ struct xt_rateest_match_info *info = (void *)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 int __init xt_rateest_mt_init(void)
+{
+ return xt_register_matches(xt_rateest_match,
+ ARRAY_SIZE(xt_rateest_match));
+}
+
+static void __exit xt_rateest_mt_fini(void)
+{
+ xt_unregister_matches(xt_rateest_match, ARRAY_SIZE(xt_rateest_match));
+}
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("xtables rate estimator match");
+MODULE_ALIAS("ipt_rateest");
+MODULE_ALIAS("ip6t_rateest");
+module_init(xt_rateest_mt_init);
+module_exit(xt_rateest_mt_fini);
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index cc3e76d77a9..7df1627c536 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -18,18 +18,14 @@
MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("X_tables realm match");
+MODULE_DESCRIPTION("Xtables: Routing realm match");
MODULE_ALIAS("ipt_realm");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_realm_info *info = matchinfo;
const struct dst_entry *dst = skb->dst;
@@ -37,25 +33,25 @@ match(const struct sk_buff *skb,
return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
}
-static struct xt_match realm_match __read_mostly = {
+static struct xt_match realm_mt_reg __read_mostly = {
.name = "realm",
- .match = match,
+ .match = realm_mt,
.matchsize = sizeof(struct xt_realm_info),
- .hooks = (1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
- (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN),
+ .hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_FORWARD) |
+ (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_LOCAL_IN),
.family = AF_INET,
.me = THIS_MODULE
};
-static int __init xt_realm_init(void)
+static int __init realm_mt_init(void)
{
- return xt_register_match(&realm_match);
+ return xt_register_match(&realm_mt_reg);
}
-static void __exit xt_realm_fini(void)
+static void __exit realm_mt_exit(void)
{
- xt_unregister_match(&realm_match);
+ xt_unregister_match(&realm_mt_reg);
}
-module_init(xt_realm_init);
-module_exit(xt_realm_fini);
+module_init(realm_mt_init);
+module_exit(realm_mt_exit);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index 3358273a47b..b718ec64333 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -11,7 +11,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kiran Kumar Immidi");
-MODULE_DESCRIPTION("Match for SCTP protocol packets");
+MODULE_DESCRIPTION("Xtables: SCTP protocol packet match");
MODULE_ALIAS("ipt_sctp");
MODULE_ALIAS("ip6t_sctp");
@@ -116,14 +116,9 @@ match_packet(const struct sk_buff *skb,
}
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
const struct xt_sctp_info *info = matchinfo;
sctp_sctphdr_t _sh, *sh;
@@ -153,11 +148,9 @@ match(const struct sk_buff *skb,
}
static bool
-checkentry(const char *tablename,
- const void *inf,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+sctp_mt_check(const char *tablename, const void *inf,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_sctp_info *info = matchinfo;
@@ -171,12 +164,12 @@ checkentry(const char *tablename,
| SCTP_CHUNK_MATCH_ONLY)));
}
-static struct xt_match xt_sctp_match[] __read_mostly = {
+static struct xt_match sctp_mt_reg[] __read_mostly = {
{
.name = "sctp",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = sctp_mt_check,
+ .match = sctp_mt,
.matchsize = sizeof(struct xt_sctp_info),
.proto = IPPROTO_SCTP,
.me = THIS_MODULE
@@ -184,23 +177,23 @@ static struct xt_match xt_sctp_match[] __read_mostly = {
{
.name = "sctp",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = sctp_mt_check,
+ .match = sctp_mt,
.matchsize = sizeof(struct xt_sctp_info),
.proto = IPPROTO_SCTP,
.me = THIS_MODULE
},
};
-static int __init xt_sctp_init(void)
+static int __init sctp_mt_init(void)
{
- return xt_register_matches(xt_sctp_match, ARRAY_SIZE(xt_sctp_match));
+ return xt_register_matches(sctp_mt_reg, ARRAY_SIZE(sctp_mt_reg));
}
-static void __exit xt_sctp_fini(void)
+static void __exit sctp_mt_exit(void)
{
- xt_unregister_matches(xt_sctp_match, ARRAY_SIZE(xt_sctp_match));
+ xt_unregister_matches(sctp_mt_reg, ARRAY_SIZE(sctp_mt_reg));
}
-module_init(xt_sctp_init);
-module_exit(xt_sctp_fini);
+module_init(sctp_mt_init);
+module_exit(sctp_mt_exit);
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index e0a528df19a..a776dc36a19 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -21,14 +21,10 @@ MODULE_ALIAS("ipt_state");
MODULE_ALIAS("ip6t_state");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_state_info *sinfo = matchinfo;
enum ip_conntrack_info ctinfo;
@@ -44,56 +40,54 @@ match(const struct sk_buff *skb,
return (sinfo->statemask & statebit);
}
-static bool check(const char *tablename,
- const void *inf,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool
+state_mt_check(const char *tablename, const void *inf,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
- "proto=%d\n", match->family);
+ "proto=%u\n", match->family);
return false;
}
return true;
}
-static void
-destroy(const struct xt_match *match, void *matchinfo)
+static void state_mt_destroy(const struct xt_match *match, void *matchinfo)
{
nf_ct_l3proto_module_put(match->family);
}
-static struct xt_match xt_state_match[] __read_mostly = {
+static struct xt_match state_mt_reg[] __read_mostly = {
{
.name = "state",
.family = AF_INET,
- .checkentry = check,
- .match = match,
- .destroy = destroy,
+ .checkentry = state_mt_check,
+ .match = state_mt,
+ .destroy = state_mt_destroy,
.matchsize = sizeof(struct xt_state_info),
.me = THIS_MODULE,
},
{
.name = "state",
.family = AF_INET6,
- .checkentry = check,
- .match = match,
- .destroy = destroy,
+ .checkentry = state_mt_check,
+ .match = state_mt,
+ .destroy = state_mt_destroy,
.matchsize = sizeof(struct xt_state_info),
.me = THIS_MODULE,
},
};
-static int __init xt_state_init(void)
+static int __init state_mt_init(void)
{
- return xt_register_matches(xt_state_match, ARRAY_SIZE(xt_state_match));
+ return xt_register_matches(state_mt_reg, ARRAY_SIZE(state_mt_reg));
}
-static void __exit xt_state_fini(void)
+static void __exit state_mt_exit(void)
{
- xt_unregister_matches(xt_state_match, ARRAY_SIZE(xt_state_match));
+ xt_unregister_matches(state_mt_reg, ARRAY_SIZE(state_mt_reg));
}
-module_init(xt_state_init);
-module_exit(xt_state_fini);
+module_init(state_mt_init);
+module_exit(state_mt_exit);
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
index 4089dae4e28..43133080da7 100644
--- a/net/netfilter/xt_statistic.c
+++ b/net/netfilter/xt_statistic.c
@@ -18,17 +18,17 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_DESCRIPTION("xtables statistical match module");
+MODULE_DESCRIPTION("Xtables: statistics-based matching (\"Nth\", random)");
MODULE_ALIAS("ipt_statistic");
MODULE_ALIAS("ip6t_statistic");
static DEFINE_SPINLOCK(nth_lock);
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
bool ret = info->flags & XT_STATISTIC_INVERT;
@@ -53,9 +53,9 @@ match(const struct sk_buff *skb,
}
static bool
-checkentry(const char *tablename, const void *entry,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+statistic_mt_check(const char *tablename, const void *entry,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_statistic_info *info = matchinfo;
@@ -66,36 +66,36 @@ checkentry(const char *tablename, const void *entry,
return true;
}
-static struct xt_match xt_statistic_match[] __read_mostly = {
+static struct xt_match statistic_mt_reg[] __read_mostly = {
{
.name = "statistic",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = statistic_mt_check,
+ .match = statistic_mt,
.matchsize = sizeof(struct xt_statistic_info),
.me = THIS_MODULE,
},
{
.name = "statistic",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
+ .checkentry = statistic_mt_check,
+ .match = statistic_mt,
.matchsize = sizeof(struct xt_statistic_info),
.me = THIS_MODULE,
},
};
-static int __init xt_statistic_init(void)
+static int __init statistic_mt_init(void)
{
- return xt_register_matches(xt_statistic_match,
- ARRAY_SIZE(xt_statistic_match));
+ return xt_register_matches(statistic_mt_reg,
+ ARRAY_SIZE(statistic_mt_reg));
}
-static void __exit xt_statistic_fini(void)
+static void __exit statistic_mt_exit(void)
{
- xt_unregister_matches(xt_statistic_match,
- ARRAY_SIZE(xt_statistic_match));
+ xt_unregister_matches(statistic_mt_reg,
+ ARRAY_SIZE(statistic_mt_reg));
}
-module_init(xt_statistic_init);
-module_exit(xt_statistic_fini);
+module_init(statistic_mt_init);
+module_exit(statistic_mt_exit);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 864133442cd..72f694d947f 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -16,19 +16,16 @@
#include <linux/textsearch.h>
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
-MODULE_DESCRIPTION("IP tables string match module");
+MODULE_DESCRIPTION("Xtables: string-based matching");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_string");
MODULE_ALIAS("ip6t_string");
-static bool match(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
+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)
{
const struct xt_string_info *conf = matchinfo;
struct ts_state state;
@@ -40,13 +37,12 @@ static bool match(const struct sk_buff *skb,
!= UINT_MAX) ^ conf->invert;
}
-#define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
+#define STRING_TEXT_PRIV(m) ((struct xt_string_info *)(m))
-static bool checkentry(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool
+string_mt_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_string_info *conf = matchinfo;
struct ts_config *ts_conf;
@@ -68,41 +64,41 @@ static bool checkentry(const char *tablename,
return true;
}
-static void destroy(const struct xt_match *match, void *matchinfo)
+static void string_mt_destroy(const struct xt_match *match, void *matchinfo)
{
textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
}
-static struct xt_match xt_string_match[] __read_mostly = {
+static struct xt_match string_mt_reg[] __read_mostly = {
{
.name = "string",
.family = AF_INET,
- .checkentry = checkentry,
- .match = match,
- .destroy = destroy,
+ .checkentry = string_mt_check,
+ .match = string_mt,
+ .destroy = string_mt_destroy,
.matchsize = sizeof(struct xt_string_info),
.me = THIS_MODULE
},
{
.name = "string",
.family = AF_INET6,
- .checkentry = checkentry,
- .match = match,
- .destroy = destroy,
+ .checkentry = string_mt_check,
+ .match = string_mt,
+ .destroy = string_mt_destroy,
.matchsize = sizeof(struct xt_string_info),
.me = THIS_MODULE
},
};
-static int __init xt_string_init(void)
+static int __init string_mt_init(void)
{
- return xt_register_matches(xt_string_match, ARRAY_SIZE(xt_string_match));
+ return xt_register_matches(string_mt_reg, ARRAY_SIZE(string_mt_reg));
}
-static void __exit xt_string_fini(void)
+static void __exit string_mt_exit(void)
{
- xt_unregister_matches(xt_string_match, ARRAY_SIZE(xt_string_match));
+ xt_unregister_matches(string_mt_reg, ARRAY_SIZE(string_mt_reg));
}
-module_init(xt_string_init);
-module_exit(xt_string_fini);
+module_init(string_mt_init);
+module_exit(string_mt_exit);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 84d401bfafa..d7a5b27fe81 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -20,19 +20,15 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-MODULE_DESCRIPTION("iptables TCP MSS match module");
+MODULE_DESCRIPTION("Xtables: TCP MSS match");
MODULE_ALIAS("ipt_tcpmss");
MODULE_ALIAS("ip6t_tcpmss");
static bool
-match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_tcpmss_match_info *info = matchinfo;
struct tcphdr _tcph, *th;
@@ -82,11 +78,11 @@ dropit:
return false;
}
-static struct xt_match xt_tcpmss_match[] __read_mostly = {
+static struct xt_match tcpmss_mt_reg[] __read_mostly = {
{
.name = "tcpmss",
.family = AF_INET,
- .match = match,
+ .match = tcpmss_mt,
.matchsize = sizeof(struct xt_tcpmss_match_info),
.proto = IPPROTO_TCP,
.me = THIS_MODULE,
@@ -94,23 +90,22 @@ static struct xt_match xt_tcpmss_match[] __read_mostly = {
{
.name = "tcpmss",
.family = AF_INET6,
- .match = match,
+ .match = tcpmss_mt,
.matchsize = sizeof(struct xt_tcpmss_match_info),
.proto = IPPROTO_TCP,
.me = THIS_MODULE,
},
};
-static int __init xt_tcpmss_init(void)
+static int __init tcpmss_mt_init(void)
{
- return xt_register_matches(xt_tcpmss_match,
- ARRAY_SIZE(xt_tcpmss_match));
+ return xt_register_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg));
}
-static void __exit xt_tcpmss_fini(void)
+static void __exit tcpmss_mt_exit(void)
{
- xt_unregister_matches(xt_tcpmss_match, ARRAY_SIZE(xt_tcpmss_match));
+ xt_unregister_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg));
}
-module_init(xt_tcpmss_init);
-module_exit(xt_tcpmss_fini);
+module_init(tcpmss_mt_init);
+module_exit(tcpmss_mt_exit);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 223f9bded67..4fa3b669f69 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -10,7 +10,7 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
-MODULE_DESCRIPTION("x_tables match for TCP and UDP(-Lite), supports IPv4 and IPv6");
+MODULE_DESCRIPTION("Xtables: TCP, UDP and UDP-Lite match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("xt_tcp");
MODULE_ALIAS("xt_udp");
@@ -68,14 +68,9 @@ tcp_find_option(u_int8_t option,
}
static bool
-tcp_match(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)
+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)
{
struct tcphdr _tcph, *th;
const struct xt_tcp *tcpinfo = matchinfo;
@@ -134,11 +129,9 @@ tcp_match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static bool
-tcp_checkentry(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+tcp_mt_check(const char *tablename, const void *info,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_tcp *tcpinfo = matchinfo;
@@ -147,14 +140,9 @@ tcp_checkentry(const char *tablename,
}
static bool
-udp_match(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)
+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)
{
struct udphdr _udph, *uh;
const struct xt_udp *udpinfo = matchinfo;
@@ -182,11 +170,9 @@ udp_match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static bool
-udp_checkentry(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+udp_mt_check(const char *tablename, const void *info,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_udp *udpinfo = matchinfo;
@@ -194,12 +180,12 @@ udp_checkentry(const char *tablename,
return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
}
-static struct xt_match xt_tcpudp_match[] __read_mostly = {
+static struct xt_match tcpudp_mt_reg[] __read_mostly = {
{
.name = "tcp",
.family = AF_INET,
- .checkentry = tcp_checkentry,
- .match = tcp_match,
+ .checkentry = tcp_mt_check,
+ .match = tcp_mt,
.matchsize = sizeof(struct xt_tcp),
.proto = IPPROTO_TCP,
.me = THIS_MODULE,
@@ -207,8 +193,8 @@ static struct xt_match xt_tcpudp_match[] __read_mostly = {
{
.name = "tcp",
.family = AF_INET6,
- .checkentry = tcp_checkentry,
- .match = tcp_match,
+ .checkentry = tcp_mt_check,
+ .match = tcp_mt,
.matchsize = sizeof(struct xt_tcp),
.proto = IPPROTO_TCP,
.me = THIS_MODULE,
@@ -216,8 +202,8 @@ static struct xt_match xt_tcpudp_match[] __read_mostly = {
{
.name = "udp",
.family = AF_INET,
- .checkentry = udp_checkentry,
- .match = udp_match,
+ .checkentry = udp_mt_check,
+ .match = udp_mt,
.matchsize = sizeof(struct xt_udp),
.proto = IPPROTO_UDP,
.me = THIS_MODULE,
@@ -225,8 +211,8 @@ static struct xt_match xt_tcpudp_match[] __read_mostly = {
{
.name = "udp",
.family = AF_INET6,
- .checkentry = udp_checkentry,
- .match = udp_match,
+ .checkentry = udp_mt_check,
+ .match = udp_mt,
.matchsize = sizeof(struct xt_udp),
.proto = IPPROTO_UDP,
.me = THIS_MODULE,
@@ -234,8 +220,8 @@ static struct xt_match xt_tcpudp_match[] __read_mostly = {
{
.name = "udplite",
.family = AF_INET,
- .checkentry = udp_checkentry,
- .match = udp_match,
+ .checkentry = udp_mt_check,
+ .match = udp_mt,
.matchsize = sizeof(struct xt_udp),
.proto = IPPROTO_UDPLITE,
.me = THIS_MODULE,
@@ -243,24 +229,23 @@ static struct xt_match xt_tcpudp_match[] __read_mostly = {
{
.name = "udplite",
.family = AF_INET6,
- .checkentry = udp_checkentry,
- .match = udp_match,
+ .checkentry = udp_mt_check,
+ .match = udp_mt,
.matchsize = sizeof(struct xt_udp),
.proto = IPPROTO_UDPLITE,
.me = THIS_MODULE,
},
};
-static int __init xt_tcpudp_init(void)
+static int __init tcpudp_mt_init(void)
{
- return xt_register_matches(xt_tcpudp_match,
- ARRAY_SIZE(xt_tcpudp_match));
+ return xt_register_matches(tcpudp_mt_reg, ARRAY_SIZE(tcpudp_mt_reg));
}
-static void __exit xt_tcpudp_fini(void)
+static void __exit tcpudp_mt_exit(void)
{
- xt_unregister_matches(xt_tcpudp_match, ARRAY_SIZE(xt_tcpudp_match));
+ xt_unregister_matches(tcpudp_mt_reg, ARRAY_SIZE(tcpudp_mt_reg));
}
-module_init(xt_tcpudp_init);
-module_exit(xt_tcpudp_fini);
+module_init(tcpudp_mt_init);
+module_exit(tcpudp_mt_exit);
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index f9c55dcd894..e9a8794bc3a 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -147,11 +147,10 @@ static void localtime_3(struct xtm *r, time_t time)
return;
}
-static bool xt_time_match(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
+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)
{
const struct xt_time_info *info = matchinfo;
unsigned int packet_time;
@@ -216,9 +215,10 @@ static bool xt_time_match(const struct sk_buff *skb,
return true;
}
-static bool xt_time_check(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
- unsigned int hook_mask)
+static bool
+time_mt_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_time_info *info = matchinfo;
@@ -232,39 +232,39 @@ static bool xt_time_check(const char *tablename, const void *ip,
return true;
}
-static struct xt_match xt_time_reg[] __read_mostly = {
+static struct xt_match time_mt_reg[] __read_mostly = {
{
.name = "time",
.family = AF_INET,
- .match = xt_time_match,
+ .match = time_mt,
.matchsize = sizeof(struct xt_time_info),
- .checkentry = xt_time_check,
+ .checkentry = time_mt_check,
.me = THIS_MODULE,
},
{
.name = "time",
.family = AF_INET6,
- .match = xt_time_match,
+ .match = time_mt,
.matchsize = sizeof(struct xt_time_info),
- .checkentry = xt_time_check,
+ .checkentry = time_mt_check,
.me = THIS_MODULE,
},
};
-static int __init xt_time_init(void)
+static int __init time_mt_init(void)
{
- return xt_register_matches(xt_time_reg, ARRAY_SIZE(xt_time_reg));
+ return xt_register_matches(time_mt_reg, ARRAY_SIZE(time_mt_reg));
}
-static void __exit xt_time_exit(void)
+static void __exit time_mt_exit(void)
{
- xt_unregister_matches(xt_time_reg, ARRAY_SIZE(xt_time_reg));
+ xt_unregister_matches(time_mt_reg, ARRAY_SIZE(time_mt_reg));
}
-module_init(xt_time_init);
-module_exit(xt_time_exit);
+module_init(time_mt_init);
+module_exit(time_mt_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
-MODULE_DESCRIPTION("netfilter time match");
+MODULE_DESCRIPTION("Xtables: time-based matching");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_time");
MODULE_ALIAS("ip6t_time");
diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c
index af75b8c3f20..9b8ed390a8e 100644
--- a/net/netfilter/xt_u32.c
+++ b/net/netfilter/xt_u32.c
@@ -88,11 +88,10 @@ static bool u32_match_it(const struct xt_u32 *data,
return true;
}
-static bool u32_match(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 net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
const struct xt_u32 *data = matchinfo;
bool ret;
@@ -101,37 +100,37 @@ static bool u32_match(const struct sk_buff *skb,
return ret ^ data->invert;
}
-static struct xt_match u32_reg[] __read_mostly = {
+static struct xt_match u32_mt_reg[] __read_mostly = {
{
.name = "u32",
.family = AF_INET,
- .match = u32_match,
+ .match = u32_mt,
.matchsize = sizeof(struct xt_u32),
.me = THIS_MODULE,
},
{
.name = "u32",
.family = AF_INET6,
- .match = u32_match,
+ .match = u32_mt,
.matchsize = sizeof(struct xt_u32),
.me = THIS_MODULE,
},
};
-static int __init xt_u32_init(void)
+static int __init u32_mt_init(void)
{
- return xt_register_matches(u32_reg, ARRAY_SIZE(u32_reg));
+ return xt_register_matches(u32_mt_reg, ARRAY_SIZE(u32_mt_reg));
}
-static void __exit xt_u32_exit(void)
+static void __exit u32_mt_exit(void)
{
- xt_unregister_matches(u32_reg, ARRAY_SIZE(u32_reg));
+ xt_unregister_matches(u32_mt_reg, ARRAY_SIZE(u32_mt_reg));
}
-module_init(xt_u32_init);
-module_exit(xt_u32_exit);
+module_init(u32_mt_init);
+module_exit(u32_mt_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
-MODULE_DESCRIPTION("netfilter u32 match module");
+MODULE_DESCRIPTION("Xtables: arbitrary byte matching");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_u32");
MODULE_ALIAS("ip6t_u32");