nikeee / wake-on-lan

Sending magic packets and performing IP address operations.
https://nikeee.github.io/wake-on-lan/README.html
GNU Lesser General Public License v3.0
58 stars 19 forks source link

ARP Requests are Windows-only #16

Open georg-jung opened 4 years ago

georg-jung commented 4 years ago

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.

nikeee commented 4 years ago

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.

georg-jung commented 4 years ago

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 commented 4 years ago

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...

nikeee commented 4 years ago

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

georg-jung commented 4 years ago

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

nikeee commented 4 years ago

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

However, it requires root as well.

georg-jung commented 4 years ago

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 commented 4 years ago

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.

nikeee commented 3 years ago

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

georg-jung commented 3 years ago

Sure!