aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-01-06 13:29:30 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-06 13:29:30 -0500
commit9aa28f2b71055d5ae17a2e1daee359d4174bb13e (patch)
treefbf4e0fd11eb924e0bece74a87f442bc54441b35 /net
parent6a8c4796df74045088a916581c736432d08c53c0 (diff)
parentc9c8e485978a308c8a359140da187d55120f8fee (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nftables
Pablo Neira Ayuso says: <pablo@netfilter.org> ==================== nftables updates for net-next The following patchset contains nftables updates for your net-next tree, they are: * Add set operation to the meta expression by means of the select_ops() infrastructure, this allows us to set the packet mark among other things. From Arturo Borrero Gonzalez. * Fix wrong format in sscanf in nf_tables_set_alloc_name(), from Daniel Borkmann. * Add new queue expression to nf_tables. These comes with two previous patches to prepare this new feature, one to add mask in nf_tables_core to evaluate the queue verdict appropriately and another to refactor common code with xt_NFQUEUE, from Eric Leblond. * Do not hide nftables from Kconfig if nfnetlink is not enabled, also from Eric Leblond. * Add the reject expression to nf_tables, this adds the missing TCP RST support. It comes with an initial patch to refactor common code with xt_NFQUEUE, again from Eric Leblond. * Remove an unused variable assignment in nf_tables_dump_set(), from Michal Nazarewicz. * Remove the nft_meta_target code, now that Arturo added the set operation to the meta expression, from me. * Add help information for nf_tables to Kconfig, also from me. * Allow to dump all sets by specifying NFPROTO_UNSPEC, similar feature is available to other nf_tables objects, requested by Arturo, from me. * Expose the table usage counter, so we can know how many chains are using this table without dumping the list of chains, from Tomasz Bursztyka. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/Kconfig18
-rw-r--r--net/ipv4/netfilter/Makefile1
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c140
-rw-r--r--net/ipv6/netfilter/Kconfig12
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c179
-rw-r--r--net/netfilter/Kconfig59
-rw-r--r--net/netfilter/Makefile3
-rw-r--r--net/netfilter/nf_tables_api.c104
-rw-r--r--net/netfilter/nf_tables_core.c5
-rw-r--r--net/netfilter/nft_meta.c146
-rw-r--r--net/netfilter/nft_meta_target.c117
-rw-r--r--net/netfilter/nft_queue.c134
-rw-r--r--net/netfilter/nft_reject.c (renamed from net/ipv4/netfilter/nft_reject_ipv4.c)23
-rw-r--r--net/netfilter/xt_NFQUEUE.c80
14 files changed, 487 insertions, 534 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 40d56073cd19..81c6910cfa92 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -39,23 +39,33 @@ config NF_CONNTRACK_PROC_COMPAT
39config NF_TABLES_IPV4 39config NF_TABLES_IPV4
40 depends on NF_TABLES 40 depends on NF_TABLES
41 tristate "IPv4 nf_tables support" 41 tristate "IPv4 nf_tables support"
42 42 help
43config NFT_REJECT_IPV4 43 This option enables the IPv4 support for nf_tables.
44 depends on NF_TABLES_IPV4
45 tristate "nf_tables IPv4 reject support"
46 44
47config NFT_CHAIN_ROUTE_IPV4 45config NFT_CHAIN_ROUTE_IPV4
48 depends on NF_TABLES_IPV4 46 depends on NF_TABLES_IPV4
49 tristate "IPv4 nf_tables route chain support" 47 tristate "IPv4 nf_tables route chain support"
48 help
49 This option enables the "route" chain for IPv4 in nf_tables. This
50 chain type is used to force packet re-routing after mangling header
51 fields such as the source, destination, type of service and
52 the packet mark.
50 53
51config NFT_CHAIN_NAT_IPV4 54config NFT_CHAIN_NAT_IPV4
52 depends on NF_TABLES_IPV4 55 depends on NF_TABLES_IPV4
53 depends on NF_NAT_IPV4 && NFT_NAT 56 depends on NF_NAT_IPV4 && NFT_NAT
54 tristate "IPv4 nf_tables nat chain support" 57 tristate "IPv4 nf_tables nat chain support"
58 help
59 This option enables the "nat" chain for IPv4 in nf_tables. This
60 chain type is used to perform Network Address Translation (NAT)
61 packet transformations such as the source, destination address and
62 source and destination ports.
55 63
56config NF_TABLES_ARP 64config NF_TABLES_ARP
57 depends on NF_TABLES 65 depends on NF_TABLES
58 tristate "ARP nf_tables support" 66 tristate "ARP nf_tables support"
67 help
68 This option enables the ARP support for nf_tables.
59 69
60config IP_NF_IPTABLES 70config IP_NF_IPTABLES
61 tristate "IP tables support (required for filtering/masq/NAT)" 71 tristate "IP tables support (required for filtering/masq/NAT)"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 19df72b7ba88..c16be9d58420 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -28,7 +28,6 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
28obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o 28obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
29 29
30obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o 30obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
31obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
32obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o 31obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
33obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o 32obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
34obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o 33obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index b969131ad1c1..5b6e0df4ccff 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -17,10 +17,6 @@
17#include <linux/udp.h> 17#include <linux/udp.h>
18#include <linux/icmp.h> 18#include <linux/icmp.h>
19#include <net/icmp.h> 19#include <net/icmp.h>
20#include <net/ip.h>
21#include <net/tcp.h>
22#include <net/route.h>
23#include <net/dst.h>
24#include <linux/netfilter/x_tables.h> 20#include <linux/netfilter/x_tables.h>
25#include <linux/netfilter_ipv4/ip_tables.h> 21#include <linux/netfilter_ipv4/ip_tables.h>
26#include <linux/netfilter_ipv4/ipt_REJECT.h> 22#include <linux/netfilter_ipv4/ipt_REJECT.h>
@@ -28,128 +24,12 @@
28#include <linux/netfilter_bridge.h> 24#include <linux/netfilter_bridge.h>
29#endif 25#endif
30 26
27#include <net/netfilter/ipv4/nf_reject.h>
28
31MODULE_LICENSE("GPL"); 29MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 30MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
33MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4"); 31MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4");
34 32
35/* Send RST reply */
36static void send_reset(struct sk_buff *oldskb, int hook)
37{
38 struct sk_buff *nskb;
39 const struct iphdr *oiph;
40 struct iphdr *niph;
41 const struct tcphdr *oth;
42 struct tcphdr _otcph, *tcph;
43
44 /* IP header checks: fragment. */
45 if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
46 return;
47
48 oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
49 sizeof(_otcph), &_otcph);
50 if (oth == NULL)
51 return;
52
53 /* No RST for RST. */
54 if (oth->rst)
55 return;
56
57 if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
58 return;
59
60 /* Check checksum */
61 if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
62 return;
63 oiph = ip_hdr(oldskb);
64
65 nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
66 LL_MAX_HEADER, GFP_ATOMIC);
67 if (!nskb)
68 return;
69
70 skb_reserve(nskb, LL_MAX_HEADER);
71
72 skb_reset_network_header(nskb);
73 niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
74 niph->version = 4;
75 niph->ihl = sizeof(struct iphdr) / 4;
76 niph->tos = 0;
77 niph->id = 0;
78 niph->frag_off = htons(IP_DF);
79 niph->protocol = IPPROTO_TCP;
80 niph->check = 0;
81 niph->saddr = oiph->daddr;
82 niph->daddr = oiph->saddr;
83
84 skb_reset_transport_header(nskb);
85 tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
86 memset(tcph, 0, sizeof(*tcph));
87 tcph->source = oth->dest;
88 tcph->dest = oth->source;
89 tcph->doff = sizeof(struct tcphdr) / 4;
90
91 if (oth->ack)
92 tcph->seq = oth->ack_seq;
93 else {
94 tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
95 oldskb->len - ip_hdrlen(oldskb) -
96 (oth->doff << 2));
97 tcph->ack = 1;
98 }
99
100 tcph->rst = 1;
101 tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
102 niph->daddr, 0);
103 nskb->ip_summed = CHECKSUM_PARTIAL;
104 nskb->csum_start = (unsigned char *)tcph - nskb->head;
105 nskb->csum_offset = offsetof(struct tcphdr, check);
106
107 /* ip_route_me_harder expects skb->dst to be set */
108 skb_dst_set_noref(nskb, skb_dst(oldskb));
109
110 nskb->protocol = htons(ETH_P_IP);
111 if (ip_route_me_harder(nskb, RTN_UNSPEC))
112 goto free_nskb;
113
114 niph->ttl = ip4_dst_hoplimit(skb_dst(nskb));
115
116 /* "Never happens" */
117 if (nskb->len > dst_mtu(skb_dst(nskb)))
118 goto free_nskb;
119
120 nf_ct_attach(nskb, oldskb);
121
122#ifdef CONFIG_BRIDGE_NETFILTER
123 /* If we use ip_local_out for bridged traffic, the MAC source on
124 * the RST will be ours, instead of the destination's. This confuses
125 * some routers/firewalls, and they drop the packet. So we need to
126 * build the eth header using the original destination's MAC as the
127 * source, and send the RST packet directly.
128 */
129 if (oldskb->nf_bridge) {
130 struct ethhdr *oeth = eth_hdr(oldskb);
131 nskb->dev = oldskb->nf_bridge->physindev;
132 niph->tot_len = htons(nskb->len);
133 ip_send_check(niph);
134 if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
135 oeth->h_source, oeth->h_dest, nskb->len) < 0)
136 goto free_nskb;
137 dev_queue_xmit(nskb);
138 } else
139#endif
140 ip_local_out(nskb);
141
142 return;
143
144 free_nskb:
145 kfree_skb(nskb);
146}
147
148static inline void send_unreach(struct sk_buff *skb_in, int code)
149{
150 icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
151}
152
153static unsigned int 33static unsigned int
154reject_tg(struct sk_buff *skb, const struct xt_action_param *par) 34reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
155{ 35{
@@ -157,28 +37,28 @@ reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
157 37
158 switch (reject->with) { 38 switch (reject->with) {
159 case IPT_ICMP_NET_UNREACHABLE: 39 case IPT_ICMP_NET_UNREACHABLE:
160 send_unreach(skb, ICMP_NET_UNREACH); 40 nf_send_unreach(skb, ICMP_NET_UNREACH);
161 break; 41 break;
162 case IPT_ICMP_HOST_UNREACHABLE: 42 case IPT_ICMP_HOST_UNREACHABLE:
163 send_unreach(skb, ICMP_HOST_UNREACH); 43 nf_send_unreach(skb, ICMP_HOST_UNREACH);
164 break; 44 break;
165 case IPT_ICMP_PROT_UNREACHABLE: 45 case IPT_ICMP_PROT_UNREACHABLE:
166 send_unreach(skb, ICMP_PROT_UNREACH); 46 nf_send_unreach(skb, ICMP_PROT_UNREACH);
167 break; 47 break;
168 case IPT_ICMP_PORT_UNREACHABLE: 48 case IPT_ICMP_PORT_UNREACHABLE:
169 send_unreach(skb, ICMP_PORT_UNREACH); 49 nf_send_unreach(skb, ICMP_PORT_UNREACH);
170 break; 50 break;
171 case IPT_ICMP_NET_PROHIBITED: 51 case IPT_ICMP_NET_PROHIBITED:
172 send_unreach(skb, ICMP_NET_ANO); 52 nf_send_unreach(skb, ICMP_NET_ANO);
173 break; 53 break;
174 case IPT_ICMP_HOST_PROHIBITED: 54 case IPT_ICMP_HOST_PROHIBITED:
175 send_unreach(skb, ICMP_HOST_ANO); 55 nf_send_unreach(skb, ICMP_HOST_ANO);
176 break; 56 break;
177 case IPT_ICMP_ADMIN_PROHIBITED: 57 case IPT_ICMP_ADMIN_PROHIBITED:
178 send_unreach(skb, ICMP_PKT_FILTERED); 58 nf_send_unreach(skb, ICMP_PKT_FILTERED);
179 break; 59 break;
180 case IPT_TCP_RESET: 60 case IPT_TCP_RESET:
181 send_reset(skb, par->hooknum); 61 nf_send_reset(skb, par->hooknum);
182 case IPT_ICMP_ECHOREPLY: 62 case IPT_ICMP_ECHOREPLY:
183 /* Doesn't happen. */ 63 /* Doesn't happen. */
184 break; 64 break;
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 7702f9e90a04..35750df744dc 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -28,15 +28,27 @@ config NF_CONNTRACK_IPV6
28config NF_TABLES_IPV6 28config NF_TABLES_IPV6
29 depends on NF_TABLES 29 depends on NF_TABLES
30 tristate "IPv6 nf_tables support" 30 tristate "IPv6 nf_tables support"
31 help
32 This option enables the IPv6 support for nf_tables.
31 33
32config NFT_CHAIN_ROUTE_IPV6 34config NFT_CHAIN_ROUTE_IPV6
33 depends on NF_TABLES_IPV6 35 depends on NF_TABLES_IPV6
34 tristate "IPv6 nf_tables route chain support" 36 tristate "IPv6 nf_tables route chain support"
37 help
38 This option enables the "route" chain for IPv6 in nf_tables. This
39 chain type is used to force packet re-routing after mangling header
40 fields such as the source, destination, flowlabel, hop-limit and
41 the packet mark.
35 42
36config NFT_CHAIN_NAT_IPV6 43config NFT_CHAIN_NAT_IPV6
37 depends on NF_TABLES_IPV6 44 depends on NF_TABLES_IPV6
38 depends on NF_NAT_IPV6 && NFT_NAT 45 depends on NF_NAT_IPV6 && NFT_NAT
39 tristate "IPv6 nf_tables nat chain support" 46 tristate "IPv6 nf_tables nat chain support"
47 help
48 This option enables the "nat" chain for IPv6 in nf_tables. This
49 chain type is used to perform Network Address Translation (NAT)
50 packet transformations such as the source, destination address and
51 source and destination ports.
40 52
41config IP6_NF_IPTABLES 53config IP6_NF_IPTABLES
42 tristate "IP6 tables support (required for filtering)" 54 tristate "IP6 tables support (required for filtering)"
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index da00a2ecde55..544b0a9da1b5 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -23,181 +23,18 @@
23#include <linux/skbuff.h> 23#include <linux/skbuff.h>
24#include <linux/icmpv6.h> 24#include <linux/icmpv6.h>
25#include <linux/netdevice.h> 25#include <linux/netdevice.h>
26#include <net/ipv6.h>
27#include <net/tcp.h>
28#include <net/icmp.h> 26#include <net/icmp.h>
29#include <net/ip6_checksum.h>
30#include <net/ip6_fib.h>
31#include <net/ip6_route.h>
32#include <net/flow.h> 27#include <net/flow.h>
33#include <linux/netfilter/x_tables.h> 28#include <linux/netfilter/x_tables.h>
34#include <linux/netfilter_ipv6/ip6_tables.h> 29#include <linux/netfilter_ipv6/ip6_tables.h>
35#include <linux/netfilter_ipv6/ip6t_REJECT.h> 30#include <linux/netfilter_ipv6/ip6t_REJECT.h>
36 31
32#include <net/netfilter/ipv6/nf_reject.h>
33
37MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>"); 34MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
38MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv6"); 35MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv6");
39MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
40 37
41/* Send RST reply */
42static void send_reset(struct net *net, struct sk_buff *oldskb, int hook)
43{
44 struct sk_buff *nskb;
45 struct tcphdr otcph, *tcph;
46 unsigned int otcplen, hh_len;
47 int tcphoff, needs_ack;
48 const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
49 struct ipv6hdr *ip6h;
50#define DEFAULT_TOS_VALUE 0x0U
51 const __u8 tclass = DEFAULT_TOS_VALUE;
52 struct dst_entry *dst = NULL;
53 u8 proto;
54 __be16 frag_off;
55 struct flowi6 fl6;
56
57 if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
58 (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
59 pr_debug("addr is not unicast.\n");
60 return;
61 }
62
63 proto = oip6h->nexthdr;
64 tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
65
66 if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
67 pr_debug("Cannot get TCP header.\n");
68 return;
69 }
70
71 otcplen = oldskb->len - tcphoff;
72
73 /* IP header checks: fragment, too short. */
74 if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
75 pr_debug("proto(%d) != IPPROTO_TCP, "
76 "or too short. otcplen = %d\n",
77 proto, otcplen);
78 return;
79 }
80
81 if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr)))
82 BUG();
83
84 /* No RST for RST. */
85 if (otcph.rst) {
86 pr_debug("RST is set\n");
87 return;
88 }
89
90 /* Check checksum. */
91 if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) {
92 pr_debug("TCP checksum is invalid\n");
93 return;
94 }
95
96 memset(&fl6, 0, sizeof(fl6));
97 fl6.flowi6_proto = IPPROTO_TCP;
98 fl6.saddr = oip6h->daddr;
99 fl6.daddr = oip6h->saddr;
100 fl6.fl6_sport = otcph.dest;
101 fl6.fl6_dport = otcph.source;
102 security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
103 dst = ip6_route_output(net, NULL, &fl6);
104 if (dst == NULL || dst->error) {
105 dst_release(dst);
106 return;
107 }
108 dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
109 if (IS_ERR(dst))
110 return;
111
112 hh_len = (dst->dev->hard_header_len + 15)&~15;
113 nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
114 + sizeof(struct tcphdr) + dst->trailer_len,
115 GFP_ATOMIC);
116
117 if (!nskb) {
118 net_dbg_ratelimited("cannot alloc skb\n");
119 dst_release(dst);
120 return;
121 }
122
123 skb_dst_set(nskb, dst);
124
125 skb_reserve(nskb, hh_len + dst->header_len);
126
127 skb_put(nskb, sizeof(struct ipv6hdr));
128 skb_reset_network_header(nskb);
129 ip6h = ipv6_hdr(nskb);
130 ip6_flow_hdr(ip6h, tclass, 0);
131 ip6h->hop_limit = ip6_dst_hoplimit(dst);
132 ip6h->nexthdr = IPPROTO_TCP;
133 ip6h->saddr = oip6h->daddr;
134 ip6h->daddr = oip6h->saddr;
135
136 skb_reset_transport_header(nskb);
137 tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
138 /* Truncate to length (no data) */
139 tcph->doff = sizeof(struct tcphdr)/4;
140 tcph->source = otcph.dest;
141 tcph->dest = otcph.source;
142
143 if (otcph.ack) {
144 needs_ack = 0;
145 tcph->seq = otcph.ack_seq;
146 tcph->ack_seq = 0;
147 } else {
148 needs_ack = 1;
149 tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
150 + otcplen - (otcph.doff<<2));
151 tcph->seq = 0;
152 }
153
154 /* Reset flags */
155 ((u_int8_t *)tcph)[13] = 0;
156 tcph->rst = 1;
157 tcph->ack = needs_ack;
158 tcph->window = 0;
159 tcph->urg_ptr = 0;
160 tcph->check = 0;
161
162 /* Adjust TCP checksum */
163 tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
164 &ipv6_hdr(nskb)->daddr,
165 sizeof(struct tcphdr), IPPROTO_TCP,
166 csum_partial(tcph,
167 sizeof(struct tcphdr), 0));
168
169 nf_ct_attach(nskb, oldskb);
170
171#ifdef CONFIG_BRIDGE_NETFILTER
172 /* If we use ip6_local_out for bridged traffic, the MAC source on
173 * the RST will be ours, instead of the destination's. This confuses
174 * some routers/firewalls, and they drop the packet. So we need to
175 * build the eth header using the original destination's MAC as the
176 * source, and send the RST packet directly.
177 */
178 if (oldskb->nf_bridge) {
179 struct ethhdr *oeth = eth_hdr(oldskb);
180 nskb->dev = oldskb->nf_bridge->physindev;
181 nskb->protocol = htons(ETH_P_IPV6);
182 ip6h->payload_len = htons(sizeof(struct tcphdr));
183 if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
184 oeth->h_source, oeth->h_dest, nskb->len) < 0)
185 return;
186 dev_queue_xmit(nskb);
187 } else
188#endif
189 ip6_local_out(nskb);
190}
191
192static inline void
193send_unreach(struct net *net, struct sk_buff *skb_in, unsigned char code,
194 unsigned int hooknum)
195{
196 if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
197 skb_in->dev = net->loopback_dev;
198
199 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
200}
201 38
202static unsigned int 39static unsigned int
203reject_tg6(struct sk_buff *skb, const struct xt_action_param *par) 40reject_tg6(struct sk_buff *skb, const struct xt_action_param *par)
@@ -208,25 +45,25 @@ reject_tg6(struct sk_buff *skb, const struct xt_action_param *par)
208 pr_debug("%s: medium point\n", __func__); 45 pr_debug("%s: medium point\n", __func__);
209 switch (reject->with) { 46 switch (reject->with) {
210 case IP6T_ICMP6_NO_ROUTE: 47 case IP6T_ICMP6_NO_ROUTE:
211 send_unreach(net, skb, ICMPV6_NOROUTE, par->hooknum); 48 nf_send_unreach6(net, skb, ICMPV6_NOROUTE, par->hooknum);
212 break; 49 break;
213 case IP6T_ICMP6_ADM_PROHIBITED: 50 case IP6T_ICMP6_ADM_PROHIBITED:
214 send_unreach(net, skb, ICMPV6_ADM_PROHIBITED, par->hooknum); 51 nf_send_unreach6(net, skb, ICMPV6_ADM_PROHIBITED, par->hooknum);
215 break; 52 break;
216 case IP6T_ICMP6_NOT_NEIGHBOUR: 53 case IP6T_ICMP6_NOT_NEIGHBOUR:
217 send_unreach(net, skb, ICMPV6_NOT_NEIGHBOUR, par->hooknum); 54 nf_send_unreach6(net, skb, ICMPV6_NOT_NEIGHBOUR, par->hooknum);
218 break; 55 break;
219 case IP6T_ICMP6_ADDR_UNREACH: 56 case IP6T_ICMP6_ADDR_UNREACH:
220 send_unreach(net, skb, ICMPV6_ADDR_UNREACH, par->hooknum); 57 nf_send_unreach6(net, skb, ICMPV6_ADDR_UNREACH, par->hooknum);
221 break; 58 break;
222 case IP6T_ICMP6_PORT_UNREACH: 59 case IP6T_ICMP6_PORT_UNREACH:
223 send_unreach(net, skb, ICMPV6_PORT_UNREACH, par->hooknum); 60 nf_send_unreach6(net, skb, ICMPV6_PORT_UNREACH, par->hooknum);
224 break; 61 break;
225 case IP6T_ICMP6_ECHOREPLY: 62 case IP6T_ICMP6_ECHOREPLY:
226 /* Do nothing */ 63 /* Do nothing */
227 break; 64 break;
228 case IP6T_TCP_RESET: 65 case IP6T_TCP_RESET:
229 send_reset(net, skb, par->hooknum); 66 nf_send_reset6(net, skb, par->hooknum);
230 break; 67 break;
231 default: 68 default:
232 net_info_ratelimited("case %u not handled yet\n", reject->with); 69 net_info_ratelimited("case %u not handled yet\n", reject->with);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index c17902cb5df9..c3b3b26c4c4e 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -414,47 +414,104 @@ config NETFILTER_SYNPROXY
414endif # NF_CONNTRACK 414endif # NF_CONNTRACK
415 415
416config NF_TABLES 416config NF_TABLES
417 depends on NETFILTER_NETLINK 417 select NETFILTER_NETLINK
418 tristate "Netfilter nf_tables support" 418 tristate "Netfilter nf_tables support"
419 help
420 nftables is the new packet classification framework that intends to
421 replace the existing {ip,ip6,arp,eb}_tables infrastructure. It
422 provides a pseudo-state machine with an extensible instruction-set
423 (also known as expressions) that the userspace 'nft' utility
424 (http://www.netfilter.org/projects/nftables) uses to build the
425 rule-set. It also comes with the generic set infrastructure that
426 allows you to construct mappings between matchings and actions
427 for performance lookups.
428
429 To compile it as a module, choose M here.
419 430
420config NFT_EXTHDR 431config NFT_EXTHDR
421 depends on NF_TABLES 432 depends on NF_TABLES
422 tristate "Netfilter nf_tables IPv6 exthdr module" 433 tristate "Netfilter nf_tables IPv6 exthdr module"
434 help
435 This option adds the "exthdr" expression that you can use to match
436 IPv6 extension headers.
423 437
424config NFT_META 438config NFT_META
425 depends on NF_TABLES 439 depends on NF_TABLES
426 tristate "Netfilter nf_tables meta module" 440 tristate "Netfilter nf_tables meta module"
441 help
442 This option adds the "meta" expression that you can use to match and
443 to set packet metainformation such as the packet mark.
427 444
428config NFT_CT 445config NFT_CT
429 depends on NF_TABLES 446 depends on NF_TABLES
430 depends on NF_CONNTRACK 447 depends on NF_CONNTRACK
431 tristate "Netfilter nf_tables conntrack module" 448 tristate "Netfilter nf_tables conntrack module"
449 help
450 This option adds the "meta" expression that you can use to match
451 connection tracking information such as the flow state.
432 452
433config NFT_RBTREE 453config NFT_RBTREE
434 depends on NF_TABLES 454 depends on NF_TABLES
435 tristate "Netfilter nf_tables rbtree set module" 455 tristate "Netfilter nf_tables rbtree set module"
456 help
457 This option adds the "rbtree" set type (Red Black tree) that is used
458 to build interval-based sets.
436 459
437config NFT_HASH 460config NFT_HASH
438 depends on NF_TABLES 461 depends on NF_TABLES
439 tristate "Netfilter nf_tables hash set module" 462 tristate "Netfilter nf_tables hash set module"
463 help
464 This option adds the "hash" set type that is used to build one-way
465 mappings between matchings and actions.
440 466
441config NFT_COUNTER 467config NFT_COUNTER
442 depends on NF_TABLES 468 depends on NF_TABLES
443 tristate "Netfilter nf_tables counter module" 469 tristate "Netfilter nf_tables counter module"
470 help
471 This option adds the "counter" expression that you can use to
472 include packet and byte counters in a rule.
444 473
445config NFT_LOG 474config NFT_LOG
446 depends on NF_TABLES 475 depends on NF_TABLES
447 tristate "Netfilter nf_tables log module" 476 tristate "Netfilter nf_tables log module"
477 help
478 This option adds the "log" expression that you can use to log
479 packets matching some criteria.
448 480
449config NFT_LIMIT 481config NFT_LIMIT
450 depends on NF_TABLES 482 depends on NF_TABLES
451 tristate "Netfilter nf_tables limit module" 483 tristate "Netfilter nf_tables limit module"
484 help
485 This option adds the "limit" expression that you can use to
486 ratelimit rule matchings.
452 487
453config NFT_NAT 488config NFT_NAT
454 depends on NF_TABLES 489 depends on NF_TABLES
455 depends on NF_CONNTRACK 490 depends on NF_CONNTRACK
456 depends on NF_NAT 491 depends on NF_NAT
457 tristate "Netfilter nf_tables nat module" 492 tristate "Netfilter nf_tables nat module"
493 help
494 This option adds the "nat" expression that you can use to perform
495 typical Network Address Translation (NAT) packet transformations.
496
497config NFT_QUEUE
498 depends on NF_TABLES
499 depends on NETFILTER_XTABLES
500 depends on NETFILTER_NETLINK_QUEUE
501 tristate "Netfilter nf_tables queue module"
502 help
503 This is required if you intend to use the userspace queueing
504 infrastructure (also known as NFQUEUE) from nftables.
505
506config NFT_REJECT
507 depends on NF_TABLES
508 depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6
509 default m if NETFILTER_ADVANCED=n
510 tristate "Netfilter nf_tables reject support"
511 help
512 This option adds the "reject" expression that you can use to
513 explicitly deny and notify via TCP reset/ICMP informational errors
514 unallowed traffic.
458 515
459config NFT_COMPAT 516config NFT_COMPAT
460 depends on NF_TABLES 517 depends on NF_TABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 407fc232f625..78b4e1c9c595 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -76,7 +76,8 @@ obj-$(CONFIG_NFT_META) += nft_meta.o
76obj-$(CONFIG_NFT_CT) += nft_ct.o 76obj-$(CONFIG_NFT_CT) += nft_ct.o
77obj-$(CONFIG_NFT_LIMIT) += nft_limit.o 77obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
78obj-$(CONFIG_NFT_NAT) += nft_nat.o 78obj-$(CONFIG_NFT_NAT) += nft_nat.o
79#nf_tables-objs += nft_meta_target.o 79obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
80obj-$(CONFIG_NFT_REJECT) += nft_reject.o
80obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o 81obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
81obj-$(CONFIG_NFT_HASH) += nft_hash.o 82obj-$(CONFIG_NFT_HASH) += nft_hash.o
82obj-$(CONFIG_NFT_COUNTER) += nft_counter.o 83obj-$(CONFIG_NFT_COUNTER) += nft_counter.o
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index f93b7d06f4be..629b6da98318 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -180,7 +180,8 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, u32 portid, u32 seq,
180 nfmsg->res_id = 0; 180 nfmsg->res_id = 0;
181 181
182 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || 182 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
183 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags))) 183 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) ||
184 nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)))
184 goto nla_put_failure; 185 goto nla_put_failure;
185 186
186 return nlmsg_end(skb, nlh); 187 return nlmsg_end(skb, nlh);
@@ -1923,12 +1924,14 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
1923{ 1924{
1924 struct net *net = sock_net(skb->sk); 1925 struct net *net = sock_net(skb->sk);
1925 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1926 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1926 const struct nft_af_info *afi; 1927 const struct nft_af_info *afi = NULL;
1927 const struct nft_table *table = NULL; 1928 const struct nft_table *table = NULL;
1928 1929
1929 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); 1930 if (nfmsg->nfgen_family != NFPROTO_UNSPEC) {
1930 if (IS_ERR(afi)) 1931 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
1931 return PTR_ERR(afi); 1932 if (IS_ERR(afi))
1933 return PTR_ERR(afi);
1934 }
1932 1935
1933 if (nla[NFTA_SET_TABLE] != NULL) { 1936 if (nla[NFTA_SET_TABLE] != NULL) {
1934 table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); 1937 table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
@@ -1973,11 +1976,14 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
1973 return -ENOMEM; 1976 return -ENOMEM;
1974 1977
1975 list_for_each_entry(i, &ctx->table->sets, list) { 1978 list_for_each_entry(i, &ctx->table->sets, list) {
1976 if (!sscanf(i->name, name, &n)) 1979 int tmp;
1980
1981 if (!sscanf(i->name, name, &tmp))
1977 continue; 1982 continue;
1978 if (n < 0 || n > BITS_PER_LONG * PAGE_SIZE) 1983 if (tmp < 0 || tmp > BITS_PER_LONG * PAGE_SIZE)
1979 continue; 1984 continue;
1980 set_bit(n, inuse); 1985
1986 set_bit(tmp, inuse);
1981 } 1987 }
1982 1988
1983 n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE); 1989 n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE);
@@ -2094,8 +2100,8 @@ done:
2094 return skb->len; 2100 return skb->len;
2095} 2101}
2096 2102
2097static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb, 2103static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2098 struct netlink_callback *cb) 2104 struct netlink_callback *cb)
2099{ 2105{
2100 const struct nft_set *set; 2106 const struct nft_set *set;
2101 unsigned int idx = 0, s_idx = cb->args[0]; 2107 unsigned int idx = 0, s_idx = cb->args[0];
@@ -2127,6 +2133,61 @@ done:
2127 return skb->len; 2133 return skb->len;
2128} 2134}
2129 2135
2136static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2137 struct netlink_callback *cb)
2138{
2139 const struct nft_set *set;
2140 unsigned int idx, s_idx = cb->args[0];
2141 const struct nft_af_info *afi;
2142 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
2143 struct net *net = sock_net(skb->sk);
2144 int cur_family = cb->args[3];
2145
2146 if (cb->args[1])
2147 return skb->len;
2148
2149 list_for_each_entry(afi, &net->nft.af_info, list) {
2150 if (cur_family) {
2151 if (afi->family != cur_family)
2152 continue;
2153
2154 cur_family = 0;
2155 }
2156
2157 list_for_each_entry(table, &afi->tables, list) {
2158 if (cur_table) {
2159 if (cur_table != table)
2160 continue;
2161
2162 cur_table = NULL;
2163 }
2164
2165 ctx->table = table;
2166 ctx->afi = afi;
2167 idx = 0;
2168 list_for_each_entry(set, &ctx->table->sets, list) {
2169 if (idx < s_idx)
2170 goto cont;
2171 if (nf_tables_fill_set(skb, ctx, set,
2172 NFT_MSG_NEWSET,
2173 NLM_F_MULTI) < 0) {
2174 cb->args[0] = idx;
2175 cb->args[2] = (unsigned long) table;
2176 cb->args[3] = afi->family;
2177 goto done;
2178 }
2179cont:
2180 idx++;
2181 }
2182 if (s_idx)
2183 s_idx = 0;
2184 }
2185 }
2186 cb->args[1] = 1;
2187done:
2188 return skb->len;
2189}
2190
2130static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) 2191static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
2131{ 2192{
2132 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 2193 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
@@ -2143,9 +2204,12 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
2143 if (err < 0) 2204 if (err < 0)
2144 return err; 2205 return err;
2145 2206
2146 if (ctx.table == NULL) 2207 if (ctx.table == NULL) {
2147 ret = nf_tables_dump_sets_all(&ctx, skb, cb); 2208 if (ctx.afi == NULL)
2148 else 2209 ret = nf_tables_dump_sets_all(&ctx, skb, cb);
2210 else
2211 ret = nf_tables_dump_sets_family(&ctx, skb, cb);
2212 } else
2149 ret = nf_tables_dump_sets_table(&ctx, skb, cb); 2213 ret = nf_tables_dump_sets_table(&ctx, skb, cb);
2150 2214
2151 return ret; 2215 return ret;
@@ -2158,6 +2222,7 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
2158 const struct nft_set *set; 2222 const struct nft_set *set;
2159 struct nft_ctx ctx; 2223 struct nft_ctx ctx;
2160 struct sk_buff *skb2; 2224 struct sk_buff *skb2;
2225 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2161 int err; 2226 int err;
2162 2227
2163 /* Verify existance before starting dump */ 2228 /* Verify existance before starting dump */
@@ -2172,6 +2237,10 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
2172 return netlink_dump_start(nlsk, skb, nlh, &c); 2237 return netlink_dump_start(nlsk, skb, nlh, &c);
2173 } 2238 }
2174 2239
2240 /* Only accept unspec with dump */
2241 if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
2242 return -EAFNOSUPPORT;
2243
2175 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); 2244 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
2176 if (IS_ERR(set)) 2245 if (IS_ERR(set))
2177 return PTR_ERR(set); 2246 return PTR_ERR(set);
@@ -2341,6 +2410,7 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
2341 const struct nlmsghdr *nlh, 2410 const struct nlmsghdr *nlh,
2342 const struct nlattr * const nla[]) 2411 const struct nlattr * const nla[])
2343{ 2412{
2413 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2344 struct nft_set *set; 2414 struct nft_set *set;
2345 struct nft_ctx ctx; 2415 struct nft_ctx ctx;
2346 int err; 2416 int err;
@@ -2352,6 +2422,9 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
2352 if (err < 0) 2422 if (err < 0)
2353 return err; 2423 return err;
2354 2424
2425 if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
2426 return -EAFNOSUPPORT;
2427
2355 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); 2428 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
2356 if (IS_ERR(set)) 2429 if (IS_ERR(set))
2357 return PTR_ERR(set); 2430 return PTR_ERR(set);
@@ -2521,9 +2594,8 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
2521 u32 portid, seq; 2594 u32 portid, seq;
2522 int event, err; 2595 int event, err;
2523 2596
2524 nfmsg = nlmsg_data(cb->nlh); 2597 err = nlmsg_parse(cb->nlh, sizeof(struct nfgenmsg), nla,
2525 err = nlmsg_parse(cb->nlh, sizeof(*nfmsg), nla, NFTA_SET_ELEM_LIST_MAX, 2598 NFTA_SET_ELEM_LIST_MAX, nft_set_elem_list_policy);
2526 nft_set_elem_list_policy);
2527 if (err < 0) 2599 if (err < 0)
2528 return err; 2600 return err;
2529 2601
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index cb9e685caae1..e8fcc343c2b9 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -164,7 +164,7 @@ next_rule:
164 break; 164 break;
165 } 165 }
166 166
167 switch (data[NFT_REG_VERDICT].verdict) { 167 switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) {
168 case NF_ACCEPT: 168 case NF_ACCEPT:
169 case NF_DROP: 169 case NF_DROP:
170 case NF_QUEUE: 170 case NF_QUEUE:
@@ -172,6 +172,9 @@ next_rule:
172 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); 172 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
173 173
174 return data[NFT_REG_VERDICT].verdict; 174 return data[NFT_REG_VERDICT].verdict;
175 }
176
177 switch (data[NFT_REG_VERDICT].verdict) {
175 case NFT_JUMP: 178 case NFT_JUMP:
176 if (unlikely(pkt->skb->nf_trace)) 179 if (unlikely(pkt->skb->nf_trace))
177 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); 180 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 8c28220a90b3..1ceaaa6dfe72 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -21,12 +21,15 @@
21 21
22struct nft_meta { 22struct nft_meta {
23 enum nft_meta_keys key:8; 23 enum nft_meta_keys key:8;
24 enum nft_registers dreg:8; 24 union {
25 enum nft_registers dreg:8;
26 enum nft_registers sreg:8;
27 };
25}; 28};
26 29
27static void nft_meta_eval(const struct nft_expr *expr, 30static void nft_meta_get_eval(const struct nft_expr *expr,
28 struct nft_data data[NFT_REG_MAX + 1], 31 struct nft_data data[NFT_REG_MAX + 1],
29 const struct nft_pktinfo *pkt) 32 const struct nft_pktinfo *pkt)
30{ 33{
31 const struct nft_meta *priv = nft_expr_priv(expr); 34 const struct nft_meta *priv = nft_expr_priv(expr);
32 const struct sk_buff *skb = pkt->skb; 35 const struct sk_buff *skb = pkt->skb;
@@ -132,23 +135,50 @@ err:
132 data[NFT_REG_VERDICT].verdict = NFT_BREAK; 135 data[NFT_REG_VERDICT].verdict = NFT_BREAK;
133} 136}
134 137
138static void nft_meta_set_eval(const struct nft_expr *expr,
139 struct nft_data data[NFT_REG_MAX + 1],
140 const struct nft_pktinfo *pkt)
141{
142 const struct nft_meta *meta = nft_expr_priv(expr);
143 struct sk_buff *skb = pkt->skb;
144 u32 value = data[meta->sreg].data[0];
145
146 switch (meta->key) {
147 case NFT_META_MARK:
148 skb->mark = value;
149 break;
150 case NFT_META_PRIORITY:
151 skb->priority = value;
152 break;
153 case NFT_META_NFTRACE:
154 skb->nf_trace = 1;
155 break;
156 default:
157 WARN_ON(1);
158 }
159}
160
135static const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = { 161static const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
136 [NFTA_META_DREG] = { .type = NLA_U32 }, 162 [NFTA_META_DREG] = { .type = NLA_U32 },
137 [NFTA_META_KEY] = { .type = NLA_U32 }, 163 [NFTA_META_KEY] = { .type = NLA_U32 },
164 [NFTA_META_SREG] = { .type = NLA_U32 },
138}; 165};
139 166
140static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr, 167static int nft_meta_init_validate_set(uint32_t key)
141 const struct nlattr * const tb[])
142{ 168{
143 struct nft_meta *priv = nft_expr_priv(expr); 169 switch (key) {
144 int err; 170 case NFT_META_MARK:
145 171 case NFT_META_PRIORITY:
146 if (tb[NFTA_META_DREG] == NULL || 172 case NFT_META_NFTRACE:
147 tb[NFTA_META_KEY] == NULL) 173 return 0;
148 return -EINVAL; 174 default:
175 return -EOPNOTSUPP;
176 }
177}
149 178
150 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); 179static int nft_meta_init_validate_get(uint32_t key)
151 switch (priv->key) { 180{
181 switch (key) {
152 case NFT_META_LEN: 182 case NFT_META_LEN:
153 case NFT_META_PROTOCOL: 183 case NFT_META_PROTOCOL:
154 case NFT_META_PRIORITY: 184 case NFT_META_PRIORITY:
@@ -167,26 +197,69 @@ static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
167#ifdef CONFIG_NETWORK_SECMARK 197#ifdef CONFIG_NETWORK_SECMARK
168 case NFT_META_SECMARK: 198 case NFT_META_SECMARK:
169#endif 199#endif
170 break; 200 return 0;
171 default: 201 default:
172 return -EOPNOTSUPP; 202 return -EOPNOTSUPP;
173 } 203 }
174 204
175 priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG])); 205}
176 err = nft_validate_output_register(priv->dreg); 206
207static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
208 const struct nlattr * const tb[])
209{
210 struct nft_meta *priv = nft_expr_priv(expr);
211 int err;
212
213 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
214
215 if (tb[NFTA_META_DREG]) {
216 err = nft_meta_init_validate_get(priv->key);
217 if (err < 0)
218 return err;
219
220 priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG]));
221 err = nft_validate_output_register(priv->dreg);
222 if (err < 0)
223 return err;
224
225 return nft_validate_data_load(ctx, priv->dreg, NULL,
226 NFT_DATA_VALUE);
227 }
228
229 err = nft_meta_init_validate_set(priv->key);
177 if (err < 0) 230 if (err < 0)
178 return err; 231 return err;
179 return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 232
233 priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG]));
234
235 return 0;
180} 236}
181 237
182static int nft_meta_dump(struct sk_buff *skb, const struct nft_expr *expr) 238static int nft_meta_get_dump(struct sk_buff *skb,
239 const struct nft_expr *expr)
183{ 240{
184 const struct nft_meta *priv = nft_expr_priv(expr); 241 const struct nft_meta *priv = nft_expr_priv(expr);
185 242
243 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
244 goto nla_put_failure;
186 if (nla_put_be32(skb, NFTA_META_DREG, htonl(priv->dreg))) 245 if (nla_put_be32(skb, NFTA_META_DREG, htonl(priv->dreg)))
187 goto nla_put_failure; 246 goto nla_put_failure;
247 return 0;
248
249nla_put_failure:
250 return -1;
251}
252
253static int nft_meta_set_dump(struct sk_buff *skb,
254 const struct nft_expr *expr)
255{
256 const struct nft_meta *priv = nft_expr_priv(expr);
257
188 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) 258 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
189 goto nla_put_failure; 259 goto nla_put_failure;
260 if (nla_put_be32(skb, NFTA_META_SREG, htonl(priv->sreg)))
261 goto nla_put_failure;
262
190 return 0; 263 return 0;
191 264
192nla_put_failure: 265nla_put_failure:
@@ -194,17 +267,44 @@ nla_put_failure:
194} 267}
195 268
196static struct nft_expr_type nft_meta_type; 269static struct nft_expr_type nft_meta_type;
197static const struct nft_expr_ops nft_meta_ops = { 270static const struct nft_expr_ops nft_meta_get_ops = {
198 .type = &nft_meta_type, 271 .type = &nft_meta_type,
199 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), 272 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
200 .eval = nft_meta_eval, 273 .eval = nft_meta_get_eval,
201 .init = nft_meta_init, 274 .init = nft_meta_init,
202 .dump = nft_meta_dump, 275 .dump = nft_meta_get_dump,
203}; 276};
204 277
278static const struct nft_expr_ops nft_meta_set_ops = {
279 .type = &nft_meta_type,
280 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
281 .eval = nft_meta_set_eval,
282 .init = nft_meta_init,
283 .dump = nft_meta_set_dump,
284};
285
286static const struct nft_expr_ops *
287nft_meta_select_ops(const struct nft_ctx *ctx,
288 const struct nlattr * const tb[])
289{
290 if (tb[NFTA_META_KEY] == NULL)
291 return ERR_PTR(-EINVAL);
292
293 if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
294 return ERR_PTR(-EINVAL);
295
296 if (tb[NFTA_META_DREG])
297 return &nft_meta_get_ops;
298
299 if (tb[NFTA_META_SREG])
300 return &nft_meta_set_ops;
301
302 return ERR_PTR(-EINVAL);
303}
304
205static struct nft_expr_type nft_meta_type __read_mostly = { 305static struct nft_expr_type nft_meta_type __read_mostly = {
206 .name = "meta", 306 .name = "meta",
207 .ops = &nft_meta_ops, 307 .select_ops = &nft_meta_select_ops,
208 .policy = nft_meta_policy, 308 .policy = nft_meta_policy,
209 .maxattr = NFTA_META_MAX, 309 .maxattr = NFTA_META_MAX,
210 .owner = THIS_MODULE, 310 .owner = THIS_MODULE,
diff --git a/net/netfilter/nft_meta_target.c b/net/netfilter/nft_meta_target.c
deleted file mode 100644
index 71177df75ffb..000000000000
--- a/net/netfilter/nft_meta_target.c
+++ /dev/null
@@ -1,117 +0,0 @@
1/*
2 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Development of this code funded by Astaro AG (http://www.astaro.com/)
9 */
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/list.h>
14#include <linux/rbtree.h>
15#include <linux/netlink.h>
16#include <linux/netfilter.h>
17#include <linux/netfilter/nf_tables.h>
18#include <net/netfilter/nf_tables.h>
19
20struct nft_meta {
21 enum nft_meta_keys key;
22};
23
24static void nft_meta_eval(const struct nft_expr *expr,
25 struct nft_data *nfres,
26 struct nft_data *data,
27 const struct nft_pktinfo *pkt)
28{
29 const struct nft_meta *meta = nft_expr_priv(expr);
30 struct sk_buff *skb = pkt->skb;
31 u32 val = data->data[0];
32
33 switch (meta->key) {
34 case NFT_META_MARK:
35 skb->mark = val;
36 break;
37 case NFT_META_PRIORITY:
38 skb->priority = val;
39 break;
40 case NFT_META_NFTRACE:
41 skb->nf_trace = val;
42 break;
43#ifdef CONFIG_NETWORK_SECMARK
44 case NFT_META_SECMARK:
45 skb->secmark = val;
46 break;
47#endif
48 default:
49 WARN_ON(1);
50 }
51}
52
53static const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
54 [NFTA_META_KEY] = { .type = NLA_U32 },
55};
56
57static int nft_meta_init(const struct nft_expr *expr, struct nlattr *tb[])
58{
59 struct nft_meta *meta = nft_expr_priv(expr);
60
61 if (tb[NFTA_META_KEY] == NULL)
62 return -EINVAL;
63
64 meta->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
65 switch (meta->key) {
66 case NFT_META_MARK:
67 case NFT_META_PRIORITY:
68 case NFT_META_NFTRACE:
69#ifdef CONFIG_NETWORK_SECMARK
70 case NFT_META_SECMARK:
71#endif
72 break;
73 default:
74 return -EINVAL;
75 }
76
77 return 0;
78}
79
80static int nft_meta_dump(struct sk_buff *skb, const struct nft_expr *expr)
81{
82 struct nft_meta *meta = nft_expr_priv(expr);
83
84 NLA_PUT_BE32(skb, NFTA_META_KEY, htonl(meta->key));
85 return 0;
86
87nla_put_failure:
88 return -1;
89}
90
91static struct nft_expr_ops meta_target __read_mostly = {
92 .name = "meta",
93 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
94 .owner = THIS_MODULE,
95 .eval = nft_meta_eval,
96 .init = nft_meta_init,
97 .dump = nft_meta_dump,
98 .policy = nft_meta_policy,
99 .maxattr = NFTA_META_MAX,
100};
101
102static int __init nft_meta_target_init(void)
103{
104 return nft_register_expr(&meta_target);
105}
106
107static void __exit nft_meta_target_exit(void)
108{
109 nft_unregister_expr(&meta_target);
110}
111
112module_init(nft_meta_target_init);
113module_exit(nft_meta_target_exit);
114
115MODULE_LICENSE("GPL");
116MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
117MODULE_ALIAS_NFT_EXPR("meta");
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
new file mode 100644
index 000000000000..cbea473d69e9
--- /dev/null
+++ b/net/netfilter/nft_queue.c
@@ -0,0 +1,134 @@
1/*
2 * Copyright (c) 2013 Eric Leblond <eric@regit.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Development of this code partly funded by OISF
9 * (http://www.openinfosecfoundation.org/)
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/netlink.h>
16#include <linux/jhash.h>
17#include <linux/netfilter.h>
18#include <linux/netfilter/nf_tables.h>
19#include <net/netfilter/nf_tables.h>
20#include <net/netfilter/nf_queue.h>
21
22static u32 jhash_initval __read_mostly;
23
24struct nft_queue {
25 u16 queuenum;
26 u16 queues_total;
27 u16 flags;
28 u8 family;
29};
30
31static void nft_queue_eval(const struct nft_expr *expr,
32 struct nft_data data[NFT_REG_MAX + 1],
33 const struct nft_pktinfo *pkt)
34{
35 struct nft_queue *priv = nft_expr_priv(expr);
36 u32 queue = priv->queuenum;
37 u32 ret;
38
39 if (priv->queues_total > 1) {
40 if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
41 int cpu = smp_processor_id();
42
43 queue = priv->queuenum + cpu % priv->queues_total;
44 } else {
45 queue = nfqueue_hash(pkt->skb, queue,
46 priv->queues_total, priv->family,
47 jhash_initval);
48 }
49 }
50
51 ret = NF_QUEUE_NR(queue);
52 if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
53 ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
54
55 data[NFT_REG_VERDICT].verdict = ret;
56}
57
58static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
59 [NFTA_QUEUE_NUM] = { .type = NLA_U16 },
60 [NFTA_QUEUE_TOTAL] = { .type = NLA_U16 },
61 [NFTA_QUEUE_FLAGS] = { .type = NLA_U16 },
62};
63
64static int nft_queue_init(const struct nft_ctx *ctx,
65 const struct nft_expr *expr,
66 const struct nlattr * const tb[])
67{
68 struct nft_queue *priv = nft_expr_priv(expr);
69
70 if (tb[NFTA_QUEUE_NUM] == NULL)
71 return -EINVAL;
72
73 init_hashrandom(&jhash_initval);
74 priv->family = ctx->afi->family;
75 priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
76
77 if (tb[NFTA_QUEUE_TOTAL] != NULL)
78 priv->queues_total = ntohs(nla_get_be16(tb[NFTA_QUEUE_TOTAL]));
79 if (tb[NFTA_QUEUE_FLAGS] != NULL) {
80 priv->flags = ntohs(nla_get_be16(tb[NFTA_QUEUE_FLAGS]));
81 if (priv->flags & ~NFT_QUEUE_FLAG_MASK)
82 return -EINVAL;
83 }
84 return 0;
85}
86
87static int nft_queue_dump(struct sk_buff *skb, const struct nft_expr *expr)
88{
89 const struct nft_queue *priv = nft_expr_priv(expr);
90
91 if (nla_put_be16(skb, NFTA_QUEUE_NUM, htons(priv->queuenum)) ||
92 nla_put_be16(skb, NFTA_QUEUE_TOTAL, htons(priv->queues_total)) ||
93 nla_put_be16(skb, NFTA_QUEUE_FLAGS, htons(priv->flags)))
94 goto nla_put_failure;
95
96 return 0;
97
98nla_put_failure:
99 return -1;
100}
101
102static struct nft_expr_type nft_queue_type;
103static const struct nft_expr_ops nft_queue_ops = {
104 .type = &nft_queue_type,
105 .size = NFT_EXPR_SIZE(sizeof(struct nft_queue)),
106 .eval = nft_queue_eval,
107 .init = nft_queue_init,
108 .dump = nft_queue_dump,
109};
110
111static struct nft_expr_type nft_queue_type __read_mostly = {
112 .name = "queue",
113 .ops = &nft_queue_ops,
114 .policy = nft_queue_policy,
115 .maxattr = NFTA_QUEUE_MAX,
116 .owner = THIS_MODULE,
117};
118
119static int __init nft_queue_module_init(void)
120{
121 return nft_register_expr(&nft_queue_type);
122}
123
124static void __exit nft_queue_module_exit(void)
125{
126 nft_unregister_expr(&nft_queue_type);
127}
128
129module_init(nft_queue_module_init);
130module_exit(nft_queue_module_exit);
131
132MODULE_LICENSE("GPL");
133MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
134MODULE_ALIAS_NFT_EXPR("queue");
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/netfilter/nft_reject.c
index 4a5e94ac314a..0d690d4101d2 100644
--- a/net/ipv4/netfilter/nft_reject_ipv4.c
+++ b/net/netfilter/nft_reject.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2013 Eric Leblond <eric@regit.org>
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
@@ -16,10 +17,16 @@
16#include <linux/netfilter/nf_tables.h> 17#include <linux/netfilter/nf_tables.h>
17#include <net/netfilter/nf_tables.h> 18#include <net/netfilter/nf_tables.h>
18#include <net/icmp.h> 19#include <net/icmp.h>
20#include <net/netfilter/ipv4/nf_reject.h>
21
22#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
23#include <net/netfilter/ipv6/nf_reject.h>
24#endif
19 25
20struct nft_reject { 26struct nft_reject {
21 enum nft_reject_types type:8; 27 enum nft_reject_types type:8;
22 u8 icmp_code; 28 u8 icmp_code;
29 u8 family;
23}; 30};
24 31
25static void nft_reject_eval(const struct nft_expr *expr, 32static void nft_reject_eval(const struct nft_expr *expr,
@@ -27,12 +34,25 @@ static void nft_reject_eval(const struct nft_expr *expr,
27 const struct nft_pktinfo *pkt) 34 const struct nft_pktinfo *pkt)
28{ 35{
29 struct nft_reject *priv = nft_expr_priv(expr); 36 struct nft_reject *priv = nft_expr_priv(expr);
37 struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
30 38
31 switch (priv->type) { 39 switch (priv->type) {
32 case NFT_REJECT_ICMP_UNREACH: 40 case NFT_REJECT_ICMP_UNREACH:
33 icmp_send(pkt->skb, ICMP_DEST_UNREACH, priv->icmp_code, 0); 41 if (priv->family == NFPROTO_IPV4)
42 nf_send_unreach(pkt->skb, priv->icmp_code);
43#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
44 else if (priv->family == NFPROTO_IPV6)
45 nf_send_unreach6(net, pkt->skb, priv->icmp_code,
46 pkt->hooknum);
47#endif
34 break; 48 break;
35 case NFT_REJECT_TCP_RST: 49 case NFT_REJECT_TCP_RST:
50 if (priv->family == NFPROTO_IPV4)
51 nf_send_reset(pkt->skb, pkt->hooknum);
52#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
53 else if (priv->family == NFPROTO_IPV6)
54 nf_send_reset6(net, pkt->skb, pkt->hooknum);
55#endif
36 break; 56 break;
37 } 57 }
38 58
@@ -53,6 +73,7 @@ static int nft_reject_init(const struct nft_ctx *ctx,
53 if (tb[NFTA_REJECT_TYPE] == NULL) 73 if (tb[NFTA_REJECT_TYPE] == NULL)
54 return -EINVAL; 74 return -EINVAL;
55 75
76 priv->family = ctx->afi->family;
56 priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); 77 priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
57 switch (priv->type) { 78 switch (priv->type) {
58 case NFT_REJECT_ICMP_UNREACH: 79 case NFT_REJECT_ICMP_UNREACH:
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index ed00fef58996..8f1779ff7e30 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -11,15 +11,13 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13 13
14#include <linux/ip.h>
15#include <linux/ipv6.h>
16#include <linux/jhash.h>
17
18#include <linux/netfilter.h> 14#include <linux/netfilter.h>
19#include <linux/netfilter_arp.h> 15#include <linux/netfilter_arp.h>
20#include <linux/netfilter/x_tables.h> 16#include <linux/netfilter/x_tables.h>
21#include <linux/netfilter/xt_NFQUEUE.h> 17#include <linux/netfilter/xt_NFQUEUE.h>
22 18
19#include <net/netfilter/nf_queue.h>
20
23MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 21MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
24MODULE_DESCRIPTION("Xtables: packet forwarding to netlink"); 22MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
25MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
@@ -28,7 +26,6 @@ MODULE_ALIAS("ip6t_NFQUEUE");
28MODULE_ALIAS("arpt_NFQUEUE"); 26MODULE_ALIAS("arpt_NFQUEUE");
29 27
30static u32 jhash_initval __read_mostly; 28static u32 jhash_initval __read_mostly;
31static bool rnd_inited __read_mostly;
32 29
33static unsigned int 30static unsigned int
34nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par) 31nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
@@ -38,69 +35,16 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
38 return NF_QUEUE_NR(tinfo->queuenum); 35 return NF_QUEUE_NR(tinfo->queuenum);
39} 36}
40 37
41static u32 hash_v4(const struct sk_buff *skb)
42{
43 const struct iphdr *iph = ip_hdr(skb);
44
45 /* packets in either direction go into same queue */
46 if ((__force u32)iph->saddr < (__force u32)iph->daddr)
47 return jhash_3words((__force u32)iph->saddr,
48 (__force u32)iph->daddr, iph->protocol, jhash_initval);
49
50 return jhash_3words((__force u32)iph->daddr,
51 (__force u32)iph->saddr, iph->protocol, jhash_initval);
52}
53
54#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
55static u32 hash_v6(const struct sk_buff *skb)
56{
57 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
58 u32 a, b, c;
59
60 if ((__force u32)ip6h->saddr.s6_addr32[3] <
61 (__force u32)ip6h->daddr.s6_addr32[3]) {
62 a = (__force u32) ip6h->saddr.s6_addr32[3];
63 b = (__force u32) ip6h->daddr.s6_addr32[3];
64 } else {
65 b = (__force u32) ip6h->saddr.s6_addr32[3];
66 a = (__force u32) ip6h->daddr.s6_addr32[3];
67 }
68
69 if ((__force u32)ip6h->saddr.s6_addr32[1] <
70 (__force u32)ip6h->daddr.s6_addr32[1])
71 c = (__force u32) ip6h->saddr.s6_addr32[1];
72 else
73 c = (__force u32) ip6h->daddr.s6_addr32[1];
74
75 return jhash_3words(a, b, c, jhash_initval);
76}
77#endif
78
79static u32
80nfqueue_hash(const struct sk_buff *skb, const struct xt_action_param *par)
81{
82 const struct xt_NFQ_info_v1 *info = par->targinfo;
83 u32 queue = info->queuenum;
84
85 if (par->family == NFPROTO_IPV4)
86 queue += ((u64) hash_v4(skb) * info->queues_total) >> 32;
87#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
88 else if (par->family == NFPROTO_IPV6)
89 queue += ((u64) hash_v6(skb) * info->queues_total) >> 32;
90#endif
91
92 return queue;
93}
94
95static unsigned int 38static unsigned int
96nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par) 39nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
97{ 40{
98 const struct xt_NFQ_info_v1 *info = par->targinfo; 41 const struct xt_NFQ_info_v1 *info = par->targinfo;
99 u32 queue = info->queuenum; 42 u32 queue = info->queuenum;
100 43
101 if (info->queues_total > 1) 44 if (info->queues_total > 1) {
102 queue = nfqueue_hash(skb, par); 45 queue = nfqueue_hash(skb, queue, info->queues_total,
103 46 par->family, jhash_initval);
47 }
104 return NF_QUEUE_NR(queue); 48 return NF_QUEUE_NR(queue);
105} 49}
106 50
@@ -120,10 +64,8 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par)
120 const struct xt_NFQ_info_v3 *info = par->targinfo; 64 const struct xt_NFQ_info_v3 *info = par->targinfo;
121 u32 maxid; 65 u32 maxid;
122 66
123 if (unlikely(!rnd_inited)) { 67 init_hashrandom(&jhash_initval);
124 get_random_bytes(&jhash_initval, sizeof(jhash_initval)); 68
125 rnd_inited = true;
126 }
127 if (info->queues_total == 0) { 69 if (info->queues_total == 0) {
128 pr_err("NFQUEUE: number of total queues is 0\n"); 70 pr_err("NFQUEUE: number of total queues is 0\n");
129 return -EINVAL; 71 return -EINVAL;
@@ -154,8 +96,10 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
154 int cpu = smp_processor_id(); 96 int cpu = smp_processor_id();
155 97
156 queue = info->queuenum + cpu % info->queues_total; 98 queue = info->queuenum + cpu % info->queues_total;
157 } else 99 } else {
158 queue = nfqueue_hash(skb, par); 100 queue = nfqueue_hash(skb, queue, info->queues_total,
101 par->family, jhash_initval);
102 }
159 } 103 }
160 104
161 ret = NF_QUEUE_NR(queue); 105 ret = NF_QUEUE_NR(queue);