So it was clear we need to do something about it. One can switch off a PC using Remote Desktop very easily (you can do it directly from Start menu), but having ability to switch off a computer remotely is useless unless you can then remotely switch on the computer again. And that is where Wake on LAN finds its place.
Magic Packet
Wake On LAN (sometimes referred as WOL or WoL) is a marketing term used for ability to bring computer out of Stand-By mode by sending it a special packet, called "Magic Packet".
When you shutdown Windows, all modern ATX-power based PCs do not switch off completely. Instead they enter a Stand-By mode, which means RAM, CPU and hard drives are switched off, but motherboard itself and a network card are still powered. To determine if your network card supports WOL, shut down your PC and check the Link LED on the network card - if it is still active, your network card is still powered and should support Wake on LAN.
Even though a PC is shut down, the network card is listening on the data layer (usually Ethernet) level and scans incoming packets for special character sequence. If it detects the sequence, it will turn on the PC. This sequence, called Magic Packet, has following structure:
Follow up:
The packet begins with 6 bytes trailer of FF bytes which is followed by 16 times repeated MAC address of the target device (i.e. the device that should be switched on). MAC Address is used as an identifier in the packet, because that is the only valuable identification that is available when the PC is not running. MAC Address is assigned by the manufacturer (it is a layer 2 identifier) and it stored in the flash memory of the network card itself, so the network card can perform the comparison very easily. It cannot use an IP address, because network card simply does not have one when PC is not running - IP address is a layer 3 identifier, which means it is assigned by the OS.
You may also ask why the MAC address is repeated 16 times - it looks like unnecessary data duplication. Well it is not. As mentioned above the network card scans all packets that are coming in and it does not support any protocols of higher levels (TCP, HTTP, etc.) - it will literally go through all bytes in the packet and if it finds the "magic packet" sequence anywhere in the data or even a packet header, it will turn on the PC. Imagine that the packet did not repeat the MAC Address, so it would only utilise 6 bytes of FF and then 6 bytes of the MAC address. I can guarantee you that this 12 bytes combination will sooner or later appear in your network communication (in a file transfer, incoming email, a picture, etc.). 12 bytes is just not enough, which is why the MAC address is repeated 16 times giving the packet solid 102 bytes. The probability that those 102 bytes will unintentionally appear in transferred data is exponentially lower (there are 256^102 different packets which should be safe enough).
Broadcasting Magic Packet
So to switch on a PC through Wake on LAN it should be enough to somehow get a packet including the "magic packet" sequence to the device that I want to switch on. Since we know that the network card is scanning all incoming packets, it is not really important which type of packet I will send as long as it reaches the device.
Since I want to be able to switch on any device in my LAN, the best "container" for the magic packet sequence is an UDP broadcast packet. UDP is a TCP/IP service without any guarantee for delivery, however it does require any handshake like TCP, so a packet can be sent without "opening a connection". UDP broadcast packet is a special type of UDP packet sent to IP address 255.255.255.255 which tells every switch in the way to send this packet to every port so effectively this packet should reach each device in local network, which is exactly what we need from our Magic Packet.
The source device will broadcast the magic packet to IP 255.255.255.255 and this packet will be spread in local network. Routers are set not to transfer broadcast messages, so the target device must be placed before any router. The broadcast packet will eventually reach the target device, which will detect its MAC address in the packet and will turn on itself.
C# Implementation
Now we now how everything works so putting everything together in the form of C# code should be just a piece of cake. At first, we need to create the magic packet:
Code: Select all
byte[] macAddress = new byte[] {0x00, 0xe1, 0xff, 0x65, 0x23, 0x10};
//Construct the packet
List<byte> packet = new List<byte>();
//Trailer of 6 FF packets
for (int i = 0; i < 6; i++)
packet.Add(0xFF);
//Repeat 16 time the MAC address (which is 6 bytes)
for (int i = 0; i < 16; i++)
packet.AddRange(macAddress);
Now we have the packet data, so we just need to send it inside UDP packet. For this purpose the UdpClient class from System.Net.Sockets will come handy:
Code: Select all
//Send the packet to broadcast address
UdpClient client = new UdpClient();
client.Connect(IPAddress.Broadcast, 7); //Any UDP port will work, but 7 is my lucky number ...
client.Send(packet.ToArray(), packet.Count);
The code above assumes that you already know MAC address of the device that you want to turn on. There are several ways how you can obtain the MAC address of target device. You can obviously run the command ipconfig /all on directly on the PC and look for the Physical Address entry of your network adapter.
But since we are talking about doing stuff remotely, I will show you how you can get a MAC address remotely. We will use ARP protocol to obtain MAC address by given IP address or hostname. The main purpose of ARP protocol is to translate an IP address into MAC address which is exactly what we need. We will use Windows API function called SendARP for this purpose:
Code: Select all
DWORD SendARP(
__in IPAddr DestIP,
__in IPAddr SrcIP,
__out PULONG pMacAddr,
__inout PULONG PhyAddrLen
);
Code: Select all
[DllImport("iphlpapi.dll", ExactSpelling = true)]
static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);
static byte[] GetMACAddress(string hostNameOrAddress)
{
IPHostEntry hostEntry = Dns.GetHostEntry(hostNameOrAddress);
if (hostEntry.AddressList.Length == 0)
return null; // We were not able to resolve given hostname / address
byte[] macAddr = new byte[6];
uint macAddrLen = (uint)macAddr.Length;
if (SendARP((int)hostEntry.AddressList[0].Address, 0, macAddr, ref macAddrLen) != 0)
return null; // The SendARP call failed
return macAddr;
}
Putting it all together
Now we have everything ready to switch on a PC remotely, except for the target PC itself. On most systems, the Wake On LAN is disabled by default, so you need to enable it. First and foremost, you need to check your BIOS to make sure that Wake On LAN is enabled. Name of this entry will be different depending on your motherboard manufacturer, but it will be most likely located in Power Management of your BIOS.
As a next step, you need to enable the WOL for specified network card directly inside Windows. Open your Device Manager (go to Control Panel, select System, go to Hardware tab and click on Device Manager button) and select the network card which will receive the magic packet. In the Power Management tab, select "Allow this device to bring this computer out of standby", as shown on the following picture:
Click OK and you are ready your brand new Wake On LAN feature.
The end of the story
The reason why I underwent all this WOL pain was the ability to remotely turn on and off PCs in our office (and to protect the environment and our electricity bills) so you may wonder how I solved it. Basically I made a simple web site which lists our workstation computers in the office. This web site runs on our server in the office (which has to run 24/7) and if you want to turn on your PC you would just go to that site and click on "Wake Up" button which then sends a Magic Packet to the PC.
Full source code Database script