~kf5jwc/dns-server-rs

9d9b76d58c2fef8330cbb274e41b502752118c59 — Kyle Jones 6 months ago 77b26c4
Add more record types!
2 files changed, 151 insertions(+), 7 deletions(-)

M src/dns_packet/dns_record.rs
M src/dns_packet/query_type.rs
M src/dns_packet/dns_record.rs => src/dns_packet/dns_record.rs +134 -5
@@ 1,5 1,5 @@
use std::io::Result;
use std::net::Ipv4Addr;
use std::net::{Ipv4Addr, Ipv6Addr};
use super::BytePacketBuffer;
use super::QueryType;



@@ 10,13 10,34 @@ pub enum DnsRecord {
        domain: String,
        qtype: u16,
        data_len: u16,
        ttl: u32,
    },
        ttl: u32
    }, // 0
    A {
        domain: String,
        addr: Ipv4Addr,
        ttl: u32,
    },
        ttl: u32
    }, // 1
    NS {
        domain: String,
        host: String,
        ttl: u32
    }, // 2
    CNAME {
        domain: String,
        host: String,
        ttl: u32
    }, // 5
    MX {
        domain: String,
        priority: u16,
        host: String,
        ttl: u32
    }, // 15
    AAAA {
        domain: String,
        addr: Ipv6Addr,
        ttl: u32
    }, // 28
}

impl DnsRecord {


@@ 41,6 62,57 @@ impl DnsRecord {
                    ttl: ttl,
                })
            },
            QueryType::AAAA => {
                let raw_addrs: Vec<u32> = (0..8).map(|_| buffer.read_u32().expect("Next raw address group")).collect();
                let addr_groups: Vec<u16> = {
                    let shifts = vec![16u8, 0].into_iter().fuse();
                    raw_addrs
                        .iter()
                        .zip(shifts)
                        .map(|(raw_addr, shift)| {
                            ((raw_addr >> shift) & 0xFFFF) as u16
                        })
                        .collect()
                };
                let addr = Ipv6Addr::new(
                    addr_groups[0], addr_groups[1], addr_groups[2], addr_groups[3],
                    addr_groups[4], addr_groups[5], addr_groups[6], addr_groups[7],
                    );

                Ok(DnsRecord::AAAA {
                    domain: domain,
                    addr: addr,
                    ttl: ttl,
                })
            },

            // NS and CNAME both have the same structure.
            QueryType::NS => {
                Ok(DnsRecord::NS {
                    domain: domain,
                    host: buffer.read_qname()?,
                    ttl: ttl
                })
            },

            QueryType::CNAME => {
                Ok(DnsRecord::CNAME {
                    domain: domain,
                    host: buffer.read_qname()?,
                    ttl: ttl
                })
            },

            // MX is almost like the previous two, but with one extra field for priority.
            QueryType::MX => {
                Ok(DnsRecord::MX {
                    domain: domain,
                    priority: buffer.read_u16()?,
                    host: buffer.read_qname()?,
                    ttl: ttl
                })
            },

            QueryType::UNKNOWN(qtype_num) => {
                buffer.step(data_len as usize)?;



@@ 71,6 143,63 @@ impl DnsRecord {
                buffer.write_u8(octets[2])?;
                buffer.write_u8(octets[3])?;
            },

            Self::NS { ref domain, ref host, ttl } => {
                buffer.write_qname(domain)?;
                buffer.write_u16(QueryType::NS.into())?;
                buffer.write_u16(1)?;
                buffer.write_u32(ttl)?;

                let pre_pos = buffer.pos;
                buffer.write_u16(0)?;
                buffer.write_qname(host)?;

                let size = buffer.pos - (pre_pos + 2);
                buffer.set_u16(pre_pos, size as u16)?;
            },

            Self::CNAME { ref domain, ref host, ttl } => {
                buffer.write_qname(domain)?;
                buffer.write_u16(QueryType::CNAME.into())?;
                buffer.write_u16(1)?;
                buffer.write_u32(ttl)?;

                let pre_pos = buffer.pos;
                buffer.write_u16(0)?;
                buffer.write_qname(host)?;

                let size = buffer.pos - (pre_pos + 2);
                buffer.set_u16(pre_pos, size as u16)?;
            },

            Self::MX { ref domain, priority, ref host, ttl } => {
                buffer.write_qname(domain)?;
                buffer.write_u16(QueryType::MX.into())?;
                buffer.write_u16(1)?;
                buffer.write_u32(ttl)?;

                let pre_pos = buffer.pos;
                buffer.write_u16(0)?;

                buffer.write_u16(priority)?;
                buffer.write_qname(host)?;

                let size = buffer.pos - (pre_pos + 2);
                buffer.set_u16(pre_pos, size as u16)?;
            },

            Self::AAAA { ref domain, ref addr, ttl } => {
                buffer.write_qname(domain)?;
                buffer.write_u16(QueryType::AAAA.into())?;
                buffer.write_u16(1)?;
                buffer.write_u32(ttl)?;
                buffer.write_u16(16)?;

                for octet in &addr.segments() {
                    buffer.write_u16(*octet)?;
                }
            },

            Self:: UNKNOWN { .. } => {
                println!("Skipping record: {:?}", self);
            },

M src/dns_packet/query_type.rs => src/dns_packet/query_type.rs +17 -2
@@ 2,6 2,13 @@
pub enum QueryType {
    UNKNOWN(u16),
    A, // 1
    NS, // 2
    AAAA, // 28
    CNAME, // 5
    MX, // 15
    //SRV, // ?
    //CERT, // ?
    //TXT, // ?
}

impl Into<u16> for QueryType {


@@ 9,6 16,10 @@ impl Into<u16> for QueryType {
        match self {
            Self::UNKNOWN(x) => x,
            Self::A => 1,
            Self::NS => 2,
            Self::CNAME => 5,
            Self::MX => 15,
            Self::AAAA => 28,
        }
    }
}


@@ 34,8 45,12 @@ impl From<u16> for QueryType {
impl From<u32> for QueryType {
    fn from(num: u32) -> Self {
        match num {
            1 => Self::A,
            _ => Self::UNKNOWN(num as u16),
            01 => Self::A,
            02 => Self::NS,
            05 => Self::CNAME,
            15 => Self::MX,
            28 => Self::AAAA,
            _ => Self::UNKNOWN(num),
        }
    }
}