...

Wednesday, November 10, 2010

Java 03

In this article, I'm going to talk about Power Management Event. Power Management Event is a PCI 2.2 standard that allows network cards to receive Wake-on-LAN packets without the need for a WOL cable.
NICs can receive these PME packets from any of the computer sleepstates. Recall that a computer can be in one of five main powered states, of which three are of interest:
S3 - Suspend to RAM. This refers to "Sleep"
S4 - Suspend to Harddisk. This refers to "Hibernate"
S5 - Soft Off. This refers to "Shut Down"

S5 is referred to as Soft Off because although most of the components are turned off, some components can still be powered to receive signal to turn it on. There is another similar mode known as G3 mode in which a power is Mechanically Off, leaving only the RTC powered by an onboard battery.

When the computer is fully turned on, it is said to be in S0 mode.

In all states, with the exception of G3, compliant NIC cards are capable of receiving Magic Packets. A Magic Packet is simply a formatted UDP packet that causes a computer to switch to S0 mode. Magic Packets are typically received on UDP ports 0, 7 or 9.

For a computer to successfully perform WOL, the following conditions must be satisfied:
-Computer in a non-G3 state
-BIOS configured for PME/WOL
-Routing/Switching equipment must forward to correct interface
-Payload must follow proper format

We'll first talk about configuring the BIOS for WOL. During bootup, you can access your BIOS with the DEL key on most motherboards. Once you're the BIOS configuration, you would have to go under the Power Management section. Make sure that WOL is turned on and allowed. Note that on certain motherboards like Gigabyte P55A-UD3, it is referred to as PME instead.

A typical home router is actually a router with one routed and multiple switched interfaces. This essentially makes it a layer 3 switch. For a switch to forward the packet to the correct interface, it must already learn the MAC of the host.

Typically people forward port 9 to the IP address of the WOL host. However, before the router can successfully send the packet to the host, it must first ARP for the host's MAC address. If the host is turned off, it does not have an IP address, and therefore the host would not reply to the ARP request. The packet would then be dropped.

The trick here is to actually send the WOL packet out of all the ports. To do this, a static host must be configured with the broadcast MAC address of FF:FF:FF:FF:FF:FF. Any packet going to that static host would be sent out of all interfaces.

To do this on a Linux-based router like a router belonging to the WRT54G/GS/GL series, you would type this command:
ip neigh add 192.168.1.254 lladdr ff:ff:ff:ff:ff:ff nud permanent dev br0

On a Cisco equipment, you should use this command instead:
arp 192.168.1.254 ffff.ffff.ffff arpa

Since this must be typed every single time the router starts up, you should put it in the Init scripts. Note that you would have to use an address that would never be occupied by a host, or strange things would start to happen whenever communication to the host is required.



Now you can forward UDP port 9 to the 192.168.1.254 address from the router's GUI. In this arrangement, anything sent to port 9 would be broadcasted out all interfaces.

We'll now talk about the Magic Packet. The Magic Packet is a UDP packet with a sync stream and a MAC portion. The sync stream is simply a series of 1's spanning 6 bytes. The MAC portion is simply the MAC address of the WOL host repeated 16 times. The resulting packet has a payload size of (6+16*6)=102-bytes.

This is a sample WOL packet:
0000   00 00 0c 07 ac 03 02 00 4c 4f 4f 50 08 00 45 00
0010   00 82 3d 8e 00 00 80 11 aa 8b 98 e2 98 4a de a4
0020   42 80 ee 91 00 09 00 6e 53 b0 ff ff ff ff ff ff
0030   1c 6f 65 3f d4 f8 1c 6f 65 3f d4 f8 1c 6f 65 3f
0040   d4 f8 1c 6f 65 3f d4 f8 1c 6f 65 3f d4 f8 1c 6f
0050   65 3f d4 f8 1c 6f 65 3f d4 f8 1c 6f 65 3f d4 f8
0060   1c 6f 65 3f d4 f8 1c 6f 65 3f d4 f8 1c 6f 65 3f
0070   d4 f8 1c 6f 65 3f d4 f8 1c 6f 65 3f d4 f8 1c 6f
0080   65 3f d4 f8 1c 6f 65 3f d4 f8 1c 6f 65 3f d4 f8


This is a 11 (UDP) packet sent from 98 e2 98 4a (152.226.152.74) to de a4 42 80 (222.164.64.128). The packet is directed at port 00 09 (9). The payload starts from "ff ff ff ff ff ff" till the end of the packet. If you count, you would see 16 repetitions of the MAC address after the sync stream.

We'll now work on the programming part. We'll start by importing the networking packages because we'll need to transmit it using UDP (DatagramPacket, DatagramSocket):
import java.net.*;

Now, we'll begin by creating the payload in a byte array. We can very quickly create it by first storing the MAC address in its own byte array, then replicating it with a for-loop into another byte array representing the payload.

We'll first create the MAC array:
String macString = "ab:cd:ef:gh:ij:kl";
String[] macStringArray = macString.split(":");
byte[] macArray = new byte[6];
for (int i=0; i<6; i++)
{
macArray[i]=(byte)Integer.parseInt(macStringArray[i],16);
}


Next, we'll create a payload array and replicate the data through:
byte[] payload = new byte[102];
for (int i=0; i<payload.length; i++)
{
if (i<6) {
payload[i]=(byte)0xff;
}
else
{
payload[i]=macArray[i%6];
}
}


From index 0 to 5, it would be filled with 1's. From 6 to 102, it would be filled with the MAC address of the target.

Now we'll create a Datagram packet with the payload array we have:
String inetAddressString = "syraxius.ath.cx";
InetAddress inetAddress = InetAddress.getByName(inetAddressString);
DatagramPacket datagramPacket = new DatagramPacket(payload, payload.length, inetAddress, port);


Now we can transmit by creating a DatagramSocket:
DatagramSocket datagramSocket = new DatagramSocket();
datagramSocket.send(datagramPacket);


Finally, we close the socket:
datagramSocket.close();

And there you have it!

No comments :

Post a Comment

<