Crate simple_dns

source
Expand description

§Simple DNS

Pure Rust implementation to work with DNS packets

You can parse or write a DNS packet by using Packet

§Packet

A Packet represents a dns packet, it is the main structure to construct and manipulate a packet before writing it into wire format.

use simple_dns::*;
use simple_dns::rdata::*;

let mut packet = Packet::new_query(1);

let question = Question::new(Name::new_unchecked("_srv._udp.local"), TYPE::TXT.into(), CLASS::IN.into(), false);
packet.questions.push(question);

let resource = ResourceRecord::new(Name::new_unchecked("_srv._udp.local"), CLASS::IN, 10, RData::A(A { address: 10 }));
packet.additional_records.push(resource);

// Write the packet in the provided buffer;
let mut bytes = [0u8; 200];
assert!(packet.write_to(&mut &mut bytes[..]).is_ok());

// Same as above, but allocates and returns a Vec<u8>
let bytes = packet.build_bytes_vec();
assert!(bytes.is_ok());

// Same as above, but Names are compressed
let bytes = packet.build_bytes_vec_compressed();
assert!(bytes.is_ok());

It doesn’t matter what order the resources are added, the packet will be built only when build_bytes_vec or write_to is called

To parse the contents of a buffer into a packet, you need call call Packet::parse

use simple_dns::Packet;

let bytes = b"\x00\x03\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01";
let packet = Packet::parse(&bytes[..]);
assert!(packet.is_ok());

It is possible to check some information about a packet withouth parsing the packet, by using the header_buffer module functions.
Be cautious when checking RCODE and packet flags, see the module documentation for more information.

use simple_dns::{header_buffer, PacketFlag};
let buffer = b"\x00\x03\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01";

assert_eq!(Ok(3), header_buffer::id(&buffer[..]));
assert!(!header_buffer::has_flags(&buffer[..], PacketFlag::RESPONSE).unwrap());

EDNS is supported by Packet opt and opt_mut functions, when working with ENDS packets, you SHOULD NOT add OPT Resource Records directly to the Additional Records sections unless you know exactly what you are doing.

§EDNS0 caveats

EDNS extends the DNS packet header by adding an OPT resource record and moving part of the header information to the additional records section. RCODE went from 4 bits to 12 bits, where the first 4 bits are stored in the header section and the last 8 bits are stored somewhere else inside the packet.

This has some implications on how a packet can be parsed or build

use simple_dns::{header_buffer, RCODE, Packet};

let buffer = b"\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x2e\x00\x00\x29\x01\xf4\x00\x00\x03\x01\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
let packet = Packet::parse(&buffer[..]).unwrap();

// Without parsing the full packet, it is impossible to know the true RCODE of the packet
assert_eq!(RCODE::NoError, header_buffer::rcode(&buffer[..]).unwrap());
assert_eq!(RCODE::BADVERS, packet.rcode());

Please, refer to RFC 6891 for more information

§DNS Packet Parser/Builder

The Packet structure provides parsing e building of a DNS packet, it aims to be fully compliant with the RFCs bellow:

Other Resource Records defined by other RFCs that are not in this list will be implemented over time

§Update packets (RFC 2136)

This library can parse update packets, however, it does not validate update rules and the update fields are overloaded in the packet fields, as defined in the RFC 2136.

Modules§

  • Helper functions to assert a buffer for the header flags of a DNS Packet. Useful for checking the header without parsing the whole packet.
    WARNING: Flags and RCODE information may be incomplete if the packet contains EDNS (OPT) or DNSSEC Resource Records
  • Contains RData implementations

Structs§

  • CharacterString is expressed in one or two ways:
  • Represents a label in a domain name
  • A Name represents a domain-name, which consists of character strings separated by dots.
    Each section of a name is called label
    ex: google.com consists of two labels google and com
  • Represents a DNS message packet
  • Possible Packet Flags
  • Question represents a query in the DNS Packet
  • Resource Records are used to represent the answer, authority, and additional sections in DNS packets.

Enums§

  • Possible CLASS values for a Resource in a DNS packet
    Each value is described according to its own RFC
  • Possible OPCODE values for a DNS packet, use to specify the type of operation.
    RFC 1035: A four bit field that specifies kind of query in this message.
    This value is set by the originator of a query and copied into the response.
  • Possible QCLASS values for a Question in a DNS packet
    Each value is described according to its own RFC
  • Possible QTYPE values for a Question in a DNS packet
    Each value is described according to its own RFC
  • Possible RCODE values for a DNS packet
    RFC 1035 Response code - this 4 bit field is set as part of responses.
    The values have the following interpretation
  • Error types for SimpleDns
  • Possible TYPE values in DNS Resource Records Each value is described according to its own RFC

Type Aliases§

  • Alias type for Result<T, SimpleDnsError>;