chiark / gitweb /
152a570f16d12098486784869aad2f17242e03ee
[hippotat.git] / server / slocal.rs
1 // Copyright 2021 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 // There is NO WARRANTY.
4
5 use super::*;
6
7 #[allow(dead_code)] // xxx
8 #[allow(unused_variables)] // xxx
9 pub async fn run(global: Arc<Global>,
10                  mut rx: mpsc::Receiver<RoutedPacket>,
11                  mut ipif: Ipif) -> Result<Void,AE> {
12   let r = async {
13     let mut goodness: i32 = 0;
14     const GOODNESS_SHIFT: u8 = 8;
15     const GOODNESS_MIN: i32 = -16;
16
17     loop {
18       select!{
19         biased;
20
21         data = rx.recv() =>
22         {
23           let data = data.ok_or_else(|| anyhow!("rx stream end!"))?;
24           let mut data = &*data.data;
25           let mut slip_end = &[SLIP_END][..];
26           let mut buf = Buf::chain(&mut data, &mut slip_end);
27           ipif.rx.write_all_buf(&mut buf).await
28             .context("write to ipif")?;
29         },
30
31         data = Ipif::next_frame(&mut ipif.tx) =>
32         {
33           let data = data?;
34           let may_route = MayRoute::came_from_outside_hippotatd();
35
36           goodness -= goodness >> GOODNESS_SHIFT;
37
38           // xxx should be process1
39           match slip::processn(SlipNoConv, global.config.mtu, &data, |header|{
40             let saddr = ip_packet_addr::<false>(header)?;
41             let daddr = ip_packet_addr::<true>(header)?;
42             Ok((saddr,daddr))
43           }, |(data, (saddr, daddr))| {
44             let global = &global;
45             let may_route = &may_route;
46             async move {
47               if ! global.config.vnetwork.iter().any(|n| n.contains(&saddr)) {
48                 // pretent as if this came from route
49                 trace!(
50                   target: "hippotatd",
51  "discard to={:?} came=ipif user=local from-outside-vnets-={:?}",
52                   daddr, saddr);
53                 return Ok(())
54               }
55
56               route_packet(
57                 &global, "ipif", None,
58                 data, daddr, may_route.clone()
59               ).await;
60
61               Ok(())
62             }
63           }, |pe| Ok(match pe {
64             PE::Empty => { },
65             other => throw!(other),
66           })).await {
67             Ok(()) => goodness += 1,
68             Err(e) => {
69               goodness -= 1;
70               error!("[good={}] invalid data from local tx ipif {}",
71                      goodness, e);
72               if goodness < GOODNESS_MIN {
73                 throw!(anyhow!("too many bad packets, too few good ones!"))
74               }
75             },
76           }
77         },
78       }
79     }
80   }.await;
81
82   ipif.quitting(None).await;
83   r
84 }