tst-ns_rr_cursor.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* Tests for resource record parsing.
  2. Copyright (C) 2022-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <arpa/nameser.h>
  16. #include <string.h>
  17. #include <support/check.h>
  18. #include <support/next_to_fault.h>
  19. /* Reference packet for packet parsing. */
  20. static const unsigned char valid_packet[] =
  21. { 0x11, 0x12, 0x13, 0x14,
  22. 0x00, 0x01, /* Question count. */
  23. 0x00, 0x02, /* Answer count. */
  24. 0x21, 0x22, 0x23, 0x24, /* Other counts (not actually in packet). */
  25. 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
  26. 0x00, 0x1c, /* Question type: AAAA. */
  27. 0x00, 0x01, /* Question class: IN. */
  28. 0xc0, 0x0c, /* Compression reference to QNAME. */
  29. 0x00, 0x1c, /* Record type: AAAA. */
  30. 0x00, 0x01, /* Record class: IN. */
  31. 0x12, 0x34, 0x56, 0x78, /* Record TTL. */
  32. 0x00, 0x10, /* Record data length (16 bytes). */
  33. 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
  34. 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* IPv6 address. */
  35. 0xc0, 0x0c, /* Compression reference to QNAME. */
  36. 0x00, 0x1c, /* Record type: AAAA. */
  37. 0x00, 0x01, /* Record class: IN. */
  38. 0x11, 0x33, 0x55, 0x77, /* Record TTL. */
  39. 0x00, 0x10, /* Record data length (16 bytes). */
  40. 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  41. 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* IPv6 address. */
  42. };
  43. /* Special offsets in valid_packet. */
  44. enum
  45. {
  46. offset_of_first_record = 29,
  47. offset_of_second_record = 57,
  48. };
  49. /* Check that parsing valid_packet succeeds. */
  50. static void
  51. test_valid (void)
  52. {
  53. struct ns_rr_cursor c;
  54. TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, valid_packet,
  55. sizeof (valid_packet)));
  56. TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
  57. TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
  58. TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
  59. TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
  60. TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
  61. TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
  62. TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
  63. TEST_COMPARE (c.current - valid_packet, offset_of_first_record);
  64. struct ns_rr_wire r;
  65. TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
  66. TEST_COMPARE (r.rtype, T_AAAA);
  67. TEST_COMPARE (r.rclass, C_IN);
  68. TEST_COMPARE (r.ttl, 0x12345678);
  69. TEST_COMPARE_BLOB (r.rdata, r.rdlength,
  70. "\x90\x91\x92\x93\x94\x95\x96\x97"
  71. "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
  72. TEST_COMPARE (c.current - valid_packet, offset_of_second_record);
  73. TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
  74. TEST_COMPARE (r.rtype, T_AAAA);
  75. TEST_COMPARE (r.rclass, C_IN);
  76. TEST_COMPARE (r.ttl, 0x11335577);
  77. TEST_COMPARE_BLOB (r.rdata, r.rdlength,
  78. "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
  79. "\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 16);
  80. TEST_VERIFY (c.current == c.end);
  81. }
  82. /* Check that trying to parse a packet with a compressed QNAME fails. */
  83. static void
  84. test_compressed_qname (void)
  85. {
  86. static const unsigned char packet[] =
  87. { 0x11, 0x12, 0x13, 0x14,
  88. 0x00, 0x01, /* Question count. */
  89. 0x00, 0x00, /* Answer count. */
  90. 0x00, 0x00, 0x00, 0x00, /* Other counts. */
  91. 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
  92. 0x00, 0x01, /* Question type: A. */
  93. 0x00, 0x01, /* Question class: IN. */
  94. };
  95. struct ns_rr_cursor c;
  96. TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
  97. }
  98. /* Check that trying to parse a packet with two questions fails. */
  99. static void
  100. test_two_questions (void)
  101. {
  102. static const unsigned char packet[] =
  103. { 0x11, 0x12, 0x13, 0x14,
  104. 0x00, 0x02, /* Question count. */
  105. 0x00, 0x00, /* Answer count. */
  106. 0x00, 0x00, 0x00, 0x00, /* Other counts. */
  107. 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
  108. 0x00, 0x01, /* Question type: A. */
  109. 0x00, 0x01, /* Question class: IN. */
  110. 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
  111. 0x00, 0x1c, /* Question type: AAAA. */
  112. 0x00, 0x01, /* Question class: IN. */
  113. };
  114. struct ns_rr_cursor c;
  115. TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
  116. }
  117. /* Used to check that parsing truncated packets does not over-read. */
  118. static struct support_next_to_fault ntf;
  119. /* Truncated packet in the second resource record. */
  120. static void
  121. test_truncated_one_rr (size_t length)
  122. {
  123. unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
  124. unsigned char *start = end - length;
  125. /* Produce the truncated packet. */
  126. memcpy (start, valid_packet, length);
  127. struct ns_rr_cursor c;
  128. TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
  129. TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
  130. TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
  131. TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
  132. TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
  133. TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
  134. TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
  135. TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
  136. TEST_COMPARE (c.current - start, offset_of_first_record);
  137. struct ns_rr_wire r;
  138. TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
  139. TEST_COMPARE (r.rtype, T_AAAA);
  140. TEST_COMPARE (r.rclass, C_IN);
  141. TEST_COMPARE (r.ttl, 0x12345678);
  142. TEST_COMPARE_BLOB (r.rdata, r.rdlength,
  143. "\x90\x91\x92\x93\x94\x95\x96\x97"
  144. "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
  145. TEST_COMPARE (c.current - start, offset_of_second_record);
  146. TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
  147. }
  148. /* Truncated packet in the first resource record. */
  149. static void
  150. test_truncated_no_rr (size_t length)
  151. {
  152. unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
  153. unsigned char *start = end - length;
  154. /* Produce the truncated packet. */
  155. memcpy (start, valid_packet, length);
  156. struct ns_rr_cursor c;
  157. TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
  158. TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
  159. TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
  160. TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
  161. TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
  162. TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
  163. TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
  164. TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
  165. TEST_COMPARE (c.current - start, offset_of_first_record);
  166. struct ns_rr_wire r;
  167. TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
  168. }
  169. /* Truncated packet before first resource record. */
  170. static void
  171. test_truncated_before_rr (size_t length)
  172. {
  173. unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
  174. unsigned char *start = end - length;
  175. /* Produce the truncated packet. */
  176. memcpy (start, valid_packet, length);
  177. struct ns_rr_cursor c;
  178. TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, start, length));
  179. }
  180. static int
  181. do_test (void)
  182. {
  183. ntf = support_next_to_fault_allocate (sizeof (valid_packet));
  184. test_valid ();
  185. test_compressed_qname ();
  186. test_two_questions ();
  187. for (int length = offset_of_second_record; length < sizeof (valid_packet);
  188. ++length)
  189. test_truncated_one_rr (length);
  190. for (int length = offset_of_first_record; length < offset_of_second_record;
  191. ++length)
  192. test_truncated_no_rr (length);
  193. for (int length = 0; length < offset_of_first_record; ++length)
  194. test_truncated_before_rr (length);
  195. support_next_to_fault_free (&ntf);
  196. return 0;
  197. }
  198. #include <support/test-driver.c>