mirror of
https://github.com/Noratrieb/wakeonlan.git
synced 2026-01-14 08:45:02 +01:00
working thing maybe thats simple and good and not UB
This commit is contained in:
commit
563ba7c519
4 changed files with 106 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/target
|
||||||
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wakeonlan"
|
||||||
|
version = "0.1.0"
|
||||||
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "wakeonlan"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
90
src/main.rs
Normal file
90
src/main.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
// adapted from https://github.com/TeemuRemes/wake-on-lan-rust
|
||||||
|
|
||||||
|
use std::net::{Ipv4Addr, ToSocketAddrs, UdpSocket};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mac_addr = std::env::args()
|
||||||
|
.nth(1)
|
||||||
|
.expect("first arg must be mac address");
|
||||||
|
let parts = mac_addr
|
||||||
|
.split(":")
|
||||||
|
.map(|part| u8::from_str_radix(part, 16).expect("invalid mac address"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.as_slice()
|
||||||
|
.try_into()
|
||||||
|
.expect("invalid mac address");
|
||||||
|
|
||||||
|
let magic_packet = MagicPacket::new(&parts);
|
||||||
|
magic_packet.send().expect("failed to send packet");
|
||||||
|
|
||||||
|
println!("Done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A Wake-on-LAN magic packet.
|
||||||
|
pub struct MagicPacket {
|
||||||
|
magic_bytes: [u8; 102],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MagicPacket {
|
||||||
|
/// Creates a new `MagicPacket` intended for `mac_address` (but doesn't send it yet).
|
||||||
|
pub fn new(mac_address: &[u8; 6]) -> MagicPacket {
|
||||||
|
let mut magic_bytes: [u8; 102] = [0; 102];
|
||||||
|
|
||||||
|
// We use `unsafe` code to skip unnecessary array initialization and bounds checking.
|
||||||
|
unsafe {
|
||||||
|
// Copy the header to the beginning.
|
||||||
|
let mut src: *const u8 = &MAGIC_BYTES_HEADER[0];
|
||||||
|
let mut dst: *mut u8 = &mut magic_bytes[0];
|
||||||
|
dst.copy_from_nonoverlapping(src, 6);
|
||||||
|
|
||||||
|
// Copy the MAC address once from the argument.
|
||||||
|
src = &mac_address[0];
|
||||||
|
dst = dst.offset(6);
|
||||||
|
dst.copy_from_nonoverlapping(src, 6);
|
||||||
|
|
||||||
|
// Repeat the MAC.
|
||||||
|
let src: *const u8 = dst; // src points to magic_bytes[6]
|
||||||
|
dst = dst.offset(6);
|
||||||
|
dst.copy_from_nonoverlapping(src, 6);
|
||||||
|
|
||||||
|
dst = dst.offset(6);
|
||||||
|
dst.copy_from_nonoverlapping(src, 12);
|
||||||
|
|
||||||
|
dst = dst.offset(12);
|
||||||
|
dst.copy_from_nonoverlapping(src, 24);
|
||||||
|
|
||||||
|
dst = dst.offset(24);
|
||||||
|
dst.copy_from_nonoverlapping(src, 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
MagicPacket { magic_bytes }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends the magic packet via UDP to the broadcast address `255.255.255.255:9`.
|
||||||
|
/// Lets the operating system choose the source port and network interface.
|
||||||
|
pub fn send(&self) -> std::io::Result<()> {
|
||||||
|
self.send_to(
|
||||||
|
(Ipv4Addr::new(255, 255, 255, 255), 9),
|
||||||
|
(Ipv4Addr::new(0, 0, 0, 0), 0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends the magic packet via UDP to/from an IP address and port number of your choosing.
|
||||||
|
pub fn send_to<A: ToSocketAddrs>(&self, to_addr: A, from_addr: A) -> std::io::Result<()> {
|
||||||
|
let socket = UdpSocket::bind(from_addr)?;
|
||||||
|
socket.set_broadcast(true)?;
|
||||||
|
socket.send_to(&self.magic_bytes, to_addr)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the magic packet's payload (6 repetitions of `0xFF` and 16 repetitions of the
|
||||||
|
/// target device's MAC address). Send these bytes yourself over the network if you want to do
|
||||||
|
/// something more advanced (like reuse a single UDP socket when sending a large number of
|
||||||
|
/// magic packets).
|
||||||
|
pub fn magic_bytes(&self) -> &[u8; 102] {
|
||||||
|
&self.magic_bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MAGIC_BYTES_HEADER: [u8; 6] = [0xFF; 6];
|
||||||
Loading…
Add table
Add a link
Reference in a new issue