96 lines
3.0 KiB
Rust
96 lines
3.0 KiB
Rust
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
pub mod error;
|
|
pub mod netlink;
|
|
pub mod nl_ffi;
|
|
pub mod route;
|
|
|
|
// from bridge.c
|
|
extern "C" {
|
|
pub(crate) fn netlink_route() -> libc::c_int;
|
|
}
|
|
|
|
/* fn main() -> error::Result<()> {
|
|
let sock = netlink::Socket::new(netlink::SocketType::Routing)?;
|
|
let lookup_sock = netlink::Socket::new(netlink::SocketType::Lookup)?;
|
|
|
|
let links = sock.get_links()?;
|
|
let routes = sock.get_routes()?;
|
|
|
|
let target_ip = "1.1.1.1".parse::<Ipv4Addr>().unwrap();
|
|
let target_ip_num = u32::from(target_ip);
|
|
|
|
let mut routes2 = routes.iter().collect::<Vec<_>>();
|
|
println!("Routes: {}", routes2.len());
|
|
routes2.sort_by(|r1, r2| {
|
|
r2.dst().map(|a| a.cidrlen())
|
|
.partial_cmp(&r1.dst().map(|a| a.cidrlen()))
|
|
.unwrap_or(std::cmp::Ordering::Equal)
|
|
});
|
|
|
|
let routes3 = routes2.iter().filter(|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 Ok(dst_addr): Result<Ipv4Addr, _> = dst.try_into() else { return false };
|
|
let dst_addr = u32::from(dst_addr);
|
|
|
|
(mask & dst_addr) == (mask & target_ip_num)
|
|
});
|
|
|
|
for route in routes3 {
|
|
let link = netlink::get_link_by_index(&links, route.ifindex());
|
|
println!(
|
|
"route: src: {:?}, dst: {:?}, link: {}, {:?}",
|
|
route.src().map(|s| (s.hw_address(), s.cidrlen())),
|
|
route.dst().map(|s| (s.hw_address(), s.cidrlen())),
|
|
route.ifindex(),
|
|
link.map(|l| l.name())
|
|
);
|
|
|
|
for hops in route.hop_iter() {
|
|
println!(
|
|
"\tgateway: {:?}, ifindex: {}",
|
|
hops.gateway().map(|g| g.hw_address()),
|
|
hops.ifindex()
|
|
);
|
|
}
|
|
}
|
|
|
|
let src_ip = route::Addr::from("172.17.0.1".parse::<Ipv4Addr>().unwrap());
|
|
|
|
let neighs = sock.get_neigh()?;
|
|
|
|
let target_neigh = route::get_neigh_for_addr(&neighs, &links, &src_ip);
|
|
|
|
if let Some((link, neigh)) = target_neigh {
|
|
println!(
|
|
"link: {}; src mac: {:?}; src ip: {:?}; dst mac: {:?}",
|
|
link.name(),
|
|
link.addr().hw_address(),
|
|
neigh.dst().hw_address(),
|
|
neigh.lladdr().hw_address()
|
|
);
|
|
}
|
|
|
|
Ok(())
|
|
} */
|