wire_parsing_tests.rs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. use std::net::Ipv4Addr;
  2. use dns::{Response, Query, Answer, Labels, Flags, Opcode, QClass, qtype};
  3. use dns::record::{Record, A, CNAME, OPT};
  4. #[test]
  5. fn parse_nothing() {
  6. assert!(Response::from_bytes(&[]).is_err());
  7. }
  8. #[test]
  9. fn parse_response_standard() {
  10. let buf = &[
  11. 0x0d, 0xcd, // transaction ID
  12. 0x81, 0x80, // flags (standard query, response, no error)
  13. 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, // counts (1, 1, 0, 1)
  14. // the query:
  15. 0x03, 0x64, 0x6e, 0x73, 0x06, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x03,
  16. 0x64, 0x6f, 0x67, 0x00, // "dns.lookup.dog."
  17. 0x00, 0x01, // type A
  18. 0x00, 0x01, // class IN
  19. // the answer:
  20. 0xc0, 0x0c, // to find the name, backtrack to position 0x0c (12)
  21. 0x00, 0x01, // type A
  22. 0x00, 0x01, // class IN
  23. 0x00, 0x00, 0x03, 0xa5, // TTL (933 seconds)
  24. 0x00, 0x04, // record data length 4
  25. 0x8a, 0x44, 0x75, 0x5e, // record date (138.68.117.94)
  26. // the additional:
  27. 0x00, // no name
  28. 0x00, 0x29, // type OPT
  29. 0x02, 0x00, // UDP payload size (512)
  30. 0x00, 0x00, // higher bits (all 0)
  31. 0x00, // EDNS version
  32. 0x00, 0x00, // extra bits (DO bit unset)
  33. 0x00, // data length 0
  34. ];
  35. let response = Response {
  36. transaction_id: 0x0dcd,
  37. flags: Flags {
  38. response: true,
  39. opcode: Opcode::Query,
  40. authoritative: false,
  41. truncated: false,
  42. recursion_desired: true,
  43. recursion_available: true,
  44. authentic_data: false,
  45. checking_disabled: false,
  46. error_code: None,
  47. },
  48. queries: vec![
  49. Query {
  50. qname: Labels::encode("dns.lookup.dog").unwrap(),
  51. qclass: QClass::IN,
  52. qtype: qtype!(A),
  53. },
  54. ],
  55. answers: vec![
  56. Answer::Standard {
  57. qname: Labels::encode("dns.lookup.dog").unwrap(),
  58. qclass: QClass::IN,
  59. ttl: 933,
  60. record: Record::A(A {
  61. address: Ipv4Addr::new(138, 68, 117, 94),
  62. }),
  63. }
  64. ],
  65. authorities: vec![],
  66. additionals: vec![
  67. Answer::Pseudo {
  68. qname: Labels::root(),
  69. opt: OPT {
  70. udp_payload_size: 512,
  71. higher_bits: 0,
  72. edns0_version: 0,
  73. flags: 0,
  74. data: vec![],
  75. },
  76. },
  77. ],
  78. };
  79. assert_eq!(Response::from_bytes(buf), Ok(response));
  80. }
  81. #[test]
  82. fn parse_response_with_mixed_string() {
  83. let buf = &[
  84. 0x06, 0x9f, // transaction ID
  85. 0x81, 0x80, // flags (standard query, response, no error)
  86. 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // counts (1, 1, 0, 0)
  87. // the query:
  88. 0x0d, 0x63, 0x6e, 0x61, 0x6d, 0x65, 0x2d, 0x65, 0x78, 0x61, 0x6d, 0x70,
  89. 0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x03, 0x64, 0x6f,
  90. 0x67, 0x00, // "cname-example.lookup.dog"
  91. 0x00, 0x05, // type CNAME
  92. 0x00, 0x01, // class IN
  93. // the answer:
  94. 0xc0, 0x0c, // to find the name, backtrack to position 0x0c (12)
  95. 0x00, 0x05, // type CNAME
  96. 0x00, 0x01, // class IN
  97. 0x00, 0x00, 0x03, 0x69, // TTL (873 seconds)
  98. 0x00, 0x06, // record data length 6
  99. 0x03, 0x64, 0x6e, 0x73, 0xc0, 0x1a,
  100. // "dns.lookup.dog.", which is "dns." + backtrack to position 0x1a (28)
  101. ];
  102. let response = Response {
  103. transaction_id: 0x069f,
  104. flags: Flags {
  105. response: true,
  106. opcode: Opcode::Query,
  107. authoritative: false,
  108. truncated: false,
  109. recursion_desired: true,
  110. recursion_available: true,
  111. authentic_data: false,
  112. checking_disabled: false,
  113. error_code: None,
  114. },
  115. queries: vec![
  116. Query {
  117. qname: Labels::encode("cname-example.lookup.dog").unwrap(),
  118. qclass: QClass::IN,
  119. qtype: qtype!(CNAME),
  120. },
  121. ],
  122. answers: vec![
  123. Answer::Standard {
  124. qname: Labels::encode("cname-example.lookup.dog").unwrap(),
  125. qclass: QClass::IN,
  126. ttl: 873,
  127. record: Record::CNAME(CNAME {
  128. domain: Labels::encode("dns.lookup.dog").unwrap(),
  129. }),
  130. }
  131. ],
  132. authorities: vec![],
  133. additionals: vec![],
  134. };
  135. assert_eq!(Response::from_bytes(buf), Ok(response));
  136. }