zond_engine/protocols/
mod.rs1pub mod arp;
8pub mod dns;
9pub mod ethernet;
10pub mod icmp;
11pub mod ip;
12pub mod mdns;
13pub mod ndp;
14pub mod tcp;
15pub mod udp;
16pub mod utils;
17
18use crate::core::models::ip::range::Ipv4Range;
19use crate::core::models::ip::set::IpSet;
20use pnet::datalink::MacAddr;
21use pnet::packet::ethernet::{EtherTypes, EthernetPacket};
22use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
23
24type Bytes = Vec<u8>;
25type PacketIter = Box<dyn Iterator<Item = (Bytes, IpAddr)> + Send>;
26
27pub fn eth_packet_iter(
28 local_mac: &MacAddr,
29 src_v4: &Option<Ipv4Addr>,
30 link_local: &Option<Ipv6Addr>,
31 ip_set: &IpSet,
32) -> anyhow::Result<PacketIter> {
33 let arp_iter = src_v4
34 .as_ref()
35 .map(|v4| create_arp_iter(local_mac, v4, ip_set))
36 .transpose()?
37 .into_iter()
38 .flatten();
39
40 let icmp_iter = link_local
41 .as_ref()
42 .map(|v6| create_icmpv6_packets(local_mac, v6))
43 .transpose()?
44 .into_iter()
45 .flatten();
46
47 Ok(Box::new(arp_iter.chain(icmp_iter)))
48}
49
50pub fn create_arp_iter(
51 local_mac: &MacAddr,
52 src_ip: &Ipv4Addr,
53 ip_set: &IpSet,
54) -> anyhow::Result<PacketIter> {
55 let local_mac = *local_mac;
56 let src_ip = *src_ip;
57 let dst_mac = MacAddr::broadcast();
58
59 let ranges: Vec<Ipv4Range> = ip_set.v4().to_vec();
60
61 let iter = ranges
62 .into_iter()
63 .flat_map(|range| {
64 let start: u32 = range.start_addr.into();
65 let end: u32 = range.end_addr.into();
66 (start..=end).map(Ipv4Addr::from)
67 })
68 .map(move |dst_addr| {
69 let packet = arp::create_packet(&local_mac, dst_mac, &src_ip, dst_addr)
70 .expect("Failed to create ARP packet");
71
72 (packet, IpAddr::V4(dst_addr))
73 });
74
75 Ok(Box::new(iter))
76}
77
78fn create_icmpv6_packets(
79 local_mac: &MacAddr,
80 link_local_addr: &Ipv6Addr,
81) -> anyhow::Result<PacketIter> {
82 let packet: Vec<u8> = icmp::create_all_nodes_echo_request_v6(local_mac, link_local_addr)?;
83
84 let iter = std::iter::once((packet, IpAddr::V6(*link_local_addr)));
85
86 Ok(Box::new(iter))
87}
88
89pub fn get_ip_addr_from_eth(frame: &EthernetPacket) -> anyhow::Result<IpAddr> {
90 match frame.get_ethertype() {
91 EtherTypes::Arp => Ok(IpAddr::V4(arp::get_ipv4_addr_from_eth(frame)?)),
92 EtherTypes::Ipv4 => Ok(IpAddr::V4(ip::get_ipv4_addr_from_eth(frame)?)),
93 EtherTypes::Ipv6 => Ok(IpAddr::V6(ip::get_ipv6_src_addr_from_eth(frame)?)),
94 _ => Err(anyhow::anyhow!(
95 "Unsupported EtherType: {:?}",
96 frame.get_ethertype()
97 )),
98 }
99}