History

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. ====================

David S. Miller committed 12 years ago

Commit 9aa28f22 parents 6a8c479 c9c8e4818 files · +872 −534Browse files

Unified · Split

18 files
  1. include/net/netfilter/ipv4/nf_reject.h +128 −0
  2. include/net/netfilter/ipv6/nf_reject.h +171 −0
  3. include/net/netfilter/nf_queue.h +62 −0
  4. include/uapi/linux/netfilter/nf_tables.h +24 −0
  5. net/ipv4/netfilter/Kconfig +14 −4
  6. net/ipv4/netfilter/Makefile +0 −1
  7. net/ipv4/netfilter/ipt_REJECT.c +10 −130
  8. net/ipv6/netfilter/Kconfig +12 −0
  9. net/ipv6/netfilter/ip6t_REJECT.c +8 −171
  10. net/netfilter/Kconfig +58 −1
  11. net/netfilter/Makefile +2 −1
  12. net/netfilter/nf_tables_api.c +88 −16
  13. net/netfilter/nf_tables_core.c +4 −1
  14. net/netfilter/nft_meta.c +123 −23
  15. net/netfilter/nft_meta_target.c +0 −117
  16. net/netfilter/nft_queue.c +134 −0
  17. net/netfilter/nft_reject.c +22 −1
  18. net/netfilter/xt_NFQUEUE.c +12 −68
