diff --git a/src/main.rs b/src/main.rs index f4d1223..e33d25f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,28 @@ fn main() { Ok((size, source)) => { let _received_data = String::from_utf8_lossy(&buf[0..size]); println!("Received {} bytes from {}", size, source); - let response = []; + let mut response = vec![]; + + let packet = Packet { + header: Header { + ident: 1234, + query: true, + opcode: 0, + authoritative: false, + truncated: false, + recursion_desired: false, + recursion_avail: false, + reserved: 0, + rcode: 0, + question_records: 0, + answer_records: 0, + authority_records: 0, + additional_records: 0, + }, + }; + + packet.write_to(&mut response); + udp_socket .send_to(&response, source) .expect("Failed to send response"); @@ -21,3 +42,81 @@ fn main() { } } } + +struct Packet { + header: Header, +} + +struct Header { + ident: u16, + query: bool, + opcode: u8, // TODO: enum + authoritative: bool, + truncated: bool, + recursion_desired: bool, + recursion_avail: bool, + reserved: u8, + rcode: u8, // TODO: enum + question_records: u16, + answer_records: u16, + authority_records: u16, + additional_records: u16, +} + +impl Packet { + pub fn parse(data: &[u8]) -> Result { + let header = Header::parse(&data[..12])?; + + Ok(Self { header }) + } + + pub fn write_to(self, buf: &mut Vec) { + self.header.write_to(buf); + } +} + +impl Header { + pub fn parse(data: &[u8]) -> Result { + if data.len() != 12 { + return Err("input bytes len is not equal to 12"); + } + + Ok(Self { + ident: u16::from_be_bytes([data[0], data[1]]), + query: ((data[2] >> 7) & 1) == 1, + opcode: (data[2] >> 3), + authoritative: ((data[2] >> 2) & 1) == 1, + truncated: ((data[2] >> 1) & 1) == 1, + recursion_desired: (data[2] & 1) == 1, + recursion_avail: ((data[3] >> 7) & 1) == 1, + reserved: ((data[3] >> 4) & 0b111), + rcode: (data[3] & 0b1111), + question_records: u16::from_be_bytes([data[4], data[5]]), + answer_records: u16::from_be_bytes([data[6], data[7]]), + authority_records: u16::from_be_bytes([data[8], data[9]]), + additional_records: u16::from_be_bytes([data[10], data[11]]), + }) + } + + pub fn write_to(self, buf: &mut Vec) { + // write ident + buf.extend(self.ident.to_be_bytes()); + + // Write flags + let flag0_byte = (self.query as u8) << 7 + | self.opcode << 3 + | (self.authoritative as u8) << 2 + | (self.truncated as u8) << 1 + | self.recursion_desired as u8; + let flag1_byte = (self.recursion_avail as u8) << 7 | self.reserved << 4 | self.rcode; + + buf.push(flag0_byte); + buf.push(flag1_byte); + + // Write counts + buf.extend(self.question_records.to_be_bytes()); + buf.extend(self.answer_records.to_be_bytes()); + buf.extend(self.authority_records.to_be_bytes()); + buf.extend(self.additional_records.to_be_bytes()); + } +}