diff --git a/Cargo.toml b/Cargo.toml index 04af6d9..0d012a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +pnet = "*" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..533337c --- /dev/null +++ b/src/main.rs @@ -0,0 +1,110 @@ +extern crate pnet; + +use pnet::datalink::Channel::Ethernet; +use pnet::datalink::{self, NetworkInterface}; +use pnet::packet::ethernet::{EtherTypes, EthernetPacket, MutableEthernetPacket}; +use pnet::packet::ip::IpNextHeaderProtocols; +use pnet::packet::ipv4::{MutableIpv4Packet, Ipv4Packet}; +use pnet::packet::ipv6::{MutableIpv6Packet, Ipv6Packet}; +use pnet::packet::tcp::TcpPacket; +use pnet::packet::{MutablePacket, Packet}; +use pnet::util::MacAddr; +use std::env; + +fn main() { + let interface_name = env::args().nth(1).unwrap(); + let interface_names_match = |iface: &NetworkInterface| iface.name == interface_name; + + let interfaces = datalink::interfaces(); + let interface = interfaces.into_iter().find(interface_names_match).unwrap(); + let own_mac = interface.mac.unwrap(); + + let (mut tx, mut rx) = match datalink::channel(&interface, Default::default()) { + Ok(Ethernet(tx, rx)) => (tx, rx), + Ok(_) => panic!("Unhandled channel type"), + Err(e) => panic!( + "An error occurred when creating the datalink channel: {}", + e + ), + }; + + loop { + match rx.next() { + Ok(packet) => { + if handle_ethernet_frame(packet, own_mac).is_none() { + println!("something broke. cool."); + } + } + Err(e) => { + // If an error occurs, we can handle it here + panic!("An error occurred while reading: {}", e); + } + } + } +} + +fn handle_ethernet_frame(packet: &[u8], own_mac: MacAddr) -> Option { + let frame = EthernetPacket::new(packet)?; + // frame is originating from us, we want to ignore it. + // same if it's not addressed to our mac + if frame.get_source() == own_mac || frame.get_destination() != own_mac { + return None; + } + let vec: Vec = frame.packet().to_owned(); + let mut clone = MutableEthernetPacket::owned(vec)?; + let ret = match frame.get_ethertype() { + EtherTypes::Ipv4 => { + clone.set_payload(handle_ipv4_frame(&frame)?.packet()); + Some(clone) + }, + EtherTypes::Ipv6 => { + clone.set_payload(handle_ipv6_frame(&frame)?.packet()); + Some(clone) + }, + _ => None, + }; + ret.map(|mut x| { + x.set_destination(frame.get_source()); + x.set_source(frame.get_destination()); + x.consume_to_immutable() + }) +} + +fn handle_ipv4_frame<'a>(ether_frame: &EthernetPacket) -> Option> { + let frame = Ipv4Packet::new(ether_frame.payload())?; + let vec: Vec = frame.packet().to_owned(); + let mut clone = MutableIpv4Packet::owned(vec)?; + let ret = match frame.get_next_level_protocol() { + IpNextHeaderProtocols::Tcp => handle_tcp_frame(&TcpPacket::new(frame.payload())?), + _ => None, + }; + ret.map(|x| { + clone.set_payload(x.packet()); + clone.consume_to_immutable() + }) +} + +fn handle_ipv6_frame<'a>(ether_frame: &EthernetPacket) -> Option> { + let frame = Ipv6Packet::new(ether_frame.payload())?; + let vec: Vec = frame.packet().to_owned(); + let mut clone = MutableIpv6Packet::owned(vec)?; + let ret = match frame.get_next_header() { + IpNextHeaderProtocols::Tcp => handle_tcp_frame(&TcpPacket::new(frame.payload())?), + _ => None, + }; + ret.map(|x| { + clone.set_payload(x.packet()); + clone.consume_to_immutable() + }) +} + +fn handle_tcp_frame<'a>(packet: &TcpPacket) -> Option> { + println!("{:?}", packet); + match packet.get_destination() { + 80 => { + let vec: Vec = packet.packet().to_owned(); + TcpPacket::owned(vec) + } + _ => None, + } +}