chiark / gitweb /
wip server
[hippotat.git] / server / slocal.rs
index 3c1f5331c5a50acc244f518c26aabaf4b79f6de1..09e6aba82cbdf0813a202d5b1c86c499c8eff3ff 100644 (file)
@@ -10,15 +10,52 @@ pub async fn run(global: Arc<Global>,
                  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;
 
         // xxx something something rx something
 
-        data = ipif.tx.next_segment() =>
+        data = Ipif::next_frame(&mut ipif.tx) =>
         {
-          let data = data.context("read from ipif")?;
+          let data = data?;
+          let may_route = MayRoute::came_from_outside_hippotatd();
+
+          goodness -= goodness >> GOODNESS_SHIFT;
+
+          match checkn(SlipNoConv, global.config.mtu, &data, |header|{
+            let saddr = ip_packet_addr::<false>(header)?;
+            let daddr = ip_packet_addr::<true>(header)?;
+            if ! global.config.vnetwork.iter().any(|n| n.contains(&saddr)) {
+              throw!(PE::Src(saddr))
+            }
+            Ok(daddr)
+          }, |(data, daddr)| route_packet(
+            &global, "ipif", None,
+            data, daddr, may_route.clone()
+          ).map(Ok), |pe| Ok(match pe {
+            PE::Empty => { },
+            PE::Src(saddr) => trace!(
+              target: "hippotatd",
+              "ipif local discard outside-vnets saddr={:?}",
+              saddr
+            ),
+            other => throw!(other),
+          })).await {
+            Ok(()) => goodness += 1,
+            Err(e) => {
+              goodness -= 1;
+              error!("[good={}] invalid data from local tx ipif {}",
+                     goodness, e);
+              if goodness < GOODNESS_MIN {
+                throw!(anyhow!("too many bad packets, too few good ones!"))
+              }
+            },
+          }
         }
       }
     }