2022-10-02 12:43:53 +02:00

171 lines
4.8 KiB
Python

#!/usr/bin/env python3
"""
https://github.com/remcohaszing/pywakeonlan
A small python module for wake on lan.
For more information on the wake on lan protocol
please take a look at Wikipedia.
http://en.wikipedia.org/wiki/Wake-on-LAN
Usage
To wake up a computer using wake on lan it must first be enabled in the BIOS
settings. Please note the computer you are trying to power on does not have an
ip address, but it does have a mac address.
The package needs to be sent as a broadcast package.
As a python module
Import the module
>>> from wakeonlan import send_magic_packet
Wake up a single computer by its mac address
>>> send_magic_packet('ff.ff.ff.ff.ff.ff')
Wake up multiple computers by their mac addresses.
>>> send_magic_packet('ff.ff.ff.ff.ff.ff', '00-00-00-00-00-00',
... 'FFFFFFFFFFFF')
An external host may be specified.
Do note that port forwarding on that host is required.
The default ip address is 255.255.255.255 and the default port is 9.
>>> send_magic_packet('ff.ff.ff.ff.ff.ff',
... ip_address='example.com',
... port=1337)
A network adapter may be specified.
The magic packet will be routed through this interface.
>>> send_magic_packet('ff.ff.ff.ff.ff.ff',
... interface='192.168.0.2')
As a standalone script
usage:
wakeonlan [-h] [-i ip] [-p port] [-n interface] mac address [mac address ...]
Wake one or more computers using the wake on lan protocol.
positional arguments:
mac address The mac addresses of the computers you are trying to wake.
optional arguments:
-h, --help show this help message and exit
-i ip The ip address of the host to send the magic packet to.
(default 255.255.255.255)
-p port The port of the host to send the magic packet to. (default 9)
-n interface The ip address of the network adapter to route the
magic packet through. (optional)
Dependencies
Python3.x
License
MIT
"""
import argparse
import socket
from typing import List
BROADCAST_IP = "255.255.255.255"
DEFAULT_PORT = 9
def create_magic_packet(macaddress: str) -> bytes:
"""
Create a magic packet.
A magic packet is a packet that can be used with the wake on lan protocol
to wake up a computer. The packet is constructed from the mac address
given as a parameter.
Args:
macaddress: the mac address that should be parsed into a magic packet.
"""
if len(macaddress) == 17:
sep = macaddress[2]
macaddress = macaddress.replace(sep, "")
elif len(macaddress) != 12:
raise ValueError("Incorrect MAC address format")
return bytes.fromhex("F" * 12 + macaddress * 16)
def send_magic_packet(
*macs: str,
ip_address: str = BROADCAST_IP,
port: int = DEFAULT_PORT,
interface: str = None
) -> None:
"""
Wake up computers having any of the given mac addresses.
Wake on lan must be enabled on the host device.
Args:
macs: One or more macaddresses of machines to wake.
Keyword Args:
ip_address: the ip address of the host to send the magic packet to.
port: the port of the host to send the magic packet to.
interface: the ip address of the network adapter to route the
magic packet through.
"""
packets = [create_magic_packet(mac) for mac in macs]
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
if interface is not None:
sock.bind((interface, 0))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.connect((ip_address, port))
for packet in packets:
sock.send(packet)
def main(argv: List[str] = None) -> None:
"""
Run wake on lan as a CLI application.
"""
parser = argparse.ArgumentParser(
description="Wake one or more computers using the \
wake on lan protocol.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"macs",
metavar="mac address",
nargs="+",
help="The mac addresses of the computers you are trying to wake.",
)
parser.add_argument(
"-i",
metavar="ip",
default=BROADCAST_IP,
help="The ip address of the host to send the magic packet to.",
)
parser.add_argument(
"-p",
metavar="port",
type=int,
default=DEFAULT_PORT,
help="The port of the host to send the magic packet to.",
)
parser.add_argument(
"-n",
metavar="interface",
default=None,
help="The ip address of the network adapter to route the \
magic packet through.",
)
args = parser.parse_args(argv)
send_magic_packet(*args.macs,
ip_address=args.i,
port=args.p,
interface=args.n)
if __name__ == "__main__": # pragma: nocover
main()