magic_shutdown: Shutdown computer remotely using Magic Packet

The title says it all. If you don’t know what a Magic Packet is then read here. Below is the code of a shell script (I call magic_shutdown) that uses tcpdump to listen for Magic Packets. When it receives on then the shell script verifies its content to make sure that this packet was meant for this computer. Note this script doesn’t require that your network interface card support Wake-on-LAN. It has no special hardware dependencies.

All-in-all, this script lets you create create a shortcut which will act as remote power button for your computer. Press it to turn the computer ON. Press it again to turn the computer OFF.

Get magic_shutdown‘s code
License: GNU Public License version 3.

[code lang=”bash”]#!/bin/bash
#Author:AppleGrew
#License:GPL version 3

listenPort=9
interface="eth0"

#Forking to daemonize…
if [[ "$2" != "forked" ]]
then
echo "Forking $0…"
"$0" "$1" forked &
echo "Forked."
exit 0
fi

#Creating pid file
ppid=$$
echo $ppid >"$1"

echo "Started"
mac=`ifconfig "$interface"|head -n1|sed -e ‘s/.*HWaddr \([0-9:a-fA-F]*\)/\1/g’ -e ‘s/://g’`
pckt_expect=`echo "ff ff ff ff ff ff $mac $mac $mac $mac $mac $mac $mac $mac"|sed ‘s/ //g’|tr ‘A-Z’ ‘a-z’`
while `true`
do
pckt_data=`tcpdump -i "$interface" -x -c 1 udp port ${listenPort}`
if [[ $? != 0 ]]
then
echo "tcpdump returned error."
exit 1
fi

pckt_data=`echo "$pckt_data" | \
grep ‘0x[0-9]*:’| \
tr ‘A-Z’ ‘a-z’| \
sed ‘s/[ \t]//g’| \
sed ‘s/0x[0-9]*:\([0-9a-f]*\)/\1/g’| \
tr -d ‘\n\r’| \
cut -c 57-`
if [[ "$pckt_data" == "$pckt_expect" ]]
then
echo "Matched! Received Magic packet shutting down…"
shutdown -P now #Not recommended
#For Gnome #Doesn’t work dunno why?
#dbus-send –session –dest=org.gnome.PowerManager \
# –type=method_call –print-reply –reply-timeout=2000 \
# /org/gnome/PowerManager org.gnome.PowerManager.Shutdown
#For KDE 3.5
#dcop `dcop|grep power-manager` power-manager shutdown
exit 0
fi
done

echo "EXITED"
exit 0[/code]

Below is the startup script that must be used to launch magic_shutdown script.

Get launch_magic_shutdown‘s code
License: GNU Public License version 3.

[code lang=”bash”]#!/bin/bash
#Author:AppleGrew
#License:GPL version 3

SCRIPT="/opt/magic_shutdown"
PID_FILE="/var/run/magic_shutdown.pid"
case "$1" in
start)
test -f "$PID_FILE" && echo "Already Running…" && exit 1
"$SCRIPT" "$PID_FILE"
echo "Started"
;;
stop)
pid=`cat "$PID_FILE"`

tcpPid=`pgrep -P $pid tcpdump`
kill -9 $pid
kill -2 $tcpPid
if [ -f "$PID_FILE" ] && ! ps -p $pid >/dev/null
then
rm -f "$PID_FILE"
else
echo "Failed to delete pid file. Maybe its already deleted."
fi
echo "Stopped"
;;
esac[/code]

Installations:-
Assuming that you have downloaded the above two codes into your home directory. Now run the following commands.

sudo cp launch_magic_shutdown /etc/init.d
sudo chmod a+x /etc/init.d/launch_magic_shutdown
cd /etc/rc2.d
sudo ln -s ../init.d/launch_magic_shutdown S99launch_magic_shutdown

sudo cp magic_shutdown /opt/magic_shutdown
sudo chmod a+x /opt/magic_shutdown

Hope this helps. Report in the comments section if you encounter any problem.


Update: Stuart’s Script
Stuart (see comment section) posted his version of magic_shutdown script. If the above one doesn’t work then maybe you should give this one a try.
[code lang=”bash”]#!/bin/sh
#Author: Stuart
#Original Author:AppleGrew
#License:GPL version 3

#Forking to daemonize…
if [[ "$2" != "forked" ]]
then
echo "Forking $0…"
"$0" "$1" forked &
echo "Forked."
exit 0
fi

#Creating pid file
ppid=$$
echo $ppid >"$1"

echo "Started"
interface=`route -n | grep "^0.0.0.0" | awk -F " " ‘{print $8}’`
mac=`ifconfig "$interface"|head -n1|sed -e ‘s/.*HWaddr \([0-9:a-fA-F]*\)/\1/g’ -e ‘s/://g’`
pckt_expect=`echo "$mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac $mac"|sed ‘s/ //g’|tr ‘A-Z’ ‘a-z’`
while `true`
do
pckt_data=`tcpdump -i "$interface" -s 0 -x -c 1 \( \(ether dst "$mac" and not ip and not arp and not rarp\) or \(udp port 9\) \)`
if [[ $? != 0 ]]
then
echo "tcpdump returned error."
exit 1
fi
pckt_data=`echo "$pckt_data" | \
grep ‘0x[0-9]*:’| \
tr ‘A-Z’ ‘a-z’| \
sed ‘s/[ \t]//g’| \
sed ‘s/0x[0-9]*:\([0-9a-f]*\)/\1/g’| \
tr -d ‘\n\r’ | \
awk -F "ffffffffffff" ‘{print $2}’`
if [[ "$pckt_data" == "$pckt_expect" ]]
then
echo "Matched! Received Magic packet shutting down…"
rm -f $1
/sbin/poweroff
exit 0
fi
done

echo "EXITED"
exit 0[/code]

Turn on (power on) your computer remotely

I was scanning the net today for ways to turn on any computer remotely. The solution I stumbled upon was Wake-On-LAN (WOL). (Read more) What’s more good, is that most of the computers sold today support this feature.

To know if your system supports this feature or not run the following command

sudo ethtool eth0

You will get output similar to the one below.

Supported ports: [ TP MII ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Full
Port: MII
PHYAD: 32
Transceiver: internal
Auto-negotiation: on
Supports Wake-on: pumbg
Wake-on: g
Current message level: 0x00000007 (7)
Link detected: yes

In the above please substitute eth0 with the network interface card’s name you want to listen for “Magic Packets“. The Supports Wake-on gives the methods your card supports to wake your computer up. In the output above, this card supports waking on any physical activity, on unicast message, on multicast message, on broadcast message and “Magic Packets” respectively. A value of d for Supports Wake-on means that your card doesn’t support WOL. (For the full list of meanings for these letters see ethtool‘s manpage under the wol portion.) In the output above Wake-on is g, which means that WOL for eth0 is enabled and is set to listen for “Magic Packets” only.

Useful links:-

  1. On Wkipedia, has steps to enable WOL via Windows.
  2. How-to for Ubuntu users.
  3. Very useful resource on WOL.
  4. Shutdown remote computers using Magic Packets.