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