Wake-On-Lan

It’s so sweety to maintain all workstations automatically in, say, 3am at night :) But this requires to turn it all on, and switch off after maintenance. Shutdowning is not a problem, but turning on… Turning on is not a problem too, but <=> your workstations support Wake-On-Lan technology.

Here a small C example how to invoke Wake-On-Lan.

Algo is simple – broadcast UDP magic-packet.

Magic packet consists of:

  1. Six 0xFF bytes
  2. Target MAC address repeated sixteen times.

If, say, target MAC is 32:00:00:23:11:13. Magic packet is

FF FF FF FF FF FF 32 00 00 23 11 13 32 00 00 23 11 13 32 00 00 23 11 13
32 00 00 23 11 13 32 00 00 23 11 13 32 00 00 23 11 13 32 00 00 23 11 13
32 00 00 23 11 13 32 00 00 23 11 13 32 00 00 23 11 13 32 00 00 23 11 13
32 00 00 23 11 13 32 00 00 23 11 13 32 00 00 23 11 13 32 00 00 23 11 13
32 00 00 23 11 13

Ok, ive stop bugging you and here is the code:

/**
 * wol.c - Wake-On-Lan example.
 *
 * 2008, Michelle Beloshitsky (itanko@li.ru)
 *
 **/

#include "winsock2.h"
#include "stdio.h"

#define MYPORT 2050 

#define MAGIC_PACKET_SIZE 6*17

/**
 * Creates magic packet
 **/
char* do_magic(char* mac)
{
    int i; int j;

    char * res = malloc(MAGIC_PACKET_SIZE);
    memset(res, 0xFF, MAGIC_PACKET_SIZE);

    for(i=1;i<17;i++)
    {
        for(j=0;j<6;j++)
        {
           res[i*6+j] = mac[j]; // expected to be at least 6 chars
        }
    }
    return res;
}

int main()
{
    unsigned char test_mac[6] = {0x00, 0x29, 0xED, 0x46, 0xE2, 0x06};

    WSADATA wsadata;
    if ( WSAStartup(MAKEWORD(2,2), &wsadata) != 0 )
    {
    printf("WSAStartup() error %i\n", WSAGetLastError());
        return 1;
    }

    SOCKET sock;
    sock = socket(AF_INET,SOCK_DGRAM,0);
    if (sock == INVALID_SOCKET)
    {
        printf("socket() error %i\n", WSAGetLastError());
        return 1;
    }

    char bc = '1'; // broadcast

    if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&bc,sizeof(bc)) < 0)
    {
        printf("setsockopt() error %i\n", WSAGetLastError());
        closesocket(sock);
        return 1;
    }

    struct sockaddr_in Sender_addr; 

    Sender_addr.sin_family       = AF_INET;
    Sender_addr.sin_port         = htons(MYPORT);
    Sender_addr.sin_addr.s_addr  = INADDR_BROADCAST;

    int res = sendto(sock,
                     do_magic(test_mac),
                     MAGIC_PACKET_SIZE,
                     0,
                     (struct sockaddr_in *)&Sender_addr,
                     sizeof(Sender_addr));

    if(res != MAGIC_PACKET_SIZE)
    {
        printf("sendto() error %i\n", WSAGetLastError());
        closesocket(sock);
        return 1;
    }

    closesocket(sock);
    WSACleanup();
}

About this entry