Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix ping on OSX when running as root #35070

Merged
merged 4 commits into from
Apr 18, 2020
Merged

fix ping on OSX when running as root #35070

merged 4 commits into from
Apr 18, 2020

Conversation

wfurt
Copy link
Member

@wfurt wfurt commented Apr 16, 2020

This is fix for thee distance issues with current implementation.

first is regression on OSX caused by dotnet/corefx#34084
It seems like OSX does connect behind the scenes and Send() files System.Net.Sockets.SocketException (56): Socket is already connected even if we call Connect just once. So I limit that to Linux only.
fixes #33430

Second issues is when PingOptions is used. In that case we would always try to set socket.DontFragment = socketConfig.Options.DontFragment and that fails on OSX because that is not supported by OS. Since we use RAW socket we have option too include IP header and set DF bit directly. I used Wireshark to verify that DF is properly set based on PingOptions.
fixes #34879

Third problem is with IPv6: (currently not tracked by any issue)


          Child exception:
            System.Net.NetworkInformation.PingException: An exception occurred during a Ping request.
           ---> System.PlatformNotSupportedException: This platform does not support packet information for dual-mode sockets.  If packet information is not required, use Socket.Receive.  If packet information is required set Socket.DualMode to false.
          /Users/furt/github/wfurt-runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs(40,0): at System.Net.Sockets.SocketPal.CheckDualModeReceiveSupport(Socket socket)
          /Users/furt/github/wfurt-runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs(1744,0): at System.Net.Sockets.Socket.ReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint& remoteEP)
          /Users/furt/github/wfurt-runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs(1812,0): at System.Net.Sockets.Socket.ReceiveFrom(Byte[] buffer, SocketFlags socketFlags, EndPoint& remoteEP)
          /Users/furt/github/wfurt-runtime/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs(206,0): at System.Net.NetworkInformation.Ping.SendIcmpEchoRequestOverRawSocket(IPAddress address, Byte[] buffer, Int32 timeout, PingOptions options)

Since we know what AF we need, the fix was to turn off DualMode on RAW socket.
I don't think we really need "packet information" and that can be possibly future improvement.

All this happened because we do not have any test coverage for RAW sockets in practice since CI runs as ordinary user. However, some other assemblies use RemoteExcetopr with RunAsSudo to get privileged access. It seems like we should be able to detect in CI. My prototype runs shows exactly the reported issues so it may be worth of getting at least some basic coverage.
https://helix.dot.net/api/2019-06-17/jobs/353faf88-9320-4dfa-8215-534c515b3fa0/workitems/System.Net.Ping.Functional.Tests/console

Downside of this is that the test depends now on sudo for outer loop runs. It may asked for password if executed interactively or it may fail if given user is not in shudders group.
Given the history, it seems like this may be worth oof some hassle.

@wfurt wfurt added this to the 5.0 milestone Apr 16, 2020
@wfurt wfurt requested a review from a team April 16, 2020 20:35
@wfurt wfurt self-assigned this Apr 16, 2020
@ghost
Copy link

ghost commented Apr 16, 2020

Tagging subscribers to this area: @dotnet/ncl
Notify danmosemsft if you want to be subscribed.

@@ -19,6 +19,8 @@ public partial class Ping
private const int IcmpHeaderLengthInBytes = 8;
private const int MinIpHeaderLengthInBytes = 20;
private const int MaxIpHeaderLengthInBytes = 60;
private static bool _sendIpHeader = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
private static bool _needsConnect = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are very fast calls; I'm not sure they need to be cached like this. But if you think it's important, make 'em readonly as suggested.

@wfurt
Copy link
Member Author

wfurt commented Apr 17, 2020

/azp run runtime-libraries outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@wfurt
Copy link
Member Author

wfurt commented Apr 18, 2020

/azp run runtime-libraries outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@wfurt wfurt merged commit d4e601c into dotnet:master Apr 18, 2020
@wfurt wfurt deleted the rawPing branch April 18, 2020 19:43
@ghost ghost locked as resolved and limited conversation to collaborators Dec 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
3 participants