#!/usr/bin/perl -w # Magic Packet for the Web # Perl version by ken.yap@acm.org after DOS/Windows C version posted by # Steve_Marfisi@3com.com on the Netboot mailing list # modified to work with web by G. Knauf <info@gknw.de> # Released under GNU Public License # require "cgi-lib.pl"; use Socket; $ver = 'v0.52 © gk 2003-Apr-24 11:00:00'; # Defaults - Modify to point to the location of your mac file $www = "$ENV{'DOCUMENT_ROOT'}/perldemo"; $maclist = "$www/maclist.txt"; # Defaults - Modify to fit to your network $defbc = '255.255.255.255'; $port = 60000; MAIN: { # Read in all the variables set by the form if (&ReadParse(*input)) { &process_form(); } else { &print_form(); } } sub process_form { # Print the header print &PrintHeader(); # If defined new mac save it if (defined($input{'mac'})) { print &HtmlTop("Result of adding an entry to the maclist"); print '<HR><H3><TT>'; &add_entry; print '</TT></H3><HR>'; print '<FORM method="POST"><input type=submit value="ok"></FORM>'; } else { # send magic packets to selected macs print &HtmlTop("Result of sending magic packets to multiple PCs"); print '<HR><H3><TT>'; if (defined($input{'all'})) { &process_file(S); } else { foreach $x (keys %input) { my ($brc,$mac) = split(/-/,$input{$x}); &send_broadcast_packet(inet_aton($brc),$mac); } } print '</TT></H3><HR>'; print '<form><input type=button value="back" onClick="history.back()"></FORM>'; } # Close the document cleanly. print &HtmlBot; exit; } sub print_form { print &PrintHeader(); print &HtmlTop("Form for sending magic packets to multiple PCs"); # Print out the body of the form print <<ENDOFTEXT; <HR> <FORM method="POST"> <H2> Select the destination mac addresses: </H2> <TABLE BORDER COLS=3 WIDTH="80%"> <TR> <TD><CENTER><B><FONT SIZE="+1">Broadcast address</FONT></B></CENTER></TD> <TD><CENTER><B><FONT SIZE="+1">MAC address</FONT></B></CENTER></TD> <TD><CENTER><B><FONT SIZE="+1">Name</FONT></B></CENTER></TD> <TD><CENTER><B><FONT SIZE="+1"><input type=checkbox name="all" value="all">Select all</FONT></B></CENTER></TD> </TR> ENDOFTEXT # build up table with mac addresses &process_file; # print rest of the form print <<ENDOFTEXT; </TABLE> <P><B><FONT SIZE="+1"> Press <input type="submit" value="wakeup"> to send the magic packets to your selections. Press <input type="reset" value="clear"> to reset the form. </FONT></B> </FORM> <HR> <FORM method="POST"> <H2>Enter new destination mac address:</H2> <B><FONT SIZE="+1">Broadcast: </FONT></B><input name="brc" size="15" maxlength="15" value="$defbc"> <B><FONT SIZE="+1">MAC: </FONT></B><input name="mac" size=17 maxlength=17> <B><FONT SIZE="+1">Name: </FONT></B><input name="ip" size=40 maxlength=40> <P><B><FONT SIZE="+1"> Press <input type="submit" value="save"> to add the entry to your maclist. Press <input type="reset" value="clear"> to reset the form. </FONT></B> </FORM> <HR> $ver ENDOFTEXT # Close the document cleanly. print &HtmlBot; } sub send_broadcast_packet { my ($nbc,$mac) = @_; if ($mac !~ /^[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}$/i) { print "Malformed MAC address $mac<BR>\n"; return; } printf("Sending wakeup packet to %04X:%08X-%s<BR>\n", $port, unpack('N',$nbc), $mac); # Remove colons $mac =~ tr/://d; # Magic packet is 6 bytes of FF followed by the MAC address 16 times $magic = ("\xff" x 6) . (pack('H12', $mac) x 16); # Create socket socket(S, PF_INET, SOCK_DGRAM, getprotobyname('udp')) or die "socket: $!\n"; # Enable broadcast setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt: $!\n"; # Send the wakeup packet defined(send(S, $magic, 0, sockaddr_in($port, $nbc))) or print "send: $!\n"; close(S); } sub process_file { unless (open(F, $maclist)) { print "Error reading $maclist: $!\n"; } else { while (<F>) { next if (/^\s*#|^\s*;/); # skip comments my ($mac, $ip) = split; next if (!defined($mac) or $mac eq ''); $mac = uc($mac); my $bc = $defbc; ($bc,$mac) = split(/-/,$mac) if ($mac =~ /-/); my $nbc = inet_aton($bc); if ($_[0] eq 'S') { &send_broadcast_packet($nbc, $mac); } else { my $hbc = sprintf("0x%08X", unpack('N',$nbc)); print "<TD WIDTH=20%><CENTER><TT>$hbc</TT></CENTER></TD>"; print "<TD WIDTH=30%><CENTER><TT>$mac</TT></CENTER></TD>"; $ip = ' ' if (!defined($ip) or $ip eq ''); print "<TD WIDTH=30%><CENTER><TT>$ip</TT></CENTER></TD>"; print "<TD WIDTH=20%><CENTER><input type=checkbox name=mac$. value=$hbc-$mac><TT>WakeUp</TT></CENTER></TD></TR>\n"; } } close(F); } } sub add_entry { if (param("brc") !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/i) { print "Malformed broadcast address ",param("brc"),"\n"; return; } if (param("mac") !~ /^[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}$/i) { print "Malformed MAC address ",param("mac"),"\n"; return; } unless (open(F, ">> $maclist")) { print "Error writing $maclist: $!\n"; } else { #my $nbc = inet_aton(param("brc")); #my $hbc = sprintf("0x%8X", unpack('N',$nbc)); #print F $hbc."-".uc(param("mac"))." ".param("ip")."\n"; print F param("brc")."-".uc(param("mac"))." ".param("ip")."\n"; close(F); print "Saved entry to maclist: ".param("brc")."-".uc(param("mac"))." ".param("ip")."\n"; } }