aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2023-11-03 22:54:00 +0100
committerHimbeerserverDE <himbeerserverde@gmail.com>2023-11-03 22:54:00 +0100
commite3e3f28dd8a02377288665d8cf94126ad7eeb245 (patch)
tree0345eec72d429225a501deea6ad5bdec08f44e4a
parente9db07c2527b2be96a1b0bf7b54ec737ec46bd3c (diff)
create pppoe discovery socket
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/error.rs13
-rw-r--r--src/lib.rs3
-rw-r--r--src/supervisor.rs54
5 files changed, 72 insertions, 2 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d6fb31e..31623ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -262,12 +262,14 @@ dependencies = [
name = "rsdsl_pppoe3"
version = "0.1.0"
dependencies = [
+ "libc",
"ppproperly",
"rand",
"rsdsl_ip_config",
"serde",
"serde_json",
"socket2",
+ "thiserror",
"tokio",
]
diff --git a/Cargo.toml b/Cargo.toml
index 8db6101..162ec85 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,10 +6,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+libc = "0.2.149"
ppproperly = { git = "https://github.com/rsdsl/ppproperly.git", version = "0.1.0" }
rand = "0.8.5"
rsdsl_ip_config = { git = "https://github.com/rsdsl/ip_config.git", version = "0.2.3" }
serde = "1.0"
serde_json = "1.0"
socket2 = "0.5.5"
+thiserror = "1.0"
tokio = { version = "1.0", features = ["rt-multi-thread", "macros", "sync", "time"] }
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..8da1cfc
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,13 @@
+use std::{ffi, io};
+
+use thiserror::Error;
+
+#[derive(Debug, Error)]
+pub enum Error {
+ #[error("io: {0}")]
+ Io(#[from] io::Error),
+ #[error("interface name contains nul byte: {0}")]
+ Nul(#[from] ffi::NulError),
+}
+
+pub type Result<T> = std::result::Result<T, Error>;
diff --git a/src/lib.rs b/src/lib.rs
index 0e666a4..9692924 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,6 @@
+mod error;
+pub use error::*;
+
mod proto;
pub use proto::*;
diff --git a/src/supervisor.rs b/src/supervisor.rs
index 6905a92..a5d349d 100644
--- a/src/supervisor.rs
+++ b/src/supervisor.rs
@@ -1,3 +1,4 @@
+use crate::Result;
use crate::{
chap::ChapClient,
pap::PapClient,
@@ -5,10 +6,18 @@ use crate::{
proto::{NegotiationProtocol, ProtocolConfig},
};
+use std::ffi::CString;
use std::net::Ipv4Addr;
+use std::{io, mem};
use ppproperly::{IpCompressionProtocol, IpcpOpt, Ipv6cpOpt, LcpOpt, QualityProtocol};
-// use socket2::Socket;
+use socket2::{SockAddr, Socket};
+
+macro_rules! os_err {
+ () => {
+ return Err(io::Error::last_os_error().into());
+ };
+}
/// A client control instance for full dual stack PPPoE sessions.
#[derive(Debug)]
@@ -122,6 +131,47 @@ impl Client {
/// Runs the connection. Blocks the caller forever unless a panic occurs.
pub fn run(&self) {
- // let sock_disc = self.new_discovery_socket();
+ let sock_disc = self.new_discovery_socket();
+ }
+
+ fn new_discovery_socket(&self) -> Result<Socket> {
+ use libc::{
+ sockaddr_ll, sockaddr_storage, socklen_t, AF_PACKET, ETH_P_PPP_DISC, PF_PACKET,
+ SOCK_RAW,
+ };
+
+ let sock = Socket::new(
+ PF_PACKET.into(),
+ SOCK_RAW.into(),
+ Some(ETH_P_PPP_DISC.into()),
+ )?;
+
+ sock.set_broadcast(true)?;
+
+ let c_link = CString::new(&*self.link)?;
+
+ let ifi = unsafe { libc::if_nametoindex(c_link.as_ptr()) };
+ if ifi == 0 {
+ os_err!();
+ }
+
+ let sa = sockaddr_ll {
+ sll_family: AF_PACKET as u16,
+ sll_protocol: (ETH_P_PPP_DISC as u16).to_be(),
+ sll_ifindex: ifi as i32,
+ sll_hatype: 0,
+ sll_pkttype: 0,
+ sll_halen: 0,
+ sll_addr: [0; 8],
+ };
+
+ sock.bind(&unsafe {
+ SockAddr::new(
+ *mem::transmute::<*const sockaddr_ll, *const sockaddr_storage>(&sa),
+ mem::size_of_val(&sa) as socklen_t,
+ )
+ })?;
+
+ Ok(sock)
}
}