Netfilter/IPVS updates for net-next
Subsystems (8)
Pablo Neira Ayuso
maintainercover Netfilter/IPVS updates for net-next
Hi David,
The following patchset contains Netfilter/IPVS updates for your net-next tree:
1) No need to set ttl from reject action for the bridge family, from Taehee Yoo.
2) Use a fixed timeout for flow that are passed up from the flowtable to conntrack, from Florian Westphal.
3) More preparation patches for tproxy support for nf_tables, from Mate Eckl.
4) Remove unnecessary indirection in core IPv6 checksum function, from Florian Westphal.
5) Use nf_ct_get_tuplepr() from openvswitch, instead of opencoding it. From Florian Westphal.
6) socket match now selects socket infrastructure, instead of depending on it. From Mate Eckl.
7) Patch series to simplify conntrack tuple building/parsing from packet path and ctnetlink, from Florian Westphal.
8) Fetch timeout policy from protocol helpers, instead of doing it from core, from Florian Westphal.
9) Merge IPv4 and IPv6 protocol trackers into conntrack core, from Florian Westphal.
10) Depend on CONFIG_NF_TABLES_IPV6 and CONFIG_IP6_NF_IPTABLES respectively, instead of IPV6. Patch from Mate Eckl.
11) Add specific function for garbage collection in conncount, from Yi-Hung Wei.
12) Catch number of elements in the connlimit list, from Yi-Hung Wei.
13) Move locking to nf_conncount, from Yi-Hung Wei.
14) Series of patches to add lockless tree traversal in nf_conncount, from Yi-Hung Wei.
15) Resolve clash in matching conntracks when race happens, from Martynas Pumputis.
16) If connection entry times out, remove template entry from the ip_vs_conn_tab table to improve behaviour under flood, from Julian Anastasov.
17) Remove useless parameter from nf_ct_helper_ext_add(), from Gao feng.
18) Call abort from 2-phase commit protocol before requesting modules, make sure this is done under the mutex, from Florian Westphal.
19) Grab module reference when starting transaction, also from Florian.
20) Dynamically allocate expression info array for pre-parsing, from Florian.
21) Add per netns mutex for nf_tables, from Florian Westphal.
22) A couple of patches to simplify and refactor nf_osf code to prepare for nft_osf support.
23) Break evaluation on missing socket, from Mate Eckl.
24) Allow to match socket mark from nft_socket, from Mate Eckl.
25) Remove dependency on nf_defrag_ipv6, now that IPv6 tracker is built-in into nf_conntrack. From Florian Westphal.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Thanks!
----------------------------------------------------------------
The following changes since commit aea06eb276d99590f400c877ca2bd74b4db91330:
Merge branch 'TLS-offload-rx-netdev-and-mlx5' (2018-07-16 00:13:40 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git HEAD
for you to fetch changes up to 24c458c485c87eef97e91d2e180f222555528b11:
netfilter: nf_osf: add missing definitions to header file (2018-07-18 11:26:55 +0200)
----------------------------------------------------------------
Fernando Fernandez Mancera (1):
netfilter: nf_osf: add missing definitions to header file
Florian Westphal (18):
netfilter: flowtables: use fixed renew timeout on teardown
netfilter: utils: move nf_ip_checksum* from ipv4 to utils
netfilter: utils: move nf_ip6_checksum* from ipv6 to utils
openvswitch: use nf_ct_get_tuplepr, invert_tuplepr
netfilter: conntrack: remove ctnetlink callbacks from l3 protocol trackers
netfilter: conntrack: remove pkt_to_tuple indirection from l3 protocol trackers
netfilter: conntrack: remove invert_tuple indirection from l3 protocol trackers
netfilter: conntrack: remove get_l4proto indirection from l3 protocol trackers
netfilter: conntrack: avoid calls to l4proto invert_tuple
netfilter: conntrack: avoid l4proto pkt_to_tuple calls
netfilter: conntrack: remove get_timeout() indirection
netfilter: conntrack: remove l3proto abstraction
netfilter: nf_tables: add and use helper for module autoload
netfilter: nf_tables: make valid_genid callback mandatory
netfilter: nf_tables: take module reference when starting a batch
netfilter: nf_tables: avoid global info storage
netfilter: nf_tables: use dedicated mutex to guard transactions
ipv6: remove dependency of nf_defrag_ipv6 on ipv6 module
Gao Feng (1):
netfilter: Remove useless param helper of nf_ct_helper_ext_add
Julian Anastasov (3):
ipvs: provide just conn to ip_vs_state_name
ipvs: add assured state for conn templates
ipvs: drop conn templates under attack
Martynas Pumputis (1):
netfilter: nf_conntrack: resolve clash for matching conntracks
Máté Eckl (5):
netfilter: nft_tproxy: Move nf_tproxy_assign_sock() to nf_tproxy.h
netfilter: Kconfig: Make NETFILTER_XT_MATCH_SOCKET select NF_SOCKET_IPV4/6
netfilter: Kconfig: Change select IPv6 dependencies
netfilter: nft_socket: Break evaluation if no socket found
netfilter: nft_socket: Expose socket mark
Pablo Neira Ayuso (2):
netfilter: nf_osf: add nf_osf_match_one()
netfilter: nf_osf: add struct nf_osf_hdr_ctx
Taehee Yoo (1):
netfilter: nft_reject_bridge: remove unnecessary ttl set
Yi-Hung Wei (6):
netfilter: nf_conncount: Early exit for garbage collection
netfilter: nf_conncount: Switch to plain list
netfilter: nf_conncount: Early exit in nf_conncount_lookup() and cleanup
netfilter: nf_conncount: Move locking into count_tree()
netfilter: nf_conncount: Split insert and traversal
netfilter: nf_conncount: Add list lock and gc worker, and RCU for init tree search
include/linux/netfilter/nfnetlink.h | 1 +
include/linux/netfilter_ipv4.h | 11 -
include/linux/netfilter_ipv6.h | 5 -
include/net/ip_vs.h | 18 +-
include/net/ipv6.h | 28 -
include/net/ipv6_frag.h | 104 +++
include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 3 -
include/net/netfilter/nf_conntrack.h | 5 +
include/net/netfilter/nf_conntrack_core.h | 15 +-
include/net/netfilter/nf_conntrack_count.h | 37 +-
include/net/netfilter/nf_conntrack_helper.h | 4 +-
include/net/netfilter/nf_conntrack_l3proto.h | 84 --
include/net/netfilter/nf_conntrack_l4proto.h | 14 +-
include/net/netfilter/nf_conntrack_timeout.h | 18 +-
include/net/netfilter/nf_tproxy.h | 8 +
include/net/netns/nftables.h | 1 +
include/uapi/linux/netfilter/nf_osf.h | 11 +
include/uapi/linux/netfilter/nf_tables.h | 4 +-
include/uapi/linux/netfilter/xt_osf.h | 10 +-
net/bridge/netfilter/nft_reject_bridge.c | 3 +-
net/ieee802154/6lowpan/reassembly.c | 2 +-
net/ipv4/netfilter.c | 53 --
net/ipv4/netfilter/Kconfig | 22 +-
net/ipv4/netfilter/Makefile | 6 -
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 472 ------------
net/ipv6/netfilter.c | 62 --
net/ipv6/netfilter/Kconfig | 27 +-
net/ipv6/netfilter/Makefile | 6 -
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 460 -----------
net/ipv6/netfilter/nf_conntrack_reasm.c | 17 +-
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 4 +-
net/ipv6/reassembly.c | 92 +--
net/netfilter/Kconfig | 12 +-
net/netfilter/Makefile | 7 +-
net/netfilter/ipvs/ip_vs_conn.c | 67 +-
net/netfilter/ipvs/ip_vs_proto.c | 19 +-
net/netfilter/ipvs/ip_vs_proto_sctp.c | 2 +
net/netfilter/ipvs/ip_vs_proto_tcp.c | 2 +
net/netfilter/ipvs/ip_vs_proto_udp.c | 2 +
net/netfilter/ipvs/ip_vs_sync.c | 18 +-
net/netfilter/nf_conncount.c | 386 +++++++---
net/netfilter/nf_conntrack_core.c | 252 ++++--
net/netfilter/nf_conntrack_expect.c | 1 -
net/netfilter/nf_conntrack_helper.c | 6 +-
net/netfilter/nf_conntrack_l3proto_generic.c | 66 --
net/netfilter/nf_conntrack_netlink.c | 98 ++-
net/netfilter/nf_conntrack_proto.c | 845 +++++++++++++++------
net/netfilter/nf_conntrack_proto_dccp.c | 44 +-
net/netfilter/nf_conntrack_proto_generic.c | 32 +-
net/netfilter/nf_conntrack_proto_gre.c | 24 +-
net/{ipv4 => }/netfilter/nf_conntrack_proto_icmp.c | 19 +-
.../netfilter/nf_conntrack_proto_icmpv6.c | 17 +-
net/netfilter/nf_conntrack_proto_sctp.c | 46 +-
net/netfilter/nf_conntrack_proto_tcp.c | 52 +-
net/netfilter/nf_conntrack_proto_udp.c | 55 +-
net/netfilter/nf_conntrack_standalone.c | 28 +-
net/netfilter/nf_flow_table_core.c | 13 +-
net/netfilter/nf_nat_core.c | 8 -
net/netfilter/nf_osf.c | 252 +++---
net/netfilter/nf_tables_api.c | 194 +++--
net/netfilter/nfnetlink.c | 23 +-
net/netfilter/nfnetlink_cttimeout.c | 13 +-
net/netfilter/nft_chain_filter.c | 4 +-
net/netfilter/nft_connlimit.c | 36 +-
net/netfilter/nft_ct.c | 2 +-
net/netfilter/nft_dynset.c | 2 +
net/netfilter/nft_socket.c | 17 +-
net/netfilter/utils.c | 131 +++-
net/netfilter/xt_CT.c | 2 +-
net/netfilter/xt_TEE.c | 4 +-
net/netfilter/xt_TPROXY.c | 9 -
net/openvswitch/conntrack.c | 20 +-
72 files changed, 2029 insertions(+), 2408 deletions(-)
create mode 100644 include/net/ipv6_frag.h
delete mode 100644 include/net/netfilter/nf_conntrack_l3proto.h
delete mode 100644 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
delete mode 100644 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
delete mode 100644 net/netfilter/nf_conntrack_l3proto_generic.c
rename net/{ipv4 => }/netfilter/nf_conntrack_proto_icmp.c (96%)
rename net/{ipv6 => }/netfilter/nf_conntrack_proto_icmpv6.c (96%)Pablo Neira Ayuso
maintainerPATCH 1/38 netfilter: nft_reject_bridge: remove unnecessary ttl set
From: Taehee Yoo <[email protected]>
In the nft_reject_br_send_v4_tcp_reset(), a ttl is set by the nf_reject_iphdr_put(). so, below code is unnecessary.
--- net/bridge/netfilter/nft_reject_bridge.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/bridge/netfilter/nft_reject_bridge.c +1 -2
@@ -89,8 +89,7 @@ static void nft_reject_br_send_v4_tcp_reset(struct net *net, niph =nf_reject_iphdr_put (nskb, oldskb,IPPROTO_TCP , net->ipv4.sysctl_ip_default_ttl);nf_reject_ip_tcphdr_put (nskb, oldskb, oth); - niph->ttl = net->ipv4.sysctl_ip_default_ttl; - niph->tot_len =htons (nskb->len); + niph->tot_len =htons (nskb->len);ip_send_check (niph);nft_reject_br_push_etherhdr (oldskb, nskb);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 2/38 netfilter: flowtables: use fixed renew timeout on teardown
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
This is one of the very few external callers of ->get_timeouts(),
We can use a fixed timeout instead, conntrack core will refresh this in case a new packet comes within this period.
Use of ESTABLISHED timeout seems way too huge anyway.
--- net/netfilter/nf_flow_table_core.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
net/netfilter/nf_flow_table_core.c +5 -8
@@ -107,11 +107,12 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp) tcp->seen[1 ].td_maxwin =0 ; } +#define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ) +#define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ) +static void flow_offload_fixup_ct_state (struct nf_conn *ct) {const struct nf_conntrack_l4proto *l4proto; -struct net *net =nf_ct_net (ct); -unsigned int *timeouts;unsigned int timeout;int l4num;
@@ -123,14 +124,10 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct)if (!l4proto)return ; - timeouts = l4proto->get_timeouts (net); -if (!timeouts) -return ; -if (l4num ==IPPROTO_TCP ) - timeout = timeouts[TCP_CONNTRACK_ESTABLISHED ]; + timeout =NF_FLOWTABLE_TCP_PICKUP_TIMEOUT ;else if (l4num ==IPPROTO_UDP ) - timeout = timeouts[UDP_CT_REPLIED ]; + timeout =NF_FLOWTABLE_UDP_PICKUP_TIMEOUT ;else return ;
Signature · 1 line
2.11.0
Re: [PATCH 02/38] netfilter: flowtables: use fixed renew timeout on teardown
Quoted 8 lines · Pablo Neira Ayuso
From: Florian Westphal <[email protected]>
This is one of the very few external callers of ->get_timeouts(),
We can use a fixed timeout instead, conntrack core will refresh this in case a new packet comes within this period.
Use of ESTABLISHED timeout seems way too huge anyway.
It seems to me that this could easily break long-lived connections that are idle most of the time.
- Felix
Florian Westphal
maintainerRe: [PATCH 02/38] netfilter: flowtables: use fixed renew timeout on teardown
Quoted 11 lines · Felix Fietkau
Quoted 8 lines · Pablo Neira Ayuso
From: Florian Westphal <[email protected]>
This is one of the very few external callers of ->get_timeouts(),
We can use a fixed timeout instead, conntrack core will refresh this in case a new packet comes within this period.
Use of ESTABLISHED timeout seems way too huge anyway.
It seems to me that this could easily break long-lived connections that are idle most of the time.
Problem is that we don't know state of connection, since it was offloaded.
We don't know if connection 'died' with unacked data (short default timeout) or not (long default timeout).
So I would prefer to err on the 'evict idle connection that had no keepalives early' side rather than the 'add dead connection hanging around forever'.
Pablo Neira Ayuso
maintainerPATCH 3/38 netfilter: nft_tproxy: Move nf_tproxy_assign_sock() to nf_tproxy.h
In reply to Pablo Neira AyusoFrom: Máté Eckl <[email protected]>
This function is also necessary to implement nft tproxy support
--- include/net/netfilter/nf_tproxy.h | 8 ++++++++ net/netfilter/xt_TPROXY.c | 9 --------- 2 files changed, 8 insertions(+), 9 deletions(-)
include/net/netfilter/nf_tproxy.h +8 -0
@@ -17,6 +17,14 @@ static inline bool nf_tproxy_sk_is_transparent(struct sock *sk)return false; } +/* assign a socket to the skb -- consumes sk */ +static inline void nf_tproxy_assign_sock (struct sk_buff *skb,struct sock *sk) +{ +skb_orphan (skb); + skb->sk = sk; + skb->destructor = sock_edemux; +} +__be32 nf_tproxy_laddr4 (struct sk_buff *skb,__be32 user_laddr,__be32 daddr);/**
net/netfilter/xt_TPROXY.c +0 -9
@@ -36,15 +36,6 @@#include <net/netfilter/nf_tproxy.h> #include <linux/netfilter/xt_TPROXY.h> -/* assign a socket to the skb -- consumes sk */ -static void -nf_tproxy_assign_sock (struct sk_buff *skb,struct sock *sk) -{ -skb_orphan (skb); - skb->sk = sk; - skb->destructor = sock_edemux; -} -static unsigned int tproxy_tg4 (struct net *net,struct sk_buff *skb,__be32 laddr,__be16 lport,u_int32_t mark_mask,u_int32_t mark_value)
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 4/38 netfilter: utils: move nf_ip_checksum* from ipv4 to utils
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
allows to make nf_ip_checksum_partial static, it no longer has an external caller.
--- include/linux/netfilter_ipv4.h | 11 --------- net/ipv4/netfilter.c | 53 ---------------------------------------- net/netfilter/utils.c | 55 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 64 deletions(-)
include/linux/netfilter_ipv4.h +0 -11
@@ -23,9 +23,6 @@ struct nf_queue_entry;#ifdef CONFIG_INET __sum16 nf_ip_checksum (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,u_int8_t protocol); -__sum16 nf_ip_checksum_partial (struct sk_buff *skb,unsigned int hook, -unsigned int dataoff,unsigned int len, -u_int8_t protocol);int nf_ip_route (struct net *net,struct dst_entry **dst,struct flowi *fl,bool strict);int nf_ip_reroute (struct sk_buff *skb,const struct nf_queue_entry *entry);
@@ -35,14 +32,6 @@ static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, {return 0 ; } -static inline __sum16 nf_ip_checksum_partial (struct sk_buff *skb, -unsigned int hook, -unsigned int dataoff, -unsigned int len, -u_int8_t protocol) -{ -return 0 ; -}static inline int nf_ip_route (struct net *net,struct dst_entry **dst,struct flowi *fl,bool strict) {
net/ipv4/netfilter.c +0 -53
59 lines not on this page · raw message
net/netfilter/utils.c +55 -0
64 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 5/38 netfilter: utils: move nf_ip6_checksum* from ipv6 to utils
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
similar to previous change, this also allows to remove it from nf_ipv6_ops and avoid the indirection.
It also removes the bogus dependency of nf_conntrack_ipv6 on ipv6 module:
ipv6 checksum functions are built into kernel even if CONFIG_IPV6=m, but ipv6/netfilter.o isn't.
--- include/linux/netfilter_ipv6.h | 5 --- net/ipv6/netfilter.c | 62 ---------------------------------- net/netfilter/utils.c | 76 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 78 deletions(-)
include/linux/netfilter_ipv6.h +0 -5
@@ -30,11 +30,6 @@ struct nf_ipv6_ops {void (*route_input)(struct sk_buff *skb);int (*fragment)(struct net *net,struct sock *sk,struct sk_buff *skb,int (*output)(struct net *,struct sock *,struct sk_buff *)); -__sum16 (*checksum)(struct sk_buff *skb,unsigned int hook, -unsigned int dataoff,u_int8_t protocol); -__sum16 (*checksum_partial)(struct sk_buff *skb,unsigned int hook, -unsigned int dataoff,unsigned int len, -u_int8_t protocol);int (*route)(struct net *net,struct dst_entry **dst,struct flowi *fl,bool strict);int (*reroute)(struct sk_buff *skb,const struct nf_queue_entry *entry);
net/ipv6/netfilter.c +0 -62
78 lines not on this page · raw message
net/netfilter/utils.c +65 -11
110 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 6/38 openvswitch: use nf_ct_get_tuplepr, invert_tuplepr
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
These versions deal with the l3proto/l4proto details internally. It removes only caller of nf_ct_get_tuple, so make it static.
After this, l3proto->get_l4proto() can be removed in a followup patch.
--- include/net/netfilter/nf_conntrack_core.h | 7 ------- net/netfilter/nf_conntrack_core.c | 3 +-- net/openvswitch/conntrack.c | 17 +++-------------- 3 files changed, 4 insertions(+), 23 deletions(-)
include/net/netfilter/nf_conntrack_core.h +0 -7
@@ -40,13 +40,6 @@ void nf_conntrack_cleanup_start(void);void nf_conntrack_init_end (void );void nf_conntrack_cleanup_end (void ); -bool nf_ct_get_tuple (const struct sk_buff *skb,unsigned int nhoff, -unsigned int dataoff,u_int16_t l3num,u_int8_t protonum, -struct net *net, -struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_l3proto *l3proto, -const struct nf_conntrack_l4proto *l4proto); - bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig, const struct nf_conntrack_l3proto *l3proto,
net/netfilter/nf_conntrack_core.c +1 -2
@@ -222,7 +222,7 @@ static u32 hash_conntrack(const struct net *net,return scale_hash (hash_conntrack_raw (tuple, net)); } -bool +static bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff, unsigned int dataoff,
@@ -244,7 +244,6 @@ nf_ct_get_tuple(const struct sk_buff *skb,return l4proto->pkt_to_tuple (skb, dataoff, net, tuple); } -EXPORT_SYMBOL_GPL (nf_ct_get_tuple); bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, u_int16_t l3num,
net/openvswitch/conntrack.c +3 -14
@@ -607,23 +607,12 @@ static struct nf_conn * ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone, u8 l3num, struct sk_buff *skb, bool natted) { - const struct nf_conntrack_l3proto *l3proto; -const struct nf_conntrack_l4proto *l4proto; struct nf_conntrack_tuple tuple;struct nf_conntrack_tuple_hash *h;struct nf_conn *ct; -unsigned int dataoff; -u8 protonum; - l3proto =__nf_ct_l3proto_find (l3num); -if (l3proto->get_l4proto (skb,skb_network_offset (skb), &dataoff, - &protonum) <=0 ) { -pr_debug ("ovs_ct_find_existing: Can't get protonum\n" ); -return NULL ; - } - l4proto =__nf_ct_l4proto_find (l3num, protonum); -if (!nf_ct_get_tuple (skb,skb_network_offset (skb), dataoff, l3num, - protonum, net, &tuple, l3proto, l4proto)) { +if (!nf_ct_get_tuplepr (skb,skb_network_offset (skb), l3num, + net, &tuple)) {pr_debug ("ovs_ct_find_existing: Can't get tuple\n" );return NULL ; }
@@ -632,7 +621,7 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,if (natted) {struct nf_conntrack_tuple inverse; -if (!nf_ct_invert_tuple (&inverse, &tuple, l3proto, l4proto)) { +if (!nf_ct_invert_tuplepr (&inverse, &tuple)) {pr_debug ("ovs_ct_find_existing: Inversion failed!\n" );return NULL ; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 7/38 netfilter: Kconfig: Make NETFILTER_XT_MATCH_SOCKET select NF_SOCKET_IPV4/6
In reply to Pablo Neira AyusoFrom: Máté Eckl <[email protected]>
Instead of depending on it.
--- net/netfilter/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/Kconfig +2 -2
@@ -1492,8 +1492,8 @@ config NETFILTER_XT_MATCH_SOCKET depends on NETFILTER_ADVANCED depends on IPV6 || IPV6=n depends on IP6_NF_IPTABLES || IP6_NF_IPTABLES=n - depends on NF_SOCKET_IPV4 - depends on NF_SOCKET_IPV6 + select NF_SOCKET_IPV4 + select NF_SOCKET_IPV6 if IP6_NF_IPTABLES select NF_DEFRAG_IPV4 select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES != n help
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 8/38 netfilter: conntrack: remove ctnetlink callbacks from l3 protocol trackers
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
handle everything from ctnetlink directly.
After all these years we still only support ipv4 and ipv6, so it seems reasonable to remove l3 protocol tracker support and instead handle ipv4/ipv6 from a common, always builtin inet tracker.
Step 1: Get rid of all the l3proto->func() calls.
Start with ctnetlink, then move on to packet-path ones.
--- include/net/netfilter/nf_conntrack_core.h | 6 +- include/net/netfilter/nf_conntrack_l3proto.h | 8 --- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 47 ------------- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 48 ------------- net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 1 - net/netfilter/nf_conntrack_expect.c | 1 - net/netfilter/nf_conntrack_helper.c | 1 - net/netfilter/nf_conntrack_netlink.c | 96 +++++++++++++++++++------- net/netfilter/nf_conntrack_proto.c | 5 +- net/netfilter/nf_conntrack_standalone.c | 14 ++-- net/netfilter/nfnetlink_cttimeout.c | 1 - 11 files changed, 79 insertions(+), 149 deletions(-)
include/net/netfilter/nf_conntrack_core.h +2 -4
@@ -68,10 +68,8 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb)return ret; } -void -print_tuple (struct seq_file *s,const struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_l3proto *l3proto, -const struct nf_conntrack_l4proto *proto); +void print_tuple (struct seq_file *s,const struct nf_conntrack_tuple *tuple, +const struct nf_conntrack_l4proto *proto);#define CONNTRACK_LOCKS 1024
include/net/netfilter/nf_conntrack_l3proto.h +0 -8
@@ -46,14 +46,6 @@ struct nf_conntrack_l3proto {int (*get_l4proto)(const struct sk_buff *skb,unsigned int nhoff,unsigned int *dataoff,u_int8_t *protonum); -#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) -int (*tuple_to_nlattr)(struct sk_buff *skb, -const struct nf_conntrack_tuple *t); -int (*nlattr_to_tuple)(struct nlattr *tb[], -struct nf_conntrack_tuple *t); -const struct nla_policy *nla_policy; -#endif -/* Called when netns wants to use connection tracking */ int (*net_ns_get)(struct net *);void (*net_ns_put)(struct net *);
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +0 -47
65 lines not on this page · raw message
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +0 -48
66 lines not on this page · raw message
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +0 -1
@@ -23,7 +23,6 @@#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_l4proto.h> -#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> #endif
net/netfilter/nf_conntrack_expect.c +0 -1
@@ -610,7 +610,6 @@ static int exp_seq_show(struct seq_file *s, void *v) expect->tuple.src.l3num, expect->tuple.dst.protonum);print_tuple (s, &expect->tuple, -__nf_ct_l3proto_find (expect->tuple.src.l3num),__nf_ct_l4proto_find (expect->tuple.src.l3num, expect->tuple.dst.protonum));
net/netfilter/nf_conntrack_helper.c +0 -1
@@ -24,7 +24,6 @@#include <linux/rtnetlink.h> #include <net/netfilter/nf_conntrack.h> -#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_core.h>
net/netfilter/nf_conntrack_netlink.c +72 -24
168 lines not on this page · raw message
net/netfilter/nf_conntrack_proto.c +1 -4
@@ -294,10 +294,7 @@ int nf_ct_l3proto_register(const struct nf_conntrack_l3proto *proto)if (proto->l3proto >=NFPROTO_NUMPROTO )return -EBUSY ; -#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) -if (proto->tuple_to_nlattr && proto->nla_size ==0 ) -return -EINVAL ; -#endif +mutex_lock (&nf_ct_proto_mutex); old =rcu_dereference_protected (nf_ct_l3protos[proto->l3proto],lockdep_is_held (&nf_ct_proto_mutex));
net/netfilter/nf_conntrack_standalone.c +4 -10
@@ -24,7 +24,6 @@#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.h> -#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_helper.h>
@@ -38,10 +37,9 @@ MODULE_LICENSE("GPL");#ifdef CONFIG_NF_CONNTRACK_PROCFS void print_tuple (struct seq_file *s,const struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_l3proto *l3proto,const struct nf_conntrack_l4proto *l4proto) { -switch (l3proto->l3proto) { +switch (tuple->src.l3num) {case NFPROTO_IPV4 :seq_printf (s,"src=%pI4 dst=%pI4 " , &tuple->src.u3.ip, &tuple->dst.u3.ip);
@@ -282,7 +280,6 @@ static int ct_seq_show(struct seq_file *s, void *v) {struct nf_conntrack_tuple_hash *hash = v;struct nf_conn *ct =nf_ct_tuplehash_to_ctrack (hash); -const struct nf_conntrack_l3proto *l3proto;const struct nf_conntrack_l4proto *l4proto;struct net *net =seq_file_net (s);int ret =0 ;
@@ -303,14 +300,12 @@ static int ct_seq_show(struct seq_file *s, void *v)if (!net_eq (nf_ct_net (ct), net)) goto release; - l3proto =__nf_ct_l3proto_find (nf_ct_l3num (ct)); -WARN_ON (!l3proto); l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct));WARN_ON (!l4proto); ret = -ENOSPC ;seq_printf (s,"%-8s %u %-8s %u " , -l3proto_name (l3proto->l3proto),nf_ct_l3num (ct), +l3proto_name (nf_ct_l3num (ct)),nf_ct_l3num (ct),l4proto_name (l4proto->l4proto),nf_ct_protonum (ct));if (!test_bit (IPS_OFFLOAD_BIT , &ct->status))
@@ -320,7 +315,7 @@ static int ct_seq_show(struct seq_file *s, void *v) l4proto->print_conntrack (s, ct);print_tuple (s, &ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple, - l3proto, l4proto); + l4proto);ct_show_zone (s, ct,NF_CT_ZONE_DIR_ORIG );
@@ -333,8 +328,7 @@ static int ct_seq_show(struct seq_file *s, void *v)if (!(test_bit (IPS_SEEN_REPLY_BIT , &ct->status)))seq_puts (s,"[UNREPLIED] " ); -print_tuple (s, &ct->tuplehash[IP_CT_DIR_REPLY ].tuple, - l3proto, l4proto); +print_tuple (s, &ct->tuplehash[IP_CT_DIR_REPLY ].tuple, l4proto);ct_show_zone (s, ct,NF_CT_ZONE_DIR_REPL );
net/netfilter/nfnetlink_cttimeout.c +0 -1
@@ -26,7 +26,6 @@#include <net/sock.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.h> -#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_timeout.h>
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 9/38 netfilter: conntrack: remove pkt_to_tuple indirection from l3 protocol trackers
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
--- include/net/netfilter/nf_conntrack_l3proto.h | 7 ----- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 17 ----------- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 18 ------------ net/netfilter/nf_conntrack_core.c | 39 ++++++++++++++++++++++---- net/netfilter/nf_conntrack_l3proto_generic.c | 10 ------- 5 files changed, 33 insertions(+), 58 deletions(-)
include/net/netfilter/nf_conntrack_l3proto.h +0 -7
@@ -25,13 +25,6 @@ struct nf_conntrack_l3proto {u16 nla_size;/* -* Try to fill in the third arg: nhoff is offset of l3 proto -* hdr. Return true if possible. -*/ -bool (*pkt_to_tuple)(const struct sk_buff *skb,unsigned int nhoff, -struct nf_conntrack_tuple *tuple); - -/* * Invert the per-proto part of the tuple: ie. turn xmit into reply. * Some packets can't be inverted: return 0 in that case. */
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +0 -17
@@ -38,22 +38,6 @@ struct conntrack4_net {unsigned int users; }; -static bool ipv4_pkt_to_tuple (const struct sk_buff *skb,unsigned int nhoff, -struct nf_conntrack_tuple *tuple) -{ -const __be32 *ap; -__be32 _addrs[2 ]; - ap =skb_header_pointer (skb, nhoff + offsetof(struct iphdr , saddr), -sizeof (u_int32_t) *2 , _addrs); -if (ap ==NULL ) -return false; - - tuple->src.u3.ip = ap[0 ]; - tuple->dst.u3.ip = ap[1 ]; - -return true; -} -static bool ipv4_invert_tuple (struct nf_conntrack_tuple *tuple,const struct nf_conntrack_tuple *orig) {
@@ -322,7 +306,6 @@ static void ipv4_hooks_unregister(struct net *net)const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .l3proto =PF_INET , - .pkt_to_tuple = ipv4_pkt_to_tuple, .invert_tuple = ipv4_invert_tuple, .get_l4proto = ipv4_get_l4proto, .net_ns_get = ipv4_hooks_register,
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +0 -18
@@ -41,23 +41,6 @@ struct conntrack6_net {unsigned int users; }; -static bool ipv6_pkt_to_tuple (const struct sk_buff *skb,unsigned int nhoff, -struct nf_conntrack_tuple *tuple) -{ -const u_int32_t *ap; -u_int32_t _addrs[8 ]; - - ap =skb_header_pointer (skb, nhoff + offsetof(struct ipv6hdr , saddr), -sizeof (_addrs), _addrs); -if (ap ==NULL ) -return false; - -memcpy (tuple->src.u3.ip6, ap,sizeof (tuple->src.u3.ip6)); -memcpy (tuple->dst.u3.ip6, ap +4 ,sizeof (tuple->dst.u3.ip6)); - -return true; -} -static bool ipv6_invert_tuple (struct nf_conntrack_tuple *tuple,const struct nf_conntrack_tuple *orig) {
@@ -307,7 +290,6 @@ static void ipv6_hooks_unregister(struct net *net)const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { .l3proto =PF_INET6 , - .pkt_to_tuple = ipv6_pkt_to_tuple, .invert_tuple = ipv6_invert_tuple, .get_l4proto = ipv6_get_l4proto, .net_ns_get = ipv6_hooks_register,
net/netfilter/nf_conntrack_core.c +33 -6
@@ -230,15 +230,43 @@ nf_ct_get_tuple(const struct sk_buff *skb,u_int8_t protonum, struct net *net, struct nf_conntrack_tuple *tuple, - const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l4proto *l4proto) { + unsigned int size; +const __be32 *ap; +__be32 _addrs[8 ]; +memset (tuple,0 ,sizeof (*tuple)); tuple->src.l3num = l3num; -if (l3proto->pkt_to_tuple (skb, nhoff, tuple) ==0 ) +switch (l3num) { +case NFPROTO_IPV4 : + nhoff += offsetof(struct iphdr , saddr); + size =2 *sizeof (__be32); +break ; +case NFPROTO_IPV6 : + nhoff += offsetof(struct ipv6hdr , saddr); + size =sizeof (_addrs); +break ; +default : +return true; + } + + ap =skb_header_pointer (skb, nhoff, size, _addrs); +if (!ap)return false; +switch (l3num) { +case NFPROTO_IPV4 : + tuple->src.u3.ip = ap[0 ]; + tuple->dst.u3.ip = ap[1 ]; +break ; +case NFPROTO_IPV6 : +memcpy (tuple->src.u3.ip6, ap,sizeof (tuple->src.u3.ip6)); +memcpy (tuple->dst.u3.ip6, ap +4 ,sizeof (tuple->dst.u3.ip6)); +break ; + } + tuple->dst.protonum = protonum; tuple->dst.dir =IP_CT_DIR_ORIGINAL ;
@@ -267,7 +295,7 @@ bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, l4proto =__nf_ct_l4proto_find (l3num, protonum); ret =nf_ct_get_tuple (skb, nhoff, protoff, l3num, protonum, net, tuple, - l3proto, l4proto); + l4proto);rcu_read_unlock ();return ret;
@@ -1318,8 +1346,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,u32 hash;if (!nf_ct_get_tuple (skb,skb_network_offset (skb), - dataoff, l3num, protonum, net, &tuple, l3proto, - l4proto)) { + dataoff, l3num, protonum, net, &tuple, l4proto)) {pr_debug ("Can't get tuple\n" );return 0 ; }
@@ -1633,7 +1660,7 @@ static int nf_conntrack_update(struct net *net, struct sk_buff *skb) l4proto =nf_ct_l4proto_find_get (l3num, l4num);if (!nf_ct_get_tuple (skb,skb_network_offset (skb), dataoff, l3num, - l4num, net, &tuple, l3proto, l4proto)) + l4num, net, &tuple, l4proto))return -1 ;if (ct->status &IPS_SRC_NAT ) {
net/netfilter/nf_conntrack_l3proto_generic.c +0 -10
@@ -31,15 +31,6 @@#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> -static bool generic_pkt_to_tuple (const struct sk_buff *skb,unsigned int nhoff, -struct nf_conntrack_tuple *tuple) -{ -memset (&tuple->src.u3,0 ,sizeof (tuple->src.u3)); -memset (&tuple->dst.u3,0 ,sizeof (tuple->dst.u3)); - -return true; -} -static bool generic_invert_tuple (struct nf_conntrack_tuple *tuple,const struct nf_conntrack_tuple *orig) {
@@ -59,7 +50,6 @@ static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,struct nf_conntrack_l3proto nf_conntrack_l3proto_generic__read_mostly = { .l3proto =PF_UNSPEC , - .pkt_to_tuple = generic_pkt_to_tuple, .invert_tuple = generic_invert_tuple, .get_l4proto = generic_get_l4proto, };
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 10/38 netfilter: conntrack: remove invert_tuple indirection from l3 protocol trackers
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Its simpler to just handle it directly in nf_ct_invert_tuple(). Also gets rid of need to pass l3proto pointer to resolve_conntrack().
--- include/net/netfilter/nf_conntrack_core.h | 1 - include/net/netfilter/nf_conntrack_l3proto.h | 7 ------- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 10 ---------- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 3 +-- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 10 ---------- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 3 +-- net/netfilter/nf_conntrack_core.c | 26 ++++++++++++++++---------- net/netfilter/nf_conntrack_l3proto_generic.c | 10 ---------- 8 files changed, 18 insertions(+), 52 deletions(-)
include/net/netfilter/nf_conntrack_core.h +0 -1
@@ -42,7 +42,6 @@ void nf_conntrack_cleanup_end(void);bool nf_ct_invert_tuple (struct nf_conntrack_tuple *inverse,const struct nf_conntrack_tuple *orig, -const struct nf_conntrack_l3proto *l3proto,const struct nf_conntrack_l4proto *l4proto);/* Find a connection corresponding to a tuple. */
include/net/netfilter/nf_conntrack_l3proto.h +0 -7
@@ -25,13 +25,6 @@ struct nf_conntrack_l3proto {u16 nla_size;/* -* Invert the per-proto part of the tuple: ie. turn xmit into reply. -* Some packets can't be inverted: return 0 in that case. -*/ -bool (*invert_tuple)(struct nf_conntrack_tuple *inverse, -const struct nf_conntrack_tuple *orig); - -/* * Called before tracking. * *dataoff: offset of protocol header (TCP, UDP,...) in skb * *protonum: protocol number
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +0 -10
@@ -38,15 +38,6 @@ struct conntrack4_net {unsigned int users; }; -static bool ipv4_invert_tuple (struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_tuple *orig) -{ - tuple->src.u3.ip = orig->dst.u3.ip; - tuple->dst.u3.ip = orig->src.u3.ip; - -return true; -} -static int ipv4_get_l4proto (const struct sk_buff *skb,unsigned int nhoff,unsigned int *dataoff,u_int8_t *protonum) {
@@ -306,7 +297,6 @@ static void ipv4_hooks_unregister(struct net *net)const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .l3proto =PF_INET , - .invert_tuple = ipv4_invert_tuple, .get_l4proto = ipv4_get_l4proto, .net_ns_get = ipv4_hooks_register, .net_ns_put = ipv4_hooks_unregister,
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +1 -2
@@ -142,8 +142,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,/* Ordinarily, we'd expect the inverted tupleproto, but it's been preserved inside the ICMP. */ -if (!nf_ct_invert_tuple (&innertuple, &origtuple, - &nf_conntrack_l3proto_ipv4, innerproto)) { +if (!nf_ct_invert_tuple (&innertuple, &origtuple, innerproto)) {pr_debug ("icmp_error_message: no match\n" );return -NF_ACCEPT ; }
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +0 -10
@@ -41,15 +41,6 @@ struct conntrack6_net {unsigned int users; }; -static bool ipv6_invert_tuple (struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_tuple *orig) -{ -memcpy (tuple->src.u3.ip6, orig->dst.u3.ip6,sizeof (tuple->src.u3.ip6)); -memcpy (tuple->dst.u3.ip6, orig->src.u3.ip6,sizeof (tuple->dst.u3.ip6)); - -return true; -} -static int ipv6_get_l4proto (const struct sk_buff *skb,unsigned int nhoff,unsigned int *dataoff,u_int8_t *protonum) {
@@ -290,7 +281,6 @@ static void ipv6_hooks_unregister(struct net *net)const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { .l3proto =PF_INET6 , - .invert_tuple = ipv6_invert_tuple, .get_l4proto = ipv6_get_l4proto, .net_ns_get = ipv6_hooks_register, .net_ns_put = ipv6_hooks_unregister,
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +1 -2
@@ -152,8 +152,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,/* Ordinarily, we'd expect the inverted tupleproto, but it's been preserved inside the ICMP. */ -if (!nf_ct_invert_tuple (&intuple, &origtuple, - &nf_conntrack_l3proto_ipv6, inproto)) { +if (!nf_ct_invert_tuple (&intuple, &origtuple, inproto)) {pr_debug ("icmpv6_error: Can't invert tuple\n" );return -NF_ACCEPT ; }
net/netfilter/nf_conntrack_core.c +16 -10
@@ -305,14 +305,24 @@ EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr);bool nf_ct_invert_tuple (struct nf_conntrack_tuple *inverse,const struct nf_conntrack_tuple *orig, -const struct nf_conntrack_l3proto *l3proto,const struct nf_conntrack_l4proto *l4proto) {memset (inverse,0 ,sizeof (*inverse)); inverse->src.l3num = orig->src.l3num; -if (l3proto->invert_tuple (inverse, orig) ==0 ) -return false; + +switch (orig->src.l3num) { +case NFPROTO_IPV4 : + inverse->src.u3.ip = orig->dst.u3.ip; + inverse->dst.u3.ip = orig->src.u3.ip; +break ; +case NFPROTO_IPV6 : + inverse->src.u3.in6 = orig->dst.u3.in6; + inverse->dst.u3.in6 = orig->src.u3.in6; +break ; +default : +break ; + } inverse->dst.dir = !orig->dst.dir;
@@ -1222,7 +1232,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_free); static noinline struct nf_conntrack_tuple_hash *init_conntrack (struct net *net,struct nf_conn *tmpl,const struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_l3proto *l3proto,const struct nf_conntrack_l4proto *l4proto,struct sk_buff *skb,unsigned int dataoff,u32 hash)
@@ -1237,7 +1246,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,struct nf_conntrack_zone tmp;unsigned int *timeouts; -if (!nf_ct_invert_tuple (&repl_tuple, tuple, l3proto, l4proto)) { +if (!nf_ct_invert_tuple (&repl_tuple, tuple, l4proto)) {pr_debug ("Can't invert tuple.\n" );return NULL ; }
@@ -1334,7 +1343,6 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,unsigned int dataoff, u_int16_t l3num, u_int8_t protonum, - const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l4proto *l4proto) { const struct nf_conntrack_zone *zone;
@@ -1356,7 +1364,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, hash =hash_conntrack_raw (&tuple, net); h =__nf_conntrack_find_get (net, zone, &tuple, hash);if (!h) { - h =init_conntrack (net, tmpl, &tuple, l3proto, l4proto, + h =init_conntrack (net, tmpl, &tuple, l4proto, skb, dataoff, hash);if (!h)return 0 ;
@@ -1439,8 +1447,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, goto out; } repeat: - ret =resolve_normal_ct (net, tmpl, skb, dataoff, pf, protonum, - l3proto, l4proto); + ret =resolve_normal_ct (net, tmpl, skb, dataoff, pf, protonum, l4proto);if (ret <0 ) {/* Too stressed to deal. */ NF_CT_STAT_INC_ATOMIC (net, drop);
@@ -1497,7 +1504,6 @@ bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,rcu_read_lock (); ret =nf_ct_invert_tuple (inverse, orig, -__nf_ct_l3proto_find (orig->src.l3num),__nf_ct_l4proto_find (orig->src.l3num, orig->dst.protonum));rcu_read_unlock ();
net/netfilter/nf_conntrack_l3proto_generic.c +0 -10
@@ -31,15 +31,6 @@#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> -static bool generic_invert_tuple (struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_tuple *orig) -{ -memset (&tuple->src.u3,0 ,sizeof (tuple->src.u3)); -memset (&tuple->dst.u3,0 ,sizeof (tuple->dst.u3)); - -return true; -} -static int generic_get_l4proto (const struct sk_buff *skb,unsigned int nhoff,unsigned int *dataoff,u_int8_t *protonum) {
@@ -50,7 +41,6 @@ static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,struct nf_conntrack_l3proto nf_conntrack_l3proto_generic__read_mostly = { .l3proto =PF_UNSPEC , - .invert_tuple = generic_invert_tuple, .get_l4proto = generic_get_l4proto, };EXPORT_SYMBOL_GPL (nf_conntrack_l3proto_generic);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 11/38 netfilter: conntrack: remove get_l4proto indirection from l3 protocol trackers
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Handle it in the core instead.
ipv6_skip_exthdr() is built-in even if ipv6 is a module, i.e. this doesn't create an ipv6 dependency.
--- include/net/netfilter/nf_conntrack_l3proto.h | 8 -- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 30 ------- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 29 ------- net/netfilter/Makefile | 2 +- net/netfilter/nf_conntrack_core.c | 108 ++++++++++++++++++++----- net/netfilter/nf_conntrack_l3proto_generic.c | 46 ----------- net/netfilter/nf_conntrack_proto.c | 5 ++ 7 files changed, 94 insertions(+), 134 deletions(-) delete mode 100644 net/netfilter/nf_conntrack_l3proto_generic.c
include/net/netfilter/nf_conntrack_l3proto.h +0 -8
@@ -24,14 +24,6 @@ struct nf_conntrack_l3proto {/* size of tuple nlattr, fills a hole */ u16 nla_size; -/* -* Called before tracking. -* *dataoff: offset of protocol header (TCP, UDP,...) in skb -* *protonum: protocol number -*/ -int (*get_l4proto)(const struct sk_buff *skb,unsigned int nhoff, -unsigned int *dataoff,u_int8_t *protonum); -/* Called when netns wants to use connection tracking */ int (*net_ns_get)(struct net *);void (*net_ns_put)(struct net *);
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +0 -30
@@ -38,35 +38,6 @@ struct conntrack4_net {unsigned int users; }; -static int ipv4_get_l4proto (const struct sk_buff *skb,unsigned int nhoff, -unsigned int *dataoff,u_int8_t *protonum) -{ -const struct iphdr *iph; -struct iphdr _iph; - - iph =skb_header_pointer (skb, nhoff,sizeof (_iph), &_iph); -if (iph ==NULL ) -return -NF_ACCEPT ; - -/* Conntrack defragments packets, we might still see fragments -* inside ICMP packets though. */ -if (iph->frag_off &htons (IP_OFFSET )) -return -NF_ACCEPT ; - - *dataoff = nhoff + (iph->ihl <<2 ); - *protonum = iph->protocol; - -/* Check bogus IP headers */ -if (*dataoff > skb->len) { -pr_debug ("nf_conntrack_ipv4: bogus IPv4 packet: " -"nhoff %u, ihl %u, skblen %u\n" , - nhoff, iph->ihl <<2 , skb->len); -return -NF_ACCEPT ; - } - -return NF_ACCEPT ; -} -static unsigned int ipv4_helper (void *priv,struct sk_buff *skb,const struct nf_hook_state *state)
@@ -297,7 +268,6 @@ static void ipv4_hooks_unregister(struct net *net)const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .l3proto =PF_INET , - .get_l4proto = ipv4_get_l4proto, .net_ns_get = ipv4_hooks_register, .net_ns_put = ipv4_hooks_unregister, .me =THIS_MODULE ,
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +0 -29
@@ -41,34 +41,6 @@ struct conntrack6_net {unsigned int users; }; -static int ipv6_get_l4proto (const struct sk_buff *skb,unsigned int nhoff, -unsigned int *dataoff,u_int8_t *protonum) -{ -unsigned int extoff = nhoff +sizeof (struct ipv6hdr ); -__be16 frag_off; -int protoff; -u8 nexthdr; - -if (skb_copy_bits (skb, nhoff + offsetof(struct ipv6hdr , nexthdr), - &nexthdr,sizeof (nexthdr)) !=0 ) { -pr_debug ("ip6_conntrack_core: can't get nexthdr\n" ); -return -NF_ACCEPT ; - } - protoff =ipv6_skip_exthdr (skb, extoff, &nexthdr, &frag_off); -/* -* (protoff == skb->len) means the packet has not data, just -* IPv6 and possibly extensions headers, but it is tracked anyway -*/ -if (protoff <0 || (frag_off &htons (~0x7 )) !=0 ) { -pr_debug ("ip6_conntrack_core: can't find proto in pkt\n" ); -return -NF_ACCEPT ; - } - - *dataoff = protoff; - *protonum = nexthdr; -return NF_ACCEPT ; -} -static unsigned int ipv6_helper (void *priv,struct sk_buff *skb,const struct nf_hook_state *state)
@@ -281,7 +253,6 @@ static void ipv6_hooks_unregister(struct net *net)const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { .l3proto =PF_INET6 , - .get_l4proto = ipv6_get_l4proto, .net_ns_get = ipv6_hooks_register, .net_ns_put = ipv6_hooks_unregister, .me =THIS_MODULE ,
net/netfilter/Makefile +1 -1
@@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o -nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o +nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
net/netfilter/nf_conntrack_core.c +88 -20
174 lines not on this page · raw message
net/netfilter/nf_conntrack_l3proto_generic.c deleted +0 -46
46 lines not on this page · raw message
net/netfilter/nf_conntrack_proto.c +5 -0
@@ -35,6 +35,11 @@ EXPORT_SYMBOL_GPL(nf_ct_l3protos);static DEFINE_MUTEX (nf_ct_proto_mutex); +struct nf_conntrack_l3proto nf_conntrack_l3proto_generic__read_mostly = { + .l3proto =PF_UNSPEC , +}; +EXPORT_SYMBOL_GPL (nf_conntrack_l3proto_generic); +#ifdef CONFIG_SYSCTL static int nf_ct_register_sysctl(struct net *net,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 12/38 netfilter: conntrack: avoid calls to l4proto invert_tuple
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Handle the common cases (tcp, udp, etc). in the core and only do the indirect call for the protocols that need it (GRE for instance).
--- include/net/netfilter/nf_conntrack_l4proto.h | 2 +- net/netfilter/nf_conntrack_core.c | 8 +++++++- net/netfilter/nf_conntrack_proto_dccp.c | 10 ---------- net/netfilter/nf_conntrack_proto_generic.c | 10 ---------- net/netfilter/nf_conntrack_proto_gre.c | 10 ---------- net/netfilter/nf_conntrack_proto_sctp.c | 10 ---------- net/netfilter/nf_conntrack_proto_tcp.c | 10 ---------- net/netfilter/nf_conntrack_proto_udp.c | 12 ------------ 8 files changed, 8 insertions(+), 64 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +1 -1
@@ -36,7 +36,7 @@ struct nf_conntrack_l4proto { struct net *net, struct nf_conntrack_tuple *tuple);/* Invert the per-proto part of the tuple: ie. turn xmit into reply. -* Some packets can't be inverted: return 0 in that case. +* Only used by icmp, most protocols use a generic version. */ bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,const struct nf_conntrack_tuple *orig);
net/netfilter/nf_conntrack_core.c +7 -1
@@ -400,7 +400,13 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, inverse->dst.dir = !orig->dst.dir; inverse->dst.protonum = orig->dst.protonum; -return l4proto->invert_tuple (inverse, orig); + +if (unlikely (l4proto->invert_tuple)) +return l4proto->invert_tuple (inverse, orig); + + inverse->src.u.all = orig->dst.u.all; + inverse->dst.u.all = orig->src.u.all; +return true; }EXPORT_SYMBOL_GPL (nf_ct_invert_tuple);
net/netfilter/nf_conntrack_proto_dccp.c +0 -10
@@ -403,14 +403,6 @@ static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,return true; } -static bool dccp_invert_tuple (struct nf_conntrack_tuple *inv, -const struct nf_conntrack_tuple *tuple) -{ - inv->src.u.dccp.port = tuple->dst.u.dccp.port; - inv->dst.u.dccp.port = tuple->src.u.dccp.port; -return true; -} -static bool dccp_new (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff,unsigned int *timeouts) {
@@ -865,7 +857,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { .l3proto = AF_INET, .l4proto = IPPROTO_DCCP, .pkt_to_tuple = dccp_pkt_to_tuple, - .invert_tuple = dccp_invert_tuple, .new = dccp_new, .packet = dccp_packet, .get_timeouts = dccp_get_timeouts,
@@ -901,7 +892,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { .l3proto = AF_INET6, .l4proto = IPPROTO_DCCP, .pkt_to_tuple = dccp_pkt_to_tuple, - .invert_tuple = dccp_invert_tuple, .new = dccp_new, .packet = dccp_packet, .get_timeouts = dccp_get_timeouts,
net/netfilter/nf_conntrack_proto_generic.c +0 -10
@@ -41,15 +41,6 @@ static bool generic_pkt_to_tuple(const struct sk_buff *skb,return true; } -static bool generic_invert_tuple (struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_tuple *orig) -{ - tuple->src.u.all =0 ; - tuple->dst.u.all =0 ; - -return true; -} -static unsigned int *generic_get_timeouts (struct net *net) {return &(generic_pernet (net)->timeout);
@@ -168,7 +159,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = .l3proto = PF_UNSPEC, .l4proto = 255, .pkt_to_tuple = generic_pkt_to_tuple, - .invert_tuple = generic_invert_tuple, .packet = generic_packet, .get_timeouts = generic_get_timeouts, .new = generic_new,
net/netfilter/nf_conntrack_proto_gre.c +0 -10
@@ -179,15 +179,6 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ -/* invert gre part of tuple */ -static bool gre_invert_tuple (struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_tuple *orig) -{ - tuple->dst.u.gre.key = orig->src.u.gre.key; - tuple->src.u.gre.key = orig->dst.u.gre.key; -return true; -} -/* gre hdr info to tuple */ static bool gre_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct net *net,struct nf_conntrack_tuple *tuple)
@@ -356,7 +347,6 @@ static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { .l3proto = AF_INET, .l4proto = IPPROTO_GRE, .pkt_to_tuple = gre_pkt_to_tuple, - .invert_tuple = gre_invert_tuple,#ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = gre_print_conntrack,#endif
net/netfilter/nf_conntrack_proto_sctp.c +0 -10
@@ -166,14 +166,6 @@ static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,return true; } -static bool sctp_invert_tuple (struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_tuple *orig) -{ - tuple->src.u.sctp.port = orig->dst.u.sctp.port; - tuple->dst.u.sctp.port = orig->src.u.sctp.port; -return true; -} -#ifdef CONFIG_NF_CONNTRACK_PROCFS /* Print out the private part of the conntrack. */ static void sctp_print_conntrack (struct seq_file *s,struct nf_conn *ct)
@@ -781,7 +773,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { .l3proto = PF_INET, .l4proto = IPPROTO_SCTP, .pkt_to_tuple = sctp_pkt_to_tuple, - .invert_tuple = sctp_invert_tuple,#ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = sctp_print_conntrack,#endif
@@ -818,7 +809,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { .l3proto = PF_INET6, .l4proto = IPPROTO_SCTP, .pkt_to_tuple = sctp_pkt_to_tuple, - .invert_tuple = sctp_invert_tuple,#ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = sctp_print_conntrack,#endif
net/netfilter/nf_conntrack_proto_tcp.c +0 -10
@@ -293,14 +293,6 @@ static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,return true; } -static bool tcp_invert_tuple (struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_tuple *orig) -{ - tuple->src.u.tcp.port = orig->dst.u.tcp.port; - tuple->dst.u.tcp.port = orig->src.u.tcp.port; -return true; -} -#ifdef CONFIG_NF_CONNTRACK_PROCFS /* Print out the private part of the conntrack. */ static void tcp_print_conntrack (struct seq_file *s,struct nf_conn *ct)
@@ -1560,7 +1552,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = .l3proto = PF_INET, .l4proto = IPPROTO_TCP, .pkt_to_tuple = tcp_pkt_to_tuple, - .invert_tuple = tcp_invert_tuple,#ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = tcp_print_conntrack,#endif
@@ -1598,7 +1589,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = .l3proto = PF_INET6, .l4proto = IPPROTO_TCP, .pkt_to_tuple = tcp_pkt_to_tuple, - .invert_tuple = tcp_invert_tuple,#ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = tcp_print_conntrack,#endif
net/netfilter/nf_conntrack_proto_udp.c +0 -12
@@ -55,14 +55,6 @@ static bool udp_pkt_to_tuple(const struct sk_buff *skb,return true; } -static bool udp_invert_tuple (struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_tuple *orig) -{ - tuple->src.u.udp.port = orig->dst.u.udp.port; - tuple->dst.u.udp.port = orig->src.u.udp.port; -return true; -} -static unsigned int *udp_get_timeouts (struct net *net) {return udp_pernet (net)->timeouts;
@@ -302,7 +294,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = .l4proto = IPPROTO_UDP, .allow_clash = true, .pkt_to_tuple = udp_pkt_to_tuple, - .invert_tuple = udp_invert_tuple, .packet = udp_packet, .get_timeouts = udp_get_timeouts, .new = udp_new,
@@ -334,7 +325,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 = .l4proto = IPPROTO_UDPLITE, .allow_clash = true, .pkt_to_tuple = udp_pkt_to_tuple, - .invert_tuple = udp_invert_tuple, .packet = udp_packet, .get_timeouts = udp_get_timeouts, .new = udp_new,
@@ -366,7 +356,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = .l4proto = IPPROTO_UDP, .allow_clash = true, .pkt_to_tuple = udp_pkt_to_tuple, - .invert_tuple = udp_invert_tuple, .packet = udp_packet, .get_timeouts = udp_get_timeouts, .new = udp_new,
@@ -398,7 +387,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 = .l4proto = IPPROTO_UDPLITE, .allow_clash = true, .pkt_to_tuple = udp_pkt_to_tuple, - .invert_tuple = udp_invert_tuple, .packet = udp_packet, .get_timeouts = udp_get_timeouts, .new = udp_new,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 13/38 netfilter: conntrack: avoid l4proto pkt_to_tuple calls
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Handle common protocols (udp, tcp, ..), in the core and only do the call if needed by the l4proto tracker.
--- net/netfilter/nf_conntrack_core.c | 16 +++++++++++++++- net/netfilter/nf_conntrack_proto_dccp.c | 17 ----------------- net/netfilter/nf_conntrack_proto_sctp.c | 18 ------------------ net/netfilter/nf_conntrack_proto_tcp.c | 19 ------------------- net/netfilter/nf_conntrack_proto_udp.c | 23 ----------------------- 5 files changed, 15 insertions(+), 78 deletions(-)
net/netfilter/nf_conntrack_core.c +15 -1
@@ -235,6 +235,10 @@ nf_ct_get_tuple(const struct sk_buff *skb,unsigned int size;const __be32 *ap;__be32 _addrs[8 ]; +struct { +__be16 sport; +__be16 dport; + } _inet_hdr, *inet_hdr;memset (tuple,0 ,sizeof (*tuple));
@@ -270,7 +274,17 @@ nf_ct_get_tuple(const struct sk_buff *skb, tuple->dst.protonum = protonum; tuple->dst.dir =IP_CT_DIR_ORIGINAL ; -return l4proto->pkt_to_tuple (skb, dataoff, net, tuple); +if (unlikely (l4proto->pkt_to_tuple)) +return l4proto->pkt_to_tuple (skb, dataoff, net, tuple); + +/* Actually only need first 4 bytes to get ports. */ + inet_hdr =skb_header_pointer (skb, dataoff,sizeof (_inet_hdr), &_inet_hdr); +if (!inet_hdr) +return false; + + tuple->src.u.udp.port = inet_hdr->sport; + tuple->dst.u.udp.port = inet_hdr->dport; +return true; } static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
net/netfilter/nf_conntrack_proto_dccp.c +0 -17
@@ -388,21 +388,6 @@ static inline struct nf_dccp_net *dccp_pernet(struct net *net)return &net->ct.nf_ct_proto.dccp; } -static bool dccp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff, -struct net *net,struct nf_conntrack_tuple *tuple) -{ -struct dccp_hdr _hdr, *dh; - -/* Actually only need first 4 bytes to get ports. */ - dh =skb_header_pointer (skb, dataoff,4 , &_hdr); -if (dh ==NULL ) -return false; - - tuple->src.u.dccp.port = dh->dccph_sport; - tuple->dst.u.dccp.port = dh->dccph_dport; -return true; -} -static bool dccp_new (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff,unsigned int *timeouts) {
@@ -856,7 +841,6 @@ static struct nf_proto_net *dccp_get_net_proto(struct net *net)const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { .l3proto =AF_INET , .l4proto =IPPROTO_DCCP , - .pkt_to_tuple = dccp_pkt_to_tuple, .new = dccp_new, .packet = dccp_packet, .get_timeouts = dccp_get_timeouts,
@@ -891,7 +875,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4);const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { .l3proto =AF_INET6 , .l4proto =IPPROTO_DCCP , - .pkt_to_tuple = dccp_pkt_to_tuple, .new = dccp_new, .packet = dccp_packet, .get_timeouts = dccp_get_timeouts,
net/netfilter/nf_conntrack_proto_sctp.c +0 -18
@@ -150,22 +150,6 @@ static inline struct nf_sctp_net *sctp_pernet(struct net *net)return &net->ct.nf_ct_proto.sctp; } -static bool sctp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff, -struct net *net,struct nf_conntrack_tuple *tuple) -{ -const struct sctphdr *hp; -struct sctphdr _hdr; - -/* Actually only need first 4 bytes to get ports. */ - hp =skb_header_pointer (skb, dataoff,4 , &_hdr); -if (hp ==NULL ) -return false; - - tuple->src.u.sctp.port = hp->source; - tuple->dst.u.sctp.port = hp->dest; -return true; -} -#ifdef CONFIG_NF_CONNTRACK_PROCFS /* Print out the private part of the conntrack. */ static void sctp_print_conntrack (struct seq_file *s,struct nf_conn *ct)
@@ -772,7 +756,6 @@ static struct nf_proto_net *sctp_get_net_proto(struct net *net)const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { .l3proto =PF_INET , .l4proto =IPPROTO_SCTP , - .pkt_to_tuple = sctp_pkt_to_tuple, #ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = sctp_print_conntrack, #endif
@@ -808,7 +791,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp4);const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { .l3proto =PF_INET6 , .l4proto =IPPROTO_SCTP , - .pkt_to_tuple = sctp_pkt_to_tuple, #ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = sctp_print_conntrack, #endif
net/netfilter/nf_conntrack_proto_tcp.c +0 -19
@@ -276,23 +276,6 @@ static inline struct nf_tcp_net *tcp_pernet(struct net *net)return &net->ct.nf_ct_proto.tcp; } -static bool tcp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff, -struct net *net,struct nf_conntrack_tuple *tuple) -{ -const struct tcphdr *hp; -struct tcphdr _hdr; - -/* Actually only need first 4 bytes to get ports. */ - hp =skb_header_pointer (skb, dataoff,4 , &_hdr); -if (hp ==NULL ) -return false; - - tuple->src.u.tcp.port = hp->source; - tuple->dst.u.tcp.port = hp->dest; - -return true; -} -#ifdef CONFIG_NF_CONNTRACK_PROCFS /* Print out the private part of the conntrack. */ static void tcp_print_conntrack (struct seq_file *s,struct nf_conn *ct)
@@ -1551,7 +1534,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = { .l3proto = PF_INET, .l4proto = IPPROTO_TCP, - .pkt_to_tuple = tcp_pkt_to_tuple, #ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = tcp_print_conntrack,#endif
@@ -1588,7 +1570,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = { .l3proto = PF_INET6, .l4proto = IPPROTO_TCP, - .pkt_to_tuple = tcp_pkt_to_tuple, #ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = tcp_print_conntrack,#endif
net/netfilter/nf_conntrack_proto_udp.c +0 -23
@@ -36,25 +36,6 @@ static inline struct nf_udp_net *udp_pernet(struct net *net)return &net->ct.nf_ct_proto.udp; } -static bool udp_pkt_to_tuple (const struct sk_buff *skb, -unsigned int dataoff, -struct net *net, -struct nf_conntrack_tuple *tuple) -{ -const struct udphdr *hp; -struct udphdr _hdr; - -/* Actually only need first 4 bytes to get ports. */ - hp =skb_header_pointer (skb, dataoff,4 , &_hdr); -if (hp ==NULL ) -return false; - - tuple->src.u.udp.port = hp->source; - tuple->dst.u.udp.port = hp->dest; - -return true; -} -static unsigned int *udp_get_timeouts (struct net *net) {return udp_pernet (net)->timeouts;
@@ -293,7 +274,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = .l3proto = PF_INET, .l4proto = IPPROTO_UDP, .allow_clash = true, - .pkt_to_tuple = udp_pkt_to_tuple, .packet = udp_packet, .get_timeouts = udp_get_timeouts, .new = udp_new,
@@ -324,7 +304,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 = .l3proto = PF_INET, .l4proto = IPPROTO_UDPLITE, .allow_clash = true, - .pkt_to_tuple = udp_pkt_to_tuple, .packet = udp_packet, .get_timeouts = udp_get_timeouts, .new = udp_new,
@@ -355,7 +334,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = .l3proto = PF_INET6, .l4proto = IPPROTO_UDP, .allow_clash = true, - .pkt_to_tuple = udp_pkt_to_tuple, .packet = udp_packet, .get_timeouts = udp_get_timeouts, .new = udp_new,
@@ -386,7 +364,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 = .l3proto = PF_INET6, .l4proto = IPPROTO_UDPLITE, .allow_clash = true, - .pkt_to_tuple = udp_pkt_to_tuple, .packet = udp_packet, .get_timeouts = udp_get_timeouts, .new = udp_new,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 14/38 netfilter: conntrack: remove get_timeout() indirection
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Not needed, we can have the l4trackers fetch it themselvs.
--- include/net/netfilter/nf_conntrack_l4proto.h | 8 ++------ include/net/netfilter/nf_conntrack_timeout.h | 18 ++++-------------- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 16 +++++++++++----- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 14 ++++++++++---- net/netfilter/nf_conntrack_core.c | 16 ++-------------- net/netfilter/nf_conntrack_proto_dccp.c | 17 +++++++---------- net/netfilter/nf_conntrack_proto_generic.c | 22 ++++++++++++---------- net/netfilter/nf_conntrack_proto_gre.c | 14 ++++++++++---- net/netfilter/nf_conntrack_proto_sctp.c | 18 ++++++++---------- net/netfilter/nf_conntrack_proto_tcp.c | 23 +++++++++++------------ net/netfilter/nf_conntrack_proto_udp.c | 20 +++++++++++++------- net/netfilter/nfnetlink_cttimeout.c | 12 ++++-------- 12 files changed, 94 insertions(+), 104 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +2 -6
@@ -45,13 +45,12 @@ struct nf_conntrack_l4proto {int (*packet)(struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo, -unsigned int *timeouts); +enum ip_conntrack_info ctinfo);/* Called when a new connection for this protocol found; * returns TRUE if it's OK. If so, packet() called next. */ bool (*new)(struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts); +unsigned int dataoff);/* Called when a conntrack entry is destroyed */ void (*destroy)(struct nf_conn *ct);
@@ -63,9 +62,6 @@ struct nf_conntrack_l4proto {/* called by gc worker if table is full */ bool (*can_early_drop)(const struct nf_conn *ct); -/* Return the array of timeouts for this protocol. */ -unsigned int *(*get_timeouts)(struct net *net); -/* convert protoinfo to nfnetink attributes */ int (*to_nlattr)(struct sk_buff *skb,struct nlattr *nla,struct nf_conn *ct);
include/net/netfilter/nf_conntrack_timeout.h +4 -14
@@ -67,27 +67,17 @@ struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct,#endif }; -static inline unsigned int * -nf_ct_timeout_lookup (struct net *net,struct nf_conn *ct, -const struct nf_conntrack_l4proto *l4proto) +static inline unsigned int *nf_ct_timeout_lookup (const struct nf_conn *ct) { +unsigned int *timeouts =NULL ;#ifdef CONFIG_NF_CONNTRACK_TIMEOUT struct nf_conn_timeout *timeout_ext; -unsigned int *timeouts; timeout_ext =nf_ct_timeout_find (ct); -if (timeout_ext) { +if (timeout_ext) timeouts =nf_ct_timeout_data (timeout_ext); -if (unlikely (!timeouts)) - timeouts = l4proto->get_timeouts (net); - }else { - timeouts = l4proto->get_timeouts (net); - } - -return timeouts; -#else -return l4proto->get_timeouts (net);#endif +return timeouts; }#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +11 -5
@@ -19,6 +19,7 @@#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_core.h> +#include <net/netfilter/nf_conntrack_timeout.h> #include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_log.h>
@@ -80,12 +81,16 @@ static unsigned int *icmp_get_timeouts(struct net *net)static int icmp_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo, -unsigned int *timeout) +enum ip_conntrack_info ctinfo) {/* Do not immediately delete the connection after the first successful reply to avoid excessive conntrackd traffic and also to handle correctly ICMP echo reply duplicates. */ +unsigned int *timeout =nf_ct_timeout_lookup (ct); + +if (!timeout) + timeout =icmp_get_timeouts (nf_ct_net (ct)); +nf_ct_refresh_acct (ct, ctinfo, skb, *timeout);return NF_ACCEPT ;
@@ -93,7 +98,7 @@ static int icmp_packet(struct nf_conn *ct,/* Called when a new connection for this protocol found. */ static bool icmp_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts) +unsigned int dataoff) {static const u_int8_t valid_new[] = { [ICMP_ECHO ] =1 ,
@@ -280,9 +285,11 @@ static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[],struct nf_icmp_net *in =icmp_pernet (net);if (tb[CTA_TIMEOUT_ICMP_TIMEOUT ]) { +if (!timeout) + timeout = &in->timeout; *timeout =ntohl (nla_get_be32 (tb[CTA_TIMEOUT_ICMP_TIMEOUT ])) *HZ ; - }else { + }else if (timeout) {/* Set default ICMP timeout. */ *timeout = in->timeout; }
@@ -357,7 +364,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = .pkt_to_tuple = icmp_pkt_to_tuple, .invert_tuple = icmp_invert_tuple, .packet = icmp_packet, - .get_timeouts = icmp_get_timeouts, .new = icmp_new, .error = icmp_error, .destroy = NULL,
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +10 -4
@@ -23,6 +23,7 @@#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_core.h> +#include <net/netfilter/nf_conntrack_timeout.h> #include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> #include <net/netfilter/nf_log.h>
@@ -93,9 +94,13 @@ static unsigned int *icmpv6_get_timeouts(struct net *net)static int icmpv6_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo, -unsigned int *timeout) +enum ip_conntrack_info ctinfo) { +unsigned int *timeout =nf_ct_timeout_lookup (ct); + +if (!timeout) + timeout =icmpv6_get_timeouts (nf_ct_net (ct)); +/* Do not immediately delete the connection after the first successful reply to avoid excessive conntrackd traffic and also to handle correctly ICMP echo reply duplicates. */
@@ -106,7 +111,7 @@ static int icmpv6_packet(struct nf_conn *ct,/* Called when a new connection for this protocol found. */ static bool icmpv6_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts) +unsigned int dataoff) {static const u_int8_t valid_new[] = { [ICMPV6_ECHO_REQUEST -128 ] =1 ,
@@ -280,6 +285,8 @@ static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[],unsigned int *timeout = data;struct nf_icmp_net *in =icmpv6_pernet (net); +if (!timeout) + timeout =icmpv6_get_timeouts (net);if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT ]) { *timeout =ntohl (nla_get_be32 (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT ])) *HZ ;
@@ -358,7 +365,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = .pkt_to_tuple = icmpv6_pkt_to_tuple, .invert_tuple = icmpv6_invert_tuple, .packet = icmpv6_packet, - .get_timeouts = icmpv6_get_timeouts, .new = icmpv6_new, .error = icmpv6_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
net/netfilter/nf_conntrack_core.c +2 -14
@@ -1337,7 +1337,6 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,const struct nf_conntrack_zone *zone;struct nf_conn_timeout *timeout_ext;struct nf_conntrack_zone tmp; -unsigned int *timeouts;if (!nf_ct_invert_tuple (&repl_tuple, tuple, l4proto)) {pr_debug ("Can't invert tuple.\n" );
@@ -1356,15 +1355,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, } timeout_ext = tmpl ?nf_ct_timeout_find (tmpl) :NULL ; -if (timeout_ext) { - timeouts =nf_ct_timeout_data (timeout_ext); -if (unlikely (!timeouts)) - timeouts = l4proto->get_timeouts (net); - }else { - timeouts = l4proto->get_timeouts (net); - } -if (!l4proto->new (ct, skb, dataoff, timeouts)) { +if (!l4proto->new (ct, skb, dataoff)) {nf_conntrack_free (ct);pr_debug ("can't track with proto module\n" );return NULL ;
@@ -1493,7 +1485,6 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,const struct nf_conntrack_l4proto *l4proto;struct nf_conn *ct, *tmpl;enum ip_conntrack_info ctinfo; -unsigned int *timeouts;u_int8_t protonum;int dataoff, ret;
@@ -1552,10 +1543,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, goto out; } -/* Decide what timeout policy we want to apply to this flow. */ - timeouts =nf_ct_timeout_lookup (net, ct, l4proto); - - ret = l4proto->packet (ct, skb, dataoff, ctinfo, timeouts); + ret = l4proto->packet (ct, skb, dataoff, ctinfo);if (ret <=0 ) {/* Invalid: inverse of the return code tells * the netfilter core what to do */
net/netfilter/nf_conntrack_proto_dccp.c +7 -10
@@ -23,6 +23,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_conntrack_timeout.h> #include <net/netfilter/nf_log.h> /* Timeouts are based on values from RFC4340:
@@ -389,7 +390,7 @@ static inline struct nf_dccp_net *dccp_pernet(struct net *net) }static bool dccp_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts) +unsigned int dataoff) {struct net *net =nf_ct_net (ct);struct nf_dccp_net *dn;
@@ -437,19 +438,14 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh)ntohl (dhack->dccph_ack_nr_low); } -static unsigned int *dccp_get_timeouts (struct net *net) -{ -return dccp_pernet (net)->dccp_timeout; -} -static int dccp_packet (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,enum ip_conntrack_info ctinfo, -unsigned int *timeouts) +unsigned int dataoff,enum ip_conntrack_info ctinfo) {enum ip_conntrack_dir dir =CTINFO2DIR (ctinfo);struct dccp_hdr _dh, *dh;u_int8_t type, old_state, new_state;enum ct_dccp_roles role; +unsigned int *timeouts; dh =skb_header_pointer (skb, dataoff,sizeof (_dh), &_dh);BUG_ON (dh ==NULL );
@@ -523,6 +519,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,if (new_state != old_state)nf_conntrack_event_cache (IPCT_PROTOINFO , ct); + timeouts =nf_ct_timeout_lookup (ct); +if (!timeouts) + timeouts =dccp_pernet (nf_ct_net (ct))->dccp_timeout;nf_ct_refresh_acct (ct, ctinfo, skb, timeouts[new_state]);return NF_ACCEPT ;
@@ -843,7 +842,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { .l4proto = IPPROTO_DCCP, .new = dccp_new, .packet = dccp_packet, - .get_timeouts = dccp_get_timeouts, .error = dccp_error, .can_early_drop = dccp_can_early_drop,#ifdef CONFIG_NF_CONNTRACK_PROCFS
@@ -877,7 +875,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { .l4proto = IPPROTO_DCCP, .new = dccp_new, .packet = dccp_packet, - .get_timeouts = dccp_get_timeouts, .error = dccp_error, .can_early_drop = dccp_can_early_drop,#ifdef CONFIG_NF_CONNTRACK_PROCFS
net/netfilter/nf_conntrack_proto_generic.c +12 -10
@@ -11,6 +11,7 @@#include <linux/timer.h> #include <linux/netfilter.h> #include <net/netfilter/nf_conntrack_l4proto.h> +#include <net/netfilter/nf_conntrack_timeout.h> static const unsigned int nf_ct_generic_timeout =600 *HZ ;
@@ -41,25 +42,24 @@ static bool generic_pkt_to_tuple(const struct sk_buff *skb,return true; } -static unsigned int *generic_get_timeouts (struct net *net) -{ -return &(generic_pernet (net)->timeout); -} -/* Returns verdict for packet, or -1 for invalid. */ static int generic_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo, -unsigned int *timeout) +enum ip_conntrack_info ctinfo) { +const unsigned int *timeout =nf_ct_timeout_lookup (ct); + +if (!timeout) + timeout = &generic_pernet (nf_ct_net (ct))->timeout; +nf_ct_refresh_acct (ct, ctinfo, skb, *timeout);return NF_ACCEPT ; }/* Called when a new connection for this protocol found. */ static bool generic_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts) +unsigned int dataoff) {bool ret;
@@ -78,8 +78,11 @@ static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,static int generic_timeout_nlattr_to_obj (struct nlattr *tb[],struct net *net,void *data) { -unsigned int *timeout = data;struct nf_generic_net *gn =generic_pernet (net); +unsigned int *timeout = data; + +if (!timeout) + timeout = &gn->timeout;if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT ]) *timeout =
@@ -160,7 +163,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = .l4proto = 255, .pkt_to_tuple = generic_pkt_to_tuple, .packet = generic_packet, - .get_timeouts = generic_get_timeouts, .new = generic_new,#if IS_ENABLED (CONFIG_NF_CT_NETLINK_TIMEOUT ) .ctnl_timeout = {
net/netfilter/nf_conntrack_proto_gre.c +10 -4
@@ -39,6 +39,7 @@#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_core.h> +#include <net/netfilter/nf_conntrack_timeout.h> #include <linux/netfilter/nf_conntrack_proto_gre.h> #include <linux/netfilter/nf_conntrack_pptp.h>
@@ -234,8 +235,7 @@ static unsigned int *gre_get_timeouts(struct net *net)static int gre_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo, -unsigned int *timeouts) +enum ip_conntrack_info ctinfo) {/* If we've seen traffic both ways, this is a GRE connection. * Extend timeout. */
@@ -254,8 +254,13 @@ static int gre_packet(struct nf_conn *ct,/* Called when a new connection for this protocol found. */ static bool gre_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts) +unsigned int dataoff) { +unsigned int *timeouts =nf_ct_timeout_lookup (ct); + +if (!timeouts) + timeouts =gre_get_timeouts (nf_ct_net (ct)); +pr_debug (": " );nf_ct_dump_tuple (&ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple);
@@ -291,6 +296,8 @@ static int gre_timeout_nlattr_to_obj(struct nlattr *tb[],unsigned int *timeouts = data;struct netns_proto_gre *net_gre =gre_pernet (net); +if (!timeouts) + timeouts =gre_get_timeouts (net);/* set default timeouts for GRE. */ timeouts[GRE_CT_UNREPLIED ] = net_gre->gre_timeouts[GRE_CT_UNREPLIED ]; timeouts[GRE_CT_REPLIED ] = net_gre->gre_timeouts[GRE_CT_REPLIED ];
@@ -350,7 +357,6 @@ static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = {#ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = gre_print_conntrack, #endif - .get_timeouts = gre_get_timeouts, .packet = gre_packet, .new = gre_new, .destroy = gre_destroy,
net/netfilter/nf_conntrack_proto_sctp.c +8 -10
@@ -28,6 +28,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_conntrack_timeout.h> /* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR
@@ -272,17 +273,11 @@ static int sctp_new_state(enum ip_conntrack_dir dir,return sctp_conntracks[dir][i][cur_state]; } -static unsigned int *sctp_get_timeouts (struct net *net) -{ -return sctp_pernet (net)->timeouts; -} -/* 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, -unsigned int *timeouts) +enum ip_conntrack_info ctinfo) {enum sctp_conntrack new_state, old_state;enum ip_conntrack_dir dir =CTINFO2DIR (ctinfo);
@@ -291,6 +286,7 @@ static int sctp_packet(struct nf_conn *ct,const struct sctp_chunkhdr *sch;struct sctp_chunkhdr _sch;u_int32_t offset, count; +unsigned int *timeouts;unsigned long map[256 /sizeof (unsigned long )] = {0 }; sh =skb_header_pointer (skb, dataoff,sizeof (_sctph), &_sctph);
@@ -379,6 +375,10 @@ static int sctp_packet(struct nf_conn *ct, }spin_unlock_bh (&ct->lock); + timeouts =nf_ct_timeout_lookup (ct); +if (!timeouts) + timeouts =sctp_pernet (nf_ct_net (ct))->timeouts; +nf_ct_refresh_acct (ct, ctinfo, skb, timeouts[new_state]); if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
@@ -399,7 +399,7 @@ static int sctp_packet(struct nf_conn *ct,/* Called when a new connection for this protocol found. */ static bool sctp_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts) +unsigned int dataoff) {enum sctp_conntrack new_state;const struct sctphdr *sh;
@@ -760,7 +760,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { .print_conntrack = sctp_print_conntrack, #endif .packet = sctp_packet, - .get_timeouts = sctp_get_timeouts, .new = sctp_new, .error = sctp_error, .can_early_drop = sctp_can_early_drop,
@@ -795,7 +794,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { .print_conntrack = sctp_print_conntrack, #endif .packet = sctp_packet, - .get_timeouts = sctp_get_timeouts, .new = sctp_new, .error = sctp_error, .can_early_drop = sctp_can_early_drop,
net/netfilter/nf_conntrack_proto_tcp.c +11 -12
@@ -29,6 +29,7 @@#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_seqadj.h> #include <net/netfilter/nf_conntrack_synproxy.h> +#include <net/netfilter/nf_conntrack_timeout.h> #include <net/netfilter/nf_log.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
@@ -768,27 +769,21 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,return NF_ACCEPT ; } -static unsigned int *tcp_get_timeouts (struct net *net) -{ -return tcp_pernet (net)->timeouts; -} -/* Returns verdict for packet, or -1 for invalid. */ static int tcp_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo, -unsigned int *timeouts) +enum ip_conntrack_info ctinfo) {struct net *net =nf_ct_net (ct);struct nf_tcp_net *tn =tcp_pernet (net);struct nf_conntrack_tuple *tuple;enum tcp_conntrack new_state, old_state; +unsigned int index, *timeouts;enum ip_conntrack_dir dir;const struct tcphdr *th;struct tcphdr _tcph;unsigned long timeout; -unsigned int index; th =skb_header_pointer (skb, dataoff,sizeof (_tcph), &_tcph);BUG_ON (th ==NULL );
@@ -1021,6 +1016,10 @@ static int tcp_packet(struct nf_conn *ct, && new_state == TCP_CONNTRACK_FIN_WAIT) ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; + timeouts =nf_ct_timeout_lookup (ct); +if (!timeouts) + timeouts = tn->timeouts; +if (ct->proto.tcp.retrans >= tn->tcp_max_retrans && timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS ]) timeout = timeouts[TCP_CONNTRACK_RETRANS ];
@@ -1070,7 +1069,7 @@ static int tcp_packet(struct nf_conn *ct,/* Called when a new connection for this protocol found. */ static bool tcp_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts) +unsigned int dataoff) {enum tcp_conntrack new_state;const struct tcphdr *th;
@@ -1288,10 +1287,12 @@ static unsigned int tcp_nlattr_tuple_size(void)static int tcp_timeout_nlattr_to_obj (struct nlattr *tb[],struct net *net,void *data) { -unsigned int *timeouts = data;struct nf_tcp_net *tn =tcp_pernet (net); +unsigned int *timeouts = data;int i; +if (!timeouts) + timeouts = tn->timeouts;/* set default TCP timeouts. */ for (i=0 ; i<TCP_CONNTRACK_TIMEOUT_MAX ; i++) timeouts[i] = tn->timeouts[i];
@@ -1538,7 +1539,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = .print_conntrack = tcp_print_conntrack, #endif .packet = tcp_packet, - .get_timeouts = tcp_get_timeouts, .new = tcp_new, .error = tcp_error, .can_early_drop = tcp_can_early_drop,
@@ -1574,7 +1574,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = .print_conntrack = tcp_print_conntrack, #endif .packet = tcp_packet, - .get_timeouts = tcp_get_timeouts, .new = tcp_new, .error = tcp_error, .can_early_drop = tcp_can_early_drop,
net/netfilter/nf_conntrack_proto_udp.c +13 -7
@@ -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_conntrack_timeout.h> #include <net/netfilter/nf_log.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
@@ -45,9 +46,14 @@ static unsigned int *udp_get_timeouts(struct net *net)static int udp_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo, -unsigned int *timeouts) +enum ip_conntrack_info ctinfo) { +unsigned int *timeouts; + + timeouts =nf_ct_timeout_lookup (ct); +if (!timeouts) + timeouts =udp_get_timeouts (nf_ct_net (ct)); +/* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ if (test_bit (IPS_SEEN_REPLY_BIT , &ct->status)) {
@@ -65,7 +71,7 @@ static int udp_packet(struct nf_conn *ct,/* Called when a new connection for this protocol found. */ static bool udp_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,unsigned int *timeouts) +unsigned int dataoff) {return true; }
@@ -176,6 +182,9 @@ static int udp_timeout_nlattr_to_obj(struct nlattr *tb[],unsigned int *timeouts = data;struct nf_udp_net *un =udp_pernet (net); +if (!timeouts) + timeouts = un->timeouts; +/* set default timeouts for UDP. */ timeouts[UDP_CT_UNREPLIED ] = un->timeouts[UDP_CT_UNREPLIED ]; timeouts[UDP_CT_REPLIED ] = un->timeouts[UDP_CT_REPLIED ];
@@ -275,7 +284,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = .l4proto = IPPROTO_UDP, .allow_clash = true, .packet = udp_packet, - .get_timeouts = udp_get_timeouts, .new = udp_new, .error = udp_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
@@ -305,7 +313,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 = .l4proto = IPPROTO_UDPLITE, .allow_clash = true, .packet = udp_packet, - .get_timeouts = udp_get_timeouts, .new = udp_new, .error = udplite_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
@@ -335,7 +342,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = .l4proto = IPPROTO_UDP, .allow_clash = true, .packet = udp_packet, - .get_timeouts = udp_get_timeouts, .new = udp_new, .error = udp_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
@@ -365,7 +371,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 = .l4proto = IPPROTO_UDPLITE, .allow_clash = true, .packet = udp_packet, - .get_timeouts = udp_get_timeouts, .new = udp_new, .error = udplite_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
@@ -388,3 +393,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 = };EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_udplite6);#endif +#include <net/netfilter/nf_conntrack_timeout.h>
net/netfilter/nfnetlink_cttimeout.c +4 -8
@@ -46,7 +46,7 @@ static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { };static int -ctnl_timeout_parse_policy (void *timeouts, +ctnl_timeout_parse_policy (void *timeout,const struct nf_conntrack_l4proto *l4proto,struct net *net,const struct nlattr *attr) {
@@ -67,7 +67,7 @@ ctnl_timeout_parse_policy(void *timeouts,if (ret <0 ) goto err; - ret = l4proto->ctnl_timeout.nlattr_to_obj (tb, net, timeouts); + ret = l4proto->ctnl_timeout.nlattr_to_obj (tb, net, timeout); err:kfree (tb);
@@ -372,7 +372,6 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl, struct netlink_ext_ack *extack) {const struct nf_conntrack_l4proto *l4proto; -unsigned int *timeouts;__u16 l3num;__u8 l4num;int ret;
@@ -392,9 +391,7 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl, goto err; } - timeouts = l4proto->get_timeouts (net); - - ret =ctnl_timeout_parse_policy (timeouts, l4proto, net, + ret =ctnl_timeout_parse_policy (NULL , l4proto, net, cda[CTA_TIMEOUT_DATA ]);if (ret <0 ) goto err;
@@ -431,7 +428,6 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,if (likely (l4proto->ctnl_timeout.obj_to_nlattr)) {struct nlattr *nest_parms; -unsigned int *timeouts = l4proto->get_timeouts (net);int ret; nest_parms = nla_nest_start(skb,
@@ -439,7 +435,7 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,if (!nest_parms) goto nla_put_failure; - ret = l4proto->ctnl_timeout.obj_to_nlattr (skb, timeouts); + ret = l4proto->ctnl_timeout.obj_to_nlattr (skb,NULL );if (ret <0 ) goto nla_put_failure;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 15/38 netfilter: conntrack: remove l3proto abstraction
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
This unifies ipv4 and ipv6 protocol trackers and removes the l3proto abstraction.
This gets rid of all l3proto indirect calls and the need to do a lookup on the function to call for l3 demux.
It increases module size by only a small amount (12kbyte), so this reduces size because nf_conntrack.ko is useless without either nf_conntrack_ipv4 or nf_conntrack_ipv6 module.
before:
text data bss dec hex filename 7357 1088 0 8445 20fd nf_conntrack_ipv4.ko 7405 1084 4 8493 212d nf_conntrack_ipv6.ko
72614 13689 236 86539 1520b nf_conntrack.ko
19K nf_conntrack_ipv4.ko
19K nf_conntrack_ipv6.ko
179K nf_conntrack.ko
after:
text data bss dec hex filename
79277 13937 236 93450 16d0a nf_conntrack.ko
191K nf_conntrack.ko
---
include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 3 -
include/net/netfilter/nf_conntrack.h | 5 +
include/net/netfilter/nf_conntrack_core.h | 1 -
include/net/netfilter/nf_conntrack_l3proto.h | 54 --
include/net/netfilter/nf_conntrack_l4proto.h | 4 -
net/ipv4/netfilter/Kconfig | 22 +-
net/ipv4/netfilter/Makefile | 6 -
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 368 ---------
net/ipv6/netfilter/Kconfig | 27 +-
net/ipv6/netfilter/Makefile | 6 -
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 355 ---------
net/netfilter/Kconfig | 2 +
net/netfilter/Makefile | 7 +-
net/netfilter/nf_conntrack_core.c | 11 +-
net/netfilter/nf_conntrack_proto.c | 847 +++++++++++++++------
net/{ipv4 => }/netfilter/nf_conntrack_proto_icmp.c | 0
.../netfilter/nf_conntrack_proto_icmpv6.c | 0
net/netfilter/nf_conntrack_standalone.c | 14 +-
net/netfilter/nf_nat_core.c | 8 -
19 files changed, 645 insertions(+), 1095 deletions(-)
delete mode 100644 include/net/netfilter/nf_conntrack_l3proto.h
delete mode 100644 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
delete mode 100644 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
rename net/{ipv4 => }/netfilter/nf_conntrack_proto_icmp.c (100%)
rename net/{ipv6 => }/netfilter/nf_conntrack_proto_icmpv6.c (100%)include/net/netfilter/ipv4/nf_conntrack_ipv4.h +0 -3
@@ -10,9 +10,6 @@#ifndef _NF_CONNTRACK_IPV4_H#define _NF_CONNTRACK_IPV4_H - -const extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
include/net/netfilter/nf_conntrack.h +5 -0
@@ -41,6 +41,11 @@ union nf_conntrack_expect_proto {/* insert expect proto private data here */ }; +struct nf_conntrack_net { +unsigned int users4; +unsigned int users6; +}; +#include <linux/types.h> #include <linux/skbuff.h>
include/net/netfilter/nf_conntrack_core.h +0 -1
@@ -14,7 +14,6 @@#define _NF_CONNTRACK_CORE_H#include <linux/netfilter.h> -#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h>
include/net/netfilter/nf_conntrack_l3proto.h deleted +0 -54
54 lines not on this page · raw message
include/net/netfilter/nf_conntrack_l4proto.h +0 -4
@@ -130,10 +130,6 @@ void nf_ct_l4proto_pernet_unregister(struct net *net,/* Protocol global registration. */ int nf_ct_l4proto_register_one (const struct nf_conntrack_l4proto *proto);void nf_ct_l4proto_unregister_one (const struct nf_conntrack_l4proto *proto); -int nf_ct_l4proto_register (const struct nf_conntrack_l4proto *const proto[], -unsigned int num_proto); -void nf_ct_l4proto_unregister (const struct nf_conntrack_l4proto *const proto[], -unsigned int num_proto);/* Generic netlink helpers */ int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
net/ipv4/netfilter/Kconfig +3 -19
@@ -9,22 +9,6 @@ config NF_DEFRAG_IPV4 tristate default n -config NF_CONNTRACK_IPV4 - tristate "IPv4 connection tracking support (required for NAT)" - depends on NF_CONNTRACK - default m if NETFILTER_ADVANCED=n - select NF_DEFRAG_IPV4 - ---help--- - Connection tracking keeps a record of what packets have passed - through your machine, in order to figure out how they are related - into connections. - - This is IPv4 support on Layer 3 independent connection tracking. - Layer 3 independent connection tracking is experimental scheme - which generalize ip_conntrack to support other layer 3 protocols. - - To compile it as a module, choose M here. If unsure, say N. - config NF_SOCKET_IPV4 tristate "IPv4 socket lookup support" help
@@ -112,7 +96,7 @@ config NF_REJECT_IPV4 config NF_NAT_IPV4 tristate "IPv4 NAT" - depends on NF_CONNTRACK_IPV4 + depends on NF_CONNTRACK default m if NETFILTER_ADVANCED=n select NF_NAT help
@@ -279,7 +263,7 @@ config IP_NF_TARGET_SYNPROXY # NAT + specific targets: nf_conntrack config IP_NF_NAT tristate "iptables NAT support" - depends on NF_CONNTRACK_IPV4 + depends on NF_CONNTRACK default m if NETFILTER_ADVANCED=n select NF_NAT select NF_NAT_IPV4
@@ -340,7 +324,7 @@ config IP_NF_MANGLE config IP_NF_TARGET_CLUSTERIP tristate "CLUSTERIP target support" depends on IP_NF_MANGLE - depends on NF_CONNTRACK_IPV4 + depends on NF_CONNTRACK depends on NETFILTER_ADVANCED select NF_CONNTRACK_MARK select NETFILTER_FAMILY_ARP
net/ipv4/netfilter/Makefile +0 -6
@@ -3,12 +3,6 @@ # Makefile for the netfilter modules on top of IPv4. # -# objects for l3 independent conntrack -nf_conntrack_ipv4-y := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o - -# connection tracking -obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o - nf_nat_ipv4-y := nf_nat_l3proto_ipv4.o nf_nat_proto_icmp.o nf_nat_ipv4-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c deleted +0 -368
368 lines not on this page · raw message
net/ipv6/netfilter/Kconfig +4 -23
@@ -5,26 +5,6 @@ menu "IPv6: Netfilter Configuration" depends on INET && IPV6 && NETFILTER -config NF_DEFRAG_IPV6 - tristate - default n - -config NF_CONNTRACK_IPV6 - tristate "IPv6 connection tracking support" - depends on INET && IPV6 && NF_CONNTRACK - default m if NETFILTER_ADVANCED=n - select NF_DEFRAG_IPV6 - ---help--- - Connection tracking keeps a record of what packets have passed - through your machine, in order to figure out how they are related - into connections. - - This is IPv6 support on Layer 3 independent connection tracking. - Layer 3 independent connection tracking is experimental scheme - which generalize ip_conntrack to support other layer 3 protocols. - - To compile it as a module, choose M here. If unsure, say N. - config NF_SOCKET_IPV6 tristate "IPv6 socket lookup support" help
@@ -128,7 +108,7 @@ config NF_LOG_IPV6 config NF_NAT_IPV6 tristate "IPv6 NAT" - depends on NF_CONNTRACK_IPV6 + depends on NF_CONNTRACK depends on NETFILTER_ADVANCED select NF_NAT help
@@ -328,7 +308,7 @@ config IP6_NF_SECURITY config IP6_NF_NAT tristate "ip6tables NAT support" - depends on NF_CONNTRACK_IPV6 + depends on NF_CONNTRACK depends on NETFILTER_ADVANCED select NF_NAT select NF_NAT_IPV6
@@ -365,6 +345,7 @@ config IP6_NF_TARGET_NPT endif # IP6_NF_NAT endif # IP6_NF_IPTABLES - endmenu +config NF_DEFRAG_IPV6 + tristate
net/ipv6/netfilter/Makefile +0 -6
@@ -11,12 +11,6 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o obj-$(CONFIG_IP6_NF_NAT) += ip6table_nat.o -# objects for l3 independent conntrack -nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o - -# l3 independent conntrack -obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o - nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o nf_nat_ipv6-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c deleted +0 -355
355 lines not on this page · raw message
net/netfilter/Kconfig +2 -0
@@ -49,6 +49,8 @@ config NETFILTER_NETLINK_LOG config NF_CONNTRACK tristate "Netfilter connection tracking support" default m if NETFILTER_ADVANCED=n + select NF_DEFRAG_IPV4 + select NF_DEFRAG_IPV6 if IPV6 != n help Connection tracking keeps a record of what packets have passed through your machine, in order to figure out how they are related
net/netfilter/Makefile +6 -1
@@ -1,7 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o -nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o +nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o \ + nf_conntrack_proto.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o \ + nf_conntrack_proto_icmp.o \ + nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o + +nf_conntrack-$(subst m,y,$(CONFIG_IPV6)) += nf_conntrack_proto_icmpv6.o nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
net/netfilter/nf_conntrack_core.c +4 -7
@@ -291,7 +291,6 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, u_int8_t *protonum) {int dataoff =-1 ; -#if IS_ENABLED (CONFIG_NF_CONNTRACK_IPV4 )const struct iphdr *iph;struct iphdr _iph;
@@ -314,15 +313,14 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, nhoff, iph->ihl << 2, skb->len);return -1 ; } -#endif return dataoff; } +#if IS_ENABLED (CONFIG_IPV6 )static int ipv6_get_l4proto (const struct sk_buff *skb,unsigned int nhoff,u8 *protonum) {int protoff =-1 ; -#if IS_ENABLED (CONFIG_NF_CONNTRACK_IPV6 )unsigned int extoff = nhoff +sizeof (struct ipv6hdr );__be16 frag_off;u8 nexthdr;
@@ -343,9 +341,9 @@ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, } *protonum = nexthdr; -#endif return protoff; } +#endif static int get_l4proto (const struct sk_buff *skb,unsigned int nhoff,u8 pf,u8 *l4num)
@@ -353,8 +351,10 @@ static int get_l4proto(const struct sk_buff *skb,switch (pf) {case NFPROTO_IPV4 :return ipv4_get_l4proto (skb, nhoff, l4num); +#if IS_ENABLED (CONFIG_IPV6 )case NFPROTO_IPV6 :return ipv6_get_l4proto (skb, nhoff, l4num); +#endif default : *l4num =0 ;break ;
@@ -2197,9 +2197,6 @@ int nf_conntrack_set_hashsize(const char *val, const struct kernel_param *kp) }EXPORT_SYMBOL_GPL (nf_conntrack_set_hashsize); -module_param_call (hashsize, nf_conntrack_set_hashsize, param_get_uint, - &nf_conntrack_htable_size,0600 ); - static __always_inline unsigned int total_extension_size(void) {/* remember to add new extensions below */
net/netfilter/nf_conntrack_proto.c +617 -230
922 lines not on this page · raw message
net/netfilter/nf_conntrack_proto_icmp.c renamed from net/ipv4/netfilter/nf_conntrack_proto_icmp.c +0 -0
net/netfilter/nf_conntrack_proto_icmpv6.c renamed from net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +0 -0
net/netfilter/nf_conntrack_standalone.c +4 -10
@@ -1,12 +1,4 @@ -/* (C) 1999-2001 Paul `Rusty' Russell -* (C) 2002-2004 Netfilter Core Team <[email protected]> -* (C) 2005-2012 Patrick McHardy <[email protected]> -* -* 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. -*/ - +// SPDX-License-Identifier: GPL-2.0 #include <linux/types.h> #include <linux/netfilter.h> #include <linux/slab.h>
@@ -32,7 +24,7 @@#include <net/netfilter/nf_conntrack_timestamp.h> #include <linux/rculist_nulls.h> -MODULE_LICENSE ("GPL" ); +unsigned int nf_conntrack_net_id__read_mostly ;#ifdef CONFIG_NF_CONNTRACK_PROCFS void
@@ -674,6 +666,8 @@ static void nf_conntrack_pernet_exit(struct list_head *net_exit_list)static struct pernet_operations nf_conntrack_net_ops = { .init = nf_conntrack_pernet_init, .exit_batch = nf_conntrack_pernet_exit, + .id = &nf_conntrack_net_id, + .size =sizeof (struct nf_conntrack_net ), };static int __init nf_conntrack_standalone_init (void )
net/netfilter/nf_nat_core.c +0 -8
@@ -28,7 +28,6 @@#include <net/netfilter/nf_nat_helper.h> #include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_seqadj.h> -#include <net/netfilter/nf_conntrack_l3proto.h> #include <net/netfilter/nf_conntrack_zones.h> #include <linux/netfilter/nf_nat.h>
@@ -743,12 +742,6 @@ EXPORT_SYMBOL_GPL(nf_nat_l4proto_unregister);int nf_nat_l3proto_register (const struct nf_nat_l3proto *l3proto) { -int err; - - err =nf_ct_l3proto_try_module_get (l3proto->l3proto); -if (err <0 ) -return err; -mutex_lock (&nf_nat_proto_mutex);RCU_INIT_POINTER (nf_nat_l4protos[l3proto->l3proto][IPPROTO_TCP ], &nf_nat_l4proto_tcp);
@@ -781,7 +774,6 @@ void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *l3proto)synchronize_rcu ();nf_nat_l3proto_clean (l3proto->l3proto); -nf_ct_l3proto_module_put (l3proto->l3proto); }EXPORT_SYMBOL_GPL (nf_nat_l3proto_unregister);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 16/38 netfilter: Kconfig: Change select IPv6 dependencies
In reply to Pablo Neira AyusoFrom: Máté Eckl <[email protected]>
... from IPV6 to NF_TABLES_IPV6 and IP6_NF_IPTABLES.
In some cases module selects depend on IPV6, but this means that they select another module even if eg. NF_TABLES_IPV6 is not set in which case the selected module is useless due to the lack of IPv6 nf_tables functionality.
The same applies for IP6_NF_IPTABLES and iptables.
Joint work with: Arnd Bermann <[email protected]>
--- net/netfilter/Kconfig | 6 +++--- net/netfilter/nft_socket.c | 4 ++-- net/netfilter/xt_TEE.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-)
net/netfilter/Kconfig +3 -3
@@ -628,7 +628,7 @@ config NFT_SOCKET tristate "Netfilter nf_tables socket match support" depends on IPV6 || IPV6=n select NF_SOCKET_IPV4 - select NF_SOCKET_IPV6 if IPV6 + select NF_SOCKET_IPV6 if NF_TABLES_IPV6 help This option allows matching for the presence or absence of a corresponding socket and its attributes.
@@ -894,7 +894,7 @@ config NETFILTER_XT_TARGET_LOG tristate "LOG target support" select NF_LOG_COMMON select NF_LOG_IPV4 - select NF_LOG_IPV6 if IPV6 + select NF_LOG_IPV6 if IP6_NF_IPTABLES default m if NETFILTER_ADVANCED=n help This option adds a `LOG' target, which allows you to create rules in
@@ -986,7 +986,7 @@ config NETFILTER_XT_TARGET_TEE depends on IPV6 || IPV6=n depends on !NF_CONNTRACK || NF_CONNTRACK select NF_DUP_IPV4 - select NF_DUP_IPV6 if IPV6 + select NF_DUP_IPV6 if IP6_NF_IPTABLES ---help--- This option adds a "TEE" target with which a packet can be cloned and this clone be rerouted to another nexthop.
net/netfilter/nft_socket.c +2 -2
@@ -31,7 +31,7 @@ static void nft_socket_eval(const struct nft_expr *expr,case NFPROTO_IPV4 : sk =nf_sk_lookup_slow_v4 (nft_net (pkt), skb,nft_in (pkt));break ; -#if IS_ENABLED (CONFIG_NF_SOCKET_IPV6 ) +#if IS_ENABLED (CONFIG_NF_TABLES_IPV6 )case NFPROTO_IPV6 : sk =nf_sk_lookup_slow_v6 (nft_net (pkt), skb,nft_in (pkt));break ;
@@ -77,7 +77,7 @@ static int nft_socket_init(const struct nft_ctx *ctx,switch (ctx->family) {case NFPROTO_IPV4 : -#if IS_ENABLED (CONFIG_NF_SOCKET_IPV6 ) +#if IS_ENABLED (CONFIG_NF_TABLES_IPV6 )case NFPROTO_IPV6 :#endif case NFPROTO_INET :
net/netfilter/xt_TEE.c +2 -2
@@ -38,7 +38,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)return XT_CONTINUE ; } -#if IS_ENABLED (CONFIG_IPV6 ) +#if IS_ENABLED (CONFIG_IP6_NF_IPTABLES )static unsigned int tee_tg6 (struct sk_buff *skb,const struct xt_action_param *par) {
@@ -141,7 +141,7 @@ static struct xt_target tee_tg_reg[] __read_mostly = { .destroy = tee_tg_destroy, .me = THIS_MODULE, }, -#if IS_ENABLED (CONFIG_IPV6 ) +#if IS_ENABLED (CONFIG_IP6_NF_IPTABLES ) { .name = "TEE", .revision = 1,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 17/38 netfilter: nf_conncount: Early exit for garbage collection
In reply to Pablo Neira AyusoFrom: Yi-Hung Wei <[email protected]>
This patch is originally from Florian Westphal.
We use an extra function with early exit for garbage collection. It is not necessary to traverse the full list for every node since it is enough to zap a couple of entries for garbage collection.
--- net/netfilter/nf_conncount.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-)
net/netfilter/nf_conncount.c +37 -2
@@ -189,6 +189,42 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, }EXPORT_SYMBOL_GPL (nf_conncount_lookup); +static void nf_conncount_gc_list (struct net *net, +struct nf_conncount_rb *rbconn) +{ +const struct nf_conntrack_tuple_hash *found; +struct nf_conncount_tuple *conn; +struct hlist_node *n; +struct nf_conn *found_ct; +unsigned int collected =0 ; + +hlist_for_each_entry_safe (conn, n, &rbconn->hhead, node) { + found =find_or_evict (net, conn); +if (IS_ERR (found)) { +if (PTR_ERR (found) == -ENOENT ) + collected++; +continue ; + } + + found_ct =nf_ct_tuplehash_to_ctrack (found); +if (already_closed (found_ct)) { +/* +* we do not care about connections which are +* closed already -> ditch it +*/ +nf_ct_put (found_ct); +hlist_del (&conn->node); +kmem_cache_free (conncount_conn_cachep, conn); + collected++; +continue ; + } + +nf_ct_put (found_ct); +if (collected >CONNCOUNT_GC_MAX_NODES ) +return ; + } +} +static void tree_nodes_free (struct rb_root *root,struct nf_conncount_rb *gc_nodes[],unsigned int gc_count)
@@ -251,8 +287,7 @@ count_tree(struct net *net, struct rb_root *root,if (no_gc || gc_count >=ARRAY_SIZE (gc_nodes))continue ; -/* only used for GC on hhead, retval and 'addit' ignored */ -nf_conncount_lookup (net, &rbconn->hhead, tuple, zone, &addit); +nf_conncount_gc_list (net, rbconn);if (hlist_empty (&rbconn->hhead)) gc_nodes[gc_count++] = rbconn; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 18/38 netfilter: nf_conncount: Switch to plain list
In reply to Pablo Neira AyusoFrom: Yi-Hung Wei <[email protected]>
Original patch is from Florian Westphal.
This patch switches from hlist to plain list to store the list of connections with the same filtering key in nf_conncount. With the plain list, we can insert new connections at the tail, so over time the beginning of list holds long-running connections and those are expired, while the newly creates ones are at the end.
Later on, we could probably move checked ones to the end of the list, so the next run has higher chance to reclaim stale entries in the front.
--- include/net/netfilter/nf_conntrack_count.h | 15 ++++-- net/netfilter/nf_conncount.c | 83 ++++++++++++++++++------------ net/netfilter/nft_connlimit.c | 24 ++++----- 3 files changed, 75 insertions(+), 47 deletions(-)
include/net/netfilter/nf_conntrack_count.h +12 -3
@@ -1,8 +1,15 @@#ifndef _NF_CONNTRACK_COUNT_H#define _NF_CONNTRACK_COUNT_H +#include <linux/list.h> +struct nf_conncount_data ; +struct nf_conncount_list { +struct list_head head;/* connections with the same filtering key */ +unsigned int count;/* length of list */ +}; +struct nf_conncount_data *nf_conncount_init (struct net *net,unsigned int family,unsigned int keylen); void nf_conncount_destroy(struct net *net, unsigned int family,
@@ -14,15 +21,17 @@ unsigned int nf_conncount_count(struct net *net,const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_zone *zone); -unsigned int nf_conncount_lookup (struct net *net,struct hlist_head *head, +unsigned int nf_conncount_lookup (struct net *net,struct nf_conncount_list *list,const struct nf_conntrack_tuple *tuple,const struct nf_conntrack_zone *zone,bool *addit); -bool nf_conncount_add (struct hlist_head *head, +void nf_conncount_list_init (struct nf_conncount_list *list); + +bool nf_conncount_add (struct nf_conncount_list *list,const struct nf_conntrack_tuple *tuple,const struct nf_conntrack_zone *zone); -void nf_conncount_cache_free (struct hlist_head *hhead); +void nf_conncount_cache_free (struct nf_conncount_list *list);#endif
net/netfilter/nf_conncount.c +51 -32
208 lines not on this page · raw message
net/netfilter/nft_connlimit.c +12 -12
@@ -14,10 +14,10 @@#include <net/netfilter/nf_conntrack_zones.h> struct nft_connlimit { -spinlock_t lock; -struct hlist_head hhead; -u32 limit; -bool invert; +spinlock_t lock; +struct nf_conncount_list list; +u32 limit; +bool invert; }; static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,
@@ -46,13 +46,13 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv, }spin_lock_bh (&priv->lock); - count =nf_conncount_lookup (nft_net (pkt), &priv->hhead, tuple_ptr, zone, + count =nf_conncount_lookup (nft_net (pkt), &priv->list, tuple_ptr, zone, &addit);if (!addit) goto out; -if (!nf_conncount_add (&priv->hhead, tuple_ptr, zone)) { +if (!nf_conncount_add (&priv->list, tuple_ptr, zone)) { regs->verdict.code =NF_DROP ;spin_unlock_bh (&priv->lock);return ;
@@ -88,7 +88,7 @@ static int nft_connlimit_do_init(const struct nft_ctx *ctx, }spin_lock_init (&priv->lock); -INIT_HLIST_HEAD (&priv->hhead); +nf_conncount_list_init (&priv->list); priv->limit = limit; priv->invert = invert;
@@ -99,7 +99,7 @@ static void nft_connlimit_do_destroy(const struct nft_ctx *ctx, struct nft_connlimit *priv) {nf_ct_netns_put (ctx->net, ctx->family); -nf_conncount_cache_free (&priv->hhead); +nf_conncount_cache_free (&priv->list); } static int nft_connlimit_do_dump(struct sk_buff *skb,
@@ -213,7 +213,7 @@ static int nft_connlimit_clone(struct nft_expr *dst, const struct nft_expr *src)struct nft_connlimit *priv_src =nft_expr_priv (src);spin_lock_init (&priv_dst->lock); -INIT_HLIST_HEAD (&priv_dst->hhead); +nf_conncount_list_init (&priv_dst->list); priv_dst->limit = priv_src->limit; priv_dst->invert = priv_src->invert;
@@ -225,7 +225,7 @@ static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx, {struct nft_connlimit *priv =nft_expr_priv (expr); -nf_conncount_cache_free (&priv->hhead); +nf_conncount_cache_free (&priv->list); }static bool nft_connlimit_gc (struct net *net,const struct nft_expr *expr)
@@ -234,9 +234,9 @@ static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr)bool addit, ret;spin_lock_bh (&priv->lock); -nf_conncount_lookup (net, &priv->hhead,NULL , &nf_ct_zone_dflt, &addit); +nf_conncount_lookup (net, &priv->list,NULL , &nf_ct_zone_dflt, &addit); - ret =hlist_empty (&priv->hhead); + ret =list_empty (&priv->list.head);spin_unlock_bh (&priv->lock);return ret;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 19/38 netfilter: nf_conncount: Early exit in nf_conncount_lookup() and cleanup
In reply to Pablo Neira AyusoFrom: Yi-Hung Wei <[email protected]>
This patch is originally from Florian Westphal.
This patch does the following three tasks.
It applies the same early exit technique for nf_conncount_lookup().
Since now we keep the number of connections in 'struct nf_conncount_list', we no longer need to return the count in nf_conncount_lookup().
Moreover, we expose the garbage collection function nf_conncount_gc_list() for nft_connlimit.
--- include/net/netfilter/nf_conntrack_count.h | 11 +++++---- net/netfilter/nf_conncount.c | 38 +++++++++++++++++------------- net/netfilter/nft_connlimit.c | 9 +++---- 3 files changed, 33 insertions(+), 25 deletions(-)
include/net/netfilter/nf_conntrack_count.h +7 -4
@@ -21,10 +21,10 @@ unsigned int nf_conncount_count(struct net *net,const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_zone *zone); -unsigned int nf_conncount_lookup (struct net *net,struct nf_conncount_list *list, -const struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_zone *zone, -bool *addit); +void nf_conncount_lookup (struct net *net,struct nf_conncount_list *list, +const struct nf_conntrack_tuple *tuple, +const struct nf_conntrack_zone *zone, +bool *addit);void nf_conncount_list_init (struct nf_conncount_list *list);
@@ -32,6 +32,9 @@ bool nf_conncount_add(struct nf_conncount_list *list,const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_zone *zone); +void nf_conncount_gc_list (struct net *net, +struct nf_conncount_list *list); +void nf_conncount_cache_free (struct nf_conncount_list *list);#endif
net/netfilter/nf_conncount.c +21 -17
@@ -144,26 +144,29 @@ find_or_evict(struct net *net, struct nf_conncount_list *list,return ERR_PTR (-EAGAIN ); } -unsigned int nf_conncount_lookup (struct net *net, -struct nf_conncount_list *list, -const struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_zone *zone, -bool *addit) +void nf_conncount_lookup (struct net *net, +struct nf_conncount_list *list, +const struct nf_conntrack_tuple *tuple, +const struct nf_conntrack_zone *zone, +bool *addit) {const struct nf_conntrack_tuple_hash *found;struct nf_conncount_tuple *conn, *conn_n;struct nf_conn *found_ct; -unsigned int length =0 ; +unsigned int collect =0 ; +/* best effort only */ *addit = tuple ? true : false;/* check the saved connections */ list_for_each_entry_safe (conn, conn_n, &list->head, node) { +if (collect >CONNCOUNT_GC_MAX_NODES ) +break ; + found =find_or_evict (net, list, conn);if (IS_ERR (found)) {/* Not found, but might be about to be confirmed */ if (PTR_ERR (found) == -EAGAIN ) { - length++;if (!tuple)continue ;
@@ -171,8 +174,8 @@ unsigned int nf_conncount_lookup(struct net *net,nf_ct_zone_id (&conn->zone, conn->zone.dir) == nf_ct_zone_id(zone, zone->dir)) *addit = false; - } - + }else if (PTR_ERR (found) == -ENOENT ) + collect++;continue ; }
@@ -181,9 +184,10 @@ unsigned int nf_conncount_lookup(struct net *net,if (tuple &&nf_ct_tuple_equal (&conn->tuple, tuple) &&nf_ct_zone_equal (found_ct, zone, zone->dir)) {/* -* Just to be sure we have it only once in the list. * We should not see tuples twice unless someone hooks * this into a table without "-p tcp --syn". +* +* Attempt to avoid a re-add in this case. */ *addit = false; }else if (already_closed (found_ct)) {
@@ -193,14 +197,12 @@ unsigned int nf_conncount_lookup(struct net *net,*/ nf_ct_put (found_ct);conn_free (list, conn); + collect++;continue ; }nf_ct_put (found_ct); - length++; } - -return length; }EXPORT_SYMBOL_GPL (nf_conncount_lookup);
@@ -211,8 +213,8 @@ void nf_conncount_list_init(struct nf_conncount_list *list) }EXPORT_SYMBOL_GPL (nf_conncount_list_init); -static void nf_conncount_gc_list (struct net *net, -struct nf_conncount_list *list) +void nf_conncount_gc_list (struct net *net, +struct nf_conncount_list *list) {const struct nf_conntrack_tuple_hash *found;struct nf_conncount_tuple *conn, *conn_n;
@@ -244,6 +246,7 @@ static void nf_conncount_gc_list(struct net *net,return ; } } +EXPORT_SYMBOL_GPL (nf_conncount_gc_list); static void tree_nodes_free(struct rb_root *root, struct nf_conncount_rb *gc_nodes[],
@@ -291,8 +294,9 @@ count_tree(struct net *net, struct rb_root *root,/* same source network -> be counted! */ unsigned int count; - count =nf_conncount_lookup (net, &rbconn->list, tuple, - zone, &addit); +nf_conncount_lookup (net, &rbconn->list, tuple, zone, + &addit); + count = rbconn->list.count;tree_nodes_free (root, gc_nodes, gc_count);if (!addit)
net/netfilter/nft_connlimit.c +5 -4
@@ -46,8 +46,9 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv, }spin_lock_bh (&priv->lock); - count =nf_conncount_lookup (nft_net (pkt), &priv->list, tuple_ptr, zone, - &addit); +nf_conncount_lookup (nft_net (pkt), &priv->list, tuple_ptr, zone, + &addit); + count = priv->list.count;if (!addit) goto out;
@@ -231,10 +232,10 @@ static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx,static bool nft_connlimit_gc (struct net *net,const struct nft_expr *expr) {struct nft_connlimit *priv =nft_expr_priv (expr); -bool addit, ret; +bool ret;spin_lock_bh (&priv->lock); -nf_conncount_lookup (net, &priv->list,NULL , &nf_ct_zone_dflt, &addit); +nf_conncount_gc_list (net, &priv->list); ret =list_empty (&priv->list.head);spin_unlock_bh (&priv->lock);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 20/38 netfilter: nf_conncount: Move locking into count_tree()
In reply to Pablo Neira AyusoFrom: Yi-Hung Wei <[email protected]>
This patch is originally from Florian Westphal.
This is a preparation patch to allow lockless traversal of the tree via RCU.
--- net/netfilter/nf_conncount.c | 52 +++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 27 deletions(-)
net/netfilter/nf_conncount.c +25 -27
@@ -262,18 +262,26 @@ static void tree_nodes_free(struct rb_root *root, }static unsigned int -count_tree (struct net *net,struct rb_root *root, -const u32 *key,u8 keylen, +count_tree (struct net *net, +struct nf_conncount_data *data, +const u32 *key,const struct nf_conntrack_tuple *tuple,const struct nf_conntrack_zone *zone) {struct nf_conncount_rb *gc_nodes[CONNCOUNT_GC_MAX_NODES ]; +struct rb_root *root;struct rb_node **rbnode, *parent;struct nf_conncount_rb *rbconn;struct nf_conncount_tuple *conn; -unsigned int gc_count; +unsigned int gc_count, hash;bool no_gc = false; +unsigned int count =0 ; +u8 keylen = data->keylen; + hash =jhash2 (key, data->keylen, conncount_rnd) %CONNCOUNT_SLOTS ; + root = &data->root[hash]; + +spin_lock_bh (&nf_conncount_locks[hash %CONNCOUNT_LOCK_SLOTS ]); restart: gc_count =0 ; parent =NULL ;
@@ -292,20 +300,20 @@ count_tree(struct net *net, struct rb_root *root, rbnode = &((*rbnode)->rb_right); }else {/* same source network -> be counted! */ -unsigned int count; -nf_conncount_lookup (net, &rbconn->list, tuple, zone, &addit); count = rbconn->list.count;tree_nodes_free (root, gc_nodes, gc_count);if (!addit) -return count; + goto out_unlock;if (!nf_conncount_add (&rbconn->list, tuple, zone)) -return 0 ;/* hotdrop */ + count =0 ;/* hotdrop */ + goto out_unlock; -return count +1 ; + count++; + goto out_unlock; }if (no_gc || gc_count >=ARRAY_SIZE (gc_nodes))
@@ -328,18 +336,18 @@ count_tree(struct net *net, struct rb_root *root, goto restart; } + count =0 ;if (!tuple) -return 0 ; - + goto out_unlock;/* no match, need to insert new node */ rbconn =kmem_cache_alloc (conncount_rb_cachep,GFP_ATOMIC );if (rbconn ==NULL ) -return 0 ; + goto out_unlock; conn =kmem_cache_alloc (conncount_conn_cachep,GFP_ATOMIC );if (conn ==NULL ) {kmem_cache_free (conncount_rb_cachep, rbconn); -return 0 ; + goto out_unlock; } conn->tuple = *tuple;
@@ -348,10 +356,13 @@ count_tree(struct net *net, struct rb_root *root,nf_conncount_list_init (&rbconn->list);list_add (&conn->node, &rbconn->list.head); + count =1 ;rb_link_node (&rbconn->node, parent, rbnode);rb_insert_color (&rbconn->node, root); -return 1 ; +out_unlock: +spin_unlock_bh (&nf_conncount_locks[hash %CONNCOUNT_LOCK_SLOTS ]); +return count; }/* Count and return number of conntrack entries in 'net' with particular 'key'.
@@ -363,20 +374,7 @@ unsigned int nf_conncount_count(struct net *net,const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_zone *zone) { - struct rb_root *root; -int count; -u32 hash; - - hash =jhash2 (key, data->keylen, conncount_rnd) %CONNCOUNT_SLOTS ; - root = &data->root[hash]; - -spin_lock_bh (&nf_conncount_locks[hash %CONNCOUNT_LOCK_SLOTS ]); - - count =count_tree (net, root, key, data->keylen, tuple, zone); - -spin_unlock_bh (&nf_conncount_locks[hash %CONNCOUNT_LOCK_SLOTS ]); - -return count; + return count_tree(net, data, key, tuple, zone); }EXPORT_SYMBOL_GPL (nf_conncount_count);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 21/38 netfilter: nf_conncount: Split insert and traversal
In reply to Pablo Neira AyusoFrom: Yi-Hung Wei <[email protected]>
This patch is originally from Florian Westphal.
When we have a very coarse grouping, e.g. by large subnets, zone id, etc, it's likely that we do not need to do tree rotation because we'll find a node where we can attach new entry. Based on this observation, we split tree traversal and insertion.
Later on, we can make traversal lockless (tree protected
by RCU), and add extra lock in the individual nodes to protect list insertion/deletion, thereby allowing parallel insert/delete in different tree nodes.
--- net/netfilter/nf_conncount.c | 87 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 20 deletions(-)
net/netfilter/nf_conncount.c +67 -20
@@ -262,6 +262,71 @@ static void tree_nodes_free(struct rb_root *root, }static unsigned int +insert_tree (struct rb_root *root, +unsigned int hash, +const u32 *key, +u8 keylen, +const struct nf_conntrack_tuple *tuple, +const struct nf_conntrack_zone *zone) +{ +struct rb_node **rbnode, *parent; +struct nf_conncount_rb *rbconn; +struct nf_conncount_tuple *conn; +unsigned int count =0 ; + +spin_lock_bh (&nf_conncount_locks[hash %CONNCOUNT_LOCK_SLOTS ]); + + parent =NULL ; + rbnode = &(root->rb_node); +while (*rbnode) { +int diff; + rbconn = rb_entry(*rbnode, struct nf_conncount_rb, node); + + parent = *rbnode; + diff =key_diff (key, rbconn->key, keylen); +if (diff <0 ) { + rbnode = &((*rbnode)->rb_left); + }else if (diff >0 ) { + rbnode = &((*rbnode)->rb_right); + }else { +/* unlikely: other cpu added node already */ +if (!nf_conncount_add (&rbconn->list, tuple, zone)) { + count =0 ;/* hotdrop */ + goto out_unlock; + } + + count = rbconn->list.count; + goto out_unlock; + } + } + +/* expected case: match, insert new node */ + rbconn =kmem_cache_alloc (conncount_rb_cachep,GFP_ATOMIC ); +if (rbconn ==NULL ) + goto out_unlock; + + conn =kmem_cache_alloc (conncount_conn_cachep,GFP_ATOMIC ); +if (conn ==NULL ) { +kmem_cache_free (conncount_rb_cachep, rbconn); + goto out_unlock; + } + + conn->tuple = *tuple; + conn->zone = *zone; +memcpy (rbconn->key, key,sizeof (u32) * keylen); + +nf_conncount_list_init (&rbconn->list); +list_add (&conn->node, &rbconn->list.head); + count =1 ; + +rb_link_node (&rbconn->node, parent, rbnode); +rb_insert_color (&rbconn->node, root); +out_unlock: +spin_unlock_bh (&nf_conncount_locks[hash %CONNCOUNT_LOCK_SLOTS ]); +return count; +} + +static unsigned int count_tree(struct net *net, struct nf_conncount_data *data, const u32 *key,
@@ -272,7 +337,6 @@ count_tree(struct net *net,struct rb_root *root;struct rb_node **rbnode, *parent;struct nf_conncount_rb *rbconn; -struct nf_conncount_tuple *conn;unsigned int gc_count, hash;bool no_gc = false;unsigned int count =0 ;
@@ -339,27 +403,10 @@ count_tree(struct net *net, count =0 ;if (!tuple) goto out_unlock; -/* no match, need to insert new node */ - rbconn =kmem_cache_alloc (conncount_rb_cachep,GFP_ATOMIC ); -if (rbconn ==NULL ) - goto out_unlock; - - conn =kmem_cache_alloc (conncount_conn_cachep,GFP_ATOMIC ); -if (conn ==NULL ) { -kmem_cache_free (conncount_rb_cachep, rbconn); - goto out_unlock; - } - - conn->tuple = *tuple; - conn->zone = *zone; -memcpy (rbconn->key, key,sizeof (u32) * keylen); -nf_conncount_list_init (&rbconn->list); -list_add (&conn->node, &rbconn->list.head); - count =1 ; +spin_unlock_bh (&nf_conncount_locks[hash %CONNCOUNT_LOCK_SLOTS ]); +return insert_tree (root, hash, key, keylen, tuple, zone); -rb_link_node (&rbconn->node, parent, rbnode); -rb_insert_color (&rbconn->node, root); out_unlock:spin_unlock_bh (&nf_conncount_locks[hash %CONNCOUNT_LOCK_SLOTS ]);return count;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 22/38 netfilter: nf_conncount: Add list lock and gc worker, and RCU for init tree search
In reply to Pablo Neira AyusoFrom: Yi-Hung Wei <[email protected]>
This patch is originally from Florian Westphal.
This patch does the following 3 main tasks.
1) Add list lock to 'struct nf_conncount_list' so that we can alter the lists containing the individual connections without holding the main tree lock. It would be useful when we only need to add/remove to/from a list without allocate/remove a node in the tree. With this change, we update nft_connlimit accordingly since we longer need to maintain a list lock in nft_connlimit now.
2) Use RCU for the initial tree search to improve tree look up performance.
3) Add a garbage collection worker. This worker is schedule when there are excessive tree node that needed to be recycled.
Moreover,the rbnode reclaim logic is moved from search tree to insert tree to avoid race condition.
--- include/net/netfilter/nf_conntrack_count.h | 17 +- net/netfilter/nf_conncount.c | 253 +++++++++++++++++++++-------- net/netfilter/nft_connlimit.c | 17 +- 3 files changed, 196 insertions(+), 91 deletions(-)
include/net/netfilter/nf_conntrack_count.h +13 -4
@@ -5,9 +5,17 @@struct nf_conncount_data ; +enum nf_conncount_list_add { +NF_CONNCOUNT_ADDED ,/* list add was ok */ +NF_CONNCOUNT_ERR ,/* -ENOMEM, must drop skb */ +NF_CONNCOUNT_SKIP ,/* list is already reclaimed by gc */ +}; +struct nf_conncount_list { +spinlock_t list_lock;struct list_head head;/* connections with the same filtering key */ unsigned int count;/* length of list */ +bool dead; }; struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
@@ -28,11 +36,12 @@ void nf_conncount_lookup(struct net *net, struct nf_conncount_list *list,void nf_conncount_list_init (struct nf_conncount_list *list); -bool nf_conncount_add (struct nf_conncount_list *list, -const struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_zone *zone); +enum nf_conncount_list_add +nf_conncount_add (struct nf_conncount_list *list, +const struct nf_conntrack_tuple *tuple, +const struct nf_conntrack_zone *zone); -void nf_conncount_gc_list (struct net *net, +bool nf_conncount_gc_list (struct net *net,struct nf_conncount_list *list);void nf_conncount_cache_free (struct nf_conncount_list *list);
net/netfilter/nf_conncount.c +181 -72
441 lines not on this page · raw message
net/netfilter/nft_connlimit.c +2 -15
@@ -14,7 +14,6 @@#include <net/netfilter/nf_conntrack_zones.h> struct nft_connlimit { -spinlock_t lock;struct nf_conncount_list list;u32 limit;bool invert;
@@ -45,7 +44,6 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,return ; } -spin_lock_bh (&priv->lock);nf_conncount_lookup (nft_net (pkt), &priv->list, tuple_ptr, zone, &addit); count = priv->list.count;
@@ -53,14 +51,12 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,if (!addit) goto out; -if (!nf_conncount_add (&priv->list, tuple_ptr, zone)) { +if (nf_conncount_add (&priv->list, tuple_ptr, zone) ==NF_CONNCOUNT_ERR ) { regs->verdict.code =NF_DROP ; -spin_unlock_bh (&priv->lock);return ; } count++; out: -spin_unlock_bh (&priv->lock);if ((count > priv->limit) ^ priv->invert) { regs->verdict.code =NFT_BREAK ;
@@ -88,7 +84,6 @@ static int nft_connlimit_do_init(const struct nft_ctx *ctx, invert = true; } -spin_lock_init (&priv->lock);nf_conncount_list_init (&priv->list); priv->limit = limit; priv->invert = invert;
@@ -213,7 +208,6 @@ static int nft_connlimit_clone(struct nft_expr *dst, const struct nft_expr *src)struct nft_connlimit *priv_dst =nft_expr_priv (dst);struct nft_connlimit *priv_src =nft_expr_priv (src); -spin_lock_init (&priv_dst->lock);nf_conncount_list_init (&priv_dst->list); priv_dst->limit = priv_src->limit; priv_dst->invert = priv_src->invert;
@@ -232,15 +226,8 @@ static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx,static bool nft_connlimit_gc (struct net *net,const struct nft_expr *expr) {struct nft_connlimit *priv =nft_expr_priv (expr); -bool ret; -spin_lock_bh (&priv->lock); -nf_conncount_gc_list (net, &priv->list); - - ret =list_empty (&priv->list.head); -spin_unlock_bh (&priv->lock); - -return ret; +return nf_conncount_gc_list (net, &priv->list); }static struct nft_expr_type nft_connlimit_type;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 23/38 netfilter: nf_conntrack: resolve clash for matching conntracks
In reply to Pablo Neira AyusoFrom: Martynas Pumputis <[email protected]>
This patch enables the clash resolution for NAT (disabled in "590b52e10d41") if clashing conntracks match (i.e. both tuples are equal) and a protocol allows it.
The clash might happen for a connections-less protocol (e.g. UDP) when two threads in parallel writes to the same socket and consequent calls to "get_unique_tuple" return the same tuples (incl. reply tuples).
In this case it is safe to perform the resolution, as the losing CT describes the same mangling as the winning CT, so no modifications to the packet are needed, and the result of rules traversal for the loser's packet stays valid.
--- net/netfilter/nf_conntrack_core.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-)
net/netfilter/nf_conntrack_core.c +22 -8
@@ -632,6 +632,18 @@ nf_ct_key_equal(struct nf_conntrack_tuple_hash *h,net_eq (net,nf_ct_net (ct)); } +static inline bool +nf_ct_match (const struct nf_conn *ct1,const struct nf_conn *ct2) +{ +return nf_ct_tuple_equal (&ct1->tuplehash[IP_CT_DIR_ORIGINAL ].tuple, + &ct2->tuplehash[IP_CT_DIR_ORIGINAL ].tuple) && +nf_ct_tuple_equal (&ct1->tuplehash[IP_CT_DIR_REPLY ].tuple, + &ct2->tuplehash[IP_CT_DIR_REPLY ].tuple) && +nf_ct_zone_equal (ct1,nf_ct_zone (ct2),IP_CT_DIR_ORIGINAL ) && +nf_ct_zone_equal (ct1,nf_ct_zone (ct2),IP_CT_DIR_REPLY ) && +net_eq (nf_ct_net (ct1),nf_ct_net (ct2)); +} +/* caller must hold rcu readlock and none of the nf_conntrack_locks */ static void nf_ct_gc_expired (struct nf_conn *ct) {
@@ -825,19 +837,21 @@ static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,/* This is the conntrack entry already in hashes that won race. */ struct nf_conn *ct =nf_ct_tuplehash_to_ctrack (h);const struct nf_conntrack_l4proto *l4proto; +enum ip_conntrack_info oldinfo; +struct nf_conn *loser_ct =nf_ct_get (skb, &oldinfo); l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct));if (l4proto->allow_clash && - ((ct->status &IPS_NAT_DONE_MASK ) ==0 ) && !nf_ct_is_dying (ct) &&atomic_inc_not_zero (&ct->ct_general.use)) { -enum ip_conntrack_info oldinfo; -struct nf_conn *loser_ct =nf_ct_get (skb, &oldinfo); - -nf_ct_acct_merge (ct, ctinfo, loser_ct); -nf_conntrack_put (&loser_ct->ct_general); -nf_ct_set (skb, ct, oldinfo); -return NF_ACCEPT ; +if (((ct->status &IPS_NAT_DONE_MASK ) ==0 ) || +nf_ct_match (ct, loser_ct)) { +nf_ct_acct_merge (ct, ctinfo, loser_ct); +nf_conntrack_put (&loser_ct->ct_general); +nf_ct_set (skb, ct, oldinfo); +return NF_ACCEPT ; + } +nf_ct_put (ct); }NF_CT_STAT_INC (net, drop);return NF_DROP ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 24/38 ipvs: provide just conn to ip_vs_state_name
In reply to Pablo Neira AyusoFrom: Julian Anastasov <[email protected]>
In preparation for followup patches, provide just the cp ptr to ip_vs_state_name.
--- include/net/ip_vs.h | 2 +- net/netfilter/ipvs/ip_vs_conn.c | 8 ++++---- net/netfilter/ipvs/ip_vs_proto.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-)
include/net/ip_vs.h +1 -1
@@ -1221,7 +1221,7 @@ struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af, struct ip_vs_dest *dest, __u32 fwmark);void ip_vs_conn_expire_now (struct ip_vs_conn *cp); -const char *ip_vs_state_name (__u16 proto,int state); +const char *ip_vs_state_name (const struct ip_vs_conn *cp);void ip_vs_tcp_conn_listen (struct ip_vs_conn *cp);int ip_vs_check_template (struct ip_vs_conn *ct,struct ip_vs_dest *cdest);
net/netfilter/ipvs/ip_vs_conn.c +4 -4
@@ -1107,7 +1107,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) &cp->caddr.in6,ntohs (cp->cport), &cp->vaddr.in6,ntohs (cp->vport), dbuf,ntohs (cp->dport), -ip_vs_state_name (cp->protocol, cp->state), +ip_vs_state_name (cp), (cp->timer.expires-jiffies)/HZ, pe_data); else#endif
@@ -1118,7 +1118,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)ntohl (cp->caddr.ip),ntohs (cp->cport),ntohl (cp->vaddr.ip),ntohs (cp->vport), dbuf,ntohs (cp->dport), -ip_vs_state_name (cp->protocol, cp->state), +ip_vs_state_name (cp), (cp->timer.expires-jiffies)/HZ, pe_data); }return 0 ;
@@ -1169,7 +1169,7 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) &cp->caddr.in6,ntohs (cp->cport), &cp->vaddr.in6,ntohs (cp->vport), dbuf,ntohs (cp->dport), -ip_vs_state_name (cp->protocol, cp->state), +ip_vs_state_name (cp),ip_vs_origin_name (cp->flags), (cp->timer.expires-jiffies)/HZ); else
@@ -1181,7 +1181,7 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)ntohl (cp->caddr.ip),ntohs (cp->cport),ntohl (cp->vaddr.ip),ntohs (cp->vport), dbuf,ntohs (cp->dport), -ip_vs_state_name (cp->protocol, cp->state), +ip_vs_state_name (cp),ip_vs_origin_name (cp->flags), (cp->timer.expires-jiffies)/HZ); }
net/netfilter/ipvs/ip_vs_proto.c +4 -4
@@ -193,13 +193,13 @@ ip_vs_create_timeout_table(int *table, int size) } -const char *ip_vs_state_name (__u16 proto,int state) +const char *ip_vs_state_name (const struct ip_vs_conn *cp) { -struct ip_vs_protocol *pp =ip_vs_proto_get (proto); +struct ip_vs_protocol *pp =ip_vs_proto_get (cp->protocol);if (pp ==NULL || pp->state_name ==NULL ) -return (IPPROTO_IP == proto) ?"NONE" :"ERR!" ; -return pp->state_name (state); +return (cp->protocol ==IPPROTO_IP ) ?"NONE" :"ERR!" ; +return pp->state_name (cp->state); }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 25/38 ipvs: add assured state for conn templates
In reply to Pablo Neira AyusoFrom: Julian Anastasov <[email protected]>
cp->state was not used for templates. Add support for state bits and for the first "assured" bit which indicates that some connection controlled by this template was established or assured by the real server. In a followup patch we will use it to drop templates under SYN attack.
--- include/net/ip_vs.h | 16 ++++++++++++++++ net/netfilter/ipvs/ip_vs_proto.c | 17 +++++++++++++++-- net/netfilter/ipvs/ip_vs_proto_sctp.c | 2 ++ net/netfilter/ipvs/ip_vs_proto_tcp.c | 2 ++ net/netfilter/ipvs/ip_vs_proto_udp.c | 2 ++ net/netfilter/ipvs/ip_vs_sync.c | 18 ++++++------------ 6 files changed, 43 insertions(+), 14 deletions(-)
include/net/ip_vs.h +16 -0
@@ -335,6 +335,11 @@ enum ip_vs_sctp_states { IP_VS_SCTP_S_LAST }; +/* Connection templates use bits from state */ +#define IP_VS_CTPL_S_NONE 0x0000 +#define IP_VS_CTPL_S_ASSURED 0x0001 +#define IP_VS_CTPL_S_LAST 0x0002 +/* Delta sequence info structure * Each ip_vs_conn has 2 (output AND input seq. changes). * Only used in the VS/NAT.
@@ -1289,6 +1294,17 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)atomic_inc (&ctl_cp->n_control); } +/* Mark our template as assured */ +static inline void +ip_vs_control_assure_ct (struct ip_vs_conn *cp) +{ +struct ip_vs_conn *ct = cp->control; + +if (ct && !(ct->state &IP_VS_CTPL_S_ASSURED ) && + (ct->flags &IP_VS_CONN_F_TEMPLATE )) + ct->state |=IP_VS_CTPL_S_ASSURED ; +} +/* IPVS netns init & cleanup functions */ int ip_vs_estimator_net_init (struct netns_ipvs *ipvs);int ip_vs_control_net_init (struct netns_ipvs *ipvs);
net/netfilter/ipvs/ip_vs_proto.c +15 -2
@@ -42,6 +42,11 @@static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE ]; +/* States for conn templates: NONE or words separated with ",", max 15 chars */ +static const char *ip_vs_ctpl_state_name_table[IP_VS_CTPL_S_LAST ] = { + [IP_VS_CTPL_S_NONE ] ="NONE" , + [IP_VS_CTPL_S_ASSURED ] ="ASSURED" , +};/* * register an ipvs protocol
@@ -195,11 +200,19 @@ ip_vs_create_timeout_table(int *table, int size)const char *ip_vs_state_name (const struct ip_vs_conn *cp) { -struct ip_vs_protocol *pp =ip_vs_proto_get (cp->protocol); +unsigned int state = cp->state; +struct ip_vs_protocol *pp; + +if (cp->flags &IP_VS_CONN_F_TEMPLATE ) { +if (state >=IP_VS_CTPL_S_LAST ) +return "ERR!" ; +return ip_vs_ctpl_state_name_table[state] ? :"?" ; + } + pp =ip_vs_proto_get (cp->protocol);if (pp ==NULL || pp->state_name ==NULL )return (cp->protocol ==IPPROTO_IP ) ?"NONE" :"ERR!" ; -return pp->state_name (cp->state); +return pp->state_name (state); }
net/netfilter/ipvs/ip_vs_proto_sctp.c +2 -0
@@ -461,6 +461,8 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, cp->flags &= ~IP_VS_CONN_F_INACTIVE ; } } +if (next_state ==IP_VS_SCTP_S_ESTABLISHED ) +ip_vs_control_assure_ct (cp); }if (likely (pd)) cp->timeout = pd->timeout_table[cp->state = next_state];
net/netfilter/ipvs/ip_vs_proto_tcp.c +2 -0
@@ -569,6 +569,8 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, cp->flags &= ~IP_VS_CONN_F_INACTIVE ; } } +if (new_state ==IP_VS_TCP_S_ESTABLISHED ) +ip_vs_control_assure_ct (cp); }if (likely (pd))
net/netfilter/ipvs/ip_vs_proto_udp.c +2 -0
@@ -460,6 +460,8 @@ udp_state_transition(struct ip_vs_conn *cp, int direction, } cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL ]; +if (direction ==IP_VS_DIR_OUTPUT ) +ip_vs_control_assure_ct (cp); }static int __udp_init (struct netns_ipvs *ipvs,struct ip_vs_proto_data *pd)
net/netfilter/ipvs/ip_vs_sync.c +6 -12
@@ -1003,12 +1003,9 @@ static void ip_vs_process_message_v0(struct netns_ipvs *ipvs, const char *buffercontinue ; } }else { -/* protocol in templates is not used for state/timeout */ -if (state >0 ) { -IP_VS_DBG (2 ,"BACKUP v0, Invalid template state %u\n" , - state); - state =0 ; - } +if (state >=IP_VS_CTPL_S_LAST ) +IP_VS_DBG (7 ,"BACKUP v0, Invalid tpl state %u\n" , + state); } ip_vs_conn_fill_param(ipvs, AF_INET, s->protocol,
@@ -1166,12 +1163,9 @@ static inline int ip_vs_proc_sync_conn(struct netns_ipvs *ipvs, __u8 *p, __u8 *m goto out; } }else { -/* protocol in templates is not used for state/timeout */ -if (state >0 ) { -IP_VS_DBG (3 ,"BACKUP, Invalid template state %u\n" , - state); - state =0 ; - } +if (state >=IP_VS_CTPL_S_LAST ) +IP_VS_DBG (7 ,"BACKUP, Invalid tpl state %u\n" , + state); }if (ip_vs_conn_fill_param_sync (ipvs, af, s, ¶m, pe_data, pe_data_len, pe_name, pe_name_len)) {
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 26/38 ipvs: drop conn templates under attack
In reply to Pablo Neira AyusoFrom: Julian Anastasov <[email protected]>
Before now, connection templates were ignored by the random dropentry procedure. But Michal Koutný suggests that we should add exception for connections under SYN attack. He provided patch that implements it for TCP:
<quote>
IPVS includes protection against filling the ip_vs_conn_tab by dropping 1/32 of feasible entries every second. The template entries (for persistent services) are never directly deleted by this mechanism but when a picked TCP connection entry is being dropped (1), the respective template entry is dropped too (realized by expiring 60 seconds after the connection entry being dropped).
There is another mechanism that removes connection entries when they time out (2), in this case the associated template entry is not deleted. Under SYN flood template entries would accumulate (due to their entry longer timeout).
The accumulation takes place also with drop_entry being enabled. Roughly 15% ((31/32)^60) of SYN_RECV connections survive the dropping mechanism
(1) and are removed by the timeout mechanism (2)(defaults to 60 seconds for SYN_RECV), thus template entries would still accumulate.
The patch ensures that when a connection entry times out, we also remove the template entry from the table. To prevent breaking persistent services (since the connection may time out in already established state) we add a new entry flag to protect templates what spawned at least one established TCP connection.
</quote>
We already added ASSURED flag for the templates in previous patch, so that we can use it now to decide which connection templates should be dropped under attack. But we also have some cases that need special handling.
We modify the dropentry procedure as follows:
- Linux timers currently use LIFO ordering but we can not rely on this to drop controlling connections. So, set cp->timeout to 0 to indicate that connection was dropped and that on expiration we should try to drop our controlling connections. As result, we can now avoid the ip_vs_conn_expire_now call.
- move the cp->n_control check above, so that it avoids restarting the timer for controlling connections when not needed.
- drop unassured connection templates here if they are not referred by any connections.
On connection expiration: if connection was dropped (cp->timeout=0) try to drop our controlling connection except if it is a template in assured state.
In ip_vs_conn_flush change order of ip_vs_conn_expire_now calls according to the LIFO timer expiration order. It should work faster for controlling connections with single controlled one.
--- net/netfilter/ipvs/ip_vs_conn.c | 59 +++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 20 deletions(-)
net/netfilter/ipvs/ip_vs_conn.c +39 -20
@@ -825,12 +825,23 @@ static void ip_vs_conn_expire(struct timer_list *t)/* Unlink conn if not referenced anymore */ if (likely (ip_vs_conn_unlink (cp))) { +struct ip_vs_conn *ct = cp->control; +/* delete the timer if it is activated by other users */ del_timer (&cp->timer);/* does anybody control me? */ -if (cp->control) +if (ct) {ip_vs_control_del (cp); +/* Drop CTL or non-assured TPL if not used anymore */ +if (!cp->timeout && !atomic_read (&ct->n_control) && + (!(ct->flags &IP_VS_CONN_F_TEMPLATE ) || + !(ct->state &IP_VS_CTPL_S_ASSURED ))) { +IP_VS_DBG (4 ,"drop controlling connection\n" ); + ct->timeout =0 ; +ip_vs_conn_expire_now (ct); + } + }if ((cp->flags &IP_VS_CONN_F_NFCT ) && !(cp->flags &IP_VS_CONN_F_ONE_PACKET )) {
@@ -872,6 +883,10 @@ static void ip_vs_conn_expire(struct timer_list *t)/* Modify timer, so that it expires as soon as possible. * Can be called without reference only if under RCU lock. +* We can have such chain of conns linked with ->control: DATA->CTL->TPL +* - DATA (eg. FTP) and TPL (persistence) can be present depending on setup +* - cp->timeout=0 indicates all conns from chain should be dropped but +* TPL is not dropped if in assured state */ void ip_vs_conn_expire_now (struct ip_vs_conn *cp) {
@@ -1197,8 +1212,11 @@ static const struct seq_operations ip_vs_conn_sync_seq_ops = {#endif -/* -* Randomly drop connection entries before running out of memory +/* Randomly drop connection entries before running out of memory +* Can be used for DATA and CTL conns. For TPL conns there are exceptions: +* - traffic for services in OPS mode increases ct->in_pkts, so it is supported +* - traffic for services not in OPS mode does not increase ct->in_pkts in +* all cases, so it is not supported */ static inline int todrop_entry (struct ip_vs_conn *cp) {
@@ -1242,7 +1260,7 @@ static inline bool ip_vs_conn_ops_mode(struct ip_vs_conn *cp)void ip_vs_random_dropentry (struct netns_ipvs *ipvs) {int idx; -struct ip_vs_conn *cp, *cp_c; +struct ip_vs_conn *cp;rcu_read_lock ();/*
@@ -1254,13 +1272,15 @@ void ip_vs_random_dropentry(struct netns_ipvs *ipvs)hlist_for_each_entry_rcu (cp, &ip_vs_conn_tab[hash], c_list) {if (cp->ipvs != ipvs)continue ; +if (atomic_read (&cp->n_control)) +continue ;if (cp->flags &IP_VS_CONN_F_TEMPLATE ) { -if (atomic_read (&cp->n_control) || - !ip_vs_conn_ops_mode (cp)) -continue ; -else -/* connection template of OPS */ +/* connection template of OPS */ +if (ip_vs_conn_ops_mode (cp)) goto try_drop; +if (!(cp->state &IP_VS_CTPL_S_ASSURED )) + goto drop; +continue ; }if (cp->protocol ==IPPROTO_TCP ) {switch (cp->state) {
@@ -1294,15 +1314,10 @@ void ip_vs_random_dropentry(struct netns_ipvs *ipvs)continue ; } -IP_VS_DBG (4 ,"del connection\n" ); +drop: +IP_VS_DBG (4 ,"drop connection\n" ); + cp->timeout =0 ;ip_vs_conn_expire_now (cp); - cp_c = cp->control; -/* cp->control is valid only with reference to cp */ -if (cp_c &&__ip_vs_conn_get (cp)) { -IP_VS_DBG (4 ,"del conn template\n" ); -ip_vs_conn_expire_now (cp_c); -__ip_vs_conn_put (cp); - } }cond_resched_rcu (); }
@@ -1325,15 +1340,19 @@ static void ip_vs_conn_flush(struct netns_ipvs *ipvs)hlist_for_each_entry_rcu (cp, &ip_vs_conn_tab[idx], c_list) {if (cp->ipvs != ipvs)continue ; -IP_VS_DBG (4 ,"del connection\n" ); -ip_vs_conn_expire_now (cp); +/* As timers are expired in LIFO order, restart +* the timer of controlling connection first, so +* that it is expired after us. +*/ cp_c = cp->control;/* cp->control is valid only with reference to cp */ if (cp_c &&__ip_vs_conn_get (cp)) { -IP_VS_DBG (4 ,"del conn template\n" ); +IP_VS_DBG (4 ,"del controlling connection\n" );ip_vs_conn_expire_now (cp_c);__ip_vs_conn_put (cp); } +IP_VS_DBG (4 ,"del connection\n" ); +ip_vs_conn_expire_now (cp); }cond_resched_rcu (); }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 27/38 netfilter: Remove useless param helper of nf_ct_helper_ext_add
In reply to Pablo Neira AyusoFrom: Gao Feng <[email protected]>
The param helper of nf_ct_helper_ext_add is useless now, then remove it now.
--- include/net/netfilter/nf_conntrack_helper.h | 4 +--- net/netfilter/nf_conntrack_core.c | 3 +-- net/netfilter/nf_conntrack_helper.c | 5 ++--- net/netfilter/nf_conntrack_netlink.c | 2 +- net/netfilter/nft_ct.c | 2 +- net/netfilter/xt_CT.c | 2 +- net/openvswitch/conntrack.c | 2 +- 7 files changed, 8 insertions(+), 12 deletions(-)
include/net/netfilter/nf_conntrack_helper.h +1 -3
@@ -103,9 +103,7 @@ int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int);void nf_conntrack_helpers_unregister (struct nf_conntrack_helper *,unsigned int ); -struct nf_conn_help *nf_ct_helper_ext_add (struct nf_conn *ct, -struct nf_conntrack_helper *helper, -gfp_t gfp); +struct nf_conn_help *nf_ct_helper_ext_add (struct nf_conn *ct,gfp_t gfp);int __nf_ct_try_assign_helper (struct nf_conn *ct,struct nf_conn *tmpl,gfp_t flags);
net/netfilter/nf_conntrack_core.c +1 -2
@@ -1401,8 +1401,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,/* exp->master safe, refcnt bumped in nf_ct_find_expectation */ ct->master = exp->master;if (exp->helper) { - help =nf_ct_helper_ext_add (ct, exp->helper, -GFP_ATOMIC ); + help =nf_ct_helper_ext_add (ct,GFP_ATOMIC );if (help)rcu_assign_pointer (help->helper, exp->helper); }
net/netfilter/nf_conntrack_helper.c +2 -3
@@ -192,8 +192,7 @@ void nf_conntrack_helper_put(struct nf_conntrack_helper *helper)EXPORT_SYMBOL_GPL (nf_conntrack_helper_put);struct nf_conn_help * -nf_ct_helper_ext_add (struct nf_conn *ct, -struct nf_conntrack_helper *helper,gfp_t gfp) +nf_ct_helper_ext_add (struct nf_conn *ct,gfp_t gfp) {struct nf_conn_help *help;
@@ -262,7 +261,7 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, }if (help ==NULL ) { - help =nf_ct_helper_ext_add (ct, helper, flags); + help =nf_ct_helper_ext_add (ct, flags);if (help ==NULL )return -ENOMEM ; }else {
net/netfilter/nf_conntrack_netlink.c +1 -1
@@ -1947,7 +1947,7 @@ ctnetlink_create_conntrack(struct net *net, }else {struct nf_conn_help *help; - help =nf_ct_helper_ext_add (ct, helper,GFP_ATOMIC ); + help =nf_ct_helper_ext_add (ct,GFP_ATOMIC );if (help ==NULL ) { err = -ENOMEM ; goto err2;
net/netfilter/nft_ct.c +1 -1
@@ -870,7 +870,7 @@ static void nft_ct_helper_obj_eval(struct nft_object *obj,if (test_bit (IPS_HELPER_BIT , &ct->status))return ; - help =nf_ct_helper_ext_add (ct, to_assign,GFP_ATOMIC ); + help =nf_ct_helper_ext_add (ct,GFP_ATOMIC );if (help) {rcu_assign_pointer (help->helper, to_assign);set_bit (IPS_HELPER_BIT , &ct->status);
net/netfilter/xt_CT.c +1 -1
@@ -93,7 +93,7 @@ xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,return -ENOENT ; } - help =nf_ct_helper_ext_add (ct, helper,GFP_KERNEL ); + help =nf_ct_helper_ext_add (ct,GFP_KERNEL );if (help ==NULL ) {nf_conntrack_helper_put (helper);return -ENOMEM ;
net/openvswitch/conntrack.c +1 -1
@@ -1303,7 +1303,7 @@ static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,return -EINVAL ; } - help =nf_ct_helper_ext_add (info->ct, helper,GFP_KERNEL ); + help =nf_ct_helper_ext_add (info->ct,GFP_KERNEL );if (!help) {nf_conntrack_helper_put (helper);return -ENOMEM ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 28/38 netfilter: nf_tables: add and use helper for module autoload
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
module autoload is problematic, it requires dropping the mutex that protects the transaction. Once the mutex has been dropped, another client can start a new transaction before we had a chance to abort current transaction log.
This helper makes sure we first zap the transaction log, then drop mutex for module autoload.
In case autload is successful, the caller has to reply entire message anyway.
--- net/netfilter/nf_tables_api.c | 81 +++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 29 deletions(-)
net/netfilter/nf_tables_api.c +52 -29
@@ -455,8 +455,40 @@ __nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family)return NULL ; } +/* +* Loading a module requires dropping mutex that guards the +* transaction. +* We first need to abort any pending transactions as once +* mutex is unlocked a different client could start a new +* transaction. It must not see any 'future generation' +* changes * as these changes will never happen. +*/ +#ifdef CONFIG_MODULES +static int __nf_tables_abort (struct net *net); + +static void nft_request_module (struct net *net,const char *fmt, ...) +{ +char module_name[MODULE_NAME_LEN ]; +va_list args; +int ret; + +__nf_tables_abort (net); + +va_start (args, fmt); + ret =vsnprintf (module_name,MODULE_NAME_LEN , fmt, args); +va_end (args); +if (WARN (ret >=MODULE_NAME_LEN ,"truncated: '%s' (len %d)" , module_name, ret)) +return ; + +nfnl_unlock (NFNL_SUBSYS_NFTABLES ); +request_module ("%s" , module_name); +nfnl_lock (NFNL_SUBSYS_NFTABLES ); +} +#endif +static const struct nft_chain_type * -nf_tables_chain_type_lookup (const struct nlattr *nla,u8 family,bool autoload) +nf_tables_chain_type_lookup (struct net *net,const struct nlattr *nla, +u8 family,bool autoload) {const struct nft_chain_type *type;
@@ -465,10 +497,8 @@ nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload)return type;#ifdef CONFIG_MODULES if (autoload) { -nfnl_unlock (NFNL_SUBSYS_NFTABLES ); -request_module ("nft-chain-%u-%.*s" , family, -nla_len (nla), (const char *)nla_data (nla)); -nfnl_lock (NFNL_SUBSYS_NFTABLES ); +nft_request_module (net,"nft-chain-%u-%.*s" , family, +nla_len (nla), (const char *)nla_data (nla)); type =__nf_tables_chain_type_lookup (nla, family);if (type !=NULL )return ERR_PTR (-EAGAIN );
@@ -1412,7 +1442,7 @@ static int nft_chain_parse_hook(struct net *net, type = chain_type[family][NFT_CHAIN_T_DEFAULT ];if (nla[NFTA_CHAIN_TYPE ]) { - type =nf_tables_chain_type_lookup (nla[NFTA_CHAIN_TYPE ], + type =nf_tables_chain_type_lookup (net, nla[NFTA_CHAIN_TYPE ], family, create);if (IS_ERR (type))return PTR_ERR (type);
@@ -1875,7 +1905,8 @@ static const struct nft_expr_type *__nft_expr_type_get(u8 family,return NULL ; } -static const struct nft_expr_type *nft_expr_type_get (u8 family, +static const struct nft_expr_type *nft_expr_type_get (struct net *net, +u8 family,struct nlattr *nla) {const struct nft_expr_type *type;
@@ -1889,17 +1920,13 @@ static const struct nft_expr_type *nft_expr_type_get(u8 family,#ifdef CONFIG_MODULES if (type ==NULL ) { -nfnl_unlock (NFNL_SUBSYS_NFTABLES ); -request_module ("nft-expr-%u-%.*s" , family, -nla_len (nla), (char *)nla_data (nla)); -nfnl_lock (NFNL_SUBSYS_NFTABLES ); +nft_request_module (net,"nft-expr-%u-%.*s" , family, +nla_len (nla), (char *)nla_data (nla));if (__nft_expr_type_get (family, nla))return ERR_PTR (-EAGAIN ); -nfnl_unlock (NFNL_SUBSYS_NFTABLES ); -request_module ("nft-expr-%.*s" , -nla_len (nla), (char *)nla_data (nla)); -nfnl_lock (NFNL_SUBSYS_NFTABLES ); +nft_request_module (net,"nft-expr-%.*s" , +nla_len (nla), (char *)nla_data (nla));if (__nft_expr_type_get (family, nla))return ERR_PTR (-EAGAIN ); }
@@ -1968,7 +1995,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,if (err <0 )return err; - type =nft_expr_type_get (ctx->family, tb[NFTA_EXPR_NAME ]); + type =nft_expr_type_get (ctx->net, ctx->family, tb[NFTA_EXPR_NAME ]);if (IS_ERR (type))return PTR_ERR (type);
@@ -2744,9 +2771,7 @@ nft_select_set_ops(const struct nft_ctx *ctx,#ifdef CONFIG_MODULES if (list_empty (&nf_tables_set_types)) { -nfnl_unlock (NFNL_SUBSYS_NFTABLES ); -request_module ("nft-set" ); -nfnl_lock (NFNL_SUBSYS_NFTABLES ); +nft_request_module (ctx->net,"nft-set" );if (!list_empty (&nf_tables_set_types))return ERR_PTR (-EAGAIN ); }
@@ -4779,7 +4804,8 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype)return NULL ; } -static const struct nft_object_type *nft_obj_type_get (u32 objtype) +static const struct nft_object_type * +nft_obj_type_get (struct net *net,u32 objtype) {const struct nft_object_type *type;
@@ -4789,9 +4815,7 @@ static const struct nft_object_type *nft_obj_type_get(u32 objtype)#ifdef CONFIG_MODULES if (type ==NULL ) { -nfnl_unlock (NFNL_SUBSYS_NFTABLES ); -request_module ("nft-obj-%u" , objtype); -nfnl_lock (NFNL_SUBSYS_NFTABLES ); +nft_request_module (net,"nft-obj-%u" , objtype);if (__nft_obj_type_get (objtype))return ERR_PTR (-EAGAIN ); }
@@ -4843,7 +4867,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,nft_ctx_init (&ctx, net, skb, nlh, family, table,NULL , nla); - type =nft_obj_type_get (objtype); + type =nft_obj_type_get (net, objtype);if (IS_ERR (type))return PTR_ERR (type);
@@ -5339,7 +5363,8 @@ static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family)return NULL ; } -static const struct nf_flowtable_type *nft_flowtable_type_get (u8 family) +static const struct nf_flowtable_type * +nft_flowtable_type_get (struct net *net,u8 family) {const struct nf_flowtable_type *type;
@@ -5349,9 +5374,7 @@ static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)#ifdef CONFIG_MODULES if (type ==NULL ) { -nfnl_unlock (NFNL_SUBSYS_NFTABLES ); -request_module ("nf-flowtable-%u" , family); -nfnl_lock (NFNL_SUBSYS_NFTABLES ); +nft_request_module (net,"nf-flowtable-%u" , family);if (__nft_flowtable_type_get (family))return ERR_PTR (-EAGAIN ); }
@@ -5431,7 +5454,7 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, goto err1; } - type =nft_flowtable_type_get (family); + type =nft_flowtable_type_get (net, family);if (IS_ERR (type)) { err =PTR_ERR (type); goto err2;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 29/38 netfilter: nf_tables: make valid_genid callback mandatory
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
always call this function, followup patch can use this to aquire a per-netns transaction log to guard the entire batch instead of using the nfnl susbsys mutex (which is shared among all namespaces).
--- net/netfilter/nf_tables_api.c | 2 +- net/netfilter/nfnetlink.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
net/netfilter/nf_tables_api.c +1 -1
@@ -6591,7 +6591,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)static bool nf_tables_valid_genid (struct net *net,u32 genid) { -return net->nft.base_seq == genid; +return genid ==0 || net->nft.base_seq == genid; }static const struct nfnetlink_subsystem nf_tables_subsys = {
net/netfilter/nfnetlink.c +2 -2
@@ -331,13 +331,13 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, } } -if (!ss->commit || !ss->abort) { +if (!ss->valid_genid || !ss->commit || !ss->abort) {nfnl_unlock (subsys_id);netlink_ack (oskb, nlh, -EOPNOTSUPP ,NULL );return kfree_skb (skb); } -if (genid && ss->valid_genid && !ss->valid_genid (net, genid)) { +if (!ss->valid_genid (net, genid)) {nfnl_unlock (subsys_id);netlink_ack (oskb, nlh, -ERESTART ,NULL );return kfree_skb (skb);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 30/38 netfilter: nf_tables: take module reference when starting a batch
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
--- include/linux/netfilter/nfnetlink.h | 1 + net/netfilter/nf_tables_api.c | 1 + net/netfilter/nfnetlink.c | 9 +++++++++ 3 files changed, 11 insertions(+)
include/linux/netfilter/nfnetlink.h +1 -0
@@ -29,6 +29,7 @@ struct nfnetlink_subsystem {__u8 subsys_id;/* nfnetlink subsystem ID */ __u8 cb_count;/* number of callbacks */ const struct nfnl_callback *cb;/* callback for individual types */ +struct module *owner;int (*commit)(struct net *net,struct sk_buff *skb);int (*abort)(struct net *net,struct sk_buff *skb);void (*cleanup)(struct net *net);
net/netfilter/nf_tables_api.c +1 -0
@@ -6603,6 +6603,7 @@ static const struct nfnetlink_subsystem nf_tables_subsys = { .abort = nf_tables_abort, .cleanup = nf_tables_cleanup, .valid_genid = nf_tables_valid_genid, + .owner = THIS_MODULE, }; int nft_chain_validate_dependency(const struct nft_chain *chain,
net/netfilter/nfnetlink.c +9 -0
@@ -337,7 +337,14 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,return kfree_skb (skb); } +if (!try_module_get (ss->owner)) { +nfnl_unlock (subsys_id); +netlink_ack (oskb, nlh, -EOPNOTSUPP ,NULL ); +return kfree_skb (skb); + } +if (!ss->valid_genid (net, genid)) { +module_put (ss->owner);nfnl_unlock (subsys_id);netlink_ack (oskb, nlh, -ERESTART ,NULL );return kfree_skb (skb);
@@ -472,6 +479,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,nfnl_err_reset (&err_list);nfnl_unlock (subsys_id);kfree_skb (skb); +module_put (ss->owner); goto replay; }else if (status ==NFNL_BATCH_DONE ) { err = ss->commit (net, oskb);
@@ -491,6 +499,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,nfnl_err_deliver (&err_list, oskb);nfnl_unlock (subsys_id);kfree_skb (skb); +module_put (ss->owner); }static const struct nla_policy nfnl_batch_policy[NFNL_BATCH_MAX +1 ] = {
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 31/38 netfilter: nf_tables: avoid global info storage
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
This works because all accesses are currently serialized by nfnl nf_tables subsys mutex.
If we want to have per-netns locking, we need to make this scratch area pernetns or allocate it on demand.
This does the latter, its ~28kbyte but we can fallback to vmalloc so it should be fine.
--- net/netfilter/nf_tables_api.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-)
net/netfilter/nf_tables_api.c +12 -16
@@ -2454,8 +2454,6 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)#define NFT_RULE_MAXEXPRS 128 -static struct nft_expr_info *info; - static int nf_tables_newrule(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[],
@@ -2463,6 +2461,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, {const struct nfgenmsg *nfmsg =nlmsg_data (nlh);u8 genmask =nft_genmask_next (net); +struct nft_expr_info *info =NULL ;int family = nfmsg->nfgen_family;struct nft_table *table;struct nft_chain *chain;
@@ -2533,6 +2532,12 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, n =0 ; size =0 ;if (nla[NFTA_RULE_EXPRESSIONS ]) { + info =kvmalloc_array (NFT_RULE_MAXEXPRS , +sizeof (struct nft_expr_info ), +GFP_KERNEL ); +if (!info) +return -ENOMEM ; +nla_for_each_nested (tmp, nla[NFTA_RULE_EXPRESSIONS ], rem) { err = -EINVAL ;if (nla_type (tmp) !=NFTA_LIST_ELEM )
@@ -2625,6 +2630,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,list_add_rcu (&rule->list, &chain->rules); } } +kvfree (info); chain->use++;if (net->nft.validate_state ==NFT_VALIDATE_DO )
@@ -2638,6 +2644,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,if (info[i].ops !=NULL )module_put (info[i].ops->type->owner); } +kvfree (info);return err; }
@@ -7203,29 +7210,19 @@ static int __init nf_tables_module_init(void)nft_chain_filter_init (); - info =kmalloc_array (NFT_RULE_MAXEXPRS ,sizeof (struct nft_expr_info ), -GFP_KERNEL ); -if (info ==NULL ) { - err = -ENOMEM ; - goto err1; - } - err =nf_tables_core_module_init ();if (err <0 ) - goto err2; +return err; err =nfnetlink_subsys_register (&nf_tables_subsys);if (err <0 ) - goto err3; + goto err;register_netdevice_notifier (&nf_tables_flowtable_notifier);return register_pernet_subsys (&nf_tables_net_ops); -err3: +err:nf_tables_core_module_exit (); -err2: -kfree (info); -err1:return err; }
@@ -7237,7 +7234,6 @@ static void __exit nf_tables_module_exit(void)unregister_pernet_subsys (&nf_tables_net_ops);rcu_barrier ();nf_tables_core_module_exit (); -kfree (info); }module_init (nf_tables_module_init);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 32/38 netfilter: nf_tables: use dedicated mutex to guard transactions
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Continue to use nftnl subsys mutex to protect (un)registration of hook types, expressions and so on, but force batch operations to do their own locking.
This allows distinct net namespaces to perform transactions in parallel.
--- include/net/netns/nftables.h | 1 + net/netfilter/nf_tables_api.c | 88 +++++++++++++++++++++++++++++++--------- net/netfilter/nfnetlink.c | 10 ++--- net/netfilter/nft_chain_filter.c | 4 +- net/netfilter/nft_dynset.c | 2 + 5 files changed, 77 insertions(+), 28 deletions(-)
include/net/netns/nftables.h +1 -0
@@ -7,6 +7,7 @@struct netns_nftables {struct list_head tables;struct list_head commit_list; +struct mutex commit_mutex;unsigned int base_seq;u8 gencursor;u8 validate_state;
net/netfilter/nf_tables_api.c +69 -19
256 lines not on this page · raw message
net/netfilter/nfnetlink.c +3 -7
@@ -350,6 +350,8 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,return kfree_skb (skb); } +nfnl_unlock (subsys_id); +while (skb->len >=nlmsg_total_size (0 )) {int msglen, type;
@@ -471,13 +473,8 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, } done:if (status &NFNL_BATCH_REPLAY ) { -const struct nfnetlink_subsystem *ss2; - - ss2 =nfnl_dereference_protected (subsys_id); -if (ss2 == ss) - ss->abort (net, oskb); + ss->abort (net, oskb);nfnl_err_reset (&err_list); -nfnl_unlock (subsys_id);kfree_skb (skb);module_put (ss->owner); goto replay;
@@ -497,7 +494,6 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, ss->cleanup (net);nfnl_err_deliver (&err_list, oskb); -nfnl_unlock (subsys_id);kfree_skb (skb);module_put (ss->owner); }
net/netfilter/nft_chain_filter.c +2 -2
@@ -322,7 +322,7 @@ static int nf_tables_netdev_event(struct notifier_block *this,if (!ctx.net)return NOTIFY_DONE ; -nfnl_lock (NFNL_SUBSYS_NFTABLES ); +mutex_lock (&ctx.net->nft.commit_mutex);list_for_each_entry (table, &ctx.net->nft.tables, list) {if (table->family !=NFPROTO_NETDEV )continue ;
@@ -337,7 +337,7 @@ static int nf_tables_netdev_event(struct notifier_block *this,nft_netdev_event (event, dev, &ctx); } } -nfnl_unlock (NFNL_SUBSYS_NFTABLES ); +mutex_unlock (&ctx.net->nft.commit_mutex);put_net (ctx.net);return NOTIFY_DONE ;
net/netfilter/nft_dynset.c +2 -0
@@ -118,6 +118,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx,u64 timeout;int err; +lockdep_assert_held (&ctx->net->nft.commit_mutex); +if (tb[NFTA_DYNSET_SET_NAME ] ==NULL || tb[NFTA_DYNSET_OP ] ==NULL || tb[NFTA_DYNSET_SREG_KEY ] ==NULL )
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 33/38 netfilter: nf_osf: add nf_osf_match_one()
In reply to Pablo Neira AyusoThis new function allows us to check if there is TCP syn packet matching with a given fingerprint that can be reused from the upcoming new nf_osf_find() function.
--- net/netfilter/nf_osf.c | 207 ++++++++++++++++++++++++++----------------------- 1 file changed, 111 insertions(+), 96 deletions(-)
net/netfilter/nf_osf.c +111 -96
@@ -21,15 +21,14 @@#include <linux/netfilter/nf_osf.h> static inline int nf_osf_ttl (const struct sk_buff *skb, -const struct nf_osf_info *info, -unsigned char f_ttl) +int ttl_check,unsigned char f_ttl) {const struct iphdr *ip =ip_hdr (skb); -if (info->flags &NF_OSF_TTL ) { -if (info->ttl ==NF_OSF_TTL_TRUE ) +if (ttl_check !=-1 ) { +if (ttl_check ==NF_OSF_TTL_TRUE )return ip->ttl == f_ttl; -if (info->ttl ==NF_OSF_TTL_NOCHECK ) +if (ttl_check ==NF_OSF_TTL_NOCHECK )return 1 ;else if (ip->ttl <= f_ttl)return 1 ;
@@ -52,6 +51,104 @@ static inline int nf_osf_ttl(const struct sk_buff *skb,return ip->ttl == f_ttl; } +static bool nf_osf_match_one (const struct sk_buff *skb, +const struct nf_osf_user_finger *f, +int ttl_check,u16 totlen,u16 window, +const unsigned char *optp, +unsigned int optsize) +{ +unsigned int check_WSS =0 ; +int fmatch =FMATCH_WRONG ; +int foptsize, optnum; +u16 mss =0 ; + +if (totlen != f->ss || !nf_osf_ttl (skb, ttl_check, f->ttl)) +return false; + +/* +* Should not happen if userspace parser was written correctly. +*/ +if (f->wss.wc >=OSF_WSS_MAX ) +return false; + +/* Check options */ + + foptsize =0 ; +for (optnum =0 ; optnum < f->opt_num; ++optnum) + foptsize += f->opt[optnum].length; + +if (foptsize >MAX_IPOPTLEN || + optsize >MAX_IPOPTLEN || + optsize != foptsize) +return false; + + check_WSS = f->wss.wc; + +for (optnum =0 ; optnum < f->opt_num; ++optnum) { +if (f->opt[optnum].kind == (*optp)) { +__u32 len = f->opt[optnum].length; +const __u8 *optend = optp + len; + + fmatch =FMATCH_OK ; + +switch (*optp) { +case OSFOPT_MSS : + mss = optp[3 ]; + mss <<=8 ; + mss |= optp[2 ]; + + mss =ntohs ((__force __be16 )mss); +break ; +case OSFOPT_TS : +break ; + } + + optp = optend; + }else + fmatch =FMATCH_OPT_WRONG ; + +if (fmatch !=FMATCH_OK ) +break ; + } + +if (fmatch !=FMATCH_OPT_WRONG ) { + fmatch =FMATCH_WRONG ; + +switch (check_WSS) { +case OSF_WSS_PLAIN : +if (f->wss.val ==0 || window == f->wss.val) + fmatch =FMATCH_OK ; +break ; +case OSF_WSS_MSS : +/* +* Some smart modems decrease mangle MSS to +* SMART_MSS_2, so we check standard, decreased +* and the one provided in the fingerprint MSS +* values. +*/ +#define SMART_MSS_1 1460 +#define SMART_MSS_2 1448 +if (window == f->wss.val * mss || + window == f->wss.val *SMART_MSS_1 || + window == f->wss.val *SMART_MSS_2 ) + fmatch =FMATCH_OK ; +break ; +case OSF_WSS_MTU : +if (window == f->wss.val * (mss +40 ) || + window == f->wss.val * (SMART_MSS_1 +40 ) || + window == f->wss.val * (SMART_MSS_2 +40 )) + fmatch =FMATCH_OK ; +break ; +case OSF_WSS_MODULO : +if ((window % f->wss.val) ==0 ) + fmatch =FMATCH_OK ; +break ; + } + } + +return fmatch ==FMATCH_OK ; +} + bool nf_osf_match(const struct sk_buff *skb, u_int8_t family, int hooknum, struct net_device *in, struct net_device *out,
@@ -59,15 +156,16 @@ nf_osf_match(const struct sk_buff *skb, u_int8_t family, const struct list_head *nf_osf_fingers) {const unsigned char *optp =NULL , *_optp =NULL ; -unsigned int optsize =0 , check_WSS =0 ; -int fmatch =FMATCH_WRONG , fcount =0 ;const struct iphdr *ip =ip_hdr (skb);const struct nf_osf_user_finger *f;unsigned char opts[MAX_IPOPTLEN ];const struct nf_osf_finger *kf; -u16 window, totlen, mss =0 ; +int fcount =0 , ttl_check; +int fmatch =FMATCH_WRONG ; +unsigned int optsize =0 ;const struct tcphdr *tcp;struct tcphdr _tcph; +u16 window, totlen;bool df; tcp =skb_header_pointer (skb,ip_hdrlen (skb),sizeof (struct tcphdr ), &_tcph);
@@ -88,103 +186,20 @@ nf_osf_match(const struct sk_buff *skb, u_int8_t family, sizeof(struct tcphdr), optsize, opts); } + ttl_check = (info->flags &NF_OSF_TTL ) ? info->ttl :-1 ; +list_for_each_entry_rcu (kf, &nf_osf_fingers[df], finger_entry) { -int foptsize, optnum; f = &kf->finger;if (!(info->flags &NF_OSF_LOG ) &&strcmp (info->genre, f->genre))continue ; - optp = _optp; - fmatch =FMATCH_WRONG ; - -if (totlen != f->ss || !nf_osf_ttl (skb, info, f->ttl)) -continue ; - -/* -* Should not happen if userspace parser was written correctly. -*/ -if (f->wss.wc >=OSF_WSS_MAX ) +if (!nf_osf_match_one (skb, f, + ttl_check, totlen, window, optp, optsize))continue ; -/* Check options */ - - foptsize =0 ; -for (optnum =0 ; optnum < f->opt_num; ++optnum) - foptsize += f->opt[optnum].length; - -if (foptsize >MAX_IPOPTLEN || - optsize >MAX_IPOPTLEN || - optsize != foptsize) -continue ; - - check_WSS = f->wss.wc; - -for (optnum =0 ; optnum < f->opt_num; ++optnum) { -if (f->opt[optnum].kind == (*optp)) { -__u32 len = f->opt[optnum].length; -const __u8 *optend = optp + len; - - fmatch =FMATCH_OK ; - -switch (*optp) { -case OSFOPT_MSS : - mss = optp[3 ]; - mss <<=8 ; - mss |= optp[2 ]; - - mss =ntohs ((__force __be16 )mss); -break ; -case OSFOPT_TS : -break ; - } - - optp = optend; - }else - fmatch =FMATCH_OPT_WRONG ; - -if (fmatch !=FMATCH_OK ) -break ; - } - -if (fmatch !=FMATCH_OPT_WRONG ) { - fmatch =FMATCH_WRONG ; - -switch (check_WSS) { -case OSF_WSS_PLAIN : -if (f->wss.val ==0 || window == f->wss.val) - fmatch =FMATCH_OK ; -break ; -case OSF_WSS_MSS : -/* -* Some smart modems decrease mangle MSS to -* SMART_MSS_2, so we check standard, decreased -* and the one provided in the fingerprint MSS -* values. -*/ -#define SMART_MSS_1 1460 -#define SMART_MSS_2 1448 -if (window == f->wss.val * mss || - window == f->wss.val *SMART_MSS_1 || - window == f->wss.val *SMART_MSS_2 ) - fmatch =FMATCH_OK ; -break ; -case OSF_WSS_MTU : -if (window == f->wss.val * (mss +40 ) || - window == f->wss.val * (SMART_MSS_1 +40 ) || - window == f->wss.val * (SMART_MSS_2 +40 )) - fmatch =FMATCH_OK ; -break ; -case OSF_WSS_MODULO : -if ((window % f->wss.val) ==0 ) - fmatch =FMATCH_OK ; -break ; - } - } - -if (fmatch !=FMATCH_OK ) -continue ; + fmatch =FMATCH_OK ; fcount++;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 34/38 netfilter: nf_osf: add struct nf_osf_hdr_ctx
In reply to Pablo Neira AyusoWrap context that allow us to guess the OS into a structure.
--- net/netfilter/nf_osf.c | 105 +++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 43 deletions(-)
net/netfilter/nf_osf.c +62 -43
@@ -51,18 +51,25 @@ static inline int nf_osf_ttl(const struct sk_buff *skb,return ip->ttl == f_ttl; } +struct nf_osf_hdr_ctx { +bool df; +u16 window; +u16 totlen; +const unsigned char *optp; +unsigned int optsize; +}; +static bool nf_osf_match_one (const struct sk_buff *skb,const struct nf_osf_user_finger *f, -int ttl_check,u16 totlen,u16 window, -const unsigned char *optp, -unsigned int optsize) +int ttl_check, +struct nf_osf_hdr_ctx *ctx) {unsigned int check_WSS =0 ;int fmatch =FMATCH_WRONG ;int foptsize, optnum;u16 mss =0 ; -if (totlen != f->ss || !nf_osf_ttl (skb, ttl_check, f->ttl)) +if (ctx->totlen != f->ss || !nf_osf_ttl (skb, ttl_check, f->ttl))return false;/*
@@ -78,24 +85,24 @@ static bool nf_osf_match_one(const struct sk_buff *skb, foptsize += f->opt[optnum].length;if (foptsize >MAX_IPOPTLEN || - optsize >MAX_IPOPTLEN || - optsize != foptsize) + ctx->optsize >MAX_IPOPTLEN || + ctx->optsize != foptsize)return false; check_WSS = f->wss.wc;for (optnum =0 ; optnum < f->opt_num; ++optnum) { -if (f->opt[optnum].kind == (*optp)) { +if (f->opt[optnum].kind == *ctx->optp) {__u32 len = f->opt[optnum].length; -const __u8 *optend = optp + len; +const __u8 *optend = ctx->optp + len; fmatch =FMATCH_OK ; -switch (*optp) { +switch (*ctx->optp) {case OSFOPT_MSS : - mss = optp[3 ]; + mss = ctx->optp[3 ]; mss <<=8 ; - mss |= optp[2 ]; + mss |= ctx->optp[2 ]; mss =ntohs ((__force __be16 )mss);break ;
@@ -103,7 +110,7 @@ static bool nf_osf_match_one(const struct sk_buff *skb,break ; } - optp = optend; + ctx->optp = optend; }else fmatch =FMATCH_OPT_WRONG ;
@@ -116,7 +123,7 @@ static bool nf_osf_match_one(const struct sk_buff *skb,switch (check_WSS) {case OSF_WSS_PLAIN : -if (f->wss.val ==0 || window == f->wss.val) +if (f->wss.val ==0 || ctx->window == f->wss.val) fmatch =FMATCH_OK ;break ;case OSF_WSS_MSS :
@@ -128,19 +135,19 @@ static bool nf_osf_match_one(const struct sk_buff *skb,*/ #define SMART_MSS_1 1460#define SMART_MSS_2 1448 -if (window == f->wss.val * mss || - window == f->wss.val *SMART_MSS_1 || - window == f->wss.val *SMART_MSS_2 ) +if (ctx->window == f->wss.val * mss || + ctx->window == f->wss.val *SMART_MSS_1 || + ctx->window == f->wss.val *SMART_MSS_2 ) fmatch =FMATCH_OK ;break ;case OSF_WSS_MTU : -if (window == f->wss.val * (mss +40 ) || - window == f->wss.val * (SMART_MSS_1 +40 ) || - window == f->wss.val * (SMART_MSS_2 +40 )) +if (ctx->window == f->wss.val * (mss +40 ) || + ctx->window == f->wss.val * (SMART_MSS_1 +40 ) || + ctx->window == f->wss.val * (SMART_MSS_2 +40 )) fmatch =FMATCH_OK ;break ;case OSF_WSS_MODULO : -if ((window % f->wss.val) ==0 ) +if ((ctx->window % f->wss.val) ==0 ) fmatch =FMATCH_OK ;break ; }
@@ -149,54 +156,66 @@ static bool nf_osf_match_one(const struct sk_buff *skb,return fmatch ==FMATCH_OK ; } +static const struct tcphdr *nf_osf_hdr_ctx_init (struct nf_osf_hdr_ctx *ctx, +const struct sk_buff *skb, +const struct iphdr *ip, +unsigned char *opts) +{ +const struct tcphdr *tcp; +struct tcphdr _tcph; + + tcp =skb_header_pointer (skb,ip_hdrlen (skb),sizeof (struct tcphdr ), &_tcph); +if (!tcp) +return NULL ; + +if (!tcp->syn) +return NULL ; + + ctx->totlen =ntohs (ip->tot_len); + ctx->df =ntohs (ip->frag_off) &IP_DF ; + ctx->window =ntohs (tcp->window); + +if (tcp->doff *4 >sizeof (struct tcphdr )) { + ctx->optsize = tcp->doff *4 -sizeof (struct tcphdr ); + + ctx->optp =skb_header_pointer (skb,ip_hdrlen (skb) + +sizeof (struct tcphdr ), ctx->optsize, opts); + } + +return tcp; +} +bool nf_osf_match (const struct sk_buff *skb,u_int8_t family,int hooknum,struct net_device *in,struct net_device *out,const struct nf_osf_info *info,struct net *net,const struct list_head *nf_osf_fingers) { -const unsigned char *optp =NULL , *_optp =NULL ;const struct iphdr *ip =ip_hdr (skb);const struct nf_osf_user_finger *f;unsigned char opts[MAX_IPOPTLEN ];const struct nf_osf_finger *kf;int fcount =0 , ttl_check;int fmatch =FMATCH_WRONG ; -unsigned int optsize =0 ; +struct nf_osf_hdr_ctx ctx;const struct tcphdr *tcp; -struct tcphdr _tcph; -u16 window, totlen; -bool df; - tcp =skb_header_pointer (skb,ip_hdrlen (skb),sizeof (struct tcphdr ), &_tcph); -if (!tcp) -return false; +memset (&ctx,0 ,sizeof (ctx)); -if (!tcp->syn) + tcp =nf_osf_hdr_ctx_init (&ctx, skb, ip, opts); +if (!tcp)return false; - totlen =ntohs (ip->tot_len); - df =ntohs (ip->frag_off) &IP_DF ; - window =ntohs (tcp->window); - -if (tcp->doff *4 >sizeof (struct tcphdr )) { - optsize = tcp->doff *4 -sizeof (struct tcphdr ); - - _optp = optp =skb_header_pointer (skb,ip_hdrlen (skb) + -sizeof (struct tcphdr ), optsize, opts); - } - ttl_check = (info->flags &NF_OSF_TTL ) ? info->ttl :-1 ; -list_for_each_entry_rcu (kf, &nf_osf_fingers[df], finger_entry) { +list_for_each_entry_rcu (kf, &nf_osf_fingers[ctx.df], finger_entry) { f = &kf->finger;if (!(info->flags &NF_OSF_LOG ) &&strcmp (info->genre, f->genre))continue ; -if (!nf_osf_match_one (skb, f, - ttl_check, totlen, window, optp, optsize)) +if (!nf_osf_match_one (skb, f, ttl_check, &ctx))continue ; fmatch =FMATCH_OK ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 35/38 netfilter: nft_socket: Break evaluation if no socket found
In reply to Pablo Neira AyusoFrom: Máté Eckl <[email protected]>
Actual implementation stores 0 in the destination register if no socket is found by the lookup, but that is not intentional as it is not really a value of any socket metadata.
This patch fixes this and breaks rule evaluation in this case.
--- net/netfilter/nft_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nft_socket.c +1 -1
@@ -43,7 +43,7 @@ static void nft_socket_eval(const struct nft_expr *expr, }if (!sk) { -nft_reg_store8 (dest,0 ); + regs->verdict.code =NFT_BREAK ;return ; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 36/38 netfilter: nft_socket: Expose socket mark
In reply to Pablo Neira AyusoFrom: Máté Eckl <[email protected]>
--- include/uapi/linux/netfilter/nf_tables.h | 4 +++- net/netfilter/nft_socket.c | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-)
include/uapi/linux/netfilter/nf_tables.h +3 -1
@@ -921,10 +921,12 @@ enum nft_socket_attributes {/* * enum nft_socket_keys - nf_tables socket expression keys * -* @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option_ +* @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option +* @NFT_SOCKET_MARK: Value of the socket mark */ enum nft_socket_keys {NFT_SOCKET_TRANSPARENT , +NFT_SOCKET_MARK , __NFT_SOCKET_MAX };#define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1)
net/netfilter/nft_socket.c +11 -0
@@ -54,6 +54,14 @@ static void nft_socket_eval(const struct nft_expr *expr,case NFT_SOCKET_TRANSPARENT :nft_reg_store8 (dest,inet_sk_transparent (sk));break ; +case NFT_SOCKET_MARK : +if (sk_fullsock (sk)) { + *dest = sk->sk_mark; + }else { + regs->verdict.code =NFT_BREAK ; +return ; + } +break ;default :WARN_ON (1 ); regs->verdict.code =NFT_BREAK ;
@@ -91,6 +99,9 @@ static int nft_socket_init(const struct nft_ctx *ctx,case NFT_SOCKET_TRANSPARENT : len =sizeof (u8);break ; +case NFT_SOCKET_MARK : + len =sizeof (u32); +break ;default :return -EOPNOTSUPP ; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 37/38 ipv6: remove dependency of nf_defrag_ipv6 on ipv6 module
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
IPV6=m
DEFRAG_IPV6=m
CONNTRACK=y yields:
net/netfilter/nf_conntrack_proto.o: In function `nf_ct_netns_do_get':net/netfilter/nf_conntrack_proto.c:802: undefined reference to nf_defrag_ipv6_enable' net/netfilter/nf_conntrack_proto.o:(.rodata+0x640): undefined reference to nf_conntrack_l4proto_icmpv6'
Setting DEFRAG_IPV6=y causes undefined references to ip6_rhash_params ip6_frag_init and ip6_expire_frag_queue so it would be needed to force IPV6=y too.
This patch gets rid of the 'followup linker error' by removing the dependency of ipv6.ko symbols from netfilter ipv6 defrag.
Shared code is placed into a header, then used from both.
--- include/net/ipv6.h | 28 -------- include/net/ipv6_frag.h | 104 ++++++++++++++++++++++++++++++ net/ieee802154/6lowpan/reassembly.c | 2 +- net/ipv6/netfilter/nf_conntrack_reasm.c | 17 +++-- net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 3 +- net/ipv6/reassembly.c | 92 ++------------------------ net/openvswitch/conntrack.c | 1 + 7 files changed, 126 insertions(+), 121 deletions(-) create mode 100644 include/net/ipv6_frag.h
include/net/ipv6.h +0 -28
@@ -581,34 +581,6 @@ static inline bool ipv6_prefix_equal(const struct in6_addr *addr1, }#endif -struct inet_frag_queue ; - -enum ip6_defrag_users { -IP6_DEFRAG_LOCAL_DELIVER , -IP6_DEFRAG_CONNTRACK_IN , - __IP6_DEFRAG_CONNTRACK_IN =IP6_DEFRAG_CONNTRACK_IN +USHRT_MAX , -IP6_DEFRAG_CONNTRACK_OUT , - __IP6_DEFRAG_CONNTRACK_OUT =IP6_DEFRAG_CONNTRACK_OUT +USHRT_MAX , -IP6_DEFRAG_CONNTRACK_BRIDGE_IN , - __IP6_DEFRAG_CONNTRACK_BRIDGE_IN =IP6_DEFRAG_CONNTRACK_BRIDGE_IN +USHRT_MAX , -}; - -void ip6_frag_init (struct inet_frag_queue *q,const void *a); -extern const struct rhashtable_params ip6_rhash_params; - -/* -* Equivalent of ipv4 struct ip -*/ -struct frag_queue { -struct inet_frag_queue q; - -int iif; -__u16 nhoffset; -u8 ecn; -}; - -void ip6_expire_frag_queue (struct net *net,struct frag_queue *fq); -static inline bool ipv6_addr_any (const struct in6_addr *a) {#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ) &&BITS_PER_LONG ==64
include/net/ipv6_frag.h new file +104 -0
104 lines not on this page · raw message
net/ieee802154/6lowpan/reassembly.c +1 -1
@@ -25,7 +25,7 @@#include <net/ieee802154_netdev.h> #include <net/6lowpan.h> -#include <net/ipv6.h> +#include <net/ipv6_frag.h> #include <net/inet_frag.h> #include "6lowpan_i.h"
net/ipv6/netfilter/nf_conntrack_reasm.c +12 -5
@@ -33,9 +33,8 @@#include <net/sock.h> #include <net/snmp.h> -#include <net/inet_frag.h> +#include <net/ipv6_frag.h> -#include <net/ipv6.h> #include <net/protocol.h> #include <net/transp_v6.h> #include <net/rawv6.h>
@@ -151,7 +150,7 @@ static void nf_ct_frag6_expire(struct timer_list *t) fq = container_of(frag, struct frag_queue, q); net = container_of(fq->q.net, struct net, nf_frag.frags); -ip6_expire_frag_queue (net, fq); +ip6frag_expire_frag_queue (net, fq); }/* Creation primitives. */
@@ -622,16 +621,24 @@ static struct pernet_operations nf_ct_net_ops = { .exit = nf_ct_net_exit, }; +static const struct rhashtable_params nfct_rhash_params = { + .head_offset = offsetof(struct inet_frag_queue , node), + .hashfn = ip6frag_key_hashfn, + .obj_hashfn = ip6frag_obj_hashfn, + .obj_cmpfn = ip6frag_obj_cmpfn, + .automatic_shrinking = true, +}; +int nf_ct_frag6_init (void ) {int ret =0 ; - nf_frags.constructor = ip6_frag_init; + nf_frags.constructor = ip6frag_init; nf_frags.destructor =NULL ; nf_frags.qsize =sizeof (struct frag_queue ); nf_frags.frag_expire = nf_ct_frag6_expire; nf_frags.frags_cache_name = nf_frags_cache_name; - nf_frags.rhash_params = ip6_rhash_params; + nf_frags.rhash_params = nfct_rhash_params; ret =inet_frags_init (&nf_frags);if (ret) goto out;
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +1 -2
@@ -14,8 +14,7 @@#include <linux/skbuff.h> #include <linux/icmp.h> #include <linux/sysctl.h> -#include <net/ipv6.h> -#include <net/inet_frag.h> +#include <net/ipv6_frag.h> #include <linux/netfilter_ipv6.h> #include <linux/netfilter_bridge.h>
net/ipv6/reassembly.c +7 -85
124 lines not on this page · raw message
net/openvswitch/conntrack.c +1 -0
@@ -26,6 +26,7 @@#include <net/netfilter/nf_conntrack_seqadj.h> #include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/ipv6/nf_defrag_ipv6.h> +#include <net/ipv6_frag.h> #ifdef CONFIG_NF_NAT_NEEDED #include <linux/netfilter/nf_nat.h>
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 38/38 netfilter: nf_osf: add missing definitions to header file
In reply to Pablo Neira AyusoFrom: Fernando Fernandez Mancera <[email protected]>
Add missing definitions from nf_osf.h in order to extract Passive OS fingerprint infrastructure from xt_osf.
--- include/uapi/linux/netfilter/nf_osf.h | 11 +++++++++++ include/uapi/linux/netfilter/xt_osf.h | 10 ++-------- 2 files changed, 13 insertions(+), 8 deletions(-)
include/uapi/linux/netfilter/nf_osf.h +11 -0
@@ -16,9 +16,14 @@#define NF_OSF_TTL_TRUE 0/* True ip and fingerprint TTL comparison */ +/* Check if ip TTL is less than fingerprint one */ +#define NF_OSF_TTL_LESS 1 +/* Do not compare ip and fingerprint TTL at all */ #define NF_OSF_TTL_NOCHECK 2 +#define NF_OSF_FLAGMASK (NF_OSF_GENRE | NF_OSF_TTL | \ + NF_OSF_LOG | NF_OSF_INVERT)/* Wildcard MSS (kind of). * It is used to implement a state machine for the different wildcard values * of the MSS and window sizes.
@@ -83,4 +88,10 @@ enum iana_options { OSFOPT_EMPTY = 255, }; +enum nf_osf_attr_type { +OSF_ATTR_UNSPEC , +OSF_ATTR_FINGER , +OSF_ATTR_MAX , +}; +#endif /* _NF_OSF_H */
include/uapi/linux/netfilter/xt_osf.h +2 -8
@@ -37,8 +37,7 @@#define XT_OSF_TTL_TRUE NF_OSF_TTL_TRUE#define XT_OSF_TTL_NOCHECK NF_OSF_TTL_NOCHECK - -#define XT_OSF_TTL_LESS 1/* Check if ip TTL is less than fingerprint one */ +#define XT_OSF_TTL_LESS NF_OSF_TTL_LESS#define xt_osf_wc nf_osf_wc#define xt_osf_opt nf_osf_opt
@@ -47,6 +46,7 @@#define xt_osf_finger nf_osf_finger#define xt_osf_nlmsg nf_osf_nlmsg +#define xt_osf_attr_type nf_osf_attr_type/* * Add/remove fingerprint from the kernel. */
@@ -56,10 +56,4 @@ enum xt_osf_msg_types { OSF_MSG_MAX, }; -enum xt_osf_attr_type { -OSF_ATTR_UNSPEC , -OSF_ATTR_FINGER , -OSF_ATTR_MAX , -}; -#endif /* _XT_OSF_H */
Signature · 1 line
2.11.0
David Miller
maintainerFrom: Pablo Neira Ayuso <[email protected]>
Date: Fri, 20 Jul 2018 15:08:28 +0200
Quoted 2 lines
The following patchset contains Netfilter/IPVS updates for your net-next tree:
...
Quoted 3 lines
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Pulled, thank you.