aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2023-05-11 18:03:41 +0200
committerHimbeerserverDE <himbeerserverde@gmail.com>2023-05-11 18:03:41 +0200
commit8c39c7f86fbf8f35b20239bd9dbd6701ab1c2664 (patch)
tree321350664847e7c6ead1997f6cfa4de94d7123b5
parentc08c7e1eeb24592aa2fcd026ec47515fdd6ab699 (diff)
implement handshake timeouts0.1.5
should fix #2
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/client.rs82
-rw-r--r--src/error.rs2
4 files changed, 79 insertions, 9 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9c41074..ac4b468 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -869,7 +869,7 @@ dependencies = [
[[package]]
name = "rsdsl_pppoe"
-version = "0.1.4"
+version = "0.1.5"
dependencies = [
"byteorder",
"md5",
diff --git a/Cargo.toml b/Cargo.toml
index 04185da..d0a93e9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rsdsl_pppoe"
-version = "0.1.4"
+version = "0.1.5"
authors = ["HimbeerserverDE <himbeerserverde@gmail.com>"]
license = "MIT"
edition = "2021"
diff --git a/src/client.rs b/src/client.rs
index b28773a..1bf205e 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -6,7 +6,7 @@ use std::num::NonZeroU16;
use std::sync::mpsc;
use std::sync::{Arc, Mutex, RwLock};
use std::thread;
-use std::time::Duration;
+use std::time::{Duration, Instant};
use byteorder::{ByteOrder, NetworkEndian as NE};
@@ -44,6 +44,20 @@ impl Default for State {
}
}
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum SessionState {
+ Link,
+ Auth,
+ Network,
+ Open,
+}
+
+impl Default for SessionState {
+ fn default() -> Self {
+ Self::Link
+ }
+}
+
#[derive(Clone, Debug)]
pub struct Client {
inner: Arc<RwLock<ClientRef>>,
@@ -60,6 +74,7 @@ impl Client {
started: false,
host_uniq: rand::random(),
state: State::default(),
+ session_state: SessionState::default(),
peer: BROADCAST,
magic_number: rand::random(),
error: String::new(),
@@ -158,10 +173,18 @@ impl Client {
self.inner.read().unwrap().state
}
+ fn session_state(&self) -> SessionState {
+ self.inner.read().unwrap().session_state
+ }
+
fn set_state(&self, state: State) {
self.inner.write().unwrap().state = state;
}
+ fn set_session_state(&self, state: SessionState) {
+ self.inner.write().unwrap().session_state = state;
+ }
+
fn session_id(&self) -> Result<NonZeroU16> {
match self.state() {
State::Session(session_id) => Ok(session_id),
@@ -319,6 +342,31 @@ impl Client {
});
}
+ fn send_timeout(&self, buf: &[u8], state: SessionState, msg: impl Into<String>) {
+ const MAX: u8 = 10;
+
+ let this = self.clone();
+ let buf = buf.to_vec();
+ let msg = msg.into();
+
+ thread::spawn(move || {
+ let mut i = 1;
+ while this.session_state() == state && i <= MAX {
+ match this.send(&buf) {
+ Ok(_) => println!("[pppoe] (re)transmit {}/{}: {}", i, MAX, &msg),
+ Err(e) => println!("[pppoe] (re)transmit {}/{} error: {}", i, MAX, e),
+ }
+
+ thread::sleep(Duration::from_secs(3));
+ i += 1
+ }
+
+ if i > MAX {
+ this.terminate(Err(Error::TooManyRetransmissions(msg)));
+ }
+ });
+ }
+
fn recv<'a>(&'a self, buf: &'a mut [u8; BUFSIZE]) -> Result<Packet> {
let mut n;
@@ -397,9 +445,8 @@ impl Client {
lcp::HeaderBuilder::create_configure_request(&mut request[22..26 + limit])?;
self.new_lcp_packet(request)?;
- self.send(request)?;
+ self.send_timeout(request, SessionState::Link, "lcp configure-req");
- println!("[pppoe] send lcp configure-req");
Ok(())
}
@@ -426,9 +473,8 @@ impl Client {
pap::HeaderBuilder::create_auth_request(&mut auth_req[22..])?;
self.new_pap_packet(auth_req)?;
- self.send(auth_req)?;
+ self.send_timeout(auth_req, SessionState::Auth, "pap authentication request");
- println!("[pppoe] send pap authentication request");
Ok(())
}
@@ -457,9 +503,8 @@ impl Client {
ipcp::HeaderBuilder::create_configure_request(&mut request[22..26 + limit])?;
self.new_ipcp_packet(request)?;
- self.send(request)?;
+ self.send_timeout(request, SessionState::Network, "ipcp configure-req");
- println!("[pppoe] send ipcp configure-req");
Ok(())
}
@@ -499,6 +544,22 @@ impl Client {
println!("[pppoe] recv lcp configure-req, opts: {:?}", opts);
if auth_is_supported {
+ self.set_session_state(SessionState::Auth);
+
+ let this = self.clone();
+ thread::spawn(move || {
+ let start = Instant::now();
+ while this.session_state() == SessionState::Auth
+ && start.duration_since(Instant::now()).as_secs() < 10
+ {
+ thread::sleep(Duration::from_secs(1));
+ }
+
+ if this.session_state() == SessionState::Auth {
+ this.terminate(Err(Error::AuthTimeout));
+ }
+ });
+
let limit = lcp.payload().len();
let mut ack = Vec::new();
@@ -656,6 +717,8 @@ impl Client {
pap::AUTH_ACK => {
println!("[pppoe] auth success");
+ self.set_session_state(SessionState::Network);
+
self.configure_ip()?;
Ok(())
}
@@ -707,6 +770,8 @@ impl Client {
chap::SUCCESS => {
println!("[pppoe] auth success");
+ self.set_session_state(SessionState::Network);
+
self.configure_ip()?;
Ok(())
}
@@ -804,6 +869,8 @@ impl Client {
})
.ok_or(Error::MissingSecondaryDns)?;
+ self.set_session_state(SessionState::Open);
+
self.set_ip_config(ip_config);
tx.send(ip_config)?;
@@ -990,6 +1057,7 @@ struct ClientRef {
started: bool,
host_uniq: [u8; 16],
state: State,
+ session_state: SessionState,
peer: [u8; 6],
magic_number: u32,
error: String,
diff --git a/src/error.rs b/src/error.rs
index 1411f3a..33dba2c 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -15,6 +15,8 @@ pub enum Error {
PartialTransmission,
#[error("too many retransmissions: {0}")]
TooManyRetransmissions(String),
+ #[error("authentication timeout")]
+ AuthTimeout,
#[error("invalid pkt code {0}")]
InvalidCode(u8),
#[error("unexpected pads")]