soa.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. use log::*;
  2. use crate::strings::ReadLabels;
  3. use crate::wire::*;
  4. /// A **SOA** _(start of authority)_ record, which contains administrative
  5. /// information about the zone the domain is in. These are returned when a
  6. /// server does not have a record for a domain.
  7. ///
  8. /// # References
  9. ///
  10. /// - [RFC 1035 §3.3.13](https://tools.ietf.org/html/rfc1035) — Domain Names, Implementation and Specification (November 1987)
  11. #[derive(PartialEq, Debug, Clone)]
  12. pub struct SOA {
  13. /// The primary master name for this server.
  14. pub mname: String,
  15. /// The e-mail address of the administrator responsible for this DNS zone.
  16. pub rname: String,
  17. /// A serial number for this DNS zone.
  18. pub serial: u32,
  19. /// Duration, in seconds, after which secondary nameservers should query
  20. /// the master for _its_ SOA record.
  21. pub refresh_interval: u32,
  22. /// Duration, in seconds, after which secondary nameservers should retry
  23. /// requesting the serial number from the master if it does not respond.
  24. /// It should be less than `refresh`.
  25. pub retry_interval: u32,
  26. /// Duration, in seconds, after which secondary nameservers should stop
  27. /// answering requests for this zone if the master does not respond.
  28. /// It should be greater than the sum of `refresh` and `retry`.
  29. pub expire_limit: u32,
  30. /// Duration, in seconds, of the minimum time-to-live.
  31. pub minimum_ttl: u32,
  32. }
  33. impl Wire for SOA {
  34. const NAME: &'static str = "SOA";
  35. const RR_TYPE: u16 = 6;
  36. #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
  37. fn read(len: u16, c: &mut Cursor<&[u8]>) -> Result<Self, WireError> {
  38. let (mname, mname_len) = c.read_labels()?;
  39. trace!("Parsed mname -> {:?}", mname);
  40. let (rname, rname_len) = c.read_labels()?;
  41. trace!("Parsed rname -> {:?}", rname);
  42. let serial = c.read_u32::<BigEndian>()?;
  43. trace!("Parsed serial -> {:?}", serial);
  44. let refresh_interval = c.read_u32::<BigEndian>()?;
  45. trace!("Parsed refresh interval -> {:?}", refresh_interval);
  46. let retry_interval = c.read_u32::<BigEndian>()?;
  47. trace!("Parsed retry interval -> {:?}", retry_interval);
  48. let expire_limit = c.read_u32::<BigEndian>()?;
  49. trace!("Parsed expire limit -> {:?}", expire_limit);
  50. let minimum_ttl = c.read_u32::<BigEndian>()?;
  51. trace!("Parsed minimum TTL -> {:?}", minimum_ttl);
  52. let got_len = 4 * 5 + mname_len + rname_len;
  53. if len == got_len {
  54. trace!("Length is correct");
  55. Ok(Self {
  56. mname, rname, serial, refresh_interval,
  57. retry_interval, expire_limit, minimum_ttl,
  58. })
  59. }
  60. else {
  61. warn!("Length is incorrect (record length {:?}, mname plus rname plus fields length {:?})", len, got_len);
  62. Err(WireError::WrongLabelLength { expected: len, got: got_len })
  63. }
  64. }
  65. }
  66. #[cfg(test)]
  67. mod test {
  68. use super::*;
  69. #[test]
  70. fn parses() {
  71. let buf = &[
  72. 0x05, 0x62, 0x73, 0x61, 0x67, 0x6f, 0x02, 0x6d, 0x65, // mname
  73. 0x00, // mname terminator
  74. 0x05, 0x62, 0x73, 0x61, 0x67, 0x6f, 0x02, 0x6d, 0x65, // rname
  75. 0x00, // rname terminator
  76. 0x5d, 0x3c, 0xef, 0x02, // Serial
  77. 0x00, 0x01, 0x51, 0x80, // Refresh interval
  78. 0x00, 0x00, 0x1c, 0x20, // Retry interval
  79. 0x00, 0x09, 0x3a, 0x80, // Expire limit
  80. 0x00, 0x00, 0x01, 0x2c, // Minimum TTL
  81. ];
  82. assert_eq!(SOA::read(buf.len() as _, &mut Cursor::new(buf)).unwrap(),
  83. SOA {
  84. mname: String::from("bsago.me."),
  85. rname: String::from("bsago.me."),
  86. serial: 1564274434,
  87. refresh_interval: 86400,
  88. retry_interval: 7200,
  89. expire_limit: 604800,
  90. minimum_ttl: 300,
  91. });
  92. }
  93. #[test]
  94. fn record_empty() {
  95. assert_eq!(SOA::read(0, &mut Cursor::new(&[])),
  96. Err(WireError::IO));
  97. }
  98. #[test]
  99. fn buffer_ends_abruptly() {
  100. let buf = &[
  101. 0x05, 0x62, // the start of an mname
  102. ];
  103. assert_eq!(SOA::read(23, &mut Cursor::new(buf)),
  104. Err(WireError::IO));
  105. }
  106. }