wireforge_app/llmnr/
mod.rs1use crate::dns::parser::{DnsPacket, DnsQuestionIter, DnsRecordIter};
8
9#[derive(Debug, Clone)]
12pub struct LlmnrPacket<'a> {
13 dns: DnsPacket<'a>,
14}
15
16impl<'a> LlmnrPacket<'a> {
17 pub fn new(buf: &'a [u8]) -> Option<Self> {
18 DnsPacket::new(buf).map(|dns| Self { dns })
19 }
20
21 pub fn is_query(&self) -> bool { !self.dns.qr() }
22 pub fn is_response(&self) -> bool { self.dns.qr() }
23
24 pub fn is_valid_query(&self) -> bool {
26 !self.dns.qr() && self.dns.questions_count() == 1
27 }
28
29 pub fn has_conflict(&self) -> bool {
32 self.dns.qr() && (self.dns.flags() & 0x0040) != 0
33 }
34
35 pub fn questions(&self) -> DnsQuestionIter<'a> { self.dns.questions() }
36 pub fn answers(&self) -> DnsRecordIter<'a> { self.dns.answers() }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use crate::dns::builder::DnsPacketBuilder;
43 use crate::dns::types::{DnsClass, DnsType};
44
45 #[test]
46 fn parse_llmnr_query() {
47 let q = DnsPacketBuilder::query()
48 .add_question("wpad", DnsType::A, DnsClass::IN)
49 .build();
50 let p = LlmnrPacket::new(&q).unwrap();
51 assert!(p.is_query());
52 assert!(p.is_valid_query());
53 }
54
55 #[test]
56 fn parse_llmnr_response() {
57 let r = DnsPacketBuilder::response()
58 .add_raw_answer("wpad", DnsType::A, 30, &[10, 0, 0, 1])
59 .build();
60 assert!(LlmnrPacket::new(&r).unwrap().is_response());
61 }
62}