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