fix: fixed weird issues with querying routes
this just involved a better understanding of the data types provided by libnl and some refactoring to make querying as a user of the libnl library easier
This commit is contained in:
parent
be5772fa23
commit
c16bf366b7
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -34,10 +34,6 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "beacon"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -195,6 +191,26 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ex-revshell-beacon"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"log",
|
||||||
|
"nl-sys",
|
||||||
|
"pcap-sys",
|
||||||
|
"simple_logger",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ex-revshell-server"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.28"
|
version = "0.3.28"
|
||||||
@ -496,10 +512,6 @@ version = "1.0.160"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
|
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "server"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.9.9"
|
version = "0.9.9"
|
||||||
|
|||||||
@ -7,10 +7,29 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./target:/backdoor
|
- ./target:/backdoor
|
||||||
command: /backdoor/release/ex-bind-shell-backdoor
|
command: /backdoor/release/ex-bind-shell-backdoor
|
||||||
|
# privileged flag is for iptables, not for the backdoor
|
||||||
privileged: true
|
privileged: true
|
||||||
|
|
||||||
examples_bindshell_client:
|
examples_bindshell_client:
|
||||||
image: alpine
|
image: alpine
|
||||||
volumes:
|
volumes:
|
||||||
- ./target:/backdoor
|
- ./target:/backdoor
|
||||||
command: /backdoor/release/ex-bind-shell-client examples_bindshell_target:54248
|
command: /backdoor/release/ex-bind-shell-client examples_bindshell_target:54248
|
||||||
|
|
||||||
|
examples_revshell_beacon:
|
||||||
|
build:
|
||||||
|
context: examples/secure-image
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
volumes:
|
||||||
|
- ./target:/bacodkkr
|
||||||
|
command: /backdoor/release/ex-revshell-beacon
|
||||||
|
# privileged flag is for iptables, not for the backdoor
|
||||||
|
privileged: true
|
||||||
|
|
||||||
|
examples_revshell_server:
|
||||||
|
image: alpine
|
||||||
|
volumes:
|
||||||
|
- ./target:/backdoor
|
||||||
|
expose:
|
||||||
|
- '54248/udp'
|
||||||
|
command: /backdoor/release/ex-revshell-server
|
||||||
@ -1,8 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "beacon"
|
name = "ex-revshell-beacon"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
tokio = { version = "1.21.2", features = ["net", "rt", "macros", "rt-multi-thread", "io-util", "time"] }
|
||||||
|
nl-sys = { path = "../../../nl-sys" }
|
||||||
|
pcap-sys = { path = "../../../pcap-sys" }
|
||||||
|
anyhow = "1.0.70"
|
||||||
|
tokio-stream = "0.1.14"
|
||||||
|
log = "0.4.17"
|
||||||
|
simple_logger = "4.1.0"
|
||||||
@ -1,3 +1,118 @@
|
|||||||
fn main() {
|
use std::{net::Ipv4Addr, collections::HashMap};
|
||||||
println!("Hello, world!");
|
|
||||||
|
use anyhow::{anyhow, bail};
|
||||||
|
use tokio::time::{Duration, interval};
|
||||||
|
use tokio_stream::StreamExt;
|
||||||
|
|
||||||
|
use nl_sys::{netlink, route};
|
||||||
|
use pcap_sys::packets::*;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
// commented out because it's hard to easily input an IP by command line with docker compose
|
||||||
|
// let mut args = std::env::args();
|
||||||
|
// args.next();
|
||||||
|
// let target = args.next()
|
||||||
|
// .map(|s| s.parse::<Ipv4Addr>().ok())
|
||||||
|
// .flatten()
|
||||||
|
// .ok_or(anyhow!("Please specify a target IP"))?;
|
||||||
|
|
||||||
|
// print!("Please enter the target IP (found with `docker-compose exec examples_revshell_server ip a`, e.x. 172.19.0.2): ");
|
||||||
|
// std::io::stdout().flush()?;
|
||||||
|
// let stdin = std::io::stdin();
|
||||||
|
// let mut target = String::new();
|
||||||
|
// stdin.read_line(&mut target)?;
|
||||||
|
// let target = target.trim().parse::<Ipv4Addr>()?;
|
||||||
|
let target: Ipv4Addr = "172.19.0.2".parse().unwrap();
|
||||||
|
|
||||||
|
let (src_mac, dst_mac, srcip) = {
|
||||||
|
let socket = netlink::Socket::new()?;
|
||||||
|
|
||||||
|
let routes = socket.get_routes()?;
|
||||||
|
let neighs = socket.get_neigh()?;
|
||||||
|
let links = socket.get_links()?;
|
||||||
|
|
||||||
|
let srcip = route::get_srcip_for_dstip(&routes, target)
|
||||||
|
.ok_or(anyhow!("Unable to find a route to the IP"))?;
|
||||||
|
|
||||||
|
let (target_link, dst_mac) = route::get_neigh_for_addr(&routes, &neighs, &links, &srcip.into())
|
||||||
|
.ok_or(anyhow!("Unable to find local interface to use"))?;
|
||||||
|
|
||||||
|
let src_mac = target_link.addr().hw_address();
|
||||||
|
|
||||||
|
(
|
||||||
|
TryInto::<[u8;6]>::try_into(src_mac).unwrap(),
|
||||||
|
TryInto::<[u8;6]>::try_into(dst_mac).unwrap(),
|
||||||
|
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)?;
|
||||||
|
|
||||||
|
interface.set_buffer_size(8192)?;
|
||||||
|
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)?;
|
||||||
|
|
||||||
|
if interface.datalink() != pcap_sys::consts::DLT_EN10MB {
|
||||||
|
bail!("interface does not support ethernet")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EventType {
|
||||||
|
Packet(Result<EthernetPacket, pcap_sys::error::Error>),
|
||||||
|
Update
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut packets = interface.stream()?;
|
||||||
|
let mut update_interval = interval(Duration::from_millis(500));
|
||||||
|
let mut current_packet_id = 0;
|
||||||
|
let mut sent_updates: HashMap<i32, bool> = HashMap::new();
|
||||||
|
|
||||||
|
while let Some(evt) = tokio::select! {
|
||||||
|
v = packets.next() => v.map(EventType::Packet),
|
||||||
|
_ = update_interval.tick() => Some(EventType::Update)
|
||||||
|
} {
|
||||||
|
match evt {
|
||||||
|
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; };
|
||||||
|
|
||||||
|
let data = udp_pkt.get_data();
|
||||||
|
|
||||||
|
let Ok(resp_id) = TryInto::<[u8;4]>::try_into(&data[..4]) else { continue; };
|
||||||
|
let resp_id = i32::from_be_bytes(resp_id);
|
||||||
|
|
||||||
|
if sent_updates.contains_key(&resp_id) {
|
||||||
|
sent_updates.remove(&resp_id);
|
||||||
|
println!("Packet {resp_id} has received a response");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EventType::Update => {
|
||||||
|
let unacknowledged_packets = sent_updates.keys().collect::<Vec<_>>();
|
||||||
|
println!("Currently unacknowledged packets: {unacknowledged_packets:?}");
|
||||||
|
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));
|
||||||
|
|
||||||
|
packets.sendpacket(eth_packet.pkt())?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "server"
|
name = "ex-revshell-server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.70"
|
||||||
@ -1,3 +1,19 @@
|
|||||||
fn main() {
|
use std::net::UdpSocket;
|
||||||
println!("Hello, world!");
|
|
||||||
|
fn main() -> anyhow::Result<()> {
|
||||||
|
let input = UdpSocket::bind("0.0.0.0:54248")?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
|
||||||
|
let Ok((amount, src)) = input.recv_from(&mut buf[..]) else { continue; };
|
||||||
|
|
||||||
|
if amount != 4 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Received packet: {}", i32::from_be_bytes(buf));
|
||||||
|
|
||||||
|
let Ok(_) = input.send_to(&buf, src) else { continue; };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
# secure-image Dockerfile
|
||||||
|
# Used to represent a "secure" computer which has a firewall in place
|
||||||
|
#
|
||||||
# Copyright (C) 2023 Andrew Rioux
|
# Copyright (C) 2023 Andrew Rioux
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
# Setup for the secure image which will set firewall rules
|
||||||
|
#
|
||||||
# Copyright (C) 2023 Andrew Rioux
|
# Copyright (C) 2023 Andrew Rioux
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
|||||||
@ -66,6 +66,7 @@ extern "C" {
|
|||||||
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_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_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_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;
|
||||||
|
|||||||
@ -13,11 +13,11 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::{ffi::{CStr, CString}, net::Ipv4Addr};
|
use std::{ffi::{CStr, CString}, net::Ipv4Addr, fmt::Debug};
|
||||||
|
|
||||||
use libc::{c_int, AF_INET, c_uint};
|
use libc::{c_int, AF_INET, c_uint};
|
||||||
|
|
||||||
use crate::{error, netlink::Cache};
|
use crate::{error, netlink::{Cache, self}};
|
||||||
|
|
||||||
use super::nl_ffi::*;
|
use super::nl_ffi::*;
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ impl Link {
|
|||||||
|
|
||||||
/// Tries to get the neighbor for this link, which can provide the destination address and the
|
/// Tries to get the neighbor for this link, which can provide the destination address and the
|
||||||
/// link layer address (lladdr)
|
/// link layer address (lladdr)
|
||||||
pub fn get_neigh(&self, neigh_table: &Cache<Neigh>, addr: &Addr) -> Option<Neigh> {
|
pub fn get_neigh(&self, neigh_table: &Cache<Neigh>, addr: &Addr) -> Option<[u8; 6]> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let neigh = rtnl_neigh_get(neigh_table.cache, self.ifindex(), addr.addr);
|
let neigh = rtnl_neigh_get(neigh_table.cache, self.ifindex(), addr.addr);
|
||||||
|
|
||||||
@ -74,11 +74,20 @@ impl Link {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Neigh { neigh })
|
Neigh { neigh }.lladdr().hw_address().try_into().ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for Link {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f
|
||||||
|
.debug_struct("Link")
|
||||||
|
.field("name", &self.name())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<*mut nl_object> for Link {
|
impl From<*mut nl_object> for Link {
|
||||||
fn from(value: *mut nl_object) -> Self {
|
fn from(value: *mut nl_object) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -87,16 +96,50 @@ impl From<*mut nl_object> for Link {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the neighbor record for the source IP specified
|
/// Gets the neighbor record for the source IP specified, or get the default address
|
||||||
pub fn get_neigh_for_addr(neighs: &Cache<Neigh>, links: &Cache<Link>, addr: &Addr) -> Option<(Link, Neigh)> {
|
pub fn get_neigh_for_addr(routes: &Cache<Route>, neighs: &Cache<Neigh>, links: &Cache<Link>, addr: &Addr) -> Option<(Link, [u8; 6])> {
|
||||||
for link in links.iter() {
|
for link in links.iter() {
|
||||||
let Some(neigh) = link.get_neigh(&neighs, addr) else { continue; };
|
let Some(neigh) = link.get_neigh(&neighs, addr) else { continue; };
|
||||||
return Some((link, neigh));
|
return Some((link, neigh));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No good neighbors were found above, try to use the default address
|
||||||
|
println!("here");
|
||||||
|
if let Some(def_neigh) = get_default_route(routes) {
|
||||||
|
println!("Found default route, trying to get link for it");
|
||||||
|
if let Some((link, neigh)) = neighs
|
||||||
|
.iter()
|
||||||
|
.filter_map(|n| {
|
||||||
|
let Some(link) = netlink::get_link_by_index(links, n.ifindex()) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
if Some(n.ifindex()) != def_neigh.hop_iter().next().map(|h| h.ifindex()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some((link, n.lladdr()))
|
||||||
|
})
|
||||||
|
.next() {
|
||||||
|
return Some((link, neigh.hw_address().try_into().ok()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given the routes cache, returns the default route among them
|
||||||
|
pub fn get_default_route(routes: &Cache<Route>) -> Option<Route> {
|
||||||
|
routes
|
||||||
|
.iter()
|
||||||
|
.find(|r|
|
||||||
|
r
|
||||||
|
.dst()
|
||||||
|
.map(|a| a.cidrlen())
|
||||||
|
.unwrap_or(33) == 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// A struct representing the neighbor of a link
|
/// A struct representing the neighbor of a link
|
||||||
pub struct Neigh {
|
pub struct Neigh {
|
||||||
neigh: *mut rtnl_neigh
|
neigh: *mut rtnl_neigh
|
||||||
@ -118,6 +161,12 @@ impl Neigh {
|
|||||||
Addr { addr }
|
Addr { addr }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ifindex(&self) -> i32 {
|
||||||
|
unsafe {
|
||||||
|
rtnl_neigh_get_ifindex(self.neigh)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<*mut nl_object> for Neigh {
|
impl From<*mut nl_object> for Neigh {
|
||||||
@ -167,6 +216,26 @@ impl Addr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for Addr {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
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())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Ipv4Addr> for Addr {
|
impl From<Ipv4Addr> for Addr {
|
||||||
fn from(value: Ipv4Addr) -> Self {
|
fn from(value: Ipv4Addr) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -200,6 +269,19 @@ pub struct Route {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Route {
|
impl Route {
|
||||||
|
/// Represents the destination of the route
|
||||||
|
pub fn src(&self) -> Option<Addr> {
|
||||||
|
unsafe {
|
||||||
|
let addr = rtnl_route_get_src(self.route);
|
||||||
|
|
||||||
|
if addr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Addr { addr })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents the destination of the route
|
/// Represents the destination of the route
|
||||||
pub fn dst(&self) -> Option<Addr> {
|
pub fn dst(&self) -> Option<Addr> {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -319,7 +401,7 @@ pub fn get_srcip_for_dstip(routes: &Cache<Route>, ip: Ipv4Addr) -> Option<Ipv4Ad
|
|||||||
|
|
||||||
sorted_routes
|
sorted_routes
|
||||||
.iter()
|
.iter()
|
||||||
.find(|route| {
|
.filter(|route| {
|
||||||
let Some(dst) = route.dst() else { return false };
|
let Some(dst) = route.dst() else { return false };
|
||||||
|
|
||||||
let mask = if dst.cidrlen() != 0 {
|
let mask = if dst.cidrlen() != 0 {
|
||||||
@ -333,15 +415,14 @@ pub fn get_srcip_for_dstip(routes: &Cache<Route>, ip: Ipv4Addr) -> Option<Ipv4Ad
|
|||||||
|
|
||||||
(mask & dst_addr) == (mask & ip_int)
|
(mask & dst_addr) == (mask & ip_int)
|
||||||
})
|
})
|
||||||
.map(|route| {
|
.filter_map(|route| {
|
||||||
route
|
route
|
||||||
.hop_iter()
|
.hop_iter()
|
||||||
.next()
|
.next()
|
||||||
|
.and_then(|hop| hop.gateway())
|
||||||
|
.or(route.dst())
|
||||||
})
|
})
|
||||||
.flatten()
|
.filter_map(|gateway| gateway.try_into().ok())
|
||||||
.map(|hop| hop.gateway())
|
.next()
|
||||||
.flatten()
|
|
||||||
.map(|gateway| gateway.try_into().ok())
|
|
||||||
.flatten()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user