iris_core/protocols/stream/dns/
parser.rs1use super::transaction::{DnsQuery, DnsResponse};
12use super::Dns;
13use crate::conntrack::pdu::L4Pdu;
14use crate::protocols::stream::{
15 ConnParsable, ParseResult, ParsingState, ProbeResult, Session, SessionData,
16};
17
18use std::collections::HashMap;
19
20#[derive(Default, Debug)]
21pub struct DnsParser {
22 sessions: HashMap<usize, Dns>,
24 cnt: usize,
26}
27
28impl ConnParsable for DnsParser {
29 fn parse(&mut self, pdu: &L4Pdu) -> ParseResult {
30 let offset = pdu.offset();
31 let length = pdu.length();
32 if length == 0 {
33 return ParseResult::Skipped;
34 }
35
36 if let Ok(data) = (pdu.mbuf_ref()).get_data_slice(offset, length) {
37 self.process(data)
38 } else {
39 log::warn!("Malformed packet");
40 ParseResult::Skipped
41 }
42 }
43
44 fn probe(&self, pdu: &L4Pdu) -> ProbeResult {
45 let dst_port = pdu.ctxt.dst.port();
46 let src_port = pdu.ctxt.src.port();
47 if src_port == 137 || dst_port == 137 {
48 return ProbeResult::NotForUs;
50 }
51 let offset = pdu.offset();
52 let length = pdu.length();
53 if pdu.length() == 0 {
54 return ProbeResult::Unsure;
55 }
56
57 if let Ok(data) = (pdu.mbuf).get_data_slice(offset, length) {
58 match dns_parser::Packet::parse(data) {
59 Ok(packet) => {
60 if packet.header.query {
61 if packet.questions.is_empty() {
62 return ProbeResult::NotForUs;
63 }
64 } else if packet.answers.is_empty() {
65 return ProbeResult::NotForUs;
66 }
67 ProbeResult::Certain
68 }
69 _ => ProbeResult::NotForUs,
70 }
71 } else {
72 log::warn!("Malformed packet");
73 ProbeResult::Error
74 }
75 }
76
77 fn remove_session(&mut self, session_id: usize) -> Option<Session> {
78 self.sessions.remove(&session_id).map(|dns| Session {
79 data: SessionData::Dns(Box::new(dns)),
80 id: session_id,
81 })
82 }
83
84 fn drain_sessions(&mut self) -> Vec<Session> {
85 self.sessions
86 .drain()
87 .map(|(session_id, dns)| Session {
88 data: SessionData::Dns(Box::new(dns)),
89 id: session_id,
90 })
91 .collect()
92 }
93
94 fn session_parsed_state(&self) -> ParsingState {
95 ParsingState::Parsing
96 }
97
98 fn body_offset(&mut self) -> Option<usize> {
100 None
101 }
102}
103
104impl DnsParser {
105 pub(crate) fn process(&mut self, data: &[u8]) -> ParseResult {
106 match dns_parser::Packet::parse(data) {
107 Ok(pkt) => {
108 if pkt.header.query {
109 log::debug!("DNS query");
110 let query = DnsQuery::parse_query(&pkt);
111 let query_id = pkt.header.id;
112 for (session_id, dns) in self.sessions.iter_mut() {
113 if query_id == dns.transaction_id {
114 if dns.response.is_some() {
115 dns.query = Some(query);
116 return ParseResult::Done(*session_id);
117 }
118 break;
119 }
120 }
121 let dns = Dns {
122 transaction_id: query_id,
123 query: Some(query),
124 response: None,
125 };
126 let session_id = self.cnt;
127 self.cnt += 1;
128 self.sessions.insert(session_id, dns);
129 ParseResult::Continue(session_id)
130 } else {
131 log::debug!("DNS answer");
132 let response = DnsResponse::parse_response(&pkt);
133 let answer_id = pkt.header.id;
134 for (session_id, dns) in self.sessions.iter_mut() {
135 if answer_id == dns.transaction_id {
136 if dns.query.is_some() {
137 dns.response = Some(response);
138 return ParseResult::Done(*session_id);
139 }
140 break;
141 }
142 }
143 let dns = Dns {
144 transaction_id: answer_id,
145 query: None,
146 response: Some(response),
147 };
148 let session_id = self.cnt;
149 self.cnt += 1;
150 self.sessions.insert(session_id, dns);
151 ParseResult::Continue(session_id)
152 }
153 }
154 e => {
155 log::debug!("parse error: {:?}", e);
156 ParseResult::Skipped
157 }
158 }
159 }
160}