wireguard_tools_rs/
lib.rs

1#![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 { //std::mem::size_of_val(self.as_ref().name) {
71            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) };  // + 1 because of nul byte
166
167            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        /*
297	wg_key public_key;
298	wg_key preshared_key;
299
300	union {
301		struct sockaddr addr;
302		struct sockaddr_in addr4;
303		struct sockaddr_in6 addr6;
304	} endpoint;
305
306	struct timespec64 last_handshake_time;
307	uint64_t rx_bytes, tx_bytes;
308	uint16_t persistent_keepalive_interval;
309
310	struct wg_allowedip *first_allowedip, *last_allowedip;
311	struct wg_peer *next_peer;
312        */
313    }
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        //dbg!(&it);
467
468        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
494// TODO: is this really safe?
495unsafe impl Sync for Device {}
496unsafe impl Send for Device {}
497
498// TODO: is this really safe?
499unsafe 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}