diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-08-13 16:10:50 +0200 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-08-13 16:10:50 +0200 |
commit | 736021c1bfca1d20e6219526e80c541e0cbb0715 (patch) | |
tree | bda6a94ad69987ea3fb36ed1818be5b50b54c896 /src | |
parent | 0eb73b99877de032f09a94ac5ccf9d3fd0627499 (diff) |
log incoming advertisements
Diffstat (limited to 'src')
-rw-r--r-- | src/error.rs | 9 | ||||
-rw-r--r-- | src/main.rs | 84 |
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!(), |