include/net/netfilter/ipv4/nf_reject.h+128−0
@@ -0,0 +1,128 @@
1+#ifndef _IPV4_NF_REJECT_H
2+#define _IPV4_NF_REJECT_H
3+
4+#include <net/ip.h>
5+#include <net/tcp.h>
6+#include <net/route.h>
7+#include <net/dst.h>
8+
9+static inline void nf_send_unreach(struct sk_buff *skb_in, int code)
10+{
11+ icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
12+}
13+
14+/* Send RST reply */
15+static void nf_send_reset(struct sk_buff *oldskb, int hook)
16+{
17+ struct sk_buff *nskb;
18+ const struct iphdr *oiph;
19+ struct iphdr *niph;
20+ const struct tcphdr *oth;
21+ struct tcphdr _otcph, *tcph;
22+
23+ /* IP header checks: fragment. */
24+ if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
25+ return;
26+
27+ oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
28+ sizeof(_otcph), &_otcph);
29+ if (oth == NULL)
30+ return;
31+
32+ /* No RST for RST. */
33+ if (oth->rst)
34+ return;
35+
36+ if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
37+ return;
38+
39+ /* Check checksum */
40+ if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
41+ return;
42+ oiph = ip_hdr(oldskb);
43+
44+ nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
45+ LL_MAX_HEADER, GFP_ATOMIC);
46+ if (!nskb)
47+ return;
48+
49+ skb_reserve(nskb, LL_MAX_HEADER);
50+
51+ skb_reset_network_header(nskb);
52+ niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
53+ niph->version = 4;
54+ niph->ihl = sizeof(struct iphdr) / 4;
55+ niph->tos = 0;
56+ niph->id = 0;
57+ niph->frag_off = htons(IP_DF);
58+ niph->protocol = IPPROTO_TCP;
59+ niph->check = 0;
60+ niph->saddr = oiph->daddr;
61+ niph->daddr = oiph->saddr;
62+
63+ skb_reset_transport_header(nskb);
64+ tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
65+ memset(tcph, 0, sizeof(*tcph));
66+ tcph->source = oth->dest;
67+ tcph->dest = oth->source;
68+ tcph->doff = sizeof(struct tcphdr) / 4;
69+
70+ if (oth->ack)
71+ tcph->seq = oth->ack_seq;
72+ else {
73+ tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
74+ oldskb->len - ip_hdrlen(oldskb) -
75+ (oth->doff << 2));
76+ tcph->ack = 1;
77+ }
78+
79+ tcph->rst = 1;
80+ tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
81+ niph->daddr, 0);
82+ nskb->ip_summed = CHECKSUM_PARTIAL;
83+ nskb->csum_start = (unsigned char *)tcph - nskb->head;
84+ nskb->csum_offset = offsetof(struct tcphdr, check);
85+
86+ /* ip_route_me_harder expects skb->dst to be set */
87+ skb_dst_set_noref(nskb, skb_dst(oldskb));
88+
89+ nskb->protocol = htons(ETH_P_IP);
90+ if (ip_route_me_harder(nskb, RTN_UNSPEC))
91+ goto free_nskb;
92+
93+ niph->ttl = ip4_dst_hoplimit(skb_dst(nskb));
94+
95+ /* "Never happens" */
96+ if (nskb->len > dst_mtu(skb_dst(nskb)))
97+ goto free_nskb;
98+
99+ nf_ct_attach(nskb, oldskb);
100+
101+#ifdef CONFIG_BRIDGE_NETFILTER
102+ /* If we use ip_local_out for bridged traffic, the MAC source on
103+ * the RST will be ours, instead of the destination's. This confuses
104+ * some routers/firewalls, and they drop the packet. So we need to
105+ * build the eth header using the original destination's MAC as the
106+ * source, and send the RST packet directly.
107+ */
108+ if (oldskb->nf_bridge) {
109+ struct ethhdr *oeth = eth_hdr(oldskb);
110+ nskb->dev = oldskb->nf_bridge->physindev;
111+ niph->tot_len = htons(nskb->len);
112+ ip_send_check(niph);
113+ if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
114+ oeth->h_source, oeth->h_dest, nskb->len) < 0)
115+ goto free_nskb;
116+ dev_queue_xmit(nskb);
117+ } else
118+#endif
119+ ip_local_out(nskb);
120+
121+ return;
122+
123+ free_nskb:
124+ kfree_skb(nskb);
125+}
126+
127+
128+#endif /* _IPV4_NF_REJECT_H */
include/net/netfilter/ipv6/nf_reject.h+171−0
@@ -0,0 +1,171 @@
1+#ifndef _IPV6_NF_REJECT_H
2+#define _IPV6_NF_REJECT_H
3+
4+#include <net/ipv6.h>
5+#include <net/ip6_route.h>
6+#include <net/ip6_fib.h>
7+#include <net/ip6_checksum.h>
8+#include <linux/netfilter_ipv6.h>
9+
10+static inline void
11+nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code,
12+ unsigned int hooknum)
13+{
14+ if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
15+ skb_in->dev = net->loopback_dev;
16+
17+ icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
18+}
19+
20+/* Send RST reply */
21+static void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
22+{
23+ struct sk_buff *nskb;
24+ struct tcphdr otcph, *tcph;
25+ unsigned int otcplen, hh_len;
26+ int tcphoff, needs_ack;
27+ const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
28+ struct ipv6hdr *ip6h;
29+#define DEFAULT_TOS_VALUE 0x0U
30+ const __u8 tclass = DEFAULT_TOS_VALUE;
31+ struct dst_entry *dst = NULL;
32+ u8 proto;
33+ __be16 frag_off;
34+ struct flowi6 fl6;
35+
36+ if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
37+ (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
38+ pr_debug("addr is not unicast.\n");
39+ return;
40+ }
41+
42+ proto = oip6h->nexthdr;
43+ tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
44+
45+ if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
46+ pr_debug("Cannot get TCP header.\n");
47+ return;
48+ }
49+
50+ otcplen = oldskb->len - tcphoff;
51+
52+ /* IP header checks: fragment, too short. */
53+ if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
54+ pr_debug("proto(%d) != IPPROTO_TCP, "
55+ "or too short. otcplen = %d\n",
56+ proto, otcplen);
57+ return;
58+ }
59+
60+ if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr)))
61+ BUG();
62+
63+ /* No RST for RST. */
64+ if (otcph.rst) {
65+ pr_debug("RST is set\n");
66+ return;
67+ }
68+
69+ /* Check checksum. */
70+ if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) {
71+ pr_debug("TCP checksum is invalid\n");
72+ return;
73+ }
74+
75+ memset(&fl6, 0, sizeof(fl6));
76+ fl6.flowi6_proto = IPPROTO_TCP;
77+ fl6.saddr = oip6h->daddr;
78+ fl6.daddr = oip6h->saddr;
79+ fl6.fl6_sport = otcph.dest;
80+ fl6.fl6_dport = otcph.source;
81+ security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
82+ dst = ip6_route_output(net, NULL, &fl6);
83+ if (dst == NULL || dst->error) {
84+ dst_release(dst);
85+ return;
86+ }
87+ dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
88+ if (IS_ERR(dst))
89+ return;
90+
91+ hh_len = (dst->dev->hard_header_len + 15)&~15;
92+ nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
93+ + sizeof(struct tcphdr) + dst->trailer_len,
94+ GFP_ATOMIC);
95+
96+ if (!nskb) {
97+ net_dbg_ratelimited("cannot alloc skb\n");
98+ dst_release(dst);
99+ return;
100+ }
101+
102+ skb_dst_set(nskb, dst);
103+
104+ skb_reserve(nskb, hh_len + dst->header_len);
105+
106+ skb_put(nskb, sizeof(struct ipv6hdr));
107+ skb_reset_network_header(nskb);
108+ ip6h = ipv6_hdr(nskb);
109+ ip6_flow_hdr(ip6h, tclass, 0);
110+ ip6h->hop_limit = ip6_dst_hoplimit(dst);
111+ ip6h->nexthdr = IPPROTO_TCP;
112+ ip6h->saddr = oip6h->daddr;
113+ ip6h->daddr = oip6h->saddr;
114+
115+ skb_reset_transport_header(nskb);
116+ tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
117+ /* Truncate to length (no data) */
118+ tcph->doff = sizeof(struct tcphdr)/4;
119+ tcph->source = otcph.dest;
120+ tcph->dest = otcph.source;
121+
122+ if (otcph.ack) {
123+ needs_ack = 0;
124+ tcph->seq = otcph.ack_seq;
125+ tcph->ack_seq = 0;
126+ } else {
127+ needs_ack = 1;
128+ tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
129+ + otcplen - (otcph.doff<<2));
130+ tcph->seq = 0;
131+ }
132+
133+ /* Reset flags */
134+ ((u_int8_t *)tcph)[13] = 0;
135+ tcph->rst = 1;
136+ tcph->ack = needs_ack;
137+ tcph->window = 0;
138+ tcph->urg_ptr = 0;
139+ tcph->check = 0;
140+
141+ /* Adjust TCP checksum */
142+ tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
143+ &ipv6_hdr(nskb)->daddr,
144+ sizeof(struct tcphdr), IPPROTO_TCP,
145+ csum_partial(tcph,
146+ sizeof(struct tcphdr), 0));
147+
148+ nf_ct_attach(nskb, oldskb);
149+
150+#ifdef CONFIG_BRIDGE_NETFILTER
151+ /* If we use ip6_local_out for bridged traffic, the MAC source on
152+ * the RST will be ours, instead of the destination's. This confuses
153+ * some routers/firewalls, and they drop the packet. So we need to
154+ * build the eth header using the original destination's MAC as the
155+ * source, and send the RST packet directly.
156+ */
157+ if (oldskb->nf_bridge) {
158+ struct ethhdr *oeth = eth_hdr(oldskb);
159+ nskb->dev = oldskb->nf_bridge->physindev;
160+ nskb->protocol = htons(ETH_P_IPV6);
161+ ip6h->payload_len = htons(sizeof(struct tcphdr));
162+ if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
163+ oeth->h_source, oeth->h_dest, nskb->len) < 0)
164+ return;
165+ dev_queue_xmit(nskb);
166+ } else
167+#endif
168+ ip6_local_out(nskb);
169+}
170+
171+#endif /* _IPV6_NF_REJECT_H */
include/net/netfilter/nf_queue.h+62−0
@@ -1,6 +1,10 @@
11 #ifndef _NF_QUEUE_H
22 #define _NF_QUEUE_H
33
4+#include <linux/ip.h>
5+#include <linux/ipv6.h>
6+#include <linux/jhash.h>
7+
48 /* Each queued (to userspace) skbuff has one of these. */
59 struct nf_queue_entry {
610 struct list_head list;
@@ -33,4 +37,62 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); · 26 unmodified lines
3337 bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
3438 void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
3539
40+static inline void init_hashrandom(u32 *jhash_initval)
41+{
42+ while (*jhash_initval == 0)
43+ *jhash_initval = prandom_u32();
44+}
45+
46+static inline u32 hash_v4(const struct sk_buff *skb, u32 jhash_initval)
47+{
48+ const struct iphdr *iph = ip_hdr(skb);
49+
50+ /* packets in either direction go into same queue */
51+ if ((__force u32)iph->saddr < (__force u32)iph->daddr)
52+ return jhash_3words((__force u32)iph->saddr,
53+ (__force u32)iph->daddr, iph->protocol, jhash_initval);
54+
55+ return jhash_3words((__force u32)iph->daddr,
56+ (__force u32)iph->saddr, iph->protocol, jhash_initval);
57+}
58+
59+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
60+static inline u32 hash_v6(const struct sk_buff *skb, u32 jhash_initval)
61+{
62+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
63+ u32 a, b, c;
64+
65+ if ((__force u32)ip6h->saddr.s6_addr32[3] <
66+ (__force u32)ip6h->daddr.s6_addr32[3]) {
67+ a = (__force u32) ip6h->saddr.s6_addr32[3];
68+ b = (__force u32) ip6h->daddr.s6_addr32[3];
69+ } else {
70+ b = (__force u32) ip6h->saddr.s6_addr32[3];
71+ a = (__force u32) ip6h->daddr.s6_addr32[3];
72+ }
73+
74+ if ((__force u32)ip6h->saddr.s6_addr32[1] <
75+ (__force u32)ip6h->daddr.s6_addr32[1])
76+ c = (__force u32) ip6h->saddr.s6_addr32[1];
77+ else
78+ c = (__force u32) ip6h->daddr.s6_addr32[1];
79+
80+ return jhash_3words(a, b, c, jhash_initval);
81+}
82+#endif
83+
84+static inline u32
85+nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family,
86+ u32 jhash_initval)
87+{
88+ if (family == NFPROTO_IPV4)
89+ queue += ((u64) hash_v4(skb, jhash_initval) * queues_total) >> 32;
90+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
91+ else if (family == NFPROTO_IPV6)
92+ queue += ((u64) hash_v6(skb, jhash_initval) * queues_total) >> 32;
93+#endif
94+
95+ return queue;
96+}
97+
3698 #endif /* _NF_QUEUE_H */
include/uapi/linux/netfilter/nf_tables.h+24−0
@@ -110,11 +110,13 @@ enum nft_table_flags { · 109 unmodified lines
110110 *
111111 * @NFTA_TABLE_NAME: name of the table (NLA_STRING)
112112 * @NFTA_TABLE_FLAGS: bitmask of enum nft_table_flags (NLA_U32)
113+ * @NFTA_TABLE_USE: number of chains in this table (NLA_U32)
113114 */
114115 enum nft_table_attributes {
115116 NFTA_TABLE_UNSPEC,
116117 NFTA_TABLE_NAME,
117118 NFTA_TABLE_FLAGS,
119+ NFTA_TABLE_USE,
118120 __NFTA_TABLE_MAX
119121 };
120122 #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
@@ -553,11 +555,13 @@ enum nft_meta_keys { · 432 unmodified lines
553555 *
554556 * @NFTA_META_DREG: destination register (NLA_U32)
555557 * @NFTA_META_KEY: meta data item to load (NLA_U32: nft_meta_keys)
558+ * @NFTA_META_SREG: source register (NLA_U32)
556559 */
557560 enum nft_meta_attributes {
558561 NFTA_META_UNSPEC,
559562 NFTA_META_DREG,
560563 NFTA_META_KEY,
564+ NFTA_META_SREG,
561565 __NFTA_META_MAX
562566 };
563567 #define NFTA_META_MAX (__NFTA_META_MAX - 1)
@@ -657,6 +661,26 @@ enum nft_log_attributes { · 93 unmodified lines
657661 };
658662 #define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
659663
664+/**
665+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
666+ *
667+ * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
668+ * @NFTA_QUEUE_TOTAL: number of queues to load balance packets on (NLA_U16)
669+ * @NFTA_QUEUE_FLAGS: various flags (NLA_U16)
670+ */
671+enum nft_queue_attributes {
672+ NFTA_QUEUE_UNSPEC,
673+ NFTA_QUEUE_NUM,
674+ NFTA_QUEUE_TOTAL,
675+ NFTA_QUEUE_FLAGS,
676+ __NFTA_QUEUE_MAX
677+};
678+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
679+
680+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
681+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
682+#define NFT_QUEUE_FLAG_MASK 0x03
683+
660684 /**
661685 * enum nft_reject_types - nf_tables reject expression reject types
662686 *
net/ipv4/netfilter/Kconfig+14−4
@@ -39,23 +39,33 @@ config NF_CONNTRACK_PROC_COMPAT · 38 unmodified lines
3939 config NF_TABLES_IPV4
4040 depends on NF_TABLES
4141 tristate "IPv4 nf_tables support"
42−
43−config NFT_REJECT_IPV4
44− depends on NF_TABLES_IPV4
45− tristate "nf_tables IPv4 reject support"
42+ help
43+ This option enables the IPv4 support for nf_tables.
4644
4745 config NFT_CHAIN_ROUTE_IPV4
4846 depends on NF_TABLES_IPV4
4947 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.
5053
5154 config NFT_CHAIN_NAT_IPV4
5255 depends on NF_TABLES_IPV4
5356 depends on NF_NAT_IPV4 && NFT_NAT
5457 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.
5563
5664 config NF_TABLES_ARP
5765 depends on NF_TABLES
5866 tristate "ARP nf_tables support"
67+ help
68+ This option enables the ARP support for nf_tables.
5969
6070 config IP_NF_IPTABLES
6171 tristate "IP tables support (required for filtering/masq/NAT)"
net/ipv4/netfilter/Makefile+0−1
@@ -28,7 +28,6 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o · 27 unmodified lines
2828 obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
2929
3030 obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
31−obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
3231 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
3332 obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
3433 obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
net/ipv4/netfilter/ipt_REJECT.c+10−130
@@ -17,10 +17,6 @@ · 16 unmodified lines
1717 #include <linux/udp.h>
1818 #include <linux/icmp.h>
1919 #include <net/icmp.h>
20−#include <net/ip.h>
21−#include <net/tcp.h>
22−#include <net/route.h>
23−#include <net/dst.h>
2420 #include <linux/netfilter/x_tables.h>
2521 #include <linux/netfilter_ipv4/ip_tables.h>
2622 #include <linux/netfilter_ipv4/ipt_REJECT.h>
@@ -28,128 +24,12 @@ · 1 unmodified line
2824 #include <linux/netfilter_bridge.h>
2925 #endif
3026
27+#include <net/netfilter/ipv4/nf_reject.h>
28+
3129 MODULE_LICENSE("GPL");
3230 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
3331 MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4");
3432
35−/* Send RST reply */
36−static 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−
148−static inline void send_unreach(struct sk_buff *skb_in, int code)
149−{
150− icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
151−}
152−
15333 static unsigned int
15434 reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
15535 {
@@ -157,28 +37,28 @@ reject_tg(struct sk_buff *skb, const struct xt_action_param *par) · 1 unmodified line
15737
15838 switch (reject->with) {
15939 case IPT_ICMP_NET_UNREACHABLE:
160− send_unreach(skb, ICMP_NET_UNREACH);
40+ nf_send_unreach(skb, ICMP_NET_UNREACH);
16141 break;
16242 case IPT_ICMP_HOST_UNREACHABLE:
163− send_unreach(skb, ICMP_HOST_UNREACH);
43+ nf_send_unreach(skb, ICMP_HOST_UNREACH);
16444 break;
16545 case IPT_ICMP_PROT_UNREACHABLE:
166− send_unreach(skb, ICMP_PROT_UNREACH);
46+ nf_send_unreach(skb, ICMP_PROT_UNREACH);
16747 break;
16848 case IPT_ICMP_PORT_UNREACHABLE:
169− send_unreach(skb, ICMP_PORT_UNREACH);
49+ nf_send_unreach(skb, ICMP_PORT_UNREACH);
17050 break;
17151 case IPT_ICMP_NET_PROHIBITED:
172− send_unreach(skb, ICMP_NET_ANO);
52+ nf_send_unreach(skb, ICMP_NET_ANO);
17353 break;
17454 case IPT_ICMP_HOST_PROHIBITED:
175− send_unreach(skb, ICMP_HOST_ANO);
55+ nf_send_unreach(skb, ICMP_HOST_ANO);
17656 break;
17757 case IPT_ICMP_ADMIN_PROHIBITED:
178− send_unreach(skb, ICMP_PKT_FILTERED);
58+ nf_send_unreach(skb, ICMP_PKT_FILTERED);
17959 break;
18060 case IPT_TCP_RESET:
181− send_reset(skb, par->hooknum);
61+ nf_send_reset(skb, par->hooknum);
18262 case IPT_ICMP_ECHOREPLY:
18363 /* Doesn't happen. */
18464 break;
net/ipv6/netfilter/Kconfig+12−0
@@ -28,15 +28,27 @@ config NF_CONNTRACK_IPV6 · 27 unmodified lines
2828 config NF_TABLES_IPV6
2929 depends on NF_TABLES
3030 tristate "IPv6 nf_tables support"
31+ help
32+ This option enables the IPv6 support for nf_tables.
3133
3234 config NFT_CHAIN_ROUTE_IPV6
3335 depends on NF_TABLES_IPV6
3436 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.
3542
3643 config NFT_CHAIN_NAT_IPV6
3744 depends on NF_TABLES_IPV6
3845 depends on NF_NAT_IPV6 && NFT_NAT
3946 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.
4052
4153 config IP6_NF_IPTABLES
4254 tristate "IP6 tables support (required for filtering)"
net/ipv6/netfilter/ip6t_REJECT.c+8−171
@@ -23,181 +23,18 @@ · 22 unmodified lines
2323 #include <linux/skbuff.h>
2424 #include <linux/icmpv6.h>
2525 #include <linux/netdevice.h>
26−#include <net/ipv6.h>
27−#include <net/tcp.h>
2826 #include <net/icmp.h>
29−#include <net/ip6_checksum.h>
30−#include <net/ip6_fib.h>
31−#include <net/ip6_route.h>
3227 #include <net/flow.h>
3328 #include <linux/netfilter/x_tables.h>
3429 #include <linux/netfilter_ipv6/ip6_tables.h>
3530 #include <linux/netfilter_ipv6/ip6t_REJECT.h>
3631
32+#include <net/netfilter/ipv6/nf_reject.h>
33+
3734 MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
3835 MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv6");
3936 MODULE_LICENSE("GPL");
4037
41−/* Send RST reply */
42−static 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−
192−static inline void
193−send_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−}
20138
20239 static unsigned int
20340 reject_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) · 4 unmodified lines
20845 pr_debug("%s: medium point\n", __func__);
20946 switch (reject->with) {
21047 case IP6T_ICMP6_NO_ROUTE:
211− send_unreach(net, skb, ICMPV6_NOROUTE, par->hooknum);
48+ nf_send_unreach6(net, skb, ICMPV6_NOROUTE, par->hooknum);
21249 break;
21350 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);
21552 break;
21653 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);
21855 break;
21956 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);
22158 break;
22259 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);
22461 break;
22562 case IP6T_ICMP6_ECHOREPLY:
22663 /* Do nothing */
22764 break;
22865 case IP6T_TCP_RESET:
229− send_reset(net, skb, par->hooknum);
66+ nf_send_reset6(net, skb, par->hooknum);
23067 break;
23168 default:
23269 net_info_ratelimited("case %u not handled yet\n", reject->with);
net/netfilter/Kconfig+58−1
@@ -414,47 +414,104 @@ config NETFILTER_SYNPROXY · 413 unmodified lines
414414 endif # NF_CONNTRACK
415415
416416 config NF_TABLES
417− depends on NETFILTER_NETLINK
417+ select NETFILTER_NETLINK
418418 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.
419430
420431 config NFT_EXTHDR
421432 depends on NF_TABLES
422433 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.
423437
424438 config NFT_META
425439 depends on NF_TABLES
426440 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.
427444
428445 config NFT_CT
429446 depends on NF_TABLES
430447 depends on NF_CONNTRACK
431448 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.
432452
433453 config NFT_RBTREE
434454 depends on NF_TABLES
435455 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.
436459
437460 config NFT_HASH
438461 depends on NF_TABLES
439462 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.
440466
441467 config NFT_COUNTER
442468 depends on NF_TABLES
443469 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.
444473
445474 config NFT_LOG
446475 depends on NF_TABLES
447476 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.
448480
449481 config NFT_LIMIT
450482 depends on NF_TABLES
451483 tristate "Netfilter nf_tables limit module"
484+ help
485+ This option adds the "limit" expression that you can use to
486+ ratelimit rule matchings.
452487
453488 config NFT_NAT
454489 depends on NF_TABLES
455490 depends on NF_CONNTRACK
456491 depends on NF_NAT
457492 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+
497+config 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+
506+config 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.
458515
459516 config NFT_COMPAT
460517 depends on NF_TABLES
net/netfilter/Makefile+2−1
@@ -76,7 +76,8 @@ obj-$(CONFIG_NFT_META) += nft_meta.o · 75 unmodified lines
7676 obj-$(CONFIG_NFT_CT) += nft_ct.o
7777 obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
7878 obj-$(CONFIG_NFT_NAT) += nft_nat.o
79−#nf_tables-objs += nft_meta_target.o
79+obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
80+obj-$(CONFIG_NFT_REJECT) += nft_reject.o
8081 obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
8182 obj-$(CONFIG_NFT_HASH) += nft_hash.o
8283 obj-$(CONFIG_NFT_COUNTER) += nft_counter.o
net/netfilter/nf_tables_api.c+88−16
@@ -180,7 +180,8 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, u32 portid, u32 seq, · 179 unmodified lines
180180 nfmsg->res_id = 0;
181181
182182 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)))
184185 goto nla_put_failure;
185186
186187 return nlmsg_end(skb, nlh);
@@ -1923,12 +1924,14 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, · 1736 unmodified lines
19231924 {
19241925 struct net *net = sock_net(skb->sk);
19251926 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1926− const struct nft_af_info *afi;
1927+ const struct nft_af_info *afi = NULL;
19271928 const struct nft_table *table = NULL;
19281929
1929− afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
1930− if (IS_ERR(afi))
1931− return PTR_ERR(afi);
1930+ if (nfmsg->nfgen_family != NFPROTO_UNSPEC) {
1931+ afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
1932+ if (IS_ERR(afi))
1933+ return PTR_ERR(afi);
1934+ }
19321935
19331936 if (nla[NFTA_SET_TABLE] != NULL) {
19341937 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, · 38 unmodified lines
19731976 return -ENOMEM;
19741977
19751978 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))
19771982 continue;
1978− if (n < 0 || n > BITS_PER_LONG * PAGE_SIZE)
1983+ if (tmp < 0 || tmp > BITS_PER_LONG * PAGE_SIZE)
19791984 continue;
1980− set_bit(n, inuse);
1985+
1986+ set_bit(tmp, inuse);
19811987 }
19821988
19831989 n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE);
@@ -2094,8 +2100,8 @@ done: · 110 unmodified lines
20942100 return skb->len;
20952101 }
20962102
2097−static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2098− struct netlink_callback *cb)
2103+static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2104+ struct netlink_callback *cb)
20992105 {
21002106 const struct nft_set *set;
21012107 unsigned int idx = 0, s_idx = cb->args[0];
@@ -2127,6 +2133,61 @@ done: · 25 unmodified lines
21272133 return skb->len;
21282134 }
21292135
2136+static 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+ }
2179+cont:
2180+ idx++;
2181+ }
2182+ if (s_idx)
2183+ s_idx = 0;
2184+ }
2185+ }
2186+ cb->args[1] = 1;
2187+done:
2188+ return skb->len;
2189+}
2190+
21302191 static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
21312192 {
21322193 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) · 10 unmodified lines
21432204 if (err < 0)
21442205 return err;
21452206
2146− if (ctx.table == NULL)
2147− ret = nf_tables_dump_sets_all(&ctx, skb, cb);
2148− else
2207+ if (ctx.table == NULL) {
2208+ if (ctx.afi == NULL)
2209+ ret = nf_tables_dump_sets_all(&ctx, skb, cb);
2210+ else
2211+ ret = nf_tables_dump_sets_family(&ctx, skb, cb);
2212+ } else
21492213 ret = nf_tables_dump_sets_table(&ctx, skb, cb);
21502214
21512215 return ret;
@@ -2158,6 +2222,7 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, · 6 unmodified lines
21582222 const struct nft_set *set;
21592223 struct nft_ctx ctx;
21602224 struct sk_buff *skb2;
2225+ const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
21612226 int err;
21622227
21632228 /* Verify existance before starting dump */
@@ -2172,6 +2237,10 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, · 8 unmodified lines
21722237 return netlink_dump_start(nlsk, skb, nlh, &c);
21732238 }
21742239
2240+ /* Only accept unspec with dump */
2241+ if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
2242+ return -EAFNOSUPPORT;
2243+
21752244 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
21762245 if (IS_ERR(set))
21772246 return PTR_ERR(set);
@@ -2341,6 +2410,7 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, · 163 unmodified lines
23412410 const struct nlmsghdr *nlh,
23422411 const struct nlattr * const nla[])
23432412 {
2413+ const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
23442414 struct nft_set *set;
23452415 struct nft_ctx ctx;
23462416 int err;
@@ -2352,6 +2422,9 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, · 5 unmodified lines
23522422 if (err < 0)
23532423 return err;
23542424
2425+ if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
2426+ return -EAFNOSUPPORT;
2427+
23552428 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
23562429 if (IS_ERR(set))
23572430 return PTR_ERR(set);
@@ -2521,9 +2594,8 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) · 163 unmodified lines
25212594 u32 portid, seq;
25222595 int event, err;
25232596
2524− nfmsg = nlmsg_data(cb->nlh);
2525− err = nlmsg_parse(cb->nlh, sizeof(*nfmsg), nla, NFTA_SET_ELEM_LIST_MAX,
2526− nft_set_elem_list_policy);
2597+ err = nlmsg_parse(cb->nlh, sizeof(struct nfgenmsg), nla,
2598+ NFTA_SET_ELEM_LIST_MAX, nft_set_elem_list_policy);
25272599 if (err < 0)
25282600 return err;
25292601
net/netfilter/nf_tables_core.c+4−1
@@ -164,7 +164,7 @@ next_rule: · 163 unmodified lines
164164 break;
165165 }
166166
167− switch (data[NFT_REG_VERDICT].verdict) {
167+ switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) {
168168 case NF_ACCEPT:
169169 case NF_DROP:
170170 case NF_QUEUE:
@@ -172,6 +172,9 @@ next_rule: · 1 unmodified line
172172 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
173173
174174 return data[NFT_REG_VERDICT].verdict;
175+ }
176+
177+ switch (data[NFT_REG_VERDICT].verdict) {
175178 case NFT_JUMP:
176179 if (unlikely(pkt->skb->nf_trace))
177180 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
net/netfilter/nft_meta.c+123−23
@@ -21,12 +21,15 @@ · 20 unmodified lines
2121
2222 struct nft_meta {
2323 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+ };
2528 };
2629
27−static void nft_meta_eval(const struct nft_expr *expr,
28− struct nft_data data[NFT_REG_MAX + 1],
29− const struct nft_pktinfo *pkt)
30+static void nft_meta_get_eval(const struct nft_expr *expr,
31+ struct nft_data data[NFT_REG_MAX + 1],
32+ const struct nft_pktinfo *pkt)
3033 {
3134 const struct nft_meta *priv = nft_expr_priv(expr);
3235 const struct sk_buff *skb = pkt->skb;
@@ -132,23 +135,50 @@ err: · 99 unmodified lines
132135 data[NFT_REG_VERDICT].verdict = NFT_BREAK;
133136 }
134137
138+static 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+
135161 static const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
136162 [NFTA_META_DREG] = { .type = NLA_U32 },
137163 [NFTA_META_KEY] = { .type = NLA_U32 },
164+ [NFTA_META_SREG] = { .type = NLA_U32 },
138165 };
139166
140−static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
141− const struct nlattr * const tb[])
167+static int nft_meta_init_validate_set(uint32_t key)
142168 {
143− struct nft_meta *priv = nft_expr_priv(expr);
144− int err;
145−
146− if (tb[NFTA_META_DREG] == NULL ||
147− tb[NFTA_META_KEY] == NULL)
148− return -EINVAL;
169+ switch (key) {
170+ case NFT_META_MARK:
171+ case NFT_META_PRIORITY:
172+ case NFT_META_NFTRACE:
173+ return 0;
174+ default:
175+ return -EOPNOTSUPP;
176+ }
177+}
149178
150− priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
151− switch (priv->key) {
179+static int nft_meta_init_validate_get(uint32_t key)
180+{
181+ switch (key) {
152182 case NFT_META_LEN:
153183 case NFT_META_PROTOCOL:
154184 case NFT_META_PRIORITY:
@@ -167,26 +197,69 @@ static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr, · 12 unmodified lines
167197 #ifdef CONFIG_NETWORK_SECMARK
168198 case NFT_META_SECMARK:
169199 #endif
170− break;
200+ return 0;
171201 default:
172202 return -EOPNOTSUPP;
173203 }
174204
175− priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG]));
176− err = nft_validate_output_register(priv->dreg);
205+}
206+
207+static 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);
177230 if (err < 0)
178231 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;
180236 }
181237
182−static int nft_meta_dump(struct sk_buff *skb, const struct nft_expr *expr)
238+static int nft_meta_get_dump(struct sk_buff *skb,
239+ const struct nft_expr *expr)
183240 {
184241 const struct nft_meta *priv = nft_expr_priv(expr);
185242
243+ if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
244+ goto nla_put_failure;
186245 if (nla_put_be32(skb, NFTA_META_DREG, htonl(priv->dreg)))
187246 goto nla_put_failure;
247+ return 0;
248+
249+nla_put_failure:
250+ return -1;
251+}
252+
253+static 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+
188258 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
189259 goto nla_put_failure;
260+ if (nla_put_be32(skb, NFTA_META_SREG, htonl(priv->sreg)))
261+ goto nla_put_failure;
262+
190263 return 0;
191264
192265 nla_put_failure:
@@ -194,17 +267,44 @@ nla_put_failure: · 1 unmodified line
194267 }
195268
196269 static struct nft_expr_type nft_meta_type;
197−static const struct nft_expr_ops nft_meta_ops = {
270+static const struct nft_expr_ops nft_meta_get_ops = {
198271 .type = &nft_meta_type,
199272 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
200− .eval = nft_meta_eval,
273+ .eval = nft_meta_get_eval,
201274 .init = nft_meta_init,
202− .dump = nft_meta_dump,
275+ .dump = nft_meta_get_dump,
203276 };
204277
278+static 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+
286+static const struct nft_expr_ops *
287+nft_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+
205305 static struct nft_expr_type nft_meta_type __read_mostly = {
206306 .name = "meta",
207− .ops = &nft_meta_ops,
307+ .select_ops = &nft_meta_select_ops,
208308 .policy = nft_meta_policy,
209309 .maxattr = NFTA_META_MAX,
210310 .owner = THIS_MODULE,
net/netfilter/nft_meta_target.c+0−117
@@ -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−
20−struct nft_meta {
21− enum nft_meta_keys key;
22−};
23−
24−static 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−
53−static const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
54− [NFTA_META_KEY] = { .type = NLA_U32 },
55−};
56−
57−static 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−
80−static 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−
87−nla_put_failure:
88− return -1;
89−}
90−
91−static 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−
102−static int __init nft_meta_target_init(void)
103−{
104− return nft_register_expr(&meta_target);
105−}
106−
107−static void __exit nft_meta_target_exit(void)
108−{
109− nft_unregister_expr(&meta_target);
110−}
111−
112−module_init(nft_meta_target_init);
113−module_exit(nft_meta_target_exit);
114−
115−MODULE_LICENSE("GPL");
116−MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
117−MODULE_ALIAS_NFT_EXPR("meta");
net/netfilter/nft_queue.c+134−0
@@ -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+
22+static u32 jhash_initval __read_mostly;
23+
24+struct nft_queue {
25+ u16 queuenum;
26+ u16 queues_total;
27+ u16 flags;
28+ u8 family;
29+};
30+
31+static 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+
58+static 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+
64+static 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+
87+static 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+
98+nla_put_failure:
99+ return -1;
100+}
101+
102+static struct nft_expr_type nft_queue_type;
103+static 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+
111+static 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+
119+static int __init nft_queue_module_init(void)
120+{
121+ return nft_register_expr(&nft_queue_type);
122+}
123+
124+static void __exit nft_queue_module_exit(void)
125+{
126+ nft_unregister_expr(&nft_queue_type);
127+}
128+
129+module_init(nft_queue_module_init);
130+module_exit(nft_queue_module_exit);
131+
132+MODULE_LICENSE("GPL");
133+MODULE_AUTHOR("Eric Leblond <eric@regit.org>");
134+MODULE_ALIAS_NFT_EXPR("queue");
net/netfilter/nft_reject.crenamed from net/ipv4/netfilter/nft_reject_ipv4.c+22−1
@@ -1,5 +1,6 @@
11 /*
22 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
3+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
34 *
45 * This program is free software; you can redistribute it and/or modify
56 * it under the terms of the GNU General Public License version 2 as
@@ -16,10 +17,16 @@ · 10 unmodified lines
1617 #include <linux/netfilter/nf_tables.h>
1718 #include <net/netfilter/nf_tables.h>
1819 #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
1925
2026 struct nft_reject {
2127 enum nft_reject_types type:8;
2228 u8 icmp_code;
29+ u8 family;
2330 };
2431
2532 static void nft_reject_eval(const struct nft_expr *expr,
@@ -27,12 +34,25 @@ static void nft_reject_eval(const struct nft_expr *expr, · 1 unmodified line
2734 const struct nft_pktinfo *pkt)
2835 {
2936 struct nft_reject *priv = nft_expr_priv(expr);
37+ struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
3038
3139 switch (priv->type) {
3240 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
3448 break;
3549 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
3656 break;
3757 }
3858
@@ -53,6 +73,7 @@ static int nft_reject_init(const struct nft_ctx *ctx, · 14 unmodified lines
5373 if (tb[NFTA_REJECT_TYPE] == NULL)
5474 return -EINVAL;
5575
76+ priv->family = ctx->afi->family;
5677 priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
5778 switch (priv->type) {
5879 case NFT_REJECT_ICMP_UNREACH:
net/netfilter/xt_NFQUEUE.c+12−68
@@ -11,15 +11,13 @@ · 10 unmodified lines
1111 #include <linux/module.h>
1212 #include <linux/skbuff.h>
1313
14−#include <linux/ip.h>
15−#include <linux/ipv6.h>
16−#include <linux/jhash.h>
17−
1814 #include <linux/netfilter.h>
1915 #include <linux/netfilter_arp.h>
2016 #include <linux/netfilter/x_tables.h>
2117 #include <linux/netfilter/xt_NFQUEUE.h>
2218
19+#include <net/netfilter/nf_queue.h>
20+
2321 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2422 MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
2523 MODULE_LICENSE("GPL");
@@ -28,7 +26,6 @@ MODULE_ALIAS("ip6t_NFQUEUE"); · 2 unmodified lines
2826 MODULE_ALIAS("arpt_NFQUEUE");
2927
3028 static u32 jhash_initval __read_mostly;
31−static bool rnd_inited __read_mostly;
3229
3330 static unsigned int
3431 nfqueue_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) · 3 unmodified lines
3835 return NF_QUEUE_NR(tinfo->queuenum);
3936 }
4037
41−static 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)
55−static 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−
79−static u32
80−nfqueue_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−
9538 static unsigned int
9639 nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
9740 {
9841 const struct xt_NFQ_info_v1 *info = par->targinfo;
9942 u32 queue = info->queuenum;
10043
101− if (info->queues_total > 1)
102− queue = nfqueue_hash(skb, par);
103−
44+ if (info->queues_total > 1) {
45+ queue = nfqueue_hash(skb, queue, info->queues_total,
46+ par->family, jhash_initval);
47+ }
10448 return NF_QUEUE_NR(queue);
10549 }
10650
@@ -120,10 +64,8 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par) · 13 unmodified lines
12064 const struct xt_NFQ_info_v3 *info = par->targinfo;
12165 u32 maxid;
12266
123− if (unlikely(!rnd_inited)) {
124− get_random_bytes(&jhash_initval, sizeof(jhash_initval));
125− rnd_inited = true;
126− }
67+ init_hashrandom(&jhash_initval);
68+
12769 if (info->queues_total == 0) {
12870 pr_err("NFQUEUE: number of total queues is 0\n");
12971 return -EINVAL;
@@ -154,8 +96,10 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) · 24 unmodified lines
15496 int cpu = smp_processor_id();
15597
15698 queue = info->queuenum + cpu % info->queues_total;
157− } else
158− queue = nfqueue_hash(skb, par);
99+ } else {
100+ queue = nfqueue_hash(skb, queue, info->queues_total,
101+ par->family, jhash_initval);
102+ }
159103 }
160104
161105 ret = NF_QUEUE_NR(queue);