Skip to content

Commit

Permalink
upgrade deps
Browse files Browse the repository at this point in the history
  • Loading branch information
ssrlive committed Mar 1, 2024
1 parent 4274ca4 commit 84705bd
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 73 deletions.
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,28 @@ default = []
log = ["tracing/log"]

[dependencies]
tokio = { version = "1.35", features = [
tokio = { version = "1.36", features = [
"sync",
"rt",
"time",
"io-util",
"macros",
], default-features = false }
etherparse = { version = "0.13", default-features = false }
etherparse = { version = "0.14", default-features = false, features = ["std"] }
thiserror = { version = "1.0", default-features = false }
tracing = { version = "0.1", default-features = false, features = [
"log",
], optional = true }

[dev-dependencies]
clap = { version = "4.4", features = ["derive"] }
clap = { version = "4.5", features = ["derive"] }
udp-stream = { version = "0.0", default-features = false }
tokio = { version = "1.35", features = [
tokio = { version = "1.36", features = [
"rt-multi-thread",
], default-features = false }

#tun2.rs example
tun2 = { version = "1.0", features = ["async"] }
tun2 = { version = "1.2", features = ["async"] }

#tun_wintun.rs example
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dev-dependencies]
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
IpStack
=======

An asynchronous lightweight implementation of TCP/IP stack for Tun device.
Unstable, under development.

[![Crates.io](https://img.shields.io/crates/v/ipstack.svg)](https://crates.io/crates/ipstack)
![ipstack](https://docs.rs/ipstack/badge.svg)
[![Documentation](https://img.shields.io/badge/docs-release-brightgreen.svg?style=flat)](https://docs.rs/ipstack)
[![Download](https://img.shields.io/crates/d/ipstack.svg)](https://crates.io/crates/ipstack)
[![License](https://img.shields.io/crates/l/ipstack.svg?style=flat)](https://github.com/narrowlink/ipstack/blob/main/LICENSE)

### Usage

```rust
Expand Down
6 changes: 3 additions & 3 deletions examples/tun2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let gateway = Ipv4Addr::new(10, 0, 0, 1);

let mut config = tun2::Configuration::default();
config.address(ipv4).netmask(netmask).mtu(MTU as usize).up();
config.address(ipv4).netmask(netmask).mtu(MTU).up();
config.destination(gateway);

#[cfg(target_os = "linux")]
Expand Down Expand Up @@ -103,7 +103,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
});
}
IpStackStream::UnknownTransport(u) => {
if u.src_addr().is_ipv4() && u.ip_protocol() == 1 {
if u.src_addr().is_ipv4() && u.ip_protocol() == 1.into() {
let (icmp_header, req_payload) = Icmpv4Header::from_slice(u.payload())?;
if let etherparse::Icmpv4Type::EchoRequest(req) = icmp_header.icmp_type {
println!("ICMPv4 echo");
Expand All @@ -121,7 +121,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
continue;
}
println!("unknown transport - Ip Protocol {}", u.ip_protocol());
println!("unknown transport - Ip Protocol {:?}", u.ip_protocol());
continue;
}
IpStackStream::UnknownNetwork(pkt) => {
Expand Down
4 changes: 2 additions & 2 deletions examples/tun_wintun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
});
}
IpStackStream::UnknownTransport(u) => {
if u.src_addr().is_ipv4() && u.ip_protocol() == 1 {
if u.src_addr().is_ipv4() && u.ip_protocol() == 1.into() {
let (icmp_header, req_payload) = Icmpv4Header::from_slice(u.payload())?;
if let etherparse::Icmpv4Type::EchoRequest(req) = icmp_header.icmp_type {
println!("ICMPv4 echo");
Expand All @@ -100,7 +100,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
continue;
}
println!("unknown transport - Ip Protocol {}", u.ip_protocol());
println!("unknown transport - Ip Protocol {:?}", u.ip_protocol());
continue;
}
IpStackStream::UnknownNetwork(pkt) => {
Expand Down
15 changes: 13 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,25 @@
pub enum IpStackError {
#[error("The transport protocol is not supported")]
UnsupportedTransportProtocol,

#[error("The packet is invalid")]
InvalidPacket,
#[error("Write error: {0}")]
PacketWriteError(etherparse::WriteError),

#[error("ValueTooBigError<u16> {0}")]
ValueTooBigErrorU16(#[from] etherparse::err::ValueTooBigError<u16>),

#[error("From<ValueTooBigError<u32>> {0}")]
ValueTooBigErrorU32(#[from] etherparse::err::ValueTooBigError<u32>),

#[error("ValueTooBigError<usize> {0}")]
ValueTooBigErrorUsize(#[from] etherparse::err::ValueTooBigError<usize>),

#[error("Invalid Tcp packet")]
InvalidTcpPacket,

#[error("IO error: {0}")]
IoError(#[from] std::io::Error),

#[error("Accept Error")]
AcceptError,

Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::{
},
time::Duration,
};
use stream::IpStackStream;
use tokio::{
io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt},
select,
Expand All @@ -18,7 +17,7 @@ use tracing::{error, trace};

use crate::{
packet::IpStackPacketProtocol,
stream::{IpStackTcpStream, IpStackUdpStream, IpStackUnknownTransport},
stream::{IpStackStream, IpStackTcpStream, IpStackUdpStream, IpStackUnknownTransport},
};
mod error;
mod packet;
Expand Down
43 changes: 16 additions & 27 deletions src/packet.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};

use etherparse::{IpHeader, PacketHeaders, TcpHeader, UdpHeader, WriteError};
use etherparse::{NetHeaders, PacketHeaders, TcpHeader, UdpHeader};

use crate::error::IpStackError;

Expand Down Expand Up @@ -34,15 +34,15 @@ pub(crate) enum TransportHeader {
}

pub struct NetworkPacket {
pub(crate) ip: IpHeader,
pub(crate) ip: NetHeaders,
pub(crate) transport: TransportHeader,
pub(crate) payload: Vec<u8>,
}

impl NetworkPacket {
pub fn parse(buf: &[u8]) -> Result<Self, IpStackError> {
let p = PacketHeaders::from_ip_slice(buf).map_err(|_| IpStackError::InvalidPacket)?;
let ip = p.ip.ok_or(IpStackError::InvalidPacket)?;
let ip = p.net.ok_or(IpStackError::InvalidPacket)?;
let transport = match p.transport {
Some(etherparse::TransportHeader::Tcp(h)) => TransportHeader::Tcp(h),
Some(etherparse::TransportHeader::Udp(u)) => TransportHeader::Udp(u),
Expand All @@ -52,7 +52,7 @@ impl NetworkPacket {
let payload = if let TransportHeader::Unknown = transport {
buf[ip.header_len()..].to_vec()
} else {
p.payload.to_vec()
p.payload.slice().to_vec()
};

Ok(NetworkPacket {
Expand All @@ -75,12 +75,8 @@ impl NetworkPacket {
_ => 0,
};
match &self.ip {
IpHeader::Version4(ip, _) => {
SocketAddr::new(IpAddr::V4(Ipv4Addr::from(ip.source)), port)
}
IpHeader::Version6(ip, _) => {
SocketAddr::new(IpAddr::V6(Ipv6Addr::from(ip.source)), port)
}
NetHeaders::Ipv4(ip, _) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(ip.source)), port),
NetHeaders::Ipv6(ip, _) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(ip.source)), port),
}
}
pub fn dst_addr(&self) -> SocketAddr {
Expand All @@ -90,10 +86,10 @@ impl NetworkPacket {
_ => 0,
};
match &self.ip {
IpHeader::Version4(ip, _) => {
NetHeaders::Ipv4(ip, _) => {
SocketAddr::new(IpAddr::V4(Ipv4Addr::from(ip.destination)), port)
}
IpHeader::Version6(ip, _) => {
NetHeaders::Ipv6(ip, _) => {
SocketAddr::new(IpAddr::V6(Ipv6Addr::from(ip.destination)), port)
}
}
Expand All @@ -114,29 +110,22 @@ impl NetworkPacket {
}
pub fn to_bytes(&self) -> Result<Vec<u8>, IpStackError> {
let mut buf = Vec::new();
self.ip
.write(&mut buf)
.map_err(IpStackError::PacketWriteError)?;
match self.ip {
NetHeaders::Ipv4(ref ip, _) => ip.write(&mut buf)?,
NetHeaders::Ipv6(ref ip, _) => ip.write(&mut buf)?,
}
match self.transport {
TransportHeader::Tcp(ref h) => h
.write(&mut buf)
.map_err(WriteError::from)
.map_err(IpStackError::PacketWriteError)?,
TransportHeader::Udp(ref h) => {
h.write(&mut buf).map_err(IpStackError::PacketWriteError)?
}
TransportHeader::Tcp(ref h) => h.write(&mut buf)?,
TransportHeader::Udp(ref h) => h.write(&mut buf)?,
_ => {}
};
// self.transport
// .write(&mut buf)
// .map_err(IpStackError::PacketWriteError)?;
buf.extend_from_slice(&self.payload);
Ok(buf)
}
pub fn ttl(&self) -> u8 {
match &self.ip {
IpHeader::Version4(ip, _) => ip.time_to_live,
IpHeader::Version6(ip, _) => ip.hop_limit,
NetHeaders::Ipv4(ip, _) => ip.time_to_live,
NetHeaders::Ipv6(ip, _) => ip.hop_limit,
}
}
}
Expand Down
32 changes: 19 additions & 13 deletions src/stream/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,41 +119,47 @@ impl IpStackTcpStream {

let ip_header = match (self.dst_addr.ip(), self.src_addr.ip()) {
(std::net::IpAddr::V4(dst), std::net::IpAddr::V4(src)) => {
let mut ip_h = Ipv4Header::new(0, ttl, 6, dst.octets(), src.octets());
let payload_len =
self.calculate_payload_len(ip_h.header_len() as u16, tcp_header.header_len());
let mut ip_h = Ipv4Header::new(0, ttl, 6.into(), dst.octets(), src.octets())
.map_err(IpStackError::from)?;
let payload_len = self.calculate_payload_len(
ip_h.header_len() as u16,
tcp_header.header_len() as u16,
);
payload.truncate(payload_len as usize);
ip_h.payload_len = payload.len() as u16 + tcp_header.header_len();
ip_h.set_payload_len(payload.len() + tcp_header.header_len())
.map_err(IpStackError::from)?;
ip_h.dont_fragment = true;
etherparse::IpHeader::Version4(ip_h, Ipv4Extensions::default())
etherparse::NetHeaders::Ipv4(ip_h, Ipv4Extensions::default())
}
(std::net::IpAddr::V6(dst), std::net::IpAddr::V6(src)) => {
let mut ip_h = etherparse::Ipv6Header {
traffic_class: 0,
flow_label: 0,
flow_label: 0.try_into().map_err(IpStackError::from)?,
payload_length: 0,
next_header: 6,
next_header: 6.into(),
hop_limit: ttl,
source: dst.octets(),
destination: src.octets(),
};
let payload_len =
self.calculate_payload_len(ip_h.header_len() as u16, tcp_header.header_len());
let payload_len = self.calculate_payload_len(
ip_h.header_len() as u16,
tcp_header.header_len() as u16,
);
payload.truncate(payload_len as usize);
ip_h.payload_length = payload.len() as u16 + tcp_header.header_len();
ip_h.payload_length = (payload.len() + tcp_header.header_len()) as u16;

etherparse::IpHeader::Version6(ip_h, Ipv6Extensions::default())
etherparse::NetHeaders::Ipv6(ip_h, Ipv6Extensions::default())
}
_ => unreachable!(),
};

match ip_header {
etherparse::IpHeader::Version4(ref ip_header, _) => {
etherparse::NetHeaders::Ipv4(ref ip_header, _) => {
tcp_header.checksum = tcp_header
.calc_checksum_ipv4(ip_header, &payload)
.map_err(|_e| Error::from(ErrorKind::InvalidInput))?;
}
etherparse::IpHeader::Version6(ref ip_header, _) => {
etherparse::NetHeaders::Ipv6(ref ip_header, _) => {
tcp_header.checksum = tcp_header
.calc_checksum_ipv6(ip_header, &payload)
.map_err(|_e| Error::from(ErrorKind::InvalidInput))?;
Expand Down
16 changes: 9 additions & 7 deletions src/stream/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use tokio::{
// use crate::packet::TransportHeader;
use crate::{
packet::{NetworkPacket, TransportHeader},
TTL,
IpStackError, TTL,
};

pub struct IpStackUdpStream {
Expand Down Expand Up @@ -62,10 +62,12 @@ impl IpStackUdpStream {
fn create_rev_packet(&self, ttl: u8, mut payload: Vec<u8>) -> Result<NetworkPacket, Error> {
match (self.dst_addr.ip(), self.src_addr.ip()) {
(std::net::IpAddr::V4(dst), std::net::IpAddr::V4(src)) => {
let mut ip_h = Ipv4Header::new(0, ttl, 17, dst.octets(), src.octets());
let mut ip_h = Ipv4Header::new(0, ttl, 17.into(), dst.octets(), src.octets())
.map_err(IpStackError::from)?;
let line_buffer = self.mtu.saturating_sub(ip_h.header_len() as u16 + 8); // 8 is udp header size
payload.truncate(line_buffer as usize);
ip_h.payload_len = payload.len() as u16 + 8; // 8 is udp header size
ip_h.set_payload_len(payload.len() + 8)
.map_err(IpStackError::from)?; // 8 is udp header size
let udp_header = UdpHeader::with_ipv4_checksum(
self.dst_addr.port(),
self.src_addr.port(),
Expand All @@ -74,17 +76,17 @@ impl IpStackUdpStream {
)
.map_err(|_e| Error::from(ErrorKind::InvalidInput))?;
Ok(NetworkPacket {
ip: etherparse::IpHeader::Version4(ip_h, Ipv4Extensions::default()),
ip: etherparse::NetHeaders::Ipv4(ip_h, Ipv4Extensions::default()),
transport: TransportHeader::Udp(udp_header),
payload,
})
}
(std::net::IpAddr::V6(dst), std::net::IpAddr::V6(src)) => {
let mut ip_h = Ipv6Header {
traffic_class: 0,
flow_label: 0,
flow_label: 0.try_into().map_err(IpStackError::from)?,
payload_length: 0,
next_header: 17,
next_header: 17.into(),
hop_limit: ttl,
source: dst.octets(),
destination: src.octets(),
Expand All @@ -102,7 +104,7 @@ impl IpStackUdpStream {
)
.map_err(|_e| Error::from(ErrorKind::InvalidInput))?;
Ok(NetworkPacket {
ip: etherparse::IpHeader::Version6(ip_h, Ipv6Extensions::default()),
ip: etherparse::NetHeaders::Ipv6(ip_h, Ipv6Extensions::default()),
transport: TransportHeader::Udp(udp_header),
payload,
})
Expand Down
Loading

0 comments on commit 84705bd

Please sign in to comment.