// 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, mut rx: mpsc::Receiver, mut ipif: Ipif) -> Result { 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::(header)?; let daddr = ip_packet_addr::(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 }