a bunch of rdata processors

This commit is contained in:
Benjamin Fry 2015-08-13 08:32:48 -07:00
parent fe13d680bc
commit 8809b9d322
9 changed files with 145 additions and 12 deletions

View File

@ -89,9 +89,10 @@ mod tests {
test_num += 1;
println!("test: {}", test_num);
binary.reverse();
assert_eq!(Name::parse(&mut binary).ok().unwrap().labels, expect);
if (expect.len() > 0) {
assert_eq!(Name::parse(&mut binary).ok().unwrap()[0], expect[0]);
let name = Name::parse(&mut binary).ok().unwrap();
assert_eq!(name.labels, expect);
if expect.len() > 0 {
assert_eq!(name[0], expect[0]);
}
}
}

View File

@ -24,7 +24,7 @@ pub fn parse(data: &mut Vec<u8>) -> RData {
#[test]
fn test_parse() {
let mut data: Vec<u8> = vec![3,b'w',b'w',b'w',8,b'e',b'x',b'a',b'm',b'p',b'l',b'e',3,b'c',b'o',b'm',0];
let mut data: Vec<u8> = vec![3,b'w',b'w',b'w',7,b'e',b'x',b'a',b'm',b'p',b'l',b'e',3,b'c',b'o',b'm',0];
data.reverse();
if let RData::CNAME { cname } = parse(&mut data) {
let expect = vec!["www","example","com"];

View File

@ -1,4 +1,5 @@
use super::super::record_data::RData;
use super::super::util;
// 3.3.2. HINFO RDATA format
//
@ -23,5 +24,18 @@ use super::super::record_data::RData;
//
// HINFO { cpu: String, os: String},
pub fn parse(data: &mut Vec<u8>) -> RData {
unimplemented!()
RData::HINFO { cpu: util::parse_character_data(data).unwrap(), os: util::parse_character_data(data).unwrap() }
}
#[test]
fn test_parse() {
let mut data: Vec<u8> = vec![6,b'x',b'8',b'6',b'_',b'6',b'4',5,b'l',b'i',b'n',b'u',b'x'];
data.reverse();
if let RData::HINFO{cpu, os} = parse(&mut data) {
assert_eq!(cpu, "x86_64".to_string());
assert_eq!(os, "linux".to_string());
} else {
assert!(false);
}
}

View File

@ -1,4 +1,6 @@
use super::super::record_data::RData;
use super::super::util;
use super::super::domain::Name;
// 3.3.9. MX RDATA format
//
@ -24,5 +26,18 @@ use super::super::record_data::RData;
//
// MX { preference: u16, exchange: Name },
pub fn parse(data: &mut Vec<u8>) -> RData {
unimplemented!()
RData::MX { preference: util::parse_u16(data), exchange: Name::parse(data).unwrap() }
}
#[test]
fn test_parse() {
let mut data: Vec<u8> = vec![1,0,1,b'n',0];
data.reverse();
if let RData::MX{ preference, exchange } = parse(&mut data) {
assert_eq!(preference, 256);
assert_eq!(exchange[0], "n".to_string());
} else {
assert!(false);
}
}

View File

@ -1,4 +1,5 @@
use super::super::record_data::RData;
use super::super::domain::Name;
// 3.3.11. NS RDATA format
//
@ -25,5 +26,19 @@ use super::super::record_data::RData;
//
// NS { nsdname: Name },
pub fn parse(data: &mut Vec<u8>) -> RData {
unimplemented!()
RData::NS{ nsdname: Name::parse(data).unwrap() }
}
#[test]
fn test_parse() {
let mut data: Vec<u8> = vec![3,b'w',b'w',b'w',7,b'e',b'x',b'a',b'm',b'p',b'l',b'e',3,b'c',b'o',b'm',0];
data.reverse();
if let RData::NS { nsdname } = parse(&mut data) {
let expect = vec!["www","example","com"];
assert_eq!(nsdname[0], expect[0]);
assert_eq!(nsdname[1], expect[1]);
assert_eq!(nsdname[2], expect[2]);
} else {
assert!(false);
}
}

View File

@ -1,4 +1,5 @@
use super::super::record_data::RData;
use super::super::domain::Name;
// 3.3.12. PTR RDATA format
//
@ -17,7 +18,21 @@ use super::super::record_data::RData;
// similar to that performed by CNAME, which identifies aliases. See the
// description of the IN-ADDR.ARPA domain for an example.
//
// PTR { ptrdnam: Name },
// PTR { ptrdname: Name },
pub fn parse(data: &mut Vec<u8>) -> RData {
unimplemented!()
RData::PTR{ ptrdname: Name::parse(data).unwrap() }
}
#[test]
fn test_parse() {
let mut data: Vec<u8> = vec![3,b'w',b'w',b'w',7,b'e',b'x',b'a',b'm',b'p',b'l',b'e',3,b'c',b'o',b'm',0];
data.reverse();
if let RData::PTR { ptrdname } = parse(&mut data) {
let expect = vec!["www","example","com"];
assert_eq!(ptrdname[0], expect[0]);
assert_eq!(ptrdname[1], expect[1]);
assert_eq!(ptrdname[2], expect[2]);
} else {
assert!(false);
}
}

View File

@ -1,4 +1,6 @@
use super::super::record_data::RData;
use super::super::util;
use super::super::domain::Name;
// 3.3.13. SOA RDATA format
//
@ -67,5 +69,39 @@ use super::super::record_data::RData;
//
// SOA { mname: Name, rname: Name, serial: u32, refresh: i32, retry: i32, expire: i32, minimum: u32, },
pub fn parse(data: &mut Vec<u8>) -> RData {
unimplemented!()
RData::SOA{
mname: Name::parse(data).unwrap(),
rname: Name::parse(data).unwrap(),
serial: util::parse_u32(data),
refresh: util::parse_i32(data),
retry: util::parse_i32(data),
expire: util::parse_i32(data),
minimum: util::parse_u32(data),
}
}
#[test]
fn test_parse() {
let mut data: Vec<u8> = vec![3,b'w',b'w',b'w',7,b'e',b'x',b'a',b'm',b'p',b'l',b'e',3,b'c',b'o',b'm',0,
3,b'x',b'x',b'x',7,b'e',b'x',b'a',b'm',b'p',b'l',b'e',3,b'c',b'o',b'm',0,
0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF];
data.reverse();
if let RData::SOA { mname, rname, serial, refresh, retry, expire, minimum } = parse(&mut data) {
let expect1 = vec!["www","example","com"];
let expect2 = vec!["xxx","example","com"];
assert_eq!(mname.labels, expect1);
assert_eq!(rname.labels, expect2);
assert_eq!(serial, u32::max_value());
assert_eq!(refresh, -1 as i32);
assert_eq!(retry, -1 as i32);
assert_eq!(expire, -1 as i32);
assert_eq!(minimum, u32::max_value());
} else {
assert!(false);
}
}

View File

@ -151,7 +151,7 @@ pub enum RData {
// These records are simple data, and don't imply any special processing
// similar to that performed by CNAME, which identifies aliases. See the
// description of the IN-ADDR.ARPA domain for an example.
PTR { ptrdnam: Name },
PTR { ptrdname: Name },
// 3.3.13. SOA RDATA format
//

View File

@ -19,7 +19,7 @@ pub fn parse_character_data(data: &mut Vec<u8>) -> Result<String, FromUtf8Error>
pub fn parse_label(data: &mut Vec<u8>, length: u8) -> Result<String, FromUtf8Error> {
// TODO once Drain stabalizes on Vec, this should be replaced...
let mut label_vec: Vec<u8> = Vec::with_capacity(length as usize);
for i in 0..length as usize {
for _ in 0..length as usize {
match data.pop() {
Some(n) => label_vec.push(n),
None => break,
@ -59,6 +59,21 @@ pub fn parse_i32(data: &mut Vec<u8>) -> i32 {
((b1 as i32) << 24) + ((b2 as i32) << 16) + ((b3 as i32) << 8) + (b4 as i32)
}
/// parses the next four bytes into u32. This performs a byte-by-byte manipulation, there
/// which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
///
/// the vector should be reversed before calling.
pub fn parse_u32(data: &mut Vec<u8>) -> u32 {
// TODO should this use a default rather than the panic! that will happen in the None case?
let b1: u8 = data.pop().unwrap();
let b2: u8 = data.pop().unwrap();
let b3: u8 = data.pop().unwrap();
let b4: u8 = data.pop().unwrap();
// translate from network byte order, i.e. big endian
((b1 as u32) << 24) + ((b2 as u32) << 16) + ((b3 as u32) << 8) + (b4 as u32)
}
#[cfg(test)]
mod tests {
#[test]
@ -119,4 +134,26 @@ mod tests {
assert_eq!(super::parse_i32(&mut binary), expect);
}
}
#[test]
fn parse_u32() {
let data: Vec<(Vec<u8>, u32)> = vec![
(vec![0x00,0x00,0x00,0x00], 0),
(vec![0x00,0x00,0x00,0x01], 1),
(vec![0x00,0x00,0x01,0x00], 256),
(vec![0x00,0x01,0x00,0x00], 256*256),
(vec![0x01,0x00,0x00,0x00], 256*256*256),
(vec![0xFF,0xFF,0xFF,0xFF], u32::max_value()),
(vec![0x80,0x00,0x00,0x00], u32::min_value()),
(vec![0x7F,0xFF,0xFF,0xFF], u32::max_value()),
];
let mut test_num = 0;
for (mut binary, expect) in data {
test_num += 1;
println!("test: {}", test_num);
binary.reverse();
assert_eq!(super::parse_i32(&mut binary), expect);
}
}
}