depicus

changing the digital world one bit at a time...

Blants (noun) the rants of a blogger

Using a Raspberry Pi as a Wake on Lan Forwarder

May 14, 2012 by The Man

Well I don’t have a Raspberry Pi yet but for $35 it’s a bargain and could be used as a WoL forwarder for those of you who don’t have a router that allow packet forwarding for Subnet Directed Broadcasts. This is a first draft of an app you can run.

1. Fire up your Raspberry Pi and download the developer tools, I am assuming your using a Debian based version of Linux. Simply type apt-get install build-essential

2. Copy the code below and place into a file e.g. nano wolf.c then save

3. Compile with gcc -o wolf wolf.c then run with ./wolf

* don’t forget to change to the name of your network interface #define ETHNAME “en1” usually eth0 on Linux but en0 on a mac.

That’s basically all there is to it. I am going to look at running as a service and report back later.


//
//  wolf.c
//
//  Created by Brian on 12/05/2012.
//  Copyright (c) 2012 Depicus. All rights reserved.
//

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define ETHNAME "eth0"
#define BUFLEN 102

char myipaddress[16];
char str[1024];
enum { ADDRS_SIZE = 8 };
struct in_addr bcast;
struct in_addr nmask;
static char netcard[16];

char const *getadapteraddress(char adapter[5])
{
    int fd;
    struct ifreq ifr;
    u_char *addr;
    u_char *braddr;
    u_char *naddr;
    fd = socket (AF_INET, SOCK_DGRAM,0);
    if ((fd = socket(AF_INET,SOCK_DGRAM,0)) < 0) 
    { 
        fprintf(stderr,"Error: Unable to create socketn"); 
        perror("socket"); 
        return "-1"; 
    } 
    memset (&ifr, 0, sizeof (struct ifreq));
    strcpy (ifr.ifr_name, adapter);
    ifr.ifr_addr.sa_family = AF_INET;
    ioctl(fd, SIOCGIFADDR, &ifr);
    addr=(u_char*)&(((struct sockaddr_in * )&ifr.ifr_addr)->sin_addr);
    //printf("eth %s, addr %d.%d.%d.%dn", ifr.ifr_name,addr[0],addr[1],addr[2],addr[3]);
    strcat(netcard,ifr.ifr_name);
    sprintf (myipaddress,"%d.%d.%d.%d",addr[0],addr[1],addr[2],addr[3]);
    
    memset (&ifr, 0, sizeof (struct ifreq));
    strcpy (ifr.ifr_name, adapter);
    ifr.ifr_addr.sa_family = AF_INET;
    ioctl(fd, SIOCGIFBRDADDR, &ifr);
    braddr=(u_char*)&(((struct sockaddr_in * )&ifr.ifr_broadaddr)->sin_addr);
    //printf("eth broadcast %d.%d.%d.%dn",braddr[0],braddr[1],braddr[2],braddr[3]);
    memcpy(&bcast, &(*(struct sockaddr_in *)&ifr.ifr_broadaddr).sin_addr, 4);

    
    memset (&ifr, 0, sizeof (struct ifreq));
    strcpy (ifr.ifr_name, adapter);
    ifr.ifr_addr.sa_family = AF_INET;
    ioctl(fd, SIOCGIFNETMASK, &ifr);
    naddr=(u_char*)&(((struct sockaddr_in * )&ifr.ifr_broadaddr)->sin_addr);
    //printf("eth subnet %d.%d.%d.%dn",braddr[0],braddr[1],braddr[2],braddr[3]);
    memcpy(&nmask, &(*(struct sockaddr_in *)&ifr.ifr_broadaddr).sin_addr, 4);
    
    close(fd);
    return myipaddress;
}

// Main section

void sendWoLPacket(char mesg[101])
{
    int sendSocket;
    struct sockaddr_in wt;
    memset(&wt, 0, sizeof(wt));
    wt.sin_family = AF_INET;
    wt.sin_port = htons(9);
    wt.sin_addr.s_addr = inet_addr(inet_ntoa(bcast)); 
    
    sendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    int udpflag = 1;
    int retval;
    retval = setsockopt(sendSocket, SOL_SOCKET, SO_BROADCAST, &udpflag, sizeof(udpflag));
    if (retval < 0)
    {
        sprintf (str,"failed to setsockopt: %s",strerror(errno));
        printf("%sn",str);
    }
    
    int res;
    res = sendto(sendSocket,mesg,BUFLEN,0,(struct sockaddr *)&wt,sizeof(wt));
    
    if (res < 0)
    {
        sprintf (str,"failed to send: %s",strerror(errno));
        printf("%sn", str);
    }
    else 
    {
        printf("Resent WoL on port %in",9);
    }

    
}

int main(int argc, const char * argv[])
{
    printf("Starting WoLf:n");
    
    char const *cptr;
    cptr = getadapteraddress(ETHNAME);
    printf("%s: inet %s netmask %s broadcast %s n",netcard,cptr,inet_ntoa(nmask),inet_ntoa(bcast));

    int sendSocket,n;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t len;
    char mesg[101]; //wol packet size is 102 so 0 to 101
    //int bytes;
    
    sendSocket=socket(AF_INET,SOCK_DGRAM,0);
    
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servaddr.sin_port=htons(4343);
    bind(sendSocket,(struct sockaddr *)&servaddr,sizeof(servaddr));
    
    for (;;)
    {
        len = sizeof(cliaddr);
        n = recvfrom(sendSocket,mesg,1000,0,(struct sockaddr *)&cliaddr,&len);
        sendto(sendSocket,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
        printf("-------------------------------------------------------n");
        mesg[n] = 0;
        printf("nPacket Received with length %in", n);
        //mesg[n] = 0;
        
        if (!n == 102) continue;
        
        printf("mac address: %02X:%02X:%02X:%02X:%02X:%02X n",(unsigned char)mesg[6],(unsigned char)mesg[7],(unsigned char)mesg[8],(unsigned char)mesg[9],(unsigned char)mesg[10],(unsigned char)mesg[11]);
        
        char ffAddress[18] = "";
        char mAddress[18] = "";
        
        // check that the first six digits are FF
        sprintf (ffAddress,"%02X:%02X:%02X:%02X:%02X:%02X",(unsigned char)mesg[0],(unsigned char)mesg[1],(unsigned char)mesg[2],(unsigned char)mesg[3],(unsigned char)mesg[4],(unsigned char)mesg[5]);
        if (!strncmp(ffAddress,"FF:FF:FF:FF:FF:FF",17)  == 0)
        {
            continue;
        }
        
        // check we have six repeating mac addresses
        int y;
        for (y = 0; y < 6; y++) 
            {
                int mply = 6 * (y + 1);
                sprintf (mAddress,"%02X:%02X:%02X:%02X:%02X:%02X",(unsigned char)mesg[mply],(unsigned char)mesg[mply+1],(unsigned char)mesg[mply+2],(unsigned char)mesg[mply+3],(unsigned char)mesg[mply+4],(unsigned char)mesg[mply+5]);
                printf("%i %s n",y, mAddress);
                
                if (y > 0)
                {
                    if (!strncmp(mAddress,ffAddress,strlen(ffAddress)) == 0)
                    {
                        continue;
                    }

                }
                stpcpy(ffAddress,mAddress);
            }
        
        //int y;
        //for (y = 0; y < sizeof(mesg); y++) 
        //{
        //    printf("%i = %02X ",y,(unsigned char)mesg[y]);
        //}
        printf("End Packetn");
        sendWoLPacket(mesg);
        
    }
         
    printf("Finn");
    return 0;
}