strings.rs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //! Reading strings from the DNS wire protocol.
  2. use std::io::{self, Write};
  3. use byteorder::{ReadBytesExt, WriteBytesExt};
  4. use log::*;
  5. use crate::wire::*;
  6. /// An extension for `Cursor` that enables reading compressed domain names
  7. /// from DNS packets.
  8. pub(crate) trait ReadLabels {
  9. /// Read and expand a compressed domain name.
  10. fn read_labels(&mut self) -> Result<String, WireError>;
  11. }
  12. impl ReadLabels for Cursor<&[u8]> {
  13. fn read_labels(&mut self) -> Result<String, WireError> {
  14. let mut name_buf = Vec::new();
  15. read_string_recursive(&mut name_buf, self, &mut Vec::new())?;
  16. Ok(String::from_utf8_lossy(&*name_buf).to_string())
  17. }
  18. }
  19. /// An extension for `Write` that enables writing domain names.
  20. pub(crate) trait WriteLabels {
  21. /// Write a domain name.
  22. ///
  23. /// The names being queried are written with one byte slice per
  24. /// domain segment, preceded by each segment’s length, with the
  25. /// whole thing ending with a segment of zero length.
  26. ///
  27. /// So “dns.lookup.dog” would be encoded as:
  28. /// “3, dns, 6, lookup, 3, dog, 0”.
  29. fn write_labels(&mut self, input: &str) -> io::Result<()>;
  30. }
  31. impl<W: Write> WriteLabels for W {
  32. fn write_labels(&mut self, input: &str) -> io::Result<()> {
  33. for label in input.split('.') {
  34. self.write_u8(label.len() as u8)?;
  35. for b in label.as_bytes() {
  36. self.write_u8(*b)?;
  37. }
  38. }
  39. self.write_u8(0)?; // terminate the string
  40. Ok(())
  41. }
  42. }
  43. const RECURSION_LIMIT: usize = 8;
  44. #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
  45. fn read_string_recursive(name_buf: &mut Vec<u8>, c: &mut Cursor<&[u8]>, recursions: &mut Vec<u16>) -> Result<(), WireError> {
  46. loop {
  47. let byte = c.read_u8()?;
  48. if byte == 0 {
  49. break;
  50. }
  51. else if byte >= 0b_1100_0000 {
  52. if recursions.len() >= RECURSION_LIMIT {
  53. return Err(WireError::TooMuchRecursion(recursions.clone()));
  54. }
  55. let name_one = byte - 0b1100_0000;
  56. let name_two = c.read_u8()?;
  57. let offset = u16::from_be_bytes([name_one, name_two]);
  58. trace!("Backtracking to offset {}", offset);
  59. let new_pos = c.position();
  60. c.set_position(u64::from(offset));
  61. recursions.push(offset);
  62. read_string_recursive(name_buf, c, recursions)?;
  63. trace!("Coming back to {}", new_pos);
  64. c.set_position(new_pos);
  65. recursions.pop();
  66. break;
  67. }
  68. // Otherwise, treat the byte as the length of a label, and read that
  69. // many characters.
  70. else {
  71. for _ in 0 .. byte {
  72. let c = c.read_u8()?;
  73. name_buf.push(c);
  74. }
  75. name_buf.push(b'.');
  76. }
  77. }
  78. Ok(())
  79. }