1/*	$OpenBSD: asr_private.h,v 1.49 2023/11/20 12:15:16 florian Exp $	*/
2/*
3 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdio.h>
19
20#define QR_MASK		(0x1 << 15)
21#define OPCODE_MASK	(0xf << 11)
22#define AA_MASK		(0x1 << 10)
23#define TC_MASK		(0x1 <<  9)
24#define RD_MASK		(0x1 <<  8)
25#define RA_MASK		(0x1 <<  7)
26#define Z_MASK		(0x1 <<  6)
27#define AD_MASK		(0x1 <<  5)
28#define CD_MASK		(0x1 <<  4)
29#define RCODE_MASK	(0xf)
30
31#define OPCODE(v)	((v) & OPCODE_MASK)
32#define RCODE(v)	((v) & RCODE_MASK)
33
34
35struct asr_pack {
36	char		*buf;
37	size_t		 len;
38	size_t		 offset;
39	int		 err;
40};
41
42struct asr_unpack {
43	const char	*buf;
44	size_t		 len;
45	size_t		 offset;
46	int		 err;
47};
48
49struct asr_dns_header {
50	uint16_t	id;
51	uint16_t	flags;
52	uint16_t	qdcount;
53	uint16_t	ancount;
54	uint16_t	nscount;
55	uint16_t	arcount;
56};
57
58struct asr_dns_query {
59	char		q_dname[MAXDNAME];
60	uint16_t	q_type;
61	uint16_t	q_class;
62};
63
64struct asr_dns_rr {
65	char		rr_dname[MAXDNAME];
66	uint16_t	rr_type;
67	uint16_t	rr_class;
68	uint32_t	rr_ttl;
69	union {
70		struct {
71			char	cname[MAXDNAME];
72		} cname;
73		struct {
74			uint16_t	preference;
75			char		exchange[MAXDNAME];
76		} mx;
77		struct {
78			char	nsname[MAXDNAME];
79		} ns;
80		struct {
81			char	ptrname[MAXDNAME];
82		} ptr;
83		struct {
84			char		mname[MAXDNAME];
85			char		rname[MAXDNAME];
86			uint32_t	serial;
87			uint32_t	refresh;
88			uint32_t	retry;
89			uint32_t	expire;
90			uint32_t	minimum;
91		} soa;
92		struct {
93			struct in_addr	addr;
94		} in_a;
95		struct {
96			struct in6_addr	addr6;
97		} in_aaaa;
98		struct {
99			uint16_t	 rdlen;
100			const void	*rdata;
101		} other;
102	} rr;
103};
104
105
106#define ASR_MAXNS	5
107#define ASR_MAXDB	3
108#define ASR_MAXDOM	10
109
110enum async_type {
111	ASR_SEND,
112	ASR_SEARCH,
113	ASR_GETRRSETBYNAME,
114	ASR_GETHOSTBYNAME,
115	ASR_GETHOSTBYADDR,
116	ASR_GETADDRINFO,
117	ASR_GETNAMEINFO,
118};
119
120#define	ASR_DB_FILE	'f'
121#define	ASR_DB_DNS	'b'
122
123struct asr_ctx {
124	int		 ac_refcount;
125	int		 ac_options;
126	int		 ac_ndots;
127	char		*ac_domain;
128	int		 ac_domcount;
129	char		*ac_dom[ASR_MAXDOM];
130	int		 ac_dbcount;
131	char		 ac_db[ASR_MAXDB + 1];
132	int		 ac_family[3];
133
134	int		 ac_nscount;
135	int		 ac_nstimeout;
136	int		 ac_nsretries;
137	struct sockaddr *ac_ns[ASR_MAXNS];
138
139};
140
141struct asr {
142	pid_t		 a_pid;
143	time_t		 a_mtime;
144	time_t		 a_rtime;
145	struct asr_ctx	*a_ctx;
146};
147
148#define ASYNC_COND		0
149#define ASYNC_DONE		1
150
151#define	ASYNC_DOM_FQDN		0x00000001
152#define	ASYNC_DOM_NDOTS		0x00000002
153#define	ASYNC_DOM_DOMAIN	0x00000004
154#define ASYNC_DOM_ASIS		0x00000008
155
156#define	ASYNC_NODATA		0x00000100
157#define	ASYNC_AGAIN		0x00000200
158
159#define	ASYNC_GETNET		0x00001000
160#define	ASYNC_EXTOBUF		0x00002000
161
162#define	ASYNC_NO_INET		0x00010000
163#define	ASYNC_NO_INET6		0x00020000
164
165struct asr_query {
166	int		(*as_run)(struct asr_query *, struct asr_result *);
167	struct asr_ctx	*as_ctx;
168	int		 as_type;
169	int		 as_flags;
170	int		 as_state;
171
172	/* cond */
173	int		 as_timeout;
174	int		 as_fd;
175	struct asr_query *as_subq;
176
177	/* loop indices in ctx */
178	int		 as_dom_step;
179	int		 as_dom_idx;
180	int		 as_dom_flags;
181	int		 as_family_idx;
182	int		 as_db_idx;
183
184	int		 as_count;
185
186	union {
187		struct {
188			uint16_t	 reqid;
189			int		 class;
190			int		 type;
191			char		*dname;		/* not fqdn! */
192			int		 rcode;		/* response code */
193			int		 ancount;	/* answer count */
194
195			int		 nsidx;
196			int		 nsloop;
197
198			/* io buffers for query/response */
199			unsigned char	*obuf;
200			size_t		 obuflen;
201			size_t		 obufsize;
202			unsigned char	*ibuf;
203			size_t		 ibuflen;
204			size_t		 ibufsize;
205			size_t		 datalen; /* for tcp io */
206			uint16_t	 pktlen;
207		} dns;
208
209		struct {
210			int		 class;
211			int		 type;
212			char		*name;
213			int		 saved_h_errno;
214		} search;
215
216		struct {
217			int		 flags;
218			int		 class;
219			int		 type;
220			char		*name;
221		} rrset;
222
223		struct {
224			char		*name;
225			int		 family;
226			char		 addr[16];
227			int		 addrlen;
228			int		 subq_h_errno;
229		} hostnamadr;
230
231		struct {
232			char		*hostname;
233			char		*servname;
234			int		 port_tcp;
235			int		 port_udp;
236			union {
237				struct sockaddr		sa;
238				struct sockaddr_in	sain;
239				struct sockaddr_in6	sain6;
240			}		 sa;
241
242			struct addrinfo	 hints;
243			char		*fqdn;
244			struct addrinfo	*aifirst;
245			struct addrinfo	*ailast;
246		} ai;
247
248		struct {
249			char		*hostname;
250			char		*servname;
251			size_t		 hostnamelen;
252			size_t		 servnamelen;
253			union {
254				struct sockaddr		sa;
255				struct sockaddr_in	sain;
256				struct sockaddr_in6	sain6;
257			}		 sa;
258			int		 flags;
259		} ni;
260#define MAXTOKEN 10
261	} as;
262
263};
264
265#define AS_DB(p) ((p)->as_ctx->ac_db[(p)->as_db_idx - 1])
266#define AS_FAMILY(p) ((p)->as_ctx->ac_family[(p)->as_family_idx])
267
268enum asr_state {
269	ASR_STATE_INIT,
270	ASR_STATE_NEXT_DOMAIN,
271	ASR_STATE_NEXT_DB,
272	ASR_STATE_SAME_DB,
273	ASR_STATE_NEXT_FAMILY,
274	ASR_STATE_NEXT_NS,
275	ASR_STATE_UDP_SEND,
276	ASR_STATE_UDP_RECV,
277	ASR_STATE_TCP_WRITE,
278	ASR_STATE_TCP_READ,
279	ASR_STATE_PACKET,
280	ASR_STATE_SUBQUERY,
281	ASR_STATE_NOT_FOUND,
282	ASR_STATE_HALT,
283};
284
285#define MAXPACKETSZ	4096
286
287__BEGIN_HIDDEN_DECLS
288
289/* asr_utils.c */
290void _asr_pack_init(struct asr_pack *, char *, size_t);
291int _asr_pack_header(struct asr_pack *, const struct asr_dns_header *);
292int _asr_pack_query(struct asr_pack *, uint16_t, uint16_t, const char *);
293int _asr_pack_edns0(struct asr_pack *, uint16_t, int);
294void _asr_unpack_init(struct asr_unpack *, const char *, size_t);
295int _asr_unpack_header(struct asr_unpack *, struct asr_dns_header *);
296int _asr_unpack_query(struct asr_unpack *, struct asr_dns_query *);
297int _asr_unpack_rr(struct asr_unpack *, struct asr_dns_rr *);
298int _asr_sockaddr_from_str(struct sockaddr *, int, const char *);
299ssize_t _asr_dname_from_fqdn(const char *, char *, size_t);
300ssize_t _asr_addr_as_fqdn(const char *, int, char *, size_t);
301int hnok_lenient(const char *);
302int _asr_is_localhost(const char*);
303
304/* asr.c */
305void _asr_resolver_done(void *);
306struct asr_ctx *_asr_use_resolver(void *);
307struct asr_ctx *_asr_no_resolver(void);
308void _asr_ctx_unref(struct asr_ctx *);
309struct asr_query *_asr_async_new(struct asr_ctx *, int);
310void _asr_async_free(struct asr_query *);
311size_t _asr_make_fqdn(const char *, const char *, char *, size_t);
312char *_asr_strdname(const char *, char *, size_t);
313int _asr_iter_db(struct asr_query *);
314int _asr_parse_namedb_line(FILE *, char **, int, char *, size_t);
315
316/* *_async.c */
317struct asr_query *_res_query_async_ctx(const char *, int, int, struct asr_ctx *);
318struct asr_query *_res_search_async_ctx(const char *, int, int, struct asr_ctx *);
319struct asr_query *_gethostbyaddr_async_ctx(const void *, socklen_t, int,
320    struct asr_ctx *);
321
322int _asr_iter_domain(struct asr_query *, const char *, char *, size_t);
323
324#ifdef DEBUG
325
326#define DPRINT(...)		do { if(_asr_debug) {		\
327		fprintf(_asr_debug, __VA_ARGS__);		\
328	} } while (0)
329#define DPRINT_PACKET(n, p, s)	do { if(_asr_debug) {		\
330		fprintf(_asr_debug, "----- %s -----\n", n);	\
331		_asr_dump_packet(_asr_debug, (p), (s));		\
332		fprintf(_asr_debug, "--------------\n");		\
333	} } while (0)
334
335#else /* DEBUG */
336
337#define DPRINT(...)
338#define DPRINT_PACKET(...)
339
340#endif /* DEBUG */
341
342const char *_asr_querystr(int);
343const char *_asr_statestr(int);
344const char *_asr_transitionstr(int);
345const char *_asr_print_sockaddr(const struct sockaddr *, char *, size_t);
346void _asr_dump_config(FILE *, struct asr *);
347void _asr_dump_packet(FILE *, const void *, size_t);
348
349extern FILE *_asr_debug;
350
351#define async_set_state(a, s) do {		\
352	DPRINT("asr: [%s@%p] %s -> %s\n",	\
353		_asr_querystr((a)->as_type),	\
354		as,				\
355		_asr_statestr((a)->as_state),	\
356		_asr_statestr((s)));		\
357	(a)->as_state = (s); } while (0)
358
359__END_HIDDEN_DECLS
360