Netfilter/IPVS updates for net-next
Subsystems (6)
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) Free hooks via call_rcu to speed up netns release path, from Florian Westphal.
2) Reduce memory footprint of hook arrays, skip allocation if family is not present - useful in case decnet support is not compiled built-in. Patches from Florian Westphal.
3) Remove defensive check for malformed IPv4 - including ihl field - and IPv6 headers in x_tables and nf_tables.
4) Add generic flow table offload infrastructure for nf_tables, this includes the netlink control plane and support for IPv4, IPv6 and mixed IPv4/IPv6 dataplanes. This comes with NAT support too. This patchset adds the IPS_OFFLOAD conntrack status bit to indicate that this flow has been offloaded.
5) Add secpath matching support for nf_tables, from Florian.
6) Save some code bytes in the fast path for the nf_tables netdev, bridge and inet families.
7) Allow one single NAT hook per point and do not allow to register NAT hooks in nf_tables before the conntrack hook, patches from Florian.
8) Seven patches to remove the struct nf_af_info abstraction, instead we perform direct calls for IPv4 which is faster. IPv6 indirections are still needed to avoid dependencies with the 'ipv6' module, but these now reside in struct nf_ipv6_ops.
9) Seven patches to handle NFPROTO_INET from the Netfilter core, hence we can remove specific code in nf_tables to handle this pseudofamily.
10) No need for synchronize_net() call for nf_queue after conversion to hook arrays. Also from Florian.
11) Call cond_resched_rcu() when dumping large sets in ipset to avoid softlockup. Again from Florian.
12) Pass lockdep_nfnl_is_held() to rcu_dereference_protected(), patch from Florian Westphal.
13) Fix matching of counters in ipset, from Jozsef Kadlecsik.
14) Missing nfnl lock protection in the ip_set_net_exit path, also from Jozsef.
15) Move connlimit code that we can reuse from nf_tables into nf_conncount, from Florian Westhal.
And asorted cleanups:
16) Get rid of nft_dereference(), it only has one single caller.
17) Add nft_set_is_anonymous() helper function.
18) Remove NF_ARP_FORWARD leftover chain definition in nf_tables_arp.
19) Remove unnecessary comments in nf_conntrack_h323_asn1.c From Varsha Rao.
20) Remove useless parameters in frag_safe_skb_hp(), from Gao Feng.
21) Constify layer 4 conntrack protocol definitions, function parameters to register/unregister these protocol trackers, and timeouts. Patches from Florian Westphal.
22) Remove nlattr_size indirection, from Florian Westphal.
23) Add fall-through comments as -Wimplicit-fallthrough needs this, from Gustavo A. R. Silva.
24) Use swap() macro to exchange values in ipset, patch from Gustavo A. R. Silva.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Thanks!
PS. I will be preparing a second batch with more updates asap.
----------------------------------------------------------------
The following changes since commit f66faae2f80a45feafc04ce63ef744ac4b6e8c05:
Merge branch 'ipv6-ipv4-nexthop-align' (2018-01-07 21:29:41 -0500)
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 f998b6b10144cd9809da6af02758615f789e8aa1:
netfilter: ipset: Missing nfnl_lock()/nfnl_unlock() is added to ip_set_net_exit() (2018-01-08 18:11:12 +0100)
----------------------------------------------------------------
Florian Westphal (20):
netfilter: conntrack: remove nlattr_size pointer from l4proto trackers
netfilter: conntrack: constify list of builtin trackers
netfilter: conntrack: l4 protocol trackers can be const
netfilter: conntrack: timeouts can be const
netfilter: ipset: use nfnl_mutex_is_locked
netfilter: ipset: add resched points during set listing
netfilter: core: make nf_unregister_net_hooks simple wrapper again
netfilter: core: remove synchronize_net call if nfqueue is used
netfilter: core: free hooks with call_rcu
netfilter: reduce size of hook entry point locations
netfilter: add defines for arp/decnet max hooks
netfilter: reduce hook array sizes to what is needed
netfilter: don't allocate space for decnet hooks unless needed
netfilter: don't allocate space for arp/bridge hooks unless needed
netfilter: reduce NF_MAX_HOOKS define
netfilter: xtables: add and use xt_request_find_table_lock
netfilter: core: only allow one nat hook per hook point
netfilter: nf_tables: reject nat hook registration if prio is before conntrack
netfilter: connlimit: split xt_connlimit into front and backend
netfilter: meta: secpath support
Gao Feng (1):
netfilter: ipvs: Remove useless ipvsh param of frag_safe_skb_hp
Gustavo A. R. Silva (2):
netfilter: mark expected switch fall-throughs
netfilter: ipset: use swap macro instead of _manually_ swapping values
Jozsef Kadlecsik (2):
netfilter: ipset: Fix "don't update counters" mode when counters used at the matching
netfilter: ipset: Missing nfnl_lock()/nfnl_unlock() is added to ip_set_net_exit()
Pablo Neira Ayuso (26):
netfilter: nf_tables_arp: don't set forward chain
netfilter: nf_tables: explicit nft_set_pktinfo() call from hook path
netfilter: nf_tables: add nft_set_is_anonymous() helper
netfilter: core: add nf_remove_net_hook
netfilter: core: pass hook number, family and device to nf_find_hook_list()
netfilter: core: pass family as parameter to nf_remove_net_hook()
netfilter: core: support for NFPROTO_INET hook registration
netfilter: nf_tables_inet: don't use multihook infrastructure anymore
netfilter: nf_tables: remove multihook chains and families
netfilter: nf_tables: remove hooks from family definition
netfilter: move checksum indirection to struct nf_ipv6_ops
netfilter: move checksum_partial indirection to struct nf_ipv6_ops
netfilter: remove saveroute indirection in struct nf_afinfo
netfilter: move route indirection to struct nf_ipv6_ops
netfilter: move reroute indirection to struct nf_ipv6_ops
netfilter: remove route_key_size field in struct nf_afinfo
netfilter: remove struct nf_afinfo and its helper functions
netfilter: remove defensive check on malformed packets from raw sockets
netfilter: nf_tables: remove nft_dereference()
netfilter: nf_conntrack: add IPS_OFFLOAD status bit
netfilter: nf_tables: add flow table netlink frontend
netfilter: add generic flow table infrastructure
netfilter: flow table support for IPv4
netfilter: flow table support for IPv6
netfilter: flow table support for the mixed IPv4/IPv6 family
netfilter: nf_tables: flow offload expression
Varsha Rao (1):
netfilter: nf_conntrack_h323: Remove unwanted comments.
include/linux/netfilter.h | 116 ++- include/linux/netfilter/ipset/ip_set.h | 6 + include/linux/netfilter/ipset/ip_set_counter.h | 25 +- include/linux/netfilter/x_tables.h | 2 + include/linux/netfilter_defs.h | 12 +- include/linux/netfilter_ipv4.h | 46 ++ include/linux/netfilter_ipv6.h | 19 + include/net/ip_vs.h | 3 +- include/net/ipv6.h | 2 + include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 12 +- include/net/netfilter/ipv6/nf_conntrack_ipv6.h | 12 +- include/net/netfilter/nf_conntrack_count.h | 17 + include/net/netfilter/nf_conntrack_l4proto.h | 19 +- include/net/netfilter/nf_flow_table.h | 122 +++ include/net/netfilter/nf_queue.h | 2 +- include/net/netfilter/nf_tables.h | 81 +- include/net/netfilter/nf_tables_ipv4.h | 27 +- include/net/netfilter/nf_tables_ipv6.h | 29 +- include/net/netns/netfilter.h | 12 +- include/uapi/linux/netfilter/nf_conntrack_common.h | 6 +- include/uapi/linux/netfilter/nf_tables.h | 66 ++ include/uapi/linux/netfilter/xt_connlimit.h | 2 +- include/uapi/linux/netfilter_arp.h | 3 + include/uapi/linux/netfilter_decnet.h | 4 +- net/Kconfig | 1 + net/bridge/br_netfilter_hooks.c | 2 +- net/bridge/netfilter/Kconfig | 2 + net/bridge/netfilter/nf_tables_bridge.c | 74 +- net/ipv4/netfilter.c | 62 +- net/ipv4/netfilter/Kconfig | 10 + net/ipv4/netfilter/Makefile | 3 + net/ipv4/netfilter/arp_tables.c | 26 +- net/ipv4/netfilter/ip_tables.c | 26 +- net/ipv4/netfilter/iptable_filter.c | 6 - net/ipv4/netfilter/iptable_mangle.c | 5 - net/ipv4/netfilter/iptable_nat.c | 4 + net/ipv4/netfilter/iptable_raw.c | 6 - net/ipv4/netfilter/iptable_security.c | 6 - net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 7 +- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 4 +- net/ipv4/netfilter/nf_flow_table_ipv4.c | 284 +++++++ net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 10 - net/ipv4/netfilter/nf_tables_arp.c | 13 +- net/ipv4/netfilter/nf_tables_ipv4.c | 36 +- net/ipv4/netfilter/nft_chain_nat_ipv4.c | 3 +- net/ipv4/netfilter/nft_chain_route_ipv4.c | 8 +- net/ipv6/ip6_output.c | 3 +- net/ipv6/netfilter.c | 44 +- net/ipv6/netfilter/Kconfig | 8 + net/ipv6/netfilter/Makefile | 3 + net/ipv6/netfilter/ip6_tables.c | 26 +- net/ipv6/netfilter/ip6table_mangle.c | 8 - net/ipv6/netfilter/ip6table_nat.c | 4 + net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 7 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 4 +- net/ipv6/netfilter/nf_flow_table_ipv6.c | 278 +++++++ net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 8 - net/ipv6/netfilter/nf_tables_ipv6.c | 35 +- net/ipv6/netfilter/nft_chain_nat_ipv6.c | 3 +- net/ipv6/netfilter/nft_chain_route_ipv6.c | 3 +- net/ipv6/netfilter/nft_fib_ipv6.c | 12 +- net/netfilter/Kconfig | 31 + net/netfilter/Makefile | 9 +- net/netfilter/core.c | 263 ++++--- net/netfilter/ipset/ip_set_bitmap_gen.h | 10 +- net/netfilter/ipset/ip_set_bitmap_ip.c | 8 +- net/netfilter/ipset/ip_set_bitmap_ipmac.c | 8 +- net/netfilter/ipset/ip_set_bitmap_port.c | 8 +- net/netfilter/ipset/ip_set_core.c | 33 +- net/netfilter/ipset/ip_set_hash_gen.h | 38 +- net/netfilter/ipset/ip_set_list_set.c | 21 +- net/netfilter/ipvs/ip_vs_conn.c | 2 +- net/netfilter/ipvs/ip_vs_core.c | 12 +- net/netfilter/ipvs/ip_vs_proto_tcp.c | 1 + net/netfilter/ipvs/ip_vs_proto_udp.c | 1 + net/netfilter/nf_conncount.c | 373 +++++++++ net/netfilter/nf_conntrack_core.c | 20 + net/netfilter/nf_conntrack_h323_asn1.c | 40 +- net/netfilter/nf_conntrack_h323_main.c | 77 +- net/netfilter/nf_conntrack_netlink.c | 17 +- net/netfilter/nf_conntrack_proto.c | 18 +- net/netfilter/nf_conntrack_proto_dccp.c | 21 +- net/netfilter/nf_conntrack_proto_generic.c | 4 +- net/netfilter/nf_conntrack_proto_gre.c | 4 +- net/netfilter/nf_conntrack_proto_sctp.c | 21 +- net/netfilter/nf_conntrack_proto_tcp.c | 25 +- net/netfilter/nf_conntrack_proto_udp.c | 10 +- net/netfilter/nf_conntrack_standalone.c | 12 +- net/netfilter/nf_flow_table.c | 429 ++++++++++ net/netfilter/nf_flow_table_inet.c | 48 ++ net/netfilter/nf_internals.h | 2 +- net/netfilter/nf_queue.c | 98 ++- net/netfilter/nf_tables_api.c | 868 +++++++++++++++++++-- net/netfilter/nf_tables_inet.c | 39 +- net/netfilter/nf_tables_netdev.c | 17 +- net/netfilter/nfnetlink_queue.c | 9 +- net/netfilter/nft_cmp.c | 2 + net/netfilter/nft_compat.c | 8 +- net/netfilter/nft_dynset.c | 2 +- net/netfilter/nft_flow_offload.c | 264 +++++++ net/netfilter/nft_meta.c | 43 + net/netfilter/nft_rt.c | 15 +- net/netfilter/utils.c | 90 +++ net/netfilter/x_tables.c | 38 +- net/netfilter/xt_TCPMSS.c | 5 +- net/netfilter/xt_addrtype.c | 15 +- net/netfilter/xt_connlimit.c | 369 +-------- net/netfilter/xt_set.c | 119 +-- 108 files changed, 3853 insertions(+), 1403 deletions(-) create mode 100644 include/net/netfilter/nf_conntrack_count.h create mode 100644 include/net/netfilter/nf_flow_table.h create mode 100644 net/ipv4/netfilter/nf_flow_table_ipv4.c create mode 100644 net/ipv6/netfilter/nf_flow_table_ipv6.c create mode 100644 net/netfilter/nf_conncount.c create mode 100644 net/netfilter/nf_flow_table.c create mode 100644 net/netfilter/nf_flow_table_inet.c create mode 100644 net/netfilter/nft_flow_offload.c create mode 100644 net/netfilter/utils.c
Pablo Neira Ayuso
maintainerPATCH 1/52 netfilter: conntrack: remove nlattr_size pointer from l4proto trackers
From: Florian Westphal <[email protected]>
similar to previous commit, but instead compute this at compile time and turn nlattr_size into an u16.
--- include/net/netfilter/nf_conntrack_l4proto.h | 7 +++---- net/netfilter/nf_conntrack_netlink.c | 2 +- net/netfilter/nf_conntrack_proto.c | 6 +----- net/netfilter/nf_conntrack_proto_dccp.c | 17 ++++++++--------- net/netfilter/nf_conntrack_proto_sctp.c | 15 +++++++-------- net/netfilter/nf_conntrack_proto_tcp.c | 16 ++++++++-------- 6 files changed, 28 insertions(+), 35 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +3 -4
@@ -27,6 +27,9 @@ struct nf_conntrack_l4proto {/* Resolve clashes on insertion races. */ bool allow_clash; +/* protoinfo nlattr size, closes a hole */ +u16 nlattr_size; +/* Try to fill in the third arg: dataoff is offset past network protocol hdr. Return true if possible. */ bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int dataoff,
@@ -66,8 +69,6 @@ struct nf_conntrack_l4proto {/* convert protoinfo to nfnetink attributes */ int (*to_nlattr)(struct sk_buff *skb,struct nlattr *nla,struct nf_conn *ct); -/* Calculate protoinfo nlattr size */ -int (*nlattr_size)(void );/* convert nfnetlink attributes to protoinfo */ int (*from_nlattr)(struct nlattr *tb[],struct nf_conn *ct);
@@ -80,8 +81,6 @@ struct nf_conntrack_l4proto { struct nf_conntrack_tuple *t);const struct nla_policy *nla_policy; -size_t nla_size; - #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) struct { int (*nlattr_to_obj)(struct nlattr *tb[],
net/netfilter/nf_conntrack_netlink.c +1 -1
@@ -544,7 +544,7 @@ static size_t ctnetlink_proto_size(const struct nf_conn *ct) len *=3u ;/* ORIG, REPLY, MASTER */ l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct)); - len += l4proto->nla_size; + len += l4proto->nlattr_size;if (l4proto->nlattr_tuple_size) { len4 = l4proto->nlattr_tuple_size (); len4 *=3u ;/* ORIG, REPLY, MASTER */
net/netfilter/nf_conntrack_proto.c +1 -5
@@ -392,7 +392,7 @@ int nf_ct_l4proto_register_one(struct nf_conntrack_l4proto *l4proto)if (l4proto->l3proto >=ARRAY_SIZE (nf_ct_protos))return -EBUSY ; -if ((l4proto->to_nlattr && !l4proto->nlattr_size) || +if ((l4proto->to_nlattr && l4proto->nlattr_size ==0 ) || (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size))return -EINVAL ;
@@ -428,10 +428,6 @@ int nf_ct_l4proto_register_one(struct nf_conntrack_l4proto *l4proto) goto out_unlock; } - l4proto->nla_size =0 ; -if (l4proto->nlattr_size) - l4proto->nla_size += l4proto->nlattr_size (); -rcu_assign_pointer (nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto); out_unlock:
net/netfilter/nf_conntrack_proto_dccp.c +8 -9
@@ -654,6 +654,12 @@ static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = { [CTA_PROTOINFO_DCCP_PAD] = { .type = NLA_UNSPEC }, }; +#define DCCP_NLATTR_SIZE ( \ + NLA_ALIGN(NLA_HDRLEN + 1) + \ + NLA_ALIGN(NLA_HDRLEN + 1) + \ + NLA_ALIGN(NLA_HDRLEN + sizeof(u64)) + \ + NLA_ALIGN(NLA_HDRLEN + 0)) +static int nlattr_to_dccp (struct nlattr *cda[],struct nf_conn *ct) {struct nlattr *attr = cda[CTA_PROTOINFO_DCCP ];
@@ -691,13 +697,6 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)spin_unlock_bh (&ct->lock); return 0; } - -static int dccp_nlattr_size (void ) -{ -return nla_total_size (0 )/* CTA_PROTOINFO_DCCP */ - +nla_policy_len (dccp_nla_policy,CTA_PROTOINFO_DCCP_MAX +1 ); -} -#endif #if IS_ENABLED (CONFIG_NF_CT_NETLINK_TIMEOUT )
@@ -876,8 +875,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 __read_mostly = { .print_conntrack = dccp_print_conntrack,#endif #if IS_ENABLED (CONFIG_NF_CT_NETLINK ) + .nlattr_size = DCCP_NLATTR_SIZE, .to_nlattr = dccp_to_nlattr, - .nlattr_size = dccp_nlattr_size, .from_nlattr = nlattr_to_dccp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
@@ -912,8 +911,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 __read_mostly = { .print_conntrack = dccp_print_conntrack,#endif #if IS_ENABLED (CONFIG_NF_CT_NETLINK ) + .nlattr_size = DCCP_NLATTR_SIZE, .to_nlattr = dccp_to_nlattr, - .nlattr_size = dccp_nlattr_size, .from_nlattr = nlattr_to_dccp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
net/netfilter/nf_conntrack_proto_sctp.c +7 -8
@@ -578,6 +578,11 @@ static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = { [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 }, }; +#define SCTP_NLATTR_SIZE ( \ + NLA_ALIGN(NLA_HDRLEN + 1) + \ + NLA_ALIGN(NLA_HDRLEN + 4) + \ + NLA_ALIGN(NLA_HDRLEN + 4)) +static int nlattr_to_sctp (struct nlattr *cda[],struct nf_conn *ct) {struct nlattr *attr = cda[CTA_PROTOINFO_SCTP ];
@@ -608,12 +613,6 @@ static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct) return 0; } - -static int sctp_nlattr_size (void ) -{ -return nla_total_size (0 )/* CTA_PROTOINFO_SCTP */ - +nla_policy_len (sctp_nla_policy,CTA_PROTOINFO_SCTP_MAX +1 ); -}#endif #if IS_ENABLED (CONFIG_NF_CT_NETLINK_TIMEOUT )
@@ -793,8 +792,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { .can_early_drop = sctp_can_early_drop, .me = THIS_MODULE,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) + .nlattr_size = SCTP_NLATTR_SIZE, .to_nlattr = sctp_to_nlattr, - .nlattr_size = sctp_nlattr_size, .from_nlattr = nlattr_to_sctp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
@@ -830,8 +829,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { .can_early_drop = sctp_can_early_drop, .me = THIS_MODULE,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) + .nlattr_size = SCTP_NLATTR_SIZE, .to_nlattr = sctp_to_nlattr, - .nlattr_size = sctp_nlattr_size, .from_nlattr = nlattr_to_sctp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
net/netfilter/nf_conntrack_proto_tcp.c +8 -8
@@ -1222,6 +1222,12 @@ static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, }; +#define TCP_NLATTR_SIZE ( \ + NLA_ALIGN(NLA_HDRLEN + 1) + \ + NLA_ALIGN(NLA_HDRLEN + 1) + \ + NLA_ALIGN(NLA_HDRLEN + sizeof(sizeof(struct nf_ct_tcp_flags))) + \ + NLA_ALIGN(NLA_HDRLEN + sizeof(sizeof(struct nf_ct_tcp_flags)))) +static int nlattr_to_tcp (struct nlattr *cda[],struct nf_conn *ct) {struct nlattr *pattr = cda[CTA_PROTOINFO_TCP ];
@@ -1274,12 +1280,6 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)return 0 ; } -static int tcp_nlattr_size (void ) -{ -return nla_total_size (0 )/* CTA_PROTOINFO_TCP */ - +nla_policy_len (tcp_nla_policy,CTA_PROTOINFO_TCP_MAX +1 ); -} -static unsigned int tcp_nlattr_tuple_size (void ) {static unsigned int size__read_mostly ;
@@ -1557,11 +1557,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = .can_early_drop = tcp_can_early_drop,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) .to_nlattr = tcp_to_nlattr, - .nlattr_size = tcp_nlattr_size, .from_nlattr = nlattr_to_tcp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nlattr_tuple_size = tcp_nlattr_tuple_size, + .nlattr_size = TCP_NLATTR_SIZE, .nla_policy = nf_ct_port_nla_policy,#endif #if IS_ENABLED (CONFIG_NF_CT_NETLINK_TIMEOUT )
@@ -1594,8 +1594,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = .error = tcp_error, .can_early_drop = tcp_can_early_drop,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) + .nlattr_size = TCP_NLATTR_SIZE, .to_nlattr = tcp_to_nlattr, - .nlattr_size = tcp_nlattr_size, .from_nlattr = nlattr_to_tcp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 2/52 netfilter: conntrack: constify list of builtin trackers
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
--- include/net/netfilter/nf_conntrack_l4proto.h | 10 +++++----- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 2 +- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 2 +- net/netfilter/nf_conntrack_proto.c | 12 ++++++------ 4 files changed, 13 insertions(+), 13 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +5 -5
@@ -125,18 +125,18 @@ int nf_ct_l4proto_pernet_register_one(struct net *net,void nf_ct_l4proto_pernet_unregister_one (struct net *net,const struct nf_conntrack_l4proto *proto);int nf_ct_l4proto_pernet_register (struct net *net, -struct nf_conntrack_l4proto *const proto[], +const struct nf_conntrack_l4proto *const proto[],unsigned int num_proto);void nf_ct_l4proto_pernet_unregister (struct net *net, -struct nf_conntrack_l4proto *const proto[], +const struct nf_conntrack_l4proto *const proto[],unsigned int num_proto);/* Protocol global registration. */ -int nf_ct_l4proto_register_one (struct nf_conntrack_l4proto *proto); +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 (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 (struct nf_conntrack_l4proto *proto[], +void nf_ct_l4proto_unregister (const struct nf_conntrack_l4proto *const proto[],unsigned int num_proto);/* Generic netlink helpers */
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +1 -1
@@ -368,7 +368,7 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));MODULE_ALIAS ("ip_conntrack" );MODULE_LICENSE ("GPL" ); -static struct nf_conntrack_l4proto *builtin_l4proto4[] = { +static const struct nf_conntrack_l4proto *const builtin_l4proto4[] = { &nf_conntrack_l4proto_tcp4, &nf_conntrack_l4proto_udp4, &nf_conntrack_l4proto_icmp,
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +1 -1
@@ -368,7 +368,7 @@ static struct nf_sockopt_ops so_getorigdst6 = { .owner = THIS_MODULE, }; -static struct nf_conntrack_l4proto *builtin_l4proto6[] = { +static const struct nf_conntrack_l4proto *const builtin_l4proto6[] = { &nf_conntrack_l4proto_tcp6, &nf_conntrack_l4proto_udp6, &nf_conntrack_l4proto_icmpv6,
net/netfilter/nf_conntrack_proto.c +6 -6
@@ -385,7 +385,7 @@ void nf_ct_l4proto_unregister_sysctl(struct net *net,/* FIXME: Allow NULL functions and sub in pointers to generic for them. --RR */ -int nf_ct_l4proto_register_one (struct nf_conntrack_l4proto *l4proto) +int nf_ct_l4proto_register_one (const struct nf_conntrack_l4proto *l4proto) {int ret =0 ;
@@ -498,7 +498,7 @@ void nf_ct_l4proto_pernet_unregister_one(struct net *net, }EXPORT_SYMBOL_GPL (nf_ct_l4proto_pernet_unregister_one); -int nf_ct_l4proto_register (struct nf_conntrack_l4proto *l4proto[], +int nf_ct_l4proto_register (const struct nf_conntrack_l4proto *const l4proto[],unsigned int num_proto) {int ret = -EINVAL , ver;
@@ -520,7 +520,7 @@ int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto[],EXPORT_SYMBOL_GPL (nf_ct_l4proto_register);int nf_ct_l4proto_pernet_register (struct net *net, -struct nf_conntrack_l4proto *const l4proto[], +const struct nf_conntrack_l4proto *const l4proto[],unsigned int num_proto) {int ret = -EINVAL ;
@@ -541,7 +541,7 @@ int nf_ct_l4proto_pernet_register(struct net *net, }EXPORT_SYMBOL_GPL (nf_ct_l4proto_pernet_register); -void nf_ct_l4proto_unregister (struct nf_conntrack_l4proto *l4proto[], +void nf_ct_l4proto_unregister (const struct nf_conntrack_l4proto *const l4proto[],unsigned int num_proto) {mutex_lock (&nf_ct_proto_mutex);
@@ -551,12 +551,12 @@ void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto[],synchronize_net ();/* Remove all contrack entries for this protocol */ -nf_ct_iterate_destroy (kill_l4proto, l4proto); +nf_ct_iterate_destroy (kill_l4proto, (void *)l4proto); }EXPORT_SYMBOL_GPL (nf_ct_l4proto_unregister);void nf_ct_l4proto_pernet_unregister (struct net *net, -struct nf_conntrack_l4proto *const l4proto[], +const struct nf_conntrack_l4proto *const l4proto[],unsigned int num_proto) {while (num_proto-- !=0 )
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 3/52 netfilter: conntrack: l4 protocol trackers can be const
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
previous patches removed all writes to these structs so we can now mark them as const.
--- include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 12 ++++++------ include/net/netfilter/ipv6/nf_conntrack_ipv6.h | 12 ++++++------ include/net/netfilter/nf_conntrack_l4proto.h | 2 +- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 2 +- net/netfilter/nf_conntrack_proto_dccp.c | 4 ++-- net/netfilter/nf_conntrack_proto_generic.c | 2 +- net/netfilter/nf_conntrack_proto_gre.c | 2 +- net/netfilter/nf_conntrack_proto_sctp.c | 4 ++-- net/netfilter/nf_conntrack_proto_tcp.c | 4 ++-- net/netfilter/nf_conntrack_proto_udp.c | 8 ++++---- 11 files changed, 27 insertions(+), 27 deletions(-)
include/net/netfilter/ipv4/nf_conntrack_ipv4.h +6 -6
@@ -13,17 +13,17 @@const extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp; +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;#ifdef CONFIG_NF_CT_PROTO_DCCP -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4;#endif #ifdef CONFIG_NF_CT_PROTO_SCTP -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4;#endif #ifdef CONFIG_NF_CT_PROTO_UDPLITE -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4;#endif int nf_conntrack_ipv4_compat_init (void );
include/net/netfilter/ipv6/nf_conntrack_ipv6.h +6 -6
@@ -4,17 +4,17 @@extern const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;#ifdef CONFIG_NF_CT_PROTO_DCCP -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6;#endif #ifdef CONFIG_NF_CT_PROTO_SCTP -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6;#endif #ifdef CONFIG_NF_CT_PROTO_UDPLITE -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6;#endif #include <linux/sysctl.h>
include/net/netfilter/nf_conntrack_l4proto.h +1 -1
@@ -108,7 +108,7 @@ struct nf_conntrack_l4proto { };/* Existing built-in generic protocol */ -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;#define MAX_NF_CT_PROTO 256
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +1 -1
@@ -351,7 +351,7 @@ static struct nf_proto_net *icmp_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.icmp.pn; } -struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = { .l3proto =PF_INET , .l4proto =IPPROTO_ICMP ,
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +1 -1
@@ -352,7 +352,7 @@ static struct nf_proto_net *icmpv6_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.icmpv6.pn; } -struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = { .l3proto =PF_INET6 , .l4proto =IPPROTO_ICMPV6 ,
net/netfilter/nf_conntrack_proto_dccp.c +2 -2
@@ -861,7 +861,7 @@ static struct nf_proto_net *dccp_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.dccp.pn; } -struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4__read_mostly = { +const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { .l3proto =AF_INET , .l4proto =IPPROTO_DCCP , .pkt_to_tuple = dccp_pkt_to_tuple,
@@ -897,7 +897,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 __read_mostly = { };EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_dccp4); -struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6__read_mostly = { +const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { .l3proto =AF_INET6 , .l4proto =IPPROTO_DCCP , .pkt_to_tuple = dccp_pkt_to_tuple,
net/netfilter/nf_conntrack_proto_generic.c +1 -1
@@ -163,7 +163,7 @@ static struct nf_proto_net *generic_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.generic.pn; } -struct nf_conntrack_l4proto nf_conntrack_l4proto_generic__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = { .l3proto =PF_UNSPEC , .l4proto =255 ,
net/netfilter/nf_conntrack_proto_gre.c +1 -1
@@ -352,7 +352,7 @@ static int gre_init_net(struct net *net, u_int16_t proto) }/* protocol helper struct */ -static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4__read_mostly = { +static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { .l3proto =AF_INET , .l4proto =IPPROTO_GRE , .pkt_to_tuple = gre_pkt_to_tuple,
net/netfilter/nf_conntrack_proto_sctp.c +2 -2
@@ -777,7 +777,7 @@ static struct nf_proto_net *sctp_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.sctp.pn; } -struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4__read_mostly = { +const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { .l3proto =PF_INET , .l4proto =IPPROTO_SCTP , .pkt_to_tuple = sctp_pkt_to_tuple,
@@ -814,7 +814,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { };EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_sctp4); -struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6__read_mostly = { +const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { .l3proto =PF_INET6 , .l4proto =IPPROTO_SCTP , .pkt_to_tuple = sctp_pkt_to_tuple,
net/netfilter/nf_conntrack_proto_tcp.c +2 -2
@@ -1541,7 +1541,7 @@ static struct nf_proto_net *tcp_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.tcp.pn; } -struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = { .l3proto =PF_INET , .l4proto =IPPROTO_TCP ,
@@ -1579,7 +1579,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = };EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp4); -struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = { .l3proto =PF_INET6 , .l4proto =IPPROTO_TCP ,
net/netfilter/nf_conntrack_proto_udp.c +4 -4
@@ -296,7 +296,7 @@ static struct nf_proto_net *udp_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.udp.pn; } -struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = { .l3proto =PF_INET , .l4proto =IPPROTO_UDP ,
@@ -328,7 +328,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_udp4);#ifdef CONFIG_NF_CT_PROTO_UDPLITE -struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 = { .l3proto =PF_INET , .l4proto = IPPROTO_UDPLITE,
@@ -360,7 +360,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_udplite4);#endif -struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = { .l3proto =PF_INET6 , .l4proto =IPPROTO_UDP ,
@@ -392,7 +392,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_udp6);#ifdef CONFIG_NF_CT_PROTO_UDPLITE -struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6__read_mostly = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 = { .l3proto =PF_INET6 , .l4proto = IPPROTO_UDPLITE,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 4/52 netfilter: mark expected switch fall-throughs
In reply to Pablo Neira AyusoFrom: "Gustavo A. R. Silva" <[email protected]>
In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through.
--- net/netfilter/ipset/ip_set_core.c | 2 +- net/netfilter/ipvs/ip_vs_proto_tcp.c | 1 + net/netfilter/ipvs/ip_vs_proto_udp.c | 1 + net/netfilter/nf_conntrack_h323_asn1.c | 3 +++ net/netfilter/nft_cmp.c | 2 ++ net/netfilter/x_tables.c | 2 +- 6 files changed, 9 insertions(+), 2 deletions(-)
net/netfilter/ipset/ip_set_core.c +1 -1
@@ -1386,7 +1386,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) goto next_set;if (set->variant->uref) set->variant->uref (set, cb, true); -/* Fall through and add elements */ +/* fall through */ default :rcu_read_lock_bh (); ret = set->variant->list (set, skb, cb);
net/netfilter/ipvs/ip_vs_proto_tcp.c +1 -0
@@ -315,6 +315,7 @@ tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)switch (skb->ip_summed) {case CHECKSUM_NONE : skb->csum =skb_checksum (skb, tcphoff, skb->len - tcphoff,0 ); +/* fall through */ case CHECKSUM_COMPLETE :#ifdef CONFIG_IP_VS_IPV6 if (af ==AF_INET6 ) {
net/netfilter/ipvs/ip_vs_proto_udp.c +1 -0
@@ -319,6 +319,7 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)case CHECKSUM_NONE : skb->csum =skb_checksum (skb, udphoff, skb->len - udphoff,0 ); +/* fall through */ case CHECKSUM_COMPLETE :#ifdef CONFIG_IP_VS_IPV6 if (af ==AF_INET6 ) {
net/netfilter/nf_conntrack_h323_asn1.c +3 -0
@@ -262,12 +262,15 @@ static unsigned int get_uint(struct bitstr *bs, int b)case 4 : v |= *bs->cur++; v <<=8 ; +/* fall through */ case 3 : v |= *bs->cur++; v <<=8 ; +/* fall through */ case 2 : v |= *bs->cur++; v <<=8 ; +/* fall through */ case 1 : v |= *bs->cur++;break ;
net/netfilter/nft_cmp.c +2 -0
@@ -44,6 +44,7 @@ static void nft_cmp_eval(const struct nft_expr *expr,case NFT_CMP_LT :if (d ==0 ) goto mismatch; +/* fall through */ case NFT_CMP_LTE :if (d >0 ) goto mismatch;
@@ -51,6 +52,7 @@ static void nft_cmp_eval(const struct nft_expr *expr,case NFT_CMP_GT :if (d ==0 ) goto mismatch; +/* fall through */ case NFT_CMP_GTE :if (d <0 ) goto mismatch;
net/netfilter/x_tables.c +1 -1
@@ -1397,7 +1397,7 @@ static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos, trav->curr = trav->curr->next;if (trav->curr != trav->head)break ; -/* fallthru, _stop will unlock */ +/* fall through */ default :return NULL ; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 5/52 netfilter: conntrack: timeouts can be const
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Nowadays this is just the default template that is used when setting up the net namespace, so nothing writes to these locations.
--- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 2 +- net/netfilter/nf_conntrack_proto_generic.c | 2 +- net/netfilter/nf_conntrack_proto_gre.c | 2 +- net/netfilter/nf_conntrack_proto_sctp.c | 2 +- net/netfilter/nf_conntrack_proto_tcp.c | 2 +- net/netfilter/nf_conntrack_proto_udp.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-)
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +1 -1
@@ -22,7 +22,7 @@#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_log.h> -static unsigned int nf_ct_icmp_timeout__read_mostly =30 *HZ ; +static const unsigned int nf_ct_icmp_timeout =30 *HZ ;static inline struct nf_icmp_net *icmp_pernet (struct net *net) {
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +1 -1
@@ -27,7 +27,7 @@#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> #include <net/netfilter/nf_log.h> -static unsigned int nf_ct_icmpv6_timeout__read_mostly =30 *HZ ; +static const unsigned int nf_ct_icmpv6_timeout =30 *HZ ;static inline struct nf_icmp_net *icmpv6_pernet (struct net *net) {
net/netfilter/nf_conntrack_proto_generic.c +1 -1
@@ -12,7 +12,7 @@#include <linux/netfilter.h> #include <net/netfilter/nf_conntrack_l4proto.h> -static unsigned int nf_ct_generic_timeout__read_mostly =600 *HZ ; +static const unsigned int nf_ct_generic_timeout =600 *HZ ;static bool nf_generic_should_process (u8 proto) {
net/netfilter/nf_conntrack_proto_gre.c +1 -1
@@ -48,7 +48,7 @@ enum grep_conntrack { GRE_CT_MAX }; -static unsigned int gre_timeouts[GRE_CT_MAX ] = { +static const unsigned int gre_timeouts[GRE_CT_MAX ] = { [GRE_CT_UNREPLIED ] =30 *HZ , [GRE_CT_REPLIED ] =180 *HZ , };
net/netfilter/nf_conntrack_proto_sctp.c +1 -1
@@ -52,7 +52,7 @@ static const char *const sctp_conntrack_names[] = {#define HOURS * 60 MINS#define DAYS * 24 HOURS -static unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX ]__read_mostly = { +static const unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX ] = { [SCTP_CONNTRACK_CLOSED] = 10 SECS, [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS, [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS,
net/netfilter/nf_conntrack_proto_tcp.c +1 -1
@@ -68,7 +68,7 @@ static const char *const tcp_conntrack_names[] = {#define HOURS * 60 MINS#define DAYS * 24 HOURS -static unsigned int tcp_timeouts[TCP_CONNTRACK_TIMEOUT_MAX ]__read_mostly = { +static const unsigned int tcp_timeouts[TCP_CONNTRACK_TIMEOUT_MAX ] = { [TCP_CONNTRACK_SYN_SENT] = 2 MINS, [TCP_CONNTRACK_SYN_RECV] = 60 SECS, [TCP_CONNTRACK_ESTABLISHED] = 5 DAYS,
net/netfilter/nf_conntrack_proto_udp.c +1 -1
@@ -26,7 +26,7 @@#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> -static unsigned int udp_timeouts[UDP_CT_MAX ] = { +static const unsigned int udp_timeouts[UDP_CT_MAX ] = { [UDP_CT_UNREPLIED ] =30 *HZ , [UDP_CT_REPLIED ] =180 *HZ , };
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 6/52 netfilter: ipvs: Remove useless ipvsh param of frag_safe_skb_hp
In reply to Pablo Neira AyusoFrom: Gao Feng <[email protected]>
The param of frag_safe_skb_hp, ipvsh, isn't used now. So remove it and update the callers' codes too.
--- include/net/ip_vs.h | 3 +-- net/netfilter/ipvs/ip_vs_conn.c | 2 +- net/netfilter/ipvs/ip_vs_core.c | 12 ++++++------ 3 files changed, 8 insertions(+), 9 deletions(-)
include/net/ip_vs.h +1 -2
@@ -69,8 +69,7 @@ struct ip_vs_iphdr { };static inline void *frag_safe_skb_hp (const struct sk_buff *skb,int offset, -int len,void *buffer, -const struct ip_vs_iphdr *ipvsh) +int len,void *buffer) {return skb_header_pointer (skb, offset, len, buffer); }
net/netfilter/ipvs/ip_vs_conn.c +1 -1
@@ -322,7 +322,7 @@ ip_vs_conn_fill_param_proto(struct netns_ipvs *ipvs, {__be16 _ports[2 ], *pptr; - pptr =frag_safe_skb_hp (skb, iph->len,sizeof (_ports), _ports, iph); + pptr =frag_safe_skb_hp (skb, iph->len,sizeof (_ports), _ports);if (pptr ==NULL )return 1 ;
net/netfilter/ipvs/ip_vs_core.c +6 -6
@@ -433,7 +433,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,/* * IPv6 frags, only the first hit here. */ - pptr =frag_safe_skb_hp (skb, iph->len,sizeof (_ports), _ports, iph); + pptr =frag_safe_skb_hp (skb, iph->len,sizeof (_ports), _ports);if (pptr ==NULL )return NULL ;
@@ -566,7 +566,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,struct netns_ipvs *ipvs = svc->ipvs;struct net *net = ipvs->net; - pptr =frag_safe_skb_hp (skb, iph->len,sizeof (_ports), _ports, iph); + pptr =frag_safe_skb_hp (skb, iph->len,sizeof (_ports), _ports);if (!pptr)return NF_DROP ; dport =likely (!ip_vs_iph_inverse (iph)) ? pptr[1 ] : pptr[0 ];
@@ -982,7 +982,7 @@ static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,unsigned int offset; *related =1 ; - ic =frag_safe_skb_hp (skb, ipvsh->len,sizeof (_icmph), &_icmph, ipvsh); + ic =frag_safe_skb_hp (skb, ipvsh->len,sizeof (_icmph), &_icmph);if (ic ==NULL )return NF_DROP ;
@@ -1214,7 +1214,7 @@ static struct ip_vs_conn *__ip_vs_rs_conn_out(unsigned int hooknum,return NULL ; pptr =frag_safe_skb_hp (skb, iph->len, -sizeof (_ports), _ports, iph); +sizeof (_ports), _ports);if (!pptr)return NULL ;
@@ -1407,7 +1407,7 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in__be16 _ports[2 ], *pptr; pptr =frag_safe_skb_hp (skb, iph.len, -sizeof (_ports), _ports, &iph); +sizeof (_ports), _ports);if (pptr ==NULL )return NF_ACCEPT ;/* Not for me */ if (ip_vs_has_real_service(ipvs, af, iph.protocol, &iph.saddr,
@@ -1741,7 +1741,7 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, *related =1 ; - ic =frag_safe_skb_hp (skb, iph->len,sizeof (_icmph), &_icmph, iph); + ic =frag_safe_skb_hp (skb, iph->len,sizeof (_icmph), &_icmph);if (ic ==NULL )return NF_DROP ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 7/52 netfilter: ipset: use nfnl_mutex_is_locked
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Check that we really hold nfnl mutex here instead of relying on correct usage alone.
--- net/netfilter/ipset/ip_set_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/ipset/ip_set_core.c +1 -1
@@ -57,7 +57,7 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);/* When the nfnl mutex is held: */ #define ip_set_dereference (p) \ - rcu_dereference_protected(p, 1) + rcu_dereference_protected(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))#define ip_set (inst, id) \ ip_set_dereference((inst)->ip_set_list)[id]
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 8/52 netfilter: ipset: add resched points during set listing
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
When sets are extremely large we can get softlockup during ipset -L. We could fix this by adding cond_resched_rcu() at the right location during iteration, but this only works if RCU nesting depth is 1.
At this time entire variant->list() is called under under rcu_read_lock_bh. This used to be a read_lock_bh() but as rcu doesn't really lock anything, it does not appear to be needed, so remove it (ipset increments set reference count before this, so a set deletion should not be possible).
--- net/netfilter/ipset/ip_set_bitmap_gen.h | 1 + net/netfilter/ipset/ip_set_core.c | 2 -- net/netfilter/ipset/ip_set_hash_gen.h | 1 + 3 files changed, 2 insertions(+), 2 deletions(-)
net/netfilter/ipset/ip_set_bitmap_gen.h +1 -0
@@ -227,6 +227,7 @@ mtype_list(const struct ip_set *set,rcu_read_lock ();for (; cb->args[IPSET_CB_ARG0 ] < map->elements; cb->args[IPSET_CB_ARG0 ]++) { +cond_resched_rcu (); id = cb->args[IPSET_CB_ARG0 ]; x =get_ext (set, map, id); if (!test_bit(id, map->members) ||
net/netfilter/ipset/ip_set_core.c +0 -2
@@ -1388,9 +1388,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) set->variant->uref (set, cb, true);/* fall through */ default : -rcu_read_lock_bh (); ret = set->variant->list (set, skb, cb); -rcu_read_unlock_bh ();if (!cb->args[IPSET_CB_ARG0 ])/* Set is done, proceed with next one */ goto next_set;
net/netfilter/ipset/ip_set_hash_gen.h +1 -0
@@ -1143,6 +1143,7 @@ mtype_list(const struct ip_set *set,rcu_read_lock ();for (; cb->args[IPSET_CB_ARG0 ] <jhash_size (t->htable_bits); cb->args[IPSET_CB_ARG0 ]++) { +cond_resched_rcu (); incomplete =skb_tail_pointer (skb); n =rcu_dereference (hbucket (t, cb->args[IPSET_CB_ARG0 ])); pr_debug("cb->arg bucket: %lu, t %p n %p\n",
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 9/52 netfilter: nf_conntrack_h323: Remove unwanted comments.
In reply to Pablo Neira AyusoFrom: Varsha Rao <[email protected]>
Change old multi-line comment style to kernel comment style and remove unwanted comments.
--- net/netfilter/nf_conntrack_h323_asn1.c | 37 +++++++------------------- net/netfilter/nf_conntrack_h323_main.c | 47 +++------------------------------- 2 files changed, 13 insertions(+), 71 deletions(-)
net/netfilter/nf_conntrack_h323_asn1.c +9 -28
@@ -1,4 +1,4 @@ -/**************************************************************************** +/* * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323 * conntrack/NAT module. *
@@ -8,7 +8,7 @@* * See ip_conntrack_helper_h323_asn1.h for details. * -****************************************************************************/ +*/ #ifdef __KERNEL__#include <linux/kernel.h>
@@ -140,14 +140,15 @@ static const decoder_t Decoders[] = { decode_choice, }; -/**************************************************************************** +/* * H.323 Types -****************************************************************************/ +*/ #include "nf_conntrack_h323_types.c" -/**************************************************************************** +/* * Functions -****************************************************************************/ +*/ +/* Assume bs is aligned && v < 16384 */ static unsigned int get_len (struct bitstr *bs) {
@@ -177,7 +178,6 @@ static int nf_h323_error_boundary(struct bitstr *bs, size_t bytes, size_t bits)return 0 ; } -/****************************************************************************/ static unsigned int get_bit (struct bitstr *bs) {unsigned int b = (*bs->cur) & (0x80 >> bs->bit);
@@ -187,7 +187,6 @@ static unsigned int get_bit(struct bitstr *bs)return b; } -/****************************************************************************/ /* Assume b <= 8 */ static unsigned int get_bits (struct bitstr *bs,unsigned int b) {
@@ -213,7 +212,6 @@ static unsigned int get_bits(struct bitstr *bs, unsigned int b)return v; } -/****************************************************************************/ /* Assume b <= 32 */ static unsigned int get_bitmap (struct bitstr *bs,unsigned int b) {
@@ -251,9 +249,9 @@ static unsigned int get_bitmap(struct bitstr *bs, unsigned int b)return v; } -/**************************************************************************** +/* * Assume bs is aligned and sizeof(unsigned int) == 4 -****************************************************************************/ +*/ static unsigned int get_uint (struct bitstr *bs,int b) {unsigned int v =0 ;
@@ -278,7 +276,6 @@ static unsigned int get_uint(struct bitstr *bs, int b)return v; } -/****************************************************************************/ static int decode_nul (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -287,7 +284,6 @@ static int decode_nul(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_bool (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -299,7 +295,6 @@ static int decode_bool(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_oid (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -319,7 +314,6 @@ static int decode_oid(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_int (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -367,7 +361,6 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_enum (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -384,7 +377,6 @@ static int decode_enum(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_bitstr (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -421,7 +413,6 @@ static int decode_bitstr(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_numstr (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -442,7 +433,6 @@ static int decode_numstr(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_octstr (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -496,7 +486,6 @@ static int decode_octstr(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_bmpstr (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -526,7 +515,6 @@ static int decode_bmpstr(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_seq (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -656,7 +644,6 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ static int decode_seqof (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -753,8 +740,6 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } - -/****************************************************************************/ static int decode_choice (struct bitstr *bs,const struct field_t *f,char *base,int level) {
@@ -836,7 +821,6 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f,return H323_ERROR_NONE ; } -/****************************************************************************/ int DecodeRasMessage (unsigned char *buf,size_t sz,RasMessage *ras) {static const struct field_t ras_message = {
@@ -852,7 +836,6 @@ int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage *ras)return decode_choice (&bs, &ras_message, (char *) ras,0 ); } -/****************************************************************************/ static int DecodeH323_UserInformation (unsigned char *buf,unsigned char *beg,size_t sz,H323_UserInformation *uuie) {
@@ -870,7 +853,6 @@ static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg,return decode_seq (&bs, &h323_userinformation, (char *) uuie,0 ); } -/****************************************************************************/ int DecodeMultimediaSystemControlMessage (unsigned char *buf,size_t sz,MultimediaSystemControlMessage * mscm)
@@ -889,7 +871,6 @@ int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, (char *) mscm, 0); } -/****************************************************************************/ int DecodeQ931 (unsigned char *buf,size_t sz,Q931 *q931) {unsigned char *p = buf;
net/netfilter/nf_conntrack_h323_main.c +4 -43
305 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 10/52 netfilter: core: make nf_unregister_net_hooks simple wrapper again
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
This reverts commit d3ad2c17b4047
("netfilter: core: batch nf_unregister_net_hooks synchronize_net calls").
Nothing wrong with it. However, followup patch will delay freeing of hooks with call_rcu, so all synchronize_net() calls become obsolete and there is no need anymore for this batching.
This revert causes a temporary performance degradation when destroying network namespace, but its resolved with the upcoming call_rcu conversion.
--- net/netfilter/core.c | 59 +++------------------------------------------------- 1 file changed, 3 insertions(+), 56 deletions(-)
net/netfilter/core.c +3 -56
@@ -395,63 +395,10 @@ EXPORT_SYMBOL(nf_register_net_hooks);void nf_unregister_net_hooks (struct net *net,const struct nf_hook_ops *reg,unsigned int hookcount) { -struct nf_hook_entries *to_free[16 ], *p; -struct nf_hook_entries __rcu **pp; -unsigned int i, j, n; - -mutex_lock (&nf_hook_mutex); -for (i =0 ; i < hookcount; i++) { - pp =nf_hook_entry_head (net, ®[i]); -if (!pp) -continue ; - - p =nf_entry_dereference (*pp); -if (WARN_ON_ONCE (!p)) -continue ; -__nf_unregister_net_hook (p, ®[i]); - } -mutex_unlock (&nf_hook_mutex); - -do { - n = min_t(unsigned int, hookcount, ARRAY_SIZE(to_free)); - -mutex_lock (&nf_hook_mutex); - -for (i =0 , j =0 ; i < hookcount && j < n; i++) { - pp =nf_hook_entry_head (net, ®[i]); -if (!pp) -continue ; - - p =nf_entry_dereference (*pp); -if (!p) -continue ; - - to_free[j] =__nf_hook_entries_try_shrink (pp); -if (to_free[j]) - ++j; - } - -mutex_unlock (&nf_hook_mutex); - -if (j) { -unsigned int nfq; - -synchronize_net (); - -/* need 2nd synchronize_net() if nfqueue is used, skb -* can get reinjected right before nf_queue_hook_drop() -*/ - nfq =nf_queue_nf_hook_drop (net); -if (nfq) -synchronize_net (); - -for (i =0 ; i < j; i++) -kvfree (to_free[i]); - } +unsigned int i; - reg += n; - hookcount -= n; - }while (hookcount >0 ); +for (i =0 ; i < hookcount; i++) +nf_unregister_net_hook (net, ®[i]); }EXPORT_SYMBOL (nf_unregister_net_hooks);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 11/52 netfilter: core: remove synchronize_net call if nfqueue is used
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
since commit 960632ece6949b ("netfilter: convert hook list to an array") nfqueue no longer stores a pointer to the hook that caused the packet to be queued. Therefore no extra synchronize_net() call is needed after dropping the packets enqueued by the old rule blob.
--- include/net/netfilter/nf_queue.h | 2 +- net/netfilter/core.c | 6 +----- net/netfilter/nf_internals.h | 2 +- net/netfilter/nf_queue.c | 7 ++----- net/netfilter/nfnetlink_queue.c | 9 ++------- 5 files changed, 7 insertions(+), 19 deletions(-)
include/net/netfilter/nf_queue.h +1 -1
@@ -25,7 +25,7 @@ struct nf_queue_entry {struct nf_queue_handler {int (*outfn)(struct nf_queue_entry *entry,unsigned int queuenum); -unsigned int (*nf_hook_drop)(struct net *net); +void (*nf_hook_drop)(struct net *net); };void nf_register_queue_handler (struct net *net,const struct nf_queue_handler *qh);
net/netfilter/core.c +1 -5
@@ -341,7 +341,6 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) {struct nf_hook_entries __rcu **pp;struct nf_hook_entries *p; -unsigned int nfq; pp =nf_hook_entry_head (net, reg);if (!pp)
@@ -364,10 +363,7 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)synchronize_net (); -/* other cpu might still process nfqueue verdict that used reg */ - nfq =nf_queue_nf_hook_drop (net); -if (nfq) -synchronize_net (); +nf_queue_nf_hook_drop (net);kvfree (p); }EXPORT_SYMBOL (nf_unregister_net_hook);
net/netfilter/nf_internals.h +1 -1
@@ -10,7 +10,7 @@int nf_queue (struct sk_buff *skb,struct nf_hook_state *state,const struct nf_hook_entries *entries,unsigned int index,unsigned int verdict); -unsigned int nf_queue_nf_hook_drop (struct net *net); +void nf_queue_nf_hook_drop (struct net *net);/* nf_log.c */ int __init netfilter_log_init (void );
net/netfilter/nf_queue.c +2 -5
@@ -96,18 +96,15 @@ void nf_queue_entry_get_refs(struct nf_queue_entry *entry) }EXPORT_SYMBOL_GPL (nf_queue_entry_get_refs); -unsigned int nf_queue_nf_hook_drop (struct net *net) +void nf_queue_nf_hook_drop (struct net *net) {const struct nf_queue_handler *qh; -unsigned int count =0 ;rcu_read_lock (); qh =rcu_dereference (net->nf.queue_handler);if (qh) - count = qh->nf_hook_drop (net); + qh->nf_hook_drop (net);rcu_read_unlock (); - -return count; }EXPORT_SYMBOL_GPL (nf_queue_nf_hook_drop);
net/netfilter/nfnetlink_queue.c +2 -7
@@ -941,23 +941,18 @@ static struct notifier_block nfqnl_dev_notifier = { .notifier_call = nfqnl_rcv_dev_event, }; -static unsigned int nfqnl_nf_hook_drop (struct net *net) +static void nfqnl_nf_hook_drop (struct net *net) {struct nfnl_queue_net *q =nfnl_queue_pernet (net); -unsigned int instances =0 ;int i;for (i =0 ; i <INSTANCE_BUCKETS ; i++) {struct nfqnl_instance *inst;struct hlist_head *head = &q->instance_table[i]; -hlist_for_each_entry_rcu (inst, head, hlist) { +hlist_for_each_entry_rcu (inst, head, hlist)nfqnl_flush (inst,NULL ,0 ); - instances++; - } } - -return instances; } static int
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 12/52 netfilter: core: free hooks with call_rcu
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Giuseppe Scrivano says:
"SELinux, if enabled, registers for each new network namespace 6
netfilter hooks."
Cost for this is high. With synchronize_net() removed:
"The net benefit on an SMP machine with two cores is that creating a new network namespace takes -40% of the original time."
This patch replaces synchronize_net+kvfree with call_rcu(). We store rcu_head at the tail of a structure that has no fixed layout, i.e. we cannot use offsetof() to compute the start of the original allocation. Thus store this information right after the rcu head.
We could simplify this by just placing the rcu_head at the start of struct nf_hook_entries. However, this structure is used in packet processing hotpath, so only place what is needed for that at the beginning of the struct.
--- include/linux/netfilter.h | 19 +++++++++++++++---- net/netfilter/core.c | 34 ++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 10 deletions(-)
include/linux/netfilter.h +15 -4
@@ -77,17 +77,28 @@ struct nf_hook_entry {void *priv; }; +struct nf_hook_entries_rcu_head { +struct rcu_head head; +void *allocation; +}; +struct nf_hook_entries {u16 num_hook_entries;/* padding */ struct nf_hook_entry hooks[]; -/* trailer: pointers to original orig_ops of each hook. -* -* This is not part of struct nf_hook_entry since its only -* needed in slow path (hook register/unregister). +/* trailer: pointers to original orig_ops of each hook, +* followed by rcu_head and scratch space used for freeing +* the structure via call_rcu. * +* This is not part of struct nf_hook_entry since its only +* needed in slow path (hook register/unregister): * const struct nf_hook_ops *orig_ops[] +* +* For the same reason, we store this at end -- its +* only needed when a hook is deleted, not during +* packet path processing: +* struct nf_hook_entries_rcu_head head */ };
net/netfilter/core.c +28 -6
@@ -74,7 +74,8 @@ static struct nf_hook_entries *allocate_hook_entries_size(u16 num)struct nf_hook_entries *e;size_t alloc =sizeof (*e) +sizeof (struct nf_hook_entry ) * num + -sizeof (struct nf_hook_ops *) * num; +sizeof (struct nf_hook_ops *) * num + +sizeof (struct nf_hook_entries_rcu_head );if (num ==0 )return NULL ;
@@ -85,6 +86,30 @@ static struct nf_hook_entries *allocate_hook_entries_size(u16 num)return e; } +static void __nf_hook_entries_free (struct rcu_head *h) +{ +struct nf_hook_entries_rcu_head *head; + + head = container_of(h, struct nf_hook_entries_rcu_head, head); +kvfree (head->allocation); +} + +static void nf_hook_entries_free (struct nf_hook_entries *e) +{ +struct nf_hook_entries_rcu_head *head; +struct nf_hook_ops **ops; +unsigned int num; + +if (!e) +return ; + + num = e->num_hook_entries; + ops =nf_hook_entries_get_hook_ops (e); + head = (void *)&ops[num]; + head->allocation = e; +call_rcu (&head->head, __nf_hook_entries_free); +} +static unsigned int accept_all (void *priv,struct sk_buff *skb,const struct nf_hook_state *state)
@@ -291,9 +316,8 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)#ifdef HAVE_JUMP_LABEL static_key_slow_inc (&nf_hooks_needed[reg->pf][reg->hooknum]);#endif -synchronize_net ();BUG_ON (p == new_hooks); -kvfree (p); +nf_hook_entries_free (p);return 0 ; }EXPORT_SYMBOL (nf_register_net_hook);
@@ -361,10 +385,8 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)if (!p)return ; -synchronize_net (); -nf_queue_nf_hook_drop (net); -kvfree (p); +nf_hook_entries_free (p); }EXPORT_SYMBOL (nf_unregister_net_hook);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 13/52 netfilter: reduce size of hook entry point locations
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
struct net contains:
struct nf_hook_entries __rcu *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
which store the hook entry point locations for the various protocol families and the hooks.
Using array results in compact c code when doing accesses, i.e.
x = rcu_dereference(net->nf.hooks[pf][hook]);
but its also wasting a lot of memory, as most families are not used.
So split the array into those families that are used, which are only 5 (instead of 13). In most cases, the 'pf' argument is constant, i.e. gcc removes switch statement.
struct net before:
/* size: 5184, cachelines: 81, members: 46 */
after:
/* size: 4672, cachelines: 73, members: 46 */
--- include/linux/netfilter.h | 24 ++++++++++++++++++++++-- include/net/netns/netfilter.h | 6 +++++- net/bridge/br_netfilter_hooks.c | 2 +- net/netfilter/core.c | 38 ++++++++++++++++++++++++++++++-------- net/netfilter/nf_queue.c | 21 +++++++++++++++++++-- 5 files changed, 77 insertions(+), 14 deletions(-)
include/linux/netfilter.h +22 -2
@@ -195,7 +195,7 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net, struct net_device *indev, struct net_device *outdev, int (*okfn)(struct net *, struct sock *, struct sk_buff *)) { - struct nf_hook_entries *hook_head; + struct nf_hook_entries *hook_head = NULL;int ret =1 ;#ifdef HAVE_JUMP_LABEL
@@ -206,7 +206,27 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,#endif rcu_read_lock (); - hook_head =rcu_dereference (net->nf.hooks[pf][hook]); +switch (pf) { +case NFPROTO_IPV4 : + hook_head =rcu_dereference (net->nf.hooks_ipv4[hook]); +break ; +case NFPROTO_IPV6 : + hook_head =rcu_dereference (net->nf.hooks_ipv6[hook]); +break ; +case NFPROTO_ARP : + hook_head =rcu_dereference (net->nf.hooks_arp[hook]); +break ; +case NFPROTO_BRIDGE : + hook_head =rcu_dereference (net->nf.hooks_bridge[hook]); +break ; +case NFPROTO_DECNET : + hook_head =rcu_dereference (net->nf.hooks_decnet[hook]); +break ; +default : +WARN_ON_ONCE (1 ); +break ; + } +if (hook_head) {struct nf_hook_state state;
include/net/netns/netfilter.h +5 -1
@@ -17,7 +17,11 @@ struct netns_nf {#ifdef CONFIG_SYSCTL struct ctl_table_header *nf_log_dir_header;#endif -struct nf_hook_entries __rcu *hooks[NFPROTO_NUMPROTO ][NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv4[NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv6[NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_arp[NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_bridge[NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_decnet[NF_MAX_HOOKS ];#if IS_ENABLED (CONFIG_NF_DEFRAG_IPV4 )bool defrag_ipv4;#endif
net/bridge/br_netfilter_hooks.c +1 -1
@@ -991,7 +991,7 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,unsigned int i;int ret; - e =rcu_dereference (net->nf.hooks[NFPROTO_BRIDGE ][hook]); + e =rcu_dereference (net->nf.hooks_bridge[hook]);if (!e)return okfn (net, sk, skb);
net/netfilter/core.c +30 -8
@@ -264,8 +264,23 @@ static void *__nf_hook_entries_try_shrink(struct nf_hook_entries __rcu **pp)static struct nf_hook_entries __rcu **nf_hook_entry_head (struct net *net,const struct nf_hook_ops *reg) { -if (reg->pf !=NFPROTO_NETDEV ) -return net->nf.hooks[reg->pf]+reg->hooknum; +switch (reg->pf) { +case NFPROTO_NETDEV : +break ; +case NFPROTO_ARP : +return net->nf.hooks_arp + reg->hooknum; +case NFPROTO_BRIDGE : +return net->nf.hooks_bridge + reg->hooknum; +case NFPROTO_IPV4 : +return net->nf.hooks_ipv4 + reg->hooknum; +case NFPROTO_IPV6 : +return net->nf.hooks_ipv6 + reg->hooknum; +case NFPROTO_DECNET : +return net->nf.hooks_decnet + reg->hooknum; +default : +WARN_ON_ONCE (1 ); +return NULL ; + }#ifdef CONFIG_NETFILTER_INGRESS if (reg->hooknum ==NF_NETDEV_INGRESS ) {
@@ -534,14 +549,21 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);EXPORT_SYMBOL (nf_nat_decode_session_hook);#endif -static int __net_init netfilter_net_init (struct net *net) +static void __net_init __netfilter_net_init (struct nf_hook_entries *e[NF_MAX_HOOKS ]) { -int i, h; +int h; -for (i =0 ; i <ARRAY_SIZE (net->nf.hooks); i++) { -for (h =0 ; h <NF_MAX_HOOKS ; h++) -RCU_INIT_POINTER (net->nf.hooks[i][h],NULL ); - } +for (h =0 ; h <NF_MAX_HOOKS ; h++) +RCU_INIT_POINTER (e[h],NULL ); +} + +static int __net_init netfilter_net_init (struct net *net) +{ +__netfilter_net_init (net->nf.hooks_ipv4); +__netfilter_net_init (net->nf.hooks_ipv6); +__netfilter_net_init (net->nf.hooks_arp); +__netfilter_net_init (net->nf.hooks_bridge); +__netfilter_net_init (net->nf.hooks_decnet);#ifdef CONFIG_PROC_FS net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
net/netfilter/nf_queue.c +19 -2
@@ -201,6 +201,23 @@ static unsigned int nf_iterate(struct sk_buff *skb,return NF_ACCEPT ; } +static struct nf_hook_entries *nf_hook_entries_head (const struct net *net,u8 pf,u8 hooknum) +{ +switch (pf) { +case NFPROTO_BRIDGE : +return rcu_dereference (net->nf.hooks_bridge[hooknum]); +case NFPROTO_IPV4 : +return rcu_dereference (net->nf.hooks_ipv4[hooknum]); +case NFPROTO_IPV6 : +return rcu_dereference (net->nf.hooks_ipv6[hooknum]); +default : +WARN_ON_ONCE (1 ); +return NULL ; + } + +return NULL ; +} +/* Caller must hold rcu read-side lock */ void nf_reinject (struct nf_queue_entry *entry,unsigned int verdict) {
@@ -216,12 +233,12 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) net = entry->state.net; pf = entry->state.pf; - hooks =rcu_dereference (net->nf.hooks[pf][entry->state.hook]); + hooks =nf_hook_entries_head (net, pf, entry->state.hook);nf_queue_entry_release_refs (entry); i = entry->hook_index; -if (WARN_ON_ONCE (i >= hooks->num_hook_entries)) { +if (WARN_ON_ONCE (!hooks || i >= hooks->num_hook_entries)) {kfree_skb (skb);kfree (entry);return ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 14/52 netfilter: add defines for arp/decnet max hooks
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
The kernel already has defines for this, but they are in uapi exposed headers.
Including these from netns.h causes build errors and also adds unneeded dependencies on heads that we don't need.
So move these defines to netfilter_defs.h and place the uapi ones in ifndef __KERNEL__ to keep them for userspace.
--- include/linux/netfilter_defs.h | 6 ++++++ include/uapi/linux/netfilter_arp.h | 3 +++ include/uapi/linux/netfilter_decnet.h | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-)
include/linux/netfilter_defs.h +6 -0
@@ -7,4 +7,10 @@/* Largest hook number + 1, see uapi/linux/netfilter_decnet.h */ #define NF_MAX_HOOKS 8 +/* in/out/forward only */ +#define NF_ARP_NUMHOOKS 3 + +/* max hook is NF_DN_ROUTE (6), also see uapi/linux/netfilter_decnet.h */ +#define NF_DN_NUMHOOKS 7 +#endif
include/uapi/linux/netfilter_arp.h +3 -0
@@ -15,6 +15,9 @@#define NF_ARP_IN 0#define NF_ARP_OUT 1#define NF_ARP_FORWARD 2 + +#ifndef __KERNEL__#define NF_ARP_NUMHOOKS 3 +#endif #endif /* __LINUX_ARP_NETFILTER_H */
include/uapi/linux/netfilter_decnet.h +3 -1
@@ -24,6 +24,9 @@#define NFC_DN_IF_IN 0x0004/* Output device. */ #define NFC_DN_IF_OUT 0x0008 + +/* kernel define is in netfilter_defs.h */ +#define NF_DN_NUMHOOKS 7#endif /* ! __KERNEL__ */ /* DECnet Hooks */
@@ -41,7 +44,6 @@#define NF_DN_HELLO 5/* Input Routing Packets */ #define NF_DN_ROUTE 6 -#define NF_DN_NUMHOOKS 7enum nf_dn_hook_priorities {NF_DN_PRI_FIRST =INT_MIN ,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 15/52 netfilter: reduce hook array sizes to what is needed
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Not all families share the same hook count, adjust sizes to what is needed.
struct net before:
/* size: 6592, cachelines: 103, members: 46 */
after:
/* size: 5952, cachelines: 93, members: 46 */
--- include/net/netns/netfilter.h | 10 +++++----- net/netfilter/core.c | 24 +++++++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-)
include/net/netns/netfilter.h +5 -5
@@ -17,11 +17,11 @@ struct netns_nf {#ifdef CONFIG_SYSCTL struct ctl_table_header *nf_log_dir_header;#endif -struct nf_hook_entries __rcu *hooks_ipv4[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_ipv6[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_arp[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_bridge[NF_MAX_HOOKS ]; -struct nf_hook_entries __rcu *hooks_decnet[NF_MAX_HOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS ]; +struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS ]; +struct nf_hook_entries __rcu *hooks_arp[NF_ARP_NUMHOOKS ]; +struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS ]; +struct nf_hook_entries __rcu *hooks_decnet[NF_DN_NUMHOOKS ];#if IS_ENABLED (CONFIG_NF_DEFRAG_IPV4 )bool defrag_ipv4;#endif
net/netfilter/core.c +17 -7
@@ -268,14 +268,24 @@ static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, constcase NFPROTO_NETDEV :break ;case NFPROTO_ARP : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_arp) <= reg->hooknum)) +return NULL ;return net->nf.hooks_arp + reg->hooknum;case NFPROTO_BRIDGE : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_bridge) <= reg->hooknum)) +return NULL ;return net->nf.hooks_bridge + reg->hooknum;case NFPROTO_IPV4 : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv4) <= reg->hooknum)) +return NULL ;return net->nf.hooks_ipv4 + reg->hooknum;case NFPROTO_IPV6 : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv6) <= reg->hooknum)) +return NULL ;return net->nf.hooks_ipv6 + reg->hooknum;case NFPROTO_DECNET : +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_decnet) <= reg->hooknum)) +return NULL ;return net->nf.hooks_decnet + reg->hooknum;default :WARN_ON_ONCE (1 );
@@ -549,21 +559,21 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);EXPORT_SYMBOL (nf_nat_decode_session_hook);#endif -static void __net_init __netfilter_net_init (struct nf_hook_entries *e[NF_MAX_HOOKS ]) +static void __net_init __netfilter_net_init (struct nf_hook_entries **e,int max) {int h; -for (h =0 ; h <NF_MAX_HOOKS ; h++) +for (h =0 ; h < max; h++)RCU_INIT_POINTER (e[h],NULL ); }static int __net_init netfilter_net_init (struct net *net) { -__netfilter_net_init (net->nf.hooks_ipv4); -__netfilter_net_init (net->nf.hooks_ipv6); -__netfilter_net_init (net->nf.hooks_arp); -__netfilter_net_init (net->nf.hooks_bridge); -__netfilter_net_init (net->nf.hooks_decnet); +__netfilter_net_init (net->nf.hooks_ipv4,ARRAY_SIZE (net->nf.hooks_ipv4)); +__netfilter_net_init (net->nf.hooks_ipv6,ARRAY_SIZE (net->nf.hooks_ipv6)); +__netfilter_net_init (net->nf.hooks_arp,ARRAY_SIZE (net->nf.hooks_arp)); +__netfilter_net_init (net->nf.hooks_bridge,ARRAY_SIZE (net->nf.hooks_bridge)); +__netfilter_net_init (net->nf.hooks_decnet,ARRAY_SIZE (net->nf.hooks_decnet));#ifdef CONFIG_PROC_FS net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 16/52 netfilter: don't allocate space for decnet hooks unless needed
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
no need to define hook points if the family isn't supported.
--- include/linux/netfilter.h | 2 ++ include/net/netns/netfilter.h | 2 ++ net/netfilter/core.c | 4 ++++ 3 files changed, 8 insertions(+)
include/linux/netfilter.h +2 -0
@@ -219,9 +219,11 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,case NFPROTO_BRIDGE : hook_head =rcu_dereference (net->nf.hooks_bridge[hook]);break ; +#if IS_ENABLED (CONFIG_DECNET )case NFPROTO_DECNET : hook_head =rcu_dereference (net->nf.hooks_decnet[hook]);break ; +#endif default :WARN_ON_ONCE (1 );break ;
include/net/netns/netfilter.h +2 -0
@@ -21,7 +21,9 @@ struct netns_nf {struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS ];struct nf_hook_entries __rcu *hooks_arp[NF_ARP_NUMHOOKS ];struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS ]; +#if IS_ENABLED (CONFIG_DECNET )struct nf_hook_entries __rcu *hooks_decnet[NF_DN_NUMHOOKS ]; +#endif #if IS_ENABLED (CONFIG_NF_DEFRAG_IPV4 )bool defrag_ipv4;#endif
net/netfilter/core.c +4 -0
@@ -283,10 +283,12 @@ static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, constif (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv6) <= reg->hooknum))return NULL ;return net->nf.hooks_ipv6 + reg->hooknum; +#if IS_ENABLED (CONFIG_DECNET )case NFPROTO_DECNET :if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_decnet) <= reg->hooknum))return NULL ;return net->nf.hooks_decnet + reg->hooknum; +#endif default :WARN_ON_ONCE (1 );return NULL ;
@@ -573,7 +575,9 @@ static int __net_init netfilter_net_init(struct net *net)__netfilter_net_init (net->nf.hooks_ipv6,ARRAY_SIZE (net->nf.hooks_ipv6));__netfilter_net_init (net->nf.hooks_arp,ARRAY_SIZE (net->nf.hooks_arp));__netfilter_net_init (net->nf.hooks_bridge,ARRAY_SIZE (net->nf.hooks_bridge)); +#if IS_ENABLED (CONFIG_DECNET )__netfilter_net_init (net->nf.hooks_decnet,ARRAY_SIZE (net->nf.hooks_decnet)); +#endif #ifdef CONFIG_PROC_FS net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 17/52 netfilter: don't allocate space for arp/bridge hooks unless needed
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
no need to define hook points if the family isn't supported. Because we need these hooks for either nftables, arp/ebtables or the 'call-iptables' hack we have in the bridge layer add two new dependencies, NETFILTER_FAMILY_{ARP,BRIDGE}, and have the users select them.
--- include/linux/netfilter.h | 4 ++++ include/net/netns/netfilter.h | 4 ++++ net/Kconfig | 1 + net/bridge/netfilter/Kconfig | 2 ++ net/ipv4/netfilter/Kconfig | 2 ++ net/netfilter/Kconfig | 6 ++++++ net/netfilter/core.c | 8 ++++++++ net/netfilter/nf_queue.c | 2 ++ 8 files changed, 29 insertions(+)
include/linux/netfilter.h +4 -0
@@ -214,10 +214,14 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net, hook_head =rcu_dereference (net->nf.hooks_ipv6[hook]);break ;case NFPROTO_ARP : +#ifdef CONFIG_NETFILTER_FAMILY_ARP hook_head =rcu_dereference (net->nf.hooks_arp[hook]); +#endif break ;case NFPROTO_BRIDGE : +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE hook_head =rcu_dereference (net->nf.hooks_bridge[hook]); +#endif break ;#if IS_ENABLED (CONFIG_DECNET )case NFPROTO_DECNET :
include/net/netns/netfilter.h +4 -0
@@ -19,8 +19,12 @@ struct netns_nf {#endif struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS ];struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS ]; +#ifdef CONFIG_NETFILTER_FAMILY_ARP struct nf_hook_entries __rcu *hooks_arp[NF_ARP_NUMHOOKS ]; +#endif +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS ]; +#endif #if IS_ENABLED (CONFIG_DECNET )struct nf_hook_entries __rcu *hooks_decnet[NF_DN_NUMHOOKS ];#endif
net/Kconfig +1 -0
@@ -182,6 +182,7 @@ config BRIDGE_NETFILTER depends on BRIDGE depends on NETFILTER && INET depends on NETFILTER_ADVANCED + select NETFILTER_FAMILY_BRIDGE default m ---help--- Enabling this option will let arptables resp. iptables see bridged
net/bridge/netfilter/Kconfig +2 -0
@@ -4,6 +4,7 @@ # menuconfig NF_TABLES_BRIDGE depends on BRIDGE && NETFILTER && NF_TABLES + select NETFILTER_FAMILY_BRIDGE tristate "Ethernet Bridge nf_tables support" if NF_TABLES_BRIDGE
@@ -29,6 +30,7 @@ endif # NF_TABLES_BRIDGE menuconfig BRIDGE_NF_EBTABLES tristate "Ethernet Bridge tables (ebtables) support" depends on BRIDGE && NETFILTER && NETFILTER_XTABLES + select NETFILTER_FAMILY_BRIDGE help ebtables is a general, extensible frame/packet identification framework. Say 'Y' or 'M' here if you want to do Ethernet
net/ipv4/netfilter/Kconfig +2 -0
@@ -72,6 +72,7 @@ endif # NF_TABLES_IPV4 config NF_TABLES_ARP tristate "ARP nf_tables support" + select NETFILTER_FAMILY_ARP help This option enables the ARP support for nf_tables.
@@ -392,6 +393,7 @@ endif # IP_NF_IPTABLES config IP_NF_ARPTABLES tristate "ARP tables support" select NETFILTER_XTABLES + select NETFILTER_FAMILY_ARP depends on NETFILTER_ADVANCED help arptables is a general, extensible packet identification framework.
net/netfilter/Kconfig +6 -0
@@ -12,6 +12,12 @@ config NETFILTER_INGRESS config NETFILTER_NETLINK tristate +config NETFILTER_FAMILY_BRIDGE + bool + +config NETFILTER_FAMILY_ARP + bool + config NETFILTER_NETLINK_ACCT tristate "Netfilter NFACCT over NFNETLINK interface" depends on NETFILTER_ADVANCED
net/netfilter/core.c +8 -0
@@ -267,14 +267,18 @@ static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, constswitch (reg->pf) {case NFPROTO_NETDEV :break ; +#ifdef CONFIG_NETFILTER_FAMILY_ARP case NFPROTO_ARP :if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_arp) <= reg->hooknum))return NULL ;return net->nf.hooks_arp + reg->hooknum; +#endif +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE case NFPROTO_BRIDGE :if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_bridge) <= reg->hooknum))return NULL ;return net->nf.hooks_bridge + reg->hooknum; +#endif case NFPROTO_IPV4 :if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv4) <= reg->hooknum))return NULL ;
@@ -573,8 +577,12 @@ static int __net_init netfilter_net_init(struct net *net) {__netfilter_net_init (net->nf.hooks_ipv4,ARRAY_SIZE (net->nf.hooks_ipv4));__netfilter_net_init (net->nf.hooks_ipv6,ARRAY_SIZE (net->nf.hooks_ipv6)); +#ifdef CONFIG_NETFILTER_FAMILY_ARP __netfilter_net_init (net->nf.hooks_arp,ARRAY_SIZE (net->nf.hooks_arp)); +#endif +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE __netfilter_net_init (net->nf.hooks_bridge,ARRAY_SIZE (net->nf.hooks_bridge)); +#endif #if IS_ENABLED (CONFIG_DECNET )__netfilter_net_init (net->nf.hooks_decnet,ARRAY_SIZE (net->nf.hooks_decnet));#endif
net/netfilter/nf_queue.c +2 -0
@@ -204,8 +204,10 @@ static unsigned int nf_iterate(struct sk_buff *skb,static struct nf_hook_entries *nf_hook_entries_head (const struct net *net,u8 pf,u8 hooknum) {switch (pf) { +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE case NFPROTO_BRIDGE :return rcu_dereference (net->nf.hooks_bridge[hooknum]); +#endif case NFPROTO_IPV4 :return rcu_dereference (net->nf.hooks_ipv4[hooknum]);case NFPROTO_IPV6 :
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 18/52 netfilter: reduce NF_MAX_HOOKS define
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
This can be same as NF_INET_NUMHOOKS if we don't support DECNET.
--- include/linux/netfilter_defs.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
include/linux/netfilter_defs.h +7 -3
@@ -4,13 +4,17 @@#include <uapi/linux/netfilter.h> -/* Largest hook number + 1, see uapi/linux/netfilter_decnet.h */ -#define NF_MAX_HOOKS 8 -/* in/out/forward only */ #define NF_ARP_NUMHOOKS 3/* max hook is NF_DN_ROUTE (6), also see uapi/linux/netfilter_decnet.h */ #define NF_DN_NUMHOOKS 7 +#if IS_ENABLED (CONFIG_DECNET ) +/* Largest hook number + 1, see uapi/linux/netfilter_decnet.h */ +#define NF_MAX_HOOKS NF_DN_NUMHOOKS +#else +#define NF_MAX_HOOKS NF_INET_NUMHOOKS +#endif +#endif
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 19/52 netfilter: xtables: add and use xt_request_find_table_lock
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
currently we always return -ENOENT to userspace if we can't find a particular table, or if the table initialization fails.
Followup patch will make nat table init fail in case nftables already registered a nat hook so this change makes xt_find_table_lock return an ERR_PTR to return the errno value reported from the table init function.
Add xt_request_find_table_lock as try_then_request_module replacement and use it where needed.
--- include/linux/netfilter/x_tables.h | 2 ++ net/ipv4/netfilter/arp_tables.c | 26 ++++++++++++-------------- net/ipv4/netfilter/ip_tables.c | 26 ++++++++++++-------------- net/ipv6/netfilter/ip6_tables.c | 26 ++++++++++++-------------- net/netfilter/x_tables.c | 36 +++++++++++++++++++++++++++--------- 5 files changed, 65 insertions(+), 51 deletions(-)
include/linux/netfilter/x_tables.h +2 -0
@@ -320,6 +320,8 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,struct xt_table *xt_find_table_lock (struct net *net,u_int8_t af,const char *name); +struct xt_table *xt_request_find_table_lock (struct net *net,u_int8_t af, +const char *name);void xt_table_unlock (struct xt_table *t);int xt_proto_init (struct net *net,u_int8_t af);
net/ipv4/netfilter/arp_tables.c +12 -14
@@ -810,9 +810,8 @@ static int get_info(struct net *net, void __user *user,if (compat)xt_compat_lock (NFPROTO_ARP );#endif - t =try_then_request_module (xt_find_table_lock (net,NFPROTO_ARP , name), -"arptable_%s" , name); -if (t) { + t =xt_request_find_table_lock (net,NFPROTO_ARP , name); +if (!IS_ERR (t)) {struct arpt_getinfo info;const struct xt_table_info *private = t->private;#ifdef CONFIG_COMPAT
@@ -841,7 +840,7 @@ static int get_info(struct net *net, void __user *user,xt_table_unlock (t);module_put (t->me); }else - ret = -ENOENT ; + ret =PTR_ERR (t);#ifdef CONFIG_COMPAT if (compat)xt_compat_unlock (NFPROTO_ARP );
@@ -866,7 +865,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr, get.name[sizeof (get.name) -1 ] ='\0' ; t =xt_find_table_lock (net,NFPROTO_ARP , get.name); -if (t) { +if (!IS_ERR (t)) {const struct xt_table_info *private = t->private;if (get.size == private->size)
@@ -878,7 +877,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,module_put (t->me);xt_table_unlock (t); }else - ret = -ENOENT ; + ret =PTR_ERR (t);return ret; }
@@ -903,10 +902,9 @@ static int __do_replace(struct net *net, const char *name, goto out; } - t =try_then_request_module (xt_find_table_lock (net,NFPROTO_ARP , name), -"arptable_%s" , name); -if (!t) { - ret = -ENOENT ; + t =xt_request_find_table_lock (net,NFPROTO_ARP , name); +if (IS_ERR (t)) { + ret =PTR_ERR (t); goto free_newinfo_counters_untrans; }
@@ -1020,8 +1018,8 @@ static int do_add_counters(struct net *net, const void __user *user,return PTR_ERR (paddc); t =xt_find_table_lock (net,NFPROTO_ARP , tmp.name); -if (!t) { - ret = -ENOENT ; +if (IS_ERR (t)) { + ret =PTR_ERR (t); goto free; }
@@ -1408,7 +1406,7 @@ static int compat_get_entries(struct net *net,xt_compat_lock (NFPROTO_ARP ); t =xt_find_table_lock (net,NFPROTO_ARP , get.name); -if (t) { +if (!IS_ERR (t)) {const struct xt_table_info *private = t->private;struct xt_table_info info;
@@ -1423,7 +1421,7 @@ static int compat_get_entries(struct net *net,module_put (t->me);xt_table_unlock (t); }else - ret = -ENOENT ; + ret =PTR_ERR (t);xt_compat_unlock (NFPROTO_ARP );return ret;
net/ipv4/netfilter/ip_tables.c +12 -14
@@ -973,9 +973,8 @@ static int get_info(struct net *net, void __user *user,if (compat)xt_compat_lock (AF_INET );#endif - t =try_then_request_module (xt_find_table_lock (net,AF_INET , name), -"iptable_%s" , name); -if (t) { + t =xt_request_find_table_lock (net,AF_INET , name); +if (!IS_ERR (t)) {struct ipt_getinfo info;const struct xt_table_info *private = t->private;#ifdef CONFIG_COMPAT
@@ -1005,7 +1004,7 @@ static int get_info(struct net *net, void __user *user,xt_table_unlock (t);module_put (t->me); }else - ret = -ENOENT ; + ret =PTR_ERR (t);#ifdef CONFIG_COMPAT if (compat)xt_compat_unlock (AF_INET );
@@ -1030,7 +1029,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, get.name[sizeof (get.name) -1 ] ='\0' ; t =xt_find_table_lock (net,AF_INET , get.name); -if (t) { +if (!IS_ERR (t)) {const struct xt_table_info *private = t->private;if (get.size == private->size) ret = copy_entries_to_user(private->size,
@@ -1041,7 +1040,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr,module_put (t->me);xt_table_unlock (t); }else - ret = -ENOENT ; + ret =PTR_ERR (t);return ret; }
@@ -1064,10 +1063,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, goto out; } - t =try_then_request_module (xt_find_table_lock (net,AF_INET , name), -"iptable_%s" , name); -if (!t) { - ret = -ENOENT ; + t =xt_request_find_table_lock (net,AF_INET , name); +if (IS_ERR (t)) { + ret =PTR_ERR (t); goto free_newinfo_counters_untrans; }
@@ -1181,8 +1179,8 @@ do_add_counters(struct net *net, const void __user *user,return PTR_ERR (paddc); t =xt_find_table_lock (net,AF_INET , tmp.name); -if (!t) { - ret = -ENOENT ; +if (IS_ERR (t)) { + ret =PTR_ERR (t); goto free; }
@@ -1625,7 +1623,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,xt_compat_lock (AF_INET ); t =xt_find_table_lock (net,AF_INET , get.name); -if (t) { +if (!IS_ERR (t)) {const struct xt_table_info *private = t->private;struct xt_table_info info; ret =compat_table_info (private, &info);
@@ -1639,7 +1637,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,module_put (t->me);xt_table_unlock (t); }else - ret = -ENOENT ; + ret =PTR_ERR (t);xt_compat_unlock (AF_INET );return ret;
net/ipv6/netfilter/ip6_tables.c +12 -14
@@ -991,9 +991,8 @@ static int get_info(struct net *net, void __user *user,if (compat)xt_compat_lock (AF_INET6 );#endif - t =try_then_request_module (xt_find_table_lock (net,AF_INET6 , name), -"ip6table_%s" , name); -if (t) { + t =xt_request_find_table_lock (net,AF_INET6 , name); +if (!IS_ERR (t)) {struct ip6t_getinfo info;const struct xt_table_info *private = t->private;#ifdef CONFIG_COMPAT
@@ -1023,7 +1022,7 @@ static int get_info(struct net *net, void __user *user,xt_table_unlock (t);module_put (t->me); }else - ret = -ENOENT ; + ret =PTR_ERR (t);#ifdef CONFIG_COMPAT if (compat)xt_compat_unlock (AF_INET6 );
@@ -1049,7 +1048,7 @@ get_entries(struct net *net, struct ip6t_get_entries __user *uptr, get.name[sizeof (get.name) -1 ] ='\0' ; t =xt_find_table_lock (net,AF_INET6 , get.name); -if (t) { +if (!IS_ERR (t)) {struct xt_table_info *private = t->private;if (get.size == private->size) ret = copy_entries_to_user(private->size,
@@ -1060,7 +1059,7 @@ get_entries(struct net *net, struct ip6t_get_entries __user *uptr,module_put (t->me);xt_table_unlock (t); }else - ret = -ENOENT ; + ret =PTR_ERR (t);return ret; }
@@ -1083,10 +1082,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, goto out; } - t =try_then_request_module (xt_find_table_lock (net,AF_INET6 , name), -"ip6table_%s" , name); -if (!t) { - ret = -ENOENT ; + t =xt_request_find_table_lock (net,AF_INET6 , name); +if (IS_ERR (t)) { + ret =PTR_ERR (t); goto free_newinfo_counters_untrans; }
@@ -1199,8 +1197,8 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,if (IS_ERR (paddc))return PTR_ERR (paddc); t =xt_find_table_lock (net,AF_INET6 , tmp.name); -if (!t) { - ret = -ENOENT ; +if (IS_ERR (t)) { + ret =PTR_ERR (t); goto free; }
@@ -1636,7 +1634,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,xt_compat_lock (AF_INET6 ); t =xt_find_table_lock (net,AF_INET6 , get.name); -if (t) { +if (!IS_ERR (t)) {const struct xt_table_info *private = t->private;struct xt_table_info info; ret =compat_table_info (private, &info);
@@ -1650,7 +1648,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,module_put (t->me);xt_table_unlock (t); }else - ret = -ENOENT ; + ret =PTR_ERR (t);xt_compat_unlock (AF_INET6 );return ret;
net/netfilter/x_tables.c +27 -9
@@ -1027,7 +1027,7 @@ void xt_free_table_info(struct xt_table_info *info) }EXPORT_SYMBOL (xt_free_table_info); -/* Find table by name, grabs mutex & ref. Returns NULL on error. */ +/* Find table by name, grabs mutex & ref. Returns ERR_PTR on error. */ struct xt_table *xt_find_table_lock (struct net *net,u_int8_t af,const char *name) {
@@ -1043,17 +1043,17 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,/* Table doesn't exist in this netns, re-try init */ list_for_each_entry (t, &init_net.xt.tables[af], list) { +int err; +if (strcmp (t->name, name))continue ; -if (!try_module_get (t->me)) { -mutex_unlock (&xt[af].mutex); -return NULL ; - } - +if (!try_module_get (t->me)) + goto out;mutex_unlock (&xt[af].mutex); -if (t->table_init (net) !=0 ) { + err = t->table_init (net); +if (err <0 ) {module_put (t->me); -return NULL ; +return ERR_PTR (err); } found = t;
@@ -1073,10 +1073,28 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,module_put (found->me); out:mutex_unlock (&xt[af].mutex); -return NULL ; +return ERR_PTR (-ENOENT ); }EXPORT_SYMBOL_GPL (xt_find_table_lock); +struct xt_table *xt_request_find_table_lock (struct net *net,u_int8_t af, +const char *name) +{ +struct xt_table *t =xt_find_table_lock (net, af, name); + +#ifdef CONFIG_MODULE +if (IS_ERR (t)) { +int err =request_module ("%stable_%s" , xt_prefix[af], name); +if (err) +return ERR_PTR (err); + t =xt_find_table_lock (net, af, name); + } +#endif + +return t; +} +EXPORT_SYMBOL_GPL (xt_request_find_table_lock); +void xt_table_unlock (struct xt_table *table) {mutex_unlock (&xt[table->af].mutex);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 20/52 netfilter: core: only allow one nat hook per hook point
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
The netfilter NAT core cannot deal with more than one NAT hook per hook location (prerouting, input ...), because the NAT hooks install a NAT null binding in case the iptables nat table (iptable_nat hooks) or the corresponding nftables chain (nft nat hooks) doesn't specify a nat transformation.
Null bindings are needed to detect port collsisions between NAT-ed and non-NAT-ed connections.
This causes nftables NAT rules to not work when iptable_nat module is loaded, and vice versa because nat binding has already been attached when the second nat hook is consulted.
The netfilter core is not really the correct location to handle this (hooks are just hooks, the core has no notion of what kinds of side
effects a hook implements), but its the only place where we can check
for conflicts between both iptables hooks and nftables hooks without adding dependencies.
So add nat annotation to hook_ops to describe those hooks that will add NAT bindings and then make core reject if such a hook already exists. The annotation fills a padding hole, in case further restrictions appar we might change this to a 'u8 type' instead of bool.
iptables error if nft nat hook active:
iptables -t nat -A POSTROUTING -j MASQUERADE
iptables v1.4.21: can't initialize iptables table `nat': File exists Perhaps iptables or your kernel needs to be upgraded.
nftables error if iptables nat table present:
nft -f /etc/nftables/ipv4-nat
/usr/etc/nftables/ipv4-nat:3:1-2: Error: Could not process rule: File exists table nat {
^^
--- include/linux/netfilter.h | 1 + net/ipv4/netfilter/iptable_nat.c | 4 ++++ net/ipv6/netfilter/ip6table_nat.c | 4 ++++ net/netfilter/core.c | 6 ++++++ net/netfilter/nf_tables_api.c | 2 ++ 5 files changed, 17 insertions(+)
include/linux/netfilter.h +1 -0
@@ -67,6 +67,7 @@ struct nf_hook_ops {struct net_device *dev;void *priv;u_int8_t pf; +bool nat_hook;unsigned int hooknum;/* Hooks are ordered in ascending priority. */ int priority;
net/ipv4/netfilter/iptable_nat.c +4 -0
@@ -72,6 +72,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = { { .hook = iptable_nat_ipv4_in, .pf = NFPROTO_IPV4, + .nat_hook = true, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_NAT_DST, },
@@ -79,6 +80,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = { { .hook = iptable_nat_ipv4_out, .pf = NFPROTO_IPV4, + .nat_hook = true, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_NAT_SRC, },
@@ -86,6 +88,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = { { .hook = iptable_nat_ipv4_local_fn, .pf = NFPROTO_IPV4, + .nat_hook = true, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST, },
@@ -93,6 +96,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = { { .hook = iptable_nat_ipv4_fn, .pf = NFPROTO_IPV4, + .nat_hook = true, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC, },
net/ipv6/netfilter/ip6table_nat.c +4 -0
@@ -74,6 +74,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = { { .hook = ip6table_nat_in, .pf = NFPROTO_IPV6, + .nat_hook = true, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_NAT_DST, },
@@ -81,6 +82,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = { { .hook = ip6table_nat_out, .pf = NFPROTO_IPV6, + .nat_hook = true, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP6_PRI_NAT_SRC, },
@@ -88,12 +90,14 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = { { .hook = ip6table_nat_local_fn, .pf = NFPROTO_IPV6, + .nat_hook = true, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_NAT_DST, },/* After packet filtering, change source */ { .hook = ip6table_nat_fn, + .nat_hook = true, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_NAT_SRC,
net/netfilter/core.c +6 -0
@@ -160,6 +160,12 @@ nf_hook_entries_grow(const struct nf_hook_entries *old, ++i;continue ; } + +if (reg->nat_hook && orig_ops[i]->nat_hook) { +kvfree (new); +return ERR_PTR (-EEXIST ); + } +if (inserted || reg->priority > orig_ops[i]->priority) { new_ops[nhooks] = (void *)orig_ops[i]; new->hooks[nhooks] = old->hooks[i];
net/netfilter/nf_tables_api.c +2 -0
@@ -1400,6 +1400,8 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, ops->hook = hookfn;if (afi->hook_ops_init) afi->hook_ops_init (ops, i); +if (basechain->type->type ==NFT_CHAIN_T_NAT ) + ops->nat_hook = true; } chain->flags |=NFT_BASE_CHAIN ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 21/52 netfilter: nf_tables: reject nat hook registration if prio is before conntrack
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
No problem for iptables as priorities are fixed values defined in the nat modules, but in nftables the priority its coming from userspace.
Reject in case we see that such a hook would not work.
--- net/netfilter/nf_tables_api.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +6 -1
@@ -1264,7 +1264,7 @@ static void nf_tables_chain_destroy(struct nft_chain *chain)struct nft_chain_hook {u32 num; -u32 priority; +s32 priority;const struct nf_chain_type *type;struct net_device *dev; };
@@ -1303,6 +1303,11 @@ static int nft_chain_parse_hook(struct net *net, }if (!(type->hook_mask & (1 << hook->num)))return -EOPNOTSUPP ; + +if (type->type ==NFT_CHAIN_T_NAT && + hook->priority <=NF_IP_PRI_CONNTRACK ) +return -EOPNOTSUPP ; +if (!try_module_get (type->owner))return -ENOENT ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 22/52 netfilter: nf_tables_arp: don't set forward chain
In reply to Pablo Neira Ayuso46928a0b49f3 ("netfilter: nf_tables: remove multihook chains and families") already removed this, this is a leftover.
--- net/ipv4/netfilter/nf_tables_arp.c | 1 - 1 file changed, 1 deletion(-)
net/ipv4/netfilter/nf_tables_arp.c +0 -1
@@ -34,7 +34,6 @@ static struct nft_af_info nft_af_arp __read_mostly = { .hooks = { [NF_ARP_IN] = nft_do_chain_arp, [NF_ARP_OUT] = nft_do_chain_arp, - [NF_ARP_FORWARD] = nft_do_chain_arp, }, };
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 23/52 netfilter: nf_tables: explicit nft_set_pktinfo() call from hook path
In reply to Pablo Neira AyusoInstead of calling this function from the family specific variant, this reduces the code size in the fast path for the netdev, bridge and inet families. After this change, we must call nft_set_pktinfo() upfront from the chain hook indirection.
Before:
text data bss dec hex filename
2145 208 0 2353 931 net/netfilter/nf_tables_netdev.o
After:
text data bss dec hex filename
2125 208 0 2333 91d net/netfilter/nf_tables_netdev.o
--- include/net/netfilter/nf_tables.h | 12 ++---------- include/net/netfilter/nf_tables_ipv4.h | 25 ++++++++----------------- include/net/netfilter/nf_tables_ipv6.h | 27 +++++++++------------------ net/bridge/netfilter/nf_tables_bridge.c | 8 +++++--- net/ipv4/netfilter/nf_tables_arp.c | 3 ++- net/ipv4/netfilter/nf_tables_ipv4.c | 3 ++- net/ipv4/netfilter/nft_chain_nat_ipv4.c | 3 ++- net/ipv4/netfilter/nft_chain_route_ipv4.c | 3 ++- net/ipv6/netfilter/nf_tables_ipv6.c | 3 ++- net/ipv6/netfilter/nft_chain_nat_ipv6.c | 3 ++- net/ipv6/netfilter/nft_chain_route_ipv6.c | 3 ++- net/netfilter/nf_tables_netdev.c | 8 +++++--- 12 files changed, 43 insertions(+), 58 deletions(-)
include/net/netfilter/nf_tables.h +2 -10
@@ -54,8 +54,8 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, pkt->xt.state = state; } -static inline void nft_set_pktinfo_proto_unspec (struct nft_pktinfo *pkt, -struct sk_buff *skb) +static inline void nft_set_pktinfo_unspec (struct nft_pktinfo *pkt, +struct sk_buff *skb) { pkt->tprot_set = false; pkt->tprot =0 ;
@@ -63,14 +63,6 @@ static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt, pkt->xt.fragoff =0 ; } -static inline void nft_set_pktinfo_unspec (struct nft_pktinfo *pkt, -struct sk_buff *skb, -const struct nf_hook_state *state) -{ -nft_set_pktinfo (pkt, skb, state); -nft_set_pktinfo_proto_unspec (pkt, skb); -} -/** * struct nft_verdict - nf_tables verdict *
include/net/netfilter/nf_tables_ipv4.h +8 -17
@@ -5,15 +5,11 @@#include <net/netfilter/nf_tables.h> #include <net/ip.h> -static inline void -nft_set_pktinfo_ipv4 (struct nft_pktinfo *pkt, -struct sk_buff *skb, -const struct nf_hook_state *state) +static inline void nft_set_pktinfo_ipv4 (struct nft_pktinfo *pkt, +struct sk_buff *skb) {struct iphdr *ip; -nft_set_pktinfo (pkt, skb, state); - ip =ip_hdr (pkt->skb); pkt->tprot_set = true; pkt->tprot = ip->protocol;
@@ -21,10 +17,8 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, pkt->xt.fragoff =ntohs (ip->frag_off) &IP_OFFSET ; } -static inline int -__nft_set_pktinfo_ipv4_validate (struct nft_pktinfo *pkt, -struct sk_buff *skb, -const struct nf_hook_state *state) +static inline int __nft_set_pktinfo_ipv4_validate (struct nft_pktinfo *pkt, +struct sk_buff *skb) {struct iphdr *iph, _iph;u32 len, thoff;
@@ -52,14 +46,11 @@ __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,return 0 ; } -static inline void -nft_set_pktinfo_ipv4_validate (struct nft_pktinfo *pkt, -struct sk_buff *skb, -const struct nf_hook_state *state) +static inline void nft_set_pktinfo_ipv4_validate (struct nft_pktinfo *pkt, +struct sk_buff *skb) { -nft_set_pktinfo (pkt, skb, state); -if (__nft_set_pktinfo_ipv4_validate (pkt, skb, state) <0 ) -nft_set_pktinfo_proto_unspec (pkt, skb); +if (__nft_set_pktinfo_ipv4_validate (pkt, skb) <0 ) +nft_set_pktinfo_unspec (pkt, skb); }extern struct nft_af_info nft_af_ipv4;
include/net/netfilter/nf_tables_ipv6.h +9 -18
@@ -5,20 +5,16 @@#include <linux/netfilter_ipv6/ip6_tables.h> #include <net/ipv6.h> -static inline void -nft_set_pktinfo_ipv6 (struct nft_pktinfo *pkt, -struct sk_buff *skb, -const struct nf_hook_state *state) +static inline void nft_set_pktinfo_ipv6 (struct nft_pktinfo *pkt, +struct sk_buff *skb) {unsigned int flags =IP6_FH_F_AUTH ;int protohdr, thoff =0 ;unsigned short frag_off; -nft_set_pktinfo (pkt, skb, state); - protohdr =ipv6_find_hdr (pkt->skb, &thoff,-1 , &frag_off, &flags);if (protohdr <0 ) { -nft_set_pktinfo_proto_unspec (pkt, skb); +nft_set_pktinfo_unspec (pkt, skb);return ; }
@@ -28,10 +24,8 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, pkt->xt.fragoff = frag_off; } -static inline int -__nft_set_pktinfo_ipv6_validate (struct nft_pktinfo *pkt, -struct sk_buff *skb, -const struct nf_hook_state *state) +static inline int __nft_set_pktinfo_ipv6_validate (struct nft_pktinfo *pkt, +struct sk_buff *skb) {#if IS_ENABLED (CONFIG_IPV6 )unsigned int flags =IP6_FH_F_AUTH ;
@@ -68,14 +62,11 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,#endif } -static inline void -nft_set_pktinfo_ipv6_validate (struct nft_pktinfo *pkt, -struct sk_buff *skb, -const struct nf_hook_state *state) +static inline void nft_set_pktinfo_ipv6_validate (struct nft_pktinfo *pkt, +struct sk_buff *skb) { -nft_set_pktinfo (pkt, skb, state); -if (__nft_set_pktinfo_ipv6_validate (pkt, skb, state) <0 ) -nft_set_pktinfo_proto_unspec (pkt, skb); +if (__nft_set_pktinfo_ipv6_validate (pkt, skb) <0 ) +nft_set_pktinfo_unspec (pkt, skb); }extern struct nft_af_info nft_af_ipv6;
net/bridge/netfilter/nf_tables_bridge.c +5 -3
@@ -25,15 +25,17 @@ nft_do_chain_bridge(void *priv, {struct nft_pktinfo pkt; +nft_set_pktinfo (&pkt, skb, state); +switch (eth_hdr (skb)->h_proto) {case htons (ETH_P_IP ): -nft_set_pktinfo_ipv4_validate (&pkt, skb, state); +nft_set_pktinfo_ipv4_validate (&pkt, skb);break ;case htons (ETH_P_IPV6 ): -nft_set_pktinfo_ipv6_validate (&pkt, skb, state); +nft_set_pktinfo_ipv6_validate (&pkt, skb);break ;default : -nft_set_pktinfo_unspec (&pkt, skb, state); +nft_set_pktinfo_unspec (&pkt, skb);break ; }
net/ipv4/netfilter/nf_tables_arp.c +2 -1
@@ -21,7 +21,8 @@ nft_do_chain_arp(void *priv, {struct nft_pktinfo pkt; -nft_set_pktinfo_unspec (&pkt, skb, state); +nft_set_pktinfo (&pkt, skb, state); +nft_set_pktinfo_unspec (&pkt, skb);return nft_do_chain (&pkt, priv); }
net/ipv4/netfilter/nf_tables_ipv4.c +2 -1
@@ -24,7 +24,8 @@ static unsigned int nft_do_chain_ipv4(void *priv, {struct nft_pktinfo pkt; -nft_set_pktinfo_ipv4 (&pkt, skb, state); +nft_set_pktinfo (&pkt, skb, state); +nft_set_pktinfo_ipv4 (&pkt, skb);return nft_do_chain (&pkt, priv); }
net/ipv4/netfilter/nft_chain_nat_ipv4.c +2 -1
@@ -33,7 +33,8 @@ static unsigned int nft_nat_do_chain(void *priv, {struct nft_pktinfo pkt; -nft_set_pktinfo_ipv4 (&pkt, skb, state); +nft_set_pktinfo (&pkt, skb, state); +nft_set_pktinfo_ipv4 (&pkt, skb);return nft_do_chain (&pkt, priv); }
net/ipv4/netfilter/nft_chain_route_ipv4.c +2 -1
@@ -38,7 +38,8 @@ static unsigned int nf_route_table_hook(void *priv, ip_hdrlen(skb) < sizeof(struct iphdr))return NF_ACCEPT ; -nft_set_pktinfo_ipv4 (&pkt, skb, state); +nft_set_pktinfo (&pkt, skb, state); +nft_set_pktinfo_ipv4 (&pkt, skb); mark = skb->mark; iph =ip_hdr (skb);
net/ipv6/netfilter/nf_tables_ipv6.c +2 -1
@@ -22,7 +22,8 @@ static unsigned int nft_do_chain_ipv6(void *priv, {struct nft_pktinfo pkt; -nft_set_pktinfo_ipv6 (&pkt, skb, state); +nft_set_pktinfo (&pkt, skb, state); +nft_set_pktinfo_ipv6 (&pkt, skb);return nft_do_chain (&pkt, priv); }
net/ipv6/netfilter/nft_chain_nat_ipv6.c +2 -1
@@ -31,7 +31,8 @@ static unsigned int nft_nat_do_chain(void *priv, {struct nft_pktinfo pkt; -nft_set_pktinfo_ipv6 (&pkt, skb, state); +nft_set_pktinfo (&pkt, skb, state); +nft_set_pktinfo_ipv6 (&pkt, skb);return nft_do_chain (&pkt, priv); }
net/ipv6/netfilter/nft_chain_route_ipv6.c +2 -1
@@ -33,7 +33,8 @@ static unsigned int nf_route_table_hook(void *priv,u32 mark, flowlabel;int err; -nft_set_pktinfo_ipv6 (&pkt, skb, state); +nft_set_pktinfo (&pkt, skb, state); +nft_set_pktinfo_ipv6 (&pkt, skb);/* save source/dest address, mark, hoplimit, flowlabel, priority */ memcpy (&saddr, &ipv6_hdr (skb)->saddr,sizeof (saddr));
net/netfilter/nf_tables_netdev.c +5 -3
@@ -21,15 +21,17 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb, {struct nft_pktinfo pkt; +nft_set_pktinfo (&pkt, skb, state); +switch (skb->protocol) {case htons (ETH_P_IP ): -nft_set_pktinfo_ipv4_validate (&pkt, skb, state); +nft_set_pktinfo_ipv4_validate (&pkt, skb);break ;case htons (ETH_P_IPV6 ): -nft_set_pktinfo_ipv6_validate (&pkt, skb, state); +nft_set_pktinfo_ipv6_validate (&pkt, skb);break ;default : -nft_set_pktinfo_unspec (&pkt, skb, state); +nft_set_pktinfo_unspec (&pkt, skb);break ; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 24/52 netfilter: nf_tables: add nft_set_is_anonymous() helper
In reply to Pablo Neira AyusoAdd helper function to test for the NFT_SET_ANONYMOUS flag.
--- include/net/netfilter/nf_tables.h | 5 +++++ net/netfilter/nf_tables_api.c | 8 ++++---- net/netfilter/nft_dynset.c | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-)
include/net/netfilter/nf_tables.h +5 -0
@@ -416,6 +416,11 @@ struct nft_set { __attribute__((aligned(__alignof__(u64)))); }; +static inline bool nft_set_is_anonymous (const struct nft_set *set) +{ +return set->flags &NFT_SET_ANONYMOUS ; +} +static inline void *nft_set_priv (const struct nft_set *set) {return (void *)set->data;
net/netfilter/nf_tables_api.c +4 -4
@@ -774,7 +774,7 @@ static int nft_flush_table(struct nft_ctx *ctx)if (!nft_is_active_next (ctx->net, set))continue ; -if (set->flags &NFT_SET_ANONYMOUS && +if (nft_set_is_anonymous (set) && !list_empty (&set->bindings))continue ;
@@ -3284,7 +3284,7 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,struct nft_set_binding *i;struct nft_set_iter iter; -if (!list_empty (&set->bindings) && set->flags &NFT_SET_ANONYMOUS ) +if (!list_empty (&set->bindings) &&nft_set_is_anonymous (set))return -EBUSY ;if (binding->flags &NFT_SET_MAP ) {
@@ -3319,7 +3319,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, {list_del_rcu (&binding->list); -if (list_empty (&set->bindings) && set->flags &NFT_SET_ANONYMOUS && +if (list_empty (&set->bindings) &&nft_set_is_anonymous (set) &&nft_is_active (ctx->net, set))nf_tables_set_destroy (ctx, set); }
@@ -5157,7 +5157,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)/* This avoids hitting -EBUSY when deleting the table * from the transaction. */ -if (nft_trans_set (trans)->flags &NFT_SET_ANONYMOUS && +if (nft_set_is_anonymous (nft_trans_set (trans)) && !list_empty (&nft_trans_set (trans)->bindings)) trans->ctx.table->use--;
net/netfilter/nft_dynset.c +1 -1
@@ -184,7 +184,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,if (tb[NFTA_DYNSET_EXPR ] !=NULL ) {if (!(set->flags &NFT_SET_EVAL ))return -EINVAL ; -if (!(set->flags &NFT_SET_ANONYMOUS )) +if (!nft_set_is_anonymous (set))return -EOPNOTSUPP ; priv->expr =nft_expr_init (ctx, tb[NFTA_DYNSET_EXPR ]);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 25/52 netfilter: core: add nf_remove_net_hook
In reply to Pablo Neira AyusoJust a cleanup, __nf_unregister_net_hook() is used by a follow up patch when handling NFPROTO_INET as a real family from the core.
--- net/netfilter/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/netfilter/core.c +4 -4
@@ -360,7 +360,7 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)EXPORT_SYMBOL (nf_register_net_hook);/* -* __nf_unregister_net_hook - remove a hook from blob +* nf_remove_net_hook - remove a hook from blob * * @oldp: current address of hook blob * @unreg: hook to unregister
@@ -368,8 +368,8 @@ EXPORT_SYMBOL(nf_register_net_hook);* This cannot fail, hook unregistration must always succeed. * Therefore replace the to-be-removed hook with a dummy hook. */ -static void __nf_unregister_net_hook (struct nf_hook_entries *old, -const struct nf_hook_ops *unreg) +static void nf_remove_net_hook (struct nf_hook_entries *old, +const struct nf_hook_ops *unreg) {struct nf_hook_ops **orig_ops;bool found = false;
@@ -415,7 +415,7 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)return ; } -__nf_unregister_net_hook (p, reg); +nf_remove_net_hook (p, reg); p =__nf_hook_entries_try_shrink (pp);mutex_unlock (&nf_hook_mutex);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 26/52 netfilter: core: pass hook number, family and device to nf_find_hook_list()
In reply to Pablo Neira AyusoInstead of passing struct nf_hook_ops, this is needed by follow up patches to handle NFPROTO_INET from the core.
--- net/netfilter/core.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-)
net/netfilter/core.c +19 -17
@@ -268,36 +268,38 @@ static void *__nf_hook_entries_try_shrink(struct nf_hook_entries __rcu **pp)return old; } -static struct nf_hook_entries __rcu **nf_hook_entry_head (struct net *net,const struct nf_hook_ops *reg) +static struct nf_hook_entries __rcu ** +nf_hook_entry_head (struct net *net,int pf,unsigned int hooknum, +struct net_device *dev) { -switch (reg->pf) { +switch (pf) {case NFPROTO_NETDEV :break ;#ifdef CONFIG_NETFILTER_FAMILY_ARP case NFPROTO_ARP : -if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_arp) <= reg->hooknum)) +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_arp) <= hooknum))return NULL ; -return net->nf.hooks_arp + reg->hooknum; +return net->nf.hooks_arp + hooknum;#endif #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE case NFPROTO_BRIDGE : -if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_bridge) <= reg->hooknum)) +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_bridge) <= hooknum))return NULL ; -return net->nf.hooks_bridge + reg->hooknum; +return net->nf.hooks_bridge + hooknum;#endif case NFPROTO_IPV4 : -if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv4) <= reg->hooknum)) +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv4) <= hooknum))return NULL ; -return net->nf.hooks_ipv4 + reg->hooknum; +return net->nf.hooks_ipv4 + hooknum;case NFPROTO_IPV6 : -if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv6) <= reg->hooknum)) +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_ipv6) <= hooknum))return NULL ; -return net->nf.hooks_ipv6 + reg->hooknum; +return net->nf.hooks_ipv6 + hooknum;#if IS_ENABLED (CONFIG_DECNET )case NFPROTO_DECNET : -if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_decnet) <= reg->hooknum)) +if (WARN_ON_ONCE (ARRAY_SIZE (net->nf.hooks_decnet) <= hooknum))return NULL ; -return net->nf.hooks_decnet + reg->hooknum; +return net->nf.hooks_decnet + hooknum;#endif default :WARN_ON_ONCE (1 );
@@ -305,9 +307,9 @@ static struct nf_hook_entries __rcu **nf_hook_entry_head(struct net *net, const }#ifdef CONFIG_NETFILTER_INGRESS -if (reg->hooknum ==NF_NETDEV_INGRESS ) { -if (reg->dev &&dev_net (reg->dev) == net) -return ®->dev->nf_hooks_ingress; +if (hooknum ==NF_NETDEV_INGRESS ) { +if (dev &&dev_net (dev) == net) +return &dev->nf_hooks_ingress; }#endif WARN_ON_ONCE (1 );
@@ -329,7 +331,7 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)return -EINVAL ; } - pp =nf_hook_entry_head (net, reg); + pp =nf_hook_entry_head (net, reg->pf, reg->hooknum, reg->dev);if (!pp)return -EINVAL ;
@@ -403,7 +405,7 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)struct nf_hook_entries __rcu **pp;struct nf_hook_entries *p; - pp =nf_hook_entry_head (net, reg); + pp =nf_hook_entry_head (net, reg->pf, reg->hooknum, reg->dev);if (!pp)return ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 27/52 netfilter: core: pass family as parameter to nf_remove_net_hook()
In reply to Pablo Neira AyusoSo static_key_slow_dec applies to the family behind NFPROTO_INET.
--- net/netfilter/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
net/netfilter/core.c +5 -5
@@ -371,7 +371,7 @@ EXPORT_SYMBOL(nf_register_net_hook);* Therefore replace the to-be-removed hook with a dummy hook. */ static void nf_remove_net_hook (struct nf_hook_entries *old, -const struct nf_hook_ops *unreg) +const struct nf_hook_ops *unreg,int pf) {struct nf_hook_ops **orig_ops;bool found = false;
@@ -389,14 +389,14 @@ static void nf_remove_net_hook(struct nf_hook_entries *old,if (found) {#ifdef CONFIG_NETFILTER_INGRESS -if (unreg->pf ==NFPROTO_NETDEV && unreg->hooknum ==NF_NETDEV_INGRESS ) +if (pf ==NFPROTO_NETDEV && unreg->hooknum ==NF_NETDEV_INGRESS )net_dec_ingress_queue ();#endif #ifdef HAVE_JUMP_LABEL -static_key_slow_dec (&nf_hooks_needed[unreg->pf][unreg->hooknum]); +static_key_slow_dec (&nf_hooks_needed[pf][unreg->hooknum]);#endif }else { -WARN_ONCE (1 ,"hook not found, pf %d num %d" , unreg->pf, unreg->hooknum); +WARN_ONCE (1 ,"hook not found, pf %d num %d" , pf, unreg->hooknum); } }
@@ -417,7 +417,7 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)return ; } -nf_remove_net_hook (p, reg); +nf_remove_net_hook (p, reg, reg->pf); p =__nf_hook_entries_try_shrink (pp);mutex_unlock (&nf_hook_mutex);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 28/52 netfilter: core: support for NFPROTO_INET hook registration
In reply to Pablo Neira AyusoExpand NFPROTO_INET in two hook registrations, one for NFPROTO_IPV4 and another for NFPROTO_IPV6. Hence, we handle NFPROTO_INET from the core.
--- net/netfilter/core.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 9 deletions(-)
net/netfilter/core.c +44 -9
@@ -316,12 +316,13 @@ nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum,return NULL ; } -int nf_register_net_hook (struct net *net,const struct nf_hook_ops *reg) +static int __nf_register_net_hook (struct net *net,int pf, +const struct nf_hook_ops *reg) {struct nf_hook_entries *p, *new_hooks;struct nf_hook_entries __rcu **pp; -if (reg->pf ==NFPROTO_NETDEV ) { +if (pf ==NFPROTO_NETDEV ) {#ifndef CONFIG_NETFILTER_INGRESS if (reg->hooknum ==NF_NETDEV_INGRESS )return -EOPNOTSUPP ;
@@ -331,7 +332,7 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)return -EINVAL ; } - pp =nf_hook_entry_head (net, reg->pf, reg->hooknum, reg->dev); + pp =nf_hook_entry_head (net, pf, reg->hooknum, reg->dev);if (!pp)return -EINVAL ;
@@ -349,17 +350,16 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)hooks_validate (new_hooks);#ifdef CONFIG_NETFILTER_INGRESS -if (reg->pf ==NFPROTO_NETDEV && reg->hooknum ==NF_NETDEV_INGRESS ) +if (pf ==NFPROTO_NETDEV && reg->hooknum ==NF_NETDEV_INGRESS )net_inc_ingress_queue ();#endif #ifdef HAVE_JUMP_LABEL -static_key_slow_inc (&nf_hooks_needed[reg->pf][reg->hooknum]); +static_key_slow_inc (&nf_hooks_needed[pf][reg->hooknum]);#endif BUG_ON (p == new_hooks);nf_hook_entries_free (p);return 0 ; } -EXPORT_SYMBOL (nf_register_net_hook);/* * nf_remove_net_hook - remove a hook from blob
@@ -400,12 +400,13 @@ static void nf_remove_net_hook(struct nf_hook_entries *old, } } -void nf_unregister_net_hook (struct net *net,const struct nf_hook_ops *reg) +void __nf_unregister_net_hook (struct net *net,int pf, +const struct nf_hook_ops *reg) {struct nf_hook_entries __rcu **pp;struct nf_hook_entries *p; - pp =nf_hook_entry_head (net, reg->pf, reg->hooknum, reg->dev); + pp =nf_hook_entry_head (net, pf, reg->hooknum, reg->dev);if (!pp)return ;
@@ -417,7 +418,7 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)return ; } -nf_remove_net_hook (p, reg, reg->pf); +nf_remove_net_hook (p, reg, pf); p =__nf_hook_entries_try_shrink (pp);mutex_unlock (&nf_hook_mutex);
@@ -427,8 +428,42 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)nf_queue_nf_hook_drop (net);nf_hook_entries_free (p); } + +void nf_unregister_net_hook (struct net *net,const struct nf_hook_ops *reg) +{ +if (reg->pf ==NFPROTO_INET ) { +__nf_unregister_net_hook (net,NFPROTO_IPV4 , reg); +__nf_unregister_net_hook (net,NFPROTO_IPV6 , reg); + }else { +__nf_unregister_net_hook (net, reg->pf, reg); + } +}EXPORT_SYMBOL (nf_unregister_net_hook); +int nf_register_net_hook (struct net *net,const struct nf_hook_ops *reg) +{ +int err; + +if (reg->pf ==NFPROTO_INET ) { + err =__nf_register_net_hook (net,NFPROTO_IPV4 , reg); +if (err <0 ) +return err; + + err =__nf_register_net_hook (net,NFPROTO_IPV6 , reg); +if (err <0 ) { +__nf_unregister_net_hook (net,NFPROTO_IPV4 , reg); +return err; + } + }else { + err =__nf_register_net_hook (net, reg->pf, reg); +if (err <0 ) +return err; + } + +return 0 ; +} +EXPORT_SYMBOL (nf_register_net_hook); +int nf_register_net_hooks (struct net *net,const struct nf_hook_ops *reg,unsigned int n) {
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 29/52 netfilter: nf_tables_inet: don't use multihook infrastructure anymore
In reply to Pablo Neira AyusoUse new native NFPROTO_INET support in netfilter core, this gets rid of ad-hoc code in the nf_tables API codebase.
--- include/net/netfilter/nf_tables_ipv4.h | 2 - include/net/netfilter/nf_tables_ipv6.h | 2 - net/ipv4/netfilter/nf_tables_ipv4.c | 3 +- net/ipv6/netfilter/nf_tables_ipv6.c | 3 +- net/netfilter/nf_tables_inet.c | 70 ++++++++++++++++++++++++++++------ 5 files changed, 60 insertions(+), 20 deletions(-)
include/net/netfilter/nf_tables_ipv4.h +0 -2
@@ -53,6 +53,4 @@ static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, nft_set_pktinfo_unspec(pkt, skb); } -extern struct nft_af_info nft_af_ipv4; -#endif
include/net/netfilter/nf_tables_ipv6.h +0 -2
@@ -69,6 +69,4 @@ static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, nft_set_pktinfo_unspec(pkt, skb); } -extern struct nft_af_info nft_af_ipv6; -#endif
net/ipv4/netfilter/nf_tables_ipv4.c +1 -2
@@ -45,7 +45,7 @@ static unsigned int nft_ipv4_output(void *priv,return nft_do_chain_ipv4 (priv, skb, state); } -struct nft_af_info nft_af_ipv4__read_mostly = { +static struct nft_af_info nft_af_ipv4__read_mostly = { .family =NFPROTO_IPV4 , .nhooks =NF_INET_NUMHOOKS , .owner =THIS_MODULE ,
@@ -58,7 +58,6 @@ struct nft_af_info nft_af_ipv4 __read_mostly = { [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, }, }; -EXPORT_SYMBOL_GPL (nft_af_ipv4);static int nf_tables_ipv4_init_net (struct net *net) {
net/ipv6/netfilter/nf_tables_ipv6.c +1 -2
@@ -42,7 +42,7 @@ static unsigned int nft_ipv6_output(void *priv,return nft_do_chain_ipv6 (priv, skb, state); } -struct nft_af_info nft_af_ipv6__read_mostly = { +static struct nft_af_info nft_af_ipv6__read_mostly = { .family =NFPROTO_IPV6 , .nhooks =NF_INET_NUMHOOKS , .owner =THIS_MODULE ,
@@ -55,7 +55,6 @@ struct nft_af_info nft_af_ipv6 __read_mostly = { [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, }, }; -EXPORT_SYMBOL_GPL (nft_af_ipv6);static int nf_tables_ipv6_init_net (struct net *net) {
net/netfilter/nf_tables_inet.c +58 -12
90 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 30/52 netfilter: nf_tables: remove multihook chains and families
In reply to Pablo Neira AyusoSince NFPROTO_INET is handled from the core, we don't need to maintain extra infrastructure in nf_tables to handle the double hook registration, one for IPv4 and another for IPv6.
--- include/net/netfilter/nf_tables.h | 9 +-- net/bridge/netfilter/nf_tables_bridge.c | 1 - net/ipv4/netfilter/nf_tables_arp.c | 1 - net/ipv4/netfilter/nf_tables_ipv4.c | 1 - net/ipv6/netfilter/nf_tables_ipv6.c | 1 - net/netfilter/nf_tables_api.c | 102 ++++++++++++++------------------ net/netfilter/nf_tables_inet.c | 1 - net/netfilter/nf_tables_netdev.c | 3 +- net/netfilter/nft_compat.c | 8 +-- 9 files changed, 49 insertions(+), 78 deletions(-)
include/net/netfilter/nf_tables.h +1 -8
@@ -902,8 +902,6 @@ struct nft_stats {struct u64_stats_sync syncp; }; -#define NFT_HOOK_OPS_MAX 2 -/** * struct nft_base_chain - nf_tables base chain *
@@ -915,7 +913,7 @@ struct nft_stats {* @dev_name: device name that this base chain is attached to (if any) */ struct nft_base_chain { -struct nf_hook_ops ops[NFT_HOOK_OPS_MAX ]; +struct nf_hook_ops ops;const struct nf_chain_type *type;u8 policy;u8 flags;
@@ -976,8 +974,6 @@ enum nft_af_flags {* @owner: module owner * @tables: used internally * @flags: family flags -* @nops: number of hook ops in this family -* @hook_ops_init: initialization function for chain hook ops * @hooks: hookfn overrides for packet validation */ struct nft_af_info {
@@ -987,9 +983,6 @@ struct nft_af_info {struct module *owner;struct list_head tables;u32 flags; -unsigned int nops; -void (*hook_ops_init)(struct nf_hook_ops *, -unsigned int );nf_hookfn *hooks[NF_MAX_HOOKS ]; };
net/bridge/netfilter/nf_tables_bridge.c +0 -1
@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_bridge __read_mostly = { .family = NFPROTO_BRIDGE, .nhooks = NF_BR_NUMHOOKS, .owner = THIS_MODULE, - .nops = 1, .hooks = { [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, [NF_BR_LOCAL_IN] = nft_do_chain_bridge,
net/ipv4/netfilter/nf_tables_arp.c +0 -1
@@ -31,7 +31,6 @@ static struct nft_af_info nft_af_arp __read_mostly = { .family = NFPROTO_ARP, .nhooks = NF_ARP_NUMHOOKS, .owner = THIS_MODULE, - .nops = 1, .hooks = { [NF_ARP_IN] = nft_do_chain_arp, [NF_ARP_OUT] = nft_do_chain_arp,
net/ipv4/netfilter/nf_tables_ipv4.c +0 -1
@@ -49,7 +49,6 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = { .family = NFPROTO_IPV4, .nhooks = NF_INET_NUMHOOKS, .owner = THIS_MODULE, - .nops = 1, .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, [NF_INET_LOCAL_OUT] = nft_ipv4_output,
net/ipv6/netfilter/nf_tables_ipv6.c +0 -1
@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = { .family = NFPROTO_IPV6, .nhooks = NF_INET_NUMHOOKS, .owner = THIS_MODULE, - .nops = 1, .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, [NF_INET_LOCAL_OUT] = nft_ipv6_output,
net/netfilter/nf_tables_api.c +43 -59
216 lines not on this page · raw message
net/netfilter/nf_tables_inet.c +0 -1
@@ -74,7 +74,6 @@ static struct nft_af_info nft_af_inet __read_mostly = { .family = NFPROTO_INET, .nhooks = NF_INET_NUMHOOKS, .owner = THIS_MODULE, - .nops = 1, .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_inet, [NF_INET_LOCAL_OUT] = nft_inet_output,
net/netfilter/nf_tables_netdev.c +1 -2
@@ -43,7 +43,6 @@ static struct nft_af_info nft_af_netdev __read_mostly = { .nhooks = NF_NETDEV_NUMHOOKS, .owner = THIS_MODULE, .flags = NFT_AF_NEEDS_DEV, - .nops = 1, .hooks = { [NF_NETDEV_INGRESS] = nft_do_chain_netdev, },
@@ -98,7 +97,7 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,__nft_release_basechain (ctx);break ;case NETDEV_CHANGENAME : -if (dev->ifindex != basechain->ops[0 ].dev->ifindex) +if (dev->ifindex != basechain->ops.dev->ifindex)return ;strncpy (basechain->dev_name, dev->name,IFNAMSIZ );
net/netfilter/nft_compat.c +4 -4
@@ -169,7 +169,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,if (nft_is_base_chain (ctx->chain)) {const struct nft_base_chain *basechain =nft_base_chain (ctx->chain); -const struct nf_hook_ops *ops = &basechain->ops[0 ]; +const struct nf_hook_ops *ops = &basechain->ops; par->hook_mask =1 << ops->hooknum; }else {
@@ -302,7 +302,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,if (nft_is_base_chain (ctx->chain)) {const struct nft_base_chain *basechain =nft_base_chain (ctx->chain); -const struct nf_hook_ops *ops = &basechain->ops[0 ]; +const struct nf_hook_ops *ops = &basechain->ops; hook_mask =1 << ops->hooknum;if (target->hooks && !(hook_mask & target->hooks))
@@ -383,7 +383,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,if (nft_is_base_chain (ctx->chain)) {const struct nft_base_chain *basechain =nft_base_chain (ctx->chain); -const struct nf_hook_ops *ops = &basechain->ops[0 ]; +const struct nf_hook_ops *ops = &basechain->ops; par->hook_mask =1 << ops->hooknum; }else {
@@ -481,7 +481,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,if (nft_is_base_chain (ctx->chain)) {const struct nft_base_chain *basechain =nft_base_chain (ctx->chain); -const struct nf_hook_ops *ops = &basechain->ops[0 ]; +const struct nf_hook_ops *ops = &basechain->ops; hook_mask =1 << ops->hooknum;if (match->hooks && !(hook_mask & match->hooks))
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 31/52 netfilter: nf_tables: remove hooks from family definition
In reply to Pablo Neira AyusoThey don't belong to the family definition, move them to the filter chain type definition instead.
--- include/net/netfilter/nf_tables.h | 4 +--- net/bridge/netfilter/nf_tables_bridge.c | 14 +++++++------- net/ipv4/netfilter/nf_tables_arp.c | 8 ++++---- net/ipv4/netfilter/nf_tables_ipv4.c | 14 +++++++------- net/ipv6/netfilter/nf_tables_ipv6.c | 14 +++++++------- net/netfilter/nf_tables_api.c | 6 +----- net/netfilter/nf_tables_inet.c | 14 +++++++------- net/netfilter/nf_tables_netdev.c | 6 +++--- 8 files changed, 37 insertions(+), 43 deletions(-)
include/net/netfilter/nf_tables.h +1 -3
@@ -880,7 +880,7 @@ enum nft_chain_type {* @family: address family * @owner: module owner * @hook_mask: mask of valid hooks -* @hooks: hookfn overrides +* @hooks: array of hook functions */ struct nf_chain_type {const char *name;
@@ -974,7 +974,6 @@ enum nft_af_flags {* @owner: module owner * @tables: used internally * @flags: family flags -* @hooks: hookfn overrides for packet validation */ struct nft_af_info {struct list_head list;
@@ -983,7 +982,6 @@ struct nft_af_info {struct module *owner;struct list_head tables;u32 flags; -nf_hookfn *hooks[NF_MAX_HOOKS ]; };int nft_register_afinfo (struct net *,struct nft_af_info *);
net/bridge/netfilter/nf_tables_bridge.c +7 -7
@@ -46,13 +46,6 @@ static struct nft_af_info nft_af_bridge __read_mostly = { .family = NFPROTO_BRIDGE, .nhooks = NF_BR_NUMHOOKS, .owner = THIS_MODULE, - .hooks = { - [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, - [NF_BR_LOCAL_IN] = nft_do_chain_bridge, - [NF_BR_FORWARD] = nft_do_chain_bridge, - [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, - [NF_BR_POST_ROUTING] = nft_do_chain_bridge, - }, };static int nf_tables_bridge_init_net (struct net *net)
@@ -93,6 +86,13 @@ static const struct nf_chain_type filter_bridge = { (1 <<NF_BR_FORWARD ) | (1 <<NF_BR_LOCAL_OUT ) | (1 << NF_BR_POST_ROUTING), + .hooks = { + [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, + [NF_BR_LOCAL_IN] = nft_do_chain_bridge, + [NF_BR_FORWARD] = nft_do_chain_bridge, + [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, + [NF_BR_POST_ROUTING] = nft_do_chain_bridge, + }, }; static void nf_br_saveroute(const struct sk_buff *skb,
net/ipv4/netfilter/nf_tables_arp.c +4 -4
@@ -31,10 +31,6 @@ static struct nft_af_info nft_af_arp __read_mostly = { .family = NFPROTO_ARP, .nhooks = NF_ARP_NUMHOOKS, .owner = THIS_MODULE, - .hooks = { - [NF_ARP_IN] = nft_do_chain_arp, - [NF_ARP_OUT] = nft_do_chain_arp, - }, };static int nf_tables_arp_init_net (struct net *net)
@@ -72,6 +68,10 @@ static const struct nf_chain_type filter_arp = { .owner = THIS_MODULE, .hook_mask = (1 << NF_ARP_IN) | (1 << NF_ARP_OUT), + .hooks = { + [NF_ARP_IN] = nft_do_chain_arp, + [NF_ARP_OUT] = nft_do_chain_arp, + }, };static int __init nf_tables_arp_init (void )
net/ipv4/netfilter/nf_tables_ipv4.c +7 -7
@@ -49,13 +49,6 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = { .family = NFPROTO_IPV4, .nhooks = NF_INET_NUMHOOKS, .owner = THIS_MODULE, - .hooks = { - [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, - [NF_INET_LOCAL_OUT] = nft_ipv4_output, - [NF_INET_FORWARD] = nft_do_chain_ipv4, - [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, - [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, - }, };static int nf_tables_ipv4_init_net (struct net *net)
@@ -96,6 +89,13 @@ static const struct nf_chain_type filter_ipv4 = { (1 <<NF_INET_FORWARD ) | (1 <<NF_INET_PRE_ROUTING ) | (1 << NF_INET_POST_ROUTING), + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, + [NF_INET_LOCAL_OUT] = nft_ipv4_output, + [NF_INET_FORWARD] = nft_do_chain_ipv4, + [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, + [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, + }, };static int __init nf_tables_ipv4_init (void )
net/ipv6/netfilter/nf_tables_ipv6.c +7 -7
@@ -46,13 +46,6 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = { .family = NFPROTO_IPV6, .nhooks = NF_INET_NUMHOOKS, .owner = THIS_MODULE, - .hooks = { - [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, - [NF_INET_LOCAL_OUT] = nft_ipv6_output, - [NF_INET_FORWARD] = nft_do_chain_ipv6, - [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, - [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, - }, };static int nf_tables_ipv6_init_net (struct net *net)
@@ -93,6 +86,13 @@ static const struct nf_chain_type filter_ipv6 = { (1 <<NF_INET_FORWARD ) | (1 <<NF_INET_PRE_ROUTING ) | (1 << NF_INET_POST_ROUTING), + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, + [NF_INET_LOCAL_OUT] = nft_ipv6_output, + [NF_INET_FORWARD] = nft_do_chain_ipv6, + [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, + [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, + }, };static int __init nf_tables_ipv6_init (void )
net/netfilter/nf_tables_api.c +1 -5
@@ -1357,7 +1357,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,if (nla[NFTA_CHAIN_HOOK ]) {struct nft_chain_hook hook;struct nf_hook_ops *ops; -nf_hookfn *hookfn; err =nft_chain_parse_hook (net, nla, afi, &hook, create);if (err <0 )
@@ -1383,7 +1382,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,static_branch_inc (&nft_counters_enabled); } - hookfn = hook.type->hooks[hook.num]; basechain->type = hook.type; chain = &basechain->chain;
@@ -1392,10 +1390,8 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, ops->hooknum = hook.num; ops->priority = hook.priority; ops->priv = chain; - ops->hook = afi->hooks[ops->hooknum]; + ops->hook = hook.type->hooks[ops->hooknum]; ops->dev = hook.dev; -if (hookfn) - ops->hook = hookfn;if (basechain->type->type ==NFT_CHAIN_T_NAT ) ops->nat_hook = true;
net/netfilter/nf_tables_inet.c +7 -7
@@ -74,13 +74,6 @@ static struct nft_af_info nft_af_inet __read_mostly = { .family = NFPROTO_INET, .nhooks = NF_INET_NUMHOOKS, .owner = THIS_MODULE, - .hooks = { - [NF_INET_LOCAL_IN] = nft_do_chain_inet, - [NF_INET_LOCAL_OUT] = nft_inet_output, - [NF_INET_FORWARD] = nft_do_chain_inet, - [NF_INET_PRE_ROUTING] = nft_do_chain_inet, - [NF_INET_POST_ROUTING] = nft_do_chain_inet, - }, };static int __net_init nf_tables_inet_init_net (struct net *net)
@@ -121,6 +114,13 @@ static const struct nf_chain_type filter_inet = { (1 <<NF_INET_FORWARD ) | (1 <<NF_INET_PRE_ROUTING ) | (1 << NF_INET_POST_ROUTING), + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_inet, + [NF_INET_LOCAL_OUT] = nft_inet_output, + [NF_INET_FORWARD] = nft_do_chain_inet, + [NF_INET_PRE_ROUTING] = nft_do_chain_inet, + [NF_INET_POST_ROUTING] = nft_do_chain_inet, + }, };static int __init nf_tables_inet_init (void )
net/netfilter/nf_tables_netdev.c +3 -3
@@ -43,9 +43,6 @@ static struct nft_af_info nft_af_netdev __read_mostly = { .nhooks = NF_NETDEV_NUMHOOKS, .owner = THIS_MODULE, .flags = NFT_AF_NEEDS_DEV, - .hooks = { - [NF_NETDEV_INGRESS] = nft_do_chain_netdev, - }, };static int nf_tables_netdev_init_net (struct net *net)
@@ -82,6 +79,9 @@ static const struct nf_chain_type nft_filter_chain_netdev = { .family = NFPROTO_NETDEV, .owner = THIS_MODULE, .hook_mask = (1 << NF_NETDEV_INGRESS), + .hooks = { + [NF_NETDEV_INGRESS] = nft_do_chain_netdev, + }, }; static void nft_netdev_event(unsigned long event, struct net_device *dev,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 32/52 netfilter: connlimit: split xt_connlimit into front and backend
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
This allows to reuse xt_connlimit infrastructure from nf_tables. The upcoming nf_tables frontend can just pass in an nftables register as input key, this allows limiting by any nft-supported key, including concatenations.
For xt_connlimit, pass in the zone and the ip/ipv6 address.
With help from Yi-Hung Wei.
--- include/net/netfilter/nf_conntrack_count.h | 17 ++ include/uapi/linux/netfilter/xt_connlimit.h | 2 +- net/netfilter/Kconfig | 3 + net/netfilter/Makefile | 2 + net/netfilter/nf_conncount.c | 373 ++++++++++++++++++++++++++++ net/netfilter/xt_connlimit.c | 369 ++------------------------- 6 files changed, 420 insertions(+), 346 deletions(-) create mode 100644 include/net/netfilter/nf_conntrack_count.h create mode 100644 net/netfilter/nf_conncount.c
include/net/netfilter/nf_conntrack_count.h new file +17 -0
@@ -0,0 +1,17 @@ +#ifndef _NF_CONNTRACK_COUNT_H +#define _NF_CONNTRACK_COUNT_H + +struct nf_conncount_data ; + +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, +struct nf_conncount_data *data); + +unsigned int nf_conncount_count (struct net *net, +struct nf_conncount_data *data, +const u32 *key, +unsigned int family, +const struct nf_conntrack_tuple *tuple, +const struct nf_conntrack_zone *zone); +#endif
include/uapi/linux/netfilter/xt_connlimit.h +1 -1
@@ -27,7 +27,7 @@ struct xt_connlimit_info {__u32 flags;/* Used internally by the kernel */ - struct xt_connlimit_data *data __attribute__((aligned(8))); + struct nf_conncount_data *data __attribute__((aligned(8))); };#endif /* _XT_CONNLIMIT_H */
net/netfilter/Kconfig +3 -0
@@ -68,6 +68,8 @@ config NF_LOG_NETDEV select NF_LOG_COMMON if NF_CONNTRACK +config NETFILTER_CONNCOUNT + tristate config NF_CONNTRACK_MARK bool 'Connection mark tracking support'
@@ -1126,6 +1128,7 @@ config NETFILTER_XT_MATCH_CONNLIMIT tristate '"connlimit" match support' depends on NF_CONNTRACK depends on NETFILTER_ADVANCED + select NETFILTER_CONNCOUNT ---help--- This match allows you to match against the number of parallel connections to a server per client IP address (or address block).
net/netfilter/Makefile +2 -0
@@ -67,6 +67,8 @@ obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o # SYNPROXY obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o +obj-$(CONFIG_NETFILTER_CONNCOUNT) += nf_conncount.o + # generic packet duplication from netdev family obj-$(CONFIG_NF_DUP_NETDEV) += nf_dup_netdev.o
net/netfilter/nf_conncount.c new file +373 -0
373 lines not on this page · raw message
net/netfilter/xt_connlimit.c +24 -345
445 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 33/52 netfilter: move checksum indirection to struct nf_ipv6_ops
In reply to Pablo Neira AyusoWe cannot make a direct call to nf_ip6_checksum() because that would result in autoloading the 'ipv6' module because of symbol dependencies. Therefore, define checksum indirection in nf_ipv6_ops where this really belongs to.
For IPv4, we can indeed make a direct function call, which is faster, given IPv4 is built-in in the networking code by default. Still, CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline stub for IPv4 in such case.
--- include/linux/netfilter.h | 19 +++---------------- include/linux/netfilter_ipv4.h | 10 ++++++++++ include/linux/netfilter_ipv6.h | 2 ++ net/bridge/netfilter/nf_tables_bridge.c | 7 ------- net/ipv4/netfilter.c | 1 - net/ipv6/netfilter.c | 4 ++-- net/netfilter/Makefile | 2 +- net/netfilter/utils.c | 26 ++++++++++++++++++++++++++ 8 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 net/netfilter/utils.c
include/linux/netfilter.h +3 -16
@@ -311,8 +311,6 @@ struct nf_queue_entry;struct nf_afinfo {unsigned short family; -__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,
@@ -333,20 +331,9 @@ static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family)return rcu_dereference (nf_afinfo[family]); } -static inline __sum16 -nf_checksum (struct sk_buff *skb,unsigned int hook,unsigned int dataoff, -u_int8_t protocol,unsigned short family) -{ -const struct nf_afinfo *afinfo; -__sum16 csum =0 ; - -rcu_read_lock (); - afinfo =nf_get_afinfo (family); -if (afinfo) - csum = afinfo->checksum (skb, hook, dataoff, protocol); -rcu_read_unlock (); -return csum; -} +__sum16 nf_checksum (struct sk_buff *skb,unsigned int hook, +unsigned int dataoff,u_int8_t protocol, +unsigned short family); static inline __sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
include/linux/netfilter_ipv4.h +10 -0
@@ -7,6 +7,16 @@#include <uapi/linux/netfilter_ipv4.h> int ip_route_me_harder (struct net *net,struct sk_buff *skb,unsigned addr_type); + +#ifdef CONFIG_INET __sum16 nf_ip_checksum (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,u_int8_t protocol); +#else +static inline __sum16 nf_ip_checksum (struct sk_buff *skb,unsigned int hook, +unsigned int dataoff,u_int8_t protocol) +{ +return 0 ; +} +#endif /* CONFIG_INET */ +#endif /*__LINUX_IP_NETFILTER_H*/
include/linux/netfilter_ipv6.h +2 -0
@@ -19,6 +19,8 @@ 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); };#ifdef CONFIG_NETFILTER
net/bridge/netfilter/nf_tables_bridge.c +0 -7
@@ -106,12 +106,6 @@ static int nf_br_reroute(struct net *net, struct sk_buff *skb,return 0 ; } -static __sum16 nf_br_checksum (struct sk_buff *skb,unsigned int hook, -unsigned int dataoff,u_int8_t protocol) -{ -return 0 ; -} -static __sum16 nf_br_checksum_partial (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,unsigned int len,u_int8_t protocol)
@@ -127,7 +121,6 @@ static int nf_br_route(struct net *net, struct dst_entry **dst,static const struct nf_afinfo nf_br_afinfo = { .family =AF_BRIDGE , - .checksum = nf_br_checksum, .checksum_partial = nf_br_checksum_partial, .route = nf_br_route, .saveroute = nf_br_saveroute,
net/ipv4/netfilter.c +0 -1
@@ -188,7 +188,6 @@ static int nf_ip_route(struct net *net, struct dst_entry **dst,static const struct nf_afinfo nf_ip_afinfo = { .family =AF_INET , - .checksum = nf_ip_checksum, .checksum_partial = nf_ip_checksum_partial, .route = nf_ip_route, .saveroute = nf_ip_saveroute,
net/ipv6/netfilter.c +2 -2
@@ -192,12 +192,12 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,static const struct nf_ipv6_ops ipv6ops = { .chk_addr = ipv6_chk_addr, .route_input = ip6_route_input, - .fragment = ip6_fragment + .fragment = ip6_fragment, + .checksum = nf_ip6_checksum, };static const struct nf_afinfo nf_ip6_afinfo = { .family =AF_INET6 , - .checksum = nf_ip6_checksum, .checksum_partial = nf_ip6_checksum_partial, .route = nf_ip6_route, .saveroute = nf_ip6_saveroute,
net/netfilter/Makefile +1 -1
@@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o +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-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o
net/netfilter/utils.c new file +26 -0
@@ -0,0 +1,26 @@ +#include <linux/kernel.h> +#include <linux/netfilter.h> +#include <linux/netfilter_ipv4.h> +#include <linux/netfilter_ipv6.h> + +__sum16 nf_checksum (struct sk_buff *skb,unsigned int hook, +unsigned int dataoff,u_int8_t protocol, +unsigned short family) +{ +const struct nf_ipv6_ops *v6ops; +__sum16 csum =0 ; + +switch (family) { +case AF_INET : + csum =nf_ip_checksum (skb, hook, dataoff, protocol); +break ; +case AF_INET6 : + v6ops =rcu_dereference (nf_ipv6_ops); +if (v6ops) + csum = v6ops->checksum (skb, hook, dataoff, protocol); +break ; + } + +return csum; +} +EXPORT_SYMBOL_GPL (nf_checksum);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 34/52 netfilter: move checksum_partial indirection to struct nf_ipv6_ops
In reply to Pablo Neira AyusoWe cannot make a direct call to nf_ip6_checksum_partial() because that would result in autoloading the 'ipv6' module because of symbol dependencies. Therefore, define checksum_partial indirection in nf_ipv6_ops where this really belongs to.
For IPv4, we can indeed make a direct function call, which is faster, given IPv4 is built-in in the networking code by default. Still, CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline stub for IPv4 in such case.
--- include/linux/netfilter.h | 24 +++--------------------- include/linux/netfilter_ipv4.h | 11 +++++++++++ include/linux/netfilter_ipv6.h | 3 +++ net/bridge/netfilter/nf_tables_bridge.c | 8 -------- net/ipv4/netfilter.c | 8 ++++---- net/ipv6/netfilter.c | 10 +++++----- net/netfilter/utils.c | 24 ++++++++++++++++++++++++ 7 files changed, 50 insertions(+), 38 deletions(-)
include/linux/netfilter.h +3 -21
@@ -311,11 +311,6 @@ struct nf_queue_entry;struct nf_afinfo {unsigned short family; -__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); void (*saveroute)(const struct sk_buff *skb,
@@ -335,22 +330,9 @@ __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol, unsigned short family); -static inline __sum16 -nf_checksum_partial (struct sk_buff *skb,unsigned int hook, -unsigned int dataoff,unsigned int len, -u_int8_t protocol,unsigned short family) -{ -const struct nf_afinfo *afinfo; -__sum16 csum =0 ; - -rcu_read_lock (); - afinfo =nf_get_afinfo (family); -if (afinfo) - csum = afinfo->checksum_partial (skb, hook, dataoff, len, - protocol); -rcu_read_unlock (); -return csum; -} +__sum16 nf_checksum_partial (struct sk_buff *skb,unsigned int hook, +unsigned int dataoff,unsigned int len, +u_int8_t protocol,unsigned short family);int nf_register_afinfo (const struct nf_afinfo *afinfo);void nf_unregister_afinfo (const struct nf_afinfo *afinfo);
include/linux/netfilter_ipv4.h +11 -0
@@ -11,12 +11,23 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type)#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);#else static inline __sum16 nf_ip_checksum (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,u_int8_t protocol) {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 ; +}#endif /* CONFIG_INET */ #endif /*__LINUX_IP_NETFILTER_H*/
include/linux/netfilter_ipv6.h +3 -0
@@ -21,6 +21,9 @@ struct nf_ipv6_ops { 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); };#ifdef CONFIG_NETFILTER
net/bridge/netfilter/nf_tables_bridge.c +0 -8
@@ -106,13 +106,6 @@ static int nf_br_reroute(struct net *net, struct sk_buff *skb,return 0 ; } -static __sum16 nf_br_checksum_partial (struct sk_buff *skb,unsigned int hook, -unsigned int dataoff,unsigned int len, -u_int8_t protocol) -{ -return 0 ; -} -static int nf_br_route (struct net *net,struct dst_entry **dst,struct flowi *fl,bool strict__always_unused ) {
@@ -121,7 +114,6 @@ static int nf_br_route(struct net *net, struct dst_entry **dst,static const struct nf_afinfo nf_br_afinfo = { .family =AF_BRIDGE , - .checksum_partial = nf_br_checksum_partial, .route = nf_br_route, .saveroute = nf_br_saveroute, .reroute = nf_br_reroute,
net/ipv4/netfilter.c +4 -4
@@ -155,9 +155,9 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, }EXPORT_SYMBOL (nf_ip_checksum); -static __sum16 nf_ip_checksum_partial (struct sk_buff *skb,unsigned int hook, -unsigned int dataoff,unsigned int len, -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) {const struct iphdr *iph =ip_hdr (skb);__sum16 csum =0 ;
@@ -175,6 +175,7 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, }return csum; } +EXPORT_SYMBOL_GPL (nf_ip_checksum_partial);static int nf_ip_route (struct net *net,struct dst_entry **dst,struct flowi *fl,bool strict__always_unused )
@@ -188,7 +189,6 @@ static int nf_ip_route(struct net *net, struct dst_entry **dst,static const struct nf_afinfo nf_ip_afinfo = { .family =AF_INET , - .checksum_partial = nf_ip_checksum_partial, .route = nf_ip_route, .saveroute = nf_ip_saveroute, .reroute = nf_ip_reroute,
net/ipv6/netfilter.c +5 -5
@@ -190,15 +190,15 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook, };static const struct nf_ipv6_ops ipv6ops = { - .chk_addr = ipv6_chk_addr, - .route_input = ip6_route_input, - .fragment = ip6_fragment, - .checksum = nf_ip6_checksum, + .chk_addr = ipv6_chk_addr, + .route_input = ip6_route_input, + .fragment = ip6_fragment, + .checksum = nf_ip6_checksum, + .checksum_partial = nf_ip6_checksum_partial, };static const struct nf_afinfo nf_ip6_afinfo = { .family =AF_INET6 , - .checksum_partial = nf_ip6_checksum_partial, .route = nf_ip6_route, .saveroute = nf_ip6_saveroute, .reroute = nf_ip6_reroute,
net/netfilter/utils.c +24 -0
@@ -24,3 +24,27 @@ __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook,return csum; }EXPORT_SYMBOL_GPL (nf_checksum); + +__sum16 nf_checksum_partial (struct sk_buff *skb,unsigned int hook, +unsigned int dataoff,unsigned int len, +u_int8_t protocol,unsigned short family) +{ +const struct nf_ipv6_ops *v6ops; +__sum16 csum =0 ; + +switch (family) { +case AF_INET : + csum =nf_ip_checksum_partial (skb, hook, dataoff, len, + protocol); +break ; +case AF_INET6 : + v6ops =rcu_dereference (nf_ipv6_ops); +if (v6ops) + csum = v6ops->checksum_partial (skb, hook, dataoff, len, + protocol); +break ; + } + +return csum; +} +EXPORT_SYMBOL_GPL (nf_checksum_partial);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 35/52 netfilter: remove saveroute indirection in struct nf_afinfo
In reply to Pablo Neira AyusoThis is only used by nf_queue.c and this function comes with no symbol dependencies with IPv6, it just refers to structure layouts. Therefore, we can replace it by a direct function call from where it belongs.
--- include/linux/netfilter.h | 2 -- include/linux/netfilter_ipv4.h | 10 ++++++++ include/linux/netfilter_ipv6.h | 9 +++++++ net/bridge/netfilter/nf_tables_bridge.c | 6 ----- net/ipv4/netfilter.c | 28 ---------------------- net/ipv6/netfilter.c | 26 -------------------- net/netfilter/nf_queue.c | 42 ++++++++++++++++++++++++++++++++- 7 files changed, 60 insertions(+), 63 deletions(-)
include/linux/netfilter.h +0 -2
@@ -313,8 +313,6 @@ struct nf_afinfo {unsigned short family;int (*route)(struct net *net,struct dst_entry **dst,struct flowi *fl,bool strict); -void (*saveroute)(const struct sk_buff *skb, -struct nf_queue_entry *entry);int (*reroute)(struct net *net,struct sk_buff *skb,const struct nf_queue_entry *entry);int route_key_size;
include/linux/netfilter_ipv4.h +10 -0
@@ -6,6 +6,16 @@#include <uapi/linux/netfilter_ipv4.h> +/* Extra routing may needed on local out, as the QUEUE target never returns +* control to the table. +*/ +struct ip_rt_info { +__be32 daddr; +__be32 saddr; +u_int8_t tos; +u_int32_t mark; +}; +int ip_route_me_harder (struct net *net,struct sk_buff *skb,unsigned addr_type);#ifdef CONFIG_INET
include/linux/netfilter_ipv6.h +9 -0
@@ -9,6 +9,15 @@#include <uapi/linux/netfilter_ipv6.h> +/* Extra routing may needed on local out, as the QUEUE target never returns +* control to the table. +*/ +struct ip6_rt_info { +struct in6_addr daddr; +struct in6_addr saddr; +u_int32_t mark; +}; +/* * Hook functions for ipv6 to allow xt_* modules to be built-in even * if IPv6 is a module.
net/bridge/netfilter/nf_tables_bridge.c +0 -6
@@ -95,11 +95,6 @@ static const struct nf_chain_type filter_bridge = { }, }; -static void nf_br_saveroute (const struct sk_buff *skb, -struct nf_queue_entry *entry) -{ -} -static int nf_br_reroute (struct net *net,struct sk_buff *skb,const struct nf_queue_entry *entry) {
@@ -115,7 +110,6 @@ static int nf_br_route(struct net *net, struct dst_entry **dst,static const struct nf_afinfo nf_br_afinfo = { .family =AF_BRIDGE , .route = nf_br_route, - .saveroute = nf_br_saveroute, .reroute = nf_br_reroute, .route_key_size =0 , };
net/ipv4/netfilter.c +0 -28
@@ -80,33 +80,6 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t }EXPORT_SYMBOL (ip_route_me_harder); -/* -* Extra routing may needed on local out, as the QUEUE target never -* returns control to the table. -*/ - -struct ip_rt_info { -__be32 daddr; -__be32 saddr; -u_int8_t tos; -u_int32_t mark; -}; - -static void nf_ip_saveroute (const struct sk_buff *skb, -struct nf_queue_entry *entry) -{ -struct ip_rt_info *rt_info =nf_queue_entry_reroute (entry); - -if (entry->state.hook ==NF_INET_LOCAL_OUT ) { -const struct iphdr *iph =ip_hdr (skb); - - rt_info->tos = iph->tos; - rt_info->daddr = iph->daddr; - rt_info->saddr = iph->saddr; - rt_info->mark = skb->mark; - } -} -static int nf_ip_reroute (struct net *net,struct sk_buff *skb,const struct nf_queue_entry *entry) {
@@ -190,7 +163,6 @@ static int nf_ip_route(struct net *net, struct dst_entry **dst,static const struct nf_afinfo nf_ip_afinfo = { .family =AF_INET , .route = nf_ip_route, - .saveroute = nf_ip_saveroute, .reroute = nf_ip_reroute, .route_key_size =sizeof (struct ip_rt_info ), };
net/ipv6/netfilter.c +0 -26
@@ -68,31 +68,6 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb) }EXPORT_SYMBOL (ip6_route_me_harder); -/* -* Extra routing may needed on local out, as the QUEUE target never -* returns control to the table. -*/ - -struct ip6_rt_info { -struct in6_addr daddr; -struct in6_addr saddr; -u_int32_t mark; -}; - -static void nf_ip6_saveroute (const struct sk_buff *skb, -struct nf_queue_entry *entry) -{ -struct ip6_rt_info *rt_info =nf_queue_entry_reroute (entry); - -if (entry->state.hook ==NF_INET_LOCAL_OUT ) { -const struct ipv6hdr *iph =ipv6_hdr (skb); - - rt_info->daddr = iph->daddr; - rt_info->saddr = iph->saddr; - rt_info->mark = skb->mark; - } -} -static int nf_ip6_reroute (struct net *net,struct sk_buff *skb,const struct nf_queue_entry *entry) {
@@ -200,7 +175,6 @@ static const struct nf_ipv6_ops ipv6ops = {static const struct nf_afinfo nf_ip6_afinfo = { .family =AF_INET6 , .route = nf_ip6_route, - .saveroute = nf_ip6_saveroute, .reroute = nf_ip6_reroute, .route_key_size =sizeof (struct ip6_rt_info ), };
net/netfilter/nf_queue.c +41 -1
60 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 36/52 netfilter: move route indirection to struct nf_ipv6_ops
In reply to Pablo Neira AyusoWe cannot make a direct call to nf_ip6_route() because that would result in autoloading the 'ipv6' module because of symbol dependencies. Therefore, define route indirection in nf_ipv6_ops where this really belongs to.
For IPv4, we can indeed make a direct function call, which is faster, given IPv4 is built-in in the networking code by default. Still, CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline stub for IPv4 in such case.
--- include/linux/netfilter.h | 4 ++-- include/linux/netfilter_ipv4.h | 7 +++++++ include/linux/netfilter_ipv6.h | 2 ++ net/bridge/netfilter/nf_tables_bridge.c | 7 ------- net/ipv4/netfilter.c | 6 +++--- net/ipv6/netfilter.c | 2 +- net/ipv6/netfilter/nft_fib_ipv6.c | 12 +++++------- net/netfilter/nf_conntrack_h323_main.c | 30 +++++++++++++++--------------- net/netfilter/nft_rt.c | 15 +++++---------- net/netfilter/utils.c | 21 +++++++++++++++++++++ net/netfilter/xt_TCPMSS.c | 5 +---- net/netfilter/xt_addrtype.c | 15 ++++++--------- 12 files changed, 68 insertions(+), 58 deletions(-)
include/linux/netfilter.h +2 -2
@@ -311,8 +311,6 @@ struct nf_queue_entry;struct nf_afinfo {unsigned short family; -int (*route)(struct net *net,struct dst_entry **dst, -struct flowi *fl,bool strict);int (*reroute)(struct net *net,struct sk_buff *skb,const struct nf_queue_entry *entry);int route_key_size;
@@ -331,6 +329,8 @@ __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook,__sum16 nf_checksum_partial (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,unsigned int len,u_int8_t protocol,unsigned short family); +int nf_route (struct net *net,struct dst_entry **dst,struct flowi *fl, +bool strict,unsigned short family);int nf_register_afinfo (const struct nf_afinfo *afinfo);void nf_unregister_afinfo (const struct nf_afinfo *afinfo);
include/linux/netfilter_ipv4.h +7 -0
@@ -24,6 +24,8 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,__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);#else static inline __sum16 nf_ip_checksum (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,u_int8_t protocol)
@@ -38,6 +40,11 @@ static inline __sum16 nf_ip_checksum_partial(struct sk_buff *skb, {return 0 ; } +static inline int nf_ip_route (struct net *net,struct dst_entry **dst, +struct flowi *fl,bool strict) +{ +return -EOPNOTSUPP ; +}#endif /* CONFIG_INET */ #endif /*__LINUX_IP_NETFILTER_H*/
include/linux/netfilter_ipv6.h +2 -0
@@ -33,6 +33,8 @@ struct nf_ipv6_ops {__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); };#ifdef CONFIG_NETFILTER
net/bridge/netfilter/nf_tables_bridge.c +0 -7
@@ -101,15 +101,8 @@ static int nf_br_reroute(struct net *net, struct sk_buff *skb,return 0 ; } -static int nf_br_route (struct net *net,struct dst_entry **dst, -struct flowi *fl,bool strict__always_unused ) -{ -return 0 ; -} -static const struct nf_afinfo nf_br_afinfo = { .family =AF_BRIDGE , - .route = nf_br_route, .reroute = nf_br_reroute, .route_key_size =0 , };
net/ipv4/netfilter.c +3 -3
@@ -150,8 +150,8 @@ __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, }EXPORT_SYMBOL_GPL (nf_ip_checksum_partial); -static int nf_ip_route (struct net *net,struct dst_entry **dst, -struct flowi *fl,bool strict__always_unused ) +int nf_ip_route (struct net *net,struct dst_entry **dst,struct flowi *fl, +bool strict__always_unused ) {struct rtable *rt =ip_route_output_key (net, &fl->u.ip4);if (IS_ERR (rt))
@@ -159,10 +159,10 @@ static int nf_ip_route(struct net *net, struct dst_entry **dst, *dst = &rt->dst;return 0 ; } +EXPORT_SYMBOL_GPL (nf_ip_route);static const struct nf_afinfo nf_ip_afinfo = { .family =AF_INET , - .route = nf_ip_route, .reroute = nf_ip_reroute, .route_key_size =sizeof (struct ip_rt_info ), };
net/ipv6/netfilter.c +1 -1
@@ -170,11 +170,11 @@ static const struct nf_ipv6_ops ipv6ops = { .fragment = ip6_fragment, .checksum = nf_ip6_checksum, .checksum_partial = nf_ip6_checksum_partial, + .route = nf_ip6_route, };static const struct nf_afinfo nf_ip6_afinfo = { .family =AF_INET6 , - .route = nf_ip6_route, .reroute = nf_ip6_reroute, .route_key_size =sizeof (struct ip6_rt_info ), };
net/ipv6/netfilter/nft_fib_ipv6.c +5 -7
@@ -60,7 +60,6 @@ static u32 __nft_fib6_eval_type(const struct nft_fib *priv, {const struct net_device *dev =NULL ;const struct nf_ipv6_ops *v6ops; -const struct nf_afinfo *afinfo;int route_err, addrtype;struct rt6_info *rt;struct flowi6 fl6 = {
@@ -69,8 +68,8 @@ static u32 __nft_fib6_eval_type(const struct nft_fib *priv, };u32 ret =0 ; - afinfo =nf_get_afinfo (NFPROTO_IPV6 ); -if (!afinfo) + v6ops =nf_get_ipv6_ops (); +if (!v6ops)return RTN_UNREACHABLE ;if (priv->flags &NFTA_FIB_F_IIF )
@@ -80,12 +79,11 @@ static u32 __nft_fib6_eval_type(const struct nft_fib *priv,nft_fib6_flowi_init (&fl6, priv, pkt, dev, iph); - v6ops =nf_get_ipv6_ops (); -if (dev && v6ops && v6ops->chk_addr (nft_net (pkt), &fl6.daddr, dev, true)) +if (dev && v6ops->chk_addr (nft_net (pkt), &fl6.daddr, dev, true)) ret =RTN_LOCAL ; - route_err = afinfo->route (nft_net (pkt), (struct dst_entry **)&rt, -flowi6_to_flowi (&fl6), false); + route_err = v6ops->route (nft_net (pkt), (struct dst_entry **)&rt, +flowi6_to_flowi (&fl6), false);if (route_err) goto err;
net/netfilter/nf_conntrack_h323_main.c +15 -15
@@ -24,6 +24,7 @@#include <linux/skbuff.h> #include <net/route.h> #include <net/ip6_route.h> +#include <linux/netfilter_ipv6.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.h>
@@ -721,14 +722,8 @@ static int callforward_do_filter(struct net *net,const union nf_inet_addr *dst, u_int8_t family) { -const struct nf_afinfo *afinfo; int ret = 0; -/* rcu_read_lock()ed by nf_hook_thresh */ - afinfo =nf_get_afinfo (family); -if (!afinfo) -return 0 ; -switch (family) {case AF_INET : {struct flowi4 fl1, fl2;
@@ -739,10 +734,10 @@ static int callforward_do_filter(struct net *net,memset (&fl2,0 ,sizeof (fl2)); fl2.daddr = dst->ip; -if (!afinfo->route (net, (struct dst_entry **)&rt1, -flowi4_to_flowi (&fl1), false)) { -if (!afinfo->route (net, (struct dst_entry **)&rt2, -flowi4_to_flowi (&fl2), false)) { +if (!nf_ip_route (net, (struct dst_entry **)&rt1, +flowi4_to_flowi (&fl1), false)) { +if (!nf_ip_route (net, (struct dst_entry **)&rt2, +flowi4_to_flowi (&fl2), false)) {if (rt_nexthop (rt1, fl1.daddr) ==rt_nexthop (rt2, fl2.daddr) && rt1->dst.dev == rt2->dst.dev)
@@ -755,18 +750,23 @@ static int callforward_do_filter(struct net *net, }#if IS_ENABLED (CONFIG_NF_CONNTRACK_IPV6 )case AF_INET6 : { -struct flowi6 fl1, fl2; +const struct nf_ipv6_ops *v6ops;struct rt6_info *rt1, *rt2; +struct flowi6 fl1, fl2; + + v6ops =nf_get_ipv6_ops (); +if (!v6ops) +return 0 ;memset (&fl1,0 ,sizeof (fl1)); fl1.daddr = src->in6;memset (&fl2,0 ,sizeof (fl2)); fl2.daddr = dst->in6; -if (!afinfo->route (net, (struct dst_entry **)&rt1, -flowi6_to_flowi (&fl1), false)) { -if (!afinfo->route (net, (struct dst_entry **)&rt2, -flowi6_to_flowi (&fl2), false)) { +if (!v6ops->route (net, (struct dst_entry **)&rt1, +flowi6_to_flowi (&fl1), false)) { +if (!v6ops->route (net, (struct dst_entry **)&rt2, +flowi6_to_flowi (&fl2), false)) {if (ipv6_addr_equal (rt6_nexthop (rt1, &fl1.daddr),rt6_nexthop (rt2, &fl2.daddr)) && rt1->dst.dev == rt2->dst.dev)
net/netfilter/nft_rt.c +5 -10
@@ -27,7 +27,7 @@ static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skb {u32 minlen =sizeof (struct ipv6hdr ), mtu =dst_mtu (skbdst);const struct sk_buff *skb = pkt->skb; -const struct nf_afinfo *ai; +struct dst_entry *dst =NULL ;struct flowi fl;memset (&fl,0 ,sizeof (fl));
@@ -43,15 +43,10 @@ static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skbbreak ; } - ai =nf_get_afinfo (nft_pf (pkt)); -if (ai) { -struct dst_entry *dst =NULL ; - - ai->route (nft_net (pkt), &dst, &fl, false); -if (dst) { - mtu =min (mtu,dst_mtu (dst)); -dst_release (dst); - } +nf_route (nft_net (pkt), &dst, &fl, false,nft_pf (pkt)); +if (dst) { + mtu =min (mtu,dst_mtu (dst)); +dst_release (dst); }if (mtu <= minlen || mtu >0xffff )
net/netfilter/utils.c +21 -0
@@ -48,3 +48,24 @@ __sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,return csum; }EXPORT_SYMBOL_GPL (nf_checksum_partial); + +int nf_route (struct net *net,struct dst_entry **dst,struct flowi *fl, +bool strict,unsigned short family) +{ +const struct nf_ipv6_ops *v6ops; +int ret =0 ; + +switch (family) { +case AF_INET : + ret =nf_ip_route (net, dst, fl, strict); +break ; +case AF_INET6 : + v6ops =rcu_dereference (nf_ipv6_ops); +if (v6ops) + ret = v6ops->route (net, dst, fl, strict); +break ; + } + +return ret; +} +EXPORT_SYMBOL_GPL (nf_route);
net/netfilter/xt_TCPMSS.c +1 -4
@@ -48,7 +48,6 @@ static u_int32_t tcpmss_reverse_mtu(struct net *net, unsigned int family) {struct flowi fl; -const struct nf_afinfo *ai;struct rtable *rt =NULL ;u_int32_t mtu = ~0U ;
@@ -62,10 +61,8 @@ static u_int32_t tcpmss_reverse_mtu(struct net *net,memset (fl6,0 ,sizeof (*fl6)); fl6->daddr =ipv6_hdr (skb)->saddr; } - ai =nf_get_afinfo (family); -if (ai !=NULL ) - ai->route (net, (struct dst_entry **)&rt, &fl, false); +nf_route (net, (struct dst_entry **)&rt, &fl, false, family);if (rt !=NULL ) { mtu =dst_mtu (&rt->dst);dst_release (&rt->dst);
net/netfilter/xt_addrtype.c +6 -9
@@ -36,7 +36,7 @@ MODULE_ALIAS("ip6t_addrtype");static u32 match_lookup_rt6 (struct net *net,const struct net_device *dev,const struct in6_addr *addr,u16 mask) { -const struct nf_afinfo *afinfo; +const struct nf_ipv6_ops *v6ops;struct flowi6 flow;struct rt6_info *rt;u32 ret =0 ;
@@ -47,17 +47,14 @@ static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,if (dev) flow.flowi6_oif = dev->ifindex; - afinfo =nf_get_afinfo (NFPROTO_IPV6 ); -if (afinfo !=NULL ) { -const struct nf_ipv6_ops *v6ops; - + v6ops =nf_get_ipv6_ops (); +if (v6ops) {if (dev && (mask &XT_ADDRTYPE_LOCAL )) { - v6ops =nf_get_ipv6_ops (); -if (v6ops && v6ops->chk_addr (net, addr, dev, true)) +if (v6ops->chk_addr (net, addr, dev, true)) ret =XT_ADDRTYPE_LOCAL ; } - route_err = afinfo->route (net, (struct dst_entry **)&rt, -flowi6_to_flowi (&flow), false); + route_err = v6ops->route (net, (struct dst_entry **)&rt, +flowi6_to_flowi (&flow), false); }else { route_err =1 ; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 37/52 netfilter: move reroute indirection to struct nf_ipv6_ops
In reply to Pablo Neira AyusoWe cannot make a direct call to nf_ip6_reroute() because that would result in autoloading the 'ipv6' module because of symbol dependencies. Therefore, define reroute indirection in nf_ipv6_ops where this really belongs to.
For IPv4, we can indeed make a direct function call, which is faster, given IPv4 is built-in in the networking code by default. Still, CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline stub for IPv4 in such case.
--- include/linux/netfilter.h | 3 +-- include/linux/netfilter_ipv4.h | 8 ++++++++ include/linux/netfilter_ipv6.h | 3 +++ net/bridge/netfilter/nf_tables_bridge.c | 7 ------- net/ipv4/netfilter.c | 8 ++++---- net/ipv6/netfilter.c | 6 +++--- net/netfilter/nf_queue.c | 4 +--- net/netfilter/utils.c | 19 +++++++++++++++++++ 8 files changed, 39 insertions(+), 19 deletions(-)
include/linux/netfilter.h +1 -2
@@ -311,8 +311,6 @@ struct nf_queue_entry;struct nf_afinfo {unsigned short family; -int (*reroute)(struct net *net,struct sk_buff *skb, -const struct nf_queue_entry *entry);int route_key_size; };
@@ -331,6 +329,7 @@ __sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook, u_int8_t protocol, unsigned short family);int nf_route (struct net *net,struct dst_entry **dst,struct flowi *fl,bool strict,unsigned short family); +int nf_reroute (struct sk_buff *skb,struct nf_queue_entry *entry);int nf_register_afinfo (const struct nf_afinfo *afinfo);void nf_unregister_afinfo (const struct nf_afinfo *afinfo);
include/linux/netfilter_ipv4.h +8 -0
@@ -18,6 +18,8 @@ struct ip_rt_info {int ip_route_me_harder (struct net *net,struct sk_buff *skb,unsigned addr_type); +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);
@@ -26,6 +28,7 @@ __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, 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);#else static inline __sum16 nf_ip_checksum (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,u_int8_t protocol)
@@ -45,6 +48,11 @@ static inline int nf_ip_route(struct net *net, struct dst_entry **dst, {return -EOPNOTSUPP ; } +static inline int nf_ip_reroute (struct sk_buff *skb, +const struct nf_queue_entry *entry) +{ +return -EOPNOTSUPP ; +}#endif /* CONFIG_INET */ #endif /*__LINUX_IP_NETFILTER_H*/
include/linux/netfilter_ipv6.h +3 -0
@@ -18,6 +18,8 @@ struct ip6_rt_info {u_int32_t mark; }; +struct nf_queue_entry ; +/* * Hook functions for ipv6 to allow xt_* modules to be built-in even * if IPv6 is a module.
@@ -35,6 +37,7 @@ struct nf_ipv6_ops { 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); };#ifdef CONFIG_NETFILTER
net/bridge/netfilter/nf_tables_bridge.c +0 -7
@@ -95,15 +95,8 @@ static const struct nf_chain_type filter_bridge = { }, }; -static int nf_br_reroute (struct net *net,struct sk_buff *skb, -const struct nf_queue_entry *entry) -{ -return 0 ; -} -static const struct nf_afinfo nf_br_afinfo = { .family =AF_BRIDGE , - .reroute = nf_br_reroute, .route_key_size =0 , };
net/ipv4/netfilter.c +4 -4
@@ -80,8 +80,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t }EXPORT_SYMBOL (ip_route_me_harder); -static int nf_ip_reroute (struct net *net,struct sk_buff *skb, -const struct nf_queue_entry *entry) +int nf_ip_reroute (struct sk_buff *skb,const struct nf_queue_entry *entry) {const struct ip_rt_info *rt_info =nf_queue_entry_reroute (entry);
@@ -92,10 +91,12 @@ static int nf_ip_reroute(struct net *net, struct sk_buff *skb, skb->mark == rt_info->mark && iph->daddr == rt_info->daddr && iph->saddr == rt_info->saddr)) -return ip_route_me_harder (net, skb,RTN_UNSPEC ); +return ip_route_me_harder (entry->state.net, skb, +RTN_UNSPEC ); }return 0 ; } +EXPORT_SYMBOL_GPL (nf_ip_reroute);__sum16 nf_ip_checksum (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,u_int8_t protocol)
@@ -163,7 +164,6 @@ EXPORT_SYMBOL_GPL(nf_ip_route);static const struct nf_afinfo nf_ip_afinfo = { .family =AF_INET , - .reroute = nf_ip_reroute, .route_key_size =sizeof (struct ip_rt_info ), };
net/ipv6/netfilter.c +3 -3
@@ -68,7 +68,7 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb) }EXPORT_SYMBOL (ip6_route_me_harder); -static int nf_ip6_reroute (struct net *net,struct sk_buff *skb, +static int nf_ip6_reroute (struct sk_buff *skb,const struct nf_queue_entry *entry) {struct ip6_rt_info *rt_info =nf_queue_entry_reroute (entry);
@@ -78,7 +78,7 @@ static int nf_ip6_reroute(struct net *net, struct sk_buff *skb,if (!ipv6_addr_equal (&iph->daddr, &rt_info->daddr) || !ipv6_addr_equal (&iph->saddr, &rt_info->saddr) || skb->mark != rt_info->mark) -return ip6_route_me_harder (net, skb); +return ip6_route_me_harder (entry->state.net, skb); }return 0 ; }
@@ -171,11 +171,11 @@ static const struct nf_ipv6_ops ipv6ops = { .checksum = nf_ip6_checksum, .checksum_partial = nf_ip6_checksum_partial, .route = nf_ip6_route, + .reroute = nf_ip6_reroute, };static const struct nf_afinfo nf_ip6_afinfo = { .family =AF_INET6 , - .reroute = nf_ip6_reroute, .route_key_size =sizeof (struct ip6_rt_info ), };
net/netfilter/nf_queue.c +1 -3
@@ -266,7 +266,6 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)const struct nf_hook_entry *hook_entry;const struct nf_hook_entries *hooks;struct sk_buff *skb = entry->skb; -const struct nf_afinfo *afinfo;const struct net *net;unsigned int i;int err;
@@ -293,8 +292,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) verdict =nf_hook_entry_hookfn (hook_entry, skb, &entry->state);if (verdict ==NF_ACCEPT ) { - afinfo =nf_get_afinfo (entry->state.pf); -if (!afinfo || afinfo->reroute (entry->state.net, skb, entry) <0 ) +if (nf_reroute (skb, entry) <0 ) verdict =NF_DROP ; }
net/netfilter/utils.c +19 -0
@@ -2,6 +2,7 @@#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv6.h> +#include <net/netfilter/nf_queue.h> __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol,
@@ -69,3 +70,21 @@ int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl,return ret; }EXPORT_SYMBOL_GPL (nf_route); + +int nf_reroute (struct sk_buff *skb,struct nf_queue_entry *entry) +{ +const struct nf_ipv6_ops *v6ops; +int ret =0 ; + +switch (entry->state.pf) { +case AF_INET : + ret =nf_ip_reroute (skb, entry); +break ; +case AF_INET6 : + v6ops =rcu_dereference (nf_ipv6_ops); +if (v6ops) + ret = v6ops->reroute (skb, entry); +break ; + } +return ret; +}
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 38/52 netfilter: remove route_key_size field in struct nf_afinfo
In reply to Pablo Neira AyusoThis is only needed by nf_queue, place this code where it belongs.
--- include/linux/netfilter.h | 1 - net/ipv4/netfilter.c | 1 - net/ipv6/netfilter.c | 1 - net/netfilter/nf_queue.c | 22 ++++++++++++++++------ 4 files changed, 16 insertions(+), 9 deletions(-)
include/linux/netfilter.h +0 -1
@@ -311,7 +311,6 @@ struct nf_queue_entry;struct nf_afinfo {unsigned short family; -int route_key_size; };extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO ];
net/ipv4/netfilter.c +0 -1
@@ -164,7 +164,6 @@ EXPORT_SYMBOL_GPL(nf_ip_route);static const struct nf_afinfo nf_ip_afinfo = { .family =AF_INET , - .route_key_size =sizeof (struct ip_rt_info ), };static int __init ipv4_netfilter_init (void )
net/ipv6/netfilter.c +0 -1
@@ -176,7 +176,6 @@ static const struct nf_ipv6_ops ipv6ops = {static const struct nf_afinfo nf_ip6_afinfo = { .family =AF_INET6 , - .route_key_size =sizeof (struct ip6_rt_info ), };int __init ipv6_netfilter_init (void )
net/netfilter/nf_queue.c +16 -6
@@ -15,6 +15,8 @@#include <linux/netfilter_bridge.h> #include <linux/seq_file.h> #include <linux/rcupdate.h> +#include <linux/netfilter_ipv4.h> +#include <linux/netfilter_ipv6.h> #include <net/protocol.h> #include <net/netfilter/nf_queue.h> #include <net/dst.h>
@@ -145,9 +147,9 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, {int status = -ENOENT ;struct nf_queue_entry *entry =NULL ; -const struct nf_afinfo *afinfo;const struct nf_queue_handler *qh;struct net *net = state->net; +unsigned int route_key_size;/* QUEUE == DROP if no one is waiting, to be safe. */ qh =rcu_dereference (net->nf.queue_handler);
@@ -156,11 +158,19 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, goto err; } - afinfo =nf_get_afinfo (state->pf); -if (!afinfo) - goto err; +switch (state->pf) { +case AF_INET : + route_key_size =sizeof (struct ip_rt_info ); +break ; +case AF_INET6 : + route_key_size =sizeof (struct ip6_rt_info ); +break ; +default : + route_key_size =0 ; +break ; + } - entry =kmalloc (sizeof (*entry) + afinfo->route_key_size,GFP_ATOMIC ); + entry =kmalloc (sizeof (*entry) + route_key_size,GFP_ATOMIC );if (!entry) { status = -ENOMEM ; goto err;
@@ -170,7 +180,7 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, .skb = skb, .state = *state, .hook_index = index, - .size = sizeof(*entry) + afinfo->route_key_size, + .size = sizeof(*entry) + route_key_size, };nf_queue_entry_get_refs (entry);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 39/52 netfilter: remove struct nf_afinfo and its helper functions
In reply to Pablo Neira AyusoThis abstraction has no clients anymore, remove it.
This is what remains from previous authors, so correct copyright statement after recent modifications and code removal.
--- include/linux/netfilter.h | 13 ------------- net/bridge/netfilter/nf_tables_bridge.c | 16 ++++------------ net/ipv4/netfilter.c | 10 ---------- net/ipv6/netfilter.c | 7 +------ net/netfilter/core.c | 25 +------------------------ 5 files changed, 6 insertions(+), 65 deletions(-)
include/linux/netfilter.h +0 -13
@@ -309,16 +309,6 @@ int skb_make_writable(struct sk_buff *skb, unsigned int writable_len);struct flowi ;struct nf_queue_entry ; -struct nf_afinfo { -unsigned short family; -}; - -extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO ]; -static inline const struct nf_afinfo *nf_get_afinfo (unsigned short family) -{ -return rcu_dereference (nf_afinfo[family]); -} -__sum16 nf_checksum (struct sk_buff *skb,unsigned int hook,unsigned int dataoff,u_int8_t protocol,unsigned short family);
@@ -330,9 +320,6 @@ int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, bool strict, unsigned short family);int nf_reroute (struct sk_buff *skb,struct nf_queue_entry *entry); -int nf_register_afinfo (const struct nf_afinfo *afinfo); -void nf_unregister_afinfo (const struct nf_afinfo *afinfo); -#include <net/flow.h> extern void (*nf_nat_decode_session_hook)(struct sk_buff *,struct flowi *);
net/bridge/netfilter/nf_tables_bridge.c +4 -12
@@ -95,30 +95,23 @@ static const struct nf_chain_type filter_bridge = { }, }; -static const struct nf_afinfo nf_br_afinfo = { - .family =AF_BRIDGE , - .route_key_size =0 , -}; -static int __init nf_tables_bridge_init (void ) {int ret; -nf_register_afinfo (&nf_br_afinfo); ret =nft_register_chain_type (&filter_bridge);if (ret <0 ) - goto err1; +return ret; ret =register_pernet_subsys (&nf_tables_bridge_net_ops);if (ret <0 ) - goto err2; + goto err_register_subsys;return ret; -err2: +err_register_subsys:nft_unregister_chain_type (&filter_bridge); -err1: -nf_unregister_afinfo (&nf_br_afinfo); +return ret; }
@@ -126,7 +119,6 @@ static void __exit nf_tables_bridge_exit(void) {unregister_pernet_subsys (&nf_tables_bridge_net_ops);nft_unregister_chain_type (&filter_bridge); -nf_unregister_afinfo (&nf_br_afinfo); }module_init (nf_tables_bridge_init);
net/ipv4/netfilter.c +0 -10
@@ -161,13 +161,3 @@ int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl,return 0 ; }EXPORT_SYMBOL_GPL (nf_ip_route); - -static const struct nf_afinfo nf_ip_afinfo = { - .family =AF_INET , -}; - -static int __init ipv4_netfilter_init (void ) -{ -return nf_register_afinfo (&nf_ip_afinfo); -} -subsys_initcall (ipv4_netfilter_init);
net/ipv6/netfilter.c +1 -6
@@ -174,14 +174,10 @@ static const struct nf_ipv6_ops ipv6ops = { .reroute = nf_ip6_reroute, }; -static const struct nf_afinfo nf_ip6_afinfo = { - .family =AF_INET6 , -}; -int __init ipv6_netfilter_init (void ) {RCU_INIT_POINTER (nf_ipv6_ops, &ipv6ops); -return nf_register_afinfo (&nf_ip6_afinfo); +return 0 ; }/* This can be called from inet6_init() on errors, so it cannot
@@ -190,5 +186,4 @@ int __init ipv6_netfilter_init(void)void ipv6_netfilter_fini (void ) {RCU_INIT_POINTER (nf_ipv6_ops,NULL ); -nf_unregister_afinfo (&nf_ip6_afinfo); }
net/netfilter/core.c +1 -24
@@ -4,8 +4,7 @@* Thanks to Rob `CmdrTaco' Malda for not influencing this code in any * way. * -* Rusty Russell (C)2000 -- This code is GPL. -* Patrick McHardy (c) 2006-2012 +* This code is GPL. */ #include <linux/kernel.h> #include <linux/netfilter.h>
@@ -28,34 +27,12 @@#include "nf_internals.h" -static DEFINE_MUTEX (afinfo_mutex); - -const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO ]__read_mostly ; -EXPORT_SYMBOL (nf_afinfo);const struct nf_ipv6_ops __rcu *nf_ipv6_ops__read_mostly ;EXPORT_SYMBOL_GPL (nf_ipv6_ops);DEFINE_PER_CPU (bool, nf_skb_duplicated);EXPORT_SYMBOL_GPL (nf_skb_duplicated); -int nf_register_afinfo (const struct nf_afinfo *afinfo) -{ -mutex_lock (&afinfo_mutex); -RCU_INIT_POINTER (nf_afinfo[afinfo->family], afinfo); -mutex_unlock (&afinfo_mutex); -return 0 ; -} -EXPORT_SYMBOL_GPL (nf_register_afinfo); - -void nf_unregister_afinfo (const struct nf_afinfo *afinfo) -{ -mutex_lock (&afinfo_mutex); -RCU_INIT_POINTER (nf_afinfo[afinfo->family],NULL ); -mutex_unlock (&afinfo_mutex); -synchronize_rcu (); -} -EXPORT_SYMBOL_GPL (nf_unregister_afinfo); -#ifdef HAVE_JUMP_LABEL struct static_key nf_hooks_needed[NFPROTO_NUMPROTO ][NF_MAX_HOOKS ];EXPORT_SYMBOL (nf_hooks_needed);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 40/52 netfilter: meta: secpath support
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
replacement for iptables "-m policy --dir in --policy {ipsec,none}".
--- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_meta.c | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+)
include/uapi/linux/netfilter/nf_tables.h +2 -0
@@ -777,6 +777,7 @@ enum nft_exthdr_attributes {* @NFT_META_OIFGROUP: packet output interface group * @NFT_META_CGROUP: socket control group (skb->sk->sk_classid) * @NFT_META_PRANDOM: a 32bit pseudo-random number +* @NFT_META_SECPATH: boolean, secpath_exists (!!skb->sp) */ enum nft_meta_keys {NFT_META_LEN ,
@@ -804,6 +805,7 @@ enum nft_meta_keys {NFT_META_OIFGROUP ,NFT_META_CGROUP ,NFT_META_PRANDOM , + NFT_META_SECPATH, };/**
net/netfilter/nft_meta.c +43 -0
67 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 41/52 netfilter: remove defensive check on malformed packets from raw sockets
In reply to Pablo Neira AyusoUsers cannot forge malformed IPv4/IPv6 headers via raw sockets that they can inject into the stack. Specifically, not for IPv4 since 55888dfb6ba7 ("AF_RAW: Augment raw_send_hdrinc to expand skb to fit iphdr->ihl (v2)"). IPv6 raw sockets also ensure that packets have a well-formed IPv6 header available in the skbuff.
At quick glance, br_netfilter also validates layer 3 headers and it drops malformed both IPv4 and IPv6 packets.
Therefore, let's remove this defensive check all over the place.
--- net/ipv4/netfilter/iptable_filter.c | 6 ----- net/ipv4/netfilter/iptable_mangle.c | 5 ---- net/ipv4/netfilter/iptable_raw.c | 6 ----- net/ipv4/netfilter/iptable_security.c | 6 ----- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 5 ---- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 10 -------- net/ipv4/netfilter/nf_tables_ipv4.c | 17 +------------ net/ipv4/netfilter/nft_chain_route_ipv4.c | 5 ---- net/ipv6/netfilter/ip6table_mangle.c | 8 ------ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 5 ---- net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 8 ------ net/ipv6/netfilter/nf_tables_ipv6.c | 16 +----------- net/netfilter/nf_tables_inet.c | 34 +------------------------- 13 files changed, 3 insertions(+), 128 deletions(-)
net/ipv4/netfilter/iptable_filter.c +0 -6
@@ -38,12 +38,6 @@ static unsigned int iptable_filter_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -if (state->hook ==NF_INET_LOCAL_OUT && - (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr ))) -/* root is playing with raw sockets. */ -return NF_ACCEPT ; -return ipt_do_table (skb, state, state->net->ipv4.iptable_filter); }
net/ipv4/netfilter/iptable_mangle.c +0 -5
@@ -49,11 +49,6 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)u_int32_t mark;int err; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; -/* Save things which could affect route */ mark = skb->mark; iph =ip_hdr (skb);
net/ipv4/netfilter/iptable_raw.c +0 -6
@@ -26,12 +26,6 @@ static unsigned int iptable_raw_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -if (state->hook ==NF_INET_LOCAL_OUT && - (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr ))) -/* root is playing with raw sockets. */ -return NF_ACCEPT ; -return ipt_do_table (skb, state, state->net->ipv4.iptable_raw); }
net/ipv4/netfilter/iptable_security.c +0 -6
@@ -43,12 +43,6 @@ static unsigned int iptable_security_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -if (state->hook ==NF_INET_LOCAL_OUT && - (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr ))) -/* Somebody is playing with raw sockets. */ -return NF_ACCEPT ; -return ipt_do_table (skb, state, state->net->ipv4.iptable_security); }
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +0 -5
@@ -154,11 +154,6 @@ static unsigned int ipv4_conntrack_local(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; - if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */ return NF_ACCEPT;
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +0 -10
@@ -356,11 +356,6 @@ nf_nat_ipv4_out(void *priv, struct sk_buff *skb,#endif unsigned int ret; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; - ret =nf_nat_ipv4_fn (priv, skb, state, do_chain);#ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN &&
@@ -396,11 +391,6 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,unsigned int ret;int err; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; - ret =nf_nat_ipv4_fn (priv, skb, state, do_chain);if (ret !=NF_DROP && ret !=NF_STOLEN && (ct =nf_ct_get (skb, &ctinfo)) !=NULL ) {
net/ipv4/netfilter/nf_tables_ipv4.c +1 -16
@@ -30,21 +30,6 @@ static unsigned int nft_do_chain_ipv4(void *priv,return nft_do_chain (&pkt, priv); } -static unsigned int nft_ipv4_output (void *priv, -struct sk_buff *skb, -const struct nf_hook_state *state) -{ -if (unlikely (skb->len <sizeof (struct iphdr ) || -ip_hdr (skb)->ihl <sizeof (struct iphdr ) /4 )) { -if (net_ratelimit ()) -pr_info ("nf_tables_ipv4: ignoring short SOCK_RAW " -"packet\n" ); -return NF_ACCEPT ; - } - -return nft_do_chain_ipv4 (priv, skb, state); -} -static struct nft_af_info nft_af_ipv4__read_mostly = { .family =NFPROTO_IPV4 , .nhooks =NF_INET_NUMHOOKS ,
@@ -91,7 +76,7 @@ static const struct nf_chain_type filter_ipv4 = { (1 << NF_INET_POST_ROUTING), .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, - [NF_INET_LOCAL_OUT] = nft_ipv4_output, + [NF_INET_LOCAL_OUT] = nft_do_chain_ipv4, [NF_INET_FORWARD] = nft_do_chain_ipv4, [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
net/ipv4/netfilter/nft_chain_route_ipv4.c +0 -5
@@ -33,11 +33,6 @@ static unsigned int nf_route_table_hook(void *priv,const struct iphdr *iph;int err; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; -nft_set_pktinfo (&pkt, skb, state);nft_set_pktinfo_ipv4 (&pkt, skb);
net/ipv6/netfilter/ip6table_mangle.c +0 -8
@@ -42,14 +42,6 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)u_int8_t hop_limit;u_int32_t flowlabel, mark;int err; -#if 0 -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) { -net_warn_ratelimited ("ip6t_hook: happy cracking\n" ); -return NF_ACCEPT ; - } -#endif /* save source/dest address, mark, hoplimit, flowlabel, priority, */ memcpy (&saddr, &ipv6_hdr (skb)->saddr,sizeof (saddr));
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +0 -5
@@ -176,11 +176,6 @@ static unsigned int ipv6_conntrack_local(void *priv,struct sk_buff *skb, const struct nf_hook_state *state) { -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct ipv6hdr )) { -net_notice_ratelimited ("ipv6_conntrack_local: packet too short\n" ); -return NF_ACCEPT ; - } return nf_conntrack_in(state->net, PF_INET6, state->hook, skb); }
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +0 -8
@@ -369,10 +369,6 @@ nf_nat_ipv6_out(void *priv, struct sk_buff *skb,#endif unsigned int ret; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct ipv6hdr )) -return NF_ACCEPT ; - ret =nf_nat_ipv6_fn (priv, skb, state, do_chain);#ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN &&
@@ -408,10 +404,6 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,unsigned int ret;int err; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct ipv6hdr )) -return NF_ACCEPT ; - ret =nf_nat_ipv6_fn (priv, skb, state, do_chain);if (ret !=NF_DROP && ret !=NF_STOLEN && (ct =nf_ct_get (skb, &ctinfo)) !=NULL ) {
net/ipv6/netfilter/nf_tables_ipv6.c +1 -15
@@ -28,20 +28,6 @@ static unsigned int nft_do_chain_ipv6(void *priv,return nft_do_chain (&pkt, priv); } -static unsigned int nft_ipv6_output (void *priv, -struct sk_buff *skb, -const struct nf_hook_state *state) -{ -if (unlikely (skb->len <sizeof (struct ipv6hdr ))) { -if (net_ratelimit ()) -pr_info ("nf_tables_ipv6: ignoring short SOCK_RAW " -"packet\n" ); -return NF_ACCEPT ; - } - -return nft_do_chain_ipv6 (priv, skb, state); -} -static struct nft_af_info nft_af_ipv6__read_mostly = { .family =NFPROTO_IPV6 , .nhooks =NF_INET_NUMHOOKS ,
@@ -88,7 +74,7 @@ static const struct nf_chain_type filter_ipv6 = { (1 << NF_INET_POST_ROUTING), .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, - [NF_INET_LOCAL_OUT] = nft_ipv6_output, + [NF_INET_LOCAL_OUT] = nft_do_chain_ipv6, [NF_INET_FORWARD] = nft_do_chain_ipv6, [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, [NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
net/netfilter/nf_tables_inet.c +1 -33
@@ -38,38 +38,6 @@ static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb,return nft_do_chain (&pkt, priv); } -static unsigned int nft_inet_output (void *priv,struct sk_buff *skb, -const struct nf_hook_state *state) -{ -struct nft_pktinfo pkt; - -nft_set_pktinfo (&pkt, skb, state); - -switch (state->pf) { -case NFPROTO_IPV4 : -if (unlikely (skb->len <sizeof (struct iphdr ) || -ip_hdr (skb)->ihl <sizeof (struct iphdr ) /4 )) { -if (net_ratelimit ()) -pr_info ("ignoring short SOCK_RAW packet\n" ); -return NF_ACCEPT ; - } -nft_set_pktinfo_ipv4 (&pkt, skb); -break ; -case NFPROTO_IPV6 : -if (unlikely (skb->len <sizeof (struct ipv6hdr ))) { -if (net_ratelimit ()) -pr_info ("ignoring short SOCK_RAW packet\n" ); -return NF_ACCEPT ; - } -nft_set_pktinfo_ipv6 (&pkt, skb); -break ; -default : -break ; - } - -return nft_do_chain (&pkt, priv); -} -static struct nft_af_info nft_af_inet__read_mostly = { .family =NFPROTO_INET , .nhooks =NF_INET_NUMHOOKS ,
@@ -116,7 +84,7 @@ static const struct nf_chain_type filter_inet = { (1 << NF_INET_POST_ROUTING), .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_inet, - [NF_INET_LOCAL_OUT] = nft_inet_output, + [NF_INET_LOCAL_OUT] = nft_do_chain_inet, [NF_INET_FORWARD] = nft_do_chain_inet, [NF_INET_PRE_ROUTING] = nft_do_chain_inet, [NF_INET_POST_ROUTING] = nft_do_chain_inet,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 42/52 netfilter: nf_tables: remove nft_dereference()
In reply to Pablo Neira AyusoThis macro is unnecessary, it just hides details for one single caller. nfnl_dereference() is just enough.
--- include/net/netfilter/nf_tables.h | 3 --- net/netfilter/nf_tables_api.c | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-)
include/net/netfilter/nf_tables.h +0 -3
@@ -1113,9 +1113,6 @@ void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt,void nft_trace_notify (struct nft_traceinfo *info); -#define nft_dereference (p) \ - nfnl_dereference(p, NFNL_SUBSYS_NFTABLES) -#define MODULE_ALIAS_NFT_FAMILY (family) \ MODULE_ALIAS("nft-afinfo-" __stringify(family))
net/netfilter/nf_tables_api.c +3 -3
@@ -1222,13 +1222,13 @@ static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr)static void nft_chain_stats_replace (struct nft_base_chain *chain,struct nft_stats __percpu *newstats) { +struct nft_stats __percpu *oldstats; +if (newstats ==NULL )return ;if (chain->stats) { -struct nft_stats __percpu *oldstats = -nft_dereference (chain->stats); - + oldstats =nfnl_dereference (chain->stats,NFNL_SUBSYS_NFTABLES );rcu_assign_pointer (chain->stats, newstats);synchronize_rcu ();free_percpu (oldstats);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 43/52 netfilter: nf_conntrack: add IPS_OFFLOAD status bit
In reply to Pablo Neira AyusoThis new bit tells us that the conntrack entry is owned by the flow table offload infrastructure.
# cat /proc/net/nf_conntrack ipv4 2 tcp 6 src=10.141.10.2 dst=147.75.205.195 sport=36392 dport=443 src=147.75.205.195 dst=192.168.2.195 sport=443 dport=36392 [OFFLOAD] mark=0 zone=0 use=2
Note the [OFFLOAD] tag in the listing.
The timer of such conntrack entries look like stopped from userspace. In practise, to make sure the conntrack entry does not go away, the conntrack timer is periodically set to an arbitrary large value that gets refreshed on every iteration from the garbage collector, so it never expires- and they display no internal state in the case of TCP flows. This allows us to save a bitcheck from the packet path via nf_ct_is_expired().
Conntrack entries that have been offloaded to the flow table infrastructure cannot be deleted/flushed via ctnetlink. The flow table infrastructure is also responsible for releasing this conntrack entry.
--- include/uapi/linux/netfilter/nf_conntrack_common.h | 6 +++++- net/netfilter/nf_conntrack_core.c | 20 ++++++++++++++++++++ net/netfilter/nf_conntrack_netlink.c | 15 ++++++++++++++- net/netfilter/nf_conntrack_proto_tcp.c | 3 +++ net/netfilter/nf_conntrack_standalone.c | 12 ++++++++---- 5 files changed, 50 insertions(+), 6 deletions(-)
include/uapi/linux/netfilter/nf_conntrack_common.h +5 -1
@@ -101,12 +101,16 @@ enum ip_conntrack_status {IPS_HELPER_BIT =13 ,IPS_HELPER = (1 <<IPS_HELPER_BIT ), +/* Conntrack has been offloaded to flow table. */ +IPS_OFFLOAD_BIT =14 , +IPS_OFFLOAD = (1 <<IPS_OFFLOAD_BIT ), +/* Be careful here, modifying these bits can make things messy, * so don't let users modify them directly. */ IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK |IPS_NAT_MASK |IPS_EXPECTED |IPS_CONFIRMED |IPS_DYING | -IPS_SEQ_ADJUST |IPS_TEMPLATE ), +IPS_SEQ_ADJUST |IPS_TEMPLATE |IPS_OFFLOAD ), __IPS_MAX_BIT = 14, };
net/netfilter/nf_conntrack_core.c +20 -0
@@ -901,6 +901,9 @@ static unsigned int early_drop_list(struct net *net,hlist_nulls_for_each_entry_rcu (h, n, head, hnnode) { tmp =nf_ct_tuplehash_to_ctrack (h); +if (test_bit (IPS_OFFLOAD_BIT , &tmp->status)) +continue ; +if (nf_ct_is_expired (tmp)) {nf_ct_gc_expired (tmp);continue ;
@@ -975,6 +978,18 @@ static bool gc_worker_can_early_drop(const struct nf_conn *ct)return false; } +#define DAY (86400 * HZ) + +/* Set an arbitrary timeout large enough not to ever expire, this save +* us a check for the IPS_OFFLOAD_BIT from the packet path via +* nf_ct_is_expired(). +*/ +static void nf_ct_offload_timeout (struct nf_conn *ct) +{ +if (nf_ct_expires (ct) <DAY /2 ) + ct->timeout = nfct_time_stamp +DAY ; +} +static void gc_worker (struct work_struct *work) {unsigned int min_interval =max (HZ /GC_MAX_BUCKETS_DIV ,1u );
@@ -1011,6 +1026,11 @@ static void gc_worker(struct work_struct *work) tmp =nf_ct_tuplehash_to_ctrack (h); scanned++; +if (test_bit (IPS_OFFLOAD_BIT , &tmp->status)) { +nf_ct_offload_timeout (tmp); +continue ; + } +if (nf_ct_is_expired (tmp)) {nf_ct_gc_expired (tmp); expired_count++;
net/netfilter/nf_conntrack_netlink.c +14 -1
@@ -1110,6 +1110,14 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { .len = NF_CT_LABELS_MAX_SIZE }, }; +static int ctnetlink_flush_iterate (struct nf_conn *ct,void *data) +{ +if (test_bit (IPS_OFFLOAD_BIT , &ct->status)) +return 0 ; + +return ctnetlink_filter_match (ct, data); +} +static int ctnetlink_flush_conntrack (struct net *net,const struct nlattr *const cda[],u32 portid,int report)
@@ -1122,7 +1130,7 @@ static int ctnetlink_flush_conntrack(struct net *net,return PTR_ERR (filter); } -nf_ct_iterate_cleanup_net (net, ctnetlink_filter_match, filter, +nf_ct_iterate_cleanup_net (net, ctnetlink_flush_iterate, filter, portid, report);kfree (filter);
@@ -1168,6 +1176,11 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl, ct =nf_ct_tuplehash_to_ctrack (h); +if (test_bit (IPS_OFFLOAD_BIT , &ct->status)) { +nf_ct_put (ct); +return -EBUSY ; + } +if (cda[CTA_ID ]) {u_int32_t id =ntohl (nla_get_be32 (cda[CTA_ID ]));if (id != (u32 )(unsigned long )ct) {
net/netfilter/nf_conntrack_proto_tcp.c +3 -0
@@ -305,6 +305,9 @@ static bool tcp_invert_tuple(struct nf_conntrack_tuple *tuple,/* Print out the private part of the conntrack. */ static void tcp_print_conntrack (struct seq_file *s,struct nf_conn *ct) { +if (test_bit (IPS_OFFLOAD_BIT , &ct->status)) +return ; +seq_printf (s,"%s " , tcp_conntrack_names[ct->proto.tcp.state]); }#endif
net/netfilter/nf_conntrack_standalone.c +8 -4
@@ -309,10 +309,12 @@ static int ct_seq_show(struct seq_file *s, void *v)WARN_ON (!l4proto); ret = -ENOSPC ; -seq_printf (s,"%-8s %u %-8s %u %ld " , +seq_printf (s,"%-8s %u %-8s %u " ,l3proto_name (l3proto->l3proto),nf_ct_l3num (ct), -l4proto_name (l4proto->l4proto),nf_ct_protonum (ct), -nf_ct_expires (ct) /HZ ); +l4proto_name (l4proto->l4proto),nf_ct_protonum (ct)); + +if (!test_bit (IPS_OFFLOAD_BIT , &ct->status)) +seq_printf (s,"%ld " ,nf_ct_expires (ct) /HZ );if (l4proto->print_conntrack) l4proto->print_conntrack (s, ct);
@@ -339,7 +341,9 @@ static int ct_seq_show(struct seq_file *s, void *v)if (seq_print_acct (s, ct,IP_CT_DIR_REPLY )) goto release; -if (test_bit (IPS_ASSURED_BIT , &ct->status)) +if (test_bit (IPS_OFFLOAD_BIT , &ct->status)) +seq_puts (s,"[OFFLOAD] " ); +else if (test_bit (IPS_ASSURED_BIT , &ct->status))seq_puts (s,"[ASSURED] " );if (seq_has_overflowed (s))
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 44/52 netfilter: nf_tables: add flow table netlink frontend
In reply to Pablo Neira AyusoThis patch introduces a netlink control plane to create, delete and dump flow tables. Flow tables are identified by name, this name is used from rules to refer to an specific flow table. Flow tables use the rhashtable class and a generic garbage collector to remove expired entries.
This also adds the infrastructure to add different flow table types, so we can add one for each layer 3 protocol family.
--- include/net/netfilter/nf_flow_table.h | 23 + include/net/netfilter/nf_tables.h | 48 ++ include/uapi/linux/netfilter/nf_tables.h | 53 +++ net/netfilter/nf_tables_api.c | 747 ++++++++++++++++++++++++++++++- 4 files changed, 870 insertions(+), 1 deletion(-) create mode 100644 include/net/netfilter/nf_flow_table.h
include/net/netfilter/nf_flow_table.h new file +23 -0
@@ -0,0 +1,23 @@ +#ifndef _NF_FLOW_TABLE_H +#define _NF_FLOW_TABLE_H + +#include <linux/rhashtable.h> + +struct nf_flowtable ; + +struct nf_flowtable_type { +struct list_head list; +int family; +void (*gc)(struct work_struct *work); +const struct rhashtable_params *params; +nf_hookfn *hook; +struct module *owner; +}; + +struct nf_flowtable { +struct rhashtable rhashtable; +const struct nf_flowtable_type *type; +struct delayed_work gc_work; +}; + +#endif /* _FLOW_OFFLOAD_H */
include/net/netfilter/nf_tables.h +48 -0
76 lines not on this page · raw message
include/uapi/linux/netfilter/nf_tables.h +53 -0
71 lines not on this page · raw message
net/netfilter/nf_tables_api.c +746 -1
858 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 45/52 netfilter: add generic flow table infrastructure
In reply to Pablo Neira AyusoThis patch defines the API to interact with flow tables, this allows to add, delete and lookup for entries in the flow table. This also adds the generic garbage code that removes entries that have expired, ie. no traffic has been seen for a while.
Users of the flow table infrastructure can delete entries via flow_offload_dead(), which sets the dying bit, this signals the garbage collector to release an entry from user context.
--- include/net/netfilter/nf_flow_table.h | 94 ++++++++ net/netfilter/Kconfig | 7 + net/netfilter/Makefile | 3 + net/netfilter/nf_flow_table.c | 429 ++++++++++++++++++++++++++++++++++ 4 files changed, 533 insertions(+) create mode 100644 net/netfilter/nf_flow_table.c
include/net/netfilter/nf_flow_table.h +94 -0
@@ -1,7 +1,12 @@#ifndef _NF_FLOW_TABLE_H#define _NF_FLOW_TABLE_H +#include <linux/in.h> +#include <linux/in6.h> +#include <linux/netdevice.h> #include <linux/rhashtable.h> +#include <linux/rcupdate.h> +#include <net/dst.h> struct nf_flowtable ;
@@ -20,4 +25,93 @@ struct nf_flowtable {struct delayed_work gc_work; }; +enum flow_offload_tuple_dir { +FLOW_OFFLOAD_DIR_ORIGINAL , +FLOW_OFFLOAD_DIR_REPLY , + __FLOW_OFFLOAD_DIR_MAX =FLOW_OFFLOAD_DIR_REPLY , +}; +#define FLOW_OFFLOAD_DIR_MAX (__FLOW_OFFLOAD_DIR_MAX + 1) + +struct flow_offload_tuple { +union { +struct in_addr src_v4; +struct in6_addr src_v6; + }; +union { +struct in_addr dst_v4; +struct in6_addr dst_v6; + }; +struct { +__be16 src_port; +__be16 dst_port; + }; + +int iifidx; + +u8 l3proto; +u8 l4proto; +u8 dir; + +int oifidx; + +struct dst_entry *dst_cache; +}; + +struct flow_offload_tuple_rhash { +struct rhash_head node; +struct flow_offload_tuple tuple; +}; + +#define FLOW_OFFLOAD_SNAT 0x1 +#define FLOW_OFFLOAD_DNAT 0x2 +#define FLOW_OFFLOAD_DYING 0x4 + +struct flow_offload { +struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX ]; +u32 flags; +union { +/* Your private driver data here. */ +u32 timeout; + }; +}; + +#define NF_FLOW_TIMEOUT (30 * HZ) + +struct nf_flow_route { +struct { +struct dst_entry *dst; +int ifindex; + } tuple[FLOW_OFFLOAD_DIR_MAX ]; +}; + +struct flow_offload *flow_offload_alloc (struct nf_conn *ct, +struct nf_flow_route *route); +void flow_offload_free (struct flow_offload *flow); + +int flow_offload_add (struct nf_flowtable *flow_table,struct flow_offload *flow); +void flow_offload_del (struct nf_flowtable *flow_table,struct flow_offload *flow); +struct flow_offload_tuple_rhash *flow_offload_lookup (struct nf_flowtable *flow_table, +struct flow_offload_tuple *tuple); +int nf_flow_table_iterate (struct nf_flowtable *flow_table, +void (*iter)(struct flow_offload *flow,void *data), +void *data); +void nf_flow_offload_work_gc (struct work_struct *work); +extern const struct rhashtable_params nf_flow_offload_rhash_params; + +void flow_offload_dead (struct flow_offload *flow); + +int nf_flow_snat_port (const struct flow_offload *flow, +struct sk_buff *skb,unsigned int thoff, +u8 protocol,enum flow_offload_tuple_dir dir); +int nf_flow_dnat_port (const struct flow_offload *flow, +struct sk_buff *skb,unsigned int thoff, +u8 protocol,enum flow_offload_tuple_dir dir); + +struct flow_ports { +__be16 source, dest; +}; + +#define MODULE_ALIAS_NF_FLOWTABLE (family) \ + MODULE_ALIAS("nf-flowtable-" __stringify(family)) +#endif /* _FLOW_OFFLOAD_H */
net/netfilter/Kconfig +7 -0
@@ -657,6 +657,13 @@ endif # NF_TABLES_NETDEV endif # NF_TABLES +config NF_FLOW_TABLE + tristate "Netfilter flow table module" + help + This option adds the flow table core infrastructure. + + To compile it as a module, choose M here. + config NETFILTER_XTABLES tristate "Netfilter Xtables support (required for ip_tables)" default m if NETFILTER_ADVANCED=n
net/netfilter/Makefile +3 -0
@@ -109,6 +109,9 @@ obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o +# flow table infrastructure +obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o + # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
net/netfilter/nf_flow_table.c new file +429 -0
429 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 46/52 netfilter: flow table support for IPv4
In reply to Pablo Neira AyusoThis patch adds the IPv4 flow table type, that implements the datapath flow table to forward IPv4 traffic. Rationale is:
1) Look up for the packet in the flow table, from the ingress hook.
2) If there's a hit, decrement ttl and pass it on to the neighbour layer for transmission.
3) If there's a miss, packet is passed up to the classic forwarding path.
This patch also supports layer 3 source and destination NAT.
--- net/ipv4/netfilter/Kconfig | 8 + net/ipv4/netfilter/Makefile | 3 + net/ipv4/netfilter/nf_flow_table_ipv4.c | 283 ++++++++++++++++++++++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 net/ipv4/netfilter/nf_flow_table_ipv4.c
net/ipv4/netfilter/Kconfig +8 -0
@@ -78,6 +78,14 @@ config NF_TABLES_ARP endif # NF_TABLES +config NF_FLOW_TABLE_IPV4 + select NF_FLOW_TABLE + tristate "Netfilter flow table IPv4 module" + help + This option adds the flow table IPv4 support. + + To compile it as a module, choose M here. + config NF_DUP_IPV4 tristate "Netfilter IPv4 packet duplication to alternate destination" depends on !NF_CONNTRACK || NF_CONNTRACK
net/ipv4/netfilter/Makefile +3 -0
@@ -43,6 +43,9 @@ obj-$(CONFIG_NFT_REDIR_IPV4) += nft_redir_ipv4.o obj-$(CONFIG_NFT_DUP_IPV4) += nft_dup_ipv4.o obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o +# flow table support +obj-$(CONFIG_NF_FLOW_TABLE_IPV4) += nf_flow_table_ipv4.o + # generic IP tables obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
net/ipv4/netfilter/nf_flow_table_ipv4.c new file +283 -0
283 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 47/52 netfilter: flow table support for IPv6
In reply to Pablo Neira AyusoThis patch adds the IPv6 flow table type, that implements the datapath flow table to forward IPv6 traffic.
This patch exports ip6_dst_mtu_forward() that is required to check for mtu to pass up packets that need PMTUD handling to the classic forwarding path.
--- include/net/ipv6.h | 2 + net/ipv6/ip6_output.c | 3 +- net/ipv6/netfilter/Kconfig | 8 + net/ipv6/netfilter/Makefile | 3 + net/ipv6/netfilter/nf_flow_table_ipv6.c | 277 ++++++++++++++++++++++++++++++++ 5 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 net/ipv6/netfilter/nf_flow_table_ipv6.c
include/net/ipv6.h +2 -0
@@ -969,6 +969,8 @@ static inline struct sk_buff *ip6_finish_skb(struct sock *sk) &inet6_sk(sk)->cork); } +unsigned int ip6_dst_mtu_forward (const struct dst_entry *dst); +int ip6_dst_lookup (struct net *net,struct sock *sk,struct dst_entry **dst,struct flowi6 *fl6); struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6,
net/ipv6/ip6_output.c +2 -1
@@ -378,7 +378,7 @@ static inline int ip6_forward_finish(struct net *net, struct sock *sk,return dst_output (net, sk, skb); } -static unsigned int ip6_dst_mtu_forward (const struct dst_entry *dst) +unsigned int ip6_dst_mtu_forward (const struct dst_entry *dst) {unsigned int mtu;struct inet6_dev *idev;
@@ -398,6 +398,7 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)return mtu; } +EXPORT_SYMBOL_GPL (ip6_dst_mtu_forward);static bool ip6_pkt_too_big (const struct sk_buff *skb,unsigned int mtu) {
net/ipv6/netfilter/Kconfig +8 -0
@@ -71,6 +71,14 @@ config NFT_FIB_IPV6 endif # NF_TABLES_IPV6 endif # NF_TABLES +config NF_FLOW_TABLE_IPV6 + select NF_FLOW_TABLE + tristate "Netfilter flow table IPv6 module" + help + This option adds the flow table IPv6 support. + + To compile it as a module, choose M here. + config NF_DUP_IPV6 tristate "Netfilter IPv6 packet duplication to alternate destination" depends on !NF_CONNTRACK || NF_CONNTRACK
net/ipv6/netfilter/Makefile +3 -0
@@ -45,6 +45,9 @@ obj-$(CONFIG_NFT_REDIR_IPV6) += nft_redir_ipv6.o obj-$(CONFIG_NFT_DUP_IPV6) += nft_dup_ipv6.o obj-$(CONFIG_NFT_FIB_IPV6) += nft_fib_ipv6.o +# flow table support +obj-$(CONFIG_NF_FLOW_TABLE_IPV6) += nf_flow_table_ipv6.o + # matches obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
net/ipv6/netfilter/nf_flow_table_ipv6.c new file +277 -0
277 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 48/52 netfilter: flow table support for the mixed IPv4/IPv6 family
In reply to Pablo Neira AyusoThis patch adds the IPv6 flow table type, that implements the datapath flow table to forward IPv6 traffic.
--- include/net/netfilter/nf_flow_table.h | 5 ++++ net/ipv4/netfilter/nf_flow_table_ipv4.c | 3 ++- net/ipv6/netfilter/nf_flow_table_ipv6.c | 3 ++- net/netfilter/Kconfig | 8 ++++++ net/netfilter/Makefile | 1 + net/netfilter/nf_flow_table_inet.c | 48 +++++++++++++++++++++++++++++++++ 6 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 net/netfilter/nf_flow_table_inet.c
include/net/netfilter/nf_flow_table.h +5 -0
@@ -111,6 +111,11 @@ struct flow_ports {__be16 source, dest; }; +unsigned int nf_flow_offload_ip_hook (void *priv,struct sk_buff *skb, +const struct nf_hook_state *state); +unsigned int nf_flow_offload_ipv6_hook (void *priv,struct sk_buff *skb, +const struct nf_hook_state *state); +#define MODULE_ALIAS_NF_FLOWTABLE (family) \ MODULE_ALIAS("nf-flowtable-" __stringify(family))
net/ipv4/netfilter/nf_flow_table_ipv4.c +2 -1
@@ -202,7 +202,7 @@ static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rtable *rt)return false; } -static unsigned int +unsigned int nf_flow_offload_ip_hook (void *priv,struct sk_buff *skb,const struct nf_hook_state *state) {
@@ -254,6 +254,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,return NF_STOLEN ; } +EXPORT_SYMBOL_GPL (nf_flow_offload_ip_hook);static struct nf_flowtable_type flowtable_ipv4 = { .family =NFPROTO_IPV4 ,
net/ipv6/netfilter/nf_flow_table_ipv6.c +2 -1
@@ -196,7 +196,7 @@ static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rt6_info *rt)return false; } -static unsigned int +unsigned int nf_flow_offload_ipv6_hook (void *priv,struct sk_buff *skb,const struct nf_hook_state *state) {
@@ -248,6 +248,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,return NF_STOLEN ; } +EXPORT_SYMBOL_GPL (nf_flow_offload_ipv6_hook);static struct nf_flowtable_type flowtable_ipv6 = { .family =NFPROTO_IPV6 ,
net/netfilter/Kconfig +8 -0
@@ -657,6 +657,14 @@ endif # NF_TABLES_NETDEV endif # NF_TABLES +config NF_FLOW_TABLE_INET + select NF_FLOW_TABLE + tristate "Netfilter flow table mixed IPv4/IPv6 module" + help + This option adds the flow table mixed IPv4/IPv6 support. + + To compile it as a module, choose M here. + config NF_FLOW_TABLE tristate "Netfilter flow table module" help
net/netfilter/Makefile +1 -0
@@ -111,6 +111,7 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o # flow table infrastructure obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o +obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
net/netfilter/nf_flow_table_inet.c new file +48 -0
48 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 49/52 netfilter: nf_tables: flow offload expression
In reply to Pablo Neira AyusoAdd new instruction for the nf_tables VM that allows us to specify what flows are offloaded into a given flow table via name. This new instruction creates the flow entry and adds it to the flow table.
Only established flows, ie. we have seen traffic in both directions, are added to the flow table. You can still decide to offload entries at a later stage via packet counting or checking the ct status in case you want to offload assured conntracks.
This new extension depends on the conntrack subsystem.
--- include/uapi/linux/netfilter/nf_tables.h | 11 ++ net/netfilter/Kconfig | 7 + net/netfilter/Makefile | 1 + net/netfilter/nft_flow_offload.c | 264 +++++++++++++++++++++++++++++++ 4 files changed, 283 insertions(+) create mode 100644 net/netfilter/nft_flow_offload.c
include/uapi/linux/netfilter/nf_tables.h +11 -0
@@ -957,6 +957,17 @@ enum nft_ct_attributes { };#define NFTA_CT_MAX (__NFTA_CT_MAX - 1) +/** +* enum nft_flow_attributes - ct offload expression attributes +* @NFTA_FLOW_TABLE_NAME: flow table name (NLA_STRING) +*/ +enum nft_offload_attributes { +NFTA_FLOW_UNSPEC , +NFTA_FLOW_TABLE_NAME , + __NFTA_FLOW_MAX, +}; +#define NFTA_FLOW_MAX (__NFTA_FLOW_MAX - 1) +enum nft_limit_type {NFT_LIMIT_PKTS ,NFT_LIMIT_PKT_BYTES
net/netfilter/Kconfig +7 -0
@@ -505,6 +505,13 @@ config NFT_CT This option adds the "ct" expression that you can use to match connection tracking information such as the flow state. +config NFT_FLOW_OFFLOAD + depends on NF_CONNTRACK + tristate "Netfilter nf_tables hardware flow offload module" + help + This option adds the "flow_offload" expression that you can use to + choose what flows are placed into the hardware. + config NFT_SET_RBTREE tristate "Netfilter nf_tables rbtree set module" help
net/netfilter/Makefile +1 -0
@@ -86,6 +86,7 @@ obj-$(CONFIG_NFT_META) += nft_meta.o obj-$(CONFIG_NFT_RT) += nft_rt.o obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o obj-$(CONFIG_NFT_CT) += nft_ct.o +obj-$(CONFIG_NFT_FLOW_OFFLOAD) += nft_flow_offload.o obj-$(CONFIG_NFT_LIMIT) += nft_limit.o obj-$(CONFIG_NFT_NAT) += nft_nat.o obj-$(CONFIG_NFT_OBJREF) += nft_objref.o
net/netfilter/nft_flow_offload.c new file +264 -0
264 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 50/52 netfilter: ipset: use swap macro instead of _manually_ swapping values
In reply to Pablo Neira AyusoFrom: "Gustavo A. R. Silva" <[email protected]>
Make use of the swap macro and remove unnecessary variables tmp. This makes the code easier to read and maintain.
This code was detected with the help of Coccinelle.
--- net/netfilter/ipset/ip_set_bitmap_ip.c | 8 ++------ net/netfilter/ipset/ip_set_bitmap_ipmac.c | 8 ++------ net/netfilter/ipset/ip_set_bitmap_port.c | 8 ++------ 3 files changed, 6 insertions(+), 18 deletions(-)
net/netfilter/ipset/ip_set_bitmap_ip.c +2 -6
@@ -263,12 +263,8 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[], ret =ip_set_get_hostipaddr4 (tb[IPSET_ATTR_IP_TO ], &last_ip);if (ret)return ret; -if (first_ip > last_ip) { -u32 tmp = first_ip; - - first_ip = last_ip; - last_ip = tmp; - } +if (first_ip > last_ip) +swap (first_ip, last_ip); }else if (tb[IPSET_ATTR_CIDR ]) {u8 cidr =nla_get_u8 (tb[IPSET_ATTR_CIDR ]);
net/netfilter/ipset/ip_set_bitmap_ipmac.c +2 -6
@@ -337,12 +337,8 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[], ret =ip_set_get_hostipaddr4 (tb[IPSET_ATTR_IP_TO ], &last_ip);if (ret)return ret; -if (first_ip > last_ip) { -u32 tmp = first_ip; - - first_ip = last_ip; - last_ip = tmp; - } +if (first_ip > last_ip) +swap (first_ip, last_ip); }else if (tb[IPSET_ATTR_CIDR ]) {u8 cidr =nla_get_u8 (tb[IPSET_ATTR_CIDR ]);
net/netfilter/ipset/ip_set_bitmap_port.c +2 -6
@@ -238,12 +238,8 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[], first_port =ip_set_get_h16 (tb[IPSET_ATTR_PORT ]); last_port =ip_set_get_h16 (tb[IPSET_ATTR_PORT_TO ]); -if (first_port > last_port) { -u16 tmp = first_port; - - first_port = last_port; - last_port = tmp; - } +if (first_port > last_port) +swap (first_port, last_port); elements = last_port - first_port +1 ; set->dsize =ip_set_elem_len (set, tb,0 ,0 );
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 51/52 netfilter: ipset: Fix "don't update counters" mode when counters used at the matching
In reply to Pablo Neira AyusoFrom: Jozsef Kadlecsik <[email protected]>
The matching of the counters was not taken into account, fixed.
--- include/linux/netfilter/ipset/ip_set.h | 6 ++ include/linux/netfilter/ipset/ip_set_counter.h | 25 ++++-- net/netfilter/ipset/ip_set_bitmap_gen.h | 9 +- net/netfilter/ipset/ip_set_core.c | 25 ++++++ net/netfilter/ipset/ip_set_hash_gen.h | 37 +++----- net/netfilter/ipset/ip_set_list_set.c | 21 ++--- net/netfilter/xt_set.c | 119 +++++++++---------------- 7 files changed, 114 insertions(+), 128 deletions(-)
include/linux/netfilter/ipset/ip_set.h +6 -0
@@ -122,6 +122,8 @@ struct ip_set_ext {u64 bytes;char *comment;u32 timeout; +u8 packets_op; +u8 bytes_op; };struct ip_set ;
@@ -339,6 +341,10 @@ extern int ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[], struct ip_set_ext *ext);extern int ip_set_put_extensions (struct sk_buff *skb,const struct ip_set *set,const void *e,bool active); +extern bool ip_set_match_extensions (struct ip_set *set, +const struct ip_set_ext *ext, +struct ip_set_ext *mext, +u32 flags,void *data);static inline int ip_set_get_hostipaddr4 (struct nlattr *nla,u32 *ipaddr)
include/linux/netfilter/ipset/ip_set_counter.h +19 -6
@@ -34,20 +34,33 @@ ip_set_get_packets(const struct ip_set_counter *counter)return (u64 )atomic64_read (&(counter)->packets); } +static inline bool +ip_set_match_counter (u64 counter,u64 match,u8 op) +{ +switch (op) { +case IPSET_COUNTER_NONE : +return true; +case IPSET_COUNTER_EQ : +return counter == match; +case IPSET_COUNTER_NE : +return counter != match; +case IPSET_COUNTER_LT : +return counter < match; +case IPSET_COUNTER_GT : +return counter > match; + } +return false; +} +static inline void ip_set_update_counter (struct ip_set_counter *counter, -const struct ip_set_ext *ext, -struct ip_set_ext *mext,u32 flags) +const struct ip_set_ext *ext,u32 flags) {if (ext->packets !=ULLONG_MAX && !(flags &IPSET_FLAG_SKIP_COUNTER_UPDATE )) {ip_set_add_bytes (ext->bytes, counter);ip_set_add_packets (ext->packets, counter); } -if (flags &IPSET_FLAG_MATCH_COUNTERS ) { - mext->packets =ip_set_get_packets (counter); - mext->bytes =ip_set_get_bytes (counter); - } } static inline bool
net/netfilter/ipset/ip_set_bitmap_gen.h +1 -8
@@ -127,14 +127,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,if (ret <=0 )return ret; -if (SET_WITH_TIMEOUT (set) && -ip_set_timeout_expired (ext_timeout (x, set))) -return 0 ; -if (SET_WITH_COUNTER (set)) -ip_set_update_counter (ext_counter (x, set), ext, mext, flags); -if (SET_WITH_SKBINFO (set)) -ip_set_get_skbinfo (ext_skbinfo (x, set), ext, mext, flags); -return 1 ; +return ip_set_match_extensions (set, ext, mext, flags, x); } static int
net/netfilter/ipset/ip_set_core.c +25 -0
@@ -472,6 +472,31 @@ ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set, }EXPORT_SYMBOL_GPL (ip_set_put_extensions); +bool +ip_set_match_extensions (struct ip_set *set,const struct ip_set_ext *ext, +struct ip_set_ext *mext,u32 flags,void *data) +{ +if (SET_WITH_TIMEOUT (set) && +ip_set_timeout_expired (ext_timeout (data, set))) +return false; +if (SET_WITH_COUNTER (set)) { +struct ip_set_counter *counter =ext_counter (data, set); + +if (flags &IPSET_FLAG_MATCH_COUNTERS && + !(ip_set_match_counter (ip_set_get_packets (counter), + mext->packets, mext->packets_op) && +ip_set_match_counter (ip_set_get_bytes (counter), + mext->bytes, mext->bytes_op))) +return false; +ip_set_update_counter (counter, ext, flags); + } +if (SET_WITH_SKBINFO (set)) +ip_set_get_skbinfo (ext_skbinfo (data, set), + ext, mext, flags); +return true; +} +EXPORT_SYMBOL_GPL (ip_set_match_extensions); +/* Creating/destroying/renaming/swapping affect the existence and * the properties of a set. All of these can be executed from userspace * only and serialized by the nfnl mutex indirectly from nfnetlink.
net/netfilter/ipset/ip_set_hash_gen.h +14 -23
@@ -917,12 +917,9 @@ static inline int mtype_data_match(struct mtype_elem *data, const struct ip_set_ext *ext, struct ip_set_ext *mext, struct ip_set *set, u32 flags) { - if (SET_WITH_COUNTER(set)) - ip_set_update_counter(ext_counter(data, set), - ext, mext, flags); - if (SET_WITH_SKBINFO(set)) - ip_set_get_skbinfo(ext_skbinfo(data, set), - ext, mext, flags); + if (!ip_set_match_extensions(set, ext, mext, flags, data)) + return 0; + /* nomatch entries return -ENOTEMPTY */ return mtype_do_data_match(data); }
@@ -941,9 +938,9 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,struct mtype_elem *data;#if IPSET_NET_COUNT ==2 struct mtype_elem orig = *d; -int i, j =0 , k; +int ret, i, j =0 , k;#else -int i, j =0 ; +int ret, i, j =0 ;#endif u32 key, multi =0 ;
@@ -969,18 +966,13 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d, data =ahash_data (n, i, set->dsize);if (!mtype_data_equal (data, d, &multi))continue ; -if (SET_WITH_TIMEOUT (set)) { -if (!ip_set_timeout_expired ( -ext_timeout (data, set))) -return mtype_data_match (data, ext, - mext, set, - flags); + ret =mtype_data_match (data, ext, mext, set, flags); +if (ret !=0 ) +return ret;#ifdef IP_SET_HASH_WITH_MULTI - multi =0 ; +/* No match, reset multiple match flag */ + multi =0 ;#endif - }else -return mtype_data_match (data, ext, - mext, set, flags); }#if IPSET_NET_COUNT ==2 }
@@ -1027,12 +1019,11 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,if (!test_bit (i, n->used))continue ; data =ahash_data (n, i, set->dsize); -if (mtype_data_equal (data, d, &multi) && - !(SET_WITH_TIMEOUT (set) && -ip_set_timeout_expired (ext_timeout (data, set)))) { - ret =mtype_data_match (data, ext, mext, set, flags); +if (!mtype_data_equal (data, d, &multi)) +continue ; + ret =mtype_data_match (data, ext, mext, set, flags); +if (ret !=0 ) goto out; - } } out:return ret;
net/netfilter/ipset/ip_set_list_set.c +6 -15
@@ -55,8 +55,9 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb, struct ip_set_adt_opt *opt, const struct ip_set_ext *ext) { struct list_set *map = set->data; +struct ip_set_ext *mext = &opt->ext;struct set_elem *e; -u32 cmdflags = opt->cmdflags; +u32 flags = opt->cmdflags;int ret;/* Don't lookup sub-counters at all */
@@ -64,21 +65,11 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb,if (opt->cmdflags &IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE ) opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE ;list_for_each_entry_rcu (e, &map->members, list) { -if (SET_WITH_TIMEOUT (set) && -ip_set_timeout_expired (ext_timeout (e, set))) -continue ; ret =ip_set_test (e->id, skb, par, opt); -if (ret >0 ) { -if (SET_WITH_COUNTER (set)) -ip_set_update_counter (ext_counter (e, set), - ext, &opt->ext, - cmdflags); -if (SET_WITH_SKBINFO (set)) -ip_set_get_skbinfo (ext_skbinfo (e, set), - ext, &opt->ext, - cmdflags); -return ret; - } +if (ret <=0 ) +continue ; +if (ip_set_match_extensions (set, ext, mext, flags, e)) +return 1 ; }return 0 ; }
net/netfilter/xt_set.c +43 -76
198 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 52/52 netfilter: ipset: Missing nfnl_lock()/nfnl_unlock() is added to ip_set_net_exit()
In reply to Pablo Neira AyusoFrom: Jozsef Kadlecsik <[email protected]>
Patch "netfilter: ipset: use nfnl_mutex_is_locked" is added the real mutex locking check, which revealed the missing locking in ip_set_net_exit().
--- net/netfilter/ipset/ip_set_core.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/ipset/ip_set_core.c +2 -0
@@ -2078,6 +2078,7 @@ ip_set_net_exit(struct net *net) inst->is_deleted = true;/* flag for ip_set_nfnl_put */ +nfnl_lock (NFNL_SUBSYS_IPSET );for (i =0 ; i < inst->ip_set_max; i++) { set =ip_set (inst, i);if (set) {
@@ -2085,6 +2086,7 @@ ip_set_net_exit(struct net *net)ip_set_destroy_set (set); } } +nfnl_unlock (NFNL_SUBSYS_IPSET );kfree (rcu_dereference_protected (inst->ip_set_list,1 )); }
Signature · 1 line
2.11.0
David Miller
maintainerFrom: Pablo Neira Ayuso <[email protected]>
Date: Mon, 8 Jan 2018 21:19:08 +0100
Quoted 2 lines
The following patchset contains Netfilter/IPVS updates for your net-next tree:
...
Quoted 5 lines
4) Add generic flow table offload infrastructure for
nf_tables, this includes the netlink control plane and support for IPv4, IPv6 and mixed IPv4/IPv6 dataplanes. This comes with NAT support too. This patchset adds theIPS_OFFLOADconntrack status bit to indicate that this flow has been offloaded.
Have driver maintainers signed off on your offload design and driver interfaces?
I've pulled, but the above is really important to indicate when a new offload feature is added.
Thanks.
Pablo Neira Ayuso
maintainerQuoted 12 lines · David Miller
From: Pablo Neira Ayuso <[email protected]>
Date: Mon, 8 Jan 2018 21:19:08 +0100Quoted 2 lines
The following patchset contains Netfilter/IPVS updates for your net-next tree:
...
Quoted 5 lines
4) Add generic flow table offload infrastructure for
nf_tables, this includes the netlink control plane and support for IPv4, IPv6 and mixed IPv4/IPv6 dataplanes. This comes with NAT support too. This patchset adds theIPS_OFFLOADconntrack status bit to indicate that this flow has been offloaded.
Quoted 5 lines
Have driver maintainers signed off on your offload design and driver interfaces?
I've pulled, but the above is really important to indicate when a new offload feature is added.
Patch that adds driver interfaces have been kept back:
http://patchwork.ozlabs.org/patch/852537/
until there's an initial driver that uses the net_device hooks, as notes in the cover letter [1].
So far, this is a generic software flow table representation, that matches basic flow table hardware semantics but that also provides a software faster path. So you can use it to purely forward packets between two nics even if they come with no hardware offload support. Numbers are available in my last NetDev 2.2 presentation
Regarding the design, feedback from vendors has been positive.
Thanks !
[1] https://lwn.net/Articles/742164/
[2] https://www.netdevconf.org/2.2/slides/ayuso-netfilter-workshop.pdf
(slide number 19).