Cleanup, polish and version bumping

This commit is contained in:
Imbus 2021-07-20 18:21:21 +02:00
parent 44e63e679e
commit d70e57ea90
8 changed files with 86 additions and 389 deletions

197
Cargo.lock generated
View file

@ -22,12 +22,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
[[package]]
name = "bitflags"
version = "1.2.1"
@ -55,15 +49,6 @@ dependencies = [
"vec_map",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "dirs"
version = "3.0.2"
@ -84,21 +69,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "eff-wordlist"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226cc2588a6b769f444d06dedd29a366ea92469edea1cef7873fbd76e5b34c24"
dependencies = [
"rand 0.6.5",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "getrandom"
version = "0.2.3"
@ -133,15 +103,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "libc"
version = "0.2.97"
version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "proc-macro2"
@ -161,161 +125,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc 0.1.0",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.3",
"rand_hc 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg",
"rand_core 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.3",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.2.9"
@ -422,9 +231,7 @@ version = "0.1.0"
dependencies = [
"clap",
"dirs",
"eff-wordlist",
"hex",
"rand 0.8.4",
"serde",
"serde_json",
]

View file

@ -11,5 +11,5 @@ serde = { version = "*", features = ["derive"] }
serde_json = "*"
dirs = "*"
clap = "*"
eff-wordlist = "*"
rand = "*"
# eff-wordlist = "*"
# rand = "*"

View file

@ -1,61 +1,36 @@
TODO: Review parsing methods
Add confirm for wake all
# Waker
**An intelligent wake on lan utility to keep track of your machines**
Hosts should be pinged on listing
The output from program help flag should provide a clear idea of its use:
```
Waker 0.1.0
Imbus64
Utility for sending magic packets to configured machines.
Structs defined:
Host
- Implement methods to retrieve as macbytes/ipv4addr
- Field containing MagicPacket?
Machines
- WakeAll method
- PingAll method
MagicPacket
- Finalze parsers
USAGE:
waker [FLAGS] [OPTIONS] [MAC ADDRESSES]...
The format of a Wake-on-LAN (WOL) magic packet is defined
as a byte array with 6 bytes of value 255 (0xFF) and
16 repetitions of the target machines 48-bit (6-byte) MAC address.
FLAGS:
-a, --add Add a new host
--all Wake all configured hosts
-e, --edit Enter edit mode
-h, --help Prints help information
-l, --list List all configured entries
-p, --print-config Print contents of configuration file to stdout
-V, --version Prints version information
102 bytes
OPTIONS:
--backup <File> Backup configuration file
several macs per name
ARGS:
<MAC ADDRESSES>...
edit, delete, add
```
This project is currently in beta. Many features are implemented, but some may not work as expected.
wakemode::all
wake(bytes) method
async ping method(ip)?
const MAGIC_BYTES_HEADER: [u8; 6] = [0xFF; 6];
vec<u8> bytes = FFFFFFFFFFFF .reserve(enough) 102?
match run_mode {
Some() => Do according to some
None => Figure out what to do(set run_mode)
}
add 8 char string -> to bytes ask for name and add
add 11 char string -> if mac[2,5,8] is same char -> split by it and ask for name -> add
store json in ~/.config/waker.conf
dump-json method
export/import? append?
struct mechine {
vec of all macs
ip of machine? so we can ping it?
name
}
struct mac_list {
Vec
}
ask what do:
1. Wake
2. Wake all
3. Add
4. Edit
## Future plans:
- Further testing and polish in general.
- [ ] Include pinging functionality, so the user gets feedback on what machines are already awake (Top priority)
- [ ] Enable users to import an existing config, appending selected hosts to current config. (Second priority)
- [ ] Perhaps wrap run_mode in an Option, with None being the default when the program is invoked without CLI parameters
- [ ] Rewrite all input/blocking related code into a struct of some sort

View file

@ -1,7 +1,7 @@
use std::io;
use std::io::prelude::*;
/// Python like input method with prompt message
/// Python like input function with prompt message
pub fn input(prompt: &str) -> String {
print!("{}", prompt);
let _ = io::stdout().flush();
@ -15,11 +15,14 @@ pub fn input(prompt: &str) -> String {
input.trim().to_string()
}
/// Simple confirm dialogue
/// Simple confirm dialogue. Appends " [y/N]: " to your message, and prints feedback on your
/// choice.
pub fn confirm(message: &str) -> bool {
let answer = input(format!("{} [y/N]: ", message).as_str()).to_uppercase();
if answer == "YES" || answer == "Y" {
println!("Yes");
return true;
}
println!("No");
return false;
}

View file

@ -56,7 +56,9 @@ impl Machines {
Ok(machines)
}
fn create_skeleton_config(file: &PathBuf) -> Result<(), Box<dyn Error>> {
/// Creates file and dumps a skeleton config into it
pub fn create_skeleton_config(file: &PathBuf) -> Result<(), Box<dyn Error>> {
std::fs::File::create(&file)?;
let skel_machines = Machines::new();
skel_machines.dump(file)?;
return Ok(());

View file

@ -16,7 +16,6 @@ mod host; // The actual Host struct
mod input; // Gives us a python-like input function, as well as a simple confirm function
mod machines; // Struct that holds a vec of Hosts, as well as operations on those
mod packet; // The actual magic packet struct, with wake methods e.t.c.
// mod random_machine; // Exposes a function that generates a random Host, with random mac, ip and name // The actual host struct.
mod sanitizers; // Functions that sanitizes MAC and IP addresses
// use crate::packet::*;
@ -76,20 +75,17 @@ fn prompt_file_creation(config_path: &PathBuf) -> Option<File> {
config_path.to_str().unwrap()
);
if input::confirm(&msg) {
let newfile = std::fs::File::create(&config_path).expect(&format!(
"Could not create file: {}",
config_path.to_str().unwrap()
));
// Deserialize an empty Machines struct into the new config file.
// The parser is not equipped to handle empty or malformatted files...
// This could potentially be moved into a static method in Machines, like
// Machines::init_config_file(), which does this for us.
//
// For now, this will do.
let skeleton_machines = Machines::new();
skeleton_machines.dump(&config_path).unwrap();
return Some(newfile);
match Machines::create_skeleton_config(config_path) {
Ok(()) => { return Some(newfile); }
Err(_) => return None,
}
} else {
return None;
}
@ -169,7 +165,7 @@ fn edit_host(host: &mut Host, editmode: HostEditMode) {
let newip = input("New IP: ");
match sanitizers::sanitize(&newip, sanitizers::AddrType::IPv4) {
Some(ip) => {
host.ips[index as usize] = newip;
host.ips[index as usize] = ip;
}
None => {
println!("Could not parse IP");
@ -226,7 +222,7 @@ fn edit_host(host: &mut Host, editmode: HostEditMode) {
let newmac = input("New MAC: ");
match sanitizers::sanitize(&newmac, sanitizers::AddrType::MAC) {
Some(mac_addr) => {
host.macs[index as usize] = newmac;
host.macs[index as usize] = mac_addr;
}
None => {
println!("Could not parse MAC");
@ -345,8 +341,11 @@ fn main() -> Result<(), Box<dyn Error>> {
let file = prompt_file_creation(&config_path);
if file.is_none() {
println!("Exiting...");
return Ok(());
}
else {
println!("Config file created.");
}
return Ok(());
}
// TODO: More sophisticated error checking and logging
@ -362,12 +361,15 @@ fn main() -> Result<(), Box<dyn Error>> {
RunMode::Wake(wake_mode) => {
match wake_mode {
WakeMode::WakeAll => {
if confirm("You are about to wake all configured machines.\nContinue?") {
machines.wakeall();
for host in &machines.list {
println!("Woke {}", host.name)
}
}
}
WakeMode::WakeSome => {
if ! machines.list.is_empty() {
println!("{}", machines);
let indexes = which_indexes(
"Select which hosts to wake up (Comma separated integers): ",
@ -380,6 +382,10 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("Woke {}", host.name)
}
}
else {
println!("No machines configured yet... Try \"waker --help\" for information about usage");
}
}
_ => println!("undefined"),
}
}

View file

@ -1,7 +1,5 @@
use std::{
error::Error,
net::{Ipv4Addr, ToSocketAddrs, UdpSocket},
};
use std::{convert::TryInto, error::Error, net::{Ipv4Addr, ToSocketAddrs, UdpSocket}};
use crate::sanitizers::{self, sanitize};
// The format of a Wake-on-LAN (WOL) magic packet is defined
// as a byte array with 6 bytes of value 255 (0xFF) followed by
@ -34,73 +32,22 @@ impl MagicPacket {
return MagicPacket { bytes: magic_bytes };
}
// This is horrible code
/// Parse a MAC-string into a packet.
/// Takes both separated and unseparated
/// The MAC-string should be 17 characters long, separated by colons (i.e. XX:XX:XX:XX:XX:XX)
pub fn from_str(mac_str: &str) -> Result<MagicPacket, Box<dyn Error>> {
use hex::FromHex;
let mut mac_string = mac_str.trim().to_string();
if mac_string.len() == 17 {
for i in 0..5 {
mac_string.remove(14 - (i * 3)); // Deal with it
}
let mac_bytes = MagicPacket::parse_macstr(mac_str, ':')?;
return Ok(MagicPacket::new(&mac_bytes));
}
let mut mac_arr: [u8; 6];
let hex_vec = Vec::from_hex(mac_string)?;
unsafe {
mac_arr = std::mem::MaybeUninit::uninit().assume_init();
let src: *const u8 = &hex_vec[0];
let dst: *mut u8 = &mut mac_arr[0];
dst.copy_from_nonoverlapping(src, 6);
}
return Ok(MagicPacket::new(&mac_arr));
}
pub fn from_str2(mac_str: &str) -> Result<MagicPacket, Box<dyn Error>> {
return Ok(MagicPacket::new(&MagicPacket::parse(mac_str).unwrap()));
}
// Stolen
fn mac_to_byte(data: &str, sep: char) -> Vec<u8> {
data.split(sep)
// This method is a bit allocation heavy.
pub fn parse_macstr<S: AsRef<str>>(mac_str: S, sep: char) -> Result<Box<[u8; 6]>, Box<dyn Error>> {
let sanitized_macstr = sanitize(mac_str.as_ref(), sanitizers::AddrType::MAC).unwrap();
let bytes_split: Vec<u8> = sanitized_macstr.split(sep)
.flat_map(|x| hex::decode(x).expect("Invalid mac!"))
.collect()
}
// Parses string by position if string is 12+5 characters long (delimited by : for example)
pub fn parse<S: AsRef<str>>(mac_str: S) -> Result<Box<[u8; 6]>, Box<dyn Error>> {
use hex::FromHex;
let mut mstr: &str = mac_str.as_ref();
mstr = mstr.trim();
let mut bytes: [u8; 6] = [0, 0, 0, 0, 0, 0];
for (index, byte) in bytes.iter_mut().enumerate() {
// 0,3,6,9...
let substr = &mstr[3 * index..3 * index + 2];
*byte = <[u8; 1]>::from_hex(substr).unwrap()[0];
}
return Ok(Box::new(bytes));
}
// Loops the string and parses any valid hex
pub fn parse_harder<S: Into<String>>(mac_str: S) -> Result<Box<[u8; 6]>, Box<dyn Error>> {
let mstr: String = mac_str.into();
let mut hexdigits: String = mstr
.chars()
.filter(|c| char::is_ascii_hexdigit(c))
.collect();
let mut bytes: [u8; 6] = [0; 6];
if hexdigits.len() >= 12 {
hexdigits.truncate(12); // May not be needed, since bytes is only 6 bytes, and from_hex might be smart enough to realize...
//let bytes: [u8; 6] = hex::FromHex::from_hex(hexdigits)?;
bytes = hex::FromHex::from_hex(hexdigits)?;
}
return Ok(Box::new(bytes));
let arr: [u8; 6] = bytes_split.try_into().unwrap();
Ok(Box::new(arr))
}
/// Send packet to/from specific address/interface
@ -118,11 +65,6 @@ impl MagicPacket {
(Ipv4Addr::new(0x0, 0x0, 0x0, 0x0), 0),
)
}
/// Return raw bytes, ready to be broadcasted
pub fn get_bytes(&self) -> &[u8; 102] {
&self.bytes
}
}
#[cfg(test)]
@ -142,7 +84,7 @@ mod tests {
#[test]
fn magic_packet_from_new() {
let packet3 = MagicPacket::from_str2("10:10:10:10:10:10").unwrap();
let packet3 = MagicPacket::from_str("10:10:10:10:10:10").unwrap();
//let vec: [u8; 102] = [0xFF; 102];
let slice = &packet3.bytes[packet3.bytes.len() - 6..];
for a in slice {
@ -155,15 +97,9 @@ mod tests {
#[test]
fn test_parse() {
let mp = MagicPacket::parse("ff:ff:ff:ff:ff:ff").unwrap();
let mp = MagicPacket::parse_macstr("ff:ff:ff:ff:ff:ff", ':').unwrap();
assert_eq!([0xFF; 6], *mp);
let mp2 = MagicPacket::parse("10:10:10:10:10:10").unwrap();
let mp2 = MagicPacket::parse_macstr("10:10:10:10:10:10", ':').unwrap();
assert_eq!([0x10; 6], *mp2);
}
#[test]
fn parse_harder_test() {
let mac = MagicPacket::parse_harder("10:10:10:10:10:10").unwrap();
assert_eq!([0x10; 6], *mac);
}
}

View file

@ -1,32 +0,0 @@
{
"list": [
{
"name": "Name",
"macs": [
"E9:A3:29:73:FE:D2"
],
"ips": []
},
{
"name": "i",
"macs": [
"7D:E1:AC:94:29:79"
],
"ips": []
},
{
"name": "PartyMaskinen",
"macs": [
"96:F8:FF:30:4C:EE"
],
"ips": []
},
{
"name": "Kalle",
"macs": [
"FF:FF:FF:FF:FF:FF"
],
"ips": []
}
]
}