Skip to content

Wake-on-LAN (C#)

6 March 2010

Wake-on-LAN is a nifty feature of some network cards that allows you to remotely power on a workstation sitting on the local network. This is an OS-agnostic feature that works by broadcasting a specially crafted “magic” packet at the data link layer. The target computer sits in a low-power state with only its network card switched on, and when it receives the magic packet, the network card “wakes up” the computer, powering it on and booting it up.

Wake-on-LAN is a handy tool and could serve a number of purposes. For instance, it could be combined with a remote shutdown command (like shutdown.exe for Windows) to easily turn any computers in your office on and off at the click of a button. (I’m sure you can think of other more creative uses!)

Enabling Wake-on-LAN

The first step is to check that your computer supports Wake-on-LAN. There’s a few things to check:

  1. Your network card must support Wake-on-LAN
  2. Your power supply must support Wake-on-LAN
  3. Wake-on-LAN must be enabled in BIOS
  4. Your router must be configured to forward broadcast packets
  5. Your OS must be configured to enable Wake-on-LAN

Google is your friend here; I won’t delve into the specifics of enabling Wake-on-LAN, and will assume you have successfully set it up in the following discussion.

Remotely waking a computer

As explained above, when a computer with Wake-on-LAN enabled is switched off, its network card waits in a low-power mode listening for a special “magic” packet that signals the computer to power on. In order to wake up a computer, you need to know its MAC address (the computer is not switched on, so it doesn’t have an IP address yet). There are various ways of checking the MAC address of a computer. In Windows, the simplest way is to type “ipconfig /all” in a command prompt and look for the “physical address” listed for your network adapter. In Linux, the equivalent is “ifconfig“.

Now that we have the MAC address, let’s define a simple C# class for storing MAC addresses:

public class MACAddress
{
    private byte[] bytes;

    public MACAddress(byte[] bytes)
    {
        if (bytes.Length != 6)
            throw new System.ArgumentException("MAC address must have 6 bytes");
        this.bytes = bytes;
    }

    public byte this[int i]
    {
        get { return this.bytes[i]; }
        set { this.bytes[i] = value; }
    }

    public override string ToString()
    {
        return BitConverter.ToString(this.bytes, 0, 6);
    }
}

Our next step is to send the magic packet to a given MAC address. The magic packet is a very simple fixed size frame that consists of 6 bytes of ones (FF FF FF FF FF FF) followed by sixteen repetitions of the target MAC address, and is sent as a broadcast UDP packet, like so:

using System.Net;
using System.Net.Sockets;

...

public static void WakeUp(MACAddress mac)
{
    byte[] packet = new byte[17*6];

    for(int i = 0; i < 6; i++)
        packet[i] = 0xff;

    for (int i = 1; i <= 16; i++)
        for (int j = 0; j < 6; j++)
            packet[i * 6 + j] = mac[j];

    UdpClient client = new UdpClient();
    client.Connect(IPAddress.Broadcast, 0);
    client.Send(packet, packet.Length);
}

For example, to use this code to wake up the computer with the MAC address of 00-01-4A-18-9B-0C, you would call the WakeUp() function as follows:

WakeUp(new MACAddress(new byte[]{0x00, 0x01, 0x4A, 0x18, 0x9B, 0x0C}));

If you correctly enabled Wake-on-LAN on your target host, it should power on shortly after receiving this packet.

Remotely obtaining MAC addresses

Although you can manually obtain the MAC address of each individual computer on your computer (e.g. by running “ipconfig /all” on each one), this can be a time-consuming process if you need to wake up a large number of computers. A more convenient method of remotely checking the MAC addresses of computers on your LAN is using ARP. This is an Ethernet-level protocol that is used to request the MAC address of any computer from its IP address. Your OS caches the MAC address of every host it communicates with. For example, try pinging a computer and then immediately after type “arp -a” at the command prompt. This is the output from my computer after pinging my router and immediately checking the ARP cache:

C:\>ping 192.168.0.1 -n 1 && arp -a

Pinging 192.168.0.1 with 32 bytes of data:

Reply from 192.168.0.1: bytes=32 time=1ms TTL=64

Ping statistics for 192.168.0.1:
    Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 1ms, Maximum = 1ms, Average = 1ms

Interface: 192.168.0.183 --- 0x20002
  Internet Address      Physical Address      Type
  192.168.0.1           00-1c-f0-02-65-69     dynamic

It shows that the MAC address of my router is 00-1C-F0-02-65-69. In C#, we can send ARP requests using the SendARP function provided by the Windows IP Helper API. The following code allows us to resolve an IP address to a MAC address using ARP:

using System.Net;
using System.Runtime.InteropServices;

...

[DllImport("iphlpapi.dll", ExactSpelling=true)]
private static extern int SendARP(int DestIP, int SrcIP,
	[Out] byte[] pMacAddr, ref int PhyAddrLen);

public static MACAddress IpToMacAddress(IPAddress ipAddress)
{
	byte[] mac = new byte[6];
	int len = mac.Length;
	int res = SendARP((int)ipAddress.Address, 0, mac, ref len);
	if(res != 0)
		throw new WebException("Error " + res + " looking up " + ipAddress.ToString());
	return new MACAddress(mac);
}

For example, if I wanted to obtain the MAC address of the host 192.168.0.1:

MACAddress foo = IpToMacAddress(IPAddress.Parse("192.168.0.1"));

After shutting down this host, I could then power it back on with the following:

WakeUp(foo);

Closing remarks

An important thing to note is that Wake-on-LAN operates below the IP level. This means that the sending machine needs to be on the LAN, so we cannot send them over remote IP-based connections, such as over SSH or VPN. Also, while this article only dealt with Wake-on-LAN over a wired local network, it is possible to perform wake-up over wi-fi (try Googling for “WoWLAN” if you are trying to wake up computers over wi-fi).

You may have also noticed that Wake-on-LAN is very insecure. Any host can wake up any other computer on the LAN with Wake-on-LAN enabled armed with only its MAC address. Some NICs do allow password-protected WOL but, as far as I know, this is not widely implemented.

From → C#, Code snippets

2 Comments
  1. A federal report on the problems with the drug include “anaphylactic shock,”
    “foaming at mouth,” “grand mal convulsion,” “coma” and “now paralyzed. The boys are putting forth their talents that they’re finally realizing they have to do what they can for Zoomwood, among other things; I hope things work out for them, now. Earnest: (hugging Clarence,) That’s even more important; that, I did, three years ago.

Trackbacks & Pingbacks

  1. Enable Wake-on-LAN on Surface | Jimability

Leave a reply to venus program Cancel reply