depicus

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

Blants (noun) the rants of a blogger

  1. 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;
    }