Compare commits
1 Commits
c913fc0fb1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0a9262cd8 |
144
src/routing.rs
144
src/routing.rs
@@ -2,6 +2,10 @@ use anyhow::Result;
|
|||||||
use libc::if_nametoindex;
|
use libc::if_nametoindex;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use netlink_packet_route::route::RouteAddress;
|
use netlink_packet_route::route::RouteAddress;
|
||||||
|
use netlink_packet_route::{
|
||||||
|
AddressFamily, RouteNetlinkMessage,
|
||||||
|
route::{RouteAttribute, RouteHeader, RouteMessage, RouteProtocol, RouteScope, RouteType},
|
||||||
|
};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
@@ -123,36 +127,16 @@ impl RouteManager {
|
|||||||
use netlink_packet_core::{
|
use netlink_packet_core::{
|
||||||
NLM_F_ACK, NLM_F_CREATE, NLM_F_REQUEST, NetlinkHeader, NetlinkMessage, NetlinkPayload,
|
NLM_F_ACK, NLM_F_CREATE, NLM_F_REQUEST, NetlinkHeader, NetlinkMessage, NetlinkPayload,
|
||||||
};
|
};
|
||||||
use netlink_packet_route::{
|
|
||||||
AddressFamily, RouteNetlinkMessage,
|
|
||||||
route::RouteProtocol,
|
|
||||||
route::RouteScope,
|
|
||||||
route::{RouteAttribute, RouteHeader, RouteMessage, RouteType},
|
|
||||||
};
|
|
||||||
use netlink_sys::{Socket, SocketAddr, protocols::NETLINK_ROUTE};
|
use netlink_sys::{Socket, SocketAddr, protocols::NETLINK_ROUTE};
|
||||||
|
|
||||||
let mut socket = Socket::new(NETLINK_ROUTE)?;
|
let mut socket = Socket::new(NETLINK_ROUTE)?;
|
||||||
let _port_number = socket.bind_auto()?.port_number();
|
let _port_number = socket.bind_auto()?.port_number();
|
||||||
socket.connect(&SocketAddr::new(0, 0))?;
|
socket.connect(&SocketAddr::new(0, 0))?;
|
||||||
let route_msg_hdr = RouteHeader {
|
|
||||||
address_family: AddressFamily::Inet,
|
|
||||||
table: MAIN_TABLE_ID,
|
|
||||||
destination_prefix_length: 0, // Default route
|
|
||||||
protocol: RouteProtocol::Boot,
|
|
||||||
scope: RouteScope::Universe,
|
|
||||||
kind: RouteType::Unicast,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut route_msg = RouteMessage::default();
|
let route_msg = create_route_message(route_info.gateway, index, route_info.metric);
|
||||||
route_msg.header = route_msg_hdr;
|
|
||||||
route_msg.attributes = vec![
|
|
||||||
RouteAttribute::Gateway(RouteAddress::Inet(route_info.gateway)),
|
|
||||||
RouteAttribute::Oif(index),
|
|
||||||
RouteAttribute::Priority(route_info.metric),
|
|
||||||
];
|
|
||||||
let mut nl_hdr = NetlinkHeader::default();
|
let mut nl_hdr = NetlinkHeader::default();
|
||||||
nl_hdr.flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; // Remove NLM_F_EXCL to allow updates
|
nl_hdr.flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
|
||||||
|
|
||||||
let mut msg = NetlinkMessage::new(
|
let mut msg = NetlinkMessage::new(
|
||||||
nl_hdr,
|
nl_hdr,
|
||||||
@@ -161,11 +145,8 @@ impl RouteManager {
|
|||||||
|
|
||||||
msg.finalize();
|
msg.finalize();
|
||||||
let mut buf = vec![0; 1024 * 8];
|
let mut buf = vec![0; 1024 * 8];
|
||||||
|
|
||||||
msg.serialize(&mut buf[..msg.buffer_len()]);
|
msg.serialize(&mut buf[..msg.buffer_len()]);
|
||||||
|
|
||||||
// Debug: Log the netlink message being sent
|
|
||||||
debug!("Netlink message being sent: {:?}", &buf[..msg.buffer_len()]);
|
|
||||||
debug!(
|
debug!(
|
||||||
"Route addition attempt: gateway={}, interface={}, metric={}, interface_index={}",
|
"Route addition attempt: gateway={}, interface={}, metric={}, interface_index={}",
|
||||||
route_info.gateway, route_info.interface, route_info.metric, index
|
route_info.gateway, route_info.interface, route_info.metric, index
|
||||||
@@ -198,33 +179,18 @@ impl RouteManager {
|
|||||||
route_info.metric
|
route_info.metric
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let error_str = match error_code {
|
return handle_netlink_error(error_code);
|
||||||
-1 => "EPERM - Operation not permitted (need root privileges)",
|
|
||||||
-2 => "ENOENT - No such file or directory",
|
|
||||||
-13 => "EACCES - Permission denied",
|
|
||||||
-22 => "EINVAL - Invalid argument",
|
|
||||||
_ => "Unknown error",
|
|
||||||
};
|
|
||||||
return Err(anyhow::anyhow!(
|
|
||||||
"Failed to add route: {} (code: {}): {:?}",
|
|
||||||
error_str,
|
|
||||||
error_code,
|
|
||||||
error_msg
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug!("Route added successfully");
|
debug!("Route added successfully");
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => Err(anyhow::anyhow!(
|
||||||
return Err(anyhow::anyhow!(
|
"Failed to deserialize netlink message: {}",
|
||||||
"Failed to deserialize netlink message: {}",
|
e
|
||||||
e
|
)),
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_default_route_internal(
|
fn delete_default_route_internal(
|
||||||
@@ -242,35 +208,13 @@ impl RouteManager {
|
|||||||
use netlink_packet_core::{
|
use netlink_packet_core::{
|
||||||
NLM_F_ACK, NLM_F_REQUEST, NetlinkHeader, NetlinkMessage, NetlinkPayload,
|
NLM_F_ACK, NLM_F_REQUEST, NetlinkHeader, NetlinkMessage, NetlinkPayload,
|
||||||
};
|
};
|
||||||
use netlink_packet_route::{
|
|
||||||
AddressFamily, RouteNetlinkMessage,
|
|
||||||
route::RouteProtocol,
|
|
||||||
route::RouteScope,
|
|
||||||
route::{RouteAttribute, RouteHeader, RouteMessage, RouteType},
|
|
||||||
};
|
|
||||||
use netlink_sys::{Socket, SocketAddr, protocols::NETLINK_ROUTE};
|
use netlink_sys::{Socket, SocketAddr, protocols::NETLINK_ROUTE};
|
||||||
|
|
||||||
let mut socket = Socket::new(NETLINK_ROUTE)?;
|
let mut socket = Socket::new(NETLINK_ROUTE)?;
|
||||||
let _port_number = socket.bind_auto()?.port_number();
|
let _port_number = socket.bind_auto()?.port_number();
|
||||||
socket.connect(&SocketAddr::new(0, 0))?;
|
socket.connect(&SocketAddr::new(0, 0))?;
|
||||||
|
|
||||||
let route_msg_hdr = RouteHeader {
|
let route_msg = create_route_message(gateway, index, metric);
|
||||||
address_family: AddressFamily::Inet,
|
|
||||||
table: MAIN_TABLE_ID,
|
|
||||||
destination_prefix_length: 0, // Default route
|
|
||||||
protocol: RouteProtocol::Boot,
|
|
||||||
scope: RouteScope::Universe,
|
|
||||||
kind: RouteType::Unicast,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut route_msg = RouteMessage::default();
|
|
||||||
route_msg.header = route_msg_hdr;
|
|
||||||
route_msg.attributes = vec![
|
|
||||||
RouteAttribute::Gateway(RouteAddress::Inet(gateway)),
|
|
||||||
RouteAttribute::Oif(index),
|
|
||||||
RouteAttribute::Priority(metric),
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut nl_hdr = NetlinkHeader::default();
|
let mut nl_hdr = NetlinkHeader::default();
|
||||||
nl_hdr.flags = NLM_F_REQUEST | NLM_F_ACK;
|
nl_hdr.flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
@@ -282,14 +226,8 @@ impl RouteManager {
|
|||||||
|
|
||||||
msg.finalize();
|
msg.finalize();
|
||||||
let mut buf = vec![0; 1024 * 8];
|
let mut buf = vec![0; 1024 * 8];
|
||||||
|
|
||||||
msg.serialize(&mut buf[..msg.buffer_len()]);
|
msg.serialize(&mut buf[..msg.buffer_len()]);
|
||||||
|
|
||||||
// Debug: Log the netlink message being sent
|
|
||||||
debug!(
|
|
||||||
"Netlink delete message being sent: {:?}",
|
|
||||||
&buf[..msg.buffer_len()]
|
|
||||||
);
|
|
||||||
debug!(
|
debug!(
|
||||||
"Route deletion attempt: gateway={}, interface={}, metric={}, interface_index={}",
|
"Route deletion attempt: gateway={}, interface={}, metric={}, interface_index={}",
|
||||||
gateway, interface, metric, index
|
gateway, interface, metric, index
|
||||||
@@ -315,16 +253,13 @@ impl RouteManager {
|
|||||||
}
|
}
|
||||||
debug!("Route deleted successfully");
|
debug!("Route deleted successfully");
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => Err(anyhow::anyhow!(
|
||||||
return Err(anyhow::anyhow!(
|
"Failed to deserialize netlink message: {}",
|
||||||
"Failed to deserialize netlink message: {}",
|
e
|
||||||
e
|
)),
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,3 +273,44 @@ fn get_interface_index(iface_name: &str) -> Result<u32> {
|
|||||||
Ok(index)
|
Ok(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_route_header() -> RouteHeader {
|
||||||
|
RouteHeader {
|
||||||
|
address_family: AddressFamily::Inet,
|
||||||
|
table: MAIN_TABLE_ID,
|
||||||
|
destination_prefix_length: 0, // Default route
|
||||||
|
protocol: RouteProtocol::Boot,
|
||||||
|
scope: RouteScope::Universe,
|
||||||
|
kind: RouteType::Unicast,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_netlink_error(error_code: i32) -> Result<()> {
|
||||||
|
if error_code == -17 {
|
||||||
|
// EEXIST - Route already exists, treat as success
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let error_str = match error_code {
|
||||||
|
-1 => "EPERM - Operation not permitted (need root privileges)",
|
||||||
|
-2 => "ENOENT - No such file or directory",
|
||||||
|
-13 => "EACCES - Permission denied",
|
||||||
|
-22 => "EINVAL - Invalid argument",
|
||||||
|
_ => "Unknown error",
|
||||||
|
};
|
||||||
|
Err(anyhow::anyhow!("Netlink operation failed: {}", error_str))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_route_message(gateway: Ipv4Addr, interface_index: u32, metric: u32) -> RouteMessage {
|
||||||
|
let route_msg_hdr = create_route_header();
|
||||||
|
|
||||||
|
let mut route_msg = RouteMessage::default();
|
||||||
|
route_msg.header = route_msg_hdr;
|
||||||
|
route_msg.attributes = vec![
|
||||||
|
RouteAttribute::Gateway(RouteAddress::Inet(gateway)),
|
||||||
|
RouteAttribute::Oif(interface_index),
|
||||||
|
RouteAttribute::Priority(metric),
|
||||||
|
];
|
||||||
|
route_msg
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user