Repository navigation
socket raises exception (un)setting IPv6Only #180
Description
Activity
@kazu-yamamoto
Hibino-san suggested that I let you know that I created this issue. I am new to ICMPv6 programming, so please feel free to let me know if I am approaching it incorrectly.By the way, (the C equivalent of) the above example is in the iputils ping6 implementation:
icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);I don't think it is wise to ignore errors.
I think we should setIPv6Onlyonly when the second option isStreamandDatagram.I agree with Kazu. Unconditionally ignoring all errors is not a good idea.
I would like to change the code like this:
#if HAVE_DECL_IPV6_V6ONLY # if Unix or Windows Vista or later when (family == AF_INET6 && (stype == Stream || stype == Datagram)) $ setSocketOption sock IPv6Only 0 # endif #endifIs there any way to check Vista or later?
Why
HAVE_DECL_IPV6_V6ONLYis set for Windows prior to Vista?I also agree that ignoring errors is a bad idea. I have updated the pull request with code like Kazu's:
https://github.com/haskell/network/pull/181/files?diff=unifiedI guess that simply removing the
setSocketOptioncall is undesirable because of backwards compatibility with code that expects it? As long as it does not raise an exception, a program (using AF_INET6 with Stream or Datagram) can just reset the option (setSocketOption sock IPv6Only 1) after creating the socket. If an exception is raised, however, the program cannot acquire the socket at all. By the way, in that case, the lost socket is not closed; perhaps thesetSocketOptioncall could use some exception handling?In the current pull request, it seems to me that
IPv6Onlyis not set to0on Vista or laster. Is this intentional? If I remember correctly, default value of IPV6_V6ONLY is platform specific. That's why we explicitly set it to0here.I think that closing a socket on errors is a good idea.
onExceptionwould help.That is my mistake; thank you for catching it!
I now better understand the reasoning behind this code. The
IPV6_V6ONLYoption should be turned off by default according to RFC 3493 Section 5.3, but it seems that some people disagree with the decision and implement it differently. (relevant blog post) I have added a comment to my pull request to document this.It is indeed strange if
HAVE_DECL_IPV6_V6ONLYis set on platforms that do not support the option. Investigating, I see in configure.ac thatIPV6_V6ONLYis explicitly defined as a "fix for MingW not defining [it]."I am unable to find a flag that could be used to indicate the Windows version. (GHC documentation) In my pull request, I am reverting to error suppression for Windows, as I assume that it was there for a reason and am unable to test it myself.
I also added an
onExceptioncall to close the socket on error. Note that it is being imported fromGHC.IO.Exception, asControl.Exceptionis only imported for Windows.LGTM.
@tibbe Let's merge this.
Pinging @tibbe
In Network.Socket:socket, the
IPv6Onlysocket option is set to0so that both IPv4 and IPv6 can be handled with one socket, when the address family isAF_INET6. This is not always desired, and some parameters cause an exception to be raised.For example, ICMPv6 (protocol number 58) is a protocol that is specifically for IPv6. The issue can be reproduced in GHCi on Linux as follows:
The code already suppresses
setSocketOptionerrors on Windows platforms. A simple fix would be to do so on all platforms, and I am preparing a pull request for this. Personally, I feel that it would be preferable to not set the option insocket, especially since its appropriateness is application-specific and will likely change as IPv4 becomes less prominent.