Skip to content

Instantly share code, notes, and snippets.

@cyberDrake
Created August 1, 2015 02:01
Show Gist options
  • Save cyberDrake/7a956b9d5082234cef27 to your computer and use it in GitHub Desktop.
Save cyberDrake/7a956b9d5082234cef27 to your computer and use it in GitHub Desktop.
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