Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.vagga
/target
/Cargo.lock
/.idea
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Next

- Update MSRV to 1.75.0, currently the older of rustc in Ubuntu LTS (Noble Numbat, 1.75.0) and Debian Stable (trixie, 1.85.0)
- Small syntactic tweaks to address all compiler and clippy warnings

# 0.8.0

Current version when changelog started
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ serde_derive = { version = "1.0", optional = true }

[dev-dependencies]
matches = "0.1.2"
itertools = "0.14.0"
29 changes: 14 additions & 15 deletions examples/sync_tcp_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@ use std::io::{Read, Write};
use std::net::TcpStream;
use std::process;


use dns_parser::{Builder, Packet, RData, ResponseCode};
use dns_parser::rdata::a::Record;
use dns_parser::{QueryType, QueryClass};

use dns_parser::{Builder, Packet, RData, ResponseCode};
use dns_parser::{QueryClass, QueryType};

fn main() {
let mut code = 0;
for name in env::args().skip(1) {
match resolve(&name) {
Ok(()) => {},
Ok(()) => {}
Err(e) => {
eprintln!("Error resolving {:?}: {}", name, e);
code = 1;
Expand All @@ -26,13 +24,15 @@ fn main() {
process::exit(code);
}

fn resolve(name: &str) -> Result<(), Box<Error>> {
fn resolve(name: &str) -> Result<(), Box<dyn Error>> {
let mut conn = TcpStream::connect("127.0.0.1:53")?;
let mut builder = Builder::new_query(1, true);
builder.add_question(name, false, QueryType::A, QueryClass::IN);
let packet = builder.build().map_err(|_| "truncated packet")?;
let psize = [((packet.len() >> 8) & 0xFF) as u8,
(packet.len() & 0xFF) as u8];
let psize = [
((packet.len() >> 8) & 0xFF) as u8,
(packet.len() & 0xFF) as u8,
];
conn.write_all(&psize[..])?;
conn.write_all(&packet)?;
let mut buf = vec![0u8; 4096];
Expand All @@ -44,7 +44,9 @@ fn resolve(name: &str) -> Result<(), Box<Error>> {
match conn.read(&mut buf[off..]) {
Ok(num) => {
off += num;
if off < 2 { continue; }
if off < 2 {
continue;
}
let bytes = ((buf[0] as usize) << 8) | buf[1] as usize;
if off < bytes + 2 {
continue;
Expand All @@ -62,15 +64,12 @@ fn resolve(name: &str) -> Result<(), Box<Error>> {
if pkt.header.response_code != ResponseCode::NoError {
return Err(pkt.header.response_code.into());
}
if pkt.answers.len() == 0 {
if pkt.answers.is_empty() {
return Err("No records received".into());
}
for ans in pkt.answers {
match ans.data {
RData::A(Record(ip)) => {
println!("{}", ip);
}
_ => {} // ignore
if let RData::A(Record(ip)) = ans.data {
println!("{}", ip);
}
}
Ok(())
Expand Down
19 changes: 7 additions & 12 deletions examples/sync_udp_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ use std::error::Error;
use std::net::UdpSocket;
use std::process;


use dns_parser::{Builder, Packet, RData, ResponseCode};
use dns_parser::rdata::a::Record;
use dns_parser::{QueryType, QueryClass};

use dns_parser::{Builder, Packet, RData, ResponseCode};
use dns_parser::{QueryClass, QueryType};

fn main() {
let mut code = 0;
for name in env::args().skip(1) {
match resolve(&name) {
Ok(()) => {},
Ok(()) => {}
Err(e) => {
eprintln!("Error resolving {:?}: {}", name, e);
code = 1;
Expand All @@ -25,7 +23,7 @@ fn main() {
process::exit(code);
}

fn resolve(name: &str) -> Result<(), Box<Error>> {
fn resolve(name: &str) -> Result<(), Box<dyn Error>> {
let sock = UdpSocket::bind("127.0.0.1:0")?;
sock.connect("127.0.0.1:53")?;
let mut builder = Builder::new_query(1, true);
Expand All @@ -38,15 +36,12 @@ fn resolve(name: &str) -> Result<(), Box<Error>> {
if pkt.header.response_code != ResponseCode::NoError {
return Err(pkt.header.response_code.into());
}
if pkt.answers.len() == 0 {
if pkt.answers.is_empty() {
return Err("No records received".into());
}
for ans in pkt.answers {
match ans.data {
RData::A(Record(ip)) => {
println!("{}", ip);
}
_ => {} // ignore
if let RData::A(Record(ip)) = ans.data {
println!("{}", ip);
}
}
Ok(())
Expand Down
2 changes: 2 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "1.75.0"
31 changes: 18 additions & 13 deletions src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use byteorder::{ByteOrder, BigEndian, WriteBytesExt};
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};

use {Opcode, ResponseCode, Header, QueryType, QueryClass};
use {Header, Opcode, QueryClass, QueryType, ResponseCode};

/// Allows to build a DNS packet
///
Expand All @@ -19,7 +19,7 @@ impl Builder {
pub fn new_query(id: u16, recursion: bool) -> Builder {
let mut buf = Vec::with_capacity(512);
let head = Header {
id: id,
id,
query: true,
opcode: Opcode::StandardQuery,
authoritative: false,
Expand All @@ -36,7 +36,7 @@ impl Builder {
};
buf.extend([0u8; 12].iter());
head.write(&mut buf[..12]);
Builder { buf: buf }
Builder { buf }
}
/// Adds a question to the packet
///
Expand All @@ -45,22 +45,27 @@ impl Builder {
/// * Answers, nameservers or additional section has already been written
/// * There are already 65535 questions in the buffer.
/// * When name is invalid
pub fn add_question(&mut self, qname: &str, prefer_unicast: bool,
qtype: QueryType, qclass: QueryClass)
-> &mut Builder
{
pub fn add_question(
&mut self,
qname: &str,
prefer_unicast: bool,
qtype: QueryType,
qclass: QueryClass,
) -> &mut Builder {
if &self.buf[6..12] != b"\x00\x00\x00\x00\x00\x00" {
panic!("Too late to add a question");
}
self.write_name(qname);
self.buf.write_u16::<BigEndian>(qtype as u16).unwrap();
let prefer_unicast: u16 = if prefer_unicast { 0x8000 } else { 0x0000 };
self.buf.write_u16::<BigEndian>(qclass as u16 | prefer_unicast).unwrap();
self.buf
.write_u16::<BigEndian>(qclass as u16 | prefer_unicast)
.unwrap();
let oldq = BigEndian::read_u16(&self.buf[4..6]);
if oldq == 65535 {
panic!("Too many questions");
}
BigEndian::write_u16(&mut self.buf[4..6], oldq+1);
BigEndian::write_u16(&mut self.buf[4..6], oldq + 1);
self
}
fn write_name(&mut self, name: &str) {
Expand All @@ -86,7 +91,7 @@ impl Builder {
/// appropriate.
// TODO(tailhook) does the truncation make sense for TCP, and how
// to treat it for EDNS0?
pub fn build(mut self) -> Result<Vec<u8>,Vec<u8>> {
pub fn build(mut self) -> Result<Vec<u8>, Vec<u8>> {
// TODO(tailhook) optimize labels
if self.buf.len() > 512 {
Header::set_truncated(&mut self.buf[..12]);
Expand All @@ -99,9 +104,9 @@ impl Builder {

#[cfg(test)]
mod test {
use QueryType as QT;
use QueryClass as QC;
use super::Builder;
use QueryClass as QC;
use QueryType as QT;

#[test]
fn build_query() {
Expand Down
Loading