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