#! /usr/bin/env python3 import argparse import sys import logging import socket import struct logger = logging.getLogger(__name__) def main() -> int: # Handle program arguments ap = argparse.ArgumentParser(prog="wol", description="Wake On LAN") ap.add_argument("mac", help="MAC address of the target machine") ap.add_argument( "-p", "--port", help="UDP port to send the magic packet to", type=int, default=9 ) ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) args = ap.parse_args() # Configure logging logging.basicConfig( level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s", ) # Parse MAC address mac = args.mac.replace(":", "").replace("-", "").replace(".", "") if len(mac) != 12: logger.error("Invalid MAC address") return 1 mac = bytes.fromhex(mac) # Create magic packet magic_packet = b"\xff" * 6 + mac * 16 # Try to broadcast magic packet over both IPv4 and IPv6 try: with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.sendto(magic_packet, ("", args.port)) except OSError as e: logger.error("Failed to broadcast magic packet over IPv4: %s", e) try: with socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) as s: s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.sendto(magic_packet, ("ff02::1", args.port)) except OSError as e: logger.error("Failed to broadcast magic packet over IPv6: %s", e) return 0 if __name__ == "__main__": sys.exit(main())