luke
06/12/08

Wake On LAN in C#

Lately I came across a requirement for an ability to remotely turn on computers in our company. Couple of team members (including me...) tend to work from home sometimes so they leave their PCs running when they leave the office so the next day they could access it over Remote Desktop. Do you spot a problem already? To be honest I did not realise this was a problem either ... until an electricity bill came in. The workstation PCs are running nonstop (no one really bothers to switch them off, what if they did not go to the office tomorrow ...), which obviously has very negative impact on the electricity consumption in our office.

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:

MagicPacket

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.

 

Wake On Lan Packet Spreading

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:

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:

//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);

You can find the complete class here - PowerManager.cs.

Obtaining MAC Address

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:

DWORD SendARP(
__in IPAddr DestIP,
__in IPAddr SrcIP,
__out PULONG pMacAddr,
__inout PULONG PhyAddrLen
);

The method accepts destination IP address (DestIP parameter) and it will fill array of 6 bytes (pointed by pMacAddr parameter) which represents the MAC address of the device. To call this method from .NET, we will use PInvoke call:

[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:

Enabling Network Card Power Management

Click OK and you are ready your brand new Wake On LAN feature.

A propos: 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.

Wake On LAN manager

LukeN 080612

Edit 080723: Full source code of web site can be found here.

Edit 080921: Database script is here.

17 comments

# Martin on 07/16/08 at 12:37

Nicely done, didn’t you think about putting whole source code away?

# Neil on 07/23/08 at 18:29

Do your PCs answer ARP requests when they’re in standby mode?

# luke   on 07/23/08 at 20:16

Martin: I have added full source code download to the site
Neil: Nope, it does not work when they are put on Stand By, they need to be switched off by selecting Shut Down option from the start menu.

# Neil on 07/24/08 at 12:11

Thanks! I see, you resolve the MAC address while they are turned on so you and store it in the database - I wondered how you were doing it!

# behzad on 08/08/08 at 11:13

It was useful,
thanks.

# Paul Woodall on 08/09/08 at 01:33

Have you looked for a way to go past the subnets, we have a multi subnetted network and do not have servers on many of the subnets, but it would be great if we could use something like this with our Green Initiative. I am only a Tech, and do not know much about programming so I am not going to be any help resolving this type of problem. None of our routers or HP Switches will allow the broadcast to the other subnets, so we have not found a good way to do this, but your work is the best I have seen so far.
Thanks for your help,
Paul

# Erhan on 09/21/08 at 00:39

May I get this project db structure as sql. Thnx and Regards…

# ahmet   on 09/21/08 at 11:51

Where is the database script?

# luke   on 09/21/08 at 12:01

I have uploaded the database creation script, hope it helps…

Luke

# Erhan on 09/21/08 at 18:43

Thank you Mr Neumann for the script…

# Olav   on 10/13/08 at 10:53

Hi, I’m unable to download your files.
Are they offline atm?

# Mike on 10/25/08 at 00:37

The URLs to all your code files are broken.

# Keith on 10/25/08 at 02:29

The links for your source material seem to be dead. Can you repost please?

# tekie on 02/24/09 at 12:25

The explanation is very good. But the link for source code is not working.

please, re post it again or send me to my mail

# kinfe   on 02/25/09 at 07:36

can any one help me controlling(on and off) internet connection in a LAN using mac address.

# luke   on 03/14/09 at 13:58

The source code is back online. Sorry for the inconvenience…

# Tommi on 03/22/09 at 13:02

Hi Lukas,

thanks for the perfect explanations and the source code snippets.
I wanted to let you know that I made a simple small app for windows mobile to send magic packets to perform WOL with the help of your code examples:
http://forum.xda-developers.com/showthread.php?t=496289

Could not download the Souce-Code file though (but given the simplicity I guess it is not needed anyways ;)

Grüsse.
Tommi

This post has 241 feedbacks awaiting moderation...

Contact Us


Are you interested in professional services of the developers who publish on this blog? Contact us on our web site now.

  XML Feeds

Add to Technorati Favorites
October 2014
Sun Mon Tue Wed Thu Fri Sat
 << <   > >>
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
blog soft