Friday, January 15, 2010

WakeOnLan ported to C#

Paul Mutton wrote a great article on how to use Wake-On-Lan which includes a tutorial on how to create a Magic Packet sender in Java.  He even provides the source of his java implementation: http://www.jibble.org/wake-on-lan/

I took the liberty of converting it to C# with a few minor modifications.  It allows a user to specify a Port number manually.

WHY C#?  Well why not?  I'm using C# at work so it comes naturally.  Mono gives me the ability to run code on both Windows and Linux.  Yes, so does Java.  There are a variety of tools out there and I like to familiarize myself with a good number of them.  In this spirit, I am currently writing a small connection testing tool in Java using Swing.  Maybe I'll write another port of Wake-On-LAN in C++ for fun.

Here is the C# code below:


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

namespace WakeOnLan
{
    class Program
    {       
        static void Main(string[] args)
        {
            string macAdd = "";
            string ip = "";
            string port = "9";
            int iPort = 0;

            if (args.Length < 2) {
                System.Console.WriteLine("Usage: wakeonlan <broadcast-ip> <mac-address> [<port>]");
                System.Console.WriteLine("Example: wakeonlan 192.168.0.255 00:0D:61:08:22:4A");
                System.Console.WriteLine("Example: wakeonlan 192.168.0.255 00-0D-61-08-22-4A");
                System.Environment.Exit(1);
            }

            ip = args[0];
            macAdd = args[1];
            if (args.Length > 2)           
                port = args[2];

            if (!IsNumeric(port))
            {
                System.Console.WriteLine("Port entered was not a number...");
                return; // quit
            }                     

            iPort = Int32.Parse(port);

            if (iPort > 65535 || iPort < 0)
            {
                System.Console.WriteLine("Port value is invalid");
                return;
            }

            byte[] mac = getMacBytes(macAdd);
            //byte[] mac = new byte[] { 0x00, 0x0F, 0x1F, 0x20, 0x2D, 0x35 };
            WakeUp(mac, iPort, ip);
        }

        ///
        /// Check whether string can be converted to a number value
        ///
        private static bool IsNumeric(string num)
        {
            try
            {
                double d = Double.Parse(num);
                return true;
            }
            catch
            {
                return false;
            }
        }

        ///
        /// Sends a Wake-On-Lan packet to the specified MAC address.
        ///
        private static void WakeUp(byte[] mac, Int32 iPort, string myIP)
        {
            //
            // WOL packet is sent over UDP 255.255.255.0:40000.
            //
            UdpClient client = new UdpClient();
            client.Connect(myIP, iPort);

            //
            // WOL packet contains a 6-bytes trailer and 16 times a 6-bytes sequence 
            // containing the MAC address.
            byte[] packet = new byte[17 * 6];

            //
            // Trailer of 6 times 0xFF.
            //
            for (int i = 0; i < 6; i++)
                packet[i] = 0xFF;

            //
            // Body of magic packet contains 16 times the MAC address.
            //
            for (int i = 1; i <= 16; i++)
                for (int j = 0; j < 6; j++)
                    packet[i * 6 + j] = mac[j];

            //
            // Submit WOL packet.
            //
            client.Send(packet, packet.Length);
            System.Console.WriteLine("Wake-on-LAN packet sent.");
        }
   
        private static byte[] getMacBytes(String macStr)
        {
            byte[] bytes = new byte[6];
            string[] hex = macStr.Split(new Char[] { ':', '-' });
            if (hex.Length != 6) {
                throw new ArgumentException("Invalid MAC address.");
            }
            try {
                for (int i = 0; i < 6; i++) {
                    Int32 intVal = Int32.Parse(hex[i], System.Globalization.NumberStyles.AllowHexSpecifier);
                    bytes[i] = (byte)intVal;
                }
            }
            catch (FormatException e) {
                throw new ArgumentException("Invalid hex digit in MAC address.");
            }
            return bytes;
        }
    }
}

No comments:

Post a Comment