wireguard_tools_rs/
lib.rs1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4#![allow(dead_code)]
5
6use sodiumoxide::crypto::box_::curve25519xsalsa20poly1305 as crypto;
7
8use std::io::{Result, ErrorKind};
9use std::io::Error;
10use std::ffi::CStr;
11use std::ffi::CString;
12use std::ptr::NonNull;
13use std::marker::PhantomData;
14use std::time::{SystemTime, UNIX_EPOCH, Duration};
15use std::net::{SocketAddr, IpAddr};
16
17#[cfg(test)]
18mod tests;
19
20mod sys {
21 pub const WGDEVICE_REPLACE_PEERS: u32 = 1 << 0;
22 pub const WGDEVICE_HAS_PRIVATE_KEY: u32 = 1 << 1;
23 pub const WGDEVICE_HAS_PUBLIC_KEY: u32 = 1 << 2;
24 pub const WGDEVICE_HAS_LISTEN_PORT: u32 = 1 << 3;
25 pub const WGDEVICE_HAS_FWMARK: u32 = 1 << 4;
26
27 pub const WGPEER_REMOVE_ME: u32 = 1 << 0;
28 pub const WGPEER_REPLACE_ALLOWEDIPS: u32 = 1 << 1;
29 pub const WGPEER_HAS_PUBLIC_KEY: u32 = 1 << 2;
30 pub const WGPEER_HAS_PRESHARED_KEY: u32 = 1 << 3;
31 pub const WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL: u32 = 1 << 4;
32
33 include!(concat!(env!("OUT_DIR"), "/sys.rs"));
34}
35
36pub struct Device(NonNull<sys::wg_device>);
37pub struct Peer<'a>(NonNull<sys::wg_peer>, PhantomData<&'a Device>);
38pub struct AllowedIp<'a>(NonNull<sys::wg_allowedip>, PhantomData<&'a Peer<'a>>);
39
40pub use crypto::SecretKey;
41pub use crypto::PublicKey;
42pub struct PresharedKey(sys::wg_key);
43
44impl Device {
45 fn inner(&self) -> &sys::wg_device {
46 unsafe { self.0.as_ref() }
47 }
48
49 fn inner_mut(&mut self) -> &mut sys::wg_device {
50 unsafe { self.0.as_mut() }
51 }
52
53 pub fn name(&self) -> Result<String> {
54 let n = self.inner().name;
55 let n: &[u8; 16] = unsafe { std::mem::transmute(&n) };
56 let len = n.iter().position(|c| *c == b'\0').unwrap_or(std::mem::size_of_val(&n));
57
58 if let Ok(n) = CString::new(&n[..len]) {
59 if let Ok(n) = n.into_string() {
60 return Ok(n)
61 }
62 }
63 Err(ErrorKind::InvalidData.into())
64 }
65
66 pub fn set_name<S: Into<CString>>(&mut self, name: S) -> Result<()> {
67 let name = name.into();
68 let bytes = name.as_bytes_with_nul();
69
70 if bytes.len() > 1 { return Err(ErrorKind::InvalidInput.into())
72 }
73
74 let bytes = unsafe { &*(&bytes[..] as *const [u8] as *const [i8]) };
75 self.inner_mut().name[..].clone_from_slice(bytes);
76 Ok(())
77 }
78
79 fn has_flag(&self, test_flag: u32) -> bool {
80 self.inner().flags & test_flag == test_flag
81 }
82
83 fn add_flag(&mut self, flag: u32) {
84 self.inner_mut().flags |= flag;
85 }
86
87 fn remove_flag(&mut self, flag: u32) {
88 self.inner_mut().flags &= !flag;
89 }
90
91 pub fn public_key(&self) -> Option<PublicKey> {
92 if !self.has_flag(sys::WGDEVICE_HAS_PUBLIC_KEY) {
93 return None;
94 }
95 Some(PublicKey(self.inner().public_key))
96 }
97
98 pub fn secret_key(&self) -> Option<SecretKey> {
99 if !self.has_flag(sys::WGDEVICE_HAS_PRIVATE_KEY) {
100 return None;
101 }
102 Some(SecretKey(self.inner().private_key))
103 }
104
105 pub fn set_secret_key(&mut self, secret_key: Option<SecretKey>) {
106 if let Some(key) = secret_key {
107 self.inner_mut().private_key = key.0;
108 self.add_flag(sys::WGDEVICE_HAS_PRIVATE_KEY)
109 } else {
110 self.remove_flag(sys::WGDEVICE_HAS_PRIVATE_KEY)
111 }
112 }
113
114 pub fn listen_port(&self) -> Option<u16> {
115 if !self.has_flag(sys::WGDEVICE_HAS_LISTEN_PORT) {
116 return None;
117 }
118 Some(self.inner().listen_port)
119 }
120
121 pub fn set_listen_port(&mut self, listen_port: Option<u16>) {
122 if let Some(listen_port) = listen_port {
123 self.inner_mut().listen_port = listen_port;
124 self.add_flag(sys::WGDEVICE_HAS_LISTEN_PORT)
125 } else {
126 self.remove_flag(sys::WGDEVICE_HAS_LISTEN_PORT)
127 }
128 }
129
130 pub fn fwmark(&self) -> Option<u32> {
131 if !self.has_flag(sys::WGDEVICE_HAS_FWMARK) {
132 return None;
133 }
134 Some(self.inner().fwmark)
135 }
136
137 pub fn set_fwmark(&mut self, fwmark: Option<u32>) {
138 if let Some(fwmark) = fwmark {
139 self.inner_mut().fwmark = fwmark;
140 self.add_flag(sys::WGDEVICE_HAS_FWMARK)
141 } else {
142 self.remove_flag(sys::WGDEVICE_HAS_FWMARK)
143 }
144 }
145
146 pub fn ifindex(&self) -> u32 {
147 self.inner().ifindex
148 }
149
150 pub fn set_ifindex(&mut self, ifindex: u32) {
151 self.inner_mut().ifindex = ifindex;
152 }
153
154 pub fn devices() -> Result<Vec<Device>> {
155 let mut devices = vec![];
156
157 let device_names = unsafe { sys::wg_list_device_names() };
158 let mut ptr = device_names;
159 assert!(!ptr.is_null());
160
161 let mut len = 1;
162 while len > 0 {
163 let name = unsafe { CStr::from_ptr(ptr) };
164 len = name.to_bytes().len();
165 ptr = unsafe { ptr.add(len + 1) }; if len > 0 {
168 devices.push(Self::get(name.to_bytes())?);
169 }
170 }
171
172 unsafe {
173 libc::free(device_names as *mut _);
174 }
175
176 return Ok(devices)
177 }
178
179 pub fn get<S: Into<Vec<u8>>>(device_name: S) -> Result<Device> {
180 if let Ok(device_name) = CString::new(device_name) {
181 let mut dev: *mut sys::wg_device = std::ptr::null_mut();
182
183 let res = unsafe {
184 sys::wg_get_device(&mut dev, device_name.as_ptr())
185 };
186 dbg!(res, device_name);
187
188 if let Some(dev) = NonNull::new(dev) {
189 let dev = Device(dev);
190 Ok(dev)
191 } else {
192 Err(Error::from_raw_os_error(res))
193 }
194 } else {
195 Err(ErrorKind::InvalidInput.into())
196
197 }
198 }
199
200 pub fn apply(&self) -> Result<()> {
201 let res = unsafe {
202 sys::wg_set_device(self.0.as_ptr())
203 };
204
205 if res < 0 {
206 return Err(Error::from_raw_os_error(res));
207 }
208
209 Ok(())
210 }
211
212 pub fn add<S: Into<Vec<u8>>>(device_name: S) -> Result<()> {
213 if let Ok(device_name) = CString::new(device_name) {
214 let res = unsafe {
215 sys::wg_add_device(device_name.as_ptr())
216 };
217
218 if res < 0 {
219 return Err(Error::from_raw_os_error(res));
220 }
221
222 Ok(())
223 } else {
224 Err(ErrorKind::InvalidInput.into())
225 }
226 }
227
228 pub fn del(&self) -> Result<()> {
229 let res = unsafe {
230 sys::wg_del_device(self.inner().name.as_ptr())
231 };
232
233 if res < 0 {
234 return Err(Error::from_raw_os_error(res));
235 }
236
237 Ok(())
238 }
239
240 pub fn get_peer<'a>(&'a self, peer: &PublicKey) -> Option<Peer<'a>> {
241 self.peers().into_iter().find(|p| p.public_key().as_ref() == Some(peer))
242 }
243
244 pub fn peers<'a>(&'a self) -> Vec<Peer<'a>> {
245 let first = self.inner().first_peer;
246 let mut it = NonNull::new(first).map(|p| Peer(p, PhantomData));
247
248 let mut res = vec![];
249 while let Some(peer) = it {
250 it = peer.next_peer();
251 res.push(peer);
252 }
253
254 res
255 }
256
257 pub fn next_handshake(&self) -> Option<Duration> {
258 self.peers().iter().filter_map(|p| p.next_handshake()).min()
259 }
260}
261
262impl Drop for Device {
263 fn drop(&mut self) {
264 unsafe {
265 sys::wg_free_device(self.0.as_ptr())
266 }
267 }
268}
269
270impl std::fmt::Debug for Device {
271 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
272 f.debug_struct("WgDevice")
273 .field("flags", &self.inner().flags)
274 .field("name", &self.name())
275 .field("ifindex", &self.ifindex())
276 .field("public_key", &self.public_key())
277 .field("secret_key", &self.secret_key())
278 .field("fwmark", &self.fwmark())
279 .field("listen_port", &self.listen_port())
280 .field("peers", &self.peers())
281 .finish()
282 }}
283
284impl<'a> std::fmt::Debug for Peer<'a> {
285 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286 f.debug_struct("WgPeer")
287 .field("flags", &self.inner().flags)
288 .field("public_key", &self.public_key())
289 .field("preshared_key", &self.preshared_key())
290 .field("endpoint", &self.endpoint())
291 .field("last_handshake_time", &self.last_handshake_time())
292 .field("rx_bytes", &self.rx_bytes())
293 .field("tx_bytes", &self.tx_bytes())
294 .field("persistent_keepalive_interval", &self.persistent_keepalive_interval())
295 .finish()
296 }
314}
315
316impl std::fmt::Debug for PresharedKey {
317 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
318 write!(f, "PresharedKey(omitted)")
319 }
320}
321
322impl<'a> Peer<'a> {
323 fn inner(&self) -> &sys::wg_peer {
324 unsafe { self.0.as_ref() }
325 }
326
327 fn inner_mut(&mut self) -> &mut sys::wg_peer {
328 unsafe { self.0.as_mut() }
329 }
330
331 pub fn last_handshake_time(&self) -> Option<SystemTime> {
332 let time = self.inner().last_handshake_time;
333 if time.tv_sec == 0 && time.tv_nsec == 0 {
334 return None;
335 }
336
337 let time = Duration::from_secs(time.tv_sec as u64) + Duration::from_nanos(time.tv_nsec as u64);
338 Some(UNIX_EPOCH + time)
339 }
340
341 fn has_flag(&self, test_flag: u32) -> bool {
342 self.inner().flags & test_flag == test_flag
343 }
344
345 fn next_handshake(&self) -> Option<Duration> {
346 if let Some(hs) = self.last_handshake_time() {
347 if let Some(keep_alive) = self.persistent_keepalive_interval() {
348 return (hs + keep_alive).duration_since(SystemTime::now()).ok()
349 }
350 }
351 None
352 }
353
354 fn add_flag(&mut self, flag: u32) {
355 self.inner_mut().flags |= flag;
356 }
357
358 fn remove_flag(&mut self, flag: u32) {
359 self.inner_mut().flags &= !flag;
360 }
361
362 pub fn persistent_keepalive_interval(&self) -> Option<Duration> {
363 if !self.has_flag(sys::WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) {
364 return None;
365 }
366 let secs = self.inner().persistent_keepalive_interval;
367 Some(Duration::from_secs(secs as u64))
368 }
369
370 pub fn set_persistent_keepalive_interval(&mut self, persistent_keepalive_interval: Option<Duration>) {
371 if let Some(interval) = persistent_keepalive_interval {
372 self.inner_mut().persistent_keepalive_interval = interval.as_secs() as u16;
373 self.add_flag(sys::WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
374 } else {
375 self.remove_flag(sys::WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
376 }
377 }
378
379 pub fn preshared_key(&self) -> Option<PresharedKey> {
380 if !self.has_flag(sys::WGPEER_HAS_PRESHARED_KEY) {
381 return None;
382 }
383 let key = self.inner().preshared_key;
384 Some(PresharedKey(key))
385 }
386
387 pub fn set_preshared_key(&mut self, preshared_key: Option<PresharedKey>) {
388 if let Some(psk) = preshared_key {
389 self.inner_mut().preshared_key[..].copy_from_slice(&psk.0[..]);
390 self.add_flag(sys::WGPEER_HAS_PRESHARED_KEY)
391 } else {
392 self.remove_flag(sys::WGPEER_HAS_PRESHARED_KEY)
393 }
394 }
395
396 pub fn public_key(&self) -> Option<PublicKey> {
397 if !self.has_flag(sys::WGPEER_HAS_PUBLIC_KEY) {
398 return None;
399 }
400 let key = self.inner().public_key;
401 Some(PublicKey(key))
402 }
403
404 pub fn set_public_key(&mut self, public_key: Option<PublicKey>) {
405 if let Some(key) = public_key {
406 self.inner_mut().public_key[..].copy_from_slice(&key.0[..]);
407 self.add_flag(sys::WGPEER_HAS_PUBLIC_KEY)
408 } else {
409 self.remove_flag(sys::WGPEER_HAS_PUBLIC_KEY)
410 }
411 }
412
413 pub fn next_peer(&self) -> Option<Peer<'a>> {
414 NonNull::new(self.inner().next_peer).map(|p| Peer(p, PhantomData))
415 }
416
417 pub fn rx_bytes(&self) -> u64 {
418 self.inner().rx_bytes
419 }
420
421 pub fn tx_bytes(&self) -> u64 {
422 self.inner().tx_bytes
423 }
424
425 pub fn remove_me(&mut self) {
426 self.add_flag(sys::WGPEER_REMOVE_ME)
427 }
428
429 pub fn keep_me(&mut self) {
430 self.remove_flag(sys::WGPEER_REMOVE_ME)
431 }
432
433 pub fn endpoint(&self) -> Option<SocketAddr> {
434 use nix::sys::socket::SockAddr;
435
436 let addr = self.inner().endpoint;
437 let ptr = &addr as *const sys::wg_peer__bindgen_ty_1 as *const libc::sockaddr;
438 let addr = unsafe { SockAddr::from_libc_sockaddr(ptr) };
439
440 if let Some(SockAddr::Inet(addr)) = addr {
441 return match addr.to_std() {
442 SocketAddr::V4(addr4) if addr4.ip().is_unspecified() && addr4.port() == 0 => None,
443 SocketAddr::V6(addr6) if addr6.ip().is_unspecified() && addr6.port() == 0 => None,
444 addr => Some(addr)
445 }
446 }
447 None
448 }
449
450 pub fn set_endpoint(&mut self, endpoint: &SocketAddr) {
451 use nix::sys::socket::InetAddr;
452 let endpoint = InetAddr::from_std(endpoint);
453
454 match endpoint {
455 InetAddr::V4(addr4) => unsafe { self.inner_mut().endpoint.addr4 = std::mem::transmute(addr4) }
456 InetAddr::V6(addr6) => unsafe { self.inner_mut().endpoint.addr6 = std::mem::transmute(addr6) }
457 }
458 }
459
460 pub fn allowed_ips(&self) -> Vec<AllowedIp<'a>> {
461 dbg!("allowed_ips");
462 let first = self.inner().first_allowedip;
463 dbg!("allowed_ips1");
464 dbg!(&first);
465 let mut it = NonNull::new(first).map(|ip| AllowedIp(ip, PhantomData));
466 let mut res = vec![];
469 while let Some(addr) = it {
470 it = addr.next_allowedip();
471 res.push(addr);
472 }
473
474 res
475 }
476
477 pub fn first_allowedip(&self) -> Option<AllowedIp<'a>> {
478 unsafe { AllowedIp::from_ptr(self.inner().first_allowedip) }
479 }
480
481 pub fn add_allowedip(&mut self, addr: IpAddr, cidr: u8) {
482 let allowedip = Box::new(unsafe { std::mem::zeroed() });
483 let allowedip = unsafe { NonNull::new_unchecked(Box::into_raw(allowedip)) };
484
485 let mut allowedip = unsafe { AllowedIp::from_non_null(allowedip) };
486 allowedip.set_ip(&addr);
487 allowedip.set_cidr(cidr);
488 allowedip.set_next_allowedip(self.first_allowedip());
489
490 self.inner_mut().first_allowedip = allowedip.0.as_ptr();
491 }
492}
493
494unsafe impl Sync for Device {}
496unsafe impl Send for Device {}
497
498unsafe impl<'a> Sync for Peer<'a> {}
500unsafe impl<'a> Send for Peer<'a> {}
501
502impl<'a> AllowedIp<'a> {
503 fn inner(&self) -> &sys::wg_allowedip {
504 unsafe { self.0.as_ref() }
505 }
506
507 fn inner_mut(&mut self) -> &mut sys::wg_allowedip {
508 unsafe { self.0.as_mut() }
509 }
510
511 pub unsafe fn from_ptr(ptr: *mut sys::wg_allowedip) -> Option<AllowedIp<'a>> {
512 let allowedip = NonNull::new(ptr);
513 allowedip.map(|ip| AllowedIp::from_non_null(ip))
514 }
515
516 pub unsafe fn from_non_null(allowedip: NonNull<sys::wg_allowedip>) -> AllowedIp<'a> {
517 AllowedIp(allowedip, PhantomData)
518 }
519
520 pub fn next_allowedip(&self) -> Option<AllowedIp<'a>> {
521 NonNull::new(self.inner().next_allowedip).map(|ip| AllowedIp(ip, PhantomData))
522 }
523
524 pub fn set_next_allowedip(&mut self, addr: Option<AllowedIp<'a>>) {
525 if let Some(addr) = addr {
526 self.inner_mut().next_allowedip = addr.0.as_ptr();
527 } else {
528 self.inner_mut().next_allowedip = std::ptr::null_mut();
529 }
530 }
531
532 pub fn ip(&self) -> IpAddr {
533 use nix::sys::socket::Ipv4Addr;
534 use nix::sys::socket::Ipv6Addr;
535
536 match self.inner().family as _ {
537 libc::AF_INET => {
538 let addr = unsafe { std::mem::transmute(self.inner().__bindgen_anon_1.ip4) };
539 Ipv4Addr(addr).to_std().into()
540 },
541 libc::AF_INET6 => {
542 let addr = unsafe { std::mem::transmute(self.inner().__bindgen_anon_1.ip6) };
543 Ipv6Addr(addr).to_std().into()
544 },
545 _ => unreachable!("Another family than AF_INET/AF_INET6 found!")
546 }
547 }
548
549 pub fn cidr(&self) -> u8 {
550 self.inner().cidr
551 }
552
553 pub fn set_cidr(&mut self, cidr: u8) {
554 self.inner_mut().cidr = cidr;
555 }
556
557 pub fn set_ip(&mut self, ip: &IpAddr) {
558 use nix::sys::socket::IpAddr;
559 use nix::sys::socket::Ipv4Addr;
560 use nix::sys::socket::Ipv6Addr;
561
562 let this = self.inner_mut();
563 match IpAddr::from_std(ip) {
564 IpAddr::V4(Ipv4Addr(addr4)) => unsafe {
565 this.family = libc::AF_INET as _;
566 this.__bindgen_anon_1.ip4 = std::mem::transmute(addr4)
567 }
568 IpAddr::V6(Ipv6Addr(addr6)) => unsafe {
569 this.family = libc::AF_INET6 as _;
570 this.__bindgen_anon_1.ip6 = std::mem::transmute(addr6)
571 }
572 }
573
574 }
575}
576
577impl PresharedKey {
578 pub fn new() -> PresharedKey {
579 let mut key = [0; std::mem::size_of::<sys::wg_key>()];
580
581 unsafe {
582 sys::wg_generate_preshared_key(key.as_mut_ptr())
583 }
584
585 PresharedKey(key)
586 }
587}