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)
committerArve Hjønnevåg <arve@android.com>
Mon, 1 Jul 2013 20:40:35 +0000 (13:40 -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 e7916c193932222b7538c104dc71eeb8b3f8b5f2..23dfd4a312cec502abb720a188479c94937ffdbc 100644 (file)
@@ -110,6 +110,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_ULOG
        tristate "ULOG target support"
        default m if NETFILTER_ADVANCED=n
index 04b18c1ac3458503a2b5d79bd7fd1547c13e76d7..452e8a587c346f5f3f8ecddc6780f92f8a7e78b6 100644 (file)
@@ -129,6 +129,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 4433ab40e7de05a2b518e20dacfa370d736bded3..7f45af3e812807d7b8bb2c77f82e47d579a65559 100644 (file)
@@ -153,6 +153,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 70f9abc0efe9a0ba0bc8fdbb6060f3bfe593291f..573c232239b0a21c8c636d289373d16c349eba5f 100644 (file)
@@ -180,6 +180,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