wg_netmanager/
run_loop.rs

1use std::net::{IpAddr, SocketAddr, SocketAddrV4};
2use std::sync::mpsc::{channel, Receiver, Sender};
3use std::time;
4
5use log::*;
6
7use crate::arch_def::Architecture;
8use crate::configuration::*;
9use crate::crypt_udp::CryptUdp;
10use crate::crypt_udp::UdpPacket;
11use crate::error::*;
12use crate::event::Event;
13use crate::manager::*;
14use crate::tui_display::TuiApp;
15use crate::wg_dev::*;
16use crate::Arch;
17
18pub fn run(
19    static_config: &StaticConfiguration,
20    mut wg_dev: Box<dyn WireguardDevice>,
21) -> BoxResult<()> {
22    let (tx, rx) = channel();
23
24    Arch::arch_specific_init(tx.clone());
25
26    let tx_handler = tx.clone();
27    ctrlc::set_handler(move || {
28        warn!("CTRL-C");
29        tx_handler
30            .send(Event::CtrlC)
31            .expect("Could not send signal on channel.")
32    })
33    .expect("Error setting Ctrl-C handler");
34
35    let port = static_config.my_admin_port();
36
37    let (v4_socket_first, need_v4_socket, need_v6_socket) = Arch::ipv4v6_socket_setup();
38
39    let mut opt_crypt_socket_v6 = None;
40    let mut opt_crypt_socket_v4 = None;
41
42    if need_v4_socket && v4_socket_first {
43        debug!("bind to 0.0.0.0:{}", port);
44        opt_crypt_socket_v4 = Some(
45            CryptUdp::bind(IpAddr::V4("0.0.0.0".parse().unwrap()), port)?
46                .key(&static_config.shared_key)?,
47        );
48    }
49    if need_v6_socket {
50        debug!("bind to :::{}", port);
51        opt_crypt_socket_v6 = Some(
52            CryptUdp::bind(IpAddr::V6("::".parse().unwrap()), port)?
53                .key(&static_config.shared_key)?,
54        );
55    }
56    if need_v4_socket && !v4_socket_first {
57        debug!("bind to 0.0.0.0:{}", port);
58        opt_crypt_socket_v4 = Some(
59            CryptUdp::bind(IpAddr::V4("0.0.0.0".parse().unwrap()), port)?
60                .key(&static_config.shared_key)?,
61        );
62    }
63
64    if opt_crypt_socket_v4.is_none() {
65        opt_crypt_socket_v4 = opt_crypt_socket_v6.as_ref().map(|s| s.try_clone().unwrap());
66    }
67    if opt_crypt_socket_v6.is_none() {
68        opt_crypt_socket_v6 = opt_crypt_socket_v4.as_ref().map(|s| s.try_clone().unwrap());
69    }
70
71    let crypt_socket_v4 = opt_crypt_socket_v4.unwrap();
72    let crypt_socket_v6 = opt_crypt_socket_v6.unwrap();
73
74    // Set up udp receiver thread for ipv4
75    if need_v4_socket {
76        let tx_clone = tx.clone();
77        let crypt_socket_v4_clone = crypt_socket_v4
78            .try_clone()
79            .expect("couldn't clone the crypt_socket");
80        std::thread::spawn(move || loop {
81            let mut buf = [0; 2000];
82            match crypt_socket_v4_clone.recv_from(&mut buf) {
83                Ok((received, src_addr)) => {
84                    info!("received {} bytes from {:?}", received, src_addr);
85                    match bincode::deserialize::<UdpPacket>(&buf[..received]) {
86                        Ok(udp_packet) => {
87                            tx_clone.send(Event::Udp(udp_packet, src_addr)).unwrap();
88                        }
89                        Err(e) => {
90                            error!("Error in decode: {:?}", e);
91                        }
92                    }
93                }
94                Err(e) => {
95                    error!("{:?}", e);
96                }
97            }
98        });
99    }
100
101    // Set up udp receiver thread for ipv6
102    if need_v6_socket {
103        let tx_clone = tx.clone();
104        let crypt_socket_v6_clone = crypt_socket_v6
105            .try_clone()
106            .expect("couldn't clone the crypt_socket");
107        std::thread::spawn(move || loop {
108            let mut buf = [0; 2000];
109            match crypt_socket_v6_clone.recv_from(&mut buf) {
110                Ok((received, src_addr)) => {
111                    info!("received {} bytes from {:?}", received, src_addr);
112                    match bincode::deserialize::<UdpPacket>(&buf[..received]) {
113                        Ok(udp_packet) => {
114                            tx_clone.send(Event::Udp(udp_packet, src_addr)).unwrap();
115                        }
116                        Err(e) => {
117                            error!("Error in decode: {:?}", e);
118                        }
119                    }
120                }
121                Err(e) => {
122                    error!("{:?}", e);
123                }
124            }
125        });
126    }
127
128    // Set up timer tick
129    let tx_clone = tx.clone();
130    std::thread::spawn(move || {
131        let interval_1s = time::Duration::from_millis(1000);
132        loop {
133            tx_clone.send(Event::TimerTick1s).unwrap();
134            std::thread::sleep(interval_1s);
135        }
136    });
137
138    // in case there are dangling routes
139    if !static_config.use_existing_interface {
140        wg_dev.take_down_device().ok();
141
142        wg_dev.create_device()?;
143    } else {
144        wg_dev.flush_all()?;
145    }
146
147    wg_dev.set_ip(&static_config.wg_ip, &static_config.subnet)?;
148
149    let mut tui_app = if static_config.use_tui {
150        TuiApp::init(tx.clone())?
151    } else {
152        TuiApp::off()
153    };
154
155    let rc = main_loop(
156        static_config,
157        &*wg_dev,
158        crypt_socket_v4,
159        crypt_socket_v6,
160        tx,
161        rx,
162        &mut tui_app,
163    );
164
165    if !static_config.use_existing_interface {
166        wg_dev.take_down_device().ok();
167    }
168
169    tui_app.deinit()?;
170
171    rc
172}
173
174fn main_loop(
175    static_config: &StaticConfiguration,
176    wg_dev: &dyn WireguardDevice,
177    mut crypt_socket_v4: CryptUdp,
178    mut crypt_socket_v6: CryptUdp,
179    tx: Sender<Event>,
180    rx: Receiver<Event>,
181    tui_app: &mut TuiApp,
182) -> BoxResult<()> {
183    let mut network_manager = NetworkManager::new(static_config);
184
185    // set up initial wireguard configuration without peers
186    tx.send(Event::UpdateWireguardConfiguration).unwrap();
187
188    let mut tick_cnt = 0;
189    loop {
190        let evt = rx.recv();
191        //trace!(target: "loop", "{:?}", evt);
192        match evt {
193            Err(e) => {
194                error!("Receive error: {:?}", e);
195                break;
196            }
197            Ok(Event::CtrlC) => {
198                break;
199            }
200            Ok(Event::TimerTick1s) => {
201                tui_app.draw()?;
202
203                if tick_cnt % 30 == 2 {
204                    // every 30s
205                    network_manager.stats();
206                }
207
208                let now = crate::util::now();
209                let events = network_manager.process_all_nodes_every_second(now, static_config);
210                for evt in events.into_iter() {
211                    tx.send(evt).unwrap();
212                }
213
214                tick_cnt += 1;
215            }
216            Ok(Event::Udp(udp_packet, src_addr)) => {
217                let src_addr = match src_addr {
218                    SocketAddr::V4(_) => src_addr,
219                    SocketAddr::V6(sa) => {
220                        if let Some(ipv4) = sa.ip().to_ipv4() {
221                            SocketAddr::V4(SocketAddrV4::new(ipv4, sa.port()))
222                        } else {
223                            src_addr
224                        }
225                    }
226                };
227
228                use UdpPacket::*;
229                let events: Vec<Event>;
230                match udp_packet {
231                    Advertisement(ad) => {
232                        debug!(target: &ad.wg_ip.to_string(), "Received advertisement from {:?}", src_addr);
233                        let now = crate::util::now();
234                        events =
235                            network_manager.analyze_advertisement(now, static_config, ad, src_addr);
236                    }
237                    RouteDatabaseRequest => match src_addr {
238                        SocketAddr::V4(destination) => {
239                            info!(target: "routing", "RouteDatabaseRequest from {:?}", src_addr);
240                            debug!(target: &destination.ip().to_string(), "Received database request");
241                            events = vec![Event::SendRouteDatabase { to: destination }];
242                        }
243                        SocketAddr::V6(source) => {
244                            error!(target: "routing", "Expected IPV4 and not IPV6 address {:?}", source);
245                            events = vec![];
246                        }
247                    },
248                    RouteDatabase(db) => {
249                        info!(target: "routing", "RouteDatabase from {}", src_addr);
250                        debug!(target: &src_addr.ip().to_string(), "Received route database, version = {}", db.routedb_version);
251                        events = network_manager
252                            .process_route_database(db)
253                            .unwrap_or_default();
254                    }
255                    LocalContactRequest => match src_addr {
256                        SocketAddr::V4(destination) => {
257                            info!(target: "probing", "LocalContactRequest from {:?}", src_addr);
258                            debug!(target: &destination.ip().to_string(), "Received local contact request");
259                            events = vec![Event::SendLocalContact { to: destination }];
260                        }
261                        SocketAddr::V6(source) => {
262                            error!(target: "probing", "Expected IPV4 and not IPV6 address {:?}", source);
263                            events = vec![];
264                        }
265                    },
266                    LocalContact(contact) => {
267                        debug!(target: "probing", "Received contact info: {:#?}", contact);
268                        debug!(target: &contact.wg_ip.to_string(), "Received local contacts");
269                        network_manager.process_local_contact(contact);
270                        events = vec![];
271                    }
272                }
273                for evt in events {
274                    tx.send(evt).unwrap();
275                }
276            }
277            Ok(Event::SendAdvertisement {
278                addressed_to,
279                to: destination,
280                wg_ip,
281            }) => {
282                debug!(target: &wg_ip.to_string(),"Send advertisement to {:?}", destination);
283                let routedb_version = network_manager.db_version();
284                let my_visible_wg_endpoint =
285                    network_manager.my_visible_wg_endpoint.as_ref().copied();
286                let my_local_wg_port = network_manager.my_local_wg_port;
287                let opt_node = network_manager.node_for(&wg_ip);
288                let advertisement = UdpPacket::advertisement_from_config(
289                    static_config,
290                    routedb_version,
291                    addressed_to,
292                    opt_node,
293                    my_local_wg_port,
294                    my_visible_wg_endpoint,
295                );
296                let buf = bincode::serialize(&advertisement).unwrap();
297                info!(target: "advertisement", "Send advertisement to {}", destination);
298                if destination.is_ipv4() {
299                    crypt_socket_v4.send_to(&buf, destination).ok();
300                } else {
301                    crypt_socket_v6.send_to(&buf, destination).ok();
302                }
303            }
304            Ok(Event::SendRouteDatabaseRequest { to: destination }) => {
305                debug!(target: &destination.ip().to_string(), "Send route database request to {:?}", destination);
306                let request = UdpPacket::route_database_request();
307                let buf = bincode::serialize(&request).unwrap();
308                info!(target: "routing", "Send RouteDatabaseRequest to {}", destination);
309                crypt_socket_v4
310                    .send_to(&buf, SocketAddr::V4(destination))
311                    .ok();
312            }
313            Ok(Event::SendRouteDatabase { to: destination }) => {
314                debug!(target: &destination.ip().to_string(), "Send route database to {:?}", destination);
315                let packages = network_manager.provide_route_database();
316                for p in packages {
317                    let buf = bincode::serialize(&p).unwrap();
318                    info!(target: "routing", "Send RouteDatabase to {}", destination);
319                    crypt_socket_v4
320                        .send_to(&buf, SocketAddr::V4(destination))
321                        .ok();
322                }
323            }
324            Ok(Event::SendLocalContactRequest { to: destination }) => {
325                debug!(target: &destination.ip().to_string(), "Send local contact request to {:?}", destination);
326                let request = UdpPacket::local_contact_request();
327                let buf = bincode::serialize(&request).unwrap();
328                info!(target: "probing", "Send LocalContactRequest to {}", destination);
329                crypt_socket_v4
330                    .send_to(&buf, SocketAddr::V4(destination))
331                    .ok();
332            }
333            Ok(Event::SendLocalContact { to: destination }) => {
334                debug!(target: &destination.ip().to_string(), "Send local contacts to {:?}", destination);
335                let local_contact = UdpPacket::local_contact_from_config(
336                    static_config,
337                    network_manager.my_local_wg_port,
338                    network_manager.my_visible_wg_endpoint,
339                );
340                trace!(target: "probing", "local contact to {:#?}", local_contact);
341                let buf = bincode::serialize(&local_contact).unwrap();
342                info!(target: "probing", "Send local contact to {}", destination);
343                crypt_socket_v4
344                    .send_to(&buf, SocketAddr::V4(destination))
345                    .ok();
346            }
347            Ok(Event::WireguardPortHop) => {
348                let mut new_port = network_manager.my_local_wg_port;
349                new_port = (new_port - 10000 + 1) % (65535 - 10000) + 10000;
350                trace!(target: "hopping", "Perform wireguard port hop to {}", new_port);
351                network_manager.my_local_wg_port = new_port;
352            }
353            Ok(Event::UpdateWireguardConfiguration) => {
354                info!("Update peers");
355                let conf = static_config.to_wg_configuration(&network_manager);
356                info!(target: "wireguard", "Configuration as peer\n{}\n", conf);
357                wg_dev.sync_conf(&conf)?;
358            }
359            Ok(Event::ReadWireguardConfiguration) => {
360                let pubkey_to_endpoint = wg_dev.retrieve_conf()?;
361                network_manager.current_wireguard_configuration(pubkey_to_endpoint);
362            }
363            Ok(Event::UpdateRoutes) => {
364                let changes = network_manager.get_route_changes();
365                for rc in changes {
366                    use RouteChange::*;
367                    debug!("{:?}", rc);
368                    match rc {
369                        AddRoute { to, gateway } => {
370                            debug!(target: &to.to_string(), "add route with gateway {:?}", gateway);
371                            wg_dev.add_route(to, gateway)?;
372                        }
373                        ReplaceRoute { to, gateway } => {
374                            debug!(target: &to.to_string(), "replace route with gateway {:?}", gateway);
375                            wg_dev.replace_route(to, gateway)?;
376                        }
377                        DelRoute { to, gateway } => {
378                            debug!(target: &to.to_string(), "del route with gateway {:?}", gateway);
379                            wg_dev.del_route(to, gateway)?;
380                        }
381                    }
382                }
383                tx.send(Event::UpdateWireguardConfiguration).unwrap();
384            }
385            Ok(Event::TuiApp(evt)) => {
386                tui_app.process_event(evt);
387                tui_app.draw()?;
388            }
389        }
390    }
391    Ok(())
392}