-
-
Save marchon/650303cd520192d89b599f6260b7b1a7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::net::UdpSocket; | |
use std::env; | |
//use std::io::BufReader; | |
use std::fmt; | |
use std::default::Default; | |
fn get_octet(buf: &[u8]) -> u16 { | |
let mut res: u16; | |
res = match (buf[0] as char).to_digit(16) { | |
Some(x) => x as u16, | |
None => panic!("eeep"), | |
}; | |
res = res << 4; | |
res += match (buf[1] as char).to_digit(16) { | |
Some(x) => x as u16, | |
None => panic!("eeep"), | |
}; | |
res = res << 4; | |
res += match (buf[2] as char).to_digit(16) { | |
Some(x) => x as u16, | |
None => panic!("eeep"), | |
}; | |
res = res << 4; | |
res += match (buf[3] as char).to_digit(16) { | |
Some(x) => x as u16, | |
None => panic!("eeep"), | |
}; | |
res | |
} | |
#[repr(u16)] | |
#[derive(Debug,PartialEq)] | |
pub enum QueryResponse { | |
QUERY = 0, | |
RESPONSE = 1 | |
} | |
impl fmt::Display for QueryResponse { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
match self { | |
&QueryResponse::QUERY => write!(f, "QUERY"), | |
&QueryResponse::RESPONSE => write!(f, "RESPONSE") | |
} | |
} | |
} | |
impl Default for QueryResponse { | |
fn default() -> QueryResponse { | |
QueryResponse::QUERY | |
} | |
} | |
#[repr(u16)] | |
#[derive(Clone,Debug,PartialEq)] | |
pub enum OpCode { | |
QUERY = 0, | |
IQUERY = 1, | |
STATUS = 2, | |
NOTIFY = 4, | |
UPDATE = 5, | |
} | |
impl Default for OpCode { | |
fn default() -> OpCode { | |
OpCode::QUERY | |
} | |
} | |
impl fmt::Display for OpCode { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
match self { | |
&OpCode::QUERY => write!(f, "QUERY"), | |
&OpCode::IQUERY => write!(f, "IQUERY"), | |
&OpCode::STATUS => write!(f, "STATUS"), | |
&OpCode::NOTIFY => write!(f, "NOTIFY"), | |
&OpCode::UPDATE => write!(f, "UPDATE") | |
} | |
} | |
} | |
//better idea for all of this, add to str and from str traits to the Header here, | |
//that will take a string representation of the header. | |
//also will need to create a struct for the payload. | |
//also need to add a trait for to_bytes that will turn them into a collection of | |
//bytes that can be sent over the wire | |
trait FromStr { | |
fn from_hex_str(&mut self, x: String) -> &mut Header; | |
} | |
#[derive(Debug,Default)] | |
pub struct Header { | |
pub id: u16, | |
pub qr: QueryResponse, | |
pub op: OpCode, | |
pub aa: bool, | |
pub tc: bool, | |
pub rd: bool, | |
pub ra: bool, | |
pub z: bool, | |
pub ad: bool, | |
pub cd: bool, | |
pub rcode: u16, | |
pub qd_count: u16, | |
pub an_count: u16, | |
pub ns_count: u16, | |
pub ar_count: u16 | |
} | |
impl fmt::Display for Header { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
write!(f, "qid: {}\nqr: {}\nop: {}\naa: {}\ntc: {}\nrd: {}\nra: {}\nz: {}\nad: {}\ncd: {}\nrcode: {}\nqdcount: {}\nancount: {}\nnscount: {}\narcount: {}", | |
self.id, self.qr, self.op, self.aa, self.tc, self.rd, self.ra, | |
self.z, self.ad, self.cd, self.rcode, self.qd_count, | |
self.an_count, self.ns_count, self.ar_count) | |
} | |
} | |
impl FromStr for Header { | |
fn from_hex_str(&mut self, x: String) -> &mut Header { | |
let buf = x.into_bytes(); | |
let res: u16; | |
let (buf2, buf) = buf.split_at(4); | |
self.id = get_octet(buf2); | |
let (buf2, buf) = buf.split_at(4); | |
res = get_octet(buf2); | |
self.qr = if (res & 0x8000) == 0x8000 { | |
QueryResponse::RESPONSE | |
} else { | |
QueryResponse::QUERY | |
}; | |
let op = (res & 0x7800) >> 11; | |
self.op = match op as u8 { | |
0 => OpCode::QUERY, | |
1 => OpCode::IQUERY, | |
2 => OpCode::STATUS, | |
4 => OpCode::NOTIFY, | |
5 => OpCode::UPDATE, | |
_ => panic!("Bad OpCode") | |
}; | |
self.aa = (res & 0x0400) == 0x0400; | |
self.tc = (res & 0x0200) == 0x0200; | |
self.rd = (res & 0x0100) == 0x0100; | |
self.ra = (res & 0x0080) == 0x0080; | |
self.z = (res & 0x0040) == 0x0040; | |
self.ad = (res & 0x0020) == 0x0020; | |
self.cd = (res & 0x0010) == 0x0010; | |
self.rcode = res & 0x0000F; | |
let (buf2, buf) = buf.split_at(4); | |
self.qd_count = get_octet(buf2); | |
let (buf2, buf) = buf.split_at(4); | |
self.an_count = get_octet(buf2); | |
let (buf2, buf) = buf.split_at(4); | |
self.ns_count = get_octet(buf2); | |
let (buf2, _) = buf.split_at(4); | |
self.ar_count = get_octet(buf2); | |
self | |
} | |
} | |
/* | |
fn ask_number() -> String { | |
let mut stdin = std::io::stdin(); | |
let mut input = String::new(); | |
stdin.read_line(&mut input).unwrap(); | |
input.trim().to_string() | |
} | |
*/ | |
fn main() { | |
println!("argument list: "); | |
let mut i = 0; | |
let mut x: String = "".to_string(); | |
for argument in env::args() { | |
println!("argument {}: {}", i, argument); | |
x = argument; | |
i += 1; | |
} | |
let socket = UdpSocket::bind("192.168.1.4:55057").ok().expect("fail bind"); | |
//let x = ask_number(); | |
let mut head = Header { ..Default::default() }; | |
head.from_hex_str(x.clone()); | |
println!("sending packet with header:\n{}", head); | |
let buf = x.into_bytes(); | |
socket.send_to(&buf, "192.168.1.1:53").unwrap(); | |
let mut rec = [0; 4096]; | |
let mut v: Vec<u8> = vec![]; | |
let (len, _) = socket.recv_from(&mut rec).ok().expect("fail recv"); | |
let (tmp, _) = rec.split_at(len); | |
v = tmp.to_vec(); | |
println!("received {} ", len); | |
//let packet = &v[0..len+1]; | |
for c in v.iter() { | |
print!("{:02X}", c); | |
} | |
println!(""); | |
println!(""); | |
let mut buf2 = String::with_capacity(len * 2); | |
for c in v.iter() { | |
buf2.push_str(&format!("{:02X}", c)); | |
} | |
println!("{}", buf2); | |
println!(""); | |
println!(""); | |
let mut result = Header { ..Default::default() }; | |
//let buf2: [u8] = buf; | |
result.from_hex_str(buf2.to_string()); | |
println!("Got packet with header:\n{}", result); | |
// println!("Got some bytes! {} of them, to be exact.", received.len()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment