xref: /aosp_15_r20/external/libwebsockets/lib/system/async-dns/async-dns-parse.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 - 2021 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 
29*1c60b9acSAndroid Build Coastguard Worker /* updates *dest, returns chars used from ls directly, else -1 for fail */
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker static int
lws_adns_parse_label(const uint8_t * pkt,int len,const uint8_t * ls,int budget,char ** dest,size_t dl)32*1c60b9acSAndroid Build Coastguard Worker lws_adns_parse_label(const uint8_t *pkt, int len, const uint8_t *ls, int budget,
33*1c60b9acSAndroid Build Coastguard Worker 		     char **dest, size_t dl)
34*1c60b9acSAndroid Build Coastguard Worker {
35*1c60b9acSAndroid Build Coastguard Worker 	const uint8_t *e = pkt + len, *ols = ls;
36*1c60b9acSAndroid Build Coastguard Worker 	char pointer = 0, first = 1;
37*1c60b9acSAndroid Build Coastguard Worker 	uint8_t ll;
38*1c60b9acSAndroid Build Coastguard Worker 	int n;
39*1c60b9acSAndroid Build Coastguard Worker 
40*1c60b9acSAndroid Build Coastguard Worker 	if (budget < 1)
41*1c60b9acSAndroid Build Coastguard Worker 		return 0;
42*1c60b9acSAndroid Build Coastguard Worker 
43*1c60b9acSAndroid Build Coastguard Worker 	/* caller must catch end of labels */
44*1c60b9acSAndroid Build Coastguard Worker 	assert(*ls);
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker again1:
47*1c60b9acSAndroid Build Coastguard Worker 	if (ls >= e)
48*1c60b9acSAndroid Build Coastguard Worker 		return -1;
49*1c60b9acSAndroid Build Coastguard Worker 
50*1c60b9acSAndroid Build Coastguard Worker 	if (((*ls) & 0xc0) == 0xc0) {
51*1c60b9acSAndroid Build Coastguard Worker 		if (budget < 2)
52*1c60b9acSAndroid Build Coastguard Worker 			return -1;
53*1c60b9acSAndroid Build Coastguard Worker 		/* pointer into message pkt to name to actually use */
54*1c60b9acSAndroid Build Coastguard Worker 		n = lws_ser_ru16be(ls) & 0x3fff;
55*1c60b9acSAndroid Build Coastguard Worker 		if (n >= len) {
56*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: illegal name pointer\n", __func__);
57*1c60b9acSAndroid Build Coastguard Worker 
58*1c60b9acSAndroid Build Coastguard Worker 			return -1;
59*1c60b9acSAndroid Build Coastguard Worker 		}
60*1c60b9acSAndroid Build Coastguard Worker 
61*1c60b9acSAndroid Build Coastguard Worker 		/* dereference the label pointer */
62*1c60b9acSAndroid Build Coastguard Worker 		ls = pkt + n;
63*1c60b9acSAndroid Build Coastguard Worker 
64*1c60b9acSAndroid Build Coastguard Worker 		/* are we being fuzzed or messed with? */
65*1c60b9acSAndroid Build Coastguard Worker 		if (((*ls) & 0xc0) == 0xc0) {
66*1c60b9acSAndroid Build Coastguard Worker 			/* ... pointer to pointer is unreasonable */
67*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: label ptr to ptr invalid\n", __func__);
68*1c60b9acSAndroid Build Coastguard Worker 
69*1c60b9acSAndroid Build Coastguard Worker 			return -1;
70*1c60b9acSAndroid Build Coastguard Worker 		}
71*1c60b9acSAndroid Build Coastguard Worker 		pointer = 1;
72*1c60b9acSAndroid Build Coastguard Worker 	}
73*1c60b9acSAndroid Build Coastguard Worker 
74*1c60b9acSAndroid Build Coastguard Worker 	if (ls >= e)
75*1c60b9acSAndroid Build Coastguard Worker 		return -1;
76*1c60b9acSAndroid Build Coastguard Worker 
77*1c60b9acSAndroid Build Coastguard Worker 	ll = *ls++;
78*1c60b9acSAndroid Build Coastguard Worker 	if (ls + ll + 1 > e) {
79*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: label len invalid, %d vs %d\n", __func__,
80*1c60b9acSAndroid Build Coastguard Worker 			    lws_ptr_diff((ls + ll + 1), pkt), lws_ptr_diff(e, pkt));
81*1c60b9acSAndroid Build Coastguard Worker 
82*1c60b9acSAndroid Build Coastguard Worker 		return -1;
83*1c60b9acSAndroid Build Coastguard Worker 	}
84*1c60b9acSAndroid Build Coastguard Worker 
85*1c60b9acSAndroid Build Coastguard Worker 	if (ls + ll > ols + budget) {
86*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: label too long %d vs %d\n", __func__, ll, budget);
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker 		return -1;
89*1c60b9acSAndroid Build Coastguard Worker 	}
90*1c60b9acSAndroid Build Coastguard Worker 
91*1c60b9acSAndroid Build Coastguard Worker 	if ((unsigned int)ll + 2 > dl) {
92*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: qname too large\n", __func__);
93*1c60b9acSAndroid Build Coastguard Worker 
94*1c60b9acSAndroid Build Coastguard Worker 		return -1;
95*1c60b9acSAndroid Build Coastguard Worker 	}
96*1c60b9acSAndroid Build Coastguard Worker 
97*1c60b9acSAndroid Build Coastguard Worker 	/* copy the label content into place */
98*1c60b9acSAndroid Build Coastguard Worker 
99*1c60b9acSAndroid Build Coastguard Worker 	memcpy(*dest, ls, ll);
100*1c60b9acSAndroid Build Coastguard Worker 	(*dest)[ll] = '.';
101*1c60b9acSAndroid Build Coastguard Worker 	(*dest)[ll + 1] = '\0';
102*1c60b9acSAndroid Build Coastguard Worker 	*dest += ll + 1;
103*1c60b9acSAndroid Build Coastguard Worker 	ls += ll;
104*1c60b9acSAndroid Build Coastguard Worker 
105*1c60b9acSAndroid Build Coastguard Worker 	if (pointer) {
106*1c60b9acSAndroid Build Coastguard Worker 		if (*ls)
107*1c60b9acSAndroid Build Coastguard Worker 			goto again1;
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker 		/*
110*1c60b9acSAndroid Build Coastguard Worker 		 * special fun rule... if whole qname was a pointer label,
111*1c60b9acSAndroid Build Coastguard Worker 		 * it has no 00 terminator afterwards
112*1c60b9acSAndroid Build Coastguard Worker 		 */
113*1c60b9acSAndroid Build Coastguard Worker 		if (first)
114*1c60b9acSAndroid Build Coastguard Worker 			return 2; /* we just took the 16-bit pointer */
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker 		return 3;
117*1c60b9acSAndroid Build Coastguard Worker 	}
118*1c60b9acSAndroid Build Coastguard Worker 
119*1c60b9acSAndroid Build Coastguard Worker 	first = 0;
120*1c60b9acSAndroid Build Coastguard Worker 
121*1c60b9acSAndroid Build Coastguard Worker 	if (*ls)
122*1c60b9acSAndroid Build Coastguard Worker 		goto again1;
123*1c60b9acSAndroid Build Coastguard Worker 
124*1c60b9acSAndroid Build Coastguard Worker 	ls++;
125*1c60b9acSAndroid Build Coastguard Worker 
126*1c60b9acSAndroid Build Coastguard Worker 	return lws_ptr_diff(ls, ols);
127*1c60b9acSAndroid Build Coastguard Worker }
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker typedef int (*lws_async_dns_find_t)(const char *name, void *opaque,
130*1c60b9acSAndroid Build Coastguard Worker 				    uint32_t ttl, adns_query_type_t type,
131*1c60b9acSAndroid Build Coastguard Worker 				    const uint8_t *payload);
132*1c60b9acSAndroid Build Coastguard Worker 
133*1c60b9acSAndroid Build Coastguard Worker /* locally query the response packet */
134*1c60b9acSAndroid Build Coastguard Worker 
135*1c60b9acSAndroid Build Coastguard Worker struct label_stack {
136*1c60b9acSAndroid Build Coastguard Worker 	char name[DNS_MAX];
137*1c60b9acSAndroid Build Coastguard Worker 	int enl;
138*1c60b9acSAndroid Build Coastguard Worker 	const uint8_t *p;
139*1c60b9acSAndroid Build Coastguard Worker };
140*1c60b9acSAndroid Build Coastguard Worker 
141*1c60b9acSAndroid Build Coastguard Worker /*
142*1c60b9acSAndroid Build Coastguard Worker  * Walk the response packet, calling back to the user-provided callback for each
143*1c60b9acSAndroid Build Coastguard Worker  * A (and AAAA if LWS_IPV6=1) record with a matching name found in there.
144*1c60b9acSAndroid Build Coastguard Worker  *
145*1c60b9acSAndroid Build Coastguard Worker  * Able to recurse using an explicit non-CPU stack to resolve CNAME usages
146*1c60b9acSAndroid Build Coastguard Worker  *
147*1c60b9acSAndroid Build Coastguard Worker  * Return -1: unexpectedly failed
148*1c60b9acSAndroid Build Coastguard Worker  *         0: found
149*1c60b9acSAndroid Build Coastguard Worker  *         1: didn't find anything matching
150*1c60b9acSAndroid Build Coastguard Worker  */
151*1c60b9acSAndroid Build Coastguard Worker 
152*1c60b9acSAndroid Build Coastguard Worker static int
lws_adns_iterate(lws_adns_q_t * q,const uint8_t * pkt,int len,const char * expname,lws_async_dns_find_t cb,void * opaque)153*1c60b9acSAndroid Build Coastguard Worker lws_adns_iterate(lws_adns_q_t *q, const uint8_t *pkt, int len,
154*1c60b9acSAndroid Build Coastguard Worker 		 const char *expname, lws_async_dns_find_t cb, void *opaque)
155*1c60b9acSAndroid Build Coastguard Worker {
156*1c60b9acSAndroid Build Coastguard Worker 	const uint8_t *e = pkt + len, *p, *pay;
157*1c60b9acSAndroid Build Coastguard Worker 	struct label_stack stack[4];
158*1c60b9acSAndroid Build Coastguard Worker 	int n = 0, stp = 0, ansc, m;
159*1c60b9acSAndroid Build Coastguard Worker 	uint16_t rrtype, rrpaylen;
160*1c60b9acSAndroid Build Coastguard Worker 	char *sp, inq;
161*1c60b9acSAndroid Build Coastguard Worker 	uint32_t ttl;
162*1c60b9acSAndroid Build Coastguard Worker 
163*1c60b9acSAndroid Build Coastguard Worker 	lws_strncpy(stack[0].name, expname, sizeof(stack[0].name));
164*1c60b9acSAndroid Build Coastguard Worker 	stack[0].enl = (int)strlen(expname);
165*1c60b9acSAndroid Build Coastguard Worker 
166*1c60b9acSAndroid Build Coastguard Worker start:
167*1c60b9acSAndroid Build Coastguard Worker 	ansc = lws_ser_ru16be(pkt + DHO_NANSWERS);
168*1c60b9acSAndroid Build Coastguard Worker 	p = pkt + DHO_SIZEOF;
169*1c60b9acSAndroid Build Coastguard Worker 	inq = 1;
170*1c60b9acSAndroid Build Coastguard Worker 
171*1c60b9acSAndroid Build Coastguard Worker 	/*
172*1c60b9acSAndroid Build Coastguard Worker 	 * The response also includes the query... and we have to parse it
173*1c60b9acSAndroid Build Coastguard Worker 	 * so we can understand we reached the response... there's a QNAME
174*1c60b9acSAndroid Build Coastguard Worker 	 * made up of labels and then 2 x 16-bit fields, for query type and
175*1c60b9acSAndroid Build Coastguard Worker 	 * query class
176*1c60b9acSAndroid Build Coastguard Worker 	 */
177*1c60b9acSAndroid Build Coastguard Worker 
178*1c60b9acSAndroid Build Coastguard Worker 
179*1c60b9acSAndroid Build Coastguard Worker 	while (p + 14 < e && (inq || ansc)) {
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker 		if (!inq && !stp)
182*1c60b9acSAndroid Build Coastguard Worker 			ansc--;
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker 		/*
185*1c60b9acSAndroid Build Coastguard Worker 		 * First is the name the query applies to... two main
186*1c60b9acSAndroid Build Coastguard Worker 		 * formats can appear here, one is a pointer to
187*1c60b9acSAndroid Build Coastguard Worker 		 * elsewhere in the message, the other separately
188*1c60b9acSAndroid Build Coastguard Worker 		 * provides len / data for each dotted "label", so for
189*1c60b9acSAndroid Build Coastguard Worker 		 * "warmcat.com" warmcat and com are given each with a
190*1c60b9acSAndroid Build Coastguard Worker 		 * prepended length byte.  Any of those may be a pointer
191*1c60b9acSAndroid Build Coastguard Worker 		 * to somewhere else in the packet :-/
192*1c60b9acSAndroid Build Coastguard Worker 		 *
193*1c60b9acSAndroid Build Coastguard Worker 		 * Paranoia is appropriate since the name length must be
194*1c60b9acSAndroid Build Coastguard Worker 		 * parsed out before the rest of the RR can be used and
195*1c60b9acSAndroid Build Coastguard Worker 		 * we can be attacked with absolutely any crafted
196*1c60b9acSAndroid Build Coastguard Worker 		 * content easily via UDP.
197*1c60b9acSAndroid Build Coastguard Worker 		 *
198*1c60b9acSAndroid Build Coastguard Worker 		 * So parse the name and additionally confirm it matches
199*1c60b9acSAndroid Build Coastguard Worker 		 * what the query the TID belongs to actually asked for.
200*1c60b9acSAndroid Build Coastguard Worker 		 */
201*1c60b9acSAndroid Build Coastguard Worker 
202*1c60b9acSAndroid Build Coastguard Worker 		sp = stack[0].name;
203*1c60b9acSAndroid Build Coastguard Worker 
204*1c60b9acSAndroid Build Coastguard Worker 		/* while we have more labels */
205*1c60b9acSAndroid Build Coastguard Worker 
206*1c60b9acSAndroid Build Coastguard Worker 		n = lws_adns_parse_label(pkt, len, p, len, &sp,
207*1c60b9acSAndroid Build Coastguard Worker 					 sizeof(stack[0].name) -
208*1c60b9acSAndroid Build Coastguard Worker 					 lws_ptr_diff_size_t(sp, stack[0].name));
209*1c60b9acSAndroid Build Coastguard Worker 		/* includes case name won't fit */
210*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0)
211*1c60b9acSAndroid Build Coastguard Worker 			return -1;
212*1c60b9acSAndroid Build Coastguard Worker 
213*1c60b9acSAndroid Build Coastguard Worker 		p += n;
214*1c60b9acSAndroid Build Coastguard Worker 
215*1c60b9acSAndroid Build Coastguard Worker 		if (p + (inq ? 5 : 14) > e)
216*1c60b9acSAndroid Build Coastguard Worker 			return -1;
217*1c60b9acSAndroid Build Coastguard Worker 
218*1c60b9acSAndroid Build Coastguard Worker 		/*
219*1c60b9acSAndroid Build Coastguard Worker 		 * p is now just after the decoded RR name, pointing at: type
220*1c60b9acSAndroid Build Coastguard Worker 		 *
221*1c60b9acSAndroid Build Coastguard Worker 		 * We sent class = 1 = IN query... response must match
222*1c60b9acSAndroid Build Coastguard Worker 		 */
223*1c60b9acSAndroid Build Coastguard Worker 
224*1c60b9acSAndroid Build Coastguard Worker 		if (lws_ser_ru16be(&p[2]) != 1) {
225*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: non-IN response 0x%x\n", __func__,
226*1c60b9acSAndroid Build Coastguard Worker 						lws_ser_ru16be(&p[2]));
227*1c60b9acSAndroid Build Coastguard Worker 
228*1c60b9acSAndroid Build Coastguard Worker 			return -1;
229*1c60b9acSAndroid Build Coastguard Worker 		}
230*1c60b9acSAndroid Build Coastguard Worker 
231*1c60b9acSAndroid Build Coastguard Worker 		if (inq) {
232*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: reached end of inq\n", __func__);
233*1c60b9acSAndroid Build Coastguard Worker 			inq = 0;
234*1c60b9acSAndroid Build Coastguard Worker 			p += 4;
235*1c60b9acSAndroid Build Coastguard Worker 			continue;
236*1c60b9acSAndroid Build Coastguard Worker 		}
237*1c60b9acSAndroid Build Coastguard Worker 
238*1c60b9acSAndroid Build Coastguard Worker 		/* carefully validate the claimed RR payload length */
239*1c60b9acSAndroid Build Coastguard Worker 
240*1c60b9acSAndroid Build Coastguard Worker 		rrpaylen = lws_ser_ru16be(&p[8]);
241*1c60b9acSAndroid Build Coastguard Worker 		if (p + 10 + rrpaylen > e) { /* it may be == e */
242*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: invalid RR data length\n", __func__);
243*1c60b9acSAndroid Build Coastguard Worker 
244*1c60b9acSAndroid Build Coastguard Worker 			return -1;
245*1c60b9acSAndroid Build Coastguard Worker 		}
246*1c60b9acSAndroid Build Coastguard Worker 
247*1c60b9acSAndroid Build Coastguard Worker 		ttl = lws_ser_ru32be(&p[4]);
248*1c60b9acSAndroid Build Coastguard Worker 		rrtype = lws_ser_ru16be(&p[0]);
249*1c60b9acSAndroid Build Coastguard Worker 		p += 10; /* point to the payload */
250*1c60b9acSAndroid Build Coastguard Worker 		pay = p;
251*1c60b9acSAndroid Build Coastguard Worker 
252*1c60b9acSAndroid Build Coastguard Worker 		/*
253*1c60b9acSAndroid Build Coastguard Worker 		 * Compare the RR names, allowing for the decoded labelname
254*1c60b9acSAndroid Build Coastguard Worker 		 * to have an extra '.' at the end.
255*1c60b9acSAndroid Build Coastguard Worker 		 */
256*1c60b9acSAndroid Build Coastguard Worker 
257*1c60b9acSAndroid Build Coastguard Worker 		n = lws_ptr_diff(sp, stack[0].name);
258*1c60b9acSAndroid Build Coastguard Worker 		if (stack[0].name[n - 1] == '.')
259*1c60b9acSAndroid Build Coastguard Worker 			n--;
260*1c60b9acSAndroid Build Coastguard Worker 
261*1c60b9acSAndroid Build Coastguard Worker 		m = stack[stp].enl;
262*1c60b9acSAndroid Build Coastguard Worker 		if (stack[stp].name[m - 1] == '.')
263*1c60b9acSAndroid Build Coastguard Worker 			m--;
264*1c60b9acSAndroid Build Coastguard Worker 
265*1c60b9acSAndroid Build Coastguard Worker 		if (n < 1 || n != m ||
266*1c60b9acSAndroid Build Coastguard Worker 		    strncmp(stack[0].name, stack[stp].name, (unsigned int)n)) {
267*1c60b9acSAndroid Build Coastguard Worker 			//lwsl_notice("%s: skipping %s vs %s\n", __func__,
268*1c60b9acSAndroid Build Coastguard Worker 			//		stack[0].name, stack[stp].name);
269*1c60b9acSAndroid Build Coastguard Worker 			goto skip;
270*1c60b9acSAndroid Build Coastguard Worker 		}
271*1c60b9acSAndroid Build Coastguard Worker 
272*1c60b9acSAndroid Build Coastguard Worker 		/*
273*1c60b9acSAndroid Build Coastguard Worker 		 * It's something we could be interested in...
274*1c60b9acSAndroid Build Coastguard Worker 		 *
275*1c60b9acSAndroid Build Coastguard Worker 		 * We can skip RRs we don't understand.  But we need to deal
276*1c60b9acSAndroid Build Coastguard Worker 		 * with at least these and their payloads:
277*1c60b9acSAndroid Build Coastguard Worker 		 *
278*1c60b9acSAndroid Build Coastguard Worker 		 *    A:      4: ipv4 address
279*1c60b9acSAndroid Build Coastguard Worker 		 *    AAAA:  16: ipv6 address (if asked for AAAA)
280*1c60b9acSAndroid Build Coastguard Worker 		 *    CNAME:  ?: labelized name
281*1c60b9acSAndroid Build Coastguard Worker 		 *
282*1c60b9acSAndroid Build Coastguard Worker 		 * If we hit a CNAME we need to try to dereference it with
283*1c60b9acSAndroid Build Coastguard Worker 		 * stuff that is in the same response packet and judge it
284*1c60b9acSAndroid Build Coastguard Worker 		 * from that, without losing our place here.  CNAMEs may
285*1c60b9acSAndroid Build Coastguard Worker 		 * point to CNAMEs to whatever depth we're willing to handle.
286*1c60b9acSAndroid Build Coastguard Worker 		 */
287*1c60b9acSAndroid Build Coastguard Worker 
288*1c60b9acSAndroid Build Coastguard Worker 		switch (rrtype) {
289*1c60b9acSAndroid Build Coastguard Worker 
290*1c60b9acSAndroid Build Coastguard Worker 		case LWS_ADNS_RECORD_AAAA:
291*1c60b9acSAndroid Build Coastguard Worker 			if (rrpaylen != 16) {
292*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: unexpected rrpaylen\n", __func__);
293*1c60b9acSAndroid Build Coastguard Worker 				return -1;
294*1c60b9acSAndroid Build Coastguard Worker 			}
295*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6)
296*1c60b9acSAndroid Build Coastguard Worker 			goto do_cb;
297*1c60b9acSAndroid Build Coastguard Worker #else
298*1c60b9acSAndroid Build Coastguard Worker 			break;
299*1c60b9acSAndroid Build Coastguard Worker #endif
300*1c60b9acSAndroid Build Coastguard Worker 
301*1c60b9acSAndroid Build Coastguard Worker 		case LWS_ADNS_RECORD_A:
302*1c60b9acSAndroid Build Coastguard Worker 			if (rrpaylen != 4) {
303*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: unexpected rrpaylen4\n", __func__);
304*1c60b9acSAndroid Build Coastguard Worker 
305*1c60b9acSAndroid Build Coastguard Worker 				return -1;
306*1c60b9acSAndroid Build Coastguard Worker 			}
307*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6)
308*1c60b9acSAndroid Build Coastguard Worker do_cb:
309*1c60b9acSAndroid Build Coastguard Worker #endif
310*1c60b9acSAndroid Build Coastguard Worker 			cb(stack[0].name, opaque, ttl, rrtype, p);
311*1c60b9acSAndroid Build Coastguard Worker 			break;
312*1c60b9acSAndroid Build Coastguard Worker 
313*1c60b9acSAndroid Build Coastguard Worker 		case LWS_ADNS_RECORD_CNAME:
314*1c60b9acSAndroid Build Coastguard Worker 			/*
315*1c60b9acSAndroid Build Coastguard Worker 			 * The name the CNAME refers to MAY itself be
316*1c60b9acSAndroid Build Coastguard Worker 			 * included elsewhere in the response packet.
317*1c60b9acSAndroid Build Coastguard Worker 			 *
318*1c60b9acSAndroid Build Coastguard Worker 			 * So switch tack, stack where to resume from and
319*1c60b9acSAndroid Build Coastguard Worker 			 * search for the decoded CNAME label name definition
320*1c60b9acSAndroid Build Coastguard Worker 			 * instead.
321*1c60b9acSAndroid Build Coastguard Worker 			 *
322*1c60b9acSAndroid Build Coastguard Worker 			 * First decode the CNAME label payload into the next
323*1c60b9acSAndroid Build Coastguard Worker 			 * stack level buffer for it.
324*1c60b9acSAndroid Build Coastguard Worker 			 */
325*1c60b9acSAndroid Build Coastguard Worker 
326*1c60b9acSAndroid Build Coastguard Worker 			if (++stp == (int)LWS_ARRAY_SIZE(stack)) {
327*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: CNAMEs too deep\n", __func__);
328*1c60b9acSAndroid Build Coastguard Worker 
329*1c60b9acSAndroid Build Coastguard Worker 				return -1;
330*1c60b9acSAndroid Build Coastguard Worker 			}
331*1c60b9acSAndroid Build Coastguard Worker 			sp = stack[stp].name;
332*1c60b9acSAndroid Build Coastguard Worker 			/* get the cname alias */
333*1c60b9acSAndroid Build Coastguard Worker 			n = lws_adns_parse_label(pkt, len, p, rrpaylen, &sp,
334*1c60b9acSAndroid Build Coastguard Worker 						 sizeof(stack[stp].name) -
335*1c60b9acSAndroid Build Coastguard Worker 						 lws_ptr_diff_size_t(sp, stack[stp].name));
336*1c60b9acSAndroid Build Coastguard Worker 			/* includes case name won't fit */
337*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0)
338*1c60b9acSAndroid Build Coastguard Worker 				return -1;
339*1c60b9acSAndroid Build Coastguard Worker 
340*1c60b9acSAndroid Build Coastguard Worker 			p += n;
341*1c60b9acSAndroid Build Coastguard Worker 
342*1c60b9acSAndroid Build Coastguard Worker 			if (p + 14 > e)
343*1c60b9acSAndroid Build Coastguard Worker 				return -1;
344*1c60b9acSAndroid Build Coastguard Worker #if 0
345*1c60b9acSAndroid Build Coastguard Worker 			/* it should have exactly reached rrpaylen if only one
346*1c60b9acSAndroid Build Coastguard Worker 			 * CNAME, else somewhere in the middle */
347*1c60b9acSAndroid Build Coastguard Worker 
348*1c60b9acSAndroid Build Coastguard Worker 			if (p != pay + rrpaylen) {
349*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: cname name bad len %d\n", __func__, rrpaylen);
350*1c60b9acSAndroid Build Coastguard Worker 
351*1c60b9acSAndroid Build Coastguard Worker 				return -1;
352*1c60b9acSAndroid Build Coastguard Worker 			}
353*1c60b9acSAndroid Build Coastguard Worker #endif
354*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: recursing looking for %s\n", __func__, stack[stp].name);
355*1c60b9acSAndroid Build Coastguard Worker 
356*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: recursing looking for %s\n", __func__,
357*1c60b9acSAndroid Build Coastguard Worker 					stack[stp].name);
358*1c60b9acSAndroid Build Coastguard Worker 
359*1c60b9acSAndroid Build Coastguard Worker 			stack[stp].enl = lws_ptr_diff(sp, stack[stp].name);
360*1c60b9acSAndroid Build Coastguard Worker 			/* when we unstack, resume from here */
361*1c60b9acSAndroid Build Coastguard Worker 			stack[stp].p = pay + rrpaylen;
362*1c60b9acSAndroid Build Coastguard Worker 			goto start;
363*1c60b9acSAndroid Build Coastguard Worker 
364*1c60b9acSAndroid Build Coastguard Worker 		default:
365*1c60b9acSAndroid Build Coastguard Worker 			break;
366*1c60b9acSAndroid Build Coastguard Worker 		}
367*1c60b9acSAndroid Build Coastguard Worker 
368*1c60b9acSAndroid Build Coastguard Worker skip:
369*1c60b9acSAndroid Build Coastguard Worker 		p += rrpaylen;
370*1c60b9acSAndroid Build Coastguard Worker 	}
371*1c60b9acSAndroid Build Coastguard Worker 
372*1c60b9acSAndroid Build Coastguard Worker 	if (!stp)
373*1c60b9acSAndroid Build Coastguard Worker 		return 1; /* we didn't find anything, but we didn't error */
374*1c60b9acSAndroid Build Coastguard Worker 
375*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: '%s' -> CNAME '%s' resolution not provided, recursing\n",
376*1c60b9acSAndroid Build Coastguard Worker 			__func__, ((const char *)&q[1]) + DNS_MAX,
377*1c60b9acSAndroid Build Coastguard Worker 			stack[stp].name);
378*1c60b9acSAndroid Build Coastguard Worker 
379*1c60b9acSAndroid Build Coastguard Worker 	/*
380*1c60b9acSAndroid Build Coastguard Worker 	 * This implies there wasn't any usable definition for the
381*1c60b9acSAndroid Build Coastguard Worker 	 * CNAME in the end, eg, only AAAA when we needed an A.
382*1c60b9acSAndroid Build Coastguard Worker 	 *
383*1c60b9acSAndroid Build Coastguard Worker 	 * It's also legit if the DNS just returns the CNAME, and that server
384*1c60b9acSAndroid Build Coastguard Worker 	 * did not directly know the next step in resolution of the CNAME, so
385*1c60b9acSAndroid Build Coastguard Worker 	 * instead of putting the resolution elsewhere in the response, has
386*1c60b9acSAndroid Build Coastguard Worker 	 * told us just the CNAME and left it to us to find out its resolution
387*1c60b9acSAndroid Build Coastguard Worker 	 * separately.
388*1c60b9acSAndroid Build Coastguard Worker 	 *
389*1c60b9acSAndroid Build Coastguard Worker 	 * Reset this request to be for the CNAME, and restart the request
390*1c60b9acSAndroid Build Coastguard Worker 	 * action with a new tid.
391*1c60b9acSAndroid Build Coastguard Worker 	 */
392*1c60b9acSAndroid Build Coastguard Worker 
393*1c60b9acSAndroid Build Coastguard Worker 	if (lws_async_dns_get_new_tid(q->context, q))
394*1c60b9acSAndroid Build Coastguard Worker 		return -1;
395*1c60b9acSAndroid Build Coastguard Worker 
396*1c60b9acSAndroid Build Coastguard Worker 	LADNS_MOST_RECENT_TID(q) &= 0xfffe;
397*1c60b9acSAndroid Build Coastguard Worker 	q->asked = q->responded = 0;
398*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6)
399*1c60b9acSAndroid Build Coastguard Worker 	q->sent[1] = 0;
400*1c60b9acSAndroid Build Coastguard Worker #endif
401*1c60b9acSAndroid Build Coastguard Worker 	q->sent[0] = 0;
402*1c60b9acSAndroid Build Coastguard Worker 	q->recursion++;
403*1c60b9acSAndroid Build Coastguard Worker 	if (q->recursion == DNS_RECURSION_LIMIT) {
404*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: recursion overflow\n", __func__);
405*1c60b9acSAndroid Build Coastguard Worker 
406*1c60b9acSAndroid Build Coastguard Worker 		return -1;
407*1c60b9acSAndroid Build Coastguard Worker 	}
408*1c60b9acSAndroid Build Coastguard Worker 
409*1c60b9acSAndroid Build Coastguard Worker 	if (q->firstcache)
410*1c60b9acSAndroid Build Coastguard Worker 		lws_adns_cache_destroy(q->firstcache);
411*1c60b9acSAndroid Build Coastguard Worker 	q->firstcache = NULL;
412*1c60b9acSAndroid Build Coastguard Worker 
413*1c60b9acSAndroid Build Coastguard Worker 	/* overwrite the query name with the CNAME */
414*1c60b9acSAndroid Build Coastguard Worker 
415*1c60b9acSAndroid Build Coastguard Worker 	n = 0;
416*1c60b9acSAndroid Build Coastguard Worker 	{
417*1c60b9acSAndroid Build Coastguard Worker 		char *cp = (char *)&q[1];
418*1c60b9acSAndroid Build Coastguard Worker 
419*1c60b9acSAndroid Build Coastguard Worker 		while (stack[stp].name[n])
420*1c60b9acSAndroid Build Coastguard Worker 			*cp++ = (char)tolower(stack[stp].name[n++]);
421*1c60b9acSAndroid Build Coastguard Worker 		/* trim the following . if any */
422*1c60b9acSAndroid Build Coastguard Worker 		if (n && cp[-1] == '.')
423*1c60b9acSAndroid Build Coastguard Worker 			cp--;
424*1c60b9acSAndroid Build Coastguard Worker 		*cp = '\0';
425*1c60b9acSAndroid Build Coastguard Worker 	}
426*1c60b9acSAndroid Build Coastguard Worker 
427*1c60b9acSAndroid Build Coastguard Worker 	lws_callback_on_writable(q->dns->wsi);
428*1c60b9acSAndroid Build Coastguard Worker 
429*1c60b9acSAndroid Build Coastguard Worker 	return 2;
430*1c60b9acSAndroid Build Coastguard Worker }
431*1c60b9acSAndroid Build Coastguard Worker 
432*1c60b9acSAndroid Build Coastguard Worker int
lws_async_dns_estimate(const char * name,void * opaque,uint32_t ttl,adns_query_type_t type,const uint8_t * payload)433*1c60b9acSAndroid Build Coastguard Worker lws_async_dns_estimate(const char *name, void *opaque, uint32_t ttl,
434*1c60b9acSAndroid Build Coastguard Worker 			adns_query_type_t type, const uint8_t *payload)
435*1c60b9acSAndroid Build Coastguard Worker {
436*1c60b9acSAndroid Build Coastguard Worker 	size_t *est = (size_t *)opaque, my;
437*1c60b9acSAndroid Build Coastguard Worker 
438*1c60b9acSAndroid Build Coastguard Worker 	my = sizeof(struct addrinfo);
439*1c60b9acSAndroid Build Coastguard Worker 	if (type == LWS_ADNS_RECORD_AAAA)
440*1c60b9acSAndroid Build Coastguard Worker 		my += sizeof(struct sockaddr_in6);
441*1c60b9acSAndroid Build Coastguard Worker 	else
442*1c60b9acSAndroid Build Coastguard Worker 		my += sizeof(struct sockaddr_in);
443*1c60b9acSAndroid Build Coastguard Worker 
444*1c60b9acSAndroid Build Coastguard Worker 	*est += my;
445*1c60b9acSAndroid Build Coastguard Worker 
446*1c60b9acSAndroid Build Coastguard Worker 	return 0;
447*1c60b9acSAndroid Build Coastguard Worker }
448*1c60b9acSAndroid Build Coastguard Worker 
449*1c60b9acSAndroid Build Coastguard Worker struct adstore {
450*1c60b9acSAndroid Build Coastguard Worker 	const char *name;
451*1c60b9acSAndroid Build Coastguard Worker 	struct addrinfo *pos;
452*1c60b9acSAndroid Build Coastguard Worker 	struct addrinfo *prev;
453*1c60b9acSAndroid Build Coastguard Worker 	int ctr;
454*1c60b9acSAndroid Build Coastguard Worker 	uint32_t smallest_ttl;
455*1c60b9acSAndroid Build Coastguard Worker 	uint8_t flags;
456*1c60b9acSAndroid Build Coastguard Worker };
457*1c60b9acSAndroid Build Coastguard Worker 
458*1c60b9acSAndroid Build Coastguard Worker /*
459*1c60b9acSAndroid Build Coastguard Worker  * Callback for each A or AAAA record, creating getaddrinfo-compatible results
460*1c60b9acSAndroid Build Coastguard Worker  * into the preallocated exact-sized storage.
461*1c60b9acSAndroid Build Coastguard Worker  */
462*1c60b9acSAndroid Build Coastguard Worker int
lws_async_dns_store(const char * name,void * opaque,uint32_t ttl,adns_query_type_t type,const uint8_t * payload)463*1c60b9acSAndroid Build Coastguard Worker lws_async_dns_store(const char *name, void *opaque, uint32_t ttl,
464*1c60b9acSAndroid Build Coastguard Worker 		    adns_query_type_t type, const uint8_t *payload)
465*1c60b9acSAndroid Build Coastguard Worker {
466*1c60b9acSAndroid Build Coastguard Worker 	struct adstore *adst = (struct adstore *)opaque;
467*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
468*1c60b9acSAndroid Build Coastguard Worker 	char buf[48];
469*1c60b9acSAndroid Build Coastguard Worker #endif
470*1c60b9acSAndroid Build Coastguard Worker 	size_t i;
471*1c60b9acSAndroid Build Coastguard Worker 
472*1c60b9acSAndroid Build Coastguard Worker 	if (ttl < adst->smallest_ttl || !adst->ctr)
473*1c60b9acSAndroid Build Coastguard Worker 		adst->smallest_ttl = ttl;
474*1c60b9acSAndroid Build Coastguard Worker 
475*1c60b9acSAndroid Build Coastguard Worker 	if (adst->prev)
476*1c60b9acSAndroid Build Coastguard Worker 		adst->prev->ai_next = adst->pos;
477*1c60b9acSAndroid Build Coastguard Worker 	adst->prev = adst->pos;
478*1c60b9acSAndroid Build Coastguard Worker 
479*1c60b9acSAndroid Build Coastguard Worker 	adst->pos->ai_flags = 0;
480*1c60b9acSAndroid Build Coastguard Worker 	adst->pos->ai_family = type == LWS_ADNS_RECORD_AAAA ?
481*1c60b9acSAndroid Build Coastguard Worker 						AF_INET6 : AF_INET;
482*1c60b9acSAndroid Build Coastguard Worker 	adst->pos->ai_socktype = SOCK_STREAM;
483*1c60b9acSAndroid Build Coastguard Worker 	adst->pos->ai_protocol = IPPROTO_UDP; /* no meaning */
484*1c60b9acSAndroid Build Coastguard Worker 	adst->pos->ai_addrlen = type == LWS_ADNS_RECORD_AAAA ?
485*1c60b9acSAndroid Build Coastguard Worker 						sizeof(struct sockaddr_in6) :
486*1c60b9acSAndroid Build Coastguard Worker 						sizeof(struct sockaddr_in);
487*1c60b9acSAndroid Build Coastguard Worker 	adst->pos->ai_canonname = (char *)adst->name;
488*1c60b9acSAndroid Build Coastguard Worker 	adst->pos->ai_addr = (struct sockaddr *)&adst->pos[1];
489*1c60b9acSAndroid Build Coastguard Worker 	adst->pos->ai_next = NULL;
490*1c60b9acSAndroid Build Coastguard Worker 
491*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_IPV6)
492*1c60b9acSAndroid Build Coastguard Worker 	if (type == LWS_ADNS_RECORD_AAAA) {
493*1c60b9acSAndroid Build Coastguard Worker 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&adst->pos[1];
494*1c60b9acSAndroid Build Coastguard Worker 
495*1c60b9acSAndroid Build Coastguard Worker 		i = sizeof(*in6);
496*1c60b9acSAndroid Build Coastguard Worker 		memset(in6, 0, i);
497*1c60b9acSAndroid Build Coastguard Worker 		in6->sin6_family = (sa_family_t)adst->pos->ai_family;
498*1c60b9acSAndroid Build Coastguard Worker 		memcpy(in6->sin6_addr.s6_addr, payload, 16);
499*1c60b9acSAndroid Build Coastguard Worker 		adst->flags |= 2;
500*1c60b9acSAndroid Build Coastguard Worker 	} else
501*1c60b9acSAndroid Build Coastguard Worker #endif
502*1c60b9acSAndroid Build Coastguard Worker 	{
503*1c60b9acSAndroid Build Coastguard Worker 		struct sockaddr_in *in = (struct sockaddr_in *)&adst->pos[1];
504*1c60b9acSAndroid Build Coastguard Worker 
505*1c60b9acSAndroid Build Coastguard Worker 		i = sizeof(*in);
506*1c60b9acSAndroid Build Coastguard Worker 		memset(in, 0, i);
507*1c60b9acSAndroid Build Coastguard Worker 		in->sin_family = (sa_family_t)adst->pos->ai_family;
508*1c60b9acSAndroid Build Coastguard Worker 		memcpy(&in->sin_addr.s_addr, payload, 4);
509*1c60b9acSAndroid Build Coastguard Worker 		adst->flags |= 1;
510*1c60b9acSAndroid Build Coastguard Worker 	}
511*1c60b9acSAndroid Build Coastguard Worker 
512*1c60b9acSAndroid Build Coastguard Worker 	adst->pos = (struct addrinfo *)((uint8_t *)adst->pos +
513*1c60b9acSAndroid Build Coastguard Worker 					sizeof(struct addrinfo) + i);
514*1c60b9acSAndroid Build Coastguard Worker 
515*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
516*1c60b9acSAndroid Build Coastguard Worker 	if (lws_write_numeric_address(payload,
517*1c60b9acSAndroid Build Coastguard Worker 				type == LWS_ADNS_RECORD_AAAA ? 16 : 4,
518*1c60b9acSAndroid Build Coastguard Worker 							buf, sizeof(buf)) > 0)
519*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %d: %s: %s\n", __func__, adst->ctr,
520*1c60b9acSAndroid Build Coastguard Worker 				adst->name, buf);
521*1c60b9acSAndroid Build Coastguard Worker #endif
522*1c60b9acSAndroid Build Coastguard Worker 	adst->ctr++;
523*1c60b9acSAndroid Build Coastguard Worker 
524*1c60b9acSAndroid Build Coastguard Worker 	return 0;
525*1c60b9acSAndroid Build Coastguard Worker }
526*1c60b9acSAndroid Build Coastguard Worker 
527*1c60b9acSAndroid Build Coastguard Worker /*
528*1c60b9acSAndroid Build Coastguard Worker  * We want to parse out all A or AAAA records
529*1c60b9acSAndroid Build Coastguard Worker  */
530*1c60b9acSAndroid Build Coastguard Worker 
531*1c60b9acSAndroid Build Coastguard Worker void
lws_adns_parse_udp(lws_async_dns_t * dns,const uint8_t * pkt,size_t len)532*1c60b9acSAndroid Build Coastguard Worker lws_adns_parse_udp(lws_async_dns_t *dns, const uint8_t *pkt, size_t len)
533*1c60b9acSAndroid Build Coastguard Worker {
534*1c60b9acSAndroid Build Coastguard Worker 	const char *nm, *nmcname;
535*1c60b9acSAndroid Build Coastguard Worker 	lws_adns_cache_t *c;
536*1c60b9acSAndroid Build Coastguard Worker 	struct adstore adst;
537*1c60b9acSAndroid Build Coastguard Worker 	lws_adns_q_t *q;
538*1c60b9acSAndroid Build Coastguard Worker 	int n, ncname;
539*1c60b9acSAndroid Build Coastguard Worker 	size_t est;
540*1c60b9acSAndroid Build Coastguard Worker 
541*1c60b9acSAndroid Build Coastguard Worker 	// lwsl_hexdump_notice(pkt, len);
542*1c60b9acSAndroid Build Coastguard Worker 
543*1c60b9acSAndroid Build Coastguard Worker 	/* we have to at least have the header */
544*1c60b9acSAndroid Build Coastguard Worker 
545*1c60b9acSAndroid Build Coastguard Worker 	if (len < DHO_SIZEOF)
546*1c60b9acSAndroid Build Coastguard Worker 		return;
547*1c60b9acSAndroid Build Coastguard Worker 
548*1c60b9acSAndroid Build Coastguard Worker 	/* we asked with one query, so anything else is bogus */
549*1c60b9acSAndroid Build Coastguard Worker 
550*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ser_ru16be(pkt + DHO_NQUERIES) != 1)
551*1c60b9acSAndroid Build Coastguard Worker 		return;
552*1c60b9acSAndroid Build Coastguard Worker 
553*1c60b9acSAndroid Build Coastguard Worker 	/* match both A and AAAA queries if any */
554*1c60b9acSAndroid Build Coastguard Worker 
555*1c60b9acSAndroid Build Coastguard Worker 	q = lws_adns_get_query(dns, 0, &dns->waiting,
556*1c60b9acSAndroid Build Coastguard Worker 			       lws_ser_ru16be(pkt + DHO_TID), NULL);
557*1c60b9acSAndroid Build Coastguard Worker 	if (!q) {
558*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: dropping unknown query tid 0x%x\n",
559*1c60b9acSAndroid Build Coastguard Worker 			    __func__, lws_ser_ru16be(pkt + DHO_TID));
560*1c60b9acSAndroid Build Coastguard Worker 
561*1c60b9acSAndroid Build Coastguard Worker 		return;
562*1c60b9acSAndroid Build Coastguard Worker 	}
563*1c60b9acSAndroid Build Coastguard Worker 
564*1c60b9acSAndroid Build Coastguard Worker 	/* we can get dups... drop any that have already happened */
565*1c60b9acSAndroid Build Coastguard Worker 
566*1c60b9acSAndroid Build Coastguard Worker 	n = 1 << (lws_ser_ru16be(pkt + DHO_TID) & 1);
567*1c60b9acSAndroid Build Coastguard Worker 	if (q->responded & n) {
568*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: dup\n", __func__);
569*1c60b9acSAndroid Build Coastguard Worker 		goto fail_out;
570*1c60b9acSAndroid Build Coastguard Worker 	}
571*1c60b9acSAndroid Build Coastguard Worker 
572*1c60b9acSAndroid Build Coastguard Worker 	q->responded = (uint8_t)(q->responded | n);
573*1c60b9acSAndroid Build Coastguard Worker 
574*1c60b9acSAndroid Build Coastguard Worker 	/* we want to confirm the results against what we last requested... */
575*1c60b9acSAndroid Build Coastguard Worker 
576*1c60b9acSAndroid Build Coastguard Worker 	nmcname = ((const char *)&q[1]);
577*1c60b9acSAndroid Build Coastguard Worker 
578*1c60b9acSAndroid Build Coastguard Worker 	/*
579*1c60b9acSAndroid Build Coastguard Worker 	 * First walk the packet figuring out the allocation needed for all
580*1c60b9acSAndroid Build Coastguard Worker 	 * the results.  Produce the following layout at c
581*1c60b9acSAndroid Build Coastguard Worker 	 *
582*1c60b9acSAndroid Build Coastguard Worker 	 *  lws_adns_cache_t: new cache object
583*1c60b9acSAndroid Build Coastguard Worker 	 *  [struct addrinfo + struct sockaddr_in or _in6]: for each A or AAAA
584*1c60b9acSAndroid Build Coastguard Worker 	 *  char []: copy of resolved name
585*1c60b9acSAndroid Build Coastguard Worker 	 */
586*1c60b9acSAndroid Build Coastguard Worker 
587*1c60b9acSAndroid Build Coastguard Worker 	ncname = (int)strlen(nmcname) + 1;
588*1c60b9acSAndroid Build Coastguard Worker 
589*1c60b9acSAndroid Build Coastguard Worker 	est = sizeof(lws_adns_cache_t) + (unsigned int)ncname;
590*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ser_ru16be(pkt + DHO_NANSWERS)) {
591*1c60b9acSAndroid Build Coastguard Worker 		int ir = lws_adns_iterate(q, pkt, (int)len, nmcname,
592*1c60b9acSAndroid Build Coastguard Worker 					  lws_async_dns_estimate, &est);
593*1c60b9acSAndroid Build Coastguard Worker 		if (ir < 0)
594*1c60b9acSAndroid Build Coastguard Worker 			goto fail_out;
595*1c60b9acSAndroid Build Coastguard Worker 
596*1c60b9acSAndroid Build Coastguard Worker 		if (ir == 2) /* CNAME recursive resolution */
597*1c60b9acSAndroid Build Coastguard Worker 			return;
598*1c60b9acSAndroid Build Coastguard Worker 	}
599*1c60b9acSAndroid Build Coastguard Worker 
600*1c60b9acSAndroid Build Coastguard Worker 	/* but we want to create the cache entry against the original request */
601*1c60b9acSAndroid Build Coastguard Worker 
602*1c60b9acSAndroid Build Coastguard Worker 	nm = ((const char *)&q[1]) + DNS_MAX;
603*1c60b9acSAndroid Build Coastguard Worker 	n = (int)strlen(nm) + 1;
604*1c60b9acSAndroid Build Coastguard Worker 
605*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: create cache entry for %s, %zu\n", __func__, nm,
606*1c60b9acSAndroid Build Coastguard Worker 			est - sizeof(lws_adns_cache_t));
607*1c60b9acSAndroid Build Coastguard Worker 	c = lws_malloc(est + 1, "async-dns-entry");
608*1c60b9acSAndroid Build Coastguard Worker 	if (!c) {
609*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: OOM %zu\n", __func__, est);
610*1c60b9acSAndroid Build Coastguard Worker 		goto fail_out;
611*1c60b9acSAndroid Build Coastguard Worker 	}
612*1c60b9acSAndroid Build Coastguard Worker 	memset(c, 0, sizeof(*c));
613*1c60b9acSAndroid Build Coastguard Worker 
614*1c60b9acSAndroid Build Coastguard Worker 	/* place it at end, no need to care about alignment padding */
615*1c60b9acSAndroid Build Coastguard Worker 	c->name = adst.name = ((const char *)c) + est - n;
616*1c60b9acSAndroid Build Coastguard Worker 	memcpy((char *)c->name, nm, (unsigned int)n);
617*1c60b9acSAndroid Build Coastguard Worker 
618*1c60b9acSAndroid Build Coastguard Worker 	/*
619*1c60b9acSAndroid Build Coastguard Worker 	 * Then walk the packet again, placing the objects we accounted for
620*1c60b9acSAndroid Build Coastguard Worker 	 * the first time into the result allocation after the cache object
621*1c60b9acSAndroid Build Coastguard Worker 	 * and copy of the name
622*1c60b9acSAndroid Build Coastguard Worker 	 */
623*1c60b9acSAndroid Build Coastguard Worker 
624*1c60b9acSAndroid Build Coastguard Worker 	adst.pos = (struct addrinfo *)&c[1];
625*1c60b9acSAndroid Build Coastguard Worker 	adst.prev = NULL;
626*1c60b9acSAndroid Build Coastguard Worker 	adst.ctr = 0;
627*1c60b9acSAndroid Build Coastguard Worker 	adst.smallest_ttl = 3600;
628*1c60b9acSAndroid Build Coastguard Worker 	adst.flags = 0;
629*1c60b9acSAndroid Build Coastguard Worker 
630*1c60b9acSAndroid Build Coastguard Worker 	/*
631*1c60b9acSAndroid Build Coastguard Worker 	 * smallest_ttl applies as it is to empty results (NXDOMAIN), or is
632*1c60b9acSAndroid Build Coastguard Worker 	 * set to the minimum ttl seen in all the results.
633*1c60b9acSAndroid Build Coastguard Worker 	 */
634*1c60b9acSAndroid Build Coastguard Worker 
635*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ser_ru16be(pkt + DHO_NANSWERS) &&
636*1c60b9acSAndroid Build Coastguard Worker 	    lws_adns_iterate(q, pkt, (int)len, nmcname, lws_async_dns_store, &adst) < 0) {
637*1c60b9acSAndroid Build Coastguard Worker 		lws_free(c);
638*1c60b9acSAndroid Build Coastguard Worker 		goto fail_out;
639*1c60b9acSAndroid Build Coastguard Worker 	}
640*1c60b9acSAndroid Build Coastguard Worker 
641*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ser_ru16be(pkt + DHO_NANSWERS)) {
642*1c60b9acSAndroid Build Coastguard Worker 		c->results = (struct addrinfo *)&c[1];
643*1c60b9acSAndroid Build Coastguard Worker 		if (q->last) /* chain the second one on */
644*1c60b9acSAndroid Build Coastguard Worker 			*q->last = c->results;
645*1c60b9acSAndroid Build Coastguard Worker 		else /* first one had no results, set first guy's c->results */
646*1c60b9acSAndroid Build Coastguard Worker 			if (q->firstcache)
647*1c60b9acSAndroid Build Coastguard Worker 				q->firstcache->results = c->results;
648*1c60b9acSAndroid Build Coastguard Worker 	}
649*1c60b9acSAndroid Build Coastguard Worker 
650*1c60b9acSAndroid Build Coastguard Worker 	if (adst.prev) /* so we know where to continue the addrinfo list */
651*1c60b9acSAndroid Build Coastguard Worker 		/* can be NULL if first resp empty */
652*1c60b9acSAndroid Build Coastguard Worker 		q->last = &adst.prev->ai_next;
653*1c60b9acSAndroid Build Coastguard Worker 
654*1c60b9acSAndroid Build Coastguard Worker 	if (q->firstcache) { /* also need to free chain when we free this guy */
655*1c60b9acSAndroid Build Coastguard Worker 		q->firstcache->chain = c;
656*1c60b9acSAndroid Build Coastguard Worker 		c->firstcache = q->firstcache;
657*1c60b9acSAndroid Build Coastguard Worker 	} else {
658*1c60b9acSAndroid Build Coastguard Worker 
659*1c60b9acSAndroid Build Coastguard Worker 		q->firstcache = c;
660*1c60b9acSAndroid Build Coastguard Worker 		c->incomplete = !q->responded;// != q->asked;
661*1c60b9acSAndroid Build Coastguard Worker 
662*1c60b9acSAndroid Build Coastguard Worker 		/*
663*1c60b9acSAndroid Build Coastguard Worker 		 * Only register the first one into the cache...
664*1c60b9acSAndroid Build Coastguard Worker 		 * Trim the oldest cache entry if necessary
665*1c60b9acSAndroid Build Coastguard Worker 		 */
666*1c60b9acSAndroid Build Coastguard Worker 
667*1c60b9acSAndroid Build Coastguard Worker 		lws_async_dns_trim_cache(dns);
668*1c60b9acSAndroid Build Coastguard Worker 
669*1c60b9acSAndroid Build Coastguard Worker 		/*
670*1c60b9acSAndroid Build Coastguard Worker 		 * cache the first results object... if a second one comes,
671*1c60b9acSAndroid Build Coastguard Worker 		 * we won't directly register it but will chain it on to this
672*1c60b9acSAndroid Build Coastguard Worker 		 * first one and continue to addinfo ai_next linked list from
673*1c60b9acSAndroid Build Coastguard Worker 		 * the first into the second
674*1c60b9acSAndroid Build Coastguard Worker 		 */
675*1c60b9acSAndroid Build Coastguard Worker 
676*1c60b9acSAndroid Build Coastguard Worker 		c->flags = adst.flags;
677*1c60b9acSAndroid Build Coastguard Worker 		lws_dll2_add_head(&c->list, &dns->cached);
678*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(q->context, 0, &c->sul, sul_cb_expire,
679*1c60b9acSAndroid Build Coastguard Worker 				 lws_now_usecs() +
680*1c60b9acSAndroid Build Coastguard Worker 				 (adst.smallest_ttl * LWS_US_PER_SEC));
681*1c60b9acSAndroid Build Coastguard Worker 	}
682*1c60b9acSAndroid Build Coastguard Worker 
683*1c60b9acSAndroid Build Coastguard Worker 	if (q->responded != q->asked)
684*1c60b9acSAndroid Build Coastguard Worker 		return;
685*1c60b9acSAndroid Build Coastguard Worker 
686*1c60b9acSAndroid Build Coastguard Worker 	/*
687*1c60b9acSAndroid Build Coastguard Worker 	 * Now we captured everything into the new object, return the
688*1c60b9acSAndroid Build Coastguard Worker 	 * addrinfo results, if any, to all interested wsi, if any...
689*1c60b9acSAndroid Build Coastguard Worker 	 */
690*1c60b9acSAndroid Build Coastguard Worker 
691*1c60b9acSAndroid Build Coastguard Worker 	c->incomplete = 0;
692*1c60b9acSAndroid Build Coastguard Worker 	lws_async_dns_complete(q, q->firstcache);
693*1c60b9acSAndroid Build Coastguard Worker 
694*1c60b9acSAndroid Build Coastguard Worker 	q->go_nogo = METRES_GO;
695*1c60b9acSAndroid Build Coastguard Worker 
696*1c60b9acSAndroid Build Coastguard Worker 	/*
697*1c60b9acSAndroid Build Coastguard Worker 	 * the query is completely finished with
698*1c60b9acSAndroid Build Coastguard Worker 	 */
699*1c60b9acSAndroid Build Coastguard Worker 
700*1c60b9acSAndroid Build Coastguard Worker fail_out:
701*1c60b9acSAndroid Build Coastguard Worker 	lws_adns_q_destroy(q);
702*1c60b9acSAndroid Build Coastguard Worker }
703*1c60b9acSAndroid Build Coastguard Worker 
704