ソースを参照

netfilter: nft_reject: support for IPv6 and TCP reset

This patch moves nft_reject_ipv4 to nft_reject and adds support
for IPv6 protocol. This patch uses functions included in nf_reject.h
to implement reject by TCP reset.

The code has to be build as a module if NF_TABLES_IPV6 is also a
module to avoid compilation error due to usage of IPv6 functions.
This has been done in Kconfig by using the construct:

 depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6

This seems a bit weird in terms of syntax but works perfectly.

Signed-off-by: Eric Leblond <eric@regit.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Eric Leblond 12 年 前
コミット
bee11dc78f

+ 0 - 4
net/ipv4/netfilter/Kconfig

@@ -40,10 +40,6 @@ config NF_TABLES_IPV4
 	depends on NF_TABLES
 	depends on NF_TABLES
 	tristate "IPv4 nf_tables support"
 	tristate "IPv4 nf_tables support"
 
 
-config NFT_REJECT_IPV4
-	depends on NF_TABLES_IPV4
-	tristate "nf_tables IPv4 reject support"
-
 config NFT_CHAIN_ROUTE_IPV4
 config NFT_CHAIN_ROUTE_IPV4
 	depends on NF_TABLES_IPV4
 	depends on NF_TABLES_IPV4
 	tristate "IPv4 nf_tables route chain support"
 	tristate "IPv4 nf_tables route chain support"

+ 0 - 1
net/ipv4/netfilter/Makefile

@@ -28,7 +28,6 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
 obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
 obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
 
 
 obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
 obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
-obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
 obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
 obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o

+ 6 - 0
net/netfilter/Kconfig

@@ -465,6 +465,12 @@ config NFT_QUEUE
 	  This is required if you intend to use the userspace queueing
 	  This is required if you intend to use the userspace queueing
 	  infrastructure (also known as NFQUEUE) from nftables.
 	  infrastructure (also known as NFQUEUE) from nftables.
 
 
+config NFT_REJECT
+	depends on NF_TABLES
+	depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6
+	default m if NETFILTER_ADVANCED=n
+	tristate "Netfilter nf_tables reject support"
+
 config NFT_COMPAT
 config NFT_COMPAT
 	depends on NF_TABLES
 	depends on NF_TABLES
 	depends on NETFILTER_XTABLES
 	depends on NETFILTER_XTABLES

+ 1 - 0
net/netfilter/Makefile

@@ -77,6 +77,7 @@ obj-$(CONFIG_NFT_CT)		+= nft_ct.o
 obj-$(CONFIG_NFT_LIMIT)		+= nft_limit.o
 obj-$(CONFIG_NFT_LIMIT)		+= nft_limit.o
 obj-$(CONFIG_NFT_NAT)		+= nft_nat.o
 obj-$(CONFIG_NFT_NAT)		+= nft_nat.o
 obj-$(CONFIG_NFT_QUEUE)		+= nft_queue.o
 obj-$(CONFIG_NFT_QUEUE)		+= nft_queue.o
+obj-$(CONFIG_NFT_REJECT) 	+= nft_reject.o
 obj-$(CONFIG_NFT_RBTREE)	+= nft_rbtree.o
 obj-$(CONFIG_NFT_RBTREE)	+= nft_rbtree.o
 obj-$(CONFIG_NFT_HASH)		+= nft_hash.o
 obj-$(CONFIG_NFT_HASH)		+= nft_hash.o
 obj-$(CONFIG_NFT_COUNTER)	+= nft_counter.o
 obj-$(CONFIG_NFT_COUNTER)	+= nft_counter.o

+ 23 - 2
net/ipv4/netfilter/nft_reject_ipv4.c → net/netfilter/nft_reject.c

@@ -1,5 +1,6 @@
 /*
 /*
  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * it under the terms of the GNU General Public License version 2 as
@@ -16,10 +17,16 @@
 #include <linux/netfilter/nf_tables.h>
 #include <linux/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables.h>
 #include <net/icmp.h>
 #include <net/icmp.h>
+#include <net/netfilter/ipv4/nf_reject.h>
+
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+#include <net/netfilter/ipv6/nf_reject.h>
+#endif
 
 
 struct nft_reject {
 struct nft_reject {
 	enum nft_reject_types	type:8;
 	enum nft_reject_types	type:8;
 	u8			icmp_code;
 	u8			icmp_code;
+	u8			family;
 };
 };
 
 
 static void nft_reject_eval(const struct nft_expr *expr,
 static void nft_reject_eval(const struct nft_expr *expr,
@@ -27,12 +34,25 @@ static void nft_reject_eval(const struct nft_expr *expr,
 			      const struct nft_pktinfo *pkt)
 			      const struct nft_pktinfo *pkt)
 {
 {
 	struct nft_reject *priv = nft_expr_priv(expr);
 	struct nft_reject *priv = nft_expr_priv(expr);
+	struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
 
 
 	switch (priv->type) {
 	switch (priv->type) {
 	case NFT_REJECT_ICMP_UNREACH:
 	case NFT_REJECT_ICMP_UNREACH:
-		icmp_send(pkt->skb, ICMP_DEST_UNREACH, priv->icmp_code, 0);
+		if (priv->family == NFPROTO_IPV4)
+			nf_send_unreach(pkt->skb, priv->icmp_code);
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+		else if (priv->family == NFPROTO_IPV6)
+			nf_send_unreach6(net, pkt->skb, priv->icmp_code,
+				      pkt->hooknum);
+#endif
 		break;
 		break;
 	case NFT_REJECT_TCP_RST:
 	case NFT_REJECT_TCP_RST:
+		if (priv->family == NFPROTO_IPV4)
+			nf_send_reset(pkt->skb, pkt->hooknum);
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+		else if (priv->family == NFPROTO_IPV6)
+			nf_send_reset6(net, pkt->skb, pkt->hooknum);
+#endif
 		break;
 		break;
 	}
 	}
 
 
@@ -53,6 +73,7 @@ static int nft_reject_init(const struct nft_ctx *ctx,
 	if (tb[NFTA_REJECT_TYPE] == NULL)
 	if (tb[NFTA_REJECT_TYPE] == NULL)
 		return -EINVAL;
 		return -EINVAL;
 
 
+	priv->family = ctx->afi->family;
 	priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
 	priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
 	switch (priv->type) {
 	switch (priv->type) {
 	case NFT_REJECT_ICMP_UNREACH:
 	case NFT_REJECT_ICMP_UNREACH:
@@ -72,7 +93,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
 {
 	const struct nft_reject *priv = nft_expr_priv(expr);
 	const struct nft_reject *priv = nft_expr_priv(expr);
 
 
-	if (nla_put_be32(skb, NFTA_REJECT_TYPE, priv->type))
+	if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
 		goto nla_put_failure;
 		goto nla_put_failure;
 
 
 	switch (priv->type) {
 	switch (priv->type) {