feat: added AggregateInterface

AggregateInterface can be used to gather multiple libpcap interfaces
together in order to listen to all simultaneously and also selectively
send on different interfaces
This commit is contained in:
Andrew Rioux
2023-05-01 12:40:12 -04:00
parent cfdf8f7e86
commit 24dff10b6b
6 changed files with 246 additions and 22 deletions

View File

@@ -1,6 +1,6 @@
use std::{net::Ipv4Addr, collections::HashMap};
use anyhow::{anyhow, bail};
use anyhow::anyhow;
use tokio::time::{Duration, interval};
use tokio_stream::StreamExt;
@@ -25,7 +25,7 @@ async fn main() -> anyhow::Result<()> {
// let target = target.trim().parse::<Ipv4Addr>()?;
let target: Ipv4Addr = "172.19.0.2".parse().unwrap();
let (src_mac, dst_mac, srcip) = {
let (ifname, src_mac, dst_mac, srcip) = {
let socket = netlink::Socket::new()?;
let routes = socket.get_routes()?;
@@ -61,7 +61,7 @@ async fn main() -> anyhow::Result<()> {
println!("link {:?}: {:?}, {}", link.name(), link.addr(), link.ifindex());
}
let (srcip, srcmac, dstmac) = route::get_macs_and_src_for_ip(&addrs, &routes, &neighs, &links, target)
let (ifname, srcip, srcmac, dstmac) = route::get_macs_and_src_for_ip(&addrs, &routes, &neighs, &links, target)
.ok_or(anyhow!("unable to find a route to the IP"))?;
/*let srcip = route::get_srcip_for_dstip(&routes, target)
@@ -75,16 +75,10 @@ async fn main() -> anyhow::Result<()> {
dbg!(srcip);
dbg!(target);
( srcmac, dstmac, srcip )
( ifname, srcmac, dstmac, srcip )
};
let mut interfaces = pcap_sys::PcapDevIterator::new()?;
let interface_name = interfaces
.find(|eth| eth.starts_with("eth"))
.ok_or(anyhow!("could not get an ethernet interface"))?;
let mut interface = pcap_sys::Interface::<pcap_sys::DevDisabled>::new(&interface_name)?;
let mut interface = pcap_sys::new_aggregate_interface(false)?;
interface.set_buffer_size(8192)?;
interface.set_non_blocking(true)?;
@@ -95,12 +89,10 @@ async fn main() -> anyhow::Result<()> {
interface.set_filter("inbound and udp port 54248", true, None)?;
if interface.datalink() != pcap_sys::consts::DLT_EN10MB {
bail!("interface does not support ethernet")
}
interface.prune(|_, interface| interface.datalink() == pcap_sys::consts::DLT_EN10MB);
enum EventType {
Packet(Result<EthernetPacket, pcap_sys::error::Error>),
Packet((String, Result<EthernetPacket, pcap_sys::error::Error>)),
Update
}
@@ -114,7 +106,7 @@ async fn main() -> anyhow::Result<()> {
_ = update_interval.tick() => Some(EventType::Update)
} {
match evt {
EventType::Packet(Ok(pkt)) => {
EventType::Packet((_, Ok(pkt))) => {
let eth_pkt = pkt.pkt();
let Ok(Layer3Pkt::IPv4Pkt(ip_pkt)) = eth_pkt.get_layer3_pkt() else { continue; };
let Ok(Layer4Pkt::UDP(udp_pkt)) = ip_pkt.get_layer4_packet() else { continue; };
@@ -139,7 +131,7 @@ async fn main() -> anyhow::Result<()> {
let ip_packet = IPv4Packet::construct(srcip, target, &Layer4Packet::UDP(udp_packet));
let eth_packet = EthernetPacket::construct(src_mac, dst_mac, &Layer3Packet::IPv4(ip_packet));
packets.sendpacket(eth_packet.pkt())?;
packets.sendpacket(&ifname, eth_packet.pkt())?;
}
_ => {}
}