netfilter: have ip*t REJECT set the sock err when an icmp is to be sent
authorJP Abgrall <jpa@google.com>
Thu, 16 Jun 2011 21:37:03 +0000 (14:37 -0700)
committerJP Abgrall <jpa@google.com>
Mon, 20 Jun 2011 20:15:47 +0000 (13:15 -0700)
Allow the REJECT --reject-with icmp*blabla to also set the matching error
locally on the socket affected by the reject.
This allows the process to see an error almost as if it received it
via ICMP.
It avoids the local process who's ingress packet is rejected to have to
wait for a pseudo-eternity until some timeout kicks in.

Ideally, this should be enabled with a new iptables flag similar to
   --reject-with-sock-err
For now it is enabled with CONFIG_IP*_NF_TARGET_REJECT_SKERR option.

Change-Id: I649a4fd5940029ec0b3233e5abb205da6984891e
Signed-off-by: JP Abgrall <jpa@google.com>
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/ipt_REJECT.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/ip6t_REJECT.c

index 1dfc18a03fd4219fe9dd419011877d0a7ce3dfa7..73b4e91a87e763a20e9a38d69286b0b40d995ca1 100644 (file)
@@ -113,6 +113,18 @@ config IP_NF_TARGET_REJECT
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_TARGET_REJECT_SKERR
+       bool "Force socket error when rejecting with icmp*"
+       depends on IP_NF_TARGET_REJECT
+       default n
+       help
+          This option enables turning a "--reject-with icmp*" into a matching
+          socket error also.
+         The REJECT target normally allows sending an ICMP message. But it
+          leaves the local socket unaware of any ingress rejects.
+
+         If unsure, say N.
+
 config IP_NF_TARGET_LOG
        tristate "LOG target support"
        default m if NETFILTER_ADVANCED=n
index 1ff79e557f96306b428874462f491ffb54c5403e..0f7585e900ee8b3bcbefbcfc772596f76bdc8a94 100644 (file)
@@ -134,6 +134,14 @@ static void send_reset(struct sk_buff *oldskb, int hook)
 static inline void send_unreach(struct sk_buff *skb_in, int code)
 {
        icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
+#ifdef CONFIG_IP_NF_TARGET_REJECT_SKERR
+       if (skb_in->sk) {
+               skb_in->sk->sk_err = icmp_err_convert[code].errno;
+               skb_in->sk->sk_error_report(skb_in->sk);
+               pr_debug("ipt_REJECT: sk_err=%d for skb=%p sk=%p\n",
+                       skb_in->sk->sk_err, skb_in, skb_in->sk);
+       }
+#endif
 }
 
 static unsigned int
index 448464844a253474fed5624f75c68c9bb33cd98e..5bbf531692023738084f3c61aabc862584381149 100644 (file)
@@ -174,6 +174,18 @@ config IP6_NF_TARGET_REJECT
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_TARGET_REJECT_SKERR
+       bool "Force socket error when rejecting with icmp*"
+       depends on IP6_NF_TARGET_REJECT
+       default n
+       help
+          This option enables turning a "--reject-with icmp*" into a matching
+          socket error also.
+         The REJECT target normally allows sending an ICMP message. But it
+          leaves the local socket unaware of any ingress rejects.
+
+         If unsure, say N.
+
 config IP6_NF_MANGLE
        tristate "Packet mangling"
        default m if NETFILTER_ADVANCED=n
index a5a4c5dd53961cf1b2432c8317592d1099eafda2..09d30498c9272e7f0537ee77d4575c01ce906ee2 100644 (file)
@@ -177,6 +177,15 @@ send_unreach(struct net *net, struct sk_buff *skb_in, unsigned char code,
                skb_in->dev = net->loopback_dev;
 
        icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
+#ifdef CONFIG_IP6_NF_TARGET_REJECT_SKERR
+       if (skb_in->sk) {
+               icmpv6_err_convert(ICMPV6_DEST_UNREACH, code,
+                                  &skb_in->sk->sk_err);
+               skb_in->sk->sk_error_report(skb_in->sk);
+               pr_debug("ip6t_REJECT: sk_err=%d for skb=%p sk=%p\n",
+                       skb_in->sk->sk_err, skb_in, skb_in->sk);
+       }
+#endif
 }
 
 static unsigned int