#!/usr/bin/env perl # Author: Jim Avera License: Public Domain or CC0 # See https://creativecommons.org/publicdomain/zero/1.0/ use strict; use warnings; use IO::Socket::INET; #### CONFIGURATION ################################ my $fqdn_or_ip = "yourrouter.hopto.org"; # DDNS domain name or public IP Addr my $target_mac = "aa:bb:cc:dd:ee:ff"; # MAC Address of host to wake up my $secureon_pw = ""; # SecureOn password if used e.g. "aa:bb:cc:dd:ee:ff"; my $tunnel_port = 9; ################################################### END{ if ($^O eq "MSWin32") { # When run via double-clicking, a command terminal is assigned but it will # immediately close when we exit. When we are done (normally or on error), # Wait for the user to type Enter so they can read our messages. print "\nType ENTER to exit: "; STDOUT->flush; ; } } # Translate fqdn or ip-addr string to numeric IP Address my $ipaddr = inet_aton($fqdn_or_ip) || die "inet_aton: $!"; my $ipaddr_str = join(".", unpack('C4',$ipaddr)); # "nn.nn.nn.nn" # Parse MAC Address string, convert to binary bytes. Any delimiter may be used. my @mac = map{ hex } split /[^a-fA-F0-9]/, $target_mac; die "target mac should be of the form hh:hh:hh:hh:hh:hh" unless @mac==6; # Ditto for the "SecureOn password" (optional and rarely used) my @pw = map{ hex } split /[^a-fA-F0-9]/, $secureon_pw; die "SecureOn password should be empty or of form hh:hh:hh:hh:hh:hh" unless @pw==0 || @pw==6; # Form the 'magic packet' data # https://en.wikipedia.org/wiki/Wake-on-LAN#Magic_packet my @bytes = ( (0xFF) x 6, (@mac) x 16, @pw ); my $msg = pack('C*', @bytes); my $handle = IO::Socket::INET->new(Proto => 'udp') or die "socket: $@"; my $port_addr = sockaddr_in($tunnel_port, $ipaddr); my $size = send($handle, $msg, 0, $port_addr) or die "cannot send to ${fqdn_or_ip}:$tunnel_port -- $!"; print "Sent ${size}-byte magic packet containing MAC Address $target_mac\n"; print " and a SecureOn password\n" if @pw; print " to port $tunnel_port at $fqdn_or_ip ($ipaddr_str)\n"; die "*** Something went wrong with send ***\n" unless $size == @bytes; exit 0;