WIP/parser: added parsers for some formats
This commit is contained in:
parent
55ee873280
commit
df9e29c4a4
|
@ -1,3 +1,4 @@
|
|||
#![feature(ip_bits)]
|
||||
#![feature(async_closure)]
|
||||
// TODO(ishan): Eventually we'll have a listener and transmitter module for every thing we want to
|
||||
// support. So, 1 for MDNS, another for WSDD?
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use crate::socket::{
|
||||
Interface as MulticastInterface, MulticastGroup, MulticastOptions, MulticastSocket,
|
||||
};
|
||||
use crate::socket::{Interface as MulticastInterface, MulticastOptions, MulticastSocket};
|
||||
use crate::Config;
|
||||
use dns_parser::Packet;
|
||||
use log::{info, trace, warn};
|
||||
|
@ -19,10 +17,7 @@ impl Mdns {
|
|||
let multicast_socket = MulticastSocket::new(
|
||||
MulticastOptions::default(),
|
||||
MulticastSocket::all_interfaces().unwrap(),
|
||||
MulticastGroup {
|
||||
ipv4: SocketAddrV4::new(Ipv4Addr::new(224, 0, 0, 251), 5353),
|
||||
port: 5353,
|
||||
},
|
||||
SocketAddrV4::new(Ipv4Addr::new(224, 0, 0, 251), 5353),
|
||||
)
|
||||
.expect("error in creating multicast socket");
|
||||
|
||||
|
@ -55,12 +50,11 @@ impl Mdns {
|
|||
|
||||
pub fn process_packet(&self, msg: crate::socket::Message) {
|
||||
// TODO: Generalize this to parse any type of supported packet
|
||||
trace!("{:0x?}", msg.data);
|
||||
let packet = Packet::parse(&msg.data).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"failed to parse packet as a dns packet: {:?} error = {:?}, loose_string = {}",
|
||||
msg,
|
||||
e,
|
||||
String::from_utf8_lossy(&msg.data)
|
||||
"failed to parse packet as a dns packet. origin = {:?} interface = {:?} error = {:?}, loose_string = {:02x?}",
|
||||
msg.origin_address,msg.interface, e, msg.data,
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -80,7 +74,6 @@ impl Mdns {
|
|||
);
|
||||
|
||||
let interfaces = get_if_addrs::get_if_addrs().unwrap();
|
||||
trace!("Interfaces: {:?}", interfaces);
|
||||
for conf in &self.config.mdns {
|
||||
let mut dst_ifs = vec![];
|
||||
|
||||
|
|
|
@ -10,4 +10,7 @@ pub enum ParserError {
|
|||
|
||||
#[error("Label is not UTF-8")]
|
||||
LabelIsNotUTF8,
|
||||
|
||||
#[error("Unknown rtype: {0}")]
|
||||
UnknownRType(u16),
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
#![allow(unused)]
|
||||
|
||||
mod header;
|
||||
use std::task::Wake;
|
||||
|
||||
pub use header::*;
|
||||
mod error;
|
||||
pub use error::*;
|
||||
|
@ -6,29 +10,87 @@ mod question;
|
|||
pub use question::*;
|
||||
mod resource_record;
|
||||
pub use resource_record::*;
|
||||
mod qname;
|
||||
pub use qname::*;
|
||||
mod rdata;
|
||||
pub use rdata::*;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DnsPacket {
|
||||
pub header: Header,
|
||||
pub questions: Vec<Question>,
|
||||
pub answers: Vec<ResourceRecord>,
|
||||
// pub authority: Authority,
|
||||
// pub additional: Additional,
|
||||
pub authority: Vec<ResourceRecord>,
|
||||
pub additional: Vec<ResourceRecord>,
|
||||
}
|
||||
|
||||
impl DnsPacket {
|
||||
pub fn parse(data: &[u8]) -> Result<Self, ParserError> {
|
||||
let header = Header::parse(data)?;
|
||||
let (questions, read) = DnsPacket::parse_questions(&header, data)?;
|
||||
let (answers, read) = DnsPacket::parse_answers(&header, data, read)?;
|
||||
let (authority, read) = DnsPacket::parse_authority(&header, data, read)?;
|
||||
let (additional, read) = DnsPacket::parse_additional(&header, data, read)?;
|
||||
|
||||
Ok(Self {
|
||||
header,
|
||||
questions,
|
||||
|
||||
..Default::default()
|
||||
answers,
|
||||
additional,
|
||||
authority,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_additional(
|
||||
header: &Header,
|
||||
data: &[u8],
|
||||
mut offset: usize,
|
||||
) -> Result<(Vec<ResourceRecord>, usize), ParserError> {
|
||||
let mut out = Vec::with_capacity(header.an_count as usize);
|
||||
|
||||
for _ in 0..header.ar_count {
|
||||
let (q, read) = ResourceRecord::parse(&data[offset..], data)?;
|
||||
|
||||
offset += read;
|
||||
out.push(q);
|
||||
}
|
||||
|
||||
Ok((out, offset))
|
||||
}
|
||||
|
||||
fn parse_authority(
|
||||
header: &Header,
|
||||
data: &[u8],
|
||||
mut offset: usize,
|
||||
) -> Result<(Vec<ResourceRecord>, usize), ParserError> {
|
||||
let mut out = Vec::with_capacity(header.an_count as usize);
|
||||
|
||||
for _ in 0..header.ns_count {
|
||||
let (q, read) = ResourceRecord::parse(&data[offset..], data)?;
|
||||
|
||||
offset += read;
|
||||
out.push(q);
|
||||
}
|
||||
|
||||
Ok((out, offset))
|
||||
}
|
||||
fn parse_answers(
|
||||
header: &Header,
|
||||
data: &[u8],
|
||||
mut offset: usize,
|
||||
) -> Result<(Vec<ResourceRecord>, usize), ParserError> {
|
||||
let mut out = Vec::with_capacity(header.an_count as usize);
|
||||
|
||||
for _ in 0..header.an_count {
|
||||
let (q, read) = ResourceRecord::parse(&data[offset..], data)?;
|
||||
|
||||
offset += read;
|
||||
out.push(q);
|
||||
}
|
||||
|
||||
Ok((out, offset))
|
||||
}
|
||||
|
||||
fn parse_questions(
|
||||
header: &Header,
|
||||
data: &[u8],
|
||||
|
@ -137,10 +199,64 @@ mod test {
|
|||
0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x11, 0x93, 0x00, 0x11, 0x0e, 0x49, 0x73, 0x68,
|
||||
0x61, 0x6e, 0xe2, 0x80, 0x99, 0x73, 0x20, 0x69, 0x50, 0x61, 0x64, 0xc0, 0x0c,
|
||||
],
|
||||
vec![
|
||||
0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x05, 0x01, 0x44,
|
||||
0x01, 0x33, 0x01, 0x42, 0x01, 0x39, 0x01, 0x45, 0x01, 0x44, 0x01, 0x45, 0x01, 0x35,
|
||||
0x01, 0x32, 0x01, 0x36, 0x01, 0x36, 0x01, 0x46, 0x01, 0x37, 0x01, 0x36, 0x01, 0x43,
|
||||
0x01, 0x31, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30,
|
||||
0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30,
|
||||
0x01, 0x38, 0x01, 0x45, 0x01, 0x46, 0x03, 0x69, 0x70, 0x36, 0x04, 0x61, 0x72, 0x70,
|
||||
0x61, 0x00, 0x00, 0x0c, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x13, 0x0b, 0x49,
|
||||
0x73, 0x68, 0x61, 0x6e, 0x73, 0x2d, 0x69, 0x50, 0x61, 0x64, 0x05, 0x6c, 0x6f, 0x63,
|
||||
0x61, 0x6c, 0x00, 0x01, 0x43, 0x01, 0x39, 0x01, 0x43, 0x01, 0x32, 0x01, 0x31, 0x01,
|
||||
0x35, 0x01, 0x33, 0x01, 0x30, 0x01, 0x46, 0x01, 0x30, 0x01, 0x34, 0x01, 0x36, 0x01,
|
||||
0x33, 0x01, 0x38, 0x01, 0x34, 0x01, 0x30, 0x01, 0x30, 0x01, 0x31, 0x01, 0x30, 0x01,
|
||||
0x30, 0x01, 0x34, 0x01, 0x30, 0x01, 0x30, 0x01, 0x34, 0x01, 0x30, 0x01, 0x34, 0x01,
|
||||
0x30, 0x01, 0x36, 0x01, 0x41, 0x01, 0x30, 0x01, 0x41, 0x01, 0x32, 0xc0, 0x4c, 0x00,
|
||||
0x0c, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x02, 0xc0, 0x60, 0x02, 0x35, 0x30,
|
||||
0x02, 0x31, 0x30, 0x01, 0x30, 0x02, 0x31, 0x30, 0x07, 0x69, 0x6e, 0x2d, 0x61, 0x64,
|
||||
0x64, 0x72, 0xc0, 0x50, 0x00, 0x0c, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x02,
|
||||
0xc0, 0x60, 0x0e, 0x49, 0x73, 0x68, 0x61, 0x6e, 0xe2, 0x80, 0x99, 0x73, 0x20, 0x69,
|
||||
0x50, 0x61, 0x64, 0x0f, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x69, 0x6f, 0x6e,
|
||||
0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x04, 0x5f, 0x74, 0x63, 0x70, 0xc0, 0x6c, 0x00, 0x10,
|
||||
0x80, 0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x82, 0x07, 0x72, 0x70, 0x4d, 0x61, 0x63,
|
||||
0x3d, 0x30, 0x11, 0x72, 0x70, 0x48, 0x4e, 0x3d, 0x61, 0x37, 0x33, 0x33, 0x36, 0x31,
|
||||
0x64, 0x61, 0x31, 0x32, 0x37, 0x63, 0x0c, 0x72, 0x70, 0x46, 0x6c, 0x3d, 0x30, 0x78,
|
||||
0x33, 0x30, 0x30, 0x30, 0x30, 0x11, 0x72, 0x70, 0x48, 0x41, 0x3d, 0x35, 0x62, 0x32,
|
||||
0x36, 0x39, 0x61, 0x65, 0x30, 0x35, 0x32, 0x32, 0x33, 0x0d, 0x72, 0x70, 0x56, 0x72,
|
||||
0x3d, 0x35, 0x31, 0x30, 0x2e, 0x37, 0x31, 0x2e, 0x31, 0x11, 0x72, 0x70, 0x41, 0x44,
|
||||
0x3d, 0x63, 0x30, 0x31, 0x66, 0x33, 0x61, 0x63, 0x39, 0x38, 0x66, 0x63, 0x38, 0x11,
|
||||
0x72, 0x70, 0x48, 0x49, 0x3d, 0x35, 0x36, 0x34, 0x39, 0x31, 0x37, 0x31, 0x64, 0x33,
|
||||
0x66, 0x61, 0x38, 0x16, 0x72, 0x70, 0x42, 0x41, 0x3d, 0x34, 0x45, 0x3a, 0x31, 0x46,
|
||||
0x3a, 0x32, 0x33, 0x3a, 0x37, 0x44, 0x3a, 0x34, 0x46, 0x3a, 0x30, 0x33, 0x09, 0x5f,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x07, 0x5f, 0x64, 0x6e, 0x73, 0x2d,
|
||||
0x73, 0x64, 0x04, 0x5f, 0x75, 0x64, 0x70, 0xc0, 0x6c, 0x00, 0x0c, 0x00, 0x01, 0x00,
|
||||
0x00, 0x11, 0x94, 0x00, 0x02, 0xc0, 0xf1, 0xc0, 0xf1, 0x00, 0x0c, 0x00, 0x01, 0x00,
|
||||
0x00, 0x11, 0x94, 0x00, 0x02, 0xc0, 0xe2, 0x0e, 0x49, 0x73, 0x68, 0x61, 0x6e, 0xe2,
|
||||
0x80, 0x99, 0x73, 0x20, 0x69, 0x50, 0x61, 0x64, 0x0c, 0x5f, 0x64, 0x65, 0x76, 0x69,
|
||||
0x63, 0x65, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0xc1, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00,
|
||||
0x00, 0x11, 0x94, 0x00, 0x0d, 0x0c, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x3d, 0x4a, 0x35,
|
||||
0x32, 0x32, 0x41, 0x50, 0xc0, 0xe2, 0x00, 0x21, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xda, 0x42, 0xc0, 0x60, 0xc0, 0x60, 0x00, 0x1c,
|
||||
0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x10, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1c, 0x67, 0xf6, 0x62, 0x5e, 0xde, 0x9b, 0x3d, 0xc0, 0x60, 0x00, 0x1c,
|
||||
0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x10, 0x2a, 0x0a, 0x60, 0x40, 0x40, 0x04,
|
||||
0x00, 0x10, 0x04, 0x83, 0x64, 0x0f, 0x03, 0x51, 0x2c, 0x9c, 0xc0, 0x60, 0x00, 0x01,
|
||||
0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x04, 0x0a, 0x00, 0x0a, 0x32, 0xc0, 0x0c,
|
||||
0x00, 0x2f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x06, 0xc0, 0x0c, 0x00, 0x02,
|
||||
0x00, 0x08, 0xc0, 0x73, 0x00, 0x2f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x06,
|
||||
0xc0, 0x73, 0x00, 0x02, 0x00, 0x08, 0xc0, 0xc1, 0x00, 0x2f, 0x80, 0x01, 0x00, 0x00,
|
||||
0x00, 0x78, 0x00, 0x06, 0xc0, 0xc1, 0x00, 0x02, 0x00, 0x08, 0xc0, 0xe2, 0x00, 0x2f,
|
||||
0x80, 0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x09, 0xc0, 0xe2, 0x00, 0x05, 0x00, 0x00,
|
||||
0x80, 0x00, 0x40, 0xc0, 0x60, 0x00, 0x2f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00,
|
||||
0x08, 0xc0, 0x60, 0x00, 0x04, 0x40, 0x00, 0x00, 0x08,
|
||||
],
|
||||
];
|
||||
|
||||
for input in inputs.iter() {
|
||||
assert!(DnsPacket::parse(input).is_ok());
|
||||
let output = DnsPacket::parse(input);
|
||||
println!("{:#?}", output);
|
||||
assert!(output.is_ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
59
src/parser/qname.rs
Normal file
59
src/parser/qname.rs
Normal file
|
@ -0,0 +1,59 @@
|
|||
use crate::ParserError;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Qname {}
|
||||
|
||||
impl Qname {
|
||||
pub fn read(data: &[u8], original: &[u8]) -> Result<(String, usize), ParserError> {
|
||||
let mut parse_data = data;
|
||||
let mut out = Vec::new();
|
||||
let mut offset = 0;
|
||||
let mut byte = parse_data[offset];
|
||||
let mut bytes_read = 1;
|
||||
|
||||
let mut return_pos: Option<usize> = None;
|
||||
|
||||
loop {
|
||||
match byte {
|
||||
0 => {
|
||||
out.pop();
|
||||
|
||||
return Ok((
|
||||
String::from_utf8(out).map_err(|_| ParserError::LabelIsNotUTF8)?,
|
||||
if let Some(p) = return_pos {
|
||||
p + 2
|
||||
} else {
|
||||
bytes_read
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
v if v & 0b1100_0000 == 0b1100_0000 => {
|
||||
let nof = (((v & 0b0011_1111) as usize) << 8) | parse_data[offset + 1] as usize;
|
||||
|
||||
if nof >= original.len() {
|
||||
return Err(ParserError::UnexpectedEOP);
|
||||
}
|
||||
|
||||
if return_pos.is_none() {
|
||||
return_pos = Some(offset);
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
parse_data = &original[nof..];
|
||||
byte = parse_data[0];
|
||||
}
|
||||
|
||||
_ => {
|
||||
out.extend(&parse_data[offset + 1..offset + 1 + byte as usize]);
|
||||
out.push(b'.');
|
||||
|
||||
offset += byte as usize + 1;
|
||||
bytes_read += byte as usize + 1;
|
||||
|
||||
byte = parse_data[offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::ParserError;
|
||||
use crate::{ParserError, Qname};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Question {
|
||||
|
@ -10,7 +10,7 @@ pub struct Question {
|
|||
|
||||
impl Question {
|
||||
pub fn parse(data: &[u8], original: &[u8]) -> Result<(Self, usize), ParserError> {
|
||||
let (qname, mut read) = Self::read_label(data, original)?;
|
||||
let (qname, mut read) = Qname::read(data, original)?;
|
||||
|
||||
let qtype = u16::from_be_bytes([data[read], data[read + 1]]);
|
||||
read += 2;
|
||||
|
@ -30,57 +30,4 @@ impl Question {
|
|||
read,
|
||||
))
|
||||
}
|
||||
|
||||
fn read_label(data: &[u8], original: &[u8]) -> Result<(String, usize), ParserError> {
|
||||
let mut parse_data = data;
|
||||
let mut out = Vec::new();
|
||||
let mut offset = 0;
|
||||
let mut byte = parse_data[offset];
|
||||
let mut bytes_read = 1;
|
||||
|
||||
let mut return_pos: Option<usize> = None;
|
||||
|
||||
loop {
|
||||
match byte {
|
||||
0 => {
|
||||
out.pop();
|
||||
|
||||
return Ok((
|
||||
String::from_utf8(out).map_err(|_| ParserError::LabelIsNotUTF8)?,
|
||||
if let Some(p) = return_pos {
|
||||
p + 2
|
||||
} else {
|
||||
bytes_read
|
||||
},
|
||||
));
|
||||
}
|
||||
0xc0 => {
|
||||
let nof = parse_data[offset + 1] as usize;
|
||||
if nof >= original.len() {
|
||||
return Err(ParserError::UnexpectedEOP);
|
||||
}
|
||||
|
||||
return_pos = match return_pos {
|
||||
Some(x) => Some(std::cmp::max(x, offset)),
|
||||
None => Some(offset),
|
||||
};
|
||||
|
||||
offset = 0;
|
||||
parse_data = &original[nof..];
|
||||
byte = parse_data[0];
|
||||
}
|
||||
|
||||
_ => {
|
||||
out.extend(&parse_data[offset + 1..offset + 1 + byte as usize]);
|
||||
|
||||
out.push(b'.');
|
||||
|
||||
offset += byte as usize + 1;
|
||||
bytes_read += byte as usize + 1;
|
||||
|
||||
byte = parse_data[offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
src/parser/rdata/a.rs
Normal file
15
src/parser/rdata/a.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use crate::ParserError;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Record {
|
||||
pub address: Ipv4Addr,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
pub fn parse(data: &[u8], original: &[u8]) -> Result<Self, ParserError> {
|
||||
let address = Ipv4Addr::from([data[0], data[1], data[2], data[3]]);
|
||||
|
||||
Ok(Self { address })
|
||||
}
|
||||
}
|
18
src/parser/rdata/aaaa.rs
Normal file
18
src/parser/rdata/aaaa.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use crate::ParserError;
|
||||
use std::net::Ipv6Addr;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Record {
|
||||
pub address: Ipv6Addr,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
pub fn parse(mut data: &[u8], original: &[u8]) -> Result<Self, ParserError> {
|
||||
let address = Ipv6Addr::from([
|
||||
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
|
||||
data[9], data[10], data[11], data[12], data[13], data[14], data[15],
|
||||
]);
|
||||
|
||||
Ok(Self { address })
|
||||
}
|
||||
}
|
10
src/parser/rdata/cname.rs
Normal file
10
src/parser/rdata/cname.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use crate::ParserError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Record {}
|
||||
|
||||
impl Record {
|
||||
pub fn parse(data: &[u8], original: &[u8]) -> Result<Self, ParserError> {
|
||||
Err(ParserError::UnexpectedEOP)
|
||||
}
|
||||
}
|
36
src/parser/rdata/mod.rs
Normal file
36
src/parser/rdata/mod.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
mod a;
|
||||
mod aaaa;
|
||||
mod cname;
|
||||
mod nsec;
|
||||
mod ptr;
|
||||
mod srv;
|
||||
mod txt;
|
||||
use crate::{ParserError, Type};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RData {
|
||||
A(a::Record),
|
||||
Aaaa(aaaa::Record),
|
||||
Cname(cname::Record),
|
||||
Ptr(ptr::Record),
|
||||
Txt(txt::Record),
|
||||
Srv(srv::Record),
|
||||
Nsec(nsec::Record),
|
||||
|
||||
Unknown(Type, Vec<u8>),
|
||||
}
|
||||
|
||||
impl RData {
|
||||
pub fn parse(rtype: Type, data: &[u8], original: &[u8]) -> Result<Self, ParserError> {
|
||||
match rtype {
|
||||
Type::A => Ok(RData::A(a::Record::parse(data, original)?)),
|
||||
Type::Cname => Ok(RData::Cname(cname::Record::parse(data, original)?)),
|
||||
Type::Ptr => Ok(RData::Ptr(ptr::Record::parse(data, original)?)),
|
||||
Type::Txt => Ok(RData::Txt(txt::Record::parse(data, original)?)),
|
||||
Type::Aaaa => Ok(RData::Aaaa(aaaa::Record::parse(data, original)?)),
|
||||
Type::Srv => Ok(RData::Srv(srv::Record::parse(data, original)?)),
|
||||
Type::Nsec => Ok(RData::Nsec(nsec::Record::parse(data, original)?)),
|
||||
Type::Https => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
21
src/parser/rdata/nsec.rs
Normal file
21
src/parser/rdata/nsec.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
use crate::{ParserError, Qname};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Record {}
|
||||
|
||||
impl Record {
|
||||
pub fn parse(data: &[u8], original: &[u8]) -> Result<Self, ParserError> {
|
||||
println!("{:02x?}", &data[..]);
|
||||
let (domain_name, mut read) = Qname::read(data, original)?;
|
||||
println!("{:02x?}", &data[read..]);
|
||||
|
||||
read += 1;
|
||||
let rr_bitmap_len = data[read];
|
||||
|
||||
let rr_bitmap = u16::from_be_bytes([data[read], data[read + 1]]);
|
||||
|
||||
println!("{:0x}", rr_bitmap_len);
|
||||
|
||||
Ok(Self {})
|
||||
}
|
||||
}
|
14
src/parser/rdata/ptr.rs
Normal file
14
src/parser/rdata/ptr.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use crate::{parser::qname, ParserError, Qname};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Record {
|
||||
domain_name: String,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
pub fn parse(data: &[u8], original: &[u8]) -> Result<Self, ParserError> {
|
||||
let (domain_name, _) = Qname::read(data, original)?;
|
||||
|
||||
Ok(Self { domain_name })
|
||||
}
|
||||
}
|
29
src/parser/rdata/srv.rs
Normal file
29
src/parser/rdata/srv.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use crate::{ParserError, Qname};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Record {
|
||||
priority: u16,
|
||||
weight: u16,
|
||||
port: u16,
|
||||
target: String,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
pub fn parse(mut data: &[u8], original: &[u8]) -> Result<Self, ParserError> {
|
||||
let priority = u16::from_be_bytes([data[0], data[1]]);
|
||||
data = &data[2..];
|
||||
let weight = u16::from_be_bytes([data[0], data[1]]);
|
||||
data = &data[2..];
|
||||
let port = u16::from_be_bytes([data[0], data[1]]);
|
||||
data = &data[2..];
|
||||
|
||||
let (target, _) = Qname::read(data, original)?;
|
||||
|
||||
Ok(Self {
|
||||
priority,
|
||||
weight,
|
||||
port,
|
||||
target,
|
||||
})
|
||||
}
|
||||
}
|
12
src/parser/rdata/txt.rs
Normal file
12
src/parser/rdata/txt.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use crate::{ParserError, Qname};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Record {
|
||||
sets: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
pub fn parse(data: &[u8], original: &[u8]) -> Result<Self, ParserError> {
|
||||
Ok(Self { sets: vec![] })
|
||||
}
|
||||
}
|
|
@ -1,9 +1,86 @@
|
|||
#[derive(Debug, Default)]
|
||||
use crate::{ParserError, Qname, RData};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ResourceRecord {
|
||||
name: String,
|
||||
rtype: u16,
|
||||
class: u16,
|
||||
ttl: u16,
|
||||
rdlength: u16,
|
||||
rdata: (),
|
||||
pub name: String,
|
||||
pub rtype: Type,
|
||||
pub class: u16,
|
||||
pub cache_flush: bool,
|
||||
pub ttl: u32,
|
||||
pub rdlength: u16,
|
||||
pub rdata: RData,
|
||||
}
|
||||
|
||||
impl ResourceRecord {
|
||||
pub fn parse(data: &[u8], original: &[u8]) -> Result<(Self, usize), ParserError> {
|
||||
let (name, mut read) = Qname::read(data, original)?;
|
||||
if read + 10 > data.len() {
|
||||
return Err(ParserError::UnexpectedEOP);
|
||||
}
|
||||
|
||||
let rtype = Type::parse(u16::from_be_bytes([data[read], data[read + 1]]))?;
|
||||
read += 2;
|
||||
|
||||
let (cache_flush, class) =
|
||||
Self::parse_class(u16::from_be_bytes([data[read], data[read + 1]]));
|
||||
read += 2;
|
||||
|
||||
let ttl = u32::from_be_bytes([data[read], data[read + 1], data[read + 2], data[read + 3]]);
|
||||
read += 4;
|
||||
|
||||
let rdlength = u16::from_be_bytes([data[read], data[read + 1]]);
|
||||
read += 2;
|
||||
if read + rdlength as usize > data.len() {
|
||||
return Err(ParserError::UnexpectedEOP);
|
||||
}
|
||||
let rdata = RData::parse(rtype, &data[read..read + rdlength as usize], original)?;
|
||||
read += rdlength as usize;
|
||||
|
||||
Ok((
|
||||
Self {
|
||||
name,
|
||||
rtype,
|
||||
class,
|
||||
cache_flush,
|
||||
ttl,
|
||||
rdlength,
|
||||
rdata,
|
||||
},
|
||||
read,
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_class(v: u16) -> (bool, u16) {
|
||||
(((v >> 15) & 1) == 1, v & !(1 << 15))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum Type {
|
||||
A = 1,
|
||||
Cname = 5,
|
||||
Ptr = 12,
|
||||
Txt = 16,
|
||||
Aaaa = 28,
|
||||
Srv = 33,
|
||||
Nsec = 47,
|
||||
Https = 65,
|
||||
}
|
||||
|
||||
impl Type {
|
||||
fn parse(v: u16) -> Result<Self, ParserError> {
|
||||
use Type::*;
|
||||
match v {
|
||||
1 => Ok(A),
|
||||
5 => Ok(Cname),
|
||||
12 => Ok(Ptr),
|
||||
16 => Ok(Txt),
|
||||
28 => Ok(Aaaa),
|
||||
33 => Ok(Srv),
|
||||
47 => Ok(Nsec),
|
||||
65 => Ok(Https),
|
||||
v => Err(ParserError::UnknownRType(v)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
use log::trace;
|
||||
// This code has been adapted from multicast_socket crate
|
||||
use nix::sys::socket::{self as sock, AddressFamily, SockaddrIn, SockaddrLike, SockaddrStorage};
|
||||
use nix::sys::{
|
||||
self,
|
||||
socket::{self as sock, AddressFamily, SockAddr, SockaddrIn, SockaddrLike, SockaddrStorage},
|
||||
};
|
||||
use serde::de::value;
|
||||
use socket2::{Domain, Protocol, Socket, Type};
|
||||
use std::{
|
||||
|
@ -33,21 +36,15 @@ impl Default for MulticastOptions {
|
|||
pub struct MulticastSocket {
|
||||
socket: socket2::Socket,
|
||||
interfaces: HashMap<String, Vec<IpAddr>>,
|
||||
multicast_group: MulticastGroup,
|
||||
multicast_group: SocketAddrV4,
|
||||
buffer_size: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MulticastGroup {
|
||||
pub ipv4: SocketAddrV4,
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
impl MulticastSocket {
|
||||
pub fn new(
|
||||
options: MulticastOptions,
|
||||
interfaces: HashMap<String, Vec<IpAddr>>,
|
||||
multicast_group: MulticastGroup,
|
||||
multicast_group: SocketAddrV4,
|
||||
) -> Result<Self, std::io::Error> {
|
||||
let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?;
|
||||
socket.set_read_timeout(Some(options.read_timeout))?;
|
||||
|
@ -62,13 +59,7 @@ impl MulticastSocket {
|
|||
.map_err(nix_to_io_error)?;
|
||||
|
||||
for (if_name, addresses) in interfaces.iter() {
|
||||
trace!(
|
||||
"joining groups = {:?} interface = {:?}",
|
||||
multicast_group.ipv4.ip(),
|
||||
Ipv4Addr::UNSPECIFIED
|
||||
);
|
||||
|
||||
socket.join_multicast_v4(multicast_group.ipv4.ip(), &Ipv4Addr::UNSPECIFIED);
|
||||
trace!("joining groups = {:?}", multicast_group);
|
||||
|
||||
for address in addresses {
|
||||
if let IpAddr::V4(v4_addr) = address {
|
||||
|
@ -76,11 +67,11 @@ impl MulticastSocket {
|
|||
continue;
|
||||
}
|
||||
|
||||
socket.join_multicast_v4(multicast_group.ipv4.ip(), v4_addr)?;
|
||||
socket.join_multicast_v4(multicast_group.ip(), v4_addr)?;
|
||||
|
||||
trace!(
|
||||
"joined ipv4 multicast group {} {}",
|
||||
multicast_group.ipv4.ip(),
|
||||
multicast_group.ip(),
|
||||
v4_addr
|
||||
);
|
||||
}
|
||||
|
@ -88,7 +79,7 @@ impl MulticastSocket {
|
|||
}
|
||||
|
||||
socket.bind(
|
||||
&SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), multicast_group.port).into(),
|
||||
&SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), multicast_group.port()).into(),
|
||||
)?;
|
||||
|
||||
Ok(MulticastSocket {
|
||||
|
@ -121,7 +112,7 @@ impl MulticastSocket {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Message {
|
||||
pub data: Vec<u8>,
|
||||
pub origin_address: Option<SocketAddr>,
|
||||
pub origin_address: Option<SocketAddrV4>,
|
||||
pub interface: Interface,
|
||||
}
|
||||
|
||||
|
@ -129,7 +120,7 @@ pub struct Message {
|
|||
pub enum Interface {
|
||||
Default,
|
||||
Index(i32),
|
||||
IpAddr(Ipv6Addr),
|
||||
IpAddr(IpAddr),
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -145,7 +136,7 @@ fn nix_to_io_error(e: nix::Error) -> io::Error {
|
|||
impl MulticastSocket {
|
||||
pub fn receive(&self) -> IoResult<Message> {
|
||||
let mut data_buffer = vec![0; self.buffer_size];
|
||||
let mut control_buffer = nix::cmsg_space!(libc::in6_pktinfo, libc::in_pktinfo);
|
||||
let mut control_buffer = nix::cmsg_space!(libc::in_pktinfo);
|
||||
|
||||
let (origin_address, interface, bytes_read) = {
|
||||
let message = sock::recvmsg(
|
||||
|
@ -156,28 +147,15 @@ impl MulticastSocket {
|
|||
)
|
||||
.map_err(nix_to_io_error)?;
|
||||
|
||||
let origin_address = match message.address {
|
||||
//v4 @ Some(SockaddrIn) => v4,
|
||||
Some(sock::SockAddr::Inet(inet)) => Some(inet.to_std()),
|
||||
_ => None,
|
||||
};
|
||||
// let origin_address = match origin_address {
|
||||
// Some(SocketAddr::V6(v6)) => v6,
|
||||
// _ => SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0),
|
||||
// };
|
||||
let origin_address = message.address.map(|x: sock::SockaddrIn| {
|
||||
SocketAddrV4::new(Ipv4Addr::from_bits(x.ip()), x.port())
|
||||
});
|
||||
|
||||
println!("{:?}", origin_address);
|
||||
let mut interface = Interface::Default;
|
||||
|
||||
for cmsg in message.cmsgs() {
|
||||
if let sock::ControlMessageOwned::Ipv6PacketInfo(pktinfo) = cmsg {
|
||||
interface = Interface::Index(pktinfo.ipi6_ifindex as _);
|
||||
trace!("control packet ipv6: {:?}", pktinfo);
|
||||
}
|
||||
if let sock::ControlMessageOwned::Ipv4PacketInfo(pktinfo) = cmsg {
|
||||
interface = Interface::Index(pktinfo.ipi_ifindex as _);
|
||||
|
||||
trace!("control packet ipv4: {:?}", pktinfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +170,31 @@ impl MulticastSocket {
|
|||
}
|
||||
|
||||
pub fn send(&self, buf: &[u8], interface: &Interface) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
let mut pkt_info: libc::in_pktinfo = unsafe { mem::zeroed() };
|
||||
|
||||
match interface {
|
||||
Interface::Default => todo!(),
|
||||
Interface::Index(i) => {
|
||||
pkt_info.ipi_ifindex = *i as _;
|
||||
}
|
||||
Interface::IpAddr(IpAddr::V4(addr)) => {
|
||||
pkt_info.ipi_spec_dst = libc::in_addr {
|
||||
s_addr: (*addr).into(),
|
||||
};
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
sock::sendmsg(
|
||||
self.socket.as_raw_fd(),
|
||||
&[IoSlice::new(buf)],
|
||||
&[sock::ControlMessage::Ipv4PacketInfo(&pkt_info)],
|
||||
sock::MsgFlags::empty(),
|
||||
Some(&SockaddrIn::from(self.multicast_group)),
|
||||
)
|
||||
.map_err(nix_to_io_error)
|
||||
|
||||
// match interface {
|
||||
// Interface::Default => todo!(),
|
||||
// Interface::Index(index) => {
|
||||
|
@ -234,7 +236,3 @@ impl MulticastSocket {
|
|||
// .map_err(nix_to_io_error)
|
||||
}
|
||||
}
|
||||
|
||||
fn print_type_of<T>(_: &T) {
|
||||
println!("{}", std::any::type_name::<T>())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user