feat: worked some on the tcp client

found out ethtool helps make the program work with lxc sockets
This commit is contained in:
Andrew Rioux 2023-09-20 00:15:15 -04:00
parent f5b31954d4
commit f092548a8c
Signed by: andrew.rioux
GPG Key ID: 9B8BAC47C17ABB94
3 changed files with 105 additions and 36 deletions

14
Cargo.lock generated
View File

@ -719,12 +719,9 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.17" version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "managed" name = "managed"
@ -1219,11 +1216,10 @@ checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
[[package]] [[package]]
name = "simple_logger" name = "simple_logger"
version = "4.1.0" version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78beb34673091ccf96a8816fce8bfd30d1292c7621ca2bcb5f2ba0fae4f558d" checksum = "2230cd5c29b815c9b699fb610b49a5ed65588f3509d9f0108be3a885da629333"
dependencies = [ dependencies = [
"atty",
"colored", "colored",
"log", "log",
"time", "time",
@ -1419,10 +1415,12 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"libc", "libc",
"log",
"nl-sys", "nl-sys",
"packets", "packets",
"pcap-sys", "pcap-sys",
"rand 0.8.5", "rand 0.8.5",
"simple_logger",
"smoltcp", "smoltcp",
"tokio", "tokio",
"tokio-stream", "tokio-stream",

View File

@ -13,5 +13,7 @@ rand = "0.8.5"
tokio = { version = "1.32.0", features = ["full"] } tokio = { version = "1.32.0", features = ["full"] }
anyhow = "1.0.75" anyhow = "1.0.75"
tokio-stream = { version = "0.1.14", features = ["full"] } tokio-stream = { version = "0.1.14", features = ["full"] }
smoltcp = { version = "0.10.0", features = ["socket-tcp", "phy-raw_socket", "std", "async", "medium-ethernet", "proto-ipv4", "reassembly-buffer-size-65536", "fragmentation-buffer-size-65536", "proto-ipv4-fragmentation"] } smoltcp = { version = "0.10", features = ["socket-tcp", "phy-raw_socket", "std", "async", "medium-ethernet", "proto-ipv4", "reassembly-buffer-size-65536", "fragmentation-buffer-size-65536", "proto-ipv4-fragmentation", "log", "verbose"] }
libc = "0.2.148" libc = "0.2.148"
log = "0.4.20"
simple_logger = "4.2.0"

View File

@ -2,11 +2,12 @@ use std::{net::Ipv4Addr, os::fd::AsRawFd, sync::Arc};
use anyhow::anyhow; use anyhow::anyhow;
use log::{debug, info, trace};
use nl_sys::{netlink, route}; use nl_sys::{netlink, route};
use smoltcp::{ use smoltcp::{
iface::{Config, Interface, Route, SocketSet}, iface::{Config, Interface, Route, SocketSet},
phy::{wait as phy_wait, Medium, RawSocket}, phy::{wait as phy_wait, Device, Medium, RawSocket},
socket::tcp, socket::tcp,
time::Instant, time::Instant,
wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address}, wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address},
@ -15,6 +16,11 @@ use tokio::io::{unix::AsyncFd, Interest};
#[tokio::main] #[tokio::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
simple_logger::SimpleLogger::new()
.with_level(log::LevelFilter::Trace)
.with_module_level("tcp_test", log::LevelFilter::Trace)
.init()?;
let ip = std::env::args() let ip = std::env::args()
.skip(1) .skip(1)
.next() .next()
@ -45,6 +51,11 @@ async fn main() -> anyhow::Result<()> {
let mut iface = Interface::new(config, &mut device, Instant::now()); let mut iface = Interface::new(config, &mut device, Instant::now());
iface.update_ip_addrs(|ip_addrs| { iface.update_ip_addrs(|ip_addrs| {
let o = srcip.octets(); let o = srcip.octets();
debug!(
"source network ip: {}.{}.{}.{}/{src_snmask}",
o[0], o[1], o[2], o[3]
);
ip_addrs ip_addrs
.push(IpCidr::new( .push(IpCidr::new(
IpAddress::v4(o[0], o[1], o[2], o[3]), IpAddress::v4(o[0], o[1], o[2], o[3]),
@ -55,36 +66,85 @@ async fn main() -> anyhow::Result<()> {
for route in routes.iter() { for route in routes.iter() {
let Some(dst) = route.dst() else { let Some(dst) = route.dst() else {
trace!("failed to get route destination");
continue; continue;
}; };
let Some(hop) = route.hop_iter().next() else { let Some(hop) = route.hop_iter().next() else {
trace!("no next hop existed for {dst:?}");
continue; continue;
}; };
if hop.ifindex() != ifindex { if hop.ifindex() != ifindex {
trace!("hop doesn't match ifindex {ifindex}");
continue; continue;
} }
let Some(laddr) = hop.gateway() else { let Some(laddr) = hop.gateway() else {
trace!("couldn't get gateway address for {dst:?}");
continue; continue;
}; };
if laddr.atype() != Some(libc::AF_INET) { if laddr.atype() != Some(libc::AF_INET) {
continue; trace!("unable to load IP info for {dst:?}");
}
let Some(raddr) = route.dst() else {
continue;
};
if raddr.atype() != Some(libc::AF_INET) {
continue; continue;
} }
if dst.cidrlen() == 0 { if dst.cidrlen() == 0 {
info!("setting default route via {:?}", &laddr);
iface iface
.routes_mut() .routes_mut()
.add_default_ipv4_route(Ipv4Address::from_bytes(&laddr.hw_address()))?; .add_default_ipv4_route(Ipv4Address::from_bytes(&laddr.hw_address()))?;
} else {
iface.routes_mut().update(|routes| { iface.routes_mut().update(|routes| {
let lip = laddr.hw_address(); let lip = laddr.hw_address();
let rip = raddr.hw_address(); _ = routes.push(Route {
cidr: IpCidr::new(IpAddress::v4(10, 0, 0, 0), 8),
via_router: IpAddress::v4(lip[0], lip[1], lip[2], lip[3]),
expires_at: None,
preferred_until: None,
});
_ = routes.push(Route {
cidr: IpCidr::new(IpAddress::v4(172, 16, 0, 0), 12),
via_router: IpAddress::v4(lip[0], lip[1], lip[2], lip[3]),
expires_at: None,
preferred_until: None,
});
});
} else {
let Some(raddr) = route.dst() else {
continue;
};
if raddr.atype() != Some(libc::AF_INET) {
continue;
}
let lip = laddr.hw_address();
let rip = raddr.hw_address();
info!(
"queueing adding {}.{}.{}.{}/{} via {}.{}.{}.{}",
rip[0],
rip[1],
rip[2],
rip[3],
dst.cidrlen(),
lip[0],
lip[1],
lip[2],
lip[3]
);
iface.routes_mut().update(|routes| {
info!(
"adding {}.{}.{}.{}/{} via {}.{}.{}.{}",
rip[0],
rip[1],
rip[2],
rip[3],
dst.cidrlen(),
lip[0],
lip[1],
lip[2],
lip[3]
);
_ = routes.push(Route { _ = routes.push(Route {
cidr: IpCidr::new( cidr: IpCidr::new(
@ -99,8 +159,15 @@ async fn main() -> anyhow::Result<()> {
} }
} }
let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 1500]); debug!("routes added:");
let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 1500]); iface.routes_mut().update(|r| {
for r in r {
debug!("\t{r:?}");
}
});
let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 65536]);
let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 65536]);
let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer); let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
let mut sockets = SocketSet::new(vec![]); let mut sockets = SocketSet::new(vec![]);
let tcp_handle = sockets.add(tcp_socket); let tcp_handle = sockets.add(tcp_socket);
@ -117,15 +184,13 @@ async fn main() -> anyhow::Result<()> {
socket.connect(iface.context(), (ip, 54248), port)?; socket.connect(iface.context(), (ip, 54248), port)?;
let fd = device.as_raw_fd(); let fd = device.as_raw_fd();
let interest = Interest::WRITABLE /*let interest = Interest::WRITABLE
.add(Interest::READABLE) .add(Interest::READABLE)
.add(Interest::ERROR) .add(Interest::ERROR)
.add(Interest::PRIORITY); .add(Interest::PRIORITY);
let afd = AsyncFd::with_interest(fd, interest)?; let afd = AsyncFd::with_interest(fd, interest)?;*/
let mut tcp_active = false; let mut tcp_active = false;
let mut tcp_data_sent = false;
let mut tcp_data_recvd = false;
loop { loop {
let timestamp = Instant::now(); let timestamp = Instant::now();
@ -133,32 +198,36 @@ async fn main() -> anyhow::Result<()> {
let socket = sockets.get_mut::<tcp::Socket>(tcp_handle); let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
if socket.is_active() && !tcp_active { if socket.is_active() && !tcp_active {
println!("connected!"); info!("connected!");
tcp_active = true;
} else if !socket.is_active() && tcp_active { } else if !socket.is_active() && tcp_active {
println!("disconnected"); info!("disconnected");
break Ok(()); tcp_active = false;
} }
tcp_active = socket.is_active(); tcp_active = socket.is_active();
if !tcp_data_sent && socket.can_send() { if !socket.is_active() && !tcp_active {
socket.send_slice(b"ping")?; socket.connect(iface.context(), (ip, 54248), port)?;
tcp_data_sent = true; info!("connecting...");
} }
if !tcp_data_recvd && socket.may_recv() {
if socket.can_send() {
socket.send_slice(b"ping")?;
info!("sent data!");
} else if socket.may_recv() {
socket.recv(|data| { socket.recv(|data| {
if !data.is_empty() { if !data.is_empty() {
match std::str::from_utf8(&data) { match std::str::from_utf8(&data) {
Ok(s) => println!("Data received: {}", s), Ok(s) => info!("Data received: {}", s),
Err(_) => println!("Data received: {:?}", data), Err(_) => info!("Data received: {:?}", data),
} }
} }
(data.len(), data) (data.len(), data)
})?; })?;
tcp_data_recvd = true;
} }
// phy_wait(fd, iface.poll_delay(timestamp, &sockets))?; phy_wait(fd, iface.poll_delay(timestamp, &sockets))?;
drop(afd.ready(interest).await?); // drop(afd.ready(interest).await?);
} }
} }