#!/usr/bin/python '''Send a Wake-on-LAN magic packet This program can be used to send a Wake-on-LAN magic packet to a host on the local network. A WOL magic packet consists of 6 bytes of all ones, followed by sixteen repetitions of the target system's hardware (MAC) address. A WOL magic packet can be sent to any network (IP) address, as the contents of the packet are only inspected for the exact contents above, regardless of other header information. Typically, magic packets are broadcast, either to the limited broadcast address (255.255.255.255) or the network broadcast address to ensure that routers and switches will forward them to the desired destination host. :Author: Dustin C. Hatch :Copyright: 2014 Dustin C. Hatch :License: Apache 2.0 ''' import argparse import re import socket import sys def wake(mac_addr, ip_addr='255.255.255.255', port=9): '''Send a Wake-on-LAN magic packet :param mac: Destination hardware (MAC) address ''' # strip all formatting characters from the given # address and convert it to an integer. # this allows any formatting variant to be accepted, # including: # * standard: 00:11:22:aa:bb:cc # * Windows: 00-11-22-AA-BB-CC # * Cisco: 0011.22AA.BBCC mac_int = int(re.sub('[^0-9a-f]', '', mac_addr.lower()), 16) # separate the address into eight-bit pieces (as integers) mac_intlist = [] while mac_int > 0: mac_intlist.insert(0, mac_int & 0xff) mac_int >>= 8 # convert the 6 integers to a byte string # and generate the preamble if str is bytes: # Python 2 payload = '\xff' * 6 mac = ''.join(chr(b) for b in mac_intlist) else: payload = bytes((0xff,) * 6) mac = bytes(mac_intlist) # populate the remainder of the packet payload by repeating # the destination hardware address for _ in range(16): payload += mac # open a UDP-IP broadcast socket and send the packet s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.connect((ip_addr, port)) s.send(payload) s.close() def _parse_args(): parser = argparse.ArgumentParser() parser.add_argument('-i', dest='ip_address', metavar='ADDRESS', default='255.255.255.255', help='destination IP address') parser.add_argument('-p', dest='port', metavar='PORT', type=int, default=9, help='destination UDP port') parser.add_argument('-f', dest='macfile', metavar='FILE', help='read destination hardware addresses from FILE') parser.add_argument('address', help='destination hardware (MAC) address', nargs='*') args = parser.parse_args() if not args.address and not args.macfile: parser.error('No hardware address given') return args def main(): args = _parse_args() if args.macfile: with open(args.macfile) as f: for line in f.readlines(): # each address in the file can be followed by a comment mac, _ = line.split(None, 1) wake(mac, args.ip_address, args.port) else: for mac in args.address: wake(mac, args.ip_address, args.port) if __name__ == '__main__': main()