wol-rs
A lightweight Rust crate and CLI for sending Wake-on-LAN magic packets to power on network devices over UDP broadcast.
Repository Health
Technical Analysis
wol-rs is a lightweight Rust crate for sending Wake-on-LAN magic packets, letting you power on network devices — servers, NAS boxes, desktops — from code or the command line. The library exposes a single send_wol function alongside a MacAddr type built on the eui48 crate, which accepts MAC addresses in a wide range of formats: colon-separated, dash-separated, dotted, and even bare hex strings.
Under the hood, send_wol constructs the standard 102-byte magic packet (six 0xFF bytes followed by the target MAC address repeated 16 times) and broadcasts it over a UDP socket, with configurable bind and broadcast addresses on both IPv4 and IPv6. An optional bin feature compiles a wol CLI binary — powered by clap — so the same functionality is available as a standalone command for scripts and homelab automation without writing any Rust.
What You Get
- A
send_wolfunction that builds and broadcasts a standards-compliant 102-byte WoL magic packet over UDP - A
MacAddrtype (viaeui48) that parses colon-, dash-, dotted-, and hex-prefixed MAC address strings - Configurable bind and broadcast addresses with mixed IPv4/IPv6 support
- An optional
wolCLI binary (via thebincargo feature) for waking devices without writing Rust
Common Use Cases
- Waking a home server or NAS before running a backup or media job
- Powering on lab or CI hardware from a deployment script
- Building a self-hosted dashboard button that wakes a machine over LAN
- Scripting device wake-up as part of a homelab automation pipeline
Under The Hood
Architecture
The crate is intentionally flat: src/lib.rs defines the public surface (MacAddr, MacAddrError, send_wol) in a single module, and the optional src/main.rs binary is a thin clap-based wrapper that parses CLI args and calls straight into send_wol. send_wol does one thing — build the 102-byte magic packet and broadcast it over a UdpSocket — with no internal layering, abstraction, or state to reason about; the entire library’s behavior can be understood from one file, and nothing would break downstream if the core function’s signature changed since the binary is its only consumer.
Tech Stack
Built on Rust 2021 edition with a minimal dependency set: eui48 (with the disp_hexstring feature) handles MAC address parsing and formatting, while clap 4.5 (derive macros) is pulled in only when the optional bin feature is enabled, keeping the pure-library build dependency-light. Tests use rstest for parameterized cases. There is no async runtime, database, or web framework involved — it is a pure standard-library std::net::UdpSocket wrapper, distributed via crates.io and GitHub Releases with a [profile.release] strip = true for smaller binaries.
Code Quality
A single #[cfg(test)] module in lib.rs uses rstest to parameterize MacAddr::from_str across colon-, dash-, dotted-, and hex-prefixed address formats, giving reasonable coverage of the one function most likely to receive malformed user input. Error handling is explicit and typed: MacAddrError implements Display/Debug rather than panicking, though the CLI binary itself calls .unwrap() on parse results, so malformed input there exits via a Rust panic rather than a clean error message. GitHub Actions runs a dedicated rust-clippy workflow alongside build/PR checks, so lint enforcement is wired into CI even though the crate’s surface area is small.
API Design
The public API is about as low-friction as a networking crate gets: one function (send_wol) and one type (MacAddr) cover the entire use case, with Option<IpAddr> parameters defaulting to sane broadcast/bind addresses so callers can omit them entirely. Accepting a wide range of MAC address string formats (colon, dash, dotted, hex-prefixed) via FromStr removes a common source of caller friction. The tradeoff is that the API is narrow by design — there is no builder, no async variant, and no packet customization beyond addressing — which is appropriate for its single-purpose scope but leaves no room to extend without a breaking change.