Wake on LAN

Many modern computers and network enabled devices support the functionality to be turned on remotely. This is commonly referred as Wake on LAN or Remote Wake-Up.
Technically this is done sending a datagram packet in broadcast to all the computers in the same network, on any port (the usual one is port number 7); the magic packet is formatted with 6 bytes with hexadecimal value 'ff' (255) followed by the mac address of the machine to wake up, repeated 16 times. So all the computers will receive the packet and, if the mac address matches and the computer is turned off, it will wake up. This feature is then supported by the bios, because of course when the computer is off no operating systems are running. So, if you want to enable this feature, the bios is probably the place where to look for.

I bought a great NAS recently that is supporting this feature, and I searched around for a program to Wake it up remotely.

I found this beautifully short Python script in one article, but i had to fix it to avoid an error (socket.error: [Errno 13] Permission denied):

#!/usr/bin/env python
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.sendto('\xff'*6+'\x01\x23\x45\x67\x89\x10'*16, ('192.168.1.255', 7))

The above script works for waking up a computer in the 192.168.1.* network having mac address 01-23-45-67-89-10, you need to change it to match your network and your computer mac address.

There are software implementing this technique, but it is quite easy to write your own program using Java, as well, even tough it's not so short as the python version. I toke some time yesterday evening before going to sleep, to write a Java version of the above script. And here is it!

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class WOL {

    public static void main(String[] args) throws IOException {
        String macAddress = args[0];
        int port = 9;
        wakeUp(macAddress, port);
    }

    private static void wakeUp(String macAddress, int port) throws IOException {
        byte[] bytes = getMagicBytes(macAddress);
        InetAddress address = getMulticastAddress();
        send(bytes, address, port);
    }

    private static void send(byte[] bytes, InetAddress addr, int port)
            throws IOException {
        DatagramPacket p = new DatagramPacket(bytes, bytes.length, addr, port);
        new DatagramSocket().send(p);
    }

    private static InetAddress getMulticastAddress()
            throws UnknownHostException {
        return InetAddress.getByAddress(new byte[] {-1, -1, -1, -1});
    }

    private static byte[] getMagicBytes(String macAddress) throws IOException {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();

        for (int i = 0; i < 6; i++)
            bytes.write(0xff);

        byte[] macAddressBytes = parseHexString(macAddress);
        for (int i = 0; i < 16; i++)
            bytes.write(macAddressBytes);

        bytes.flush();

        return bytes.toByteArray();
    }

    private static byte[] parseHexString(String string) {
        byte[] bytes = new byte[string.length() / 2];
        for (int i = 0, j = 0; i < string.length(); i += 2, j++)
            bytes[j] = (byte) Integer.parseInt(string.substring(i, i + 2), 16);
        return bytes;
    }
}

The above program must be compiled with "javac WOL.java" and run as "java WOL 12345678910" where 12345678910 is the mac address. It will autmatically use the IP address 255.255.255.255 (for java byte is a signed type, so it corresponds to -1.-1.-1.-1), to obtain the broadcast address. If you have multiple network interface you may change the program a little bit to specify the broadcast address manually.

Then to complete the work I wrote a simple bash script to do the work of switching on/off the nas:

 
#! /bin/bash

case "$1" in
on)
        cd $(dirname $0)
        if [[ ! -e WOL.class ]]; then
            javac WOL.java
        fi
        java WOL 12345678910
        ;;
off)
        ssh root@my-nas poweroff
        ;;

*)
        echo "Usage: `basename $0` {on|off}"
        exit 1
        ;;
esac

Done.


No Responses to “Wake on LAN”  

  1. No Comments

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>



Calendar

April 2010
M T W T F S S
« Jan   May »
 1234
567891011
12131415161718
19202122232425
2627282930  

Follow me

twitter flickr LinkedIn feed

Subscribe by email

Enter your email address:

Archives


Categories

Tag Cloud


Listening