Thread (3 messages) 3 messages, 2 authors, 2016-12-05

Re: Trigger EHOSTUNREACH

From: Marco Zunino <hidden>
Date: 2016-12-05 19:07:16

Hi Neal, thank you!
I can succesfully repoduce the following socket error now after
setting the IP_RECVERR socket option:

    ICMP type=3, code=1 -> EHOSTUNREACH
    ICMP type=3, code=2 -> ENOPROTOOPT
    ICMP type=3, code=3 -> ECONNREFUSED
    ICMP type=3, code=4 -> No error
    ICMP type=3, code=5 -> ENOTSUP
    ICMP type=3, code=6 -> ENETUNREACH
    ICMP type=3, code=7 -> EHOSTDOWN
    ICMP type=3, code=8 -> ENONET

In my case, the errors are triggered while in recv(). I did not know
packetdrill, so I am triggering this error using our own tool.

I tried to send an ICMP type=3 code=1 on an ESTABLISHED TCP connection
opened by Chrome browser, and after about 20 minutes, I get
ERR_ADDRESS_UNREACHABLE error in the browser screen. It is curious how
it does not fail with a  CONNECTION_TIMEOUT, I think this reflect your
interpretation of RFC 1122 section 3.2.2.1.

If I try to run your packetdrill test case, I get an error: unknown
symbol: 'IP_RECVERR'.
In the testcase, I tried to replace IP_RECVERR with the corresponding
value '0x0b', but in this case the write() does not return any error.


On Sun, Dec 4, 2016 at 6:51 PM, Neal Cardwell [off-list ref] wrote:
On Sun, Dec 4, 2016 at 7:04 AM, Marco Zunino [off-list ref] wrote:
quoted
Hallo everyone, hope you are having a good day
we are building a networking testing tool to simulate network error
condition, and we are having difficulties triggering the EHOSTUNREACH
socket error.

We are trying to trigger this error by sending an ICMP packet type=3
code=3 on an open STREAM socket, but it has no effect.

Based on RFC1122 and the code here

https://github.com/torvalds/linux/blob/e76d21c40bd6c67fd4e2c1540d77e113df962b4d/net/ipv4/tcp_ipv4.c#L353

I would expect the this ICMP packet to abort the socket connection
with a EHOSTUNREACH error on the client side, but this does not
happen.
In my quick tests with packetdrill, it looks like Linux will not
immediately pass EHOSTUNREACH to the application unless the
application has requested this with setsockopt(SOL_IP, IP_RECVERR).

Specifically, the following packetdrill test passes for me:
---
0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
   +0 bind(3, ..., ...) = 0
   +0 listen(3, 1) = 0

   +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.020 < . 1:1(0) ack 1 win 257
   +0 accept(3, ..., ...) = 4
   +0 setsockopt(4, SOL_IP, IP_RECVERR, [1], 4) = 0
   +0 write(4, ..., 1000) = 1000
   +0 > P. 1:1001(1000) ack 1

+.010 < icmp unreachable host_unreachable [1:1461(1460)]

   +0 write(4, ..., 1) = -1 EHOSTUNREACH (No route to host)
---

But without the setsockopt(SOL_IP, IP_RECVERR) there is no error upon
the second write().

My reading of RFC 1122 is that this is consistent with the RFC.

RFC 1122 section 3.2.2.1 says:

            A Destination Unreachable message that is received with code
            0 (Net), 1 (Host), or 5 (Bad Source Route) may result from a
            routing transient and MUST therefore be interpreted as only
            a hint, not proof, that the specified destination is
            unreachable [IP:11].

So it seems that the RFC is suggesting that by default an ICMP host
unreachable should not cause an immediate error for the connection.
Instead, it should be used as a hint as to the cause of the problem if
TCP's normal reliable delivery mechanisms ultimately timeout and fail.

neal
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help