Skip to content

Commit

Permalink
Merge branch 'special-wakeups' into 'master'
Browse files Browse the repository at this point in the history
Add support for /etc/wake-on-lan/special-wakeup.d

See merge request i4/infra/wake-on-lan!3
  • Loading branch information
Flowdalic committed Sep 13, 2022
2 parents a1df4c0 + 1de2daf commit 28e37dd
Showing 1 changed file with 25 additions and 5 deletions.
30 changes: 25 additions & 5 deletions wol.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#!/usr/bin/env python3

from pathlib import Path
from pyparsing import *
from typing import Dict, Optional
import socketserver
import argparse
import logging
import psutil
import stat
import socket
import subprocess
import sys
import os
import re
Expand Down Expand Up @@ -74,9 +77,16 @@ def sendMagicPacket(macAddress: str, iface: str) -> bool:
logging.exception('Sending magic packet to {} (on {}) failed'.format(macAddress, iface))
return False

SPECIAL_WAKEUP_DIR = Path("/etc/wake-on-lan/special-wakeup.d")

def wake(hostname: str) -> bool:
global hosts
if hostname in hosts:
special_wakeup_file = SPECIAL_WAKEUP_DIR / hostname
if special_wakeup_file.is_file() and os.access(special_wakeup_file, os.X_OK):
with subprocess.Popen(special_wakeup_file) as proc:
returncode = proc.wait()
return returncode == 0
elif hostname in hosts:
logging.info('Waking up {}...'.format(hostname))
host = hosts[hostname]
if not 'iface' in host:
Expand All @@ -89,20 +99,30 @@ def wake(hostname: str) -> bool:
logging.warning('Unknown host "{}"'.format(hostname))
return False

LDH_RE = re.compile(r"[0-9A-Za-z\-]+")

class WakeRequestHandler(socketserver.StreamRequestHandler):
def handle(self):
self.connection.settimeout(6)
client = self.client_address[0]
logging.debug('Connected {}'.format(client))
try:
while self.rfile:
hostname = self.rfile.readline().strip()
if hostname:
hostname = self.rfile.readline().decode('ascii').strip()
if not hostname:
break

# Check if nostname matches the letter-digits-hyphen rule of DNS.
# This also prevents remote code execution in case hostname is
# e.g., "../../../bin/sh".
if LDH_RE.match(hostname):
logging.info('Request WoL at "{}" from {}'.format(hostname, client))
success = wake(hostname)
self.wfile.write(b"success\n" if success else b"failed\n")
else:
break
success = False
logging.warning(f"Invalid hostname: {hostname}")
self.wfile.write(b"success\n" if success else b"failed\n")

except socket.timeout:
logging.debug('Timeout of {}'.format(client))

Expand Down

0 comments on commit 28e37dd

Please sign in to comment.