1use std::marker;
2use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
3
4use byteorder::{BigEndian, ByteOrder};
5
6use crate::compress::*;
7use crate::constants::*;
8use crate::dns_sector::*;
9use crate::errors::*;
10use crate::parsed_packet::*;
11
12#[derive(Copy, Clone, Debug)]
16pub struct RRRaw<'t> {
17 pub packet: &'t [u8],
18 pub offset: usize,
19 pub name_end: usize,
20}
21
22pub struct RRRawMut<'t> {
26 pub packet: &'t mut [u8],
27 pub offset: usize,
28 pub name_end: usize,
29}
30
31pub trait DNSIterable {
34 fn next(self) -> Option<Self>
36 where
37 Self: marker::Sized;
38
39 fn offset(&self) -> Option<usize>;
45
46 fn offset_next(&self) -> usize;
48
49 fn set_offset(&mut self, offset: usize);
51
52 fn set_offset_next(&mut self, offset: usize);
54
55 fn invalidate(&mut self);
59
60 fn is_tombstone(&self) -> bool {
63 self.offset().is_none()
64 }
65
66 fn recompute_rr(&mut self);
68
69 fn recompute_sections(&mut self);
71
72 fn raw(&self) -> RRRaw<'_>;
74
75 fn raw_mut(&mut self) -> RRRawMut<'_>;
77
78 fn parsed_packet(&self) -> &ParsedPacket;
80
81 fn parsed_packet_mut(&mut self) -> &mut ParsedPacket;
83
84 #[inline]
86 fn packet(&self) -> &[u8] {
87 let raw = self.raw();
88 raw.packet
89 }
90
91 #[inline]
93 fn name_slice(&self) -> &[u8] {
94 let raw = self.raw();
95 &raw.packet[raw.offset..raw.name_end]
96 }
97
98 #[inline]
100 fn rdata_slice(&self) -> &[u8] {
101 let raw = self.raw();
102 &raw.packet[raw.name_end..]
103 }
104
105 #[inline]
107 fn name_slice_mut(&mut self) -> &mut [u8] {
108 let raw = self.raw_mut();
109 &mut raw.packet[raw.offset..raw.name_end]
110 }
111
112 #[inline]
115 fn rdata_slice_mut(&mut self) -> &mut [u8] {
116 let raw = self.raw_mut();
117 &mut raw.packet[raw.name_end..]
118 }
119
120 fn uncompress(&mut self) -> Result<(), Error> {
122 if !self.parsed_packet().maybe_compressed {
123 return Ok(());
124 }
125 let (uncompressed, new_offset_next) = {
126 let ref_offset_next = self.offset_next();
127 let compressed = self.raw_mut().packet;
128 Compress::uncompress_with_previous_offset(compressed, ref_offset_next)?
129 };
130 self.parsed_packet_mut().packet = Some(uncompressed);
131 self.set_offset_next(new_offset_next);
132 self.recompute_sections();
133 self.recompute_rr();
134 Ok(())
135 }
136}
137
138pub trait TypedIterable {
139 fn name(&self) -> Vec<u8>
143 where
144 Self: DNSIterable,
145 {
146 let raw = self.raw();
147 let offset = raw.offset;
148 if raw.name_end <= offset {
149 return Vec::new();
150 }
151 let packet = raw.packet;
152 let mut name = Compress::raw_name_to_str(packet, offset);
153 name.make_ascii_lowercase();
154 name
155 }
156
157 fn copy_raw_name(&self, name: &mut Vec<u8>) -> usize
161 where
162 Self: DNSIterable,
163 {
164 let raw = self.raw();
165 if raw.name_end <= raw.offset {
166 return 0;
167 }
168 Compress::copy_uncompressed_name(name, raw.packet, raw.offset).name_len
169 }
170
171 fn current_section(&self) -> Result<Section, Error>
173 where
174 Self: DNSIterable,
175 {
176 let offset = self.offset();
177 let parsed_packet = self.parsed_packet();
178 if offset < parsed_packet.offset_question {
179 bail!(DSError::InternalError("name before the question section"));
180 }
181 let mut section = Section::Question;
182 if parsed_packet.offset_answers.is_some() && offset >= parsed_packet.offset_answers {
183 section = Section::Answer;
184 }
185 if parsed_packet.offset_nameservers.is_some() && offset >= parsed_packet.offset_nameservers
186 {
187 section = Section::NameServers
188 }
189 if parsed_packet.offset_additional.is_some() && offset >= parsed_packet.offset_additional {
190 section = Section::Additional;
191 }
192 Ok(section)
193 }
194
195 fn resize_rr(&mut self, shift: isize) -> Result<(), Error>
198 where
199 Self: DNSIterable,
200 {
201 {
202 if shift == 0 {
203 return Ok(());
204 }
205 let offset = self.offset().ok_or(DSError::VoidRecord)?;
206 let packet = &mut self.parsed_packet_mut().packet_mut();
207 let packet_len = packet.len();
208 if shift > 0 {
209 let new_packet_len = packet_len + shift as usize;
210 if new_packet_len > 0xffff {
211 bail!(DSError::PacketTooLarge);
212 }
213 packet.resize(new_packet_len, 0);
214 debug_assert_eq!(
215 new_packet_len,
216 (offset as isize + shift) as usize + (packet_len - offset)
217 );
218 packet.copy_within(offset..offset + packet_len, offset + shift as usize);
219 } else if shift < 0 {
220 let shift = (-shift) as usize;
221 assert!(packet_len >= shift);
222 packet.copy_within(offset + shift.., offset);
223 packet.truncate(packet_len - shift);
224 }
225 }
226 let new_offset_next = (self.offset_next() as isize + shift) as usize;
227 self.set_offset_next(new_offset_next);
228 let section = self.current_section()?;
229 let parsed_packet = self.parsed_packet_mut();
230 if section == Section::NameServers
231 || section == Section::Answer
232 || section == Section::Question
233 {
234 parsed_packet.offset_additional = parsed_packet
235 .offset_additional
236 .map(|x| (x as isize + shift) as usize)
237 }
238 if section == Section::Answer || section == Section::Question {
239 parsed_packet.offset_nameservers = parsed_packet
240 .offset_nameservers
241 .map(|x| (x as isize + shift) as usize)
242 }
243 if section == Section::Question {
244 parsed_packet.offset_answers = parsed_packet
245 .offset_answers
246 .map(|x| (x as isize + shift) as usize)
247 }
248 Ok(())
249 }
250
251 fn set_raw_name(&mut self, name: &[u8]) -> Result<(), Error>
253 where
254 Self: DNSIterable,
255 {
256 let new_name_len = DNSSector::check_uncompressed_name(name, 0)?;
257 let name = &name[..new_name_len];
258 if self.parsed_packet().maybe_compressed {
259 let (uncompressed, new_offset) = {
260 let ref_offset = self.offset().ok_or(DSError::VoidRecord)?;
261 let compressed = self.raw_mut().packet;
262 Compress::uncompress_with_previous_offset(compressed, ref_offset)?
263 };
264 self.parsed_packet_mut().packet = Some(uncompressed);
265 self.set_offset(new_offset);
266 self.recompute_rr(); self.recompute_sections();
268 }
269 let offset = self.offset().ok_or(DSError::VoidRecord)?;
270 debug_assert!(!self.parsed_packet().maybe_compressed);
271 let current_name_len = Compress::raw_name_len(self.name_slice());
272 let shift = new_name_len as isize - current_name_len as isize;
273 self.resize_rr(shift)?;
274 {
275 let packet = &mut self.parsed_packet_mut().packet_mut();
276 packet[offset..offset + new_name_len].copy_from_slice(name);
277 }
278 self.recompute_rr();
279
280 Ok(())
281 }
282
283 fn delete(&mut self) -> Result<(), Error>
285 where
286 Self: DNSIterable,
287 {
288 self.offset().ok_or(DSError::VoidRecord)?;
289 let section = self.current_section()?;
290 if self.parsed_packet().maybe_compressed {
291 let (uncompressed, new_offset) = {
292 let ref_offset = self.offset().expect("delete() called on a tombstone");
293 let compressed = self.raw_mut().packet;
294 Compress::uncompress_with_previous_offset(compressed, ref_offset)?
295 };
296 self.parsed_packet_mut().packet = Some(uncompressed);
297 self.set_offset(new_offset);
298 self.recompute_rr(); self.recompute_sections();
300 }
301 let rr_len = self.offset_next()
302 - self
303 .offset()
304 .expect("Deleting record with no known offset after optional decompression");
305 assert!(rr_len > 0);
306 self.resize_rr(-(rr_len as isize))?;
307 let offset = self.offset().unwrap();
308 self.set_offset_next(offset);
309 self.invalidate();
310 let parsed_packet = self.parsed_packet_mut();
311 let rrcount = parsed_packet.rrcount_dec(section)?;
312 if rrcount <= 0 {
313 let offset = match section {
314 Section::Question => &mut parsed_packet.offset_question,
315 Section::Answer => &mut parsed_packet.offset_answers,
316 Section::NameServers => &mut parsed_packet.offset_nameservers,
317 Section::Additional => &mut parsed_packet.offset_additional,
318 _ => panic!("delete() cannot be used to delete EDNS pseudo-records"),
319 };
320 *offset = None;
321 }
322 Ok(())
323 }
324
325 #[inline]
327 fn rr_type(&self) -> u16
328 where
329 Self: DNSIterable,
330 {
331 BigEndian::read_u16(&self.rdata_slice()[DNS_RR_TYPE_OFFSET..])
332 }
333
334 #[inline]
336 fn rr_class(&self) -> u16
337 where
338 Self: DNSIterable,
339 {
340 BigEndian::read_u16(&self.rdata_slice()[DNS_RR_CLASS_OFFSET..])
341 }
342}
343
344#[derive(Copy, Clone, Debug)]
346pub enum RawRRData<'t> {
347 IpAddr(IpAddr),
348 Data(&'t [u8]),
349}
350
351pub trait RdataIterable {
352 #[inline]
354 fn rr_ttl(&self) -> u32
355 where
356 Self: DNSIterable + TypedIterable,
357 {
358 BigEndian::read_u32(&self.rdata_slice()[DNS_RR_TTL_OFFSET..])
359 }
360
361 fn set_rr_ttl(&mut self, ttl: u32)
363 where
364 Self: DNSIterable + TypedIterable,
365 {
366 BigEndian::write_u32(&mut self.rdata_slice_mut()[DNS_RR_TTL_OFFSET..], ttl);
367 }
368
369 #[inline]
371 fn rr_rdlen(&self) -> usize
372 where
373 Self: DNSIterable + TypedIterable,
374 {
375 BigEndian::read_u16(&self.rdata_slice()[DNS_RR_RDLEN_OFFSET..]) as usize
376 }
377
378 fn rr_rd(&self) -> Result<RawRRData<'_>, Error>
380 where
381 Self: DNSIterable + TypedIterable,
382 {
383 if let Ok(ip_addr) = self.rr_ip() {
384 return Ok(RawRRData::IpAddr(ip_addr));
385 }
386 let rdata_len = self.rr_rdlen();
387 let rdata = &self.rdata_slice()[DNS_RR_HEADER_SIZE..DNS_RR_HEADER_SIZE + rdata_len];
388 Ok(RawRRData::Data(rdata))
389 }
390
391 fn rr_ip(&self) -> Result<IpAddr, Error>
393 where
394 Self: DNSIterable + TypedIterable,
395 {
396 match self.rr_type() {
397 x if x == Type::A.into() => {
398 let rdata = self.rdata_slice();
399 assert!(rdata.len() >= DNS_RR_HEADER_SIZE + 4);
400 let mut ip = [0u8; 4];
401 ip.copy_from_slice(&rdata[DNS_RR_HEADER_SIZE..DNS_RR_HEADER_SIZE + 4]);
402 Ok(IpAddr::V4(Ipv4Addr::from(ip)))
403 }
404 x if x == Type::AAAA.into() => {
405 let rdata = self.rdata_slice();
406 assert!(rdata.len() >= DNS_RR_HEADER_SIZE + 16);
407 let mut ip = [0u8; 16];
408 ip.copy_from_slice(&rdata[DNS_RR_HEADER_SIZE..DNS_RR_HEADER_SIZE + 16]);
409 Ok(IpAddr::V6(Ipv6Addr::from(ip)))
410 }
411 _ => bail!(DSError::PropertyNotFound),
412 }
413 }
414
415 fn set_rr_ip(&mut self, ip: &IpAddr) -> Result<(), Error>
417 where
418 Self: DNSIterable + TypedIterable,
419 {
420 match self.rr_type() {
421 x if x == Type::A.into() => match *ip {
422 IpAddr::V4(ip) => {
423 let rdata = self.rdata_slice_mut();
424 assert!(rdata.len() >= DNS_RR_HEADER_SIZE + 4);
425 rdata[DNS_RR_HEADER_SIZE..DNS_RR_HEADER_SIZE + 4].copy_from_slice(&ip.octets());
426 Ok(())
427 }
428 _ => bail!(DSError::WrongAddressFamily),
429 },
430 x if x == Type::AAAA.into() => match *ip {
431 IpAddr::V6(ip) => {
432 let rdata = self.rdata_slice_mut();
433 assert!(rdata.len() >= DNS_RR_HEADER_SIZE + 16);
434 rdata[DNS_RR_HEADER_SIZE..DNS_RR_HEADER_SIZE + 16]
435 .copy_from_slice(&ip.octets());
436 Ok(())
437 }
438 _ => bail!(DSError::WrongAddressFamily),
439 },
440 _ => bail!(DSError::PropertyNotFound),
441 }
442 }
443}
444
445#[derive(Debug)]
453pub struct RRIterator<'t> {
454 pub parsed_packet: &'t mut ParsedPacket,
455 pub section: Section,
456 pub offset: Option<usize>,
457 pub offset_next: usize,
458 pub name_end: usize,
459 pub rrs_left: u16,
460}
461
462impl<'t> RRIterator<'t> {
463 pub fn new(parsed_packet: &'t mut ParsedPacket, section: Section) -> Self {
466 RRIterator {
467 parsed_packet,
468 section,
469 offset: None,
470 offset_next: 0,
471 name_end: 0,
472 rrs_left: 0,
473 }
474 }
475
476 pub fn recompute(&mut self) {
477 let offset = self
478 .offset
479 .expect("recompute() called prior to iterating over RRs");
480 let name_end = Self::skip_name(self.parsed_packet.packet(), offset);
481 let offset_next = Self::skip_rdata(self.parsed_packet.packet(), name_end);
482 self.name_end = name_end;
483 self.offset_next = offset_next;
484 }
485
486 pub fn skip_name(packet: &[u8], mut offset: usize) -> usize {
489 let packet_len = packet.len();
490 loop {
491 let label_len = match packet[offset] {
492 len if len & 0xc0 == 0xc0 => {
493 assert!(packet_len - offset > 2);
494 offset += 2;
495 break;
496 }
497 len => len,
498 } as usize;
499 assert!(label_len < packet_len - offset - 1);
500 offset += label_len + 1;
501 if label_len == 0 {
502 break;
503 }
504 }
505 offset
506 }
507
508 #[inline]
509 fn rr_rdlen(packet: &[u8], offset: usize) -> usize {
510 BigEndian::read_u16(&packet[offset + DNS_RR_RDLEN_OFFSET..]) as usize
511 }
512
513 #[inline]
514 pub fn skip_rdata(packet: &[u8], offset: usize) -> usize {
515 offset + DNS_RR_HEADER_SIZE + Self::rr_rdlen(packet, offset)
516 }
517
518 #[inline]
519 pub fn skip_rr(packet: &[u8], offset: usize) -> usize {
520 Self::skip_rdata(packet, Self::skip_name(packet, offset))
521 }
522
523 #[inline]
524 fn edns_rr_rdlen(packet: &[u8], offset: usize) -> usize {
525 BigEndian::read_u16(&packet[offset + DNS_EDNS_RR_RDLEN_OFFSET..]) as usize
526 }
527
528 pub fn edns_skip_rr(packet: &[u8], mut offset: usize) -> usize {
529 offset += DNS_EDNS_RR_HEADER_SIZE + Self::edns_rr_rdlen(packet, offset);
530 offset
531 }
532}