depicus

  just another nerd on the interweb…



  • home
  • gallery
  • play page
  • privacy
  • support
  • videos
  • what is depicus

Using a Raspberry Pi as a Wake on Lan Forwarder

Author: 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.

View Code C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
 
//
//  wolf.c
//
//  Created by Brian on 12/05/2012.
//  Copyright (c) 2012 Depicus. All rights reserved.
//
 
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/types.h>
 
#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 socket\n"); 
        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.%d\n", 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.%d\n",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.%d\n",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("%s\n",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("%s\n", str);
    }
    else 
    {
        printf("Resent WoL on port %i\n",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 %i\n", 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 Packet\n");
        sendWoLPacket(mesg);
 
    }
 
    printf("Fin\n");
    return 0;
}
Tweet

Tags: Raspberry Pi

This entry was posted on Monday, May 14th, 2012 at 7:46 pm and is filed under Computers, Interweb, Software Development, Wake On Lan. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.

13 Responses to “Using a Raspberry Pi as a Wake on Lan Forwarder”

May 28th, 2012 at 1:39 pm

Jonas Lonnroth says:

Your idea to use a small hardware device to circumvent the broadcast limitation is a good idea. I use Jump routers in virtual cable mode for this (see http://www.automonitor.net/jump), one on each side. With this particular VPN set up, you can broadcast and use any remote access without router hassle. Jump also works with a 3G modem inserted directly in the USB port of the small device, the mode can still be virtual cable. If needed in a LAN, you can set static ip adress. Set up takes only minutes and is very straight forward.

Í used your depicus ipad app over the Jump routers from one adsl network to another with good result.

So, one hardware device could help, but inexpensive hardware based vpn is better.

Kind regards

Jonas

May 28th, 2012 at 2:30 pm

The Man says:

Like that idea, might have to get one to have a play with :)

June 11th, 2012 at 12:37 pm

Clark says:

Jonas,
The Jump router in virtual cable mode sounds very interesting. Is it possible to use this Jump router behind my home router to wake up any home computer without using a 3G modem?

My Asus RT-N16 router has its own VPN server. I would like to use VPN client from remote pc to wake WHS server to do remote backups. I think the router broadcast limitation is stopping me.

Raspberry Pi and Jump router would be some fun home projects to try to resolve my WOL problem.

Thanks for sharing!!

Clark

July 5th, 2012 at 8:25 am

Russ says:

Great idea and it’s exactly what I was trying to get working with other methods but still struggled with.

I’ve tried the script on my Raspberry Pi, it compiles and launches OK but I’m stuck at that point.

Can somebody confirm what I need to do next to enable WOL over the internet by using my rpi as a forwarder please?

Thanks for the great idea!

Russ

July 5th, 2012 at 8:44 am

The Man says:

Hi Russ

Well got my Pi last week and got it up and running so thing to check.

1. Make sure you change “#define ETHNAME “en1″” to the name of the interface on the Pi, on mine it’s eth0 but ifconfig will tell you.
2. By default it listens on port 4343 and sends on port 9 but you can change if you want, just find those values in the code.
3. On your adsl box just do a port forward rule from the outside world to the ip of your Pi using port 4343 or whatever port you change it to.

That should be it. Any problems just ask.

July 5th, 2012 at 1:39 pm

Russ says:

This works great locally and in theory should work once I create a port forward in my router. The issue I do have is that I believe my ISP is blocking UDP packets for some reason. I have tried several routers and will be trying a basic Netgear router this afternoon maybe.

Would there be any other way to be able to get WOL broadcast packets inside a network by using a Pi as a forwarder when using a port forward rule on a ADSL router. Something along the lines of creating a listening service on the Pi that we send commands to over TCP instead of UDP? I thought about using something similar to Hamachi or VPN tunnels but that could get messy!

Russ

July 5th, 2012 at 2:16 pm

The Man says:

Hi Russ

