wake-on-lan icon indicating copy to clipboard operation
wake-on-lan copied to clipboard

ARP Requests are Windows-only

Open georg-jung opened this issue 4 years ago • 10 comments

Trying to execute them on linux results in the following exception:

System.DllNotFoundException: Unable to load shared library 'iphlpapi.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libiphlpapi.dll: cannot open shared object file: No such file or directory
   at System.Net.NativeMethods.SendARP(Int32 destinationIp, Int32 sourceIp, Byte[] macAddress, Int32& physicalAddrLength)
   at System.Net.ArpRequest.Send(IPAddress destination)
   at System.Net.ArpRequest.<>c__DisplayClass1_0.<SendAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location where exception was thrown ---
   at WoL.Services.AddressLookupService.GetMac(IPAddress ip)
   at WoL.Pages.AddHost.GetHostByName()
   at WoL.Pages.AddHost.GetHost()
   at WoL.Pages.AddHost.HandleValidSubmit(EditContext context)

While I understand why this is the case it might be nice to provide a different solution for non-windows platforms or at least throwing a platform not supported exception.

georg-jung avatar Dec 13 '19 13:12 georg-jung

This is correct, as stated in the readme.

I did not find a good way of reliably sending ARP requests on Linux/BSD systems. If you know how to do it properly, I'd be happy to know! :)

You are right, a PlatformNotSupportedException would be much better.

nikeee avatar Dec 13 '19 14:12 nikeee

Seems like the easiest way involves parsing commandline outputs from arp or arping, which aren't available everywhere (i.e. in my default WSL installation without apt getting arping). A good starting point regarding this seems to be https://github.com/Kiphaz/PureActive/blob/master/src/PureActive.Network.Services.ArpService/ArpService.cs. Either way this doesn't feel like a good solution.

georg-jung avatar Dec 13 '19 14:12 georg-jung

It's doable using https://github.com/chmorgan/sharppcap/blob/master/SharpPcap/ARP.cs too but this requires a dependency to non-managed code. While it's possibly better then parsing stdout it doesn't seem optimal either...

georg-jung avatar Dec 13 '19 15:12 georg-jung

If I'm not mistaking, it also requires the OS to have PCAP installed.

nikeee avatar Dec 13 '19 15:12 nikeee

See https://github.com/georg-jung/LinuxArpLookupDemo This is workaround-ish too but possibly the best option if one wants to get arp working on linux. Doesn't have prerequisits or dependencies.

Note that this doesn't work on WSL (1, seems like it will on 2), but thats a thing of WSL.

Possible that this requires root though - the machine I tested with just has a root user.

Edit: Reading does work as a non-root user on a debian I just tried and it seems to work on android too

georg-jung avatar Dec 13 '19 17:12 georg-jung

One could use Linux' raw socket to send the ARP packet directly: https://gist.github.com/austinmarton/1922600

However, it requires root as well.

nikeee avatar Dec 13 '19 17:12 nikeee

Yeah I've seen this. Raw sockets on linux require root, on windows they are completely unsupported. One way around is pcap. But the solution I linked works without root and without calling external processes. It is even kind of truly async.

georg-jung avatar Dec 13 '19 17:12 georg-jung

Actually I think this method works quite well and has reasonable drawbacks - the unnecessary ping. If one wanted to not use a ping one could obviously try to connect to some port via TCP or send a UDP packet too. I liked the ping option most.

On the plus side we get linux + android support, a real async method and don't take dependencies. I created https://github.com/georg-jung/ArpLookup to support the arp-only use case. Feel free to integrate my code if you like to.

georg-jung avatar Dec 13 '19 21:12 georg-jung

The linux lookup looks promising. If it's still ok for you, I'd integrate the linux lookup into the library.

nikeee avatar Sep 17 '20 08:09 nikeee

Sure!

georg-jung avatar Sep 17 '20 13:09 georg-jung