Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there an idiomatic and elegant way to read a compressed DNS message using deku's attributes? #514

Open
ivanbgd opened this issue Dec 12, 2024 · 0 comments

Comments

@ivanbgd
Copy link

ivanbgd commented Dec 12, 2024

I believe this could be useful for other formats & protocols as well.

RFC 1035 4 Messages

RFC 1035 4.1.4. Message compression

The highest two bits of the first byte (big-endian), if set, define a pointer. If they are reset, they define the label length.

I've been using the until attribute, to read until the terminating (NULL) character, but that only works for uncompressed names.

#[derive(Debug, DekuRead, DekuWrite, PartialEq)]
pub struct Message {
    pub header: Header,

    #[deku(count = "header.qdcount")]
    pub question: Vec<Question>,
}

#[derive(Debug, DekuRead, DekuWrite, PartialEq)]
pub struct Question {
    #[deku(until = "|v: &u8| *v == 0")]
    pub qname: Vec<u8>,

    pub qtype: Qtype,

    pub qclass: Qclass,
}

let mut buf = [0u8; 512];
let (read, source) = udp_socket
    .recv_from(&mut buf)
    .await
    .map_err(ConnectionError::RecvError)?;

let qmsg = Message::from_bytes((&mut buf, 0))?;

I am reading a whole message at once.

In case of a compressed name, we'd have to jump to the previously read uncompressed section.

I suppose I could read the header part and questions separately, one by one in a loop, but I'd like to solve it using attributes as that would be more elegant and more concise.

I was thinking about map, or cond & seek_from_start combined (but that's not possible). Can I somehow access the already read uncompressed name?

For example, if we query for abc.longname.com and def.longname.com, and the second name uses compression, we'd have to jump after def to the first longname.com and re-read it or re-use it somehow.

Perhaps it would be nice if we could combine cond with seek* and other attributes.

What would be the best (the most elegant) way to solve this now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant