aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2023-08-13 16:10:50 +0200
committerHimbeerserverDE <himbeerserverde@gmail.com>2023-08-13 16:10:50 +0200
commit736021c1bfca1d20e6219526e80c541e0cbb0715 (patch)
treebda6a94ad69987ea3fb36ed1818be5b50b54c896 /src
parent0eb73b99877de032f09a94ac5ccf9d3fd0627499 (diff)
log incoming advertisements
Diffstat (limited to 'src')
-rw-r--r--src/error.rs9
-rw-r--r--src/main.rs84
2 files changed, 75 insertions, 18 deletions
diff --git a/src/error.rs b/src/error.rs
index c35ff38..83cfc98 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,11 +1,20 @@
use std::{ffi, io, net};
+use dhcproto::v6::Status;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
+ #[error("no ia_pd")]
+ NoIAPD,
+ #[error("no ia_pd status code")]
+ NoIAPDStatus,
+ #[error("no ia_prefix")]
+ NoIAPrefix,
#[error("incomplete transmission")]
PartialSend,
+ #[error("unsuccessful pd status code")]
+ UnsuccessfulPd(Status),
#[error("parse address: {0}")]
AddrParse(#[from] net::AddrParseError),
diff --git a/src/main.rs b/src/main.rs
index 54c338c..ee8a935 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,22 +8,23 @@ use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
-use dhcproto::v6::{duid::Duid, DhcpOption, Message, MessageType, OptionCode, IAPD, ORO};
-use dhcproto::{Decodable, Decoder, Encodable, Encoder};
+use dhcproto::v6::{duid::Duid, DhcpOption, Message, MessageType, OptionCode, Status, IAPD, ORO};
+use dhcproto::{Decodable, Decoder, Encodable, Encoder, Name};
use rsdsl_dhcp6::util::setsockopt;
use rsdsl_dhcp6::{Error, Result};
use rsdsl_ip_config::DsConfig;
use rsdsl_netlinkd::link;
use socket2::{Domain, SockAddr, Socket, Type};
+use trust_dns_proto::serialize::binary::BinDecodable;
const BUFSIZE: usize = 1500;
#[derive(Clone, Debug, Eq, PartialEq)]
enum State {
Solicit(Vec<u8>),
- Request,
- Active,
- Renew,
+ Request(Vec<u8>, SocketAddrV6),
+ Active(Vec<u8>, SocketAddrV6),
+ Renew(Vec<u8>, SocketAddrV6),
}
impl Default for State {
@@ -77,8 +78,9 @@ fn main() -> Result<()> {
sock.bind(&address.into())?;
let sock2 = sock.try_clone()?;
+ let state2 = state.clone();
thread::spawn(move || loop {
- match tick(&sock2, state.clone()) {
+ match tick(&sock2, state2.clone()) {
Ok(_) => thread::sleep(Duration::from_secs(3)),
Err(e) => println!("can't tick on ppp0: {}", e),
}
@@ -95,32 +97,78 @@ fn main() -> Result<()> {
let remote = remote.as_socket_ipv6().unwrap();
- match handle_response(&sock, buf) {
+ match handle_response(&sock, buf, state.clone()) {
Ok(_) => {}
Err(e) => println!("can't handle pkt from {} on ppp0: {}", remote, e),
}
}
}
-fn handle_response(sock: &Socket, buf: &[u8]) -> Result<()> {
- // let dst: SocketAddrV6 = "[ff02::1:2]:547".parse()?;
-
- // let msg = Message::decode(&mut Decoder::new(buf))?;
+fn handle_response(sock: &Socket, buf: &[u8], state: Arc<Mutex<State>>) -> Result<()> {
+ let dst: SocketAddrV6 = "[ff02::1:2]:547".parse()?;
- // let typ = msg.msg_type();
- // match typ {
- // MessageType::Advertise => {}
- // }
+ let msg = Message::decode(&mut Decoder::new(buf))?;
+
+ let typ = msg.msg_type();
+ match typ {
+ MessageType::Advertise => {
+ let opts = msg.opts();
+
+ let aftr = opts.get(OptionCode::AftrName).map(|v| match v {
+ DhcpOption::Unknown(unk) => {
+ Name::from_bytes(unk.data()).expect("invalid aftr name format")
+ }
+ _ => unreachable!(),
+ });
+
+ let ia_pd = match opts.get(OptionCode::IAPD).ok_or(Error::NoIAPD)? {
+ DhcpOption::IAPD(ia_pd) => ia_pd,
+ _ => unreachable!(),
+ };
+
+ let status = match ia_pd
+ .opts
+ .get(OptionCode::StatusCode)
+ .ok_or(Error::NoIAPDStatus)?
+ {
+ DhcpOption::StatusCode(status) => status,
+ _ => unreachable!(),
+ };
+
+ if status.status != Status::Success {
+ return Err(Error::UnsuccessfulPd(status.status));
+ }
+
+ let ia_prefix = match ia_pd
+ .opts
+ .get(OptionCode::IAPrefix)
+ .ok_or(Error::NoIAPrefix)?
+ {
+ DhcpOption::IAPrefix(ia_prefix) => ia_prefix,
+ _ => unreachable!(),
+ };
+
+ println!(
+ " <- advertise pd {}/{} valid {} pref {}, aftr {}",
+ ia_prefix.prefix_ip,
+ ia_prefix.prefix_len,
+ ia_prefix.valid_lifetime,
+ ia_prefix.preferred_lifetime,
+ aftr.map(|v| v.to_utf8()).unwrap_or("unset".into())
+ );
+ }
+ _ => todo!(),
+ }
Ok(())
}
fn tick(sock: &Socket, state: Arc<Mutex<State>>) -> Result<()> {
- let dst: SocketAddrV6 = "[ff02::1:2]:547".parse()?;
-
let state = state.lock().expect("state mutex is poisoned");
match *state {
State::Solicit(ref client_id) => {
+ let dst: SocketAddrV6 = "[ff02::1:2]:547".parse()?;
+
let mut req = Message::new(MessageType::Solicit);
let opts = req.opts_mut();
@@ -140,7 +188,7 @@ fn tick(sock: &Socket, state: Arc<Mutex<State>>) -> Result<()> {
send_to_exact(sock, &req_buf, &dst.into())?;
- println!("solicit pd 1 aftr");
+ println!(" -> solicit pd 1 aftr");
Ok(())
}
_ => todo!(),