diff --git a/scripts/wol b/scripts/wol new file mode 100755 index 0000000..5d32cf0 --- /dev/null +++ b/scripts/wol @@ -0,0 +1,57 @@ +#! /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())