diff options
28 files changed, 372 insertions, 254 deletions
diff --git a/include/net/netfilter/ipv4/nf_nat_redirect.h b/include/net/netfilter/ipv4/nf_nat_redirect.h deleted file mode 100644 index 19e1df3a0a4d..000000000000 --- a/include/net/netfilter/ipv4/nf_nat_redirect.h +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
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_ */ | ||
diff --git a/include/net/netfilter/ipv6/nf_nat_redirect.h b/include/net/netfilter/ipv6/nf_nat_redirect.h deleted file mode 100644 index 1ebdffc461cc..000000000000 --- a/include/net/netfilter/ipv6/nf_nat_redirect.h +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
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_ */ | ||
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index c8a7db605e03..f0daed2b54d1 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -92,12 +92,18 @@ struct nf_conn { | |||
92 | /* Have we seen traffic both ways yet? (bitset) */ | 92 | /* Have we seen traffic both ways yet? (bitset) */ |
93 | unsigned long status; | 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 | /* Timer function; drops refcnt when it goes off. */ | 95 | /* Timer function; drops refcnt when it goes off. */ |
99 | struct timer_list timeout; | 96 | struct timer_list timeout; |
100 | 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; | ||
106 | |||
101 | #if defined(CONFIG_NF_CONNTRACK_MARK) | 107 | #if defined(CONFIG_NF_CONNTRACK_MARK) |
102 | u_int32_t mark; | 108 | u_int32_t mark; |
103 | #endif | 109 | #endif |
@@ -108,9 +114,6 @@ struct nf_conn { | |||
108 | 114 | ||
109 | /* Extensions */ | 115 | /* Extensions */ |
110 | struct nf_ct_ext *ext; | 116 | struct nf_ct_ext *ext; |
111 | #ifdef CONFIG_NET_NS | ||
112 | struct net *ct_net; | ||
113 | #endif | ||
114 | 117 | ||
115 | /* Storage reserved for other modules, must be the last member */ | 118 | /* Storage reserved for other modules, must be the last member */ |
116 | union nf_conntrack_proto proto; | 119 | union nf_conntrack_proto proto; |
diff --git a/include/net/netfilter/nf_nat_redirect.h b/include/net/netfilter/nf_nat_redirect.h new file mode 100644 index 000000000000..73b729543309 --- /dev/null +++ b/include/net/netfilter/nf_nat_redirect.h | |||
@@ -0,0 +1,12 @@ | |||
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_ */ | ||
diff --git a/include/net/netfilter/nf_tables_bridge.h b/include/net/netfilter/nf_tables_bridge.h new file mode 100644 index 000000000000..511fb79f6dad --- /dev/null +++ b/include/net/netfilter/nf_tables_bridge.h | |||
@@ -0,0 +1,7 @@ | |||
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 */ | ||
diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h index ca03119111a2..5ab4e60894cf 100644 --- a/include/uapi/linux/netfilter/ipset/ip_set.h +++ b/include/uapi/linux/netfilter/ipset/ip_set.h | |||
@@ -256,11 +256,17 @@ enum { | |||
256 | IPSET_COUNTER_GT, | 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 | __u8 op; | 261 | __u8 op; |
261 | __u64 value; | 262 | __u64 value; |
262 | }; | 263 | }; |
263 | 264 | ||
265 | struct ip_set_counter_match { | ||
266 | __aligned_u64 value; | ||
267 | __u8 op; | ||
268 | }; | ||
269 | |||
264 | /* Interface to iptables/ip6tables */ | 270 | /* Interface to iptables/ip6tables */ |
265 | 271 | ||
266 | #define SO_IP_SET 83 | 272 | #define SO_IP_SET 83 |
diff --git a/include/uapi/linux/netfilter/xt_set.h b/include/uapi/linux/netfilter/xt_set.h index d6a1df1f2947..d4e02348384c 100644 --- a/include/uapi/linux/netfilter/xt_set.h +++ b/include/uapi/linux/netfilter/xt_set.h | |||
@@ -66,8 +66,8 @@ struct xt_set_info_target_v2 { | |||
66 | 66 | ||
67 | struct xt_set_info_match_v3 { | 67 | struct xt_set_info_match_v3 { |
68 | struct xt_set_info match_set; | 68 | struct xt_set_info match_set; |
69 | struct ip_set_counter_match packets; | 69 | struct ip_set_counter_match0 packets; |
70 | struct ip_set_counter_match bytes; | 70 | struct ip_set_counter_match0 bytes; |
71 | __u32 flags; | 71 | __u32 flags; |
72 | }; | 72 | }; |
73 | 73 | ||
@@ -81,4 +81,13 @@ struct xt_set_info_target_v3 { | |||
81 | __u32 timeout; | 81 | __u32 timeout; |
82 | }; | 82 | }; |
83 | 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; | ||
91 | }; | ||
92 | |||
84 | #endif /*_XT_SET_H*/ | 93 | #endif /*_XT_SET_H*/ |
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index 074c557ab505..19473a9371b8 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c | |||
@@ -13,6 +13,82 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/netfilter_bridge.h> | 14 | #include <linux/netfilter_bridge.h> |
15 | #include <net/netfilter/nf_tables.h> | 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 | static unsigned int | 93 | static unsigned int |
18 | nft_do_chain_bridge(const struct nf_hook_ops *ops, | 94 | nft_do_chain_bridge(const struct nf_hook_ops *ops, |
@@ -23,7 +99,17 @@ nft_do_chain_bridge(const struct nf_hook_ops *ops, | |||
23 | { | 99 | { |
24 | struct nft_pktinfo pkt; | 100 | struct nft_pktinfo pkt; |
25 | 101 | ||
26 | nft_set_pktinfo(&pkt, ops, skb, in, out); | 102 | switch (eth_hdr(skb)->h_proto) { |
103 | case htons(ETH_P_IP): | ||
104 | nft_bridge_set_pktinfo_ipv4(&pkt, ops, skb, in, out); | ||
105 | break; | ||
106 | case htons(ETH_P_IPV6): | ||
107 | nft_bridge_set_pktinfo_ipv6(&pkt, ops, skb, in, out); | ||
108 | break; | ||
109 | default: | ||
110 | nft_set_pktinfo(&pkt, ops, skb, in, out); | ||
111 | break; | ||
112 | } | ||
27 | 113 | ||
28 | return nft_do_chain(&pkt, ops); | 114 | return nft_do_chain(&pkt, ops); |
29 | } | 115 | } |
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index 48da2c54a69e..b0330aecbf97 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/netfilter/nf_tables.h> | 14 | #include <linux/netfilter/nf_tables.h> |
15 | #include <net/netfilter/nf_tables.h> | 15 | #include <net/netfilter/nf_tables.h> |
16 | #include <net/netfilter/nft_reject.h> | 16 | #include <net/netfilter/nft_reject.h> |
17 | #include <net/netfilter/nf_tables_bridge.h> | ||
17 | #include <net/netfilter/ipv4/nf_reject.h> | 18 | #include <net/netfilter/ipv4/nf_reject.h> |
18 | #include <net/netfilter/ipv6/nf_reject.h> | 19 | #include <net/netfilter/ipv6/nf_reject.h> |
19 | #include <linux/ip.h> | 20 | #include <linux/ip.h> |
@@ -35,30 +36,6 @@ static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, | |||
35 | skb_pull(nskb, ETH_HLEN); | 36 | skb_pull(nskb, ETH_HLEN); |
36 | } | 37 | } |
37 | 38 | ||
38 | static int nft_reject_iphdr_validate(struct sk_buff *oldskb) | ||
39 | { | ||
40 | struct iphdr *iph; | ||
41 | u32 len; | ||
42 | |||
43 | if (!pskb_may_pull(oldskb, sizeof(struct iphdr))) | ||
44 | return 0; | ||
45 | |||
46 | iph = ip_hdr(oldskb); | ||
47 | if (iph->ihl < 5 || iph->version != 4) | ||
48 | return 0; | ||
49 | |||
50 | len = ntohs(iph->tot_len); | ||
51 | if (oldskb->len < len) | ||
52 | return 0; | ||
53 | else if (len < (iph->ihl*4)) | ||
54 | return 0; | ||
55 | |||
56 | if (!pskb_may_pull(oldskb, iph->ihl*4)) | ||
57 | return 0; | ||
58 | |||
59 | return 1; | ||
60 | } | ||
61 | |||
62 | static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) | 39 | static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) |
63 | { | 40 | { |
64 | struct sk_buff *nskb; | 41 | struct sk_buff *nskb; |
@@ -66,7 +43,7 @@ static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) | |||
66 | const struct tcphdr *oth; | 43 | const struct tcphdr *oth; |
67 | struct tcphdr _oth; | 44 | struct tcphdr _oth; |
68 | 45 | ||
69 | if (!nft_reject_iphdr_validate(oldskb)) | 46 | if (!nft_bridge_iphdr_validate(oldskb)) |
70 | return; | 47 | return; |
71 | 48 | ||
72 | oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); | 49 | oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); |
@@ -101,7 +78,7 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, | |||
101 | void *payload; | 78 | void *payload; |
102 | __wsum csum; | 79 | __wsum csum; |
103 | 80 | ||
104 | if (!nft_reject_iphdr_validate(oldskb)) | 81 | if (!nft_bridge_iphdr_validate(oldskb)) |
105 | return; | 82 | return; |
106 | 83 | ||
107 | /* IP header checks: fragment. */ | 84 | /* IP header checks: fragment. */ |
@@ -146,25 +123,6 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, | |||
146 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | 123 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); |
147 | } | 124 | } |
148 | 125 | ||
149 | static int nft_reject_ip6hdr_validate(struct sk_buff *oldskb) | ||
150 | { | ||
151 | struct ipv6hdr *hdr; | ||
152 | u32 pkt_len; | ||
153 | |||
154 | if (!pskb_may_pull(oldskb, sizeof(struct ipv6hdr))) | ||
155 | return 0; | ||
156 | |||
157 | hdr = ipv6_hdr(oldskb); | ||
158 | if (hdr->version != 6) | ||
159 | return 0; | ||
160 | |||
161 | pkt_len = ntohs(hdr->payload_len); | ||
162 | if (pkt_len + sizeof(struct ipv6hdr) > oldskb->len) | ||
163 | return 0; | ||
164 | |||
165 | return 1; | ||
166 | } | ||
167 | |||
168 | static void nft_reject_br_send_v6_tcp_reset(struct net *net, | 126 | static void nft_reject_br_send_v6_tcp_reset(struct net *net, |
169 | struct sk_buff *oldskb, int hook) | 127 | struct sk_buff *oldskb, int hook) |
170 | { | 128 | { |
@@ -174,7 +132,7 @@ static void nft_reject_br_send_v6_tcp_reset(struct net *net, | |||
174 | unsigned int otcplen; | 132 | unsigned int otcplen; |
175 | struct ipv6hdr *nip6h; | 133 | struct ipv6hdr *nip6h; |
176 | 134 | ||
177 | if (!nft_reject_ip6hdr_validate(oldskb)) | 135 | if (!nft_bridge_ip6hdr_validate(oldskb)) |
178 | return; | 136 | return; |
179 | 137 | ||
180 | oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook); | 138 | oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook); |
@@ -207,7 +165,7 @@ static void nft_reject_br_send_v6_unreach(struct net *net, | |||
207 | unsigned int len; | 165 | unsigned int len; |
208 | void *payload; | 166 | void *payload; |
209 | 167 | ||
210 | if (!nft_reject_ip6hdr_validate(oldskb)) | 168 | if (!nft_bridge_ip6hdr_validate(oldskb)) |
211 | return; | 169 | return; |
212 | 170 | ||
213 | /* Include "As much of invoking packet as possible without the ICMPv6 | 171 | /* Include "As much of invoking packet as possible without the ICMPv6 |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 8358b2da1549..59f883d9cadf 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -104,12 +104,6 @@ config NF_NAT_MASQUERADE_IPV4 | |||
104 | This is the kernel functionality to provide NAT in the masquerade | 104 | This is the kernel functionality to provide NAT in the masquerade |
105 | flavour (automatic source address selection). | 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 | config NFT_MASQ_IPV4 | 107 | config NFT_MASQ_IPV4 |
114 | tristate "IPv4 masquerading support for nf_tables" | 108 | tristate "IPv4 masquerading support for nf_tables" |
115 | depends on NF_TABLES_IPV4 | 109 | depends on NF_TABLES_IPV4 |
@@ -123,7 +117,7 @@ config NFT_REDIR_IPV4 | |||
123 | tristate "IPv4 redirect support for nf_tables" | 117 | tristate "IPv4 redirect support for nf_tables" |
124 | depends on NF_TABLES_IPV4 | 118 | depends on NF_TABLES_IPV4 |
125 | depends on NFT_REDIR | 119 | depends on NFT_REDIR |
126 | select NF_NAT_REDIRECT_IPV4 | 120 | select NF_NAT_REDIRECT |
127 | help | 121 | help |
128 | This is the expression that provides IPv4 redirect support for | 122 | This is the expression that provides IPv4 redirect support for |
129 | nf_tables. | 123 | nf_tables. |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 902bcd1597bb..7fe6c703528f 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -31,7 +31,6 @@ obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o | |||
31 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o | 31 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o |
32 | obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o | 32 | obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o |
33 | obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o | 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 | # NAT protocols (nf_nat) | 35 | # NAT protocols (nf_nat) |
37 | obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o | 36 | obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o |
diff --git a/net/ipv4/netfilter/nft_redir_ipv4.c b/net/ipv4/netfilter/nft_redir_ipv4.c index 643c5967aa27..ff2d23d8c87a 100644 --- a/net/ipv4/netfilter/nft_redir_ipv4.c +++ b/net/ipv4/netfilter/nft_redir_ipv4.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/netfilter/nf_tables.h> | 14 | #include <linux/netfilter/nf_tables.h> |
15 | #include <net/netfilter/nf_tables.h> | 15 | #include <net/netfilter/nf_tables.h> |
16 | #include <net/netfilter/nf_nat.h> | 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 | #include <net/netfilter/nft_redir.h> | 18 | #include <net/netfilter/nft_redir.h> |
19 | 19 | ||
20 | static void nft_redir_ipv4_eval(const struct nft_expr *expr, | 20 | static void nft_redir_ipv4_eval(const struct nft_expr *expr, |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 0dbe5c7953e5..a069822936e6 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -82,12 +82,6 @@ config NF_NAT_MASQUERADE_IPV6 | |||
82 | This is the kernel functionality to provide NAT in the masquerade | 82 | This is the kernel functionality to provide NAT in the masquerade |
83 | flavour (automatic source address selection) for IPv6. | 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 | config NFT_MASQ_IPV6 | 85 | config NFT_MASQ_IPV6 |
92 | tristate "IPv6 masquerade support for nf_tables" | 86 | tristate "IPv6 masquerade support for nf_tables" |
93 | depends on NF_TABLES_IPV6 | 87 | depends on NF_TABLES_IPV6 |
@@ -101,7 +95,7 @@ config NFT_REDIR_IPV6 | |||
101 | tristate "IPv6 redirect support for nf_tables" | 95 | tristate "IPv6 redirect support for nf_tables" |
102 | depends on NF_TABLES_IPV6 | 96 | depends on NF_TABLES_IPV6 |
103 | depends on NFT_REDIR | 97 | depends on NFT_REDIR |
104 | select NF_NAT_REDIRECT_IPV6 | 98 | select NF_NAT_REDIRECT |
105 | help | 99 | help |
106 | This is the expression that provides IPv4 redirect support for | 100 | This is the expression that provides IPv4 redirect support for |
107 | nf_tables. | 101 | nf_tables. |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index d2ac9f5f212c..c36e0a5490de 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -19,7 +19,6 @@ obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o | |||
19 | nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o | 19 | nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o |
20 | obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o | 20 | obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o |
21 | obj-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o | 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 | # defrag | 23 | # defrag |
25 | nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | 24 | nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o |
diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c index 7fc34d1681a1..ddf07e6f59d7 100644 --- a/net/ipv6/netfilter/nf_log_ipv6.c +++ b/net/ipv6/netfilter/nf_log_ipv6.c | |||
@@ -422,6 +422,6 @@ module_init(nf_log_ipv6_init); | |||
422 | module_exit(nf_log_ipv6_exit); | 422 | module_exit(nf_log_ipv6_exit); |
423 | 423 | ||
424 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 424 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
425 | MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); | 425 | MODULE_DESCRIPTION("Netfilter IPv6 packet logging"); |
426 | MODULE_LICENSE("GPL"); | 426 | MODULE_LICENSE("GPL"); |
427 | MODULE_ALIAS_NF_LOGGER(AF_INET6, 0); | 427 | MODULE_ALIAS_NF_LOGGER(AF_INET6, 0); |
diff --git a/net/ipv6/netfilter/nf_nat_redirect_ipv6.c b/net/ipv6/netfilter/nf_nat_redirect_ipv6.c deleted file mode 100644 index ea1308aeb048..000000000000 --- a/net/ipv6/netfilter/nf_nat_redirect_ipv6.c +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
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>"); | ||
diff --git a/net/ipv6/netfilter/nft_redir_ipv6.c b/net/ipv6/netfilter/nft_redir_ipv6.c index 83420eeaad1c..2433a6bfb191 100644 --- a/net/ipv6/netfilter/nft_redir_ipv6.c +++ b/net/ipv6/netfilter/nft_redir_ipv6.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <net/netfilter/nf_tables.h> | 15 | #include <net/netfilter/nf_tables.h> |
16 | #include <net/netfilter/nf_nat.h> | 16 | #include <net/netfilter/nf_nat.h> |
17 | #include <net/netfilter/nft_redir.h> | 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 | static void nft_redir_ipv6_eval(const struct nft_expr *expr, | 20 | static void nft_redir_ipv6_eval(const struct nft_expr *expr, |
21 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_data data[NFT_REG_MAX + 1], |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 57f15a9aa481..b02660fa9eb0 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -411,6 +411,13 @@ config NF_NAT_TFTP | |||
411 | depends on NF_CONNTRACK && NF_NAT | 411 | depends on NF_CONNTRACK && NF_NAT |
412 | default NF_NAT && NF_CONNTRACK_TFTP | 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 | config NETFILTER_SYNPROXY | 421 | config NETFILTER_SYNPROXY |
415 | tristate | 422 | tristate |
416 | 423 | ||
@@ -844,8 +851,7 @@ config NETFILTER_XT_TARGET_RATEEST | |||
844 | config NETFILTER_XT_TARGET_REDIRECT | 851 | config NETFILTER_XT_TARGET_REDIRECT |
845 | tristate "REDIRECT target support" | 852 | tristate "REDIRECT target support" |
846 | depends on NF_NAT | 853 | depends on NF_NAT |
847 | select NF_NAT_REDIRECT_IPV4 if NF_NAT_IPV4 | 854 | select NF_NAT_REDIRECT |
848 | select NF_NAT_REDIRECT_IPV6 if NF_NAT_IPV6 | ||
849 | ---help--- | 855 | ---help--- |
850 | REDIRECT is a special case of NAT: all incoming connections are | 856 | REDIRECT is a special case of NAT: all incoming connections are |
851 | mapped onto the incoming interface's address, causing the packets to | 857 | mapped onto the incoming interface's address, causing the packets to |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index f3eb4680f2ec..89f73a9e9874 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -51,6 +51,7 @@ nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ | |||
51 | obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o | 51 | obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o |
52 | 52 | ||
53 | obj-$(CONFIG_NF_NAT) += nf_nat.o | 53 | obj-$(CONFIG_NF_NAT) += nf_nat.o |
54 | obj-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o | ||
54 | 55 | ||
55 | # NAT protocols (nf_nat) | 56 | # NAT protocols (nf_nat) |
56 | obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o | 57 | obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o |
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index fee7c64e4dd1..974ff386db0f 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h | |||
@@ -147,16 +147,22 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize) | |||
147 | #else | 147 | #else |
148 | #define __CIDR(cidr, i) (cidr) | 148 | #define __CIDR(cidr, i) (cidr) |
149 | #endif | 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 | #ifdef IP_SET_HASH_WITH_NETS_PACKED | 154 | #ifdef IP_SET_HASH_WITH_NETS_PACKED |
151 | /* When cidr is packed with nomatch, cidr - 1 is stored in the entry */ | 155 | /* When cidr is packed with nomatch, cidr - 1 is stored in the data entry */ |
152 | #define CIDR(cidr, i) (__CIDR(cidr, i) + 1) | 156 | #define GCIDR(cidr, i) (__CIDR(cidr, i) + 1) |
157 | #define NCIDR(cidr) (cidr) | ||
153 | #else | 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 | #endif | 161 | #endif |
156 | 162 | ||
157 | #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) | 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 | #define NLEN(family) (SET_HOST_MASK(family) + 1) | 166 | #define NLEN(family) (SET_HOST_MASK(family) + 1) |
161 | #else | 167 | #else |
162 | #define NLEN(family) SET_HOST_MASK(family) | 168 | #define NLEN(family) SET_HOST_MASK(family) |
@@ -292,24 +298,22 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n) | |||
292 | int i, j; | 298 | int i, j; |
293 | 299 | ||
294 | /* Add in increasing prefix order, so larger cidr first */ | 300 | /* Add in increasing prefix order, so larger cidr first */ |
295 | for (i = 0, j = -1; i < nets_length && h->nets[i].nets[n]; i++) { | 301 | for (i = 0, j = -1; i < nets_length && h->nets[i].cidr[n]; i++) { |
296 | if (j != -1) | 302 | if (j != -1) |
297 | continue; | 303 | continue; |
298 | else if (h->nets[i].cidr[n] < cidr) | 304 | else if (h->nets[i].cidr[n] < cidr) |
299 | j = i; | 305 | j = i; |
300 | else if (h->nets[i].cidr[n] == cidr) { | 306 | else if (h->nets[i].cidr[n] == cidr) { |
301 | h->nets[i].nets[n]++; | 307 | h->nets[cidr - 1].nets[n]++; |
302 | return; | 308 | return; |
303 | } | 309 | } |
304 | } | 310 | } |
305 | if (j != -1) { | 311 | if (j != -1) { |
306 | for (; i > j; i--) { | 312 | for (; i > j; i--) |
307 | h->nets[i].cidr[n] = h->nets[i - 1].cidr[n]; | 313 | h->nets[i].cidr[n] = h->nets[i - 1].cidr[n]; |
308 | h->nets[i].nets[n] = h->nets[i - 1].nets[n]; | ||
309 | } | ||
310 | } | 314 | } |
311 | h->nets[i].cidr[n] = cidr; | 315 | h->nets[i].cidr[n] = cidr; |
312 | h->nets[i].nets[n] = 1; | 316 | h->nets[cidr - 1].nets[n] = 1; |
313 | } | 317 | } |
314 | 318 | ||
315 | static void | 319 | static void |
@@ -320,16 +324,12 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n) | |||
320 | for (i = 0; i < nets_length; i++) { | 324 | for (i = 0; i < nets_length; i++) { |
321 | if (h->nets[i].cidr[n] != cidr) | 325 | if (h->nets[i].cidr[n] != cidr) |
322 | continue; | 326 | continue; |
323 | if (h->nets[i].nets[n] > 1 || i == net_end || | 327 | h->nets[cidr -1].nets[n]--; |
324 | h->nets[i + 1].nets[n] == 0) { | 328 | if (h->nets[cidr -1].nets[n] > 0) |
325 | h->nets[i].nets[n]--; | ||
326 | return; | 329 | return; |
327 | } | 330 | for (j = i; j < net_end && h->nets[j].cidr[n]; j++) |
328 | for (j = i; j < net_end && h->nets[j].nets[n]; j++) { | ||
329 | h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; | 331 | h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; |
330 | h->nets[j].nets[n] = h->nets[j + 1].nets[n]; | 332 | h->nets[j].cidr[n] = 0; |
331 | } | ||
332 | h->nets[j].nets[n] = 0; | ||
333 | return; | 333 | return; |
334 | } | 334 | } |
335 | } | 335 | } |
@@ -486,7 +486,7 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize) | |||
486 | pr_debug("expired %u/%u\n", i, j); | 486 | pr_debug("expired %u/%u\n", i, j); |
487 | #ifdef IP_SET_HASH_WITH_NETS | 487 | #ifdef IP_SET_HASH_WITH_NETS |
488 | for (k = 0; k < IPSET_NET_COUNT; k++) | 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 | nets_length, k); | 490 | nets_length, k); |
491 | #endif | 491 | #endif |
492 | ip_set_ext_destroy(set, data); | 492 | ip_set_ext_destroy(set, data); |
@@ -633,29 +633,6 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
633 | bool flag_exist = flags & IPSET_FLAG_EXIST; | 633 | bool flag_exist = flags & IPSET_FLAG_EXIST; |
634 | u32 key, multi = 0; | 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 | rcu_read_lock_bh(); | 636 | rcu_read_lock_bh(); |
660 | t = rcu_dereference_bh(h->table); | 637 | t = rcu_dereference_bh(h->table); |
661 | key = HKEY(value, h->initval, t->htable_bits); | 638 | key = HKEY(value, h->initval, t->htable_bits); |
@@ -680,15 +657,32 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
680 | j != AHASH_MAX(h) + 1) | 657 | j != AHASH_MAX(h) + 1) |
681 | j = i; | 658 | j = i; |
682 | } | 659 | } |
660 | if (h->elements >= h->maxelem && SET_WITH_FORCEADD(set) && n->pos) { | ||
661 | /* Choosing the first entry in the array to replace */ | ||
662 | j = 0; | ||
663 | goto reuse_slot; | ||
664 | } | ||
665 | if (SET_WITH_TIMEOUT(set) && h->elements >= h->maxelem) | ||
666 | /* FIXME: when set is full, we slow down here */ | ||
667 | mtype_expire(set, h, NLEN(set->family), set->dsize); | ||
668 | |||
669 | if (h->elements >= h->maxelem) { | ||
670 | if (net_ratelimit()) | ||
671 | pr_warn("Set %s is full, maxelem %u reached\n", | ||
672 | set->name, h->maxelem); | ||
673 | ret = -IPSET_ERR_HASH_FULL; | ||
674 | goto out; | ||
675 | } | ||
676 | |||
683 | reuse_slot: | 677 | reuse_slot: |
684 | if (j != AHASH_MAX(h) + 1) { | 678 | if (j != AHASH_MAX(h) + 1) { |
685 | /* Fill out reused slot */ | 679 | /* Fill out reused slot */ |
686 | data = ahash_data(n, j, set->dsize); | 680 | data = ahash_data(n, j, set->dsize); |
687 | #ifdef IP_SET_HASH_WITH_NETS | 681 | #ifdef IP_SET_HASH_WITH_NETS |
688 | for (i = 0; i < IPSET_NET_COUNT; i++) { | 682 | for (i = 0; i < IPSET_NET_COUNT; i++) { |
689 | mtype_del_cidr(h, CIDR(data->cidr, i), | 683 | mtype_del_cidr(h, SCIDR(data->cidr, i), |
690 | NLEN(set->family), i); | 684 | NLEN(set->family), i); |
691 | mtype_add_cidr(h, CIDR(d->cidr, i), | 685 | mtype_add_cidr(h, SCIDR(d->cidr, i), |
692 | NLEN(set->family), i); | 686 | NLEN(set->family), i); |
693 | } | 687 | } |
694 | #endif | 688 | #endif |
@@ -705,7 +699,7 @@ reuse_slot: | |||
705 | data = ahash_data(n, n->pos++, set->dsize); | 699 | data = ahash_data(n, n->pos++, set->dsize); |
706 | #ifdef IP_SET_HASH_WITH_NETS | 700 | #ifdef IP_SET_HASH_WITH_NETS |
707 | for (i = 0; i < IPSET_NET_COUNT; i++) | 701 | for (i = 0; i < IPSET_NET_COUNT; i++) |
708 | mtype_add_cidr(h, CIDR(d->cidr, i), NLEN(set->family), | 702 | mtype_add_cidr(h, SCIDR(d->cidr, i), NLEN(set->family), |
709 | i); | 703 | i); |
710 | #endif | 704 | #endif |
711 | h->elements++; | 705 | h->elements++; |
@@ -766,7 +760,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
766 | h->elements--; | 760 | h->elements--; |
767 | #ifdef IP_SET_HASH_WITH_NETS | 761 | #ifdef IP_SET_HASH_WITH_NETS |
768 | for (j = 0; j < IPSET_NET_COUNT; j++) | 762 | for (j = 0; j < IPSET_NET_COUNT; j++) |
769 | mtype_del_cidr(h, CIDR(d->cidr, j), NLEN(set->family), | 763 | mtype_del_cidr(h, SCIDR(d->cidr, j), NLEN(set->family), |
770 | j); | 764 | j); |
771 | #endif | 765 | #endif |
772 | ip_set_ext_destroy(set, data); | 766 | ip_set_ext_destroy(set, data); |
@@ -827,15 +821,15 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d, | |||
827 | u8 nets_length = NLEN(set->family); | 821 | u8 nets_length = NLEN(set->family); |
828 | 822 | ||
829 | pr_debug("test by nets\n"); | 823 | pr_debug("test by nets\n"); |
830 | for (; j < nets_length && h->nets[j].nets[0] && !multi; j++) { | 824 | for (; j < nets_length && h->nets[j].cidr[0] && !multi; j++) { |
831 | #if IPSET_NET_COUNT == 2 | 825 | #if IPSET_NET_COUNT == 2 |
832 | mtype_data_reset_elem(d, &orig); | 826 | mtype_data_reset_elem(d, &orig); |
833 | mtype_data_netmask(d, h->nets[j].cidr[0], false); | 827 | mtype_data_netmask(d, NCIDR(h->nets[j].cidr[0]), false); |
834 | for (k = 0; k < nets_length && h->nets[k].nets[1] && !multi; | 828 | for (k = 0; k < nets_length && h->nets[k].cidr[1] && !multi; |
835 | k++) { | 829 | k++) { |
836 | mtype_data_netmask(d, h->nets[k].cidr[1], true); | 830 | mtype_data_netmask(d, NCIDR(h->nets[k].cidr[1]), true); |
837 | #else | 831 | #else |
838 | mtype_data_netmask(d, h->nets[j].cidr[0]); | 832 | mtype_data_netmask(d, NCIDR(h->nets[j].cidr[0])); |
839 | #endif | 833 | #endif |
840 | key = HKEY(d, h->initval, t->htable_bits); | 834 | key = HKEY(d, h->initval, t->htable_bits); |
841 | n = hbucket(t, key); | 835 | n = hbucket(t, key); |
@@ -883,7 +877,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
883 | /* If we test an IP address and not a network address, | 877 | /* If we test an IP address and not a network address, |
884 | * try all possible network sizes */ | 878 | * try all possible network sizes */ |
885 | for (i = 0; i < IPSET_NET_COUNT; i++) | 879 | for (i = 0; i < IPSET_NET_COUNT; i++) |
886 | if (CIDR(d->cidr, i) != SET_HOST_MASK(set->family)) | 880 | if (GCIDR(d->cidr, i) != SET_HOST_MASK(set->family)) |
887 | break; | 881 | break; |
888 | if (i == IPSET_NET_COUNT) { | 882 | if (i == IPSET_NET_COUNT) { |
889 | ret = mtype_test_cidrs(set, d, ext, mext, flags); | 883 | ret = mtype_test_cidrs(set, d, ext, mext, flags); |
@@ -1107,8 +1101,7 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |||
1107 | 1101 | ||
1108 | hsize = sizeof(*h); | 1102 | hsize = sizeof(*h); |
1109 | #ifdef IP_SET_HASH_WITH_NETS | 1103 | #ifdef IP_SET_HASH_WITH_NETS |
1110 | hsize += sizeof(struct net_prefixes) * | 1104 | hsize += sizeof(struct net_prefixes) * NLEN(set->family); |
1111 | (set->family == NFPROTO_IPV4 ? 32 : 128); | ||
1112 | #endif | 1105 | #endif |
1113 | h = kzalloc(hsize, GFP_KERNEL); | 1106 | h = kzalloc(hsize, GFP_KERNEL); |
1114 | if (!h) | 1107 | if (!h) |
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index 35dd35873442..758b002130d9 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |||
@@ -115,6 +115,7 @@ iface_add(struct rb_root *root, const char **iface) | |||
115 | #define IP_SET_HASH_WITH_NETS | 115 | #define IP_SET_HASH_WITH_NETS |
116 | #define IP_SET_HASH_WITH_RBTREE | 116 | #define IP_SET_HASH_WITH_RBTREE |
117 | #define IP_SET_HASH_WITH_MULTI | 117 | #define IP_SET_HASH_WITH_MULTI |
118 | #define IP_SET_HASH_WITH_NET0 | ||
118 | 119 | ||
119 | #define STREQ(a, b) (strcmp(a, b) == 0) | 120 | #define STREQ(a, b) (strcmp(a, b) == 0) |
120 | 121 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c index da00284b3571..ea8772afb6e7 100644 --- a/net/netfilter/ipset/ip_set_hash_netnet.c +++ b/net/netfilter/ipset/ip_set_hash_netnet.c | |||
@@ -46,6 +46,7 @@ struct hash_netnet4_elem { | |||
46 | __be64 ipcmp; | 46 | __be64 ipcmp; |
47 | }; | 47 | }; |
48 | u8 nomatch; | 48 | u8 nomatch; |
49 | u8 padding; | ||
49 | union { | 50 | union { |
50 | u8 cidr[2]; | 51 | u8 cidr[2]; |
51 | u16 ccmp; | 52 | u16 ccmp; |
@@ -271,6 +272,7 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
271 | struct hash_netnet6_elem { | 272 | struct hash_netnet6_elem { |
272 | union nf_inet_addr ip[2]; | 273 | union nf_inet_addr ip[2]; |
273 | u8 nomatch; | 274 | u8 nomatch; |
275 | u8 padding; | ||
274 | union { | 276 | union { |
275 | u8 cidr[2]; | 277 | u8 cidr[2]; |
276 | u16 ccmp; | 278 | u16 ccmp; |
diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c index b8053d675fc3..bfaa94c7baa7 100644 --- a/net/netfilter/ipset/ip_set_hash_netportnet.c +++ b/net/netfilter/ipset/ip_set_hash_netportnet.c | |||
@@ -53,6 +53,7 @@ struct hash_netportnet4_elem { | |||
53 | u8 cidr[2]; | 53 | u8 cidr[2]; |
54 | u16 ccmp; | 54 | u16 ccmp; |
55 | }; | 55 | }; |
56 | u16 padding; | ||
56 | u8 nomatch:1; | 57 | u8 nomatch:1; |
57 | u8 proto; | 58 | u8 proto; |
58 | }; | 59 | }; |
@@ -324,6 +325,7 @@ struct hash_netportnet6_elem { | |||
324 | u8 cidr[2]; | 325 | u8 cidr[2]; |
325 | u16 ccmp; | 326 | u16 ccmp; |
326 | }; | 327 | }; |
328 | u16 padding; | ||
327 | u8 nomatch:1; | 329 | u8 nomatch:1; |
328 | u8 proto; | 330 | u8 proto; |
329 | }; | 331 | }; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 5016a6929085..a11674806707 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -824,22 +824,19 @@ __nf_conntrack_alloc(struct net *net, u16 zone, | |||
824 | atomic_dec(&net->ct.count); | 824 | atomic_dec(&net->ct.count); |
825 | return ERR_PTR(-ENOMEM); | 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 | spin_lock_init(&ct->lock); | 827 | spin_lock_init(&ct->lock); |
835 | ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; | 828 | ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; |
836 | ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL; | 829 | ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL; |
837 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; | 830 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; |
838 | /* save hash for reusing when confirming */ | 831 | /* save hash for reusing when confirming */ |
839 | *(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash; | 832 | *(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash; |
833 | ct->status = 0; | ||
840 | /* Don't set timer yet: wait for confirmation */ | 834 | /* Don't set timer yet: wait for confirmation */ |
841 | setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); | 835 | setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); |
842 | write_pnet(&ct->ct_net, net); | 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 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 840 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
844 | if (zone) { | 841 | if (zone) { |
845 | struct nf_conntrack_zone *nf_ct_zone; | 842 | struct nf_conntrack_zone *nf_ct_zone; |
diff --git a/net/ipv4/netfilter/nf_nat_redirect_ipv4.c b/net/netfilter/nf_nat_redirect.c index a220552fc532..97b75f9bfbcd 100644 --- a/net/ipv4/netfilter/nf_nat_redirect_ipv4.c +++ b/net/netfilter/nf_nat_redirect.c | |||
@@ -20,12 +20,13 @@ | |||
20 | #include <linux/netfilter.h> | 20 | #include <linux/netfilter.h> |
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/netfilter_ipv4.h> | 22 | #include <linux/netfilter_ipv4.h> |
23 | #include <linux/netfilter_ipv6.h> | ||
23 | #include <linux/netfilter/x_tables.h> | 24 | #include <linux/netfilter/x_tables.h> |
24 | #include <net/addrconf.h> | 25 | #include <net/addrconf.h> |
25 | #include <net/checksum.h> | 26 | #include <net/checksum.h> |
26 | #include <net/protocol.h> | 27 | #include <net/protocol.h> |
27 | #include <net/netfilter/nf_nat.h> | 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 | unsigned int | 31 | unsigned int |
31 | nf_nat_redirect_ipv4(struct sk_buff *skb, | 32 | nf_nat_redirect_ipv4(struct sk_buff *skb, |
@@ -78,5 +79,49 @@ nf_nat_redirect_ipv4(struct sk_buff *skb, | |||
78 | } | 79 | } |
79 | EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4); | 80 | EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4); |
80 | 81 | ||
82 | static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; | ||
83 | |||
84 | unsigned int | ||
85 | nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range, | ||
86 | unsigned int hooknum) | ||
87 | { | ||
88 | struct nf_nat_range newrange; | ||
89 | struct in6_addr newdst; | ||
90 | enum ip_conntrack_info ctinfo; | ||
91 | struct nf_conn *ct; | ||
92 | |||
93 | ct = nf_ct_get(skb, &ctinfo); | ||
94 | if (hooknum == NF_INET_LOCAL_OUT) { | ||
95 | newdst = loopback_addr; | ||
96 | } else { | ||
97 | struct inet6_dev *idev; | ||
98 | struct inet6_ifaddr *ifa; | ||
99 | bool addr = false; | ||
100 | |||
101 | rcu_read_lock(); | ||
102 | idev = __in6_dev_get(skb->dev); | ||
103 | if (idev != NULL) { | ||
104 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
105 | newdst = ifa->addr; | ||
106 | addr = true; | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | rcu_read_unlock(); | ||
111 | |||
112 | if (!addr) | ||
113 | return NF_DROP; | ||
114 | } | ||
115 | |||
116 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
117 | newrange.min_addr.in6 = newdst; | ||
118 | newrange.max_addr.in6 = newdst; | ||
119 | newrange.min_proto = range->min_proto; | ||
120 | newrange.max_proto = range->max_proto; | ||
121 | |||
122 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); | ||
123 | } | ||
124 | EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv6); | ||
125 | |||
81 | MODULE_LICENSE("GPL"); | 126 | MODULE_LICENSE("GPL"); |
82 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 127 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
diff --git a/net/netfilter/xt_REDIRECT.c b/net/netfilter/xt_REDIRECT.c index b6ec67efd900..03f0b370e178 100644 --- a/net/netfilter/xt_REDIRECT.c +++ b/net/netfilter/xt_REDIRECT.c | |||
@@ -26,8 +26,7 @@ | |||
26 | #include <net/checksum.h> | 26 | #include <net/checksum.h> |
27 | #include <net/protocol.h> | 27 | #include <net/protocol.h> |
28 | #include <net/netfilter/nf_nat.h> | 28 | #include <net/netfilter/nf_nat.h> |
29 | #include <net/netfilter/ipv4/nf_nat_redirect.h> | 29 | #include <net/netfilter/nf_nat_redirect.h> |
30 | #include <net/netfilter/ipv6/nf_nat_redirect.h> | ||
31 | 30 | ||
32 | static unsigned int | 31 | static unsigned int |
33 | redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) | 32 | redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index a9faae89f955..30dbe34915ae 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
@@ -43,25 +43,29 @@ MODULE_LICENSE("GPL"); | |||
43 | MODULE_ALIAS("ipt_recent"); | 43 | MODULE_ALIAS("ipt_recent"); |
44 | MODULE_ALIAS("ip6t_recent"); | 44 | MODULE_ALIAS("ip6t_recent"); |
45 | 45 | ||
46 | static unsigned int ip_list_tot = 100; | 46 | static unsigned int ip_list_tot __read_mostly = 100; |
47 | static unsigned int ip_pkt_list_tot = 20; | 47 | static unsigned int ip_list_hash_size __read_mostly; |
48 | static unsigned int ip_list_hash_size = 0; | 48 | static unsigned int ip_list_perms __read_mostly = 0644; |
49 | static unsigned int ip_list_perms = 0644; | 49 | static unsigned int ip_list_uid __read_mostly; |
50 | static unsigned int ip_list_uid = 0; | 50 | static unsigned int ip_list_gid __read_mostly; |
51 | static unsigned int ip_list_gid = 0; | ||
52 | module_param(ip_list_tot, uint, 0400); | 51 | module_param(ip_list_tot, uint, 0400); |
53 | module_param(ip_pkt_list_tot, uint, 0400); | ||
54 | module_param(ip_list_hash_size, uint, 0400); | 52 | module_param(ip_list_hash_size, uint, 0400); |
55 | module_param(ip_list_perms, uint, 0400); | 53 | module_param(ip_list_perms, uint, 0400); |
56 | module_param(ip_list_uid, uint, S_IRUGO | S_IWUSR); | 54 | module_param(ip_list_uid, uint, S_IRUGO | S_IWUSR); |
57 | module_param(ip_list_gid, uint, S_IRUGO | S_IWUSR); | 55 | module_param(ip_list_gid, uint, S_IRUGO | S_IWUSR); |
58 | MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list"); | 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 | MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); | 57 | MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); |
61 | MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files"); | 58 | MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files"); |
62 | MODULE_PARM_DESC(ip_list_uid, "default owner of /proc/net/xt_recent/* files"); | 59 | MODULE_PARM_DESC(ip_list_uid, "default owner of /proc/net/xt_recent/* files"); |
63 | MODULE_PARM_DESC(ip_list_gid, "default owning group of /proc/net/xt_recent/* files"); | 60 | MODULE_PARM_DESC(ip_list_gid, "default owning group of /proc/net/xt_recent/* files"); |
64 | 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 | ||
68 | |||
65 | struct recent_entry { | 69 | struct recent_entry { |
66 | struct list_head list; | 70 | struct list_head list; |
67 | struct list_head lru_list; | 71 | struct list_head lru_list; |
@@ -79,6 +83,7 @@ struct recent_table { | |||
79 | union nf_inet_addr mask; | 83 | union nf_inet_addr mask; |
80 | unsigned int refcnt; | 84 | unsigned int refcnt; |
81 | unsigned int entries; | 85 | unsigned int entries; |
86 | u8 nstamps_max_mask; | ||
82 | struct list_head lru_list; | 87 | struct list_head lru_list; |
83 | struct list_head iphash[0]; | 88 | struct list_head iphash[0]; |
84 | }; | 89 | }; |
@@ -90,7 +95,8 @@ struct recent_net { | |||
90 | #endif | 95 | #endif |
91 | }; | 96 | }; |
92 | 97 | ||
93 | static int recent_net_id; | 98 | static int recent_net_id __read_mostly; |
99 | |||
94 | static inline struct recent_net *recent_pernet(struct net *net) | 100 | static inline struct recent_net *recent_pernet(struct net *net) |
95 | { | 101 | { |
96 | return net_generic(net, recent_net_id); | 102 | return net_generic(net, recent_net_id); |
@@ -171,12 +177,15 @@ recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr, | |||
171 | u_int16_t family, u_int8_t ttl) | 177 | u_int16_t family, u_int8_t ttl) |
172 | { | 178 | { |
173 | struct recent_entry *e; | 179 | struct recent_entry *e; |
180 | unsigned int nstamps_max = t->nstamps_max_mask; | ||
174 | 181 | ||
175 | if (t->entries >= ip_list_tot) { | 182 | if (t->entries >= ip_list_tot) { |
176 | e = list_entry(t->lru_list.next, struct recent_entry, lru_list); | 183 | e = list_entry(t->lru_list.next, struct recent_entry, lru_list); |
177 | recent_entry_remove(t, e); | 184 | recent_entry_remove(t, e); |
178 | } | 185 | } |
179 | e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * ip_pkt_list_tot, | 186 | |
187 | nstamps_max += 1; | ||
188 | e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * nstamps_max, | ||
180 | GFP_ATOMIC); | 189 | GFP_ATOMIC); |
181 | if (e == NULL) | 190 | if (e == NULL) |
182 | return NULL; | 191 | return NULL; |
@@ -197,7 +206,7 @@ recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr, | |||
197 | 206 | ||
198 | static void recent_entry_update(struct recent_table *t, struct recent_entry *e) | 207 | static void recent_entry_update(struct recent_table *t, struct recent_entry *e) |
199 | { | 208 | { |
200 | e->index %= ip_pkt_list_tot; | 209 | e->index &= t->nstamps_max_mask; |
201 | e->stamps[e->index++] = jiffies; | 210 | e->stamps[e->index++] = jiffies; |
202 | if (e->index > e->nstamps) | 211 | if (e->index > e->nstamps) |
203 | e->nstamps = e->index; | 212 | e->nstamps = e->index; |
@@ -326,6 +335,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
326 | kuid_t uid; | 335 | kuid_t uid; |
327 | kgid_t gid; | 336 | kgid_t gid; |
328 | #endif | 337 | #endif |
338 | unsigned int nstamp_mask; | ||
329 | unsigned int i; | 339 | unsigned int i; |
330 | int ret = -EINVAL; | 340 | int ret = -EINVAL; |
331 | size_t sz; | 341 | size_t sz; |
@@ -349,19 +359,33 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
349 | return -EINVAL; | 359 | return -EINVAL; |
350 | if ((info->check_set & XT_RECENT_REAP) && !info->seconds) | 360 | if ((info->check_set & XT_RECENT_REAP) && !info->seconds) |
351 | return -EINVAL; | 361 | return -EINVAL; |
352 | if (info->hit_count > ip_pkt_list_tot) { | 362 | if (info->hit_count >= XT_RECENT_MAX_NSTAMPS) { |
353 | pr_info("hitcount (%u) is larger than " | 363 | pr_info("hitcount (%u) is larger than allowed maximum (%u)\n", |
354 | "packets to be remembered (%u)\n", | 364 | info->hit_count, XT_RECENT_MAX_NSTAMPS - 1); |
355 | info->hit_count, ip_pkt_list_tot); | ||
356 | return -EINVAL; | 365 | return -EINVAL; |
357 | } | 366 | } |
358 | if (info->name[0] == '\0' || | 367 | if (info->name[0] == '\0' || |
359 | strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN) | 368 | strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN) |
360 | return -EINVAL; | 369 | return -EINVAL; |
361 | 370 | ||
371 | if (ip_pkt_list_tot && info->hit_count < ip_pkt_list_tot) | ||
372 | nstamp_mask = roundup_pow_of_two(ip_pkt_list_tot) - 1; | ||
373 | else if (info->hit_count) | ||
374 | nstamp_mask = roundup_pow_of_two(info->hit_count) - 1; | ||
375 | else | ||
376 | nstamp_mask = 32 - 1; | ||
377 | |||
362 | mutex_lock(&recent_mutex); | 378 | mutex_lock(&recent_mutex); |
363 | t = recent_table_lookup(recent_net, info->name); | 379 | t = recent_table_lookup(recent_net, info->name); |
364 | if (t != NULL) { | 380 | if (t != NULL) { |
381 | if (info->hit_count > t->nstamps_max_mask) { | ||
382 | pr_info("hitcount (%u) is larger than packets to be remembered (%u) for table %s\n", | ||
383 | info->hit_count, t->nstamps_max_mask + 1, | ||
384 | info->name); | ||
385 | ret = -EINVAL; | ||
386 | goto out; | ||
387 | } | ||
388 | |||
365 | t->refcnt++; | 389 | t->refcnt++; |
366 | ret = 0; | 390 | ret = 0; |
367 | goto out; | 391 | goto out; |
@@ -377,6 +401,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
377 | goto out; | 401 | goto out; |
378 | } | 402 | } |
379 | t->refcnt = 1; | 403 | t->refcnt = 1; |
404 | t->nstamps_max_mask = nstamp_mask; | ||
380 | 405 | ||
381 | memcpy(&t->mask, &info->mask, sizeof(t->mask)); | 406 | memcpy(&t->mask, &info->mask, sizeof(t->mask)); |
382 | strcpy(t->name, info->name); | 407 | strcpy(t->name, info->name); |
@@ -497,9 +522,12 @@ static void recent_seq_stop(struct seq_file *s, void *v) | |||
497 | static int recent_seq_show(struct seq_file *seq, void *v) | 522 | static int recent_seq_show(struct seq_file *seq, void *v) |
498 | { | 523 | { |
499 | const struct recent_entry *e = v; | 524 | const struct recent_entry *e = v; |
525 | struct recent_iter_state *st = seq->private; | ||
526 | const struct recent_table *t = st->table; | ||
500 | unsigned int i; | 527 | unsigned int i; |
501 | 528 | ||
502 | i = (e->index - 1) % ip_pkt_list_tot; | 529 | i = (e->index - 1) & t->nstamps_max_mask; |
530 | |||
503 | if (e->family == NFPROTO_IPV4) | 531 | if (e->family == NFPROTO_IPV4) |
504 | seq_printf(seq, "src=%pI4 ttl: %u last_seen: %lu oldest_pkt: %u", | 532 | seq_printf(seq, "src=%pI4 ttl: %u last_seen: %lu oldest_pkt: %u", |
505 | &e->addr.ip, e->ttl, e->stamps[i], e->index); | 533 | &e->addr.ip, e->ttl, e->stamps[i], e->index); |
@@ -717,7 +745,9 @@ static int __init recent_mt_init(void) | |||
717 | { | 745 | { |
718 | int err; | 746 | int err; |
719 | 747 | ||
720 | if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255) | 748 | BUILD_BUG_ON_NOT_POWER_OF_2(XT_RECENT_MAX_NSTAMPS); |
749 | |||
750 | if (!ip_list_tot || ip_pkt_list_tot >= XT_RECENT_MAX_NSTAMPS) | ||
721 | return -EINVAL; | 751 | return -EINVAL; |
722 | ip_list_hash_size = 1 << fls(ip_list_tot); | 752 | ip_list_hash_size = 1 << fls(ip_list_tot); |
723 | 753 | ||
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 5732cd64acc0..0d47afea9682 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c | |||
@@ -157,7 +157,7 @@ set_match_v1_destroy(const struct xt_mtdtor_param *par) | |||
157 | /* Revision 3 match */ | 157 | /* Revision 3 match */ |
158 | 158 | ||
159 | static bool | 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 | switch (info->op) { | 162 | switch (info->op) { |
163 | case IPSET_COUNTER_NONE: | 163 | case IPSET_COUNTER_NONE: |
@@ -192,14 +192,60 @@ set_match_v3(const struct sk_buff *skb, struct xt_action_param *par) | |||
192 | if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS)) | 192 | if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS)) |
193 | return ret; | 193 | return ret; |
194 | 194 | ||
195 | if (!match_counter(opt.ext.packets, &info->packets)) | 195 | if (!match_counter0(opt.ext.packets, &info->packets)) |
196 | return 0; | 196 | return 0; |
197 | return match_counter(opt.ext.bytes, &info->bytes); | 197 | return match_counter0(opt.ext.bytes, &info->bytes); |
198 | } | 198 | } |
199 | 199 | ||
200 | #define set_match_v3_checkentry set_match_v1_checkentry | 200 | #define set_match_v3_checkentry set_match_v1_checkentry |
201 | #define set_match_v3_destroy set_match_v1_destroy | 201 | #define set_match_v3_destroy set_match_v1_destroy |
202 | 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 | |||
241 | if (!match_counter(opt.ext.packets, &info->packets)) | ||
242 | return 0; | ||
243 | return match_counter(opt.ext.bytes, &info->bytes); | ||
244 | } | ||
245 | |||
246 | #define set_match_v4_checkentry set_match_v1_checkentry | ||
247 | #define set_match_v4_destroy set_match_v1_destroy | ||
248 | |||
203 | /* Revision 0 interface: backward compatible with netfilter/iptables */ | 249 | /* Revision 0 interface: backward compatible with netfilter/iptables */ |
204 | 250 | ||
205 | static unsigned int | 251 | static unsigned int |
@@ -573,6 +619,27 @@ static struct xt_match set_matches[] __read_mostly = { | |||
573 | .destroy = set_match_v3_destroy, | 619 | .destroy = set_match_v3_destroy, |
574 | .me = THIS_MODULE | 620 | .me = THIS_MODULE |
575 | }, | 621 | }, |
622 | /* new revision for counters support: update, match */ | ||
623 | { | ||
624 | .name = "set", | ||
625 | .family = NFPROTO_IPV4, | ||
626 | .revision = 4, | ||
627 | .match = set_match_v4, | ||
628 | .matchsize = sizeof(struct xt_set_info_match_v4), | ||
629 | .checkentry = set_match_v4_checkentry, | ||
630 | .destroy = set_match_v4_destroy, | ||
631 | .me = THIS_MODULE | ||
632 | }, | ||
633 | { | ||
634 | .name = "set", | ||
635 | .family = NFPROTO_IPV6, | ||
636 | .revision = 4, | ||
637 | .match = set_match_v4, | ||
638 | .matchsize = sizeof(struct xt_set_info_match_v4), | ||
639 | .checkentry = set_match_v4_checkentry, | ||
640 | .destroy = set_match_v4_destroy, | ||
641 | .me = THIS_MODULE | ||
642 | }, | ||
576 | }; | 643 | }; |
577 | 644 | ||
578 | static struct xt_target set_targets[] __read_mostly = { | 645 | static struct xt_target set_targets[] __read_mostly = { |