Skip to content

Commit d253efc

Browse files
authored
Tracing crashes (#52)
* Key can be converted from base16 string; other debugging improvements * Format and update Cargo.lock * Remove unused code * Rename KernelNotSupported to PlatformNotSupported * Revert KernelNotSupported * Bump version
1 parent a118bb7 commit d253efc

File tree

8 files changed

+79
-68
lines changed

8 files changed

+79
-68
lines changed

Cargo.lock

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "defguard_wireguard_rs"
3-
version = "0.4.0"
3+
version = "0.4.1"
44
edition = "2021"
55
description = "A unified multi-platform high-level API for managing WireGuard interfaces"
66
license = "Apache-2.0"

examples/userspace.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#[cfg(target_os = "mac_os")]
2-
use defguard_wireguard_rs::WireguardApiUserspace;
31
use defguard_wireguard_rs::{host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration};
2+
#[cfg(target_os = "macos")]
3+
use defguard_wireguard_rs::{WireguardApiUserspace, WireguardInterfaceApi};
44
use std::{
55
io::{stdin, stdout, Read, Write},
66
net::SocketAddr,
@@ -15,7 +15,7 @@ fn pause() {
1515
stdin().read_exact(&mut [0]).unwrap();
1616
}
1717

18-
#[cfg(target_os = "mac_os")]
18+
#[cfg(target_os = "macos")]
1919
fn main() -> Result<(), Box<dyn std::error::Error>> {
2020
// Setup API struct for interface management
2121
let ifname: String = if cfg!(target_os = "linux") || cfg!(target_os = "freebsd") {
@@ -35,7 +35,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
3535
let peer_key: Key = key.as_ref().try_into().unwrap();
3636
let mut peer = Peer::new(peer_key.clone());
3737

38-
log::info!("endpoint");
38+
println!("endpoint");
3939
// Your WireGuard server endpoint which peer connects too
4040
let endpoint: SocketAddr = "10.20.30.40:55001".parse().unwrap();
4141
// Peer endpoint and interval
@@ -73,5 +73,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
7373
Ok(())
7474
}
7575

76-
#[cfg(not(mac_os))]
76+
#[cfg(not(target_os = "macos"))]
7777
fn main() {}

src/bsd/ifconfig.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ impl IfReq {
5050
.for_each(|(i, b)| ifr_name[i] = b);
5151

5252
// First, try to load a kernel module for this type of network interface.
53-
let mod_name = format!("if_{if_name}");
53+
// Omit digits at the end of interface name, e.g. "wg0" -> "if_wg".
54+
let index = if_name
55+
.find(|c: char| c.is_ascii_digit())
56+
.unwrap_or(if_name.len());
57+
let mod_name = format!("if_{}", &if_name[0..index]);
5458
unsafe {
5559
// Ignore the return value for the time being.
5660
// Do the cast because `c_char` differs across platforms.

src/bsd/wgio.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,17 @@ impl WgDataIo {
6262
let socket = create_socket(AddressFamily::Unix).map_err(IoError::ReadIo)?;
6363
unsafe {
6464
// First do ioctl with empty `wg_data` to obtain buffer size.
65-
read_wireguard_data(socket.as_raw_fd(), self).map_err(IoError::ReadIo)?;
65+
if let Err(err) = read_wireguard_data(socket.as_raw_fd(), self) {
66+
error!("WgDataIo first read error {err}");
67+
return Err(IoError::ReadIo(err));
68+
}
6669
// Allocate buffer.
6770
self.alloc_data()?;
6871
// Second call to ioctl with allocated buffer.
69-
read_wireguard_data(socket.as_raw_fd(), self).map_err(IoError::ReadIo)?;
72+
if let Err(err) = read_wireguard_data(socket.as_raw_fd(), self) {
73+
error!("WgDataIo second read error {err}");
74+
return Err(IoError::ReadIo(err));
75+
}
7076
}
7177

7278
Ok(())
@@ -75,7 +81,10 @@ impl WgDataIo {
7581
pub(super) fn write_data(&mut self) -> Result<(), IoError> {
7682
let socket = create_socket(AddressFamily::Unix).map_err(IoError::WriteIo)?;
7783
unsafe {
78-
write_wireguard_data(socket.as_raw_fd(), self).map_err(IoError::WriteIo)?;
84+
if let Err(err) = write_wireguard_data(socket.as_raw_fd(), self) {
85+
error!("WgDataIo write error {err}");
86+
return Err(IoError::WriteIo(err));
87+
}
7988
}
8089

8190
Ok(())

src/key.rs

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Public key utilities
22
33
use std::{
4-
error, fmt,
4+
fmt,
55
hash::{Hash, Hasher},
66
str::FromStr,
77
};
@@ -11,29 +11,21 @@ use serde::{Deserialize, Serialize};
1111

1212
const KEY_LENGTH: usize = 32;
1313

14+
/// Returns value of hex digit, if possible.
15+
fn hex_value(char: u8) -> Option<u8> {
16+
match char {
17+
b'A'..=b'F' => Some(char - b'A' + 10),
18+
b'a'..=b'f' => Some(char - b'a' + 10),
19+
b'0'..=b'9' => Some(char - b'0'),
20+
_ => None,
21+
}
22+
}
23+
1424
/// WireGuard key representation in binary form.
1525
#[derive(Clone, Default, Serialize, Deserialize)]
26+
#[serde(try_from = "&str")]
1627
pub struct Key([u8; KEY_LENGTH]);
1728

18-
#[derive(Debug)]
19-
pub enum KeyError {
20-
InvalidCharacter(u8),
21-
InvalidStringLength(usize),
22-
}
23-
24-
impl error::Error for KeyError {}
25-
26-
impl fmt::Display for KeyError {
27-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28-
match self {
29-
Self::InvalidCharacter(char) => {
30-
write!(f, "Invalid character {char}")
31-
}
32-
Self::InvalidStringLength(length) => write!(f, "Invalid string length {length}"),
33-
}
34-
}
35-
}
36-
3729
impl Key {
3830
/// Create a new key from buffer.
3931
#[must_use]
@@ -71,28 +63,22 @@ impl Key {
7163
/// Converts a text string of hexadecimal digits to `Key`.
7264
///
7365
/// # Errors
74-
/// Will return `KeyError` if text string has wrong length,
66+
/// Will return `DecodeError` if text string has wrong length,
7567
/// or contains an invalid character.
76-
pub fn decode<T: AsRef<[u8]>>(hex: T) -> Result<Self, KeyError> {
68+
pub fn decode<T: AsRef<[u8]>>(hex: T) -> Result<Self, DecodeError> {
7769
let hex = hex.as_ref();
78-
let length = hex.len();
79-
if length != 64 {
80-
return Err(KeyError::InvalidStringLength(length));
70+
if hex.len() != KEY_LENGTH * 2 {
71+
return Err(DecodeError::InvalidLength);
8172
}
8273

83-
let hex_value = |char: u8| -> Result<u8, KeyError> {
84-
match char {
85-
b'A'..=b'F' => Ok(char - b'A' + 10),
86-
b'a'..=b'f' => Ok(char - b'a' + 10),
87-
b'0'..=b'9' => Ok(char - b'0'),
88-
_ => Err(KeyError::InvalidCharacter(char)),
89-
}
90-
};
91-
9274
let mut key = [0; KEY_LENGTH];
9375
for (index, chunk) in hex.chunks(2).enumerate() {
94-
let msd = hex_value(chunk[0])?;
95-
let lsd = hex_value(chunk[1])?;
76+
let Some(msd) = hex_value(chunk[0]) else {
77+
return Err(DecodeError::InvalidByte(index, chunk[0]));
78+
};
79+
let Some(lsd) = hex_value(chunk[1]) else {
80+
return Err(DecodeError::InvalidByte(index, chunk[1]));
81+
};
9682
key[index] = msd << 4 | lsd;
9783
}
9884
Ok(Self(key))
@@ -102,13 +88,20 @@ impl Key {
10288
impl TryFrom<&str> for Key {
10389
type Error = DecodeError;
10490

91+
/// Try to decode `Key` from base16 or base64 encoded string.
10592
fn try_from(value: &str) -> Result<Self, Self::Error> {
106-
let v = BASE64_STANDARD.decode(value)?;
107-
if v.len() == KEY_LENGTH {
108-
let buf = v.try_into().map_err(|_| Self::Error::InvalidLength)?;
109-
Ok(Self::new(buf))
93+
if value.len() == KEY_LENGTH * 2 {
94+
// Try base16
95+
Key::decode(value)
11096
} else {
111-
Err(Self::Error::InvalidLength)
97+
// Try base64
98+
let v = BASE64_STANDARD.decode(value)?;
99+
if v.len() == KEY_LENGTH {
100+
let buf = v.try_into().map_err(|_| Self::Error::InvalidLength)?;
101+
Ok(Self::new(buf))
102+
} else {
103+
Err(Self::Error::InvalidLength)
104+
}
112105
}
113106
}
114107
}

src/wgapi.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ impl WGApi {
4545
#[cfg(target_os = "freebsd")]
4646
return Ok(Self(Box::new(WireguardApiFreebsd::new(ifname))));
4747

48-
#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
48+
#[cfg(not(any(
49+
target_os = "linux",
50+
target_os = "freebsd",
51+
target_os = "macos",
52+
target_os = "windows"
53+
)))]
4954
Err(WireguardInterfaceError::KernelNotSupported)
5055
}
5156
}

src/wgapi_freebsd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99

1010
/// Manages interfaces created with FreeBSD kernel WireGuard module.
1111
///
12-
/// Requires FreeBSD version 14+.
12+
/// Requires FreeBSD version 13+.
1313
#[derive(Clone)]
1414
pub struct WireguardApiFreebsd {
1515
ifname: String,

0 commit comments

Comments
 (0)