Posted: Fri Jan 28, 2011 1:07 Post subject: Feature Idea: Activity based WOL [update: script included]
The idea is to have advanced control over Wake-On-LAN based on the activity on the network. Suppose you want your server, which hosts your iTunes library, to automatically wake up when a request is sent to it on the ports used by iTunes home sharing (TCP 3689 and UDP 5353). DD-WRT could detect requests sent to the server on those ports (perhaps restricting it when only coming from certain clients), and automatically send a WOL magic packet. To avoid always sending magic packets when detecting activity on the specified ports, you could program a time in between successive magic packets. So suppose you have your Server set to sleep after 30 minutes of inactivity. It wouldn't make any sense to send magic packets due to the detecting of activity on that port less than 30 minutes apart. Alternatively, DD-WRT could do a quick ping to see if the computer appears to be in standby.
This certainly seems very feasible, and I'd imagine many people would be interested in such a feature. It sure beats having to manually issue a WOL magic packet every time prior to using files from a server that is set to go into standby during periods of inactivity.
Last edited by onlinespending on Fri Jan 28, 2011 22:41; edited 1 time in total
Traffic going over the lan switch from one port to another is not seen by dd-wrt.
There is no routing software involved for it, the switch hardware handles it by itself. _________________ Kernel panic: Aiee, killing interrupt handler!
For one it'd be nice if such a feature were built-in as it'd be far more efficient than parsing a log file. But this method is limited to detecting traffic on the inbound WAN connection, as that's all the log file in question captures.
Does DD-WRT have any visibility on the internal traffic, whether it be wired LAN or wifi? Even if DD-WRT isn't involved in the routing of internal traffic, can it in any way monitor or poll it? LOM seemed to suggest this is not the case (I made the poor assumption he was talking only about wire LAN connections, when I first read what he wrote).
Looks like I may be able to do this using tcpdump. It wouldn't be the most straightforward or elegant solution. But given that tcpdump can view internal LAN traffic, I don't see why DD-WRT couldn't offer a more direct way to provide automatic activity based WOL.
Any other ways to log internal traffic besides tcpdump?
tcpdump -s 64 -U -C 1 -W 1 -w /tmp/var/log/tcpdump.log dst $IPADDR and not host $GATEWAY 2>/dev/null &
while sleep $INTERVAL;do
ACTTIME=`tcpdump -tt -r /tmp/var/log/tcpdump.log arp or \( dst port 445 or 3389 or 3689 or 6783 \) 2>&1 | tail -1 | awk '{printf "%d", $1}'`
CURTIME=`date +%s`
if [ `expr $CURTIME - $ACTTIME` -lt $IDLETIME ]; then
$WOL -i $BCAST -p $PORT $MAC
kill $(pidof tcpdump)
sleep $IDLETIME
tcpdump -s 64 -U -C 1 -W 1 -w /tmp/var/log/tcpdump.log dst $IPADDR and not host $GATEWAY 2>/dev/null &
fi
done
A few things of note. Basically the script starts by running tcpdump in the background and only intercepts packets sent to the host with ip address of $IPADDR and stores them to /tmp/var/log/tcpdump.log in a raw format. It then enters the while loop which is iterated on with a 5 second wait. It then sees if there is any ARP requests to the Server (typical if the machine is in standby and offline) or if there is any activity on the chosen ports (this can be changed to your liking). If either of these conditions have occurred within the time specified by IDLETIME, then it will issue a WOL to the Server. The IDLETIME is the amount of inactivity required before your Server enters standby. I have mine set to 30 minutes, hence the 1800 seconds. The thinking is, if the machine has had a recent activity on it, then it's safe to put the script to sleep for that IDLETIME and kill tcpdump (to be more efficient while not needing to analyze packets). Even though I'm looking to see if there's any activity within IDLETIME, it would have to have been within the last 5+ seconds (because the script was either sleeping for IDLETIME or had just iterated once through the loop in 5+ seconds).
EDIT: I noticed that despite the initial filter of 'dst $IPADDR' that some unintended ARP lines related to the Gateway/router address snuck through, which was waking up the Server unexpectedly. I updated the script to include 'not host $GATEWAY'.
Posted: Wed Nov 16, 2011 11:48 Post subject: Not on 4MB Flash routers?
Do I understand correctly, that on routers with 4MB flash is no TCPDUMP by default and because there is also no JFFS it cannot be installed and so the script is not working here?
Posted: Sat Feb 11, 2012 14:27 Post subject: Activity based WOL [update: script included]
I could not get the script to work. I am trying to wake my media pc only when a request is made for a shared file from it from any locally connected network client such as networked TV. Can this be done? Any help is appreciated.
rostar, I have mine setup to do the same thing with a SMB share. The obvious things are to make sure you change IPADDR to the ip address of your media pc and MAC to the MAC address of your media pc. Make sure your build of dd-wrt even includes tcpdump. And you can change the dst port to just include 445, but make sure you leave everything else in that line the same, including the arp.
Code:
ACTTIME=`tcpdump -tt -r /tmp/var/log/tcpdump.log arp or \( dst port 445 \) 2>&1 | tail -1 | awk '{printf "%d", $1}'`
rostar, I have mine setup to do the same thing with a SMB share. The obvious things are to make sure you change IPADDR to the ip address of your media pc and MAC to the MAC address of your media pc. Make sure your build of dd-wrt even includes tcpdump. And you can change the dst port to just include 445, but make sure you leave everything else in that line the same, including the arp.
Code:
ACTTIME=`tcpdump -tt -r /tmp/var/log/tcpdump.log arp or \( dst port 445 \) 2>&1 | tail -1 | awk '{printf "%d", $1}'`
I just realized that I can not load a version with TCPdump (WRT54G V3). Is it possible to wake my media server whenever the router senses my TV is online instead? Thanks again
Here's an updated version that cleans it up a bit and allows an easier way to add your own destination ports. It also takes care of UPnP used by DLNA, since it doesn't directly address the server but rather broadcasts on UDP port 1900. You can edit the DLNA variable to include the IP addresses of your DLNA clients.
INTERVAL=5
IDLETIME=1140
WOL=/usr/sbin/wol
GATEWAY=192.168.1.1
IPADDR=192.168.1.10
BCAST=192.168.1.255
WOLPORT=9
MAC=00:11:22:33:44:55
DSTPORTS="445 or 3389 or 3689 or 6783"
DLNA="192.168.1.30 or 192.168.1.31"
sleep 60
tcpdump -s 64 -U -C 1 -W 1 -w /tmp/var/log/tcpdump.log dst $IPADDR and not host $GATEWAY and \(dst port $DSTPORTS\) or \(udp port 1900 and src $DLNA\) 2>/dev/null &
while sleep $INTERVAL;do
ACTTIME=`tcpdump -tt -r /tmp/var/log/tcpdump.log 2>&1 | tail -1 | awk '{printf "%d", $1}'`
CURTIME=`date +%s`
if [ `expr $CURTIME - $ACTTIME` -lt 10 ]; then
$WOL -i $BCAST -p $WOLPORT $MAC
kill $(pidof tcpdump)
sleep $IDLETIME
tcpdump -s 64 -U -C 1 -W 1 -w /tmp/var/log/tcpdump.log dst $IPADDR and not host $GATEWAY and \(dst port $DSTPORTS\) or \(udp port 1900 and src $DLNA\) 2>/dev/null &
fi
Here's an updated version that cleans it up a bit and allows an easier way to add your own destination ports. It also takes care of UPnP used by DLNA, since it doesn't directly address the server but rather broadcasts on UDP port 1900. You can edit the DLNA variable to include the IP addresses of your DLNA clients.
INTERVAL=5
IDLETIME=1140
WOL=/usr/sbin/wol
GATEWAY=192.168.1.1
IPADDR=192.168.1.10
BCAST=192.168.1.255
WOLPORT=9
MAC=00:11:22:33:44:55
DSTPORTS="445 or 3389 or 3689 or 6783"
DLNA="192.168.1.30 or 192.168.1.31"
sleep 60
tcpdump -s 64 -U -C 1 -W 1 -w /tmp/var/log/tcpdump.log dst $IPADDR and not host $GATEWAY and \(dst port $DSTPORTS\) or \(udp port 1900 and src $DLNA\) 2>/dev/null &
while sleep $INTERVAL;do
ACTTIME=`tcpdump -tt -r /tmp/var/log/tcpdump.log 2>&1 | tail -1 | awk '{printf "%d", $1}'`
CURTIME=`date +%s`
if [ `expr $CURTIME - $ACTTIME` -lt 10 ]; then
$WOL -i $BCAST -p $WOLPORT $MAC
kill $(pidof tcpdump)
sleep $IDLETIME
tcpdump -s 64 -U -C 1 -W 1 -w /tmp/var/log/tcpdump.log dst $IPADDR and not host $GATEWAY and \(dst port $DSTPORTS\) or \(udp port 1900 and src $DLNA\) 2>/dev/null &
fi
Nice code, dude, I have number of server to look after, so I will update your code into array of IP address. Can you put your code under GPL, so I can modify it please.