Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

The following batch contains netfilter updates for net-next. Basically,
enhancements for xt_recent, skip zeroing of timer in conntrack, fix
linking problem with recent redirect support for nf_tables, ipset
updates and a couple of cleanups. More specifically, they are:

1) Rise maximum number per IP address to be remembered in xt_recent
while retaining backward compatibility, from Florian Westphal.

2) Skip zeroing timer area in nf_conn objects, also from Florian.

3) Inspect IPv4 and IPv6 traffic from the bridge to allow filtering using
using meta l4proto and transport layer header, from Alvaro Neira.

4) Fix linking problems in the new redirect support when CONFIG_IPV6=n
and IP6_NF_IPTABLES=n.

And ipset updates from Jozsef Kadlecsik:

5) Support updating element extensions when the set is full (fixes
netfilter bugzilla id 880).

6) Fix set match with 32-bits userspace / 64-bits kernel.

7) Indicate explicitly when /0 networks are supported in ipset.

8) Simplify cidr handling for hash:*net* types.

9) Allocate the proper size of memory when /0 networks are supported.

10) Explicitly add padding elements to hash:net,net and hash:net,port,
because the elements must be u32 sized for the used hash function.

Jozsef is also cooking ipset RCU conversion which should land soon if
they reach the merge window in time.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+372 -254
-9
include/net/netfilter/ipv4/nf_nat_redirect.h
··· 1 - #ifndef _NF_NAT_REDIRECT_IPV4_H_ 2 - #define _NF_NAT_REDIRECT_IPV4_H_ 3 - 4 - unsigned int 5 - nf_nat_redirect_ipv4(struct sk_buff *skb, 6 - const struct nf_nat_ipv4_multi_range_compat *mr, 7 - unsigned int hooknum); 8 - 9 - #endif /* _NF_NAT_REDIRECT_IPV4_H_ */
-8
include/net/netfilter/ipv6/nf_nat_redirect.h
··· 1 - #ifndef _NF_NAT_REDIRECT_IPV6_H_ 2 - #define _NF_NAT_REDIRECT_IPV6_H_ 3 - 4 - unsigned int 5 - nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, 6 - unsigned int hooknum); 7 - 8 - #endif /* _NF_NAT_REDIRECT_IPV6_H_ */
+9 -6
include/net/netfilter/nf_conntrack.h
··· 92 92 /* Have we seen traffic both ways yet? (bitset) */ 93 93 unsigned long status; 94 94 95 - /* If we were expected by an expectation, this will be it */ 96 - struct nf_conn *master; 97 - 98 95 /* Timer function; drops refcnt when it goes off. */ 99 96 struct timer_list timeout; 97 + 98 + #ifdef CONFIG_NET_NS 99 + struct net *ct_net; 100 + #endif 101 + /* all members below initialized via memset */ 102 + u8 __nfct_init_offset[0]; 103 + 104 + /* If we were expected by an expectation, this will be it */ 105 + struct nf_conn *master; 100 106 101 107 #if defined(CONFIG_NF_CONNTRACK_MARK) 102 108 u_int32_t mark; ··· 114 108 115 109 /* Extensions */ 116 110 struct nf_ct_ext *ext; 117 - #ifdef CONFIG_NET_NS 118 - struct net *ct_net; 119 - #endif 120 111 121 112 /* Storage reserved for other modules, must be the last member */ 122 113 union nf_conntrack_proto proto;
+12
include/net/netfilter/nf_nat_redirect.h
··· 1 + #ifndef _NF_NAT_REDIRECT_H_ 2 + #define _NF_NAT_REDIRECT_H_ 3 + 4 + unsigned int 5 + nf_nat_redirect_ipv4(struct sk_buff *skb, 6 + const struct nf_nat_ipv4_multi_range_compat *mr, 7 + unsigned int hooknum); 8 + unsigned int 9 + nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, 10 + unsigned int hooknum); 11 + 12 + #endif /* _NF_NAT_REDIRECT_H_ */
+7
include/net/netfilter/nf_tables_bridge.h
··· 1 + #ifndef _NET_NF_TABLES_BRIDGE_H 2 + #define _NET_NF_TABLES_BRIDGE_H 3 + 4 + int nft_bridge_iphdr_validate(struct sk_buff *skb); 5 + int nft_bridge_ip6hdr_validate(struct sk_buff *skb); 6 + 7 + #endif /* _NET_NF_TABLES_BRIDGE_H */
+7 -1
include/uapi/linux/netfilter/ipset/ip_set.h
··· 256 256 IPSET_COUNTER_GT, 257 257 }; 258 258 259 - struct ip_set_counter_match { 259 + /* Backward compatibility for set match v3 */ 260 + struct ip_set_counter_match0 { 260 261 __u8 op; 261 262 __u64 value; 263 + }; 264 + 265 + struct ip_set_counter_match { 266 + __aligned_u64 value; 267 + __u8 op; 262 268 }; 263 269 264 270 /* Interface to iptables/ip6tables */
+11 -2
include/uapi/linux/netfilter/xt_set.h
··· 66 66 67 67 struct xt_set_info_match_v3 { 68 68 struct xt_set_info match_set; 69 - struct ip_set_counter_match packets; 70 - struct ip_set_counter_match bytes; 69 + struct ip_set_counter_match0 packets; 70 + struct ip_set_counter_match0 bytes; 71 71 __u32 flags; 72 72 }; 73 73 ··· 79 79 struct xt_set_info map_set; 80 80 __u32 flags; 81 81 __u32 timeout; 82 + }; 83 + 84 + /* Revision 4 match */ 85 + 86 + struct xt_set_info_match_v4 { 87 + struct xt_set_info match_set; 88 + struct ip_set_counter_match packets; 89 + struct ip_set_counter_match bytes; 90 + __u32 flags; 82 91 }; 83 92 84 93 #endif /*_XT_SET_H*/
+87 -1
net/bridge/netfilter/nf_tables_bridge.c
··· 13 13 #include <linux/module.h> 14 14 #include <linux/netfilter_bridge.h> 15 15 #include <net/netfilter/nf_tables.h> 16 + #include <net/netfilter/nf_tables_bridge.h> 17 + #include <linux/ip.h> 18 + #include <linux/ipv6.h> 19 + #include <net/netfilter/nf_tables_ipv4.h> 20 + #include <net/netfilter/nf_tables_ipv6.h> 21 + 22 + int nft_bridge_iphdr_validate(struct sk_buff *skb) 23 + { 24 + struct iphdr *iph; 25 + u32 len; 26 + 27 + if (!pskb_may_pull(skb, sizeof(struct iphdr))) 28 + return 0; 29 + 30 + iph = ip_hdr(skb); 31 + if (iph->ihl < 5 || iph->version != 4) 32 + return 0; 33 + 34 + len = ntohs(iph->tot_len); 35 + if (skb->len < len) 36 + return 0; 37 + else if (len < (iph->ihl*4)) 38 + return 0; 39 + 40 + if (!pskb_may_pull(skb, iph->ihl*4)) 41 + return 0; 42 + 43 + return 1; 44 + } 45 + EXPORT_SYMBOL_GPL(nft_bridge_iphdr_validate); 46 + 47 + int nft_bridge_ip6hdr_validate(struct sk_buff *skb) 48 + { 49 + struct ipv6hdr *hdr; 50 + u32 pkt_len; 51 + 52 + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 53 + return 0; 54 + 55 + hdr = ipv6_hdr(skb); 56 + if (hdr->version != 6) 57 + return 0; 58 + 59 + pkt_len = ntohs(hdr->payload_len); 60 + if (pkt_len + sizeof(struct ipv6hdr) > skb->len) 61 + return 0; 62 + 63 + return 1; 64 + } 65 + EXPORT_SYMBOL_GPL(nft_bridge_ip6hdr_validate); 66 + 67 + static inline void nft_bridge_set_pktinfo_ipv4(struct nft_pktinfo *pkt, 68 + const struct nf_hook_ops *ops, 69 + struct sk_buff *skb, 70 + const struct net_device *in, 71 + const struct net_device *out) 72 + { 73 + if (nft_bridge_iphdr_validate(skb)) 74 + nft_set_pktinfo_ipv4(pkt, ops, skb, in, out); 75 + else 76 + nft_set_pktinfo(pkt, ops, skb, in, out); 77 + } 78 + 79 + static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt, 80 + const struct nf_hook_ops *ops, 81 + struct sk_buff *skb, 82 + const struct net_device *in, 83 + const struct net_device *out) 84 + { 85 + #if IS_ENABLED(CONFIG_IPV6) 86 + if (nft_bridge_ip6hdr_validate(skb) && 87 + nft_set_pktinfo_ipv6(pkt, ops, skb, in, out) == 0) 88 + return; 89 + #endif 90 + nft_set_pktinfo(pkt, ops, skb, in, out); 91 + } 16 92 17 93 static unsigned int 18 94 nft_do_chain_bridge(const struct nf_hook_ops *ops, ··· 99 23 { 100 24 struct nft_pktinfo pkt; 101 25 102 - nft_set_pktinfo(&pkt, ops, skb, in, out); 26 + switch (eth_hdr(skb)->h_proto) { 27 + case htons(ETH_P_IP): 28 + nft_bridge_set_pktinfo_ipv4(&pkt, ops, skb, in, out); 29 + break; 30 + case htons(ETH_P_IPV6): 31 + nft_bridge_set_pktinfo_ipv6(&pkt, ops, skb, in, out); 32 + break; 33 + default: 34 + nft_set_pktinfo(&pkt, ops, skb, in, out); 35 + break; 36 + } 103 37 104 38 return nft_do_chain(&pkt, ops); 105 39 }
+5 -47
net/bridge/netfilter/nft_reject_bridge.c
··· 14 14 #include <linux/netfilter/nf_tables.h> 15 15 #include <net/netfilter/nf_tables.h> 16 16 #include <net/netfilter/nft_reject.h> 17 + #include <net/netfilter/nf_tables_bridge.h> 17 18 #include <net/netfilter/ipv4/nf_reject.h> 18 19 #include <net/netfilter/ipv6/nf_reject.h> 19 20 #include <linux/ip.h> ··· 36 35 skb_pull(nskb, ETH_HLEN); 37 36 } 38 37 39 - static int nft_reject_iphdr_validate(struct sk_buff *oldskb) 40 - { 41 - struct iphdr *iph; 42 - u32 len; 43 - 44 - if (!pskb_may_pull(oldskb, sizeof(struct iphdr))) 45 - return 0; 46 - 47 - iph = ip_hdr(oldskb); 48 - if (iph->ihl < 5 || iph->version != 4) 49 - return 0; 50 - 51 - len = ntohs(iph->tot_len); 52 - if (oldskb->len < len) 53 - return 0; 54 - else if (len < (iph->ihl*4)) 55 - return 0; 56 - 57 - if (!pskb_may_pull(oldskb, iph->ihl*4)) 58 - return 0; 59 - 60 - return 1; 61 - } 62 - 63 38 static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) 64 39 { 65 40 struct sk_buff *nskb; ··· 43 66 const struct tcphdr *oth; 44 67 struct tcphdr _oth; 45 68 46 - if (!nft_reject_iphdr_validate(oldskb)) 69 + if (!nft_bridge_iphdr_validate(oldskb)) 47 70 return; 48 71 49 72 oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); ··· 78 101 void *payload; 79 102 __wsum csum; 80 103 81 - if (!nft_reject_iphdr_validate(oldskb)) 104 + if (!nft_bridge_iphdr_validate(oldskb)) 82 105 return; 83 106 84 107 /* IP header checks: fragment. */ ··· 123 146 br_deliver(br_port_get_rcu(oldskb->dev), nskb); 124 147 } 125 148 126 - static int nft_reject_ip6hdr_validate(struct sk_buff *oldskb) 127 - { 128 - struct ipv6hdr *hdr; 129 - u32 pkt_len; 130 - 131 - if (!pskb_may_pull(oldskb, sizeof(struct ipv6hdr))) 132 - return 0; 133 - 134 - hdr = ipv6_hdr(oldskb); 135 - if (hdr->version != 6) 136 - return 0; 137 - 138 - pkt_len = ntohs(hdr->payload_len); 139 - if (pkt_len + sizeof(struct ipv6hdr) > oldskb->len) 140 - return 0; 141 - 142 - return 1; 143 - } 144 - 145 149 static void nft_reject_br_send_v6_tcp_reset(struct net *net, 146 150 struct sk_buff *oldskb, int hook) 147 151 { ··· 132 174 unsigned int otcplen; 133 175 struct ipv6hdr *nip6h; 134 176 135 - if (!nft_reject_ip6hdr_validate(oldskb)) 177 + if (!nft_bridge_ip6hdr_validate(oldskb)) 136 178 return; 137 179 138 180 oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook); ··· 165 207 unsigned int len; 166 208 void *payload; 167 209 168 - if (!nft_reject_ip6hdr_validate(oldskb)) 210 + if (!nft_bridge_ip6hdr_validate(oldskb)) 169 211 return; 170 212 171 213 /* Include "As much of invoking packet as possible without the ICMPv6
+1 -7
net/ipv4/netfilter/Kconfig
··· 104 104 This is the kernel functionality to provide NAT in the masquerade 105 105 flavour (automatic source address selection). 106 106 107 - config NF_NAT_REDIRECT_IPV4 108 - tristate "IPv4 redirect support" 109 - help 110 - This is the kernel functionality to provide NAT in the redirect 111 - flavour (redirect packets to local machine). 112 - 113 107 config NFT_MASQ_IPV4 114 108 tristate "IPv4 masquerading support for nf_tables" 115 109 depends on NF_TABLES_IPV4 ··· 117 123 tristate "IPv4 redirect support for nf_tables" 118 124 depends on NF_TABLES_IPV4 119 125 depends on NFT_REDIR 120 - select NF_NAT_REDIRECT_IPV4 126 + select NF_NAT_REDIRECT 121 127 help 122 128 This is the expression that provides IPv4 redirect support for 123 129 nf_tables.
-1
net/ipv4/netfilter/Makefile
··· 31 31 obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o 32 32 obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o 33 33 obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o 34 - obj-$(CONFIG_NF_NAT_REDIRECT_IPV4) += nf_nat_redirect_ipv4.o 35 34 36 35 # NAT protocols (nf_nat) 37 36 obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
+46 -1
net/ipv4/netfilter/nf_nat_redirect_ipv4.c net/netfilter/nf_nat_redirect.c
··· 20 20 #include <linux/netfilter.h> 21 21 #include <linux/types.h> 22 22 #include <linux/netfilter_ipv4.h> 23 + #include <linux/netfilter_ipv6.h> 23 24 #include <linux/netfilter/x_tables.h> 24 25 #include <net/addrconf.h> 25 26 #include <net/checksum.h> 26 27 #include <net/protocol.h> 27 28 #include <net/netfilter/nf_nat.h> 28 - #include <net/netfilter/ipv4/nf_nat_redirect.h> 29 + #include <net/netfilter/nf_nat_redirect.h> 29 30 30 31 unsigned int 31 32 nf_nat_redirect_ipv4(struct sk_buff *skb, ··· 78 77 return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); 79 78 } 80 79 EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4); 80 + 81 + static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; 82 + 83 + unsigned int 84 + nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, 85 + unsigned int hooknum) 86 + { 87 + struct nf_nat_range newrange; 88 + struct in6_addr newdst; 89 + enum ip_conntrack_info ctinfo; 90 + struct nf_conn *ct; 91 + 92 + ct = nf_ct_get(skb, &ctinfo); 93 + if (hooknum == NF_INET_LOCAL_OUT) { 94 + newdst = loopback_addr; 95 + } else { 96 + struct inet6_dev *idev; 97 + struct inet6_ifaddr *ifa; 98 + bool addr = false; 99 + 100 + rcu_read_lock(); 101 + idev = __in6_dev_get(skb->dev); 102 + if (idev != NULL) { 103 + list_for_each_entry(ifa, &idev->addr_list, if_list) { 104 + newdst = ifa->addr; 105 + addr = true; 106 + break; 107 + } 108 + } 109 + rcu_read_unlock(); 110 + 111 + if (!addr) 112 + return NF_DROP; 113 + } 114 + 115 + newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; 116 + newrange.min_addr.in6 = newdst; 117 + newrange.max_addr.in6 = newdst; 118 + newrange.min_proto = range->min_proto; 119 + newrange.max_proto = range->max_proto; 120 + 121 + return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); 122 + } 123 + EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv6); 81 124 82 125 MODULE_LICENSE("GPL"); 83 126 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+1 -1
net/ipv4/netfilter/nft_redir_ipv4.c
··· 14 14 #include <linux/netfilter/nf_tables.h> 15 15 #include <net/netfilter/nf_tables.h> 16 16 #include <net/netfilter/nf_nat.h> 17 - #include <net/netfilter/ipv4/nf_nat_redirect.h> 17 + #include <net/netfilter/nf_nat_redirect.h> 18 18 #include <net/netfilter/nft_redir.h> 19 19 20 20 static void nft_redir_ipv4_eval(const struct nft_expr *expr,
+1 -7
net/ipv6/netfilter/Kconfig
··· 82 82 This is the kernel functionality to provide NAT in the masquerade 83 83 flavour (automatic source address selection) for IPv6. 84 84 85 - config NF_NAT_REDIRECT_IPV6 86 - tristate "IPv6 redirect support" 87 - help 88 - This is the kernel functionality to provide NAT in the redirect 89 - flavour (redirect packet to local machine) for IPv6. 90 - 91 85 config NFT_MASQ_IPV6 92 86 tristate "IPv6 masquerade support for nf_tables" 93 87 depends on NF_TABLES_IPV6 ··· 95 101 tristate "IPv6 redirect support for nf_tables" 96 102 depends on NF_TABLES_IPV6 97 103 depends on NFT_REDIR 98 - select NF_NAT_REDIRECT_IPV6 104 + select NF_NAT_REDIRECT 99 105 help 100 106 This is the expression that provides IPv4 redirect support for 101 107 nf_tables.
-1
net/ipv6/netfilter/Makefile
··· 19 19 nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o 20 20 obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o 21 21 obj-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o 22 - obj-$(CONFIG_NF_NAT_REDIRECT_IPV6) += nf_nat_redirect_ipv6.o 23 22 24 23 # defrag 25 24 nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
+1 -1
net/ipv6/netfilter/nf_log_ipv6.c
··· 422 422 module_exit(nf_log_ipv6_exit); 423 423 424 424 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 425 - MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); 425 + MODULE_DESCRIPTION("Netfilter IPv6 packet logging"); 426 426 MODULE_LICENSE("GPL"); 427 427 MODULE_ALIAS_NF_LOGGER(AF_INET6, 0);
-75
net/ipv6/netfilter/nf_nat_redirect_ipv6.c
··· 1 - /* 2 - * (C) 1999-2001 Paul `Rusty' Russell 3 - * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> 4 - * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation. 9 - * 10 - * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 11 - * NAT funded by Astaro. 12 - */ 13 - 14 - #include <linux/if.h> 15 - #include <linux/inetdevice.h> 16 - #include <linux/ip.h> 17 - #include <linux/kernel.h> 18 - #include <linux/module.h> 19 - #include <linux/netdevice.h> 20 - #include <linux/netfilter.h> 21 - #include <linux/types.h> 22 - #include <linux/netfilter_ipv6.h> 23 - #include <linux/netfilter/x_tables.h> 24 - #include <net/addrconf.h> 25 - #include <net/checksum.h> 26 - #include <net/protocol.h> 27 - #include <net/netfilter/nf_nat.h> 28 - #include <net/netfilter/ipv6/nf_nat_redirect.h> 29 - 30 - static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; 31 - 32 - unsigned int 33 - nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, 34 - unsigned int hooknum) 35 - { 36 - struct nf_nat_range newrange; 37 - struct in6_addr newdst; 38 - enum ip_conntrack_info ctinfo; 39 - struct nf_conn *ct; 40 - 41 - ct = nf_ct_get(skb, &ctinfo); 42 - if (hooknum == NF_INET_LOCAL_OUT) { 43 - newdst = loopback_addr; 44 - } else { 45 - struct inet6_dev *idev; 46 - struct inet6_ifaddr *ifa; 47 - bool addr = false; 48 - 49 - rcu_read_lock(); 50 - idev = __in6_dev_get(skb->dev); 51 - if (idev != NULL) { 52 - list_for_each_entry(ifa, &idev->addr_list, if_list) { 53 - newdst = ifa->addr; 54 - addr = true; 55 - break; 56 - } 57 - } 58 - rcu_read_unlock(); 59 - 60 - if (!addr) 61 - return NF_DROP; 62 - } 63 - 64 - newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; 65 - newrange.min_addr.in6 = newdst; 66 - newrange.max_addr.in6 = newdst; 67 - newrange.min_proto = range->min_proto; 68 - newrange.max_proto = range->max_proto; 69 - 70 - return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); 71 - } 72 - EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv6); 73 - 74 - MODULE_LICENSE("GPL"); 75 - MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+1 -1
net/ipv6/netfilter/nft_redir_ipv6.c
··· 15 15 #include <net/netfilter/nf_tables.h> 16 16 #include <net/netfilter/nf_nat.h> 17 17 #include <net/netfilter/nft_redir.h> 18 - #include <net/netfilter/ipv6/nf_nat_redirect.h> 18 + #include <net/netfilter/nf_nat_redirect.h> 19 19 20 20 static void nft_redir_ipv6_eval(const struct nft_expr *expr, 21 21 struct nft_data data[NFT_REG_MAX + 1],
+8 -2
net/netfilter/Kconfig
··· 411 411 depends on NF_CONNTRACK && NF_NAT 412 412 default NF_NAT && NF_CONNTRACK_TFTP 413 413 414 + config NF_NAT_REDIRECT 415 + tristate "IPv4/IPv6 redirect support" 416 + depends on NF_NAT 417 + help 418 + This is the kernel functionality to redirect packets to local 419 + machine through NAT. 420 + 414 421 config NETFILTER_SYNPROXY 415 422 tristate 416 423 ··· 851 844 config NETFILTER_XT_TARGET_REDIRECT 852 845 tristate "REDIRECT target support" 853 846 depends on NF_NAT 854 - select NF_NAT_REDIRECT_IPV4 if NF_NAT_IPV4 855 - select NF_NAT_REDIRECT_IPV6 if NF_NAT_IPV6 847 + select NF_NAT_REDIRECT 856 848 ---help--- 857 849 REDIRECT is a special case of NAT: all incoming connections are 858 850 mapped onto the incoming interface's address, causing the packets to
+1
net/netfilter/Makefile
··· 51 51 obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o 52 52 53 53 obj-$(CONFIG_NF_NAT) += nf_nat.o 54 + obj-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o 54 55 55 56 # NAT protocols (nf_nat) 56 57 obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
+47 -54
net/netfilter/ipset/ip_set_hash_gen.h
··· 147 147 #else 148 148 #define __CIDR(cidr, i) (cidr) 149 149 #endif 150 + 151 + /* cidr + 1 is stored in net_prefixes to support /0 */ 152 + #define SCIDR(cidr, i) (__CIDR(cidr, i) + 1) 153 + 150 154 #ifdef IP_SET_HASH_WITH_NETS_PACKED 151 - /* When cidr is packed with nomatch, cidr - 1 is stored in the entry */ 152 - #define CIDR(cidr, i) (__CIDR(cidr, i) + 1) 155 + /* When cidr is packed with nomatch, cidr - 1 is stored in the data entry */ 156 + #define GCIDR(cidr, i) (__CIDR(cidr, i) + 1) 157 + #define NCIDR(cidr) (cidr) 153 158 #else 154 - #define CIDR(cidr, i) (__CIDR(cidr, i)) 159 + #define GCIDR(cidr, i) (__CIDR(cidr, i)) 160 + #define NCIDR(cidr) (cidr - 1) 155 161 #endif 156 162 157 163 #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) 158 164 159 - #ifdef IP_SET_HASH_WITH_MULTI 165 + #ifdef IP_SET_HASH_WITH_NET0 160 166 #define NLEN(family) (SET_HOST_MASK(family) + 1) 161 167 #else 162 168 #define NLEN(family) SET_HOST_MASK(family) ··· 298 292 int i, j; 299 293 300 294 /* Add in increasing prefix order, so larger cidr first */ 301 - for (i = 0, j = -1; i < nets_length && h->nets[i].nets[n]; i++) { 295 + for (i = 0, j = -1; i < nets_length && h->nets[i].cidr[n]; i++) { 302 296 if (j != -1) 303 297 continue; 304 298 else if (h->nets[i].cidr[n] < cidr) 305 299 j = i; 306 300 else if (h->nets[i].cidr[n] == cidr) { 307 - h->nets[i].nets[n]++; 301 + h->nets[cidr - 1].nets[n]++; 308 302 return; 309 303 } 310 304 } 311 305 if (j != -1) { 312 - for (; i > j; i--) { 306 + for (; i > j; i--) 313 307 h->nets[i].cidr[n] = h->nets[i - 1].cidr[n]; 314 - h->nets[i].nets[n] = h->nets[i - 1].nets[n]; 315 - } 316 308 } 317 309 h->nets[i].cidr[n] = cidr; 318 - h->nets[i].nets[n] = 1; 310 + h->nets[cidr - 1].nets[n] = 1; 319 311 } 320 312 321 313 static void ··· 324 320 for (i = 0; i < nets_length; i++) { 325 321 if (h->nets[i].cidr[n] != cidr) 326 322 continue; 327 - if (h->nets[i].nets[n] > 1 || i == net_end || 328 - h->nets[i + 1].nets[n] == 0) { 329 - h->nets[i].nets[n]--; 323 + h->nets[cidr -1].nets[n]--; 324 + if (h->nets[cidr -1].nets[n] > 0) 330 325 return; 331 - } 332 - for (j = i; j < net_end && h->nets[j].nets[n]; j++) { 326 + for (j = i; j < net_end && h->nets[j].cidr[n]; j++) 333 327 h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; 334 - h->nets[j].nets[n] = h->nets[j + 1].nets[n]; 335 - } 336 - h->nets[j].nets[n] = 0; 328 + h->nets[j].cidr[n] = 0; 337 329 return; 338 330 } 339 331 } ··· 486 486 pr_debug("expired %u/%u\n", i, j); 487 487 #ifdef IP_SET_HASH_WITH_NETS 488 488 for (k = 0; k < IPSET_NET_COUNT; k++) 489 - mtype_del_cidr(h, CIDR(data->cidr, k), 489 + mtype_del_cidr(h, SCIDR(data->cidr, k), 490 490 nets_length, k); 491 491 #endif 492 492 ip_set_ext_destroy(set, data); ··· 633 633 bool flag_exist = flags & IPSET_FLAG_EXIST; 634 634 u32 key, multi = 0; 635 635 636 - if (h->elements >= h->maxelem && SET_WITH_FORCEADD(set)) { 637 - rcu_read_lock_bh(); 638 - t = rcu_dereference_bh(h->table); 639 - key = HKEY(value, h->initval, t->htable_bits); 640 - n = hbucket(t,key); 641 - if (n->pos) { 642 - /* Choosing the first entry in the array to replace */ 643 - j = 0; 644 - goto reuse_slot; 645 - } 646 - rcu_read_unlock_bh(); 647 - } 648 - if (SET_WITH_TIMEOUT(set) && h->elements >= h->maxelem) 649 - /* FIXME: when set is full, we slow down here */ 650 - mtype_expire(set, h, NLEN(set->family), set->dsize); 651 - 652 - if (h->elements >= h->maxelem) { 653 - if (net_ratelimit()) 654 - pr_warn("Set %s is full, maxelem %u reached\n", 655 - set->name, h->maxelem); 656 - return -IPSET_ERR_HASH_FULL; 657 - } 658 - 659 636 rcu_read_lock_bh(); 660 637 t = rcu_dereference_bh(h->table); 661 638 key = HKEY(value, h->initval, t->htable_bits); ··· 657 680 j != AHASH_MAX(h) + 1) 658 681 j = i; 659 682 } 683 + if (h->elements >= h->maxelem && SET_WITH_FORCEADD(set) && n->pos) { 684 + /* Choosing the first entry in the array to replace */ 685 + j = 0; 686 + goto reuse_slot; 687 + } 688 + if (SET_WITH_TIMEOUT(set) && h->elements >= h->maxelem) 689 + /* FIXME: when set is full, we slow down here */ 690 + mtype_expire(set, h, NLEN(set->family), set->dsize); 691 + 692 + if (h->elements >= h->maxelem) { 693 + if (net_ratelimit()) 694 + pr_warn("Set %s is full, maxelem %u reached\n", 695 + set->name, h->maxelem); 696 + ret = -IPSET_ERR_HASH_FULL; 697 + goto out; 698 + } 699 + 660 700 reuse_slot: 661 701 if (j != AHASH_MAX(h) + 1) { 662 702 /* Fill out reused slot */ 663 703 data = ahash_data(n, j, set->dsize); 664 704 #ifdef IP_SET_HASH_WITH_NETS 665 705 for (i = 0; i < IPSET_NET_COUNT; i++) { 666 - mtype_del_cidr(h, CIDR(data->cidr, i), 706 + mtype_del_cidr(h, SCIDR(data->cidr, i), 667 707 NLEN(set->family), i); 668 - mtype_add_cidr(h, CIDR(d->cidr, i), 708 + mtype_add_cidr(h, SCIDR(d->cidr, i), 669 709 NLEN(set->family), i); 670 710 } 671 711 #endif ··· 699 705 data = ahash_data(n, n->pos++, set->dsize); 700 706 #ifdef IP_SET_HASH_WITH_NETS 701 707 for (i = 0; i < IPSET_NET_COUNT; i++) 702 - mtype_add_cidr(h, CIDR(d->cidr, i), NLEN(set->family), 708 + mtype_add_cidr(h, SCIDR(d->cidr, i), NLEN(set->family), 703 709 i); 704 710 #endif 705 711 h->elements++; ··· 760 766 h->elements--; 761 767 #ifdef IP_SET_HASH_WITH_NETS 762 768 for (j = 0; j < IPSET_NET_COUNT; j++) 763 - mtype_del_cidr(h, CIDR(d->cidr, j), NLEN(set->family), 769 + mtype_del_cidr(h, SCIDR(d->cidr, j), NLEN(set->family), 764 770 j); 765 771 #endif 766 772 ip_set_ext_destroy(set, data); ··· 821 827 u8 nets_length = NLEN(set->family); 822 828 823 829 pr_debug("test by nets\n"); 824 - for (; j < nets_length && h->nets[j].nets[0] && !multi; j++) { 830 + for (; j < nets_length && h->nets[j].cidr[0] && !multi; j++) { 825 831 #if IPSET_NET_COUNT == 2 826 832 mtype_data_reset_elem(d, &orig); 827 - mtype_data_netmask(d, h->nets[j].cidr[0], false); 828 - for (k = 0; k < nets_length && h->nets[k].nets[1] && !multi; 833 + mtype_data_netmask(d, NCIDR(h->nets[j].cidr[0]), false); 834 + for (k = 0; k < nets_length && h->nets[k].cidr[1] && !multi; 829 835 k++) { 830 - mtype_data_netmask(d, h->nets[k].cidr[1], true); 836 + mtype_data_netmask(d, NCIDR(h->nets[k].cidr[1]), true); 831 837 #else 832 - mtype_data_netmask(d, h->nets[j].cidr[0]); 838 + mtype_data_netmask(d, NCIDR(h->nets[j].cidr[0])); 833 839 #endif 834 840 key = HKEY(d, h->initval, t->htable_bits); 835 841 n = hbucket(t, key); ··· 877 883 /* If we test an IP address and not a network address, 878 884 * try all possible network sizes */ 879 885 for (i = 0; i < IPSET_NET_COUNT; i++) 880 - if (CIDR(d->cidr, i) != SET_HOST_MASK(set->family)) 886 + if (GCIDR(d->cidr, i) != SET_HOST_MASK(set->family)) 881 887 break; 882 888 if (i == IPSET_NET_COUNT) { 883 889 ret = mtype_test_cidrs(set, d, ext, mext, flags); ··· 1101 1107 1102 1108 hsize = sizeof(*h); 1103 1109 #ifdef IP_SET_HASH_WITH_NETS 1104 - hsize += sizeof(struct net_prefixes) * 1105 - (set->family == NFPROTO_IPV4 ? 32 : 128); 1110 + hsize += sizeof(struct net_prefixes) * NLEN(set->family); 1106 1111 #endif 1107 1112 h = kzalloc(hsize, GFP_KERNEL); 1108 1113 if (!h)
+1
net/netfilter/ipset/ip_set_hash_netiface.c
··· 115 115 #define IP_SET_HASH_WITH_NETS 116 116 #define IP_SET_HASH_WITH_RBTREE 117 117 #define IP_SET_HASH_WITH_MULTI 118 + #define IP_SET_HASH_WITH_NET0 118 119 119 120 #define STREQ(a, b) (strcmp(a, b) == 0) 120 121
+2
net/netfilter/ipset/ip_set_hash_netnet.c
··· 46 46 __be64 ipcmp; 47 47 }; 48 48 u8 nomatch; 49 + u8 padding; 49 50 union { 50 51 u8 cidr[2]; 51 52 u16 ccmp; ··· 272 271 struct hash_netnet6_elem { 273 272 union nf_inet_addr ip[2]; 274 273 u8 nomatch; 274 + u8 padding; 275 275 union { 276 276 u8 cidr[2]; 277 277 u16 ccmp;
+2
net/netfilter/ipset/ip_set_hash_netportnet.c
··· 53 53 u8 cidr[2]; 54 54 u16 ccmp; 55 55 }; 56 + u16 padding; 56 57 u8 nomatch:1; 57 58 u8 proto; 58 59 }; ··· 325 324 u8 cidr[2]; 326 325 u16 ccmp; 327 326 }; 327 + u16 padding; 328 328 u8 nomatch:1; 329 329 u8 proto; 330 330 };
+4 -7
net/netfilter/nf_conntrack_core.c
··· 824 824 atomic_dec(&net->ct.count); 825 825 return ERR_PTR(-ENOMEM); 826 826 } 827 - /* 828 - * Let ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.next 829 - * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged. 830 - */ 831 - memset(&ct->tuplehash[IP_CT_DIR_MAX], 0, 832 - offsetof(struct nf_conn, proto) - 833 - offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX])); 834 827 spin_lock_init(&ct->lock); 835 828 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; 836 829 ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL; 837 830 ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; 838 831 /* save hash for reusing when confirming */ 839 832 *(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash; 833 + ct->status = 0; 840 834 /* Don't set timer yet: wait for confirmation */ 841 835 setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); 842 836 write_pnet(&ct->ct_net, net); 837 + memset(&ct->__nfct_init_offset[0], 0, 838 + offsetof(struct nf_conn, proto) - 839 + offsetof(struct nf_conn, __nfct_init_offset[0])); 843 840 #ifdef CONFIG_NF_CONNTRACK_ZONES 844 841 if (zone) { 845 842 struct nf_conntrack_zone *nf_ct_zone;
+1 -2
net/netfilter/xt_REDIRECT.c
··· 26 26 #include <net/checksum.h> 27 27 #include <net/protocol.h> 28 28 #include <net/netfilter/nf_nat.h> 29 - #include <net/netfilter/ipv4/nf_nat_redirect.h> 30 - #include <net/netfilter/ipv6/nf_nat_redirect.h> 29 + #include <net/netfilter/nf_nat_redirect.h> 31 30 32 31 static unsigned int 33 32 redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)
+47 -17
net/netfilter/xt_recent.c
··· 43 43 MODULE_ALIAS("ipt_recent"); 44 44 MODULE_ALIAS("ip6t_recent"); 45 45 46 - static unsigned int ip_list_tot = 100; 47 - static unsigned int ip_pkt_list_tot = 20; 48 - static unsigned int ip_list_hash_size = 0; 49 - static unsigned int ip_list_perms = 0644; 50 - static unsigned int ip_list_uid = 0; 51 - static unsigned int ip_list_gid = 0; 46 + static unsigned int ip_list_tot __read_mostly = 100; 47 + static unsigned int ip_list_hash_size __read_mostly; 48 + static unsigned int ip_list_perms __read_mostly = 0644; 49 + static unsigned int ip_list_uid __read_mostly; 50 + static unsigned int ip_list_gid __read_mostly; 52 51 module_param(ip_list_tot, uint, 0400); 53 - module_param(ip_pkt_list_tot, uint, 0400); 54 52 module_param(ip_list_hash_size, uint, 0400); 55 53 module_param(ip_list_perms, uint, 0400); 56 54 module_param(ip_list_uid, uint, S_IRUGO | S_IWUSR); 57 55 module_param(ip_list_gid, uint, S_IRUGO | S_IWUSR); 58 56 MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list"); 59 - MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP address to remember (max. 255)"); 60 57 MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); 61 58 MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files"); 62 59 MODULE_PARM_DESC(ip_list_uid, "default owner of /proc/net/xt_recent/* files"); 63 60 MODULE_PARM_DESC(ip_list_gid, "default owning group of /proc/net/xt_recent/* files"); 61 + 62 + /* retained for backwards compatibility */ 63 + static unsigned int ip_pkt_list_tot __read_mostly; 64 + module_param(ip_pkt_list_tot, uint, 0400); 65 + MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP address to remember (max. 255)"); 66 + 67 + #define XT_RECENT_MAX_NSTAMPS 256 64 68 65 69 struct recent_entry { 66 70 struct list_head list; ··· 83 79 union nf_inet_addr mask; 84 80 unsigned int refcnt; 85 81 unsigned int entries; 82 + u8 nstamps_max_mask; 86 83 struct list_head lru_list; 87 84 struct list_head iphash[0]; 88 85 }; ··· 95 90 #endif 96 91 }; 97 92 98 - static int recent_net_id; 93 + static int recent_net_id __read_mostly; 94 + 99 95 static inline struct recent_net *recent_pernet(struct net *net) 100 96 { 101 97 return net_generic(net, recent_net_id); ··· 177 171 u_int16_t family, u_int8_t ttl) 178 172 { 179 173 struct recent_entry *e; 174 + unsigned int nstamps_max = t->nstamps_max_mask; 180 175 181 176 if (t->entries >= ip_list_tot) { 182 177 e = list_entry(t->lru_list.next, struct recent_entry, lru_list); 183 178 recent_entry_remove(t, e); 184 179 } 185 - e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * ip_pkt_list_tot, 180 + 181 + nstamps_max += 1; 182 + e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * nstamps_max, 186 183 GFP_ATOMIC); 187 184 if (e == NULL) 188 185 return NULL; ··· 206 197 207 198 static void recent_entry_update(struct recent_table *t, struct recent_entry *e) 208 199 { 209 - e->index %= ip_pkt_list_tot; 200 + e->index &= t->nstamps_max_mask; 210 201 e->stamps[e->index++] = jiffies; 211 202 if (e->index > e->nstamps) 212 203 e->nstamps = e->index; ··· 335 326 kuid_t uid; 336 327 kgid_t gid; 337 328 #endif 329 + unsigned int nstamp_mask; 338 330 unsigned int i; 339 331 int ret = -EINVAL; 340 332 size_t sz; ··· 359 349 return -EINVAL; 360 350 if ((info->check_set & XT_RECENT_REAP) && !info->seconds) 361 351 return -EINVAL; 362 - if (info->hit_count > ip_pkt_list_tot) { 363 - pr_info("hitcount (%u) is larger than " 364 - "packets to be remembered (%u)\n", 365 - info->hit_count, ip_pkt_list_tot); 352 + if (info->hit_count >= XT_RECENT_MAX_NSTAMPS) { 353 + pr_info("hitcount (%u) is larger than allowed maximum (%u)\n", 354 + info->hit_count, XT_RECENT_MAX_NSTAMPS - 1); 366 355 return -EINVAL; 367 356 } 368 357 if (info->name[0] == '\0' || 369 358 strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN) 370 359 return -EINVAL; 371 360 361 + if (ip_pkt_list_tot && info->hit_count < ip_pkt_list_tot) 362 + nstamp_mask = roundup_pow_of_two(ip_pkt_list_tot) - 1; 363 + else if (info->hit_count) 364 + nstamp_mask = roundup_pow_of_two(info->hit_count) - 1; 365 + else 366 + nstamp_mask = 32 - 1; 367 + 372 368 mutex_lock(&recent_mutex); 373 369 t = recent_table_lookup(recent_net, info->name); 374 370 if (t != NULL) { 371 + if (info->hit_count > t->nstamps_max_mask) { 372 + pr_info("hitcount (%u) is larger than packets to be remembered (%u) for table %s\n", 373 + info->hit_count, t->nstamps_max_mask + 1, 374 + info->name); 375 + ret = -EINVAL; 376 + goto out; 377 + } 378 + 375 379 t->refcnt++; 376 380 ret = 0; 377 381 goto out; ··· 401 377 goto out; 402 378 } 403 379 t->refcnt = 1; 380 + t->nstamps_max_mask = nstamp_mask; 404 381 405 382 memcpy(&t->mask, &info->mask, sizeof(t->mask)); 406 383 strcpy(t->name, info->name); ··· 522 497 static int recent_seq_show(struct seq_file *seq, void *v) 523 498 { 524 499 const struct recent_entry *e = v; 500 + struct recent_iter_state *st = seq->private; 501 + const struct recent_table *t = st->table; 525 502 unsigned int i; 526 503 527 - i = (e->index - 1) % ip_pkt_list_tot; 504 + i = (e->index - 1) & t->nstamps_max_mask; 505 + 528 506 if (e->family == NFPROTO_IPV4) 529 507 seq_printf(seq, "src=%pI4 ttl: %u last_seen: %lu oldest_pkt: %u", 530 508 &e->addr.ip, e->ttl, e->stamps[i], e->index); ··· 745 717 { 746 718 int err; 747 719 748 - if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255) 720 + BUILD_BUG_ON_NOT_POWER_OF_2(XT_RECENT_MAX_NSTAMPS); 721 + 722 + if (!ip_list_tot || ip_pkt_list_tot >= XT_RECENT_MAX_NSTAMPS) 749 723 return -EINVAL; 750 724 ip_list_hash_size = 1 << fls(ip_list_tot); 751 725
+70 -3
net/netfilter/xt_set.c
··· 157 157 /* Revision 3 match */ 158 158 159 159 static bool 160 - match_counter(u64 counter, const struct ip_set_counter_match *info) 160 + match_counter0(u64 counter, const struct ip_set_counter_match0 *info) 161 161 { 162 162 switch (info->op) { 163 163 case IPSET_COUNTER_NONE: ··· 192 192 if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS)) 193 193 return ret; 194 194 195 + if (!match_counter0(opt.ext.packets, &info->packets)) 196 + return 0; 197 + return match_counter0(opt.ext.bytes, &info->bytes); 198 + } 199 + 200 + #define set_match_v3_checkentry set_match_v1_checkentry 201 + #define set_match_v3_destroy set_match_v1_destroy 202 + 203 + /* Revision 4 match */ 204 + 205 + static bool 206 + match_counter(u64 counter, const struct ip_set_counter_match *info) 207 + { 208 + switch (info->op) { 209 + case IPSET_COUNTER_NONE: 210 + return true; 211 + case IPSET_COUNTER_EQ: 212 + return counter == info->value; 213 + case IPSET_COUNTER_NE: 214 + return counter != info->value; 215 + case IPSET_COUNTER_LT: 216 + return counter < info->value; 217 + case IPSET_COUNTER_GT: 218 + return counter > info->value; 219 + } 220 + return false; 221 + } 222 + 223 + static bool 224 + set_match_v4(const struct sk_buff *skb, struct xt_action_param *par) 225 + { 226 + const struct xt_set_info_match_v4 *info = par->matchinfo; 227 + ADT_OPT(opt, par->family, info->match_set.dim, 228 + info->match_set.flags, info->flags, UINT_MAX); 229 + int ret; 230 + 231 + if (info->packets.op != IPSET_COUNTER_NONE || 232 + info->bytes.op != IPSET_COUNTER_NONE) 233 + opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS; 234 + 235 + ret = match_set(info->match_set.index, skb, par, &opt, 236 + info->match_set.flags & IPSET_INV_MATCH); 237 + 238 + if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS)) 239 + return ret; 240 + 195 241 if (!match_counter(opt.ext.packets, &info->packets)) 196 242 return 0; 197 243 return match_counter(opt.ext.bytes, &info->bytes); 198 244 } 199 245 200 - #define set_match_v3_checkentry set_match_v1_checkentry 201 - #define set_match_v3_destroy set_match_v1_destroy 246 + #define set_match_v4_checkentry set_match_v1_checkentry 247 + #define set_match_v4_destroy set_match_v1_destroy 202 248 203 249 /* Revision 0 interface: backward compatible with netfilter/iptables */ 204 250 ··· 617 571 .matchsize = sizeof(struct xt_set_info_match_v3), 618 572 .checkentry = set_match_v3_checkentry, 619 573 .destroy = set_match_v3_destroy, 574 + .me = THIS_MODULE 575 + }, 576 + /* new revision for counters support: update, match */ 577 + { 578 + .name = "set", 579 + .family = NFPROTO_IPV4, 580 + .revision = 4, 581 + .match = set_match_v4, 582 + .matchsize = sizeof(struct xt_set_info_match_v4), 583 + .checkentry = set_match_v4_checkentry, 584 + .destroy = set_match_v4_destroy, 585 + .me = THIS_MODULE 586 + }, 587 + { 588 + .name = "set", 589 + .family = NFPROTO_IPV6, 590 + .revision = 4, 591 + .match = set_match_v4, 592 + .matchsize = sizeof(struct xt_set_info_match_v4), 593 + .checkentry = set_match_v4_checkentry, 594 + .destroy = set_match_v4_destroy, 620 595 .me = THIS_MODULE 621 596 }, 622 597 };