resolv_test.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  1. /* DNS test framework and libresolv redirection.
  2. Copyright (C) 2016-2019 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. <http://www.gnu.org/licenses/>. */
  15. #include <support/resolv_test.h>
  16. #include <arpa/inet.h>
  17. #include <errno.h>
  18. #include <fcntl.h>
  19. #include <nss.h>
  20. #include <resolv.h>
  21. #include <search.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <support/check.h>
  25. #include <support/namespace.h>
  26. #include <support/support.h>
  27. #include <support/test-driver.h>
  28. #include <support/xsocket.h>
  29. #include <support/xthread.h>
  30. #include <support/xunistd.h>
  31. #include <sys/uio.h>
  32. #include <unistd.h>
  33. /* Response builder. */
  34. enum
  35. {
  36. max_response_length = 65536
  37. };
  38. /* Used for locating domain names containing for the purpose of
  39. forming compression references. */
  40. struct compressed_name
  41. {
  42. uint16_t offset;
  43. unsigned char length;
  44. unsigned char name[]; /* Without terminating NUL. */
  45. };
  46. static struct compressed_name *
  47. allocate_compressed_name (const unsigned char *encoded, unsigned int offset)
  48. {
  49. /* Compute the length of the domain name. */
  50. size_t length;
  51. {
  52. const unsigned char *p;
  53. for (p = encoded; *p != '\0';)
  54. {
  55. /* No compression references are allowed. */
  56. TEST_VERIFY (*p <= 63);
  57. /* Skip over the label. */
  58. p += 1 + *p;
  59. }
  60. length = p - encoded;
  61. ++length; /* For the terminating NUL byte. */
  62. }
  63. TEST_VERIFY_EXIT (length <= 255);
  64. struct compressed_name *result
  65. = xmalloc (offsetof (struct compressed_name, name) + length);
  66. result->offset = offset;
  67. result->length = length;
  68. memcpy (result->name, encoded, length);
  69. return result;
  70. }
  71. /* Convert CH to lower case. Only change letters in the ASCII
  72. range. */
  73. static inline unsigned char
  74. ascii_tolower (unsigned char ch)
  75. {
  76. if ('A' <= ch && ch <= 'Z')
  77. return ch - 'A' + 'a';
  78. else
  79. return ch;
  80. }
  81. /* Compare both names, for use with tsearch. The order is arbitrary,
  82. but the comparison is case-insenstive. */
  83. static int
  84. compare_compressed_name (const void *left, const void *right)
  85. {
  86. const struct compressed_name *crleft = left;
  87. const struct compressed_name *crright = right;
  88. if (crleft->length != crright->length)
  89. /* The operands are converted to int before the subtraction. */
  90. return crleft->length - crright->length;
  91. const unsigned char *nameleft = crleft->name;
  92. const unsigned char *nameright = crright->name;
  93. while (true)
  94. {
  95. int lenleft = *nameleft++;
  96. int lenright = *nameright++;
  97. /* Labels must not e compression references. */
  98. TEST_VERIFY (lenleft <= 63);
  99. TEST_VERIFY (lenright <= 63);
  100. if (lenleft != lenright)
  101. return left - right;
  102. if (lenleft == 0)
  103. /* End of name reached without spotting a difference. */
  104. return 0;
  105. /* Compare the label in a case-insenstive manner. */
  106. const unsigned char *endnameleft = nameleft + lenleft;
  107. while (nameleft < endnameleft)
  108. {
  109. int l = *nameleft++;
  110. int r = *nameright++;
  111. if (l != r)
  112. {
  113. l = ascii_tolower (l);
  114. r = ascii_tolower (r);
  115. if (l != r)
  116. return l - r;
  117. }
  118. }
  119. }
  120. }
  121. struct resolv_response_builder
  122. {
  123. const unsigned char *query_buffer;
  124. size_t query_length;
  125. size_t offset; /* Bytes written so far in buffer. */
  126. ns_sect section; /* Current section in the DNS packet. */
  127. unsigned int truncate_bytes; /* Bytes to remove at end of response. */
  128. bool drop; /* Discard generated response. */
  129. bool close; /* Close TCP client connection. */
  130. /* Offset of the two-byte RDATA length field in the currently
  131. written RDATA sub-structure. 0 if no RDATA is being written. */
  132. size_t current_rdata_offset;
  133. /* tsearch tree for locating targets for label compression. */
  134. void *compression_offsets;
  135. /* Must be last. Not zeroed for performance reasons. */
  136. unsigned char buffer[max_response_length];
  137. };
  138. /* Response builder. */
  139. void
  140. resolv_response_init (struct resolv_response_builder *b,
  141. struct resolv_response_flags flags)
  142. {
  143. if (b->offset > 0)
  144. FAIL_EXIT1 ("response_init: called at offset %zu", b->offset);
  145. if (b->query_length < 12)
  146. FAIL_EXIT1 ("response_init called for a query of size %zu",
  147. b->query_length);
  148. if (flags.rcode > 15)
  149. FAIL_EXIT1 ("response_init: invalid RCODE %u", flags.rcode);
  150. /* Copy the transaction ID. */
  151. b->buffer[0] = b->query_buffer[0];
  152. b->buffer[1] = b->query_buffer[1];
  153. /* Initialize the flags. */
  154. b->buffer[2] = 0x80; /* Mark as response. */
  155. b->buffer[2] |= b->query_buffer[2] & 0x01; /* Copy the RD bit. */
  156. if (flags.tc)
  157. b->buffer[2] |= 0x02;
  158. b->buffer[3] = 0x80 | flags.rcode; /* Always set RA. */
  159. /* Fill in the initial section count values. */
  160. b->buffer[4] = flags.qdcount >> 8;
  161. b->buffer[5] = flags.qdcount;
  162. b->buffer[6] = flags.ancount >> 8;
  163. b->buffer[7] = flags.ancount;
  164. b->buffer[8] = flags.nscount >> 8;
  165. b->buffer[9] = flags.nscount;
  166. b->buffer[10] = flags.adcount >> 8;
  167. b->buffer[11] = flags.adcount;
  168. b->offset = 12;
  169. }
  170. void
  171. resolv_response_section (struct resolv_response_builder *b, ns_sect section)
  172. {
  173. if (b->offset == 0)
  174. FAIL_EXIT1 ("resolv_response_section: response_init not called before");
  175. if (section < b->section)
  176. FAIL_EXIT1 ("resolv_response_section: cannot go back to previous section");
  177. b->section = section;
  178. }
  179. /* Add a single byte to B. */
  180. static inline void
  181. response_add_byte (struct resolv_response_builder *b, unsigned char ch)
  182. {
  183. if (b->offset == max_response_length)
  184. FAIL_EXIT1 ("DNS response exceeds 64 KiB limit");
  185. b->buffer[b->offset] = ch;
  186. ++b->offset;
  187. }
  188. /* Add a 16-bit word VAL to B, in big-endian format. */
  189. static void
  190. response_add_16 (struct resolv_response_builder *b, uint16_t val)
  191. {
  192. response_add_byte (b, val >> 8);
  193. response_add_byte (b, val);
  194. }
  195. /* Increment the pers-section record counter in the packet header. */
  196. static void
  197. response_count_increment (struct resolv_response_builder *b)
  198. {
  199. unsigned int offset = b->section;
  200. offset = 4 + 2 * offset;
  201. ++b->buffer[offset + 1];
  202. if (b->buffer[offset + 1] == 0)
  203. {
  204. /* Carry. */
  205. ++b->buffer[offset];
  206. if (b->buffer[offset] == 0)
  207. /* Overflow. */
  208. FAIL_EXIT1 ("too many records in section");
  209. }
  210. }
  211. void
  212. resolv_response_add_question (struct resolv_response_builder *b,
  213. const char *name, uint16_t class, uint16_t type)
  214. {
  215. if (b->offset == 0)
  216. FAIL_EXIT1 ("resolv_response_add_question: "
  217. "resolv_response_init not called");
  218. if (b->section != ns_s_qd)
  219. FAIL_EXIT1 ("resolv_response_add_question: "
  220. "must be called in the question section");
  221. resolv_response_add_name (b, name);
  222. response_add_16 (b, type);
  223. response_add_16 (b, class);
  224. response_count_increment (b);
  225. }
  226. void
  227. resolv_response_add_name (struct resolv_response_builder *b,
  228. const char *const origname)
  229. {
  230. unsigned char encoded_name[NS_MAXDNAME];
  231. if (ns_name_pton (origname, encoded_name, sizeof (encoded_name)) < 0)
  232. FAIL_EXIT1 ("ns_name_pton (\"%s\"): %m", origname);
  233. /* Copy the encoded name into the output buffer, apply compression
  234. where possible. */
  235. for (const unsigned char *name = encoded_name; ;)
  236. {
  237. if (*name == '\0')
  238. {
  239. /* We have reached the end of the name. Add the terminating
  240. NUL byte. */
  241. response_add_byte (b, '\0');
  242. break;
  243. }
  244. /* Set to the compression target if compression is possible. */
  245. struct compressed_name *crname_target;
  246. /* Compression references can only reach the beginning of the
  247. packet. */
  248. enum { compression_limit = 1 << 12 };
  249. {
  250. /* The trailing part of the name to be looked up in the tree
  251. with the compression targets. */
  252. struct compressed_name *crname
  253. = allocate_compressed_name (name, b->offset);
  254. if (b->offset < compression_limit)
  255. {
  256. /* Add the name to the tree, for future compression
  257. references. */
  258. void **ptr = tsearch (crname, &b->compression_offsets,
  259. compare_compressed_name);
  260. if (ptr == NULL)
  261. FAIL_EXIT1 ("tsearch out of memory");
  262. crname_target = *ptr;
  263. if (crname_target != crname)
  264. /* The new name was not actually added to the tree.
  265. Deallocate it. */
  266. free (crname);
  267. else
  268. /* Signal that the tree did not yet contain the name,
  269. but keep the allocation because it is now part of the
  270. tree. */
  271. crname_target = NULL;
  272. }
  273. else
  274. {
  275. /* This name cannot be reached by a compression reference.
  276. No need to add it to the tree for future reference. */
  277. void **ptr = tfind (crname, &b->compression_offsets,
  278. compare_compressed_name);
  279. if (ptr != NULL)
  280. crname_target = *ptr;
  281. else
  282. crname_target = NULL;
  283. TEST_VERIFY (crname_target != crname);
  284. /* Not added to the tree. */
  285. free (crname);
  286. }
  287. }
  288. if (crname_target != NULL)
  289. {
  290. /* The name is known. Reference the previous location. */
  291. unsigned int old_offset = crname_target->offset;
  292. TEST_VERIFY_EXIT (old_offset < compression_limit);
  293. response_add_byte (b, 0xC0 | (old_offset >> 8));
  294. response_add_byte (b, old_offset);
  295. break;
  296. }
  297. else
  298. {
  299. /* The name is new. Add this label. */
  300. unsigned int len = 1 + *name;
  301. resolv_response_add_data (b, name, len);
  302. name += len;
  303. }
  304. }
  305. }
  306. void
  307. resolv_response_open_record (struct resolv_response_builder *b,
  308. const char *name,
  309. uint16_t class, uint16_t type, uint32_t ttl)
  310. {
  311. if (b->section == ns_s_qd)
  312. FAIL_EXIT1 ("resolv_response_open_record called in question section");
  313. if (b->current_rdata_offset != 0)
  314. FAIL_EXIT1 ("resolv_response_open_record called with open record");
  315. resolv_response_add_name (b, name);
  316. response_add_16 (b, type);
  317. response_add_16 (b, class);
  318. response_add_16 (b, ttl >> 16);
  319. response_add_16 (b, ttl);
  320. b->current_rdata_offset = b->offset;
  321. /* Add room for the RDATA length. */
  322. response_add_16 (b, 0);
  323. }
  324. void
  325. resolv_response_close_record (struct resolv_response_builder *b)
  326. {
  327. size_t rdata_offset = b->current_rdata_offset;
  328. if (rdata_offset == 0)
  329. FAIL_EXIT1 ("response_close_record called without open record");
  330. size_t rdata_length = b->offset - rdata_offset - 2;
  331. if (rdata_length > 65535)
  332. FAIL_EXIT1 ("RDATA length %zu exceeds limit", rdata_length);
  333. b->buffer[rdata_offset] = rdata_length >> 8;
  334. b->buffer[rdata_offset + 1] = rdata_length;
  335. response_count_increment (b);
  336. b->current_rdata_offset = 0;
  337. }
  338. void
  339. resolv_response_add_data (struct resolv_response_builder *b,
  340. const void *data, size_t length)
  341. {
  342. size_t remaining = max_response_length - b->offset;
  343. if (remaining < length)
  344. FAIL_EXIT1 ("resolv_response_add_data: not enough room for %zu bytes",
  345. length);
  346. memcpy (b->buffer + b->offset, data, length);
  347. b->offset += length;
  348. }
  349. void
  350. resolv_response_drop (struct resolv_response_builder *b)
  351. {
  352. b->drop = true;
  353. }
  354. void
  355. resolv_response_close (struct resolv_response_builder *b)
  356. {
  357. b->close = true;
  358. }
  359. void
  360. resolv_response_truncate_data (struct resolv_response_builder *b, size_t count)
  361. {
  362. if (count > 65535)
  363. FAIL_EXIT1 ("resolv_response_truncate_data: argument too large: %zu",
  364. count);
  365. b->truncate_bytes = count;
  366. }
  367. size_t
  368. resolv_response_length (const struct resolv_response_builder *b)
  369. {
  370. return b->offset;
  371. }
  372. unsigned char *
  373. resolv_response_buffer (const struct resolv_response_builder *b)
  374. {
  375. unsigned char *result = xmalloc (b->offset);
  376. memcpy (result, b->buffer, b->offset);
  377. return result;
  378. }
  379. static struct resolv_response_builder *
  380. response_builder_allocate
  381. (const unsigned char *query_buffer, size_t query_length)
  382. {
  383. struct resolv_response_builder *b = xmalloc (sizeof (*b));
  384. memset (b, 0, offsetof (struct resolv_response_builder, buffer));
  385. b->query_buffer = query_buffer;
  386. b->query_length = query_length;
  387. return b;
  388. }
  389. static void
  390. response_builder_free (struct resolv_response_builder *b)
  391. {
  392. tdestroy (b->compression_offsets, free);
  393. free (b);
  394. }
  395. /* DNS query processing. */
  396. /* Data extracted from the question section of a DNS packet. */
  397. struct query_info
  398. {
  399. char qname[MAXDNAME];
  400. uint16_t qclass;
  401. uint16_t qtype;
  402. struct resolv_edns_info edns;
  403. };
  404. /* Update *INFO from the specified DNS packet. */
  405. static void
  406. parse_query (struct query_info *info,
  407. const unsigned char *buffer, size_t length)
  408. {
  409. HEADER hd;
  410. _Static_assert (sizeof (hd) == 12, "DNS header size");
  411. if (length < sizeof (hd))
  412. FAIL_EXIT1 ("malformed DNS query: too short: %zu bytes", length);
  413. memcpy (&hd, buffer, sizeof (hd));
  414. if (ntohs (hd.qdcount) != 1)
  415. FAIL_EXIT1 ("malformed DNS query: wrong question count: %d",
  416. (int) ntohs (hd.qdcount));
  417. if (ntohs (hd.ancount) != 0)
  418. FAIL_EXIT1 ("malformed DNS query: wrong answer count: %d",
  419. (int) ntohs (hd.ancount));
  420. if (ntohs (hd.nscount) != 0)
  421. FAIL_EXIT1 ("malformed DNS query: wrong authority count: %d",
  422. (int) ntohs (hd.nscount));
  423. if (ntohs (hd.arcount) > 1)
  424. FAIL_EXIT1 ("malformed DNS query: wrong additional count: %d",
  425. (int) ntohs (hd.arcount));
  426. int ret = dn_expand (buffer, buffer + length, buffer + sizeof (hd),
  427. info->qname, sizeof (info->qname));
  428. if (ret < 0)
  429. FAIL_EXIT1 ("malformed DNS query: cannot uncompress QNAME");
  430. /* Obtain QTYPE and QCLASS. */
  431. size_t remaining = length - (12 + ret);
  432. struct
  433. {
  434. uint16_t qtype;
  435. uint16_t qclass;
  436. } qtype_qclass;
  437. if (remaining < sizeof (qtype_qclass))
  438. FAIL_EXIT1 ("malformed DNS query: "
  439. "query lacks QCLASS/QTYPE, QNAME: %s", info->qname);
  440. memcpy (&qtype_qclass, buffer + 12 + ret, sizeof (qtype_qclass));
  441. info->qclass = ntohs (qtype_qclass.qclass);
  442. info->qtype = ntohs (qtype_qclass.qtype);
  443. memset (&info->edns, 0, sizeof (info->edns));
  444. if (ntohs (hd.arcount) > 0)
  445. {
  446. /* Parse EDNS record. */
  447. struct __attribute__ ((packed, aligned (1)))
  448. {
  449. uint8_t root;
  450. uint16_t rtype;
  451. uint16_t payload;
  452. uint8_t edns_extended_rcode;
  453. uint8_t edns_version;
  454. uint16_t flags;
  455. uint16_t rdatalen;
  456. } rr;
  457. _Static_assert (sizeof (rr) == 11, "EDNS record size");
  458. if (remaining < 4 + sizeof (rr))
  459. FAIL_EXIT1 ("mailformed DNS query: no room for EDNS record");
  460. memcpy (&rr, buffer + 12 + ret + 4, sizeof (rr));
  461. if (rr.root != 0)
  462. FAIL_EXIT1 ("malformed DNS query: invalid OPT RNAME: %d\n", rr.root);
  463. if (rr.rtype != htons (41))
  464. FAIL_EXIT1 ("malformed DNS query: invalid OPT type: %d\n",
  465. ntohs (rr.rtype));
  466. info->edns.active = true;
  467. info->edns.extended_rcode = rr.edns_extended_rcode;
  468. info->edns.version = rr.edns_version;
  469. info->edns.flags = ntohs (rr.flags);
  470. info->edns.payload_size = ntohs (rr.payload);
  471. }
  472. }
  473. /* Main testing framework. */
  474. /* Per-server information. One struct is allocated for each test
  475. server. */
  476. struct resolv_test_server
  477. {
  478. /* Local address of the server. UDP and TCP use the same port. */
  479. struct sockaddr_in address;
  480. /* File descriptor of the UDP server, or -1 if this server is
  481. disabled. */
  482. int socket_udp;
  483. /* File descriptor of the TCP server, or -1 if this server is
  484. disabled. */
  485. int socket_tcp;
  486. /* Counter of the number of responses processed so far. */
  487. size_t response_number;
  488. /* Thread handles for the server threads (if not disabled in the
  489. configuration). */
  490. pthread_t thread_udp;
  491. pthread_t thread_tcp;
  492. };
  493. /* Main struct for keeping track of libresolv redirection and
  494. testing. */
  495. struct resolv_test
  496. {
  497. /* After initialization, any access to the struct must be performed
  498. while this lock is acquired. */
  499. pthread_mutex_t lock;
  500. /* Data for each test server. */
  501. struct resolv_test_server servers[resolv_max_test_servers];
  502. /* Used if config.single_thread_udp is true. */
  503. pthread_t thread_udp_single;
  504. struct resolv_redirect_config config;
  505. bool termination_requested;
  506. };
  507. /* Function implementing a server thread. */
  508. typedef void (*thread_callback) (struct resolv_test *, int server_index);
  509. /* Storage for thread-specific data, for passing to the
  510. thread_callback function. */
  511. struct thread_closure
  512. {
  513. struct resolv_test *obj; /* Current test object. */
  514. thread_callback callback; /* Function to call. */
  515. int server_index; /* Index of the implemented server. */
  516. };
  517. /* Wrap response_callback as a function which can be passed to
  518. pthread_create. */
  519. static void *
  520. thread_callback_wrapper (void *arg)
  521. {
  522. struct thread_closure *closure = arg;
  523. closure->callback (closure->obj, closure->server_index);
  524. free (closure);
  525. return NULL;
  526. }
  527. /* Start a server thread for the specified SERVER_INDEX, implemented
  528. by CALLBACK. */
  529. static pthread_t
  530. start_server_thread (struct resolv_test *obj, int server_index,
  531. thread_callback callback)
  532. {
  533. struct thread_closure *closure = xmalloc (sizeof (*closure));
  534. *closure = (struct thread_closure)
  535. {
  536. .obj = obj,
  537. .callback = callback,
  538. .server_index = server_index,
  539. };
  540. return xpthread_create (NULL, thread_callback_wrapper, closure);
  541. }
  542. /* Process one UDP query. Return false if a termination requested has
  543. been detected. */
  544. static bool
  545. server_thread_udp_process_one (struct resolv_test *obj, int server_index)
  546. {
  547. unsigned char query[512];
  548. struct sockaddr_storage peer;
  549. socklen_t peerlen = sizeof (peer);
  550. size_t length = xrecvfrom (obj->servers[server_index].socket_udp,
  551. query, sizeof (query), 0,
  552. (struct sockaddr *) &peer, &peerlen);
  553. /* Check for termination. */
  554. {
  555. bool termination_requested;
  556. xpthread_mutex_lock (&obj->lock);
  557. termination_requested = obj->termination_requested;
  558. xpthread_mutex_unlock (&obj->lock);
  559. if (termination_requested)
  560. return false;
  561. }
  562. struct query_info qinfo;
  563. parse_query (&qinfo, query, length);
  564. if (test_verbose > 0)
  565. {
  566. if (test_verbose > 1)
  567. printf ("info: UDP server %d: incoming query:"
  568. " %zd bytes, %s/%u/%u, tnxid=0x%02x%02x\n",
  569. server_index, length, qinfo.qname, qinfo.qclass, qinfo.qtype,
  570. query[0], query[1]);
  571. else
  572. printf ("info: UDP server %d: incoming query:"
  573. " %zd bytes, %s/%u/%u\n",
  574. server_index, length, qinfo.qname, qinfo.qclass, qinfo.qtype);
  575. }
  576. struct resolv_response_context ctx =
  577. {
  578. .query_buffer = query,
  579. .query_length = length,
  580. .server_index = server_index,
  581. .tcp = false,
  582. .edns = qinfo.edns,
  583. };
  584. struct resolv_response_builder *b = response_builder_allocate (query, length);
  585. obj->config.response_callback
  586. (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype);
  587. if (b->drop)
  588. {
  589. if (test_verbose)
  590. printf ("info: UDP server %d: dropping response to %s/%u/%u\n",
  591. server_index, qinfo.qname, qinfo.qclass, qinfo.qtype);
  592. }
  593. else
  594. {
  595. if (test_verbose)
  596. {
  597. if (b->offset >= 12)
  598. printf ("info: UDP server %d: sending response:"
  599. " %zu bytes, RCODE %d (for %s/%u/%u)\n",
  600. server_index, b->offset, b->buffer[3] & 0x0f,
  601. qinfo.qname, qinfo.qclass, qinfo.qtype);
  602. else
  603. printf ("info: UDP server %d: sending response: %zu bytes"
  604. " (for %s/%u/%u)\n",
  605. server_index, b->offset,
  606. qinfo.qname, qinfo.qclass, qinfo.qtype);
  607. if (b->truncate_bytes > 0)
  608. printf ("info: truncated by %u bytes\n", b->truncate_bytes);
  609. }
  610. size_t to_send = b->offset;
  611. if (to_send < b->truncate_bytes)
  612. to_send = 0;
  613. else
  614. to_send -= b->truncate_bytes;
  615. /* Ignore most errors here because the other end may have closed
  616. the socket. */
  617. if (sendto (obj->servers[server_index].socket_udp,
  618. b->buffer, to_send, 0,
  619. (struct sockaddr *) &peer, peerlen) < 0)
  620. TEST_VERIFY_EXIT (errno != EBADF);
  621. }
  622. response_builder_free (b);
  623. return true;
  624. }
  625. /* UDP thread_callback function. Variant for one thread per
  626. server. */
  627. static void
  628. server_thread_udp (struct resolv_test *obj, int server_index)
  629. {
  630. while (server_thread_udp_process_one (obj, server_index))
  631. ;
  632. }
  633. /* Single-threaded UDP processing function, for the single_thread_udp
  634. case. */
  635. static void *
  636. server_thread_udp_single (void *closure)
  637. {
  638. struct resolv_test *obj = closure;
  639. struct pollfd fds[resolv_max_test_servers];
  640. for (int server_index = 0; server_index < resolv_max_test_servers;
  641. ++server_index)
  642. if (obj->config.servers[server_index].disable_udp)
  643. fds[server_index] = (struct pollfd) {.fd = -1};
  644. else
  645. {
  646. fds[server_index] = (struct pollfd)
  647. {
  648. .fd = obj->servers[server_index].socket_udp,
  649. .events = POLLIN
  650. };
  651. /* Make the socket non-blocking. */
  652. int flags = fcntl (obj->servers[server_index].socket_udp, F_GETFL, 0);
  653. if (flags < 0)
  654. FAIL_EXIT1 ("fcntl (F_GETFL): %m");
  655. flags |= O_NONBLOCK;
  656. if (fcntl (obj->servers[server_index].socket_udp, F_SETFL, flags) < 0)
  657. FAIL_EXIT1 ("fcntl (F_SETFL): %m");
  658. }
  659. while (true)
  660. {
  661. xpoll (fds, resolv_max_test_servers, -1);
  662. for (int server_index = 0; server_index < resolv_max_test_servers;
  663. ++server_index)
  664. if (fds[server_index].revents != 0)
  665. {
  666. if (!server_thread_udp_process_one (obj, server_index))
  667. goto out;
  668. fds[server_index].revents = 0;
  669. }
  670. }
  671. out:
  672. return NULL;
  673. }
  674. /* Start the single UDP handler thread (for the single_thread_udp
  675. case). */
  676. static void
  677. start_server_thread_udp_single (struct resolv_test *obj)
  678. {
  679. obj->thread_udp_single
  680. = xpthread_create (NULL, server_thread_udp_single, obj);
  681. }
  682. /* Data describing a TCP client connect. */
  683. struct tcp_thread_closure
  684. {
  685. struct resolv_test *obj;
  686. int server_index;
  687. int client_socket;
  688. };
  689. /* Read a complete DNS query packet. If EOF_OK, an immediate
  690. end-of-file condition is acceptable. */
  691. static bool
  692. read_fully (int fd, void *buf, size_t len, bool eof_ok)
  693. {
  694. const void *const end = buf + len;
  695. while (buf < end)
  696. {
  697. ssize_t ret = read (fd, buf, end - buf);
  698. if (ret == 0)
  699. {
  700. if (!eof_ok)
  701. {
  702. support_record_failure ();
  703. printf ("error: unexpected EOF on TCP connection\n");
  704. }
  705. return false;
  706. }
  707. else if (ret < 0)
  708. {
  709. if (!eof_ok || errno != ECONNRESET)
  710. {
  711. support_record_failure ();
  712. printf ("error: TCP read: %m\n");
  713. }
  714. return false;
  715. }
  716. buf += ret;
  717. eof_ok = false;
  718. }
  719. return true;
  720. }
  721. /* Write an array of iovecs. Terminate the process on failure. */
  722. static void
  723. writev_fully (int fd, struct iovec *buffers, size_t count)
  724. {
  725. while (count > 0)
  726. {
  727. /* Skip zero-length write requests. */
  728. if (buffers->iov_len == 0)
  729. {
  730. ++buffers;
  731. --count;
  732. continue;
  733. }
  734. /* Try to rewrite the remaing buffers. */
  735. ssize_t ret = writev (fd, buffers, count);
  736. if (ret < 0)
  737. FAIL_EXIT1 ("writev: %m");
  738. if (ret == 0)
  739. FAIL_EXIT1 ("writev: invalid return value zero");
  740. /* Find the buffers that were successfully written. */
  741. while (ret > 0)
  742. {
  743. if (count == 0)
  744. FAIL_EXIT1 ("internal writev consistency failure");
  745. /* Current buffer was partially written. */
  746. if (buffers->iov_len > (size_t) ret)
  747. {
  748. buffers->iov_base += ret;
  749. buffers->iov_len -= ret;
  750. ret = 0;
  751. }
  752. else
  753. {
  754. ret -= buffers->iov_len;
  755. buffers->iov_len = 0;
  756. ++buffers;
  757. --count;
  758. }
  759. }
  760. }
  761. }
  762. /* Thread callback for handling a single established TCP connection to
  763. a client. */
  764. static void *
  765. server_thread_tcp_client (void *arg)
  766. {
  767. struct tcp_thread_closure *closure = arg;
  768. while (true)
  769. {
  770. /* Read packet length. */
  771. uint16_t query_length;
  772. if (!read_fully (closure->client_socket,
  773. &query_length, sizeof (query_length), true))
  774. break;
  775. query_length = ntohs (query_length);
  776. /* Read the packet. */
  777. unsigned char *query_buffer = xmalloc (query_length);
  778. read_fully (closure->client_socket, query_buffer, query_length, false);
  779. struct query_info qinfo;
  780. parse_query (&qinfo, query_buffer, query_length);
  781. if (test_verbose > 0)
  782. {
  783. if (test_verbose > 1)
  784. printf ("info: UDP server %d: incoming query:"
  785. " %d bytes, %s/%u/%u, tnxid=0x%02x%02x\n",
  786. closure->server_index, query_length,
  787. qinfo.qname, qinfo.qclass, qinfo.qtype,
  788. query_buffer[0], query_buffer[1]);
  789. else
  790. printf ("info: TCP server %d: incoming query:"
  791. " %u bytes, %s/%u/%u\n",
  792. closure->server_index, query_length,
  793. qinfo.qname, qinfo.qclass, qinfo.qtype);
  794. }
  795. struct resolv_response_context ctx =
  796. {
  797. .query_buffer = query_buffer,
  798. .query_length = query_length,
  799. .server_index = closure->server_index,
  800. .tcp = true,
  801. .edns = qinfo.edns,
  802. };
  803. struct resolv_response_builder *b = response_builder_allocate
  804. (query_buffer, query_length);
  805. closure->obj->config.response_callback
  806. (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype);
  807. if (b->drop)
  808. {
  809. if (test_verbose)
  810. printf ("info: TCP server %d: dropping response to %s/%u/%u\n",
  811. closure->server_index,
  812. qinfo.qname, qinfo.qclass, qinfo.qtype);
  813. }
  814. else
  815. {
  816. if (test_verbose)
  817. printf ("info: TCP server %d: sending response: %zu bytes"
  818. " (for %s/%u/%u)\n",
  819. closure->server_index, b->offset,
  820. qinfo.qname, qinfo.qclass, qinfo.qtype);
  821. uint16_t length = htons (b->offset);
  822. size_t to_send = b->offset;
  823. if (to_send < b->truncate_bytes)
  824. to_send = 0;
  825. else
  826. to_send -= b->truncate_bytes;
  827. struct iovec buffers[2] =
  828. {
  829. {&length, sizeof (length)},
  830. {b->buffer, to_send}
  831. };
  832. writev_fully (closure->client_socket, buffers, 2);
  833. }
  834. bool close_flag = b->close;
  835. response_builder_free (b);
  836. free (query_buffer);
  837. if (close_flag)
  838. break;
  839. }
  840. xclose (closure->client_socket);
  841. free (closure);
  842. return NULL;
  843. }
  844. /* thread_callback for the TCP case. Accept connections and create a
  845. new thread for each client. */
  846. static void
  847. server_thread_tcp (struct resolv_test *obj, int server_index)
  848. {
  849. while (true)
  850. {
  851. /* Get the client conenction. */
  852. int client_socket = xaccept
  853. (obj->servers[server_index].socket_tcp, NULL, NULL);
  854. /* Check for termination. */
  855. xpthread_mutex_lock (&obj->lock);
  856. if (obj->termination_requested)
  857. {
  858. xpthread_mutex_unlock (&obj->lock);
  859. xclose (client_socket);
  860. break;
  861. }
  862. xpthread_mutex_unlock (&obj->lock);
  863. /* Spawn a new thread for handling this connection. */
  864. struct tcp_thread_closure *closure = xmalloc (sizeof (*closure));
  865. *closure = (struct tcp_thread_closure)
  866. {
  867. .obj = obj,
  868. .server_index = server_index,
  869. .client_socket = client_socket,
  870. };
  871. pthread_t thr
  872. = xpthread_create (NULL, server_thread_tcp_client, closure);
  873. /* TODO: We should keep track of this thread so that we can
  874. block in resolv_test_end until it has exited. */
  875. xpthread_detach (thr);
  876. }
  877. }
  878. /* Create UDP and TCP server sockets. */
  879. static void
  880. make_server_sockets (struct resolv_test_server *server)
  881. {
  882. while (true)
  883. {
  884. server->socket_udp = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  885. server->socket_tcp = xsocket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  886. /* Pick the address for the UDP socket. */
  887. server->address = (struct sockaddr_in)
  888. {
  889. .sin_family = AF_INET,
  890. .sin_addr = {.s_addr = htonl (INADDR_LOOPBACK)}
  891. };
  892. xbind (server->socket_udp,
  893. (struct sockaddr *)&server->address, sizeof (server->address));
  894. /* Retrieve the address. */
  895. socklen_t addrlen = sizeof (server->address);
  896. xgetsockname (server->socket_udp,
  897. (struct sockaddr *)&server->address, &addrlen);
  898. /* Bind the TCP socket to the same address. */
  899. {
  900. int on = 1;
  901. xsetsockopt (server->socket_tcp, SOL_SOCKET, SO_REUSEADDR,
  902. &on, sizeof (on));
  903. }
  904. if (bind (server->socket_tcp,
  905. (struct sockaddr *)&server->address,
  906. sizeof (server->address)) != 0)
  907. {
  908. /* Port collision. The UDP bind succeeded, but the TCP BIND
  909. failed. We assume here that the kernel will pick the
  910. next local UDP address randomly. */
  911. if (errno == EADDRINUSE)
  912. {
  913. xclose (server->socket_udp);
  914. xclose (server->socket_tcp);
  915. continue;
  916. }
  917. FAIL_EXIT1 ("TCP bind: %m");
  918. }
  919. xlisten (server->socket_tcp, 5);
  920. break;
  921. }
  922. }
  923. /* Like make_server_sockets, but the caller supplies the address to
  924. use. */
  925. static void
  926. make_server_sockets_for_address (struct resolv_test_server *server,
  927. const struct sockaddr *addr)
  928. {
  929. server->socket_udp = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  930. server->socket_tcp = xsocket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  931. if (addr->sa_family == AF_INET)
  932. server->address = *(const struct sockaddr_in *) addr;
  933. else
  934. /* We cannot store the server address in the socket. This should
  935. not matter if disable_redirect is used. */
  936. server->address = (struct sockaddr_in) { .sin_family = 0, };
  937. xbind (server->socket_udp,
  938. (struct sockaddr *)&server->address, sizeof (server->address));
  939. xbind (server->socket_tcp,
  940. (struct sockaddr *)&server->address, sizeof (server->address));
  941. xlisten (server->socket_tcp, 5);
  942. }
  943. /* One-time initialization of NSS. */
  944. static void
  945. resolv_redirect_once (void)
  946. {
  947. /* Only use nss_dns. */
  948. __nss_configure_lookup ("hosts", "dns");
  949. __nss_configure_lookup ("networks", "dns");
  950. /* Enter a network namespace for isolation and firewall state
  951. cleanup. The tests will still work if these steps fail, but they
  952. may be less reliable. */
  953. support_become_root ();
  954. support_enter_network_namespace ();
  955. }
  956. pthread_once_t resolv_redirect_once_var = PTHREAD_ONCE_INIT;
  957. void
  958. resolv_test_init (void)
  959. {
  960. /* Perform one-time initialization of NSS. */
  961. xpthread_once (&resolv_redirect_once_var, resolv_redirect_once);
  962. }
  963. /* Copy the search path from CONFIG.search to the _res object. */
  964. static void
  965. set_search_path (struct resolv_redirect_config config)
  966. {
  967. memset (_res.defdname, 0, sizeof (_res.defdname));
  968. memset (_res.dnsrch, 0, sizeof (_res.dnsrch));
  969. char *current = _res.defdname;
  970. char *end = current + sizeof (_res.defdname);
  971. for (unsigned int i = 0;
  972. i < sizeof (config.search) / sizeof (config.search[0]); ++i)
  973. {
  974. if (config.search[i] == NULL)
  975. continue;
  976. size_t length = strlen (config.search[i]) + 1;
  977. size_t remaining = end - current;
  978. TEST_VERIFY_EXIT (length <= remaining);
  979. memcpy (current, config.search[i], length);
  980. _res.dnsrch[i] = current;
  981. current += length;
  982. }
  983. }
  984. struct resolv_test *
  985. resolv_test_start (struct resolv_redirect_config config)
  986. {
  987. /* Apply configuration defaults. */
  988. if (config.nscount == 0)
  989. config.nscount = resolv_max_test_servers;
  990. struct resolv_test *obj = xmalloc (sizeof (*obj));
  991. *obj = (struct resolv_test) {
  992. .config = config,
  993. .lock = PTHREAD_MUTEX_INITIALIZER,
  994. };
  995. if (!config.disable_redirect)
  996. resolv_test_init ();
  997. /* Create all the servers, to reserve the necessary ports. */
  998. for (int server_index = 0; server_index < config.nscount; ++server_index)
  999. if (config.disable_redirect && config.server_address_overrides != NULL)
  1000. make_server_sockets_for_address
  1001. (obj->servers + server_index,
  1002. config.server_address_overrides[server_index]);
  1003. else
  1004. make_server_sockets (obj->servers + server_index);
  1005. /* Start server threads. Disable the server ports, as
  1006. requested. */
  1007. for (int server_index = 0; server_index < config.nscount; ++server_index)
  1008. {
  1009. struct resolv_test_server *server = obj->servers + server_index;
  1010. if (config.servers[server_index].disable_udp)
  1011. {
  1012. xclose (server->socket_udp);
  1013. server->socket_udp = -1;
  1014. }
  1015. else if (!config.single_thread_udp)
  1016. server->thread_udp = start_server_thread (obj, server_index,
  1017. server_thread_udp);
  1018. if (config.servers[server_index].disable_tcp)
  1019. {
  1020. xclose (server->socket_tcp);
  1021. server->socket_tcp = -1;
  1022. }
  1023. else
  1024. server->thread_tcp = start_server_thread (obj, server_index,
  1025. server_thread_tcp);
  1026. }
  1027. if (config.single_thread_udp)
  1028. start_server_thread_udp_single (obj);
  1029. if (config.disable_redirect)
  1030. return obj;
  1031. int timeout = 1;
  1032. /* Initialize libresolv. */
  1033. TEST_VERIFY_EXIT (res_init () == 0);
  1034. /* Disable IPv6 name server addresses. The code below only
  1035. overrides the IPv4 addresses. */
  1036. __res_iclose (&_res, true);
  1037. _res._u._ext.nscount = 0;
  1038. /* Redirect queries to the server socket. */
  1039. if (test_verbose)
  1040. {
  1041. printf ("info: old timeout value: %d\n", _res.retrans);
  1042. printf ("info: old retry attempt value: %d\n", _res.retry);
  1043. printf ("info: old _res.options: 0x%lx\n", _res.options);
  1044. printf ("info: old _res.nscount value: %d\n", _res.nscount);
  1045. printf ("info: old _res.ndots value: %d\n", _res.ndots);
  1046. }
  1047. _res.retrans = timeout;
  1048. _res.retry = 4;
  1049. _res.nscount = config.nscount;
  1050. _res.options = RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
  1051. _res.ndots = 1;
  1052. if (test_verbose)
  1053. {
  1054. printf ("info: new timeout value: %d\n", _res.retrans);
  1055. printf ("info: new retry attempt value: %d\n", _res.retry);
  1056. printf ("info: new _res.options: 0x%lx\n", _res.options);
  1057. printf ("info: new _res.nscount value: %d\n", _res.nscount);
  1058. printf ("info: new _res.ndots value: %d\n", _res.ndots);
  1059. }
  1060. for (int server_index = 0; server_index < config.nscount; ++server_index)
  1061. {
  1062. TEST_VERIFY_EXIT (obj->servers[server_index].address.sin_port != 0);
  1063. _res.nsaddr_list[server_index] = obj->servers[server_index].address;
  1064. if (test_verbose)
  1065. {
  1066. char buf[256];
  1067. TEST_VERIFY_EXIT
  1068. (inet_ntop (AF_INET, &obj->servers[server_index].address.sin_addr,
  1069. buf, sizeof (buf)) != NULL);
  1070. printf ("info: server %d: %s/%u\n",
  1071. server_index, buf,
  1072. htons (obj->servers[server_index].address.sin_port));
  1073. }
  1074. }
  1075. set_search_path (config);
  1076. return obj;
  1077. }
  1078. void
  1079. resolv_test_end (struct resolv_test *obj)
  1080. {
  1081. res_close ();
  1082. xpthread_mutex_lock (&obj->lock);
  1083. obj->termination_requested = true;
  1084. xpthread_mutex_unlock (&obj->lock);
  1085. /* Send trigger packets to unblock the server threads. */
  1086. for (int server_index = 0; server_index < obj->config.nscount;
  1087. ++server_index)
  1088. {
  1089. if (!obj->config.servers[server_index].disable_udp)
  1090. {
  1091. int sock = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  1092. xsendto (sock, "", 1, 0,
  1093. (struct sockaddr *) &obj->servers[server_index].address,
  1094. sizeof (obj->servers[server_index].address));
  1095. xclose (sock);
  1096. }
  1097. if (!obj->config.servers[server_index].disable_tcp)
  1098. {
  1099. int sock = xsocket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  1100. xconnect (sock,
  1101. (struct sockaddr *) &obj->servers[server_index].address,
  1102. sizeof (obj->servers[server_index].address));
  1103. xclose (sock);
  1104. }
  1105. }
  1106. if (obj->config.single_thread_udp)
  1107. xpthread_join (obj->thread_udp_single);
  1108. /* Wait for the server threads to terminate. */
  1109. for (int server_index = 0; server_index < obj->config.nscount;
  1110. ++server_index)
  1111. {
  1112. if (!obj->config.servers[server_index].disable_udp)
  1113. {
  1114. if (!obj->config.single_thread_udp)
  1115. xpthread_join (obj->servers[server_index].thread_udp);
  1116. xclose (obj->servers[server_index].socket_udp);
  1117. }
  1118. if (!obj->config.servers[server_index].disable_tcp)
  1119. {
  1120. xpthread_join (obj->servers[server_index].thread_tcp);
  1121. xclose (obj->servers[server_index].socket_tcp);
  1122. }
  1123. }
  1124. free (obj);
  1125. }