Bug 36941 - setting MulticastTimeToLive on Socket throws exception
Summary: setting MulticastTimeToLive on Socket throws exception
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: io-layer ()
Version: 4.2.0 (C6)
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Ludovic Henry
URL:
Depends on:
Blocks:
 
Reported: 2015-12-12 21:36 UTC by Karsten Gebbert
Modified: 2017-06-21 13:48 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
code example (637 bytes, text/plain)
2015-12-12 21:36 UTC, Karsten Gebbert
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Karsten Gebbert 2015-12-12 21:36:13 UTC
Created attachment 14261 [details]
code example

Setting SocketOptionLevel.IP SocketOptionName.MulticastTimeToLive on a newly created UDP socket results in a SocketException being thrown.

Output of `mono -V`:

> Mono JIT compiler version 4.2.1 (Stable 4.2.1.124/39edf24 Fri Dec 11 08:42:32 UTC 2015)
> Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
> 	TLS:           __thread
>	SIGSEGV:       altstack
>	Notifications: epoll
>	Architecture:  amd64
>	Disabled:      none
>	Misc:          softdebug 
>	LLVM:          supported, not enabled.
>	GC:            sgen

The test program:

> using System;
> using System.Net;
> using System.Net.Sockets;
> 
> namespace Tests {
>     class Test {
> 
>         static void Main(string [] args)
>         {
>             var theSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
>             IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 11000);
>             theSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
> 
>             theSocket.Bind(localEndPoint);
>             theSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 19);
>             
>             Console.ReadLine();
>         }
> 
>     }
> }

The exception thrown:

> Unhandled Exception:
> System.Net.Sockets.SocketException: Protocol option not supported
>   at System.Net.Sockets.Socket.SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, Int32 optionValue) <0x415
> 67d80 + 0x000a3> in <filename unknown>:0                                                                                            
>   at Tests.Test.Main (System.String[] args) <0x41567050 + 0x000e3> in <filename unknown>:0 
> [ERROR] FATAL UNHANDLED EXCEPTION: System.Net.Sockets.SocketException: Protocol option not supported
>   at System.Net.Sockets.Socket.SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, Int32 optionValue) <0x415
> 67d80 + 0x000a3> in <filename unknown>:0                                                                                            
>   at Tests.Test.Main (System.String[] args) <0x41567050 + 0x000e3> in <filename unknown>:0
Comment 1 Karsten Gebbert 2015-12-13 11:57:37 UTC
After some digging in the sources I found that this multicast related flag is indeed implemented, so I had some doubts as to whether this was happening due to `mono` or my system configuration. 

I found some test C code that roughly emulates the same socket setup:

https://gist.github.com/krgn/ff864f18b3a0fdec3dc4

and

https://gist.github.com/krgn/7068b54b0f9cae8f7582

Setting the IP_MULTICAST_TTL does not crash in those programs, and multicast works as expected.
Comment 2 Ludovic Henry 2015-12-15 21:40:08 UTC
I cannot reproduce with the test case you provided on ubuntu 64bits 14.04.3. Which OS are you using?
Comment 3 Karsten Gebbert 2015-12-15 21:49:02 UTC
I'm running NixOS 64bits. My kernel is GNU/Linux 4.1.13
Comment 4 Karsten Gebbert 2015-12-15 22:21:12 UTC
Ok, I am digging into this a bit. 

If I look at the relevant part in socket-io.c around line 2178, I see that for the call to setsockopt int_val is cast to "char *" and th
Comment 5 Karsten Gebbert 2015-12-15 22:55:51 UTC
Sorry, this bug tracker is a bit finicky :)

If I look at the relevant part in socket-io.c around line 2178, I see that for the call to setsockopt int_val is cast to "char *" and the optlen is the sizeof int_val (4 bytes for "gint32"?). This causes that call setsockopt in my C-only examples to fail, as it expects this to be the sizeof u_char (1 byte).

Changing this does however not completely fix the problem and I suspect that I'm overlooking something (multiple internal threads here?).
Comment 6 Aleksey Kliger 2015-12-22 16:42:18 UTC
Karsten,

I assume the test program works if you change the line to

> byte[] b = { 19 };
> theSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive,  b);
Comment 7 Ludovic Henry 2017-02-08 20:07:20 UTC
Karsten, did Aleksey's workaround work? Thank you
Comment 8 Will Dietz 2017-03-21 17:22:21 UTC
Hi, I'm running into the same problem, and using the provided test case am observing the same exception.

The provided C examples seem to work without problem.

Trying the suggested workaround (byte[] b ..) does not fix the issue for me unfortunately.

Running 'strace -tfo trace.log mono ./test.exe' produces the following:

> socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
> setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> setsockopt(3, 0x4 /* SOL_?? */, 10, [0], 4) = -1 ENOPROTOOPT (Protocol not available)
> shutdown(3, SHUT_RD)                    = -1 ENOTCONN (Transport endpoint is not connected)
> socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) = 4
> setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> setsockopt(4, 0x4 /* SOL_?? */, 10, [0], 4) = -1 ENOPROTOOPT (Protocol not available)
> setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> getsockopt(4, SOL_SOCKET, SO_TYPE, [2], [4]) = 0
> setsockopt(4, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
> bind(4, {sa_family=AF_INET, sin_port=htons(11000), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
> setsockopt(4, 0x4 /* SOL_?? */, 33, [19], 4) = -1 ENOPROTOOPT (Protocol not available)

The call to setsockopt(4, 0x4, ...) seems questionable, not sure where that's coming from.

This is with mono --version:
> Mono JIT compiler version 4.6.0 (Stable 4.6.0.182/3ed2bba Sat Mar 18 16:23:51 UTC 2017)
> Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
>       TLS:           __thread
>       SIGSEGV:       altstack
>       Notifications: epoll
>       Architecture:  amd64
>       Disabled:      none
>       Misc:          softdebug 
>       LLVM:          supported, not enabled.
>       GC:            sgen

LMK if you need more information or if I should file a separate bug for this.
Comment 9 Will Dietz 2017-03-21 17:55:42 UTC
Same occurs with a copy of 4.8 I built a few days ago:

> Mono JIT compiler version 4.8.0 (Stable 4.8.0.495/e4a3cf3 Sun Mar 19 04:03:22 UTC 2017)
> Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
>       TLS:           __thread
>       SIGSEGV:       altstack
>       Notifications: epoll
>       Architecture:  amd64
>       Disabled:      none
>       Misc:          softdebug 
>       LLVM:          supported, not enabled.
>       GC:            sgen
Comment 10 Will Dietz 2017-03-24 12:55:00 UTC
I can't reproduce this using the Docker mono images (tried a few versions), so it appears this is a bug in how mono is built?  Sorry for the bug hijack if this is unrelated to your issue O:).
Comment 11 Will Dietz 2017-03-24 16:37:23 UTC
Looks like the culprit here was an outdated /etc/protocols. It caused "ip" to map to '4' (ipip/ipencaps) which explains the value in strace and the resulting problems.

Hope this helps!
Comment 12 Karsten Gebbert 2017-06-21 13:48:21 UTC
You are my hero.

This is so obscure, I'm not sure I would have ever figured this one out. First of all, I had never heard of that file, and in NixOS, the only two packages I have install that depend on this, are syncthing and keybase. Even in the newest version of NixOS the file appears to be ancient, mapping ip to 4 (as so you also discovered). But its easy enough to fix, and now I have working multicast transport on NixOS. Thank you *so much*.

Best, 

Karsten