| 
					
				 | 
			
			
				@@ -1,10 +1,11 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-use std::net::{Ipv4Addr}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::{net::Ipv4Addr, path::PathBuf}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use aya::{Bpf, maps::HashMap}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use anyhow::{anyhow, Context}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use aya::programs::{Xdp, XdpFlags}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use aya_log::BpfLogger; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use clap::Parser; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use env_logger::Env; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use log::{info, warn}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use tokio::signal; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use csv::ReaderBuilder; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -18,6 +19,8 @@ struct Opt { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     scan_type: String, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[clap(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     csv: Option<String>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[clap(default_value = "bpfel-unknown-none", long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    target: String, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #[derive(Debug, Deserialize, Eq, PartialEq)] 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -29,24 +32,26 @@ struct CsvRow { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 async fn main() -> Result<(), anyhow::Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let opt = Opt::parse(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    env_logger::init(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut bpf_path = PathBuf::new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bpf_path.push("target"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bpf_path.push(opt.target); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[cfg(debug_assertions)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let bpefl_dir =  "target/bpfel-unknown-none/debug"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bpf_path.push("debug"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #[cfg(not(debug_assertions))] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let bpefl_dir =  "target/bpfel-unknown-none/release"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bpf_path.push("release"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let xdp_name = opt.scan_type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bpf_path.push(xdp_name.clone()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let mut bpf = Bpf::load_file(format!("{}/{}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        bpefl_dir, xdp_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ))?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // TODO Proper pathing 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut bpf = Bpf::load_file(bpf_path)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if let Err(e) = BpfLogger::init(&mut bpf) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // This can happen if you remove all log statements from your eBPF program. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        warn!("failed to initialize eBPF logger: {}", e); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        warn!("failed to initialize eBPF logger: {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+This can happen if the loaded eBPF program has no log statements.", e); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // Obtain and load the XDP program called "responder" defined in the XDP file loaded above 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -54,13 +59,16 @@ async fn main() -> Result<(), anyhow::Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     program.load()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     program.attach(&opt.iface, XdpFlags::default()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				            .context(format!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-               "failed to attach the {} XDP program with default flags - try changing XdpFlags::default() to XdpFlags::SKB_MODE", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               "failed to attach the {} XDP program with default flags \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ - try changing XdpFlags::default() to XdpFlags::SKB_MODE", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                xdp_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				            ))?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     info!("Loaded {} XDP program", xdp_name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let mut filter_map: HashMap<_, u32, u8> = HashMap::try_from(bpf.map_mut("FILTER_MAP").ok_or(anyhow!("Could not construct mutable FILTER_MAP"))?)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut filter_map: HashMap<_, u32, u8> = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        HashMap::try_from(bpf.map_mut("FILTER_MAP") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                          .ok_or(anyhow!("Could not construct mutable FILTER_MAP"))?)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if let Some(csv_path) = opt.csv { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         info!("Installing filter rules from {}", csv_path); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -70,6 +78,7 @@ async fn main() -> Result<(), anyhow::Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for record in reader.deserialize() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             let row: CsvRow = record?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             filter_map.insert(u32::from(row.saddr), 1u8, 0)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // TODO replace with BPF_MAP_UPDATE_BATCH 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |