ptr.rs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. use log::*;
  2. use crate::strings::{Labels, ReadLabels};
  3. use crate::wire::*;
  4. /// A **PTR** record, which holds a _pointer_ to a canonical name. This is
  5. /// most often used for reverse DNS lookups.
  6. ///
  7. /// # Encoding
  8. ///
  9. /// The text encoding is not specified, but this crate treats it as UTF-8.
  10. /// Invalid bytes are turned into the replacement character.
  11. ///
  12. /// # References
  13. ///
  14. /// - [RFC 1035 §3.3.14](https://tools.ietf.org/html/rfc1035) — Domain Names,
  15. /// Implementation and Specification (November 1987)
  16. #[derive(PartialEq, Debug)]
  17. pub struct PTR {
  18. /// The CNAME contained in the record.
  19. pub cname: Labels,
  20. }
  21. impl Wire for PTR {
  22. const NAME: &'static str = "PTR";
  23. const RR_TYPE: u16 = 12;
  24. #[cfg_attr(feature = "with_mutagen", ::mutagen::mutate)]
  25. fn read(stated_length: u16, c: &mut Cursor<&[u8]>) -> Result<Self, WireError> {
  26. let (cname, cname_length) = c.read_labels()?;
  27. trace!("Parsed cname -> {:?}", cname);
  28. if stated_length == cname_length {
  29. trace!("Length is correct");
  30. Ok(Self { cname })
  31. }
  32. else {
  33. warn!("Length is incorrect (stated length {:?}, cname length {:?}", stated_length, cname_length);
  34. Err(WireError::WrongLabelLength { stated_length, length_after_labels: cname_length })
  35. }
  36. }
  37. }
  38. #[cfg(test)]
  39. mod test {
  40. use super::*;
  41. use pretty_assertions::assert_eq;
  42. #[test]
  43. fn parses() {
  44. let buf = &[
  45. 0x03, 0x64, 0x6e, 0x73, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, // cname
  46. 0x00, // cname terminator
  47. ];
  48. assert_eq!(PTR::read(buf.len() as _, &mut Cursor::new(buf)).unwrap(),
  49. PTR {
  50. cname: Labels::encode("dns.google").unwrap(),
  51. });
  52. }
  53. #[test]
  54. fn incorrect_record_length() {
  55. let buf = &[
  56. 0x03, 0x65, 0x66, 0x67, // cname
  57. 0x00, // cname terminator
  58. ];
  59. assert_eq!(PTR::read(6, &mut Cursor::new(buf)),
  60. Err(WireError::WrongLabelLength { stated_length: 6, length_after_labels: 5 }));
  61. }
  62. #[test]
  63. fn record_empty() {
  64. assert_eq!(PTR::read(0, &mut Cursor::new(&[])),
  65. Err(WireError::IO));
  66. }
  67. #[test]
  68. fn buffer_ends_abruptly() {
  69. let buf = &[
  70. 0x03, 0x64, // the start of a cname
  71. ];
  72. assert_eq!(PTR::read(23, &mut Cursor::new(buf)),
  73. Err(WireError::IO));
  74. }
  75. }