async-dns.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include "private-lib-core.h"
  25. #include "private-lib-async-dns.h"
  26. static const uint32_t botable[] = { 500, 1000, 1250, 5000
  27. /* in case everything just dog slow */ };
  28. static const lws_retry_bo_t retry_policy = {
  29. botable, LWS_ARRAY_SIZE(botable), LWS_ARRAY_SIZE(botable),
  30. /* don't conceal after the last table entry */ 0, 0, 20 };
  31. void
  32. lws_adns_q_destroy(lws_adns_q_t *q)
  33. {
  34. lws_dll2_remove(&q->sul.list);
  35. lws_dll2_remove(&q->list);
  36. lws_free(q);
  37. }
  38. lws_adns_q_t *
  39. lws_adns_get_query(lws_async_dns_t *dns, adns_query_type_t qtype,
  40. lws_dll2_owner_t *owner, uint16_t tid, const char *name)
  41. {
  42. lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
  43. lws_dll2_get_head(owner)) {
  44. lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list);
  45. if (!name && (tid & 0xfffe) == (q->tid & 0xfffe))
  46. return q;
  47. if (name && q->qtype == ((tid & 1) ? LWS_ADNS_RECORD_AAAA :
  48. LWS_ADNS_RECORD_A) &&
  49. !strcasecmp(name, (const char *)&q[1])) {
  50. if (owner == &dns->cached) {
  51. /* Keep sorted by LRU: move to the head */
  52. lws_dll2_remove(&q->list);
  53. lws_dll2_add_head(&q->list, &dns->cached);
  54. }
  55. return q;
  56. }
  57. } lws_end_foreach_dll_safe(d, d1);
  58. return NULL;
  59. }
  60. void
  61. lws_async_dns_drop_server(struct lws_context *context)
  62. {
  63. context->async_dns.dns_server_set = 0;
  64. lws_set_timeout(context->async_dns.wsi, 1, LWS_TO_KILL_ASYNC);
  65. context->async_dns.wsi = NULL;
  66. }
  67. int
  68. lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c)
  69. {
  70. lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
  71. lws_dll2_get_head(&q->wsi_adns)) {
  72. struct lws *w = lws_container_of(d, struct lws, adns);
  73. lws_dll2_remove(d);
  74. if (c && c->results) {
  75. lwsl_debug("%s: q: %p, c: %p, refcount %d -> %d\n",
  76. __func__, q, c, c->refcount, c->refcount + 1);
  77. c->refcount++;
  78. }
  79. w->adns_cb(w, (const char *)&q[1], c ? c->results : NULL, 0,
  80. q->opaque);
  81. } lws_end_foreach_dll_safe(d, d1);
  82. if (q->standalone_cb) {
  83. if (c && c->results) {
  84. lwsl_debug("%s: q: %p, c: %p, refcount %d -> %d\n",
  85. __func__, q, c, c->refcount, c->refcount + 1);
  86. c->refcount++;
  87. }
  88. q->standalone_cb(NULL, (const char *)&q[1],
  89. c ? c->results : NULL, 0, q->opaque);
  90. }
  91. return 0;
  92. }
  93. static void
  94. lws_async_dns_sul_cb_retry(struct lws_sorted_usec_list *sul)
  95. {
  96. lws_adns_q_t *q = lws_container_of(sul, lws_adns_q_t, sul);
  97. // lwsl_notice("%s\n", __func__);
  98. lws_callback_on_writable(q->dns->wsi);
  99. }
  100. static void
  101. lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q)
  102. {
  103. uint8_t pkt[LWS_PRE + DNS_PACKET_LEN], *e = &pkt[sizeof(pkt)], *p, *pl;
  104. int m, n, which;
  105. const char *name;
  106. // lwsl_notice("%s: %p\n", __func__, q);
  107. /*
  108. * UDP is not reliable, it can be locally dropped, or dropped
  109. * by any intermediary or the remote peer. So even though we
  110. * will do the write in a moment, we schedule another request
  111. * for rewrite according to the wsi retry policy.
  112. *
  113. * If the result came before, we'll cancel it as part of the
  114. * wsi close.
  115. *
  116. * If we have already reached the end of our concealed retries
  117. * in the policy, just close without another write.
  118. */
  119. if (lws_dll2_is_detached(&q->sul.list) &&
  120. lws_retry_sul_schedule_retry_wsi(wsi, &q->sul,
  121. lws_async_dns_sul_cb_retry, &q->retry)) {
  122. /* we have reached the end of our concealed retries */
  123. lwsl_notice("%s: failing query\n", __func__);
  124. /*
  125. * our policy is to force reloading the dns server info
  126. * if our connection ever timed out, in case it or the
  127. * routing state changed
  128. */
  129. lws_async_dns_drop_server(q->context);
  130. goto qfail;
  131. }
  132. name = (const char *)&q[1];
  133. p = &pkt[LWS_PRE];
  134. memset(p, 0, DHO_SIZEOF);
  135. #if defined(LWS_WITH_IPV6)
  136. if (!q->responded) {
  137. /* must pick between ipv6 and ipv4 */
  138. which = q->sent[0] >= q->sent[1];
  139. q->sent[which]++;
  140. q->asked = 3; /* want results for 4 & 6 before done */
  141. } else
  142. which = q->responded & 1;
  143. #else
  144. which = 0;
  145. q->asked = 1;
  146. #endif
  147. /* we hack b0 of the tid to be 0 = A, 1 = AAAA */
  148. lws_ser_wu16be(&p[DHO_TID],
  149. #if defined(LWS_WITH_IPV6)
  150. which ? q->tid | 1 :
  151. #endif
  152. q->tid);
  153. lws_ser_wu16be(&p[DHO_FLAGS], (1 << 8));
  154. lws_ser_wu16be(&p[DHO_NQUERIES], 1);
  155. p += DHO_SIZEOF;
  156. /* start of label-formatted qname */
  157. pl = p++;
  158. do {
  159. if (*name == '.' || !*name) {
  160. *pl = lws_ptr_diff(p, pl + 1);
  161. pl = p;
  162. *p++ = 0; /* also serves as terminal length */
  163. if (!*name++)
  164. break;
  165. } else
  166. *p++ = *name++;
  167. } while (p + 6 < e);
  168. if (p + 6 >= e) {
  169. assert(0);
  170. lwsl_err("%s: name too big\n", __func__);
  171. goto qfail;
  172. }
  173. lws_ser_wu16be(p, which ? LWS_ADNS_RECORD_AAAA :
  174. LWS_ADNS_RECORD_A);
  175. p += 2;
  176. lws_ser_wu16be(p, 1); /* IN class */
  177. p += 2;
  178. assert(p < pkt + sizeof(pkt) - LWS_PRE);
  179. n = lws_ptr_diff(p, pkt + LWS_PRE);
  180. m = lws_write(wsi, pkt + LWS_PRE, n, 0);
  181. if (m != n) {
  182. lwsl_notice("%s: dns write failed %d %d errno %d\n", __func__,
  183. m, n, errno);
  184. goto qfail;
  185. }
  186. #if defined(LWS_WITH_IPV6)
  187. if (!q->responded && q->sent[0] != q->sent[1])
  188. lws_callback_on_writable(wsi);
  189. #endif
  190. /* if we did anything, check one more time */
  191. lws_callback_on_writable(wsi);
  192. return;
  193. qfail:
  194. lwsl_warn("%s: failing query doing NULL completion\n", __func__);
  195. /*
  196. * in ipv6 case, we made a cache entry for the first response but
  197. * evidently the second response didn't come in time, purge the
  198. * incomplete cache entry
  199. */
  200. if (q->firstcache)
  201. lws_adns_cache_destroy(q->firstcache);
  202. lws_async_dns_complete(q, NULL);
  203. lws_adns_q_destroy(q);
  204. }
  205. static int
  206. callback_async_dns(struct lws *wsi, enum lws_callback_reasons reason,
  207. void *user, void *in, size_t len)
  208. {
  209. struct lws_async_dns *dns = &(lws_get_context(wsi)->async_dns);
  210. switch (reason) {
  211. /* callbacks related to raw socket descriptor */
  212. case LWS_CALLBACK_RAW_ADOPT:
  213. // lwsl_user("LWS_CALLBACK_RAW_ADOPT\n");
  214. break;
  215. case LWS_CALLBACK_RAW_CLOSE:
  216. // lwsl_user("LWS_CALLBACK_RAW_CLOSE\n");
  217. break;
  218. case LWS_CALLBACK_RAW_RX:
  219. // lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len);
  220. // lwsl_hexdump_level(LLL_NOTICE, in, len);
  221. lws_adns_parse_udp(dns, in, len);
  222. break;
  223. case LWS_CALLBACK_RAW_WRITEABLE:
  224. // lwsl_notice("%s: WRITABLE\n", __func__);
  225. lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
  226. dns->waiting.head) {
  227. lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t,
  228. list);
  229. if (lws_dll2_is_detached(&q->sul.list) &&
  230. (!q->asked || q->responded != q->asked))
  231. lws_async_dns_writeable(wsi, q);
  232. } lws_end_foreach_dll_safe(d, d1);
  233. break;
  234. default:
  235. break;
  236. }
  237. return 0;
  238. }
  239. struct lws_protocols lws_async_dns_protocol = {
  240. "lws-async-dns", callback_async_dns, 0, 0
  241. };
  242. int
  243. lws_async_dns_init(struct lws_context *context)
  244. {
  245. lws_async_dns_t *dns = &context->async_dns;
  246. char ads[48];
  247. int n;
  248. if (!context->vhost_list) { /* coverity... system vhost always present */
  249. lwsl_err("%s: no system vhost\n", __func__);
  250. return 1;
  251. }
  252. memset(&dns->sa46, 0, sizeof(dns->sa46));
  253. #if defined(LWS_WITH_SYS_DHCP_CLIENT)
  254. if (lws_dhcpc_status(context, &dns->sa46))
  255. goto ok;
  256. #endif
  257. n = lws_plat_asyncdns_init(context, &dns->sa46);
  258. if (n < 0) {
  259. lwsl_warn("%s: no valid dns server, retry\n", __func__);
  260. return 1;
  261. }
  262. if (n != LADNS_CONF_SERVER_CHANGED)
  263. return 0;
  264. #if defined(LWS_WITH_SYS_DHCP_CLIENT)
  265. ok:
  266. #endif
  267. dns->sa46.sa4.sin_port = htons(53);
  268. lws_write_numeric_address((uint8_t *)&dns->sa46.sa4.sin_addr.s_addr, 4,
  269. ads, sizeof(ads));
  270. context->async_dns.wsi = lws_create_adopt_udp(context->vhost_list, ads,
  271. 53, 0, lws_async_dns_protocol.name, NULL,
  272. NULL, NULL, &retry_policy);
  273. if (!dns->wsi) {
  274. lwsl_err("%s: foreign socket adoption failed\n", __func__);
  275. return 1;
  276. }
  277. dns->dns_server_set = 1;
  278. return 0;
  279. }
  280. lws_adns_cache_t *
  281. lws_adns_get_cache(lws_async_dns_t *dns, const char *name)
  282. {
  283. lws_adns_cache_t *c;
  284. const char *cn;
  285. lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
  286. lws_dll2_get_head(&dns->cached)) {
  287. c = lws_container_of(d, lws_adns_cache_t, list);
  288. cn = (const char *)&c[1];
  289. if (name && !c->incomplete && !strcasecmp(name, cn)) {
  290. /* Keep sorted by LRU: move to the head */
  291. lws_dll2_remove(&c->list);
  292. lws_dll2_add_head(&c->list, &dns->cached);
  293. return c;
  294. }
  295. } lws_end_foreach_dll_safe(d, d1);
  296. return NULL;
  297. }
  298. void
  299. lws_adns_cache_destroy(lws_adns_cache_t *c)
  300. {
  301. lws_dll2_remove(&c->sul.list);
  302. lws_dll2_remove(&c->list);
  303. if (c->chain)
  304. lws_free(c->chain);
  305. lws_free(c);
  306. }
  307. static int
  308. cache_clean(struct lws_dll2 *d, void *user)
  309. {
  310. lws_adns_cache_destroy(lws_container_of(d, lws_adns_cache_t, list));
  311. return 0;
  312. }
  313. void
  314. sul_cb_expire(struct lws_sorted_usec_list *sul)
  315. {
  316. lws_adns_cache_t *c = lws_container_of(sul, lws_adns_cache_t, sul);
  317. lws_adns_cache_destroy(c);
  318. }
  319. void
  320. lws_async_dns_freeaddrinfo(const struct addrinfo **pai)
  321. {
  322. lws_adns_cache_t *c;
  323. if (!*pai)
  324. return;
  325. /*
  326. * First query may have been empty... if second has something, we
  327. * fixed up the first result to point to second... but it means
  328. * looking backwards from ai, which is c->result, which is the second
  329. * packet's results, doesn't get us to the firstcache pointer.
  330. *
  331. * Adjust c to the firstcache in this case.
  332. */
  333. c = &((lws_adns_cache_t *)(*pai))[-1];
  334. if (c->firstcache)
  335. c = c->firstcache;
  336. lwsl_debug("%s: c %p, %s, refcount %d -> %d\n", __func__, c,
  337. (c->results && c->results->ai_canonname) ?
  338. c->results->ai_canonname : "none",
  339. c->refcount, c->refcount - 1);
  340. assert(c->refcount > 0);
  341. c->refcount--;
  342. *pai = NULL;
  343. }
  344. void
  345. lws_async_dns_trim_cache(lws_async_dns_t *dns)
  346. {
  347. lws_adns_cache_t *c1;
  348. if (dns->cached.count + 1< MAX_CACHE_ENTRIES)
  349. return;
  350. c1 = lws_container_of(lws_dll2_get_tail(&dns->cached),
  351. lws_adns_cache_t, list);
  352. if (c1->refcount)
  353. lwsl_notice("%s: wsi %p: refcount %d on purge\n",
  354. __func__, c1, c1->refcount);
  355. else
  356. lws_adns_cache_destroy(c1);
  357. }
  358. static int
  359. clean(struct lws_dll2 *d, void *user)
  360. {
  361. lws_adns_q_destroy(lws_container_of(d, lws_adns_q_t, list));
  362. return 0;
  363. }
  364. void
  365. lws_async_dns_deinit(lws_async_dns_t *dns)
  366. {
  367. lws_dll2_foreach_safe(&dns->waiting, NULL, clean);
  368. lws_dll2_foreach_safe(&dns->cached, NULL, cache_clean);
  369. }
  370. static int
  371. cancel(struct lws_dll2 *d, void *user)
  372. {
  373. lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list);
  374. lws_start_foreach_dll_safe(struct lws_dll2 *, d3, d4,
  375. lws_dll2_get_head(&q->wsi_adns)) {
  376. struct lws *w = lws_container_of(d3, struct lws, adns);
  377. if (user == w) {
  378. lws_dll2_remove(d3);
  379. if (!q->wsi_adns.count)
  380. lws_adns_q_destroy(q);
  381. return 1;
  382. }
  383. } lws_end_foreach_dll_safe(d3, d4);
  384. return 0;
  385. }
  386. void
  387. lws_async_dns_cancel(struct lws *wsi)
  388. {
  389. lws_async_dns_t *dns = &wsi->a.context->async_dns;
  390. lws_dll2_foreach_safe(&dns->waiting, wsi, cancel);
  391. }
  392. static int
  393. check_tid(struct lws_dll2 *d, void *user)
  394. {
  395. lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list);
  396. return q->tid == (uint16_t)(intptr_t)user;
  397. }
  398. int
  399. lws_async_dns_get_new_tid(struct lws_context *context, lws_adns_q_t *q)
  400. {
  401. lws_async_dns_t *dns = &context->async_dns;
  402. int budget = 10;
  403. /*
  404. * Make the TID unpredictable, but must be unique amongst ongoing ones
  405. */
  406. do {
  407. uint16_t tid;
  408. if (lws_get_random(context, &tid, 2) != 2)
  409. return -1;
  410. if (lws_dll2_foreach_safe(&dns->waiting,
  411. (void *)(intptr_t)tid, check_tid))
  412. continue;
  413. q->tid = tid;
  414. return 0;
  415. } while (budget--);
  416. lwsl_err("%s: unable to get unique tid\n", __func__);
  417. return -1;
  418. }
  419. struct temp_q {
  420. lws_adns_q_t tq;
  421. char name[48];
  422. };
  423. lws_async_dns_retcode_t
  424. lws_async_dns_query(struct lws_context *context, int tsi, const char *name,
  425. adns_query_type_t qtype, lws_async_dns_cb_t cb,
  426. struct lws *wsi, void *opaque)
  427. {
  428. lws_async_dns_t *dns = &context->async_dns;
  429. size_t nlen = strlen(name);
  430. lws_sockaddr46 *sa46;
  431. lws_adns_cache_t *c;
  432. struct addrinfo *ai;
  433. struct temp_q tmq;
  434. lws_adns_q_t *q;
  435. uint8_t ads[16];
  436. char *p;
  437. int m;
  438. #if !defined(LWS_WITH_IPV6)
  439. if (qtype == LWS_ADNS_RECORD_AAAA) {
  440. lwsl_err("%s: ipv6 not enabled\n", __func__);
  441. goto failed;
  442. }
  443. #endif
  444. if (nlen >= DNS_MAX - 1)
  445. goto failed;
  446. /*
  447. * we magically know 'localhost' and 'localhost6' if IPv6, this is a
  448. * sort of canned /etc/hosts
  449. */
  450. if (!strcmp(name, "localhost"))
  451. name = "127.0.0.1";
  452. #if defined(LWS_WITH_IPV6)
  453. if (!strcmp(name, "localhost6"))
  454. name = "::1";
  455. #endif
  456. if (wsi) {
  457. if (!lws_dll2_is_detached(&wsi->adns)) {
  458. lwsl_err("%s: wsi %p already bound to query %p\n",
  459. __func__, wsi, wsi->adns.owner);
  460. goto failed;
  461. }
  462. wsi->adns_cb = cb;
  463. }
  464. /* there's a done, cached query we can just reuse? */
  465. c = lws_adns_get_cache(dns, name);
  466. if (c) {
  467. lwsl_err("%s: using cached, c->results %p\n", __func__, c->results);
  468. m = c->results ? LADNS_RET_FOUND : LADNS_RET_FAILED;
  469. if (c->results)
  470. c->refcount++;
  471. cb(wsi, name, c->results, m, opaque);
  472. return m;
  473. }
  474. /*
  475. * It's a 1.2.3.4 type IP address already? We don't need a dns
  476. * server set up to be able to create an addrinfo result for that.
  477. *
  478. * Create it as a cached object so it follows the refcount lifecycle
  479. * of any other result
  480. */
  481. m = lws_parse_numeric_address(name, ads, sizeof(ads));
  482. if (m == 4
  483. #if defined(LWS_WITH_IPV6)
  484. || m == 16
  485. #endif
  486. ) {
  487. lws_async_dns_trim_cache(dns);
  488. c = lws_zalloc(sizeof(lws_adns_cache_t) +
  489. sizeof(struct addrinfo) +
  490. sizeof(lws_sockaddr46) + nlen + 1, "adns-numip");
  491. if (!c)
  492. goto failed;
  493. ai = (struct addrinfo *)&c[1];
  494. sa46 = (lws_sockaddr46 *)&ai[1];
  495. ai->ai_socktype = SOCK_STREAM;
  496. memcpy(&sa46[1], name, nlen + 1);
  497. ai->ai_canonname = (char *)&sa46[1];
  498. c->results = ai;
  499. memset(&tmq.tq, 0, sizeof(tmq.tq));
  500. tmq.tq.opaque = opaque;
  501. if (wsi) {
  502. wsi->adns_cb = cb;
  503. lws_dll2_add_head(&wsi->adns, &tmq.tq.wsi_adns);
  504. } else
  505. tmq.tq.standalone_cb = cb;
  506. lws_strncpy(tmq.name, name, sizeof(tmq.name));
  507. lws_dll2_add_head(&c->list, &dns->cached);
  508. lws_sul_schedule(context, 0, &c->sul, sul_cb_expire,
  509. lws_now_usecs() + (3600ll * LWS_US_PER_SEC));
  510. }
  511. if (m == 4) {
  512. ai->ai_family = sa46->sa4.sin_family = AF_INET;
  513. ai->ai_addrlen = sizeof(sa46->sa4);
  514. ai->ai_addr = (struct sockaddr *)&sa46->sa4;
  515. memcpy(&sa46->sa4.sin_addr, ads, m);
  516. lws_async_dns_complete(&tmq.tq, c);
  517. return LADNS_RET_FOUND;
  518. }
  519. #if defined(LWS_WITH_IPV6)
  520. if (m == 16) {
  521. ai->ai_family = sa46->sa6.sin6_family = AF_INET6;
  522. ai->ai_addrlen = sizeof(sa46->sa6);
  523. ai->ai_addr = (struct sockaddr *)&sa46->sa6;
  524. memcpy(&sa46->sa6.sin6_addr, ads, m);
  525. lws_async_dns_complete(&tmq.tq, c);
  526. return LADNS_RET_FOUND;
  527. }
  528. #endif
  529. /*
  530. * to try anything else we need a remote server configured...
  531. */
  532. if (!context->async_dns.dns_server_set &&
  533. lws_async_dns_init(context)) {
  534. lwsl_notice("%s: init failed\n", __func__);
  535. goto failed;
  536. }
  537. /* there's an ongoing query we can share the result of */
  538. q = lws_adns_get_query(dns, qtype, &dns->waiting, 0, name);
  539. if (q) {
  540. lwsl_debug("%s: dns piggybacking: %d:%s\n", __func__,
  541. qtype, name);
  542. if (wsi)
  543. lws_dll2_add_head(&wsi->adns, &q->wsi_adns);
  544. return LADNS_RET_CONTINUING;
  545. }
  546. /*
  547. * Allocate new query / queries... this is a bit complicated because
  548. * multiple queries in one packet are not supported peoperly in DNS
  549. * itself, and there's no reliable other way to get both ipv6 and ipv4
  550. * (AAAA and A) responses in one hit.
  551. *
  552. * If we don't support ipv6, it's simple, we just ask for A and that's
  553. * it. But if we do support ipv6, we need to ask twice, once for A
  554. * and in a separate query, again for AAAA.
  555. *
  556. * For ipv6, A / ipv4 is routable over ipv6. So we always ask for A
  557. * first and then if ipv6, AAAA separately.
  558. *
  559. * Allocate for DNS_MAX, because we may recurse and alter what we're
  560. * looking for.
  561. *
  562. * 0 sizeof(*q) sizeof(*q) + DNS_MAX
  563. * [lws_adns_q_t][ name (DNS_MAX reserved) ] [ name \0 ]
  564. */
  565. q = (lws_adns_q_t *)lws_malloc(sizeof(*q) + DNS_MAX + nlen + 1,
  566. __func__);
  567. if (!q)
  568. goto failed;
  569. memset(q, 0, sizeof(*q));
  570. if (wsi)
  571. lws_dll2_add_head(&wsi->adns, &q->wsi_adns);
  572. q->qtype = (uint16_t)qtype;
  573. if (lws_async_dns_get_new_tid(context, q))
  574. goto failed;
  575. q->tid &= 0xfffe;
  576. q->context = context;
  577. q->tsi = tsi;
  578. q->opaque = opaque;
  579. q->dns = dns;
  580. if (!wsi)
  581. q->standalone_cb = cb;
  582. /* schedule a retry according to the retry policy on the wsi */
  583. if (lws_retry_sul_schedule_retry_wsi(dns->wsi, &q->sul,
  584. lws_async_dns_sul_cb_retry, &q->retry))
  585. goto failed;
  586. /*
  587. * We may rewrite the copy at +sizeof(*q) for CNAME recursion. Keep
  588. * a second copy at + sizeof(*q) + DNS_MAX so we can create the cache
  589. * entry for the original name, not the last CNAME we met.
  590. */
  591. p = (char *)&q[1];
  592. while (nlen--) {
  593. *p++ = tolower(*name++);
  594. p[DNS_MAX - 1] = p[-1];
  595. }
  596. *p = '\0';
  597. p[DNS_MAX] = '\0';
  598. lws_callback_on_writable(dns->wsi);
  599. lws_dll2_add_head(&q->list, &dns->waiting);
  600. lwsl_debug("%s: created new query\n", __func__);
  601. return LADNS_RET_CONTINUING;
  602. failed:
  603. cb(wsi, NULL, NULL, LADNS_RET_FAILED, opaque);
  604. return LADNS_RET_FAILED;
  605. }