feat: added basic structure around packet transfer

This commit is contained in:
Andrew Rioux 2023-09-25 23:24:37 -04:00
parent 867464f673
commit 0bda72491c
Signed by: andrew.rioux
GPG Key ID: 9B8BAC47C17ABB94
3 changed files with 154 additions and 16 deletions

View File

@ -600,7 +600,12 @@ impl TCPPacketBuilder {
let seqnumber = self.seqnumber.unwrap();
let window = self.window.unwrap();
let len: u8 = (self.options.len() / 4 + 5).try_into().unwrap();
let mut options = self.options;
while options.len() % 4 != 0 {
options.push(0);
}
let len: u8 = (options.len() / 4 + 5).try_into().unwrap();
let len = len << 4;
let mut bytes = [
@ -617,7 +622,7 @@ impl TCPPacketBuilder {
&window.to_be_bytes(),
&[0, 0],
&self.urgent_ptr.to_be_bytes(),
&self.options,
&options,
&data,
]
.concat();

View File

@ -450,6 +450,18 @@ impl<T: Activated> InterfaceStream<T> {
pub fn sendpacket(&mut self, packet: packets::EthernetPkt) -> error::Result<()> {
self.inner.get_mut().interface.sendpacket(packet)
}
pub fn set_filter(
&mut self,
filter: &str,
optimize: bool,
mask: Option<u32>,
) -> error::Result<Box<ffi::BpfProgram>> {
self.inner
.get_mut()
.interface
.set_filter(filter, optimize, mask)
}
}
impl<T: Activated> Unpin for InterfaceStream<T> {}

View File

@ -1,15 +1,21 @@
use std::{
collections::VecDeque,
net::{Ipv4Addr, SocketAddr}, time::Duration,
net::{Ipv4Addr, SocketAddr},
time::Duration,
};
use anyhow::anyhow;
use anyhow::{anyhow, bail};
use log::{debug, info, trace};
use log::{debug, error, info, trace};
use nl_sys::{netlink, route};
use packets::{self, EthernetPacket, IPv4Pkt, TCPPacket, TCPPacketBuilder, TCPPkt};
use packets::{
self, EthernetPacket, IPv4Packet, IPv4Pkt, Layer3Packet, Layer3Pkt, Layer4Packet, Layer4Pkt,
TCPPacket, TCPPacketBuilder, TCPPkt,
};
use pcap_sys;
use tokio::{sync::mpsc, task};
use tokio_stream::StreamExt;
struct PeerInfo {
remote_addr: Ipv4Addr,
@ -30,7 +36,7 @@ struct TcpSocket {
local_rx_last_ack: Option<u32>,
state: TcpState,
peer_info: Option<PeerInfo>,
ack_timeout: Option<Duration>
ack_timeout: Option<Duration>,
}
#[derive(Default)]
@ -49,6 +55,22 @@ enum TcpState {
Closed,
}
enum TcpOptions {
EndOfList,
NoOp,
MaxSegmentSize(u16),
}
impl TcpOptions {
fn get_bytes(&self) -> Vec<u8> {
match self {
Self::EndOfList => vec![0x00],
Self::NoOp => vec![0x01],
Self::MaxSegmentSize(size) => [&[0x02, 0x04][..], &size.to_be_bytes()].concat(),
}
}
}
fn socket_accepts_packet(socket: &TcpSocket, ip: IPv4Pkt<'_>, tcp: TCPPkt<'_>) -> bool {
if let Some(peer) = &socket.peer_info {
peer.local_addr == ip.dest_ip()
@ -65,7 +87,7 @@ fn connect(
remote_addr: Ipv4Addr,
remote_port: u16,
local_addr: Ipv4Addr,
) -> TCPPacket {
) -> (u16, TCPPacket) {
socket.state = TcpState::SynSent;
let local_port: u16 = loop {
let port = rand::random();
@ -82,25 +104,54 @@ fn connect(
socket.local_seq_no = rand::random();
TCPPacketBuilder::default()
let packet = TCPPacketBuilder::default()
.srcport(local_port)
.dstport(remote_port)
.
.syn(true)
.window(64240)
.seqnumber(socket.local_seq_no)
.build(local_addr, remote_addr, vec![], None)
.options([TcpOptions::MaxSegmentSize(64240).get_bytes()].concat())
.build(local_addr, remote_addr, vec![], None);
(local_port, packet)
}
fn process_packet(
socket: &mut TcpSocket,
packet: TCPPkt<'_>,
) -> anyhow::Result<Option<(TCPPacketBuilder, Vec<u8>)>> {
) -> anyhow::Result<(Option<(TCPPacketBuilder, Vec<u8>)>, Option<Vec<u8>>)> {
match socket.state {
TcpState::SynSent if packet.ack() && packet.syn() => {}
_ => {}
}
Ok(None)
Ok((None, None))
}
fn send_data(socket: &mut TcpSocket, data: Vec<u8>) -> anyhow::Result<(TCPPacketBuilder, Vec<u8>)> {
Ok(todo!())
}
struct TcpSocketHandle {
send_channel: mpsc::Sender<Vec<u8>>,
receiver_channel: mpsc::Receiver<Vec<u8>>,
}
async fn use_socket(mut socket_handle: TcpSocketHandle) {
_ = socket_handle.send_channel.send(b"ping".to_vec()).await;
match socket_handle.receiver_channel.recv().await {
Some(bytes) => match std::str::from_utf8(&bytes) {
Ok(string) => {
log::info!("received packet: {string}")
}
Err(_) => {
log::info!("received packet: {bytes:?}");
}
},
None => {
log::error!("could not get packets from server")
}
}
}
#[tokio::main]
@ -116,7 +167,7 @@ async fn main() -> anyhow::Result<()> {
.ok_or(anyhow!("could not get target IP"))?
.parse::<Ipv4Addr>()?;
let (routes, (ifname, ifindex, srcip, src_mac, _, src_snmask)) = {
let (routes, (ifname, ifindex, srcip, src_mac, dst_mac, src_snmask)) = {
let socket = netlink::Socket::new()?;
let routes = socket.get_routes()?;
@ -130,7 +181,77 @@ async fn main() -> anyhow::Result<()> {
(routes, res)
};
let socket = TcpSocket::default();
let mut socket = TcpSocket::default();
Ok(())
let mut interface = pcap_sys::Interface::<pcap_sys::DevDisabled>::new(&ifname)?;
interface.set_buffer_size(8192)?;
interface.set_non_blocking(true)?;
interface.set_promisc(false)?;
interface.set_timeout(10)?;
let interface = interface.activate()?;
macro_rules! format_packet {
($tcp_packet:expr) => {{
let layer3pkt = Layer3Packet::IPv4(IPv4Packet::construct(
srcip,
ip,
&Layer4Packet::TCP($tcp_packet),
));
EthernetPacket::construct(src_mac, dst_mac, &layer3pkt)
}};
}
let (port, packet) = connect(&mut socket, ip, 54248, srcip);
interface.set_filter(&format!("inbound and tcp port {port}"), true, None)?;
if interface.datalink() != pcap_sys::consts::DLT_EN10MB {
bail!("interface does not support ethernet");
}
let mut packets = interface.stream()?;
packets.sendpacket(format_packet!(packet).pkt())?;
let (send_channel, mut send_packet) = mpsc::channel(1024);
let (receive_packet, receiver_channel) = mpsc::channel(1024);
let socket_handle = TcpSocketHandle {
receiver_channel,
send_channel,
};
task::spawn(async move { use_socket(socket_handle) });
loop {
let Some((builder, data)) = tokio::select! {
Some(Ok(bytes)) = packets.next() => {
let pkt = bytes.pkt();
let Ok(Layer3Pkt::IPv4Pkt(ip_pkt)) = pkt.get_layer3_pkt() else { continue; };
let Ok(Layer4Pkt::TCP(tcp_pkt)) = ip_pkt.get_layer4_packet() else { continue; };
let Ok((to_send, received)) = process_packet(&mut socket, tcp_pkt) else { continue; };
if let Some(received) = received {
_ = receive_packet.send(received).await;
}
to_send
},
Some(to_send) = send_packet.recv() => {
match send_data(&mut socket, to_send) {
Ok(v) => Some(v),
Err(_) => continue
}
},
else => { continue; }
} else {
continue;
};
let packet = builder.build(srcip, ip, data, None);
_ = packets.sendpacket(format_packet!(packet).pkt());
}
}