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