aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock18
-rw-r--r--Cargo.toml3
-rw-r--r--src/error.rs6
-rw-r--r--src/main.rs59
4 files changed, 83 insertions, 3 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4f78eb2..e27dea2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -27,6 +27,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]]
+name = "arrayvec"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
+
+[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -238,6 +244,15 @@ dependencies = [
]
[[package]]
+name = "etherparse"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "827292ea592108849932ad8e30218f8b1f21c0dfd0696698a18b5d0aed62d990"
+dependencies = [
+ "arrayvec",
+]
+
+[[package]]
name = "filetime"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -925,9 +940,10 @@ dependencies = [
[[package]]
name = "rsdsl_pppoe"
-version = "0.1.1"
+version = "0.1.2"
dependencies = [
"byteorder",
+ "etherparse",
"md5",
"pppoe",
"rand",
diff --git a/Cargo.toml b/Cargo.toml
index 0d3ade2..341d8e4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rsdsl_pppoe"
-version = "0.1.1"
+version = "0.1.2"
authors = ["HimbeerserverDE <himbeerserverde@gmail.com>"]
license = "MIT"
edition = "2021"
@@ -9,6 +9,7 @@ edition = "2021"
[dependencies]
byteorder = "1.4.3"
+etherparse = "0.13.0"
md5 = "0.7.0"
pppoe = { git = "https://github.com/rsdsl/pppoe-rs.git", version = "0.1.0", features = ["socket"] }
rand = "0.8.5"
diff --git a/src/error.rs b/src/error.rs
index 1411f3a..d35730b 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -65,6 +65,12 @@ pub enum Error {
Pppoe(pppoe::error::Error),
#[error("pppoe parse error: {0:?}")]
PppoeParse(pppoe::error::ParseError),
+ #[error("etherparse read error: {0}")]
+ EtherParseRead(#[from] etherparse::ReadError),
+ #[error("etherparse tcp option write error: {0}")]
+ EtherParseTcpOptionWrite(#[from] etherparse::TcpOptionWriteError),
+ #[error("etherparse value error: {0}")]
+ EtherParseValue(#[from] etherparse::ValueError),
#[error("rsdsl_netlinkd error")]
RsdslNetlinkd(#[from] rsdsl_netlinkd::error::Error),
#[error("serde_json error")]
diff --git a/src/main.rs b/src/main.rs
index 5a7f047..1be7d5f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,11 +8,14 @@ use std::sync::{Arc, Mutex};
use std::thread;
use byteorder::{ByteOrder, NetworkEndian as NE};
+use etherparse::{Ipv4Header, TcpHeader, TcpOptionElement};
use pppoe::packet::IPV4;
use rsdsl_ip_config::IpConfig;
use rsdsl_netlinkd::link;
use tun_tap::{Iface, Mode};
+const IPPROTO_TCP: u8 = 0x06;
+
fn prepend<T>(v: Vec<T>, s: &[T]) -> Vec<T>
where
T: Clone,
@@ -22,6 +25,50 @@ where
tmp
}
+fn clamp_mss_if_needed(buf: &mut [u8]) -> Result<()> {
+ let ipv4_header = Ipv4Header::from_slice(&buf[4..])?.0;
+
+ if ipv4_header.protocol == IPPROTO_TCP {
+ let ipv4_header_bytes = ipv4_header.ihl() as usize * 4;
+
+ let mut tcp_header = TcpHeader::from_slice(&buf[4 + ipv4_header_bytes..])?.0;
+
+ if tcp_header.syn {
+ let tcp_header_bytes = tcp_header.header_len() as usize;
+
+ let mut opts = Vec::new();
+ for opt in tcp_header.options_iterator() {
+ match opt {
+ Ok(mut opt) => {
+ if let TcpOptionElement::MaximumSegmentSize(_) = opt {
+ opt = TcpOptionElement::MaximumSegmentSize(1492);
+ }
+
+ opts.push(opt);
+ }
+ Err(e) => println!("[pppoe] ignore invalid tcp opt: {}", e),
+ }
+ }
+
+ tcp_header.set_options(&opts)?;
+ tcp_header.checksum = tcp_header.calc_checksum_ipv4(
+ &ipv4_header,
+ &buf[4 + ipv4_header_bytes + tcp_header_bytes..],
+ )?;
+
+ let tcp_header_bytes = tcp_header.header_len() as usize;
+
+ let mut hdr = Vec::new();
+ tcp_header.write(&mut hdr)?;
+
+ buf[4 + ipv4_header_bytes..4 + ipv4_header_bytes + tcp_header_bytes]
+ .copy_from_slice(&hdr);
+ }
+ }
+
+ Ok(())
+}
+
fn tun2ppp(tx: mpsc::Sender<Option<Vec<u8>>>, tun: Arc<Iface>) -> Result<()> {
loop {
let mut buf = [0; 4 + 1492];
@@ -32,7 +79,7 @@ fn tun2ppp(tx: mpsc::Sender<Option<Vec<u8>>>, tun: Arc<Iface>) -> Result<()> {
continue;
}
};
- let buf = &buf[..n];
+ let buf = &mut buf[..n];
let ether_type = NE::read_u16(&buf[2..4]);
if ether_type != IPV4 {
@@ -43,6 +90,11 @@ fn tun2ppp(tx: mpsc::Sender<Option<Vec<u8>>>, tun: Arc<Iface>) -> Result<()> {
continue;
}
+ match clamp_mss_if_needed(buf) {
+ Ok(_) => {}
+ Err(e) => println!("[pppoe] ignore outbound mss clamping error: {}", e),
+ }
+
tx.send(Some(buf[4..].to_vec()))?;
}
}
@@ -54,6 +106,11 @@ fn ppp2tun(rx: Arc<Mutex<mpsc::Receiver<Vec<u8>>>>, tun: Arc<Iface>) -> Result<(
NE::write_u16(&mut packet_info[2..4], IPV4);
while let Ok(mut buf) = rx.recv() {
+ match clamp_mss_if_needed(&mut buf) {
+ Ok(_) => {}
+ Err(e) => println!("[pppoe] ignore inbound mss clamping error: {}", e),
+ }
+
buf = prepend(buf, &packet_info);
let n = match tun.send(&buf) {