1/* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com> 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 25#include "private-lib-core.h" 26#include "private-lib-async-dns.h" 27 28static const uint32_t botable[] = { 300, 500, 700, 1250, 5000 29 /* in case everything just dog slow */ }; 30static const lws_retry_bo_t retry_policy = { 31 botable, LWS_ARRAY_SIZE(botable), LWS_RETRY_CONCEAL_ALWAYS, 32 /* don't conceal after the last table entry */ 0, 0, 20 }; 33 34void 35lws_adns_q_destroy(lws_adns_q_t *q) 36{ 37 lws_metrics_caliper_report(q->metcal, (char)q->go_nogo); 38 39 lws_sul_cancel(&q->sul); 40 lws_sul_cancel(&q->write_sul); 41 lws_dll2_remove(&q->list); 42 lws_free(q); 43} 44 45lws_adns_q_t * 46lws_adns_get_query(lws_async_dns_t *dns, adns_query_type_t qtype, 47 lws_dll2_owner_t *owner, uint16_t tid, const char *name) 48{ 49 lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, 50 lws_dll2_get_head(owner)) { 51 lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list); 52 int n = 0, nmax = q->tids >= LWS_ARRAY_SIZE(q->tid) ? 53 LWS_ARRAY_SIZE(q->tid) : q->tids; 54 55 if (!name) 56 for (n = 0; n < nmax; n++) 57 if ((tid & 0xfffe) == (q->tid[n] & 0xfffe)) 58 return q; 59 60 if (name && q->qtype == ((tid & 1) ? LWS_ADNS_RECORD_AAAA : 61 LWS_ADNS_RECORD_A) && 62 !strcasecmp(name, (const char *)&q[1])) { 63 if (owner == &dns->cached) { 64 /* Keep sorted by LRU: move to the head */ 65 lws_dll2_remove(&q->list); 66 lws_dll2_add_head(&q->list, &dns->cached); 67 } 68 69 return q; 70 } 71 } lws_end_foreach_dll_safe(d, d1); 72 73 return NULL; 74} 75 76void 77lws_async_dns_drop_server(struct lws_context *context) 78{ 79 context->async_dns.dns_server_set = 0; 80 lws_set_timeout(context->async_dns.wsi, 1, LWS_TO_KILL_ASYNC); 81 context->async_dns.wsi = NULL; 82 context->async_dns.dns_server_connected = 0; 83} 84 85int 86lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) 87{ 88 89 lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, 90 lws_dll2_get_head(&q->wsi_adns)) { 91 struct lws *w = lws_container_of(d, struct lws, adns); 92 93 lws_dll2_remove(d); 94 if (c && c->results) { 95 lwsl_wsi_debug(w, "q: %p, c: %p, refcount %d -> %d", 96 q, c, c->refcount, c->refcount + 1); 97 c->refcount++; 98 } 99 lws_set_timeout(w, NO_PENDING_TIMEOUT, 0); 100 /* 101 * This may decide to close / delete w 102 */ 103 if (w->adns_cb(w, (const char *)&q[1], c ? c->results : NULL, 0, 104 q->opaque) == NULL) 105 lwsl_info("%s: failed\n", __func__); 106 // lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS, 107 // "adopt udp2 fail"); 108 109 110 } lws_end_foreach_dll_safe(d, d1); 111 112 if (q->standalone_cb) { 113 if (c && c->results) { 114 lwsl_wsi_debug(q->dns ? q->dns->wsi : NULL, "q: %p, c: %p, refcount %d -> %d", 115 q, c, c->refcount, c->refcount + 1); 116 c->refcount++; 117 } 118 119 q->standalone_cb(NULL, (const char *)&q[1], 120 c ? c->results : NULL, 0, q->opaque); 121 } 122 123 lws_adns_dump(q->dns); 124 125 return 0; 126} 127 128static void 129lws_async_dns_sul_cb_retry(struct lws_sorted_usec_list *sul) 130{ 131 lws_adns_q_t *q = lws_container_of(sul, lws_adns_q_t, sul); 132 133 lwsl_wsi_info(q->dns ? q->dns->wsi : NULL, "in"); 134 lws_adns_dump(q->dns); 135 136 if (q->dns && q->dns->wsi) { 137 q->is_retry = 1; 138 lws_callback_on_writable(q->dns->wsi); 139 } 140} 141 142static void 143lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) 144{ 145 uint8_t pkt[LWS_PRE + DNS_PACKET_LEN], *e = &pkt[sizeof(pkt)], *p, *pl; 146 int m, n, which; 147 const char *name; 148 149 /* 150 * We managed to get to the point of being WRITEABLE, which is not a 151 * given if no routes. So call off the write_sul timeout for that. 152 */ 153 lws_sul_cancel(&q->write_sul); 154 155 if (!q->is_retry && q->sent[0] 156#if defined(LWS_WITH_IPV6) 157 && q->sent[0] == q->sent[1] 158#endif 159 ) 160 return; 161 162 q->is_retry = 0; 163 164 /* 165 * UDP is not reliable, it can be locally dropped, or dropped 166 * by any intermediary or the remote peer. So even though we 167 * will do the write in a moment, we schedule another request 168 * for rewrite according to the wsi retry policy. 169 * 170 * If the result came before, we'll cancel it as part of the 171 * wsi close. 172 * 173 * If we have already reached the end of our concealed retries 174 * in the policy, just close without another write. 175 */ 176 if (lws_dll2_is_detached(&q->sul.list) && 177 lws_retry_sul_schedule_retry_wsi(wsi, &q->sul, 178 lws_async_dns_sul_cb_retry, &q->retry)) { 179 /* we have reached the end of our concealed retries */ 180 lwsl_wsi_info(wsi, "failing query"); 181 /* 182 * our policy is to force reloading the dns server info 183 * if our connection ever timed out, in case it or the 184 * routing state changed 185 */ 186 187 lws_async_dns_drop_server(q->context); 188 goto qfail; 189 } 190 191 name = (const char *)&q[1]; 192 193 p = &pkt[LWS_PRE]; 194 memset(p, 0, DHO_SIZEOF); 195 196#if defined(LWS_WITH_IPV6) 197 if (!q->responded) { 198 /* must pick between ipv6 and ipv4 */ 199 which = q->sent[0] >= q->sent[1]; 200 q->sent[which]++; 201 q->asked = 3; /* want results for 4 & 6 before done */ 202 } else 203 which = q->responded & 1; 204#else 205 which = 0; 206 q->asked = 1; 207#endif 208 209 lwsl_wsi_info(wsi, "%s, which %d", name, which); 210 211 /* we hack b0 of the tid to be 0 = A, 1 = AAAA */ 212 213 lws_ser_wu16be(&p[DHO_TID], 214#if defined(LWS_WITH_IPV6) 215 which ? (LADNS_MOST_RECENT_TID(q) | 1) : 216#endif 217 LADNS_MOST_RECENT_TID(q)); 218 lws_ser_wu16be(&p[DHO_FLAGS], (1 << 8)); 219 lws_ser_wu16be(&p[DHO_NQUERIES], 1); 220 221 p += DHO_SIZEOF; 222 223 /* start of label-formatted qname */ 224 225 pl = p++; 226 227 do { 228 if (*name == '.' || !*name) { 229 *pl = (uint8_t)(unsigned int)lws_ptr_diff(p, pl + 1); 230 pl = p; 231 *p++ = 0; /* also serves as terminal length */ 232 if (!*name++) 233 break; 234 } else 235 *p++ = (uint8_t)*name++; 236 } while (p + 6 < e); 237 238 if (p + 6 >= e) { 239 assert(0); 240 lwsl_wsi_err(wsi, "name too big"); 241 goto qfail; 242 } 243 244 lws_ser_wu16be(p, which ? LWS_ADNS_RECORD_AAAA : LWS_ADNS_RECORD_A); 245 p += 2; 246 247 lws_ser_wu16be(p, 1); /* IN class */ 248 p += 2; 249 250 assert(p < pkt + sizeof(pkt) - LWS_PRE); 251 n = lws_ptr_diff(p, pkt + LWS_PRE); 252 253 m = lws_write(wsi, pkt + LWS_PRE, (unsigned int)n, 0); 254 if (m != n) { 255 lwsl_wsi_notice(wsi, "dns write failed %d %d errno %d", 256 m, n, errno); 257 goto qfail; 258 } 259 260#if defined(LWS_WITH_IPV6) 261 if (!q->responded && q->sent[0] != q->sent[1]) { 262 lwsl_wsi_debug(wsi, "request writeable for ipv6"); 263 lws_callback_on_writable(wsi); 264 } 265#endif 266 267 return; 268 269qfail: 270 lwsl_wsi_warn(wsi, "failing query doing NULL completion"); 271 /* 272 * in ipv6 case, we made a cache entry for the first response but 273 * evidently the second response didn't come in time, purge the 274 * incomplete cache entry 275 */ 276 if (q->firstcache) { 277 lwsl_wsi_debug(wsi, "destroy firstcache"); 278 lws_adns_cache_destroy(q->firstcache); 279 q->firstcache = NULL; 280 } 281 lws_async_dns_complete(q, NULL); 282 lws_adns_q_destroy(q); 283} 284 285static int 286callback_async_dns(struct lws *wsi, enum lws_callback_reasons reason, 287 void *user, void *in, size_t len) 288{ 289 struct lws_async_dns *dns = &(lws_get_context(wsi)->async_dns); 290 291 switch (reason) { 292 293 /* callbacks related to raw socket descriptor */ 294 295 case LWS_CALLBACK_RAW_ADOPT: 296 //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_ADOPT"); 297 break; 298 299 case LWS_CALLBACK_RAW_CLOSE: 300 //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_CLOSE"); 301 break; 302 303 case LWS_CALLBACK_RAW_RX: 304 //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_RX (%d)", (int)len); 305 // lwsl_hexdump_wsi_notice(wsi, in, len); 306 lws_adns_parse_udp(dns, in, len); 307 break; 308 309 case LWS_CALLBACK_RAW_WRITEABLE: 310 //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_WRITEABLE"); 311 lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, 312 dns->waiting.head) { 313 lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, 314 list); 315 316 if (//lws_dll2_is_detached(&q->sul.list) && 317 (!q->asked || q->responded != q->asked)) 318 lws_async_dns_writeable(wsi, q); 319 } lws_end_foreach_dll_safe(d, d1); 320 break; 321 322 default: 323 break; 324 } 325 326 return 0; 327} 328 329struct lws_protocols lws_async_dns_protocol = { 330 "lws-async-dns", callback_async_dns, 0, 0, 0, NULL, 0 331}; 332 333int 334lws_async_dns_init(struct lws_context *context) 335{ 336 lws_async_dns_t *dns = &context->async_dns; 337 char ads[48]; 338 int n; 339 340 if (dns->wsi) 341 return 0; 342 343 if (!context->vhost_list) { /* coverity... system vhost always present */ 344 lwsl_cx_err(context, "no system vhost"); 345 return 1; 346 } 347 348 memset(&dns->sa46, 0, sizeof(dns->sa46)); 349 350#if defined(LWS_WITH_SYS_DHCP_CLIENT) 351 if (lws_dhcpc_status(context, &dns->sa46)) 352 goto ok; 353#endif 354 355 n = lws_plat_asyncdns_init(context, &dns->sa46); 356 if (n < 0) { 357 lwsl_cx_warn(context, "no valid dns server, retry"); 358 359 return 1; 360 } 361 362 if (n != LADNS_CONF_SERVER_CHANGED) 363 return 0; 364 365#if defined(LWS_WITH_SYS_DHCP_CLIENT) 366ok: 367#endif 368 dns->sa46.sa4.sin_port = htons(53); 369 lws_write_numeric_address((uint8_t *)&dns->sa46.sa4.sin_addr.s_addr, 4, 370 ads, sizeof(ads)); 371 372 dns->wsi = lws_create_adopt_udp(context->vhost_list, ads, 53, 0, 373 lws_async_dns_protocol.name, NULL, 374 NULL, NULL, &retry_policy, "asyncdns"); 375 if (!dns->wsi) { 376 lwsl_cx_err(context, "foreign socket adoption failed"); 377 return 1; 378 } 379 380 context->async_dns.wsi->udp->sa46 = dns->sa46; 381 382 dns->dns_server_set = 1; 383 384 return 0; 385} 386 387lws_adns_cache_t * 388lws_adns_get_cache(lws_async_dns_t *dns, const char *name) 389{ 390 lws_adns_cache_t *c; 391 392 if (!name) { 393 assert(0); 394 return NULL; 395 } 396 397 lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, 398 lws_dll2_get_head(&dns->cached)) { 399 c = lws_container_of(d, lws_adns_cache_t, list); 400 401 // lwsl_wsi_notice(dns->wsi, "%s vs %s (inc %d)", name, c->name, c->incomplete); 402 403 if (!c->incomplete && !strcasecmp(name, c->name)) { 404 /* Keep sorted by LRU: move to the head */ 405 lws_dll2_remove(&c->list); 406 lws_dll2_add_head(&c->list, &dns->cached); 407 408 return c; 409 } 410 } lws_end_foreach_dll_safe(d, d1); 411 412 return NULL; 413} 414 415#if defined(_DEBUG) 416void 417lws_adns_dump(lws_async_dns_t *dns) 418{ 419 lws_adns_cache_t *c; 420 421 if (!dns) 422 return; 423 424 lwsl_wsi_info(dns->wsi, "ADNS cache %u entries", 425 (unsigned int)dns->cached.count); 426 427 lws_start_foreach_dll(struct lws_dll2 *, d, 428 lws_dll2_get_head(&dns->cached)) { 429 c = lws_container_of(d, lws_adns_cache_t, list); 430 431 lwsl_wsi_info(dns->wsi, "cache: '%s', exp: %lldus, incomp %d, " 432 "fl 0x%x, refc %d, res %p\n", c->name, 433 (long long)(c->sul.us - lws_now_usecs()), 434 c->incomplete, c->flags, c->refcount, c->results); 435 } lws_end_foreach_dll(d); 436 437 lws_start_foreach_dll(struct lws_dll2 *, d, 438 lws_dll2_get_head(&dns->waiting)) { 439 lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list); 440 441 lwsl_wsi_info(dns->wsi, "q: '%s', sent %d, resp %d", 442 (const char *)&q[1], q->sent[0], 443 q->responded); 444 } lws_end_foreach_dll(d); 445} 446#endif 447 448void 449lws_adns_cache_destroy(lws_adns_cache_t *c) 450{ 451 lws_dll2_remove(&c->sul.list); 452 lws_dll2_remove(&c->list); 453 if (c->chain) 454 lws_free(c->chain); 455 lws_free(c); 456} 457 458static int 459cache_clean(struct lws_dll2 *d, void *user) 460{ 461 lws_adns_cache_destroy(lws_container_of(d, lws_adns_cache_t, list)); 462 463 return 0; 464} 465 466void 467sul_cb_expire(struct lws_sorted_usec_list *sul) 468{ 469 lws_adns_cache_t *c = lws_container_of(sul, lws_adns_cache_t, sul); 470 471 lws_adns_cache_destroy(c); 472} 473 474void 475sul_cb_write(struct lws_sorted_usec_list *sul) 476{ 477 lws_adns_q_t *q = lws_container_of(sul, lws_adns_q_t, write_sul); 478 479 /* 480 * Something's up, we couldn't even get from write request to 481 * WRITEABLE within the timeout, let alone the result... fail 482 * the query and everyone riding on it... 483 */ 484 485 lwsl_wsi_info(q->dns ? q->dns->wsi : NULL, "failing"); 486 lws_adns_dump(q->dns); 487 488 lws_async_dns_complete(q, NULL); /* no cache to relate to */ 489 lws_adns_q_destroy(q); 490} 491 492void 493lws_async_dns_freeaddrinfo(const struct addrinfo **pai) 494{ 495 lws_adns_cache_t *c; 496 497 if (!*pai) 498 return; 499 500 /* 501 * First query may have been empty... if second has something, we 502 * fixed up the first result to point to second... but it means 503 * looking backwards from ai, which is c->result, which is the second 504 * packet's results, doesn't get us to the firstcache pointer. 505 * 506 * Adjust c to the firstcache in this case. 507 */ 508 509 c = &((lws_adns_cache_t *)(*pai))[-1]; 510 if (c->firstcache) 511 c = c->firstcache; 512 513 lwsl_debug("%s: c %p, %s, refcount %d -> %d\n", __func__, c, 514 (c->results && c->results->ai_canonname) ? 515 c->results->ai_canonname : "none", 516 c->refcount, c->refcount - 1); 517 518 assert(c->refcount > 0); 519 c->refcount--; 520 *pai = NULL; 521} 522 523void 524lws_async_dns_trim_cache(lws_async_dns_t *dns) 525{ 526 lws_adns_cache_t *c1; 527 528 if (dns->cached.count + 1< MAX_CACHE_ENTRIES) 529 return; 530 531 c1 = lws_container_of(lws_dll2_get_tail(&dns->cached), 532 lws_adns_cache_t, list); 533 if (c1->refcount) 534 lwsl_wsi_info(dns->wsi, "acache %p: refcount %d on purge", 535 c1, c1->refcount); 536 else 537 lws_adns_cache_destroy(c1); 538} 539 540 541static int 542clean(struct lws_dll2 *d, void *user) 543{ 544 lws_adns_q_destroy(lws_container_of(d, lws_adns_q_t, list)); 545 546 return 0; 547} 548 549void 550lws_async_dns_deinit(lws_async_dns_t *dns) 551{ 552 lws_dll2_foreach_safe(&dns->waiting, NULL, clean); 553 lws_dll2_foreach_safe(&dns->cached, NULL, cache_clean); 554 555 if (dns->wsi && !dns->dns_server_connected) { 556 lwsl_wsi_notice(dns->wsi, "late free of incomplete dns wsi"); 557 __lws_lc_untag(dns->wsi->a.context, &dns->wsi->lc); 558#if defined(LWS_WITH_SYS_METRICS) 559 lws_metrics_tags_destroy(&dns->wsi->cal_conn.mtags_owner); 560#endif 561 lws_free_set_NULL(dns->wsi->udp); 562 lws_free_set_NULL(dns->wsi); 563 } 564} 565 566 567static int 568cancel(struct lws_dll2 *d, void *user) 569{ 570 lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list); 571 572 lws_start_foreach_dll_safe(struct lws_dll2 *, d3, d4, 573 lws_dll2_get_head(&q->wsi_adns)) { 574 struct lws *w = lws_container_of(d3, struct lws, adns); 575 576 if (user == w) { 577 lws_dll2_remove(d3); 578 if (!q->wsi_adns.count) 579 lws_adns_q_destroy(q); 580 return 1; 581 } 582 } lws_end_foreach_dll_safe(d3, d4); 583 584 return 0; 585} 586 587void 588lws_async_dns_cancel(struct lws *wsi) 589{ 590 lws_async_dns_t *dns = &wsi->a.context->async_dns; 591 592 lws_dll2_foreach_safe(&dns->waiting, wsi, cancel); 593} 594 595 596static int 597check_tid(struct lws_dll2 *d, void *user) 598{ 599 lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list); 600 int n = 0, nmax = q->tids >= LWS_ARRAY_SIZE(q->tid) ? 601 LWS_ARRAY_SIZE(q->tid) : q->tids; 602 uint16_t check = (uint16_t)(intptr_t)user; 603 604 for (n = 0; n < nmax; n++) 605 if (check == q->tid[n]) 606 return 1; 607 608 return 0; 609} 610 611int 612lws_async_dns_get_new_tid(struct lws_context *context, lws_adns_q_t *q) 613{ 614 lws_async_dns_t *dns = &context->async_dns; 615 int budget = 10; 616 617 /* 618 * Make the TID unpredictable, but must be unique amongst ongoing ones 619 */ 620 do { 621 uint16_t tid; 622 623 if (lws_get_random(context, &tid, 2) != 2) 624 return -1; 625 626 if (lws_dll2_foreach_safe(&dns->waiting, 627 (void *)(intptr_t)tid, check_tid)) 628 continue; 629 630 q->tids++; 631 LADNS_MOST_RECENT_TID(q) = tid; 632 633 return 0; 634 635 } while (budget--); 636 637 lwsl_cx_err(context, "unable to get unique tid"); 638 639 return -1; 640} 641 642struct temp_q { 643 lws_adns_q_t tq; 644 char name[48]; 645}; 646 647lws_async_dns_retcode_t 648lws_async_dns_query(struct lws_context *context, int tsi, const char *name, 649 adns_query_type_t qtype, lws_async_dns_cb_t cb, 650 struct lws *wsi, void *opaque) 651{ 652 lws_async_dns_t *dns = &context->async_dns; 653 size_t nlen = strlen(name); 654 lws_sockaddr46 *sa46; 655 lws_adns_cache_t *c; 656 struct addrinfo *ai; 657 struct temp_q tmq; 658 lws_adns_q_t *q; 659 uint8_t ads[16]; 660 char *p; 661 int m; 662 663 lwsl_cx_info(context, "entry %s", name); 664 lws_adns_dump(dns); 665 666#if !defined(LWS_WITH_IPV6) 667 if (qtype == LWS_ADNS_RECORD_AAAA) { 668 lwsl_cx_err(context, "ipv6 not enabled"); 669 goto failed; 670 } 671#endif 672 673 if (nlen >= DNS_MAX - 1) 674 goto failed; 675 676 /* 677 * we magically know 'localhost' and 'localhost6' if IPv6, this is a 678 * sort of canned /etc/hosts 679 */ 680 681 if (!strcmp(name, "localhost")) 682 name = "127.0.0.1"; 683 684#if defined(LWS_WITH_IPV6) 685 if (!strcmp(name, "localhost6")) 686 name = "::1"; 687#endif 688 689 if (wsi) { 690 if (!lws_dll2_is_detached(&wsi->adns)) { 691 lwsl_cx_err(context, "%s already bound to query %p", 692 lws_wsi_tag(wsi), wsi->adns.owner); 693 goto failed; 694 } 695 wsi->adns_cb = cb; 696 } 697 698 /* there's a done, cached query we can just reuse? */ 699 700 c = lws_adns_get_cache(dns, name); 701 if (c) { 702 lwsl_cx_info(context, "%s: using cached, c->results %p", 703 name, c->results); 704 m = c->results ? LADNS_RET_FOUND : LADNS_RET_FAILED; 705 if (c->results) 706 c->refcount++; 707 708#if defined(LWS_WITH_SYS_METRICS) 709 lws_metric_event(context->mt_adns_cache, METRES_GO, 0); 710#endif 711 712 if (cb(wsi, name, c->results, m, opaque) == NULL) 713 return LADNS_RET_FAILED_WSI_CLOSED; 714 715 return m; 716 } else 717 lwsl_cx_info(context, "%s uncached", name); 718 719#if defined(LWS_WITH_SYS_METRICS) 720 lws_metric_event(context->mt_adns_cache, METRES_NOGO, 0); 721#endif 722 723 /* 724 * It's a 1.2.3.4 or ::1 type IP address already? We don't need a dns 725 * server set up to be able to create an addrinfo result for that. 726 * 727 * Create it as a cached object so it follows the refcount lifecycle 728 * of any other result 729 */ 730 731 m = lws_parse_numeric_address(name, ads, sizeof(ads)); 732 if (m == 4 733#if defined(LWS_WITH_IPV6) 734 || m == 16 735#endif 736 ) { 737 lws_async_dns_trim_cache(dns); 738 739 c = lws_zalloc(sizeof(lws_adns_cache_t) + 740 sizeof(struct addrinfo) + 741 sizeof(lws_sockaddr46) + nlen + 1, "adns-numip"); 742 if (!c) 743 goto failed; 744 745 ai = (struct addrinfo *)&c[1]; 746 sa46 = (lws_sockaddr46 *)&ai[1]; 747 748 ai->ai_socktype = SOCK_STREAM; 749 c->name = (const char *)&sa46[1]; 750 memcpy((char *)c->name, name, nlen + 1); 751 ai->ai_canonname = (char *)&sa46[1]; 752 753 c->results = ai; 754 memset(&tmq.tq, 0, sizeof(tmq.tq)); 755 tmq.tq.opaque = opaque; 756 if (wsi) { 757 wsi->adns_cb = cb; 758 lws_dll2_add_head(&wsi->adns, &tmq.tq.wsi_adns); 759 } else 760 tmq.tq.standalone_cb = cb; 761 lws_strncpy(tmq.name, name, sizeof(tmq.name)); 762 763 lws_dll2_add_head(&c->list, &dns->cached); 764 lws_sul_schedule(context, 0, &c->sul, sul_cb_expire, 765 3600ll * LWS_US_PER_SEC); 766 767 lws_adns_dump(dns); 768 } 769 770 if (m == 4) { 771 ai = (struct addrinfo *)&c[1]; 772 sa46 = (lws_sockaddr46 *)&ai[1]; 773 ai->ai_family = sa46->sa4.sin_family = AF_INET; 774 ai->ai_addrlen = sizeof(sa46->sa4); 775 ai->ai_addr = (struct sockaddr *)&sa46->sa4; 776 memcpy(&sa46->sa4.sin_addr, ads, (unsigned int)m); 777 778 lws_async_dns_complete(&tmq.tq, c); 779 780 return LADNS_RET_FOUND; 781 } 782 783#if defined(LWS_WITH_IPV6) 784 if (m == 16) { 785 ai->ai_family = sa46->sa6.sin6_family = AF_INET6; 786 ai->ai_addrlen = sizeof(sa46->sa6); 787 ai->ai_addr = (struct sockaddr *)&sa46->sa6; 788 memcpy(&sa46->sa6.sin6_addr, ads, (unsigned int)m); 789 790 lws_async_dns_complete(&tmq.tq, c); 791 792 return LADNS_RET_FOUND; 793 } 794#endif 795 796 /* 797 * to try anything else we need a remote server configured... 798 */ 799 800 if (!context->async_dns.dns_server_set && 801 lws_async_dns_init(context)) { 802 lwsl_cx_notice(context, "init failed"); 803 goto failed; 804 } 805 806 /* there's an ongoing query we can share the result of */ 807 808 q = lws_adns_get_query(dns, qtype, &dns->waiting, 0, name); 809 if (q) { 810 lwsl_cx_debug(context, "dns piggybacking: %d:%s", 811 qtype, name); 812 if (wsi) 813 lws_dll2_add_head(&wsi->adns, &q->wsi_adns); 814 815 return LADNS_RET_CONTINUING; 816 } 817 818 /* 819 * Allocate new query / queries... this is a bit complicated because 820 * multiple queries in one packet are not supported peoperly in DNS 821 * itself, and there's no reliable other way to get both ipv6 and ipv4 822 * (AAAA and A) responses in one hit. 823 * 824 * If we don't support ipv6, it's simple, we just ask for A and that's 825 * it. But if we do support ipv6, we need to ask twice, once for A 826 * and in a separate query, again for AAAA. 827 * 828 * For ipv6, A / ipv4 is routable over ipv6. So we always ask for A 829 * first and then if ipv6, AAAA separately. 830 * 831 * Allocate for DNS_MAX, because we may recurse and alter what we're 832 * looking for. 833 * 834 * 0 sizeof(*q) sizeof(*q) + DNS_MAX 835 * [lws_adns_q_t][ name (DNS_MAX reserved) ] [ name \0 ] 836 */ 837 838 q = (lws_adns_q_t *)lws_malloc(sizeof(*q) + DNS_MAX + nlen + 1, 839 __func__); 840 if (!q) 841 goto failed; 842 memset(q, 0, sizeof(*q)); 843 844 if (wsi) 845 lws_dll2_add_head(&wsi->adns, &q->wsi_adns); 846 847 q->qtype = (uint16_t)qtype; 848 849 if (lws_async_dns_get_new_tid(context, q)) { 850 lwsl_cx_err(context, "tid fail"); 851 goto failed; 852 } 853 854 LADNS_MOST_RECENT_TID(q) &= 0xfffe; 855 q->context = context; 856 q->tsi = (uint8_t)tsi; 857 q->opaque = opaque; 858 q->dns = dns; 859 860 if (!wsi) 861 q->standalone_cb = cb; 862 863 /* schedule a retry according to the retry policy on the wsi */ 864 if (lws_retry_sul_schedule_retry_wsi(dns->wsi, &q->sul, 865 lws_async_dns_sul_cb_retry, &q->retry)) 866 goto failed; 867 868 /* fail us if we can't write by this timeout */ 869 lws_sul_schedule(context, 0, &q->write_sul, sul_cb_write, LWS_US_PER_SEC); 870 871 /* 872 * We may rewrite the copy at +sizeof(*q) for CNAME recursion. Keep 873 * a second copy at + sizeof(*q) + DNS_MAX so we can create the cache 874 * entry for the original name, not the last CNAME we met. 875 */ 876 877 p = (char *)&q[1]; 878 while (nlen--) { 879 *p++ = (char)tolower(*name++); 880 p[DNS_MAX - 1] = p[-1]; 881 } 882 *p = '\0'; 883 p[DNS_MAX] = '\0'; 884 885 lws_callback_on_writable(dns->wsi); 886 887 lws_dll2_add_head(&q->list, &dns->waiting); 888 889 lws_metrics_caliper_bind(q->metcal, context->mt_conn_dns); 890 q->go_nogo = METRES_NOGO; 891 /* caliper is reported in lws_adns_q_destroy */ 892 893 lwsl_cx_info(context, "created new query: %s", name); 894 lws_adns_dump(dns); 895 896 return LADNS_RET_CONTINUING; 897 898failed: 899 lwsl_cx_notice(context, "failed"); 900 if (!cb(wsi, NULL, NULL, LADNS_RET_FAILED, opaque)) 901 return LADNS_RET_FAILED_WSI_CLOSED; 902 903 return LADNS_RET_FAILED; 904} 905