You might be blocked on lower ports but never heard of them being blocked on high ports above 1024.

How are you sending from the web ?

Technically you could use TCP but that would need a tcp sender and receiver which I don’t think anybody does.

July 5th, 2012 at 2:50 pm

Russ says:

I tried port 4343 and 43434 with the same results as well as trying port 7.

I also tried using your woli.aspx as well as your GUI to send the WOL packets.

I’ve been able to launch the WOL monitor on a different server in a different office and use the same procedure as above and the monitor shows the packets working fine without any issues. It’s this that makes me think that I have an issue with my ISP blocking UDP altogether.

July 5th, 2012 at 3:53 pm

Russ says:

An idea…

I’ve installed Hamachi onto the Pi to get around my ISP potentially blocking UDP ports and then I have installed Hamachi onto a different computer. I’ve then run this forwarder code on the Pi specifying the Hamachi interface which works as much as it accepts the packet but I’m assuming it’s trying to then relay it back onto the same interface “ham0″ Is that correct?

Is it possible to add code to be able to specify what interface to use to send the magic packet back out onto? So in this case it would be “eth0″

Russ

July 5th, 2012 at 4:03 pm

The Man says:

Well this I found on MSDN

“For Sockets Using IP (Version 4)
To send a broadcast (on a SOCK_DGRAM only), the address pointed to by the to parameter can be constructed to contain the special IPv4 address INADDR_BROADCAST (defined in Winsock2.h), together with the intended port number. If the address pointed to by the to parameter contains the INADDR_BROADCAST address and intended port, then the broadcast will be sent out on all interfaces to that port.
If the broadcast should be sent out only on a specific interface, then the address pointed to by the to parameter should contain the subnet broadcast address for the interface and the intended port. For example, an IPv4 network address of 192.168.1.0 with a subnet mask of 255.255.255.0 would use a subnet broadcast address of 192.168.1.255.”

Not sure how you set up Hamachi, never heard of it before but going to have a play tonight :)

August 7th, 2012 at 10:36 am

Bix says:

Awesome, works like a charm. Hope you’re still working on making it into a service.

August 7th, 2012 at 10:54 am

The Man says:

Yes just got olympic fever at the moment :)

August 10th, 2012 at 4:50 pm

Vincent says:

Great !

I had the same idea a few months ago, and started to write a little magic packet forwarder for my brand new arduino uno + ethernet shield board.

If you’re interested, I wrote a tutorial about this little program, you can read it on my website here :

http://www.finalclap.com/tuto/arduino-wake-on-lan-repeater-80/

It’s in french but you can easily translate it to english to understand what I say, with google translate, or simply grab the source code & upload it to your arduino.

It works really great, I use it everyday to remote boot my personal computer from work and… ;)

Also, I added an optional feature : ip change logger (you need a PHP web hosting to run your own logger script, called by the arduino).

Everything is explained in the tutorial.

  • how i pay the bills

  • depicus in africa

    depicus in africa
  • my charity page

    JustGiving - Sponsor me now!
  • friends

    • Agency Manager
    • AllClear Travel
    • Climbing Tikes
    • Globe Bloggers
    • Marchday
    • The Travel Toad
  • gallery

    IMG_2304 IMG_0290 IMG_2589 IMG_4210
  • videos

    Vimeo

    YouTube
  • twitter

    • No public Twitter messages.
  • recent comments

    • john coull: correction to above, its www.oakley-ukstore.com
    • john coull: they are at it again. adverts on facebook . they are being hosted by enotch.com on ip address...
    • steve: The site are selling £120+ Oakley sun glasses for £13.00 I think its safe to say they may be either...
    • rob: have received a pair of glasses not what ive ordered they are now telling me the ones ive ordered are out of...
    • phil: hi i have purchased some (stupidly),not arrived yet, will they arrive/will they be fake/plz help

Copyright © - depicus | Entries (RSS) | Comments (RSS)

WordPress theme butchered and amended by me.