aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs59
1 files changed, 58 insertions, 1 deletions
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